main.c - scc - simple c99 compiler
 (HTM) git clone git://git.simple-cc.org/scc
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Submodules
 (DIR) README
 (DIR) LICENSE
       ---
       main.c (7784B)
       ---
            1 #include <ctype.h>
            2 #include <errno.h>
            3 #include <limits.h>
            4 #include <stdarg.h>
            5 #include <stdio.h>
            6 #include <stdlib.h>
            7 #include <string.h>
            8 #include <time.h>
            9 
           10 #include <scc/ar.h>
           11 #include <scc/arg.h>
           12 #include <scc/scc.h>
           13 #include <scc/mach.h>
           14 
           15 #include "objdump.h"
           16 
           17 struct binops {
           18         void (*dumpsyms)(Obj *);
           19         void (*dumpsecs)(Obj *);
           20         void (*dumpfhdr)(Obj *, unsigned long long *, Flags *);
           21         int (*hasrelloc)(Obj *, Section *);
           22 };
           23 
           24 int tflag, fflag, hflag, pflag, aflag, rflag, sflag;
           25 char *argv0;
           26 
           27 static int status, nsecs;
           28 static char *filename, *membname, **secs;
           29 
           30 static struct binops *op, ops[NFORMATS] = {
           31         [COFF32] = {
           32                 .dumpsyms = coff32syms,
           33                 .dumpsecs = coff32scns,
           34                 .dumpfhdr = coff32fhdr,
           35                 .hasrelloc = coff32hasrelloc,
           36         },
           37         [ELF] = {
           38                 .dumpsyms = elfsyms,
           39                 .dumpsecs = elfscns,
           40                 .dumpfhdr = elffhdr,
           41                 .hasrelloc = elfhasrelloc,
           42         },
           43 };
           44 
           45 void
           46 error(char *fmt, ...)
           47 {
           48         va_list va;
           49 
           50         va_start(va, fmt);
           51         fprintf(stderr, "objdump: %s: ", filename);
           52         if (membname)
           53                 fprintf(stderr, "%s: ", membname);
           54         vfprintf(stderr, fmt, va);
           55         putc('\n', stderr);
           56         va_end(va);
           57 
           58         status = EXIT_FAILURE;
           59 }
           60 
           61 void
           62 setflag(Flags *f, int cond, int flag)
           63 {
           64         if (cond)
           65                 f->flags |= 1 << flag;
           66 }
           67 
           68 void
           69 printflags(Flags *f)
           70 {
           71         int i, first;
           72         unsigned long flags = f->flags;
           73 
           74         first = 1;
           75         for (i = 0; i < f->nr; i++) {
           76                 if (flags & 1) {
           77                         if (!first)
           78                                 fputs(", ", stdout);
           79                         first = 0;
           80                         fputs(f->text[i], stdout);
           81                 }
           82                 flags >>= 1;
           83         }
           84 
           85         putchar('\n');
           86 }
           87 
           88 static void
           89 dumpfhdr(Obj *obj, char *fmt)
           90 {
           91         unsigned long long start = 0;
           92         static Flags f = {
           93                 .nr = NR_FILE_FLAGS,
           94                 .text = {
           95                         [HAS_RELOC] = "HAS_RELOC",
           96                         [EXEC_P] = "EXEC_P",
           97                         [HAS_LINENO] = "HAS_LINENO",
           98                         [HAS_DEBUG] = "HAS_DEBUG",
           99                         [HAS_SYMS] = "HAS_SYMS",
          100                         [HAS_LOCALS] = "HAS_LOCALS",
          101                         [DYNAMIC] = "DYNAMIC",
          102                 }
          103         };
          104 
          105         printf("architecture: %s, flags: 0x%08x\n",
          106                strchr(fmt, '-') + 1,
          107                obj->type);
          108 
          109         f.flags = 0;
          110 
          111         (*op->dumpfhdr)(obj, &start, &f);
          112         printflags(&f);
          113         printf("start address 0x%08llx\n", start);
          114 }
          115 
          116 static int
          117 logb2(unsigned val)
          118 {
          119         int n;
          120 
          121         if (val == 0)
          122                 return 0;
          123 
          124         for (n = 0; (val & 1) == 0; n++)
          125                 val >>= 1;
          126         return n;
          127 }
          128 
          129 int
          130 selected(char *secname)
          131 {
          132         int i;
          133 
          134         if (nsecs == 0)
          135                 return 1;
          136 
          137         for (i = 0; i < nsecs; i++) {
          138                 if (strcmp(secname, secs[i]) == 0)
          139                         return 1;
          140         }
          141 
          142         return 0;
          143 }
          144 
          145 static void
          146 dumpscns(Obj *obj)
          147 {
          148         int i, debug;
          149         unsigned flags;
          150         Section sec;
          151         static Flags f = {
          152                 .nr = NR_SEC_FLAGS,
          153                 .text = {
          154                         [SEC_HAS_CONTENTS] = "CONTENTS",
          155                         [SEC_ALLOC] = "ALLOC",
          156                         [SEC_LOAD] = "LOAD",
          157                         [SEC_RELOC] = "RELOC",
          158                         [SEC_READONLY] = "READONLY",
          159                         [SEC_CODE] = "CODE",
          160                         [SEC_DATA] = "DATA",
          161                         [SEC_DEBUGGING] = "DEBUGGING",
          162                 }
          163         };
          164 
          165         puts("Sections:");
          166         puts("Idx Name          Size      VMA       LMA       File off  Algn");
          167         for (i = 0; getsec(obj, &i, &sec); i++) {
          168                 if (!selected(sec.name))
          169                         continue;
          170 
          171                 printf("%3d %-13s %08llx  %08llx  %08llx  %08llx  2**%d\n",
          172                        sec.index,
          173                        sec.name,
          174                        sec.size,
          175                        sec.base,
          176                        sec.load,
          177                        sec.offset,
          178                        logb2(sec.align));
          179 
          180                 f.flags = 0;
          181                 flags = sec.flags;
          182                 debug = sec.type == 'N';
          183                 setflag(&f, flags & SALLOC, SEC_ALLOC);
          184                 setflag(&f, flags & SLOAD, SEC_LOAD);
          185                 setflag(&f, (*op->hasrelloc)(obj, &sec), SEC_RELOC);
          186                 setflag(&f, (flags & SWRITE) == 0 && !debug, SEC_READONLY);
          187                 setflag(&f, flags & SEXEC, SEC_CODE);
          188                 setflag(&f, (flags & (SEXEC|SLOAD)) == SLOAD, SEC_DATA);
          189                 setflag(&f, debug, SEC_DEBUGGING);
          190                 setflag(&f, (flags & SALLOC) && sec.size > 0, SEC_HAS_CONTENTS);
          191                 fputs("                  ", stdout);
          192                 printflags(&f);
          193         }
          194 
          195         if (!pflag)
          196                 return;
          197         (*op->dumpsecs)(obj);
          198 }
          199 
          200 static void
          201 dumpdata(Obj *obj, FILE *fp)
          202 {
          203         int i, j, c;
          204         char buf[19];
          205         Section sec;
          206         unsigned long long n;
          207 
          208         buf[0] = '|';
          209         buf[17] = '|';
          210         buf[18] = '\0';
          211 
          212         for (i = 0; getsec(obj, &i, &sec); i++) {
          213                 if (!selected(sec.name))
          214                         continue;
          215                 if ((sec.flags & SALLOC) == 0 || sec.size == 0)
          216                         continue;
          217 
          218                 printf("Contents of section %s\n", sec.name);
          219 
          220                 if (!objpos(obj, fp, sec.offset))
          221                         goto errno_error;
          222 
          223                 for (n = 0; n < sec.size; ) {
          224                         memset(buf+1, '.', 16);
          225                         printf(" %04llx ", sec.base + n);
          226                         for (j = 0; j < 16 && n < sec.size; j++, n++) {
          227                                 if ((c = getc(fp)) == EOF) {
          228                                         if (ferror(fp))
          229                                                 goto errno_error;
          230                                         error("section %s: end of file found before end of section",
          231                                               sec.name);
          232                                         goto next_section;
          233                                 }
          234 
          235                                 if (c < CHAR_MAX && c > 0 && isprint(c))
          236                                         buf[j] = c;
          237 
          238                                 printf("%02x ", (unsigned) c & 0xFF);
          239                         }
          240 
          241                         for ( ; j < 16; j++)
          242                                 fputs("   ", stdout);
          243                         puts(buf);
          244                 }
          245 
          246 next_section:
          247                 continue;
          248 
          249 errno_error:
          250                 error("section %s: %s", sec.name, strerror(errno));
          251         }
          252 }
          253 
          254 
          255 static void
          256 dumpobj(FILE *fp, int type, char *fmt)
          257 {
          258         int id;
          259         Obj *obj;
          260 
          261         printf("\n%s", filename);
          262         if (membname)
          263                 printf("(%s)", membname);
          264         printf(":\tfile format %s\n", fmt);
          265 
          266         if ((obj = newobj(type)) == NULL) {
          267                 error("failed object allocation");
          268                 return;
          269         }
          270 
          271         if (readobj(obj, fp) < 0) {
          272                 error("object file corrupted");
          273                 goto err;
          274         }
          275 
          276         id = objfmt(obj);
          277         if (id >= NFORMATS) {
          278                 error("unknown symbol binary format");
          279                 return;
          280         }
          281         op = &ops[id];
          282 
          283         if (fflag)
          284                 dumpfhdr(obj, fmt);
          285         if (hflag)
          286                 dumpscns(obj);
          287         if (sflag)
          288                 dumpdata(obj, fp);
          289         if (tflag)
          290                 (*op->dumpsyms)(obj);
          291 
          292 err:
          293         delobj(obj);
          294 }
          295 
          296 static void
          297 dumprights(unsigned r)
          298 {
          299         putchar((r & 4) ? 'r' : '-');
          300         putchar((r & 2) ? 'w' : '-');
          301         putchar((r & 1) ? 'x' : '-');
          302 }
          303 
          304 static void
          305 dumpar(char *fname, struct ar_hdr *hdr, char *fmt)
          306 {
          307         time_t t;
          308         int n;
          309         struct tm *tm;
          310         char buf[60];
          311         unsigned long mode;
          312 
          313         printf("%s:     file format %s\n", fname, fmt);
          314 
          315         mode = strtol(hdr->ar_mode, NULL, 8);
          316         dumprights((mode >> 6) & 7);
          317         dumprights((mode >> 3) & 7);
          318         dumprights(mode & 7);
          319 
          320         t = fromepoch(atoll(hdr->ar_date));
          321         strftime(buf, sizeof(buf), "%c", gmtime(&t));
          322         printf(" %d/%d   %lld %s %s\n\n",
          323                atoi(hdr->ar_uid),
          324                atoi(hdr->ar_gid),
          325                atoll(hdr->ar_size),
          326                buf,
          327                fname);
          328 }
          329 
          330 static void
          331 dumplib(FILE *fp)
          332 {
          333         int t;
          334         char *fmt;
          335         long off, cur;
          336         struct ar_hdr hdr;
          337         char memb[SARNAM+1];
          338 
          339         for (;;) {
          340                 cur = ftell(fp);
          341 
          342                 off = armember(fp, memb, &hdr);
          343                 switch (off) {
          344                 case -1:
          345                         error("library corrupted");
          346                         if (ferror(fp))
          347                                 error(strerror(errno));
          348                 case 0:
          349                         return;
          350                 default:
          351                         membname = memb;
          352                         if ((t = objprobe(fp, &fmt)) != -1) {
          353                                 if (aflag)
          354                                         dumpar(memb, &hdr, fmt);
          355                                 dumpobj(fp, t, fmt);
          356                         }
          357                         membname = NULL;
          358                         fseek(fp, cur, SEEK_SET);
          359                         fseek(fp, off, SEEK_CUR);
          360                         break;
          361                 }
          362         }
          363 }
          364 
          365 static void
          366 objdump(char *fname)
          367 {
          368         int t;
          369         char *fmt;
          370         FILE *fp;
          371 
          372         membname = NULL;
          373         filename = fname;
          374         if ((fp = fopen(fname, "rb")) == NULL) {
          375                 error(strerror(errno));
          376                 return;
          377         }
          378 
          379         if ((t = objprobe(fp, &fmt)) != -1)
          380                 dumpobj(fp, t, fmt);
          381         else if (archive(fp))
          382                 dumplib(fp);
          383         else
          384                 error("bad format");
          385                         
          386         fclose(fp);
          387 }
          388 
          389 static void
          390 usage(void)
          391 {
          392         fputs("usage: objdump [-afhpts][-j section] file...\n", stderr);
          393         exit(EXIT_FAILURE);
          394 }
          395 
          396 int
          397 main(int argc, char *argv[])
          398 {
          399         char *s;
          400 
          401         ARGBEGIN {
          402         case 'a':
          403                 aflag = 1;
          404                 break;
          405         case 'f':
          406                 fflag = 1;
          407                 break;
          408         case 'h':
          409                 hflag = 1;
          410                 break;
          411         case 'p':
          412                 pflag = 1;
          413                 break;
          414         case 's':
          415                 sflag = 1;
          416                 break;
          417         case 't':
          418                 tflag = 1;
          419                 break;
          420         case 'j':
          421                 s = EARGF(usage());
          422                 secs = xrealloc(secs, (nsecs + 1) * sizeof(char *));
          423                 secs[nsecs++] = s;
          424                 break;                
          425         default:
          426                 usage();
          427         } ARGEND
          428 
          429         if (!aflag && !fflag && !hflag
          430         && !tflag && !sflag) {
          431                 fputs("objdump: At lest one of [afhts] flags must be used\n",
          432                       stderr);
          433                 usage();
          434         }
          435 
          436         if (argc == 0) {
          437                 objdump("a.out");
          438         } else {
          439                 for ( ; *argv; ++argv)
          440                         objdump(*argv);
          441         }
          442 
          443         if (fflush(stdout)) {
          444                 fprintf(stderr,
          445                         "size: error writing in output:%s\n",
          446                         strerror(errno));
          447                 status = 1;
          448         }
          449 
          450         return status;
          451 }