ref: 3ba625a83430f2616905108eaa93ac8c9009d45a
dir: /src/objdump/main.c/
#include <errno.h> #include <limits.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <scc/arg.h> #include <scc/scc.h> #include <scc/myro.h> char *argv0; static char *strings; static size_t strsiz; struct obj_info { char *fname; FILE *fp; struct myrohdr hdr; fpos_t strpos; fpos_t secpos; fpos_t sympos; fpos_t relpos; fpos_t datapos; }; static char * getstring(unsigned long off) { size_t n; if ((int32_t) off == -1) return ""; if (off < SIZE_MAX) { for (n = off; n < strsiz && strings[n]; ++n) ; if (n < strsiz) return &strings[off]; } fprintf(stderr, "objdump: wrong string offset %lu\n", off); return ""; } static int printhdr(struct obj_info *obj) { struct myrohdr *hdr = &obj->hdr; printf("header:\n" " magic: %02x %02x %02x %02x \"%4.4s\"\n" " format: %lu (\"%s\")\n" " entry: %llu\n" " string table size: %llu\n" " section table size: %llu\n" " symbol table size: %llu\n" " relocation table size: %llu\n", hdr->magic[0], hdr->magic[1], hdr->magic[2], hdr->magic[3], hdr->magic, hdr->format, getstring(hdr->format), hdr->entry, hdr->strsize, hdr->secsize, hdr->symsize, hdr->relsize); return 0; } static int printstrings(struct obj_info *obj) { size_t off, begin;; char *s = NULL; puts("strings:"); for (off = 0; off < strsiz; off++) { if (s == NULL) { s = &strings[off]; begin = off; } if (strings[off] == '\0') { printf(" [%zd] \"%s\"\n", begin, s); s = NULL; } } return 0; } static char * sectflags(struct myrosect *sec) { static char flags[10]; char *s = flags + sizeof(flags); if (sec->flags & MYROSEC_LOAD) *--s = 'L'; if (sec->flags & MYROSEC_FILE) *--s = 'F'; if (sec->flags & MYROSEC_ABS) *--s = 'A'; if (sec->flags & MYROSEC_EXEC) *--s = 'X'; if (sec->flags & MYROSEC_WRITE) *--s = 'W'; if (sec->flags & MYROSEC_READ) *--s = 'R'; return s; } static int printsections(struct obj_info *obj) { unsigned long long n, i; struct myrosect sect; struct myrohdr *hdr = &obj->hdr; printf("sections:\n" " [Nr]\t%s\t%-16s\t%-16s\t%s\t%s\t%s\n", "Name", "Offset", "Size", "Fill", "Align", "Flags"); n = hdr->secsize / MYROSECT_SIZ; for (i = 0; i < n; ++i) { if (rdmyrosec(obj->fp, §) < 0) return -1; printf(" [%2llu]\t%s\t%016llX\t%016llX\t%02X\t%u\t%s\n", i, getstring(sect.name), sect.offset, sect.len, sect.fill, sect.aligment, sectflags(§)); } return 0; } static char * symflags(struct myrosym *sym) { static char flags[10]; char *s = flags + sizeof(flags); if (sym->flags & MYROSYM_COMMON) *--s = 'C'; if (sym->flags & MYROSYM_EXTERN) *--s = 'G'; if (sym->flags & MYROSYM_UNDEF) *s-- = 'U'; return s; } static int printsymbols(struct obj_info *obj) { unsigned long long n, i; struct myrosym sym; struct myrohdr *hdr = &obj->hdr; printf("symbols:\n" " [Nr]\t%s\t%-16s\t%s\t%s\t%s\t%s\n", "Name", "Value", "Section", "Flags", "Size", "Type"); n = hdr->symsize / MYROSYM_SIZ; for (i = 0; i < n; ++i) { if (rdmyrosym(obj->fp, &sym) < 0) return -1; printf(" [%2llu]\t%s\t%016llX\t%u\t%s\t%llu\t%s\n", i, getstring(sym.name), sym.offset, sym.section, symflags(&sym), sym.len, getstring(sym.type)); } return 0; } static int printrelocs(struct obj_info *obj) { unsigned long long n, i; struct myrorel rel; struct myrohdr *hdr = &obj->hdr; printf("relocs:\n" " [Nr]\t%-16s\tType\tId\tSize\tNbits\tShift\n", "Offset"); n = hdr->relsize / MYROREL_SIZ; for (i = 0; i < n; ++i) { if (rdmyrorel(obj->fp, &rel) < 0) return -1; printf(" [%2llu]\t%016llX\t%s\t%lu\t%u\t%u\t%u\n", i, rel.offset, (rel.id & 1<<31) ? "section" : "symbol", rel.id & ~(1<<31), rel.size, rel.nbits, rel.shift); } return 0; } static int printdata(struct obj_info *obj) { unsigned long long off; int c, i, j; puts("data:"); for (off = 0; ; off += 32) { printf(" %016llX:", off); for (i = 0; i < 2; i++) { for (j = 0; j < 8; j++) { if ((c = getc(obj->fp)) == EOF) goto exit_loop; printf(" %02X", c); } putchar('\t'); } putchar('\n'); } exit_loop: putchar('\n'); return (ferror(obj->fp)) ? -1 : 0; } void dump(char *fname, FILE *fp) { struct obj_info obj; struct myrohdr *hdr; obj.fname = fname; obj.fp = fp; hdr = &obj.hdr; if (rdmyrohdr(obj.fp, hdr) < 0) goto wrong_file; if (strncmp(hdr->magic, MYROMAGIC, MYROMAGIC_SIZ)) { fprintf(stderr, "objdump: %s: File format not recognized\n", fname); return; } puts(fname); if (hdr->strsize > SIZE_MAX) { fprintf(stderr, "objdump: %s: overflow in header\n", fname); return; } strsiz = hdr->strsize; if (strsiz > 0) { strings = xmalloc(strsiz); fread(strings, strsiz, 1, fp); if (feof(fp)) goto wrong_file; } if (printhdr(&obj) < 0) goto wrong_file; if (printstrings(&obj) < 0) goto wrong_file; if (printsections(&obj) < 0) goto wrong_file; if (printsymbols(&obj) < 0) goto wrong_file; if (printrelocs(&obj) < 0) goto wrong_file; if (printdata(&obj) < 0) goto wrong_file; return; wrong_file: fprintf(stderr, "objdump: %s: %s\n", fname, strerror(errno)); } void doit(char *fname) { FILE *fp; if ((fp = fopen(fname, "rb")) == NULL) { fprintf(stderr, "objdump: %s: %s\n", fname, strerror(errno)); return; } dump(fname, fp); fclose(fp); } void usage(void) { fputs("usage: objdump file ...\n", stderr); exit(1); } int main(int argc, char *argv[]) { ARGBEGIN { default: usage(); } ARGEND if (argc == 0) doit("a.out"); else while (*argv) { free(strings); strings = NULL; doit(*argv++); } if (fclose(stdout) == EOF) die("objdump: stdout: %s", strerror(errno)); return 0; }