scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | 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 }