ref: 955a99b7c855cfc2378a9857bfbb8cb853047d6c
dir: /objdump/main.c/
#include <errno.h> #include <limits.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include "../inc/arg.h" #include "../inc/scc.h" #include "../inc/myro.h" char *argv0; static char *strings; static size_t strsiz; 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 void printhdr(struct myrohdr *hdr) { printf("header:\n" "\tmagic: %02x %02x %02x %02x \"%4.4s\"\n" "\tformat: %lu (\"%s\")\n" "\tentry: %llu\n" "\tstring table size: %llu\n" "\tsection table size: %llu\n" "\tsymbol table size: %llu\n" "\trelocation 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); } static void printstrings(struct myrohdr *hdr) { 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("\t[%zd] \"%s\"\n", begin, s); s = NULL; } } } static char * sectflags(struct myrosect *sec) { static char flags[10]; char *s = flags + sizeof(flags); if (sec->flags & MYROSEC_READ) *--s = 'R'; if (sec->flags & MYROSEC_WRITE) *--s = 'W'; if (sec->flags & MYROSEC_EXEC) *--s = 'X'; if (sec->flags & MYROSEC_LOAD) *--s = 'L'; if (sec->flags & MYROSEC_FILE) *--s = 'F'; if (sec->flags & MYROSEC_ABS) *--s = 'A'; return s; } static int printsections(struct myrohdr *hdr, FILE *fp) { unsigned long long n, i; struct myrosect sect; 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(fp, §) < 0) return -1; printf("[%2d]\t%s\t%016X\t%016X\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_DEDUP) *--s = 'D'; 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 myrohdr *hdr, FILE *fp) { unsigned long long n, i; struct myrosym sym; printf("symbols:\n" "[Nr]\t%s\t%-16s\t%s\t%s\t%s\n", "Name", "Value", "Section", "Flags", "Type"); n = hdr->symsize / MYROSYM_SIZ; for (i = 0; i < n; ++i) { if (rdmyrosym(fp, &sym) < 0) return -1; printf("[%2u]\t%s\t%016X\t%u\t%s\t%s\n", i, getstring(sym.name), sym.offset, sym.section, symflags(&sym), getstring(sym.type)); } return 0; } static int printrelocs(struct myrohdr *hdr, FILE *fp) { unsigned long long n, i; struct myrorel rel; puts("relocs:"); n = hdr->relsize / MYROREL_SIZ; for (i = 0; i < n; ++i) { if (rdmyrorel(fp, &rel) < 0) return -1; printf("\tid: %lu\n" "\tflags: %x\n" "\tsize: %u\n" "\tnbits: %u\n" "\tshift: %u\n" "\toffset: %llu\n", rel.id, rel.flags, rel.size, rel.nbits, rel.shift, rel.offset); } return 0; } static int printdata(struct myrohdr *hdr, FILE *fp) { unsigned long off; int c, i, j; puts("data:"); for (off = 0; ; off += 32) { printf("\t%08x:", off); for (i = 0; i < 2; i++) { for (j = 0; j < 16; j++) { if ((c = getc(fp)) == EOF) goto exit_loop; printf(" %02X", c); } putchar('\t'); } putchar('\n'); } exit_loop: putchar('\n'); return (ferror(fp)) ? -1 : 0; } void dump(char *fname) { FILE *fp; struct myrohdr hdr; if ((fp = fopen(fname, "rb")) == NULL) goto wrong_file; if (rdmyrohdr(fp, &hdr) < 0) goto wrong_file; if (strncmp(hdr.magic, MYROMAGIC, MYROMAGIC_SIZ)) { fprintf(stderr, "objdump: %s: File format not recognized\n", fname); goto close_file; } puts(fname); if (hdr.strsize > SIZE_MAX) { fprintf(stderr, "objdump: %s: overflow in header\n", fname, strerror(errno)); goto close_file; } strsiz = hdr.strsize; if (strsiz > 0) { strings = xmalloc(strsiz); fread(strings, strsiz, 1, fp); if (feof(fp)) goto wrong_file; } printhdr(&hdr); printstrings(&hdr); if (printsections(&hdr, fp) < 0) goto wrong_file; if (printsymbols(&hdr, fp) < 0) goto wrong_file; if (printrelocs(&hdr, fp) < 0) goto wrong_file; if (printdata(&hdr, fp) < 0) goto wrong_file; goto close_file; wrong_file: fprintf(stderr, "objdump: %s: %s\n", fname, strerror(errno)); close_file: if (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) dump("a.out"); else while (*argv) { free(strings); strings = NULL; dump(*argv++); } if (fclose(stdout) == EOF) die("objdump: stdout: %s", strerror(errno)); return 0; }