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 }