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