scc

simple C compiler
git clone git@git.2f30.org/scc.git
Log | Files | Refs | README | LICENSE

main.c (6103B)


      1 
      2 #include <errno.h>
      3 #include <limits.h>
      4 #include <stdint.h>
      5 #include <stdio.h>
      6 #include <stdlib.h>
      7 #include <string.h>
      8 
      9 #include "../inc/arg.h"
     10 #include "../inc/scc.h"
     11 #include "../inc/myro.h"
     12 
     13 char *argv0;
     14 static char *strings;
     15 static size_t strsiz;
     16 
     17 struct obj_info {
     18 	char *fname;
     19 	FILE *fp;
     20 	struct myrohdr hdr;
     21 	fpos_t strpos;
     22 	fpos_t secpos;
     23 	fpos_t sympos;
     24 	fpos_t relpos;
     25 	fpos_t datapos;
     26 };
     27 
     28 static char *
     29 getstring(unsigned long off)
     30 {
     31 	size_t n;
     32 
     33 	if ((int32_t) off == -1)
     34 		return "";
     35 	if (off < SIZE_MAX) {
     36 		for (n = off; n < strsiz && strings[n]; ++n)
     37 			;
     38 		if (n < strsiz)
     39 			return &strings[off];
     40 	}
     41 	fprintf(stderr, "objdump: wrong string offset %lu\n", off);
     42 	return "";
     43 }
     44 
     45 static int
     46 printhdr(struct obj_info *obj)
     47 {
     48 	struct myrohdr *hdr = &obj->hdr;
     49 
     50 	printf("header:\n"
     51 	       " magic: %02x %02x %02x %02x \"%4.4s\"\n"
     52 	       " format: %lu (\"%s\")\n"
     53 	       " entry: %llu\n"
     54 	       " string table size: %llu\n"
     55 	       " section table size: %llu\n"
     56 	       " symbol table size: %llu\n"
     57 	       " relocation table size: %llu\n",
     58 	       hdr->magic[0], hdr->magic[1],
     59 	       hdr->magic[2], hdr->magic[3],
     60 	       hdr->magic,
     61 	       hdr->format, getstring(hdr->format),
     62 	       hdr->entry,
     63 	       hdr->strsize,
     64 	       hdr->secsize,
     65 	       hdr->symsize,
     66 	       hdr->relsize);
     67 	return 0;
     68 }
     69 
     70 static int
     71 printstrings(struct obj_info *obj)
     72 {
     73 	size_t off, begin;;
     74 	char *s = NULL;
     75 
     76 	puts("strings:");
     77 	for (off = 0; off < strsiz; off++) {
     78 		if (s == NULL) {
     79 			s = &strings[off];
     80 			begin = off;
     81 		}
     82 		if (strings[off] == '\0') {
     83 			printf(" [%zd] \"%s\"\n", begin, s);
     84 			s = NULL;
     85 		}
     86 	}
     87 	return 0;
     88 }
     89 
     90 static char *
     91 sectflags(struct myrosect *sec)
     92 {
     93 	static char flags[10];
     94 	char *s = flags + sizeof(flags);
     95 
     96 	if (sec->flags & MYROSEC_READ)
     97 		*--s = 'R';
     98 	if (sec->flags & MYROSEC_WRITE)
     99 		*--s = 'W';
    100 	if (sec->flags & MYROSEC_EXEC)
    101 		*--s = 'X';
    102 	if (sec->flags & MYROSEC_LOAD)
    103 		*--s = 'L';
    104 	if (sec->flags & MYROSEC_FILE)
    105 		*--s = 'F';
    106 	if (sec->flags & MYROSEC_ABS)
    107 		*--s = 'A';
    108 	return s;
    109 }
    110 
    111 static int
    112 printsections(struct obj_info *obj)
    113 {
    114 	unsigned long long n, i;
    115 	struct myrosect sect;
    116 	struct myrohdr *hdr = &obj->hdr;
    117 
    118 	printf("sections:\n"
    119 	       " [Nr]\t%s\t%-16s\t%-16s\t%s\t%s\t%s\n",
    120 	       "Name",
    121 	       "Offset",
    122 	       "Size",
    123 	       "Fill",
    124 	       "Align",
    125 	       "Flags");
    126 
    127 	n = hdr->secsize / MYROSECT_SIZ;
    128 	for (i = 0; i < n; ++i) {
    129 		if (rdmyrosec(obj->fp, &sect) < 0)
    130 			return -1;
    131 		printf(" [%2llu]\t%s\t%016llX\t%016llX\t%02X\t%u\t%s\n",
    132 		       i,
    133 		       getstring(sect.name),
    134 		       sect.offset,
    135 		       sect.len,
    136 		       sect.fill,
    137 		       sect.aligment,
    138 		       sectflags(&sect));
    139 	}
    140 	return 0;
    141 }
    142 
    143 static char *
    144 symflags(struct myrosym *sym)
    145 {
    146 	static char flags[10];
    147 	char *s = flags + sizeof(flags);
    148 
    149 	if (sym->flags & MYROSYM_DEDUP)
    150 		*--s = 'D';
    151 	if (sym->flags & MYROSYM_COMMON)
    152 		*--s = 'C';
    153 	if (sym->flags & MYROSYM_EXTERN)
    154 		*--s = 'G';
    155 	if (sym->flags & MYROSYM_UNDEF)
    156 		*s-- = 'U';
    157 	return s;
    158 }
    159 
    160 static int
    161 printsymbols(struct obj_info *obj)
    162 {
    163 	unsigned long long n, i;
    164 	struct myrosym sym;
    165 	struct myrohdr *hdr = &obj->hdr;
    166 
    167 	printf("symbols:\n"
    168 	       " [Nr]\t%s\t%-16s\t%s\t%s\t%s\n",
    169 	       "Name",
    170 	       "Value",
    171 	       "Section",
    172 	       "Flags",
    173 	       "Type");
    174 	n = hdr->symsize / MYROSYM_SIZ;
    175 	for (i = 0; i < n; ++i) {
    176 		if (rdmyrosym(obj->fp, &sym) < 0)
    177 			return -1;
    178 		printf(" [%2llu]\t%s\t%016llX\t%u\t%s\t%s\n",
    179 		       i,
    180 		       getstring(sym.name),
    181 		       sym.offset,
    182 		       sym.section,
    183 		       symflags(&sym),
    184 		       getstring(sym.type));
    185 	}
    186 	return 0;
    187 }
    188 
    189 static int
    190 printrelocs(struct obj_info *obj)
    191 {
    192 	unsigned long long n, i;
    193 	struct myrorel rel;
    194 	struct myrohdr *hdr = &obj->hdr;
    195 
    196 	printf("relocs:\n"
    197 	       " [Nr]\t%-16s\tType\tId\tSize\tNbits\tShift\n",
    198 	       "Offset");
    199 	n = hdr->relsize / MYROREL_SIZ;
    200 	for (i = 0; i < n; ++i) {
    201 		if (rdmyrorel(obj->fp, &rel) < 0)
    202 			return -1;
    203 		printf(" [%2llu]\t%016llX\t%s\t%lu\t%u\t%u\t%u\n",
    204 		       i,
    205 		       rel.offset,
    206 		       (rel.id & 1<<31) ? "section" : "symbol",
    207 		       rel.id & ~(1<<31),
    208 		       rel.size,
    209 		       rel.nbits,
    210 		       rel.shift);
    211 	}
    212 	return 0;
    213 }
    214 
    215 static int
    216 printdata(struct obj_info *obj)
    217 {
    218 	unsigned long long off;
    219 	int c, i, j;
    220 
    221 	puts("data:");
    222 	for (off = 0; ; off += 32) {
    223 		printf(" %016llX:", off);
    224 		for (i = 0; i < 2; i++) {
    225 			for (j = 0; j < 16; j++) {
    226 				if ((c = getc(obj->fp)) == EOF)
    227 					goto exit_loop;
    228 				printf(" %02X", c);
    229 			}
    230 			putchar('\t');
    231 		}
    232 		putchar('\n');
    233 	}
    234 
    235 exit_loop:
    236 	putchar('\n');
    237 	return (ferror(obj->fp)) ? -1 : 0;
    238 }
    239 
    240 void
    241 dump(char *fname, FILE *fp)
    242 {
    243 	struct obj_info obj;
    244 	struct myrohdr *hdr;
    245 
    246 	obj.fname = fname;
    247 	obj.fp = fp;
    248 	hdr = &obj.hdr;
    249 
    250 	if (rdmyrohdr(obj.fp, hdr) < 0)
    251 		goto wrong_file;
    252 	if (strncmp(hdr->magic, MYROMAGIC, MYROMAGIC_SIZ)) {
    253 		fprintf(stderr,
    254 		        "objdump: %s: File format not recognized\n",
    255 		        fname);
    256 		return;
    257 	}
    258 	puts(fname);
    259 	if (hdr->strsize > SIZE_MAX) {
    260 		fprintf(stderr,
    261 			"objdump: %s: overflow in header\n",
    262 			fname);
    263 			return;
    264 	}
    265 	strsiz = hdr->strsize;
    266 
    267 	if (strsiz > 0) {
    268 		strings = xmalloc(strsiz);
    269 		fread(strings, strsiz, 1, fp);
    270 		if (feof(fp))
    271 			goto wrong_file;
    272 	}
    273 
    274 	if (printhdr(&obj) < 0)
    275 		goto wrong_file;
    276 	if (printstrings(&obj) < 0)
    277 		goto wrong_file;
    278 	if (printsections(&obj) < 0)
    279 		goto wrong_file;
    280 	if (printsymbols(&obj) < 0)
    281 		goto wrong_file;
    282 	if (printrelocs(&obj) < 0)
    283 		goto wrong_file;
    284 	if (printdata(&obj) < 0)
    285 		goto wrong_file;
    286 	return;
    287 
    288 wrong_file:
    289 	fprintf(stderr,
    290 		"objdump: %s: %s\n",
    291 		fname, strerror(errno));
    292 }
    293 
    294 void
    295 doit(char *fname)
    296 {
    297 	FILE *fp;
    298 
    299 	if ((fp = fopen(fname, "rb")) == NULL) {
    300 		fprintf(stderr, "objdump: %s: %s\n", fname, strerror(errno));
    301 		return;
    302 	}
    303 	dump(fname, fp);
    304 	fclose(fp);
    305 }
    306 
    307 void
    308 usage(void)
    309 {
    310 	fputs("usage: objdump file ...\n", stderr);
    311 	exit(1);
    312 }
    313 
    314 int
    315 main(int argc, char *argv[])
    316 {
    317 	ARGBEGIN {
    318 	default:
    319 		usage();
    320 	} ARGEND
    321 
    322 	if (argc == 0)
    323 		doit("a.out");
    324 	else while (*argv) {
    325 		free(strings);
    326 		strings = NULL;
    327 		doit(*argv++);
    328 	}
    329 
    330 	if (fclose(stdout) == EOF)
    331 		die("objdump: stdout: %s", strerror(errno));
    332 
    333 	return 0;
    334 }