scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

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 }