scc

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

main.c (4846B)


      1 static char sccsid[] = "@(#) ./nm/main.c";
      2 
      3 #include <errno.h>
      4 #include <limits.h>
      5 #include <stdint.h>
      6 #include <stdio.h>
      7 #include <stdlib.h>
      8 #include <string.h>
      9 
     10 #include "../inc/arg.h"
     11 #include "../inc/scc.h"
     12 #include "../inc/myro.h"
     13 #include "../inc/ar.h"
     14 
     15 char *argv0;
     16 char *strings;
     17 static int radix = 16;
     18 static int Pflag;
     19 static int Aflag;
     20 static int vflag;
     21 static int gflag;
     22 static int uflag;
     23 static int archflag;
     24 
     25 static int
     26 object(char *fname, FILE *fp)
     27 {
     28 	char magic[MYROMAGIC_SIZ];
     29 	fpos_t pos;
     30 
     31 	fgetpos(fp, &pos);
     32 	fread(magic, sizeof(magic), 1, fp);
     33 	if (!ferror(fp)) {
     34 		if (!strncmp(magic, MYROMAGIC, MYROMAGIC_SIZ))
     35 			return 1;
     36 	}
     37 
     38 	fsetpos(fp, &pos);
     39 	return 0;
     40 }
     41 
     42 static int
     43 archive(char *fname, FILE *fp)
     44 {
     45 	char magic[ARMAGIC_SIZ];
     46 	fpos_t pos;
     47 
     48 	fgetpos(fp, &pos);
     49 	fread(magic, sizeof(magic), 1, fp);
     50 
     51 	if (!ferror(fp)) {
     52 		if (!strncmp(magic, ARMAGIC, ARMAGIC_SIZ))
     53 			return 1;
     54 	}
     55 
     56 	fsetpos(fp, &pos);
     57 	return 0;
     58 }
     59 
     60 static int
     61 cmp(const void *p1, const void *p2)
     62 {
     63 	const struct myrosym *s1 = p1, *s2 = p2;
     64 
     65 	if (vflag)
     66 		return s1->offset - s2->offset;
     67 	else
     68 		return strcmp(strings + s1->name, strings + s2->name);
     69 }
     70 
     71 static int
     72 typeof(struct myrosym *sym)
     73 {
     74 	return 'U';
     75 }
     76 
     77 static void
     78 print(char *file, char *member, struct myrosym *sym, FILE *fp)
     79 {
     80 	char *fmt, *name = strings + sym->name;
     81 	int type = typeof(sym);
     82 
     83 	if (uflag && type != 'U')
     84 		return;
     85 	if (gflag && type != 'A' && type != 'B' && type != 'D')
     86 		return;
     87 
     88 	if (Aflag)
     89 		fprintf(fp, (archflag) ? "%s[%s]: " : "%s: ", file, member);
     90 	if (Pflag) {
     91 		fprintf(fp, "%s %c", name, type);
     92 		if (type != 'U') {
     93 			if (radix == 8)
     94 				fmt = "%llo %llo";
     95 			else if (radix == 10)
     96 				fmt = "%llu %llu";
     97 			else
     98 				fmt = "%llx %llx";
     99 			fprintf(fp, fmt, sym->offset, sym->len);
    100 		}
    101 	} else {
    102 		if (type == 'U')
    103 			fmt = "                ";
    104 		else if (radix == 8)
    105 			fmt = "%016.16llo";
    106 		else if (radix == 8)
    107 			fmt = "%016.16lld";
    108 		else
    109 			fmt = "%016.16llx";
    110 		fprintf(fp, fmt, sym->offset);
    111 		fprintf(fp, " %c %s", type, name);
    112 	}
    113 	putc('\n', fp);
    114 }
    115 
    116 static void
    117 nm(char *fname, char *member, FILE *fp)
    118 {
    119 	struct myrohdr hdr;
    120 	struct myrosym *syms = NULL;
    121 	size_t n, i;
    122 	long off;
    123 
    124 	strings = NULL;
    125 	if (rdmyrohdr(fp, &hdr) < 0) {
    126 		fprintf(stderr, "nm: %s: incorrect header\n", member);
    127 		return;
    128 	}
    129 
    130 	n = hdr.symsize / MYROSYM_SIZ;
    131 	if (n == 0) {
    132 		fprintf(stderr, "nm: %s: no name list\n", member);
    133 		return;
    134 	}
    135 	if (n > SIZE_MAX / sizeof(struct myrosym) ||
    136 	    hdr.symsize / MYROSYM_SIZ > SIZE_MAX ||
    137 	    hdr.strsize > SIZE_MAX) {
    138 		goto offset_overflow;
    139 	}
    140 
    141 	syms = xmalloc(n * sizeof(struct myrosym));
    142 	strings = xmalloc(hdr.strsize);
    143 	fread(strings, hdr.strsize, 1, fp);
    144 	if (feof(fp))
    145 		goto free_arrays;
    146 	if ((off = ftell(fp)) < 0)
    147 		return;
    148 	if (off > LONG_MAX - hdr.secsize)
    149 		goto offset_overflow;
    150 	off += hdr.secsize;
    151 
    152 	if (fseek(fp, off, SEEK_SET) < 0)
    153 		goto free_arrays;
    154 
    155 	for (i = 0; i < n; ++i) {
    156 		if (rdmyrosym(fp, &syms[i]) < 0)
    157 			goto free_arrays;
    158 		if (syms[i].name >= hdr.strsize)
    159 			goto offset_overflow;
    160 	}
    161 	qsort(syms, n, sizeof(*syms), cmp);
    162 	for (i = 0; i < n; ++i)
    163 		print(fname, member, &syms[i], fp);
    164 
    165 
    166 free_arrays:
    167 	free(syms);
    168 	free(strings);
    169 	return;
    170 
    171 offset_overflow:
    172 	fprintf(stderr, "nm: %s: overflow in headers of archive\n",
    173 		fname);
    174 	goto free_arrays;
    175 }
    176 
    177 static void
    178 ar(char *fname, FILE *fp)
    179 {
    180 	struct arhdr hdr;
    181 	long pos;
    182 
    183 	archflag = 1;
    184 	while (rdarhdr(fp, &hdr) != EOF) {
    185 		pos = ftell(fp);
    186 		if (pos == -1 || pos > LONG_MAX - hdr.size) {
    187 			fprintf(stderr,
    188 			        "nm: %s: overflow in size of archive\n",
    189 			        fname);
    190 			return;
    191 		}
    192 		pos += hdr.size;
    193 		if (hdr.size & 1)
    194 			++pos;
    195 
    196 		if (object(fname, fp)) {
    197 			nm(fname, hdr.name, fp);
    198 		} else {
    199 			fprintf(stderr,
    200 			        "nm: skipping member %s in archive %s\n",
    201 			        hdr.name, fname);
    202 		}
    203 		fseek(fp, pos, SEEK_SET);
    204 	}
    205 }
    206 
    207 void
    208 doit(char *fname)
    209 {
    210 	FILE *fp;
    211 
    212 	archflag = 0;
    213 	if ((fp = fopen(fname, "rb")) == NULL)
    214 		goto file_error;
    215 
    216 	if (object(fname, fp))
    217 		nm(fname, fname, fp);
    218 	else if (archive(fname, fp))
    219 		ar(fname, fp);
    220 	else
    221 		fprintf(stderr, "nm: %s: File format not recognized\n", fname);
    222 
    223 	if (fclose(fp) != EOF)
    224 		return;
    225 
    226 file_error:
    227 	die("nm: %s: %s", fname, strerror(errno));
    228 }
    229 
    230 void
    231 usage(void)
    232 {
    233 	fputs("nm [-APv][ -g| -u][-t format] [file...]\n", stderr);
    234 	exit(1);
    235 }
    236 
    237 int
    238 main(int argc, char *argv[])
    239 {
    240 	char *t;
    241 
    242 	ARGBEGIN {
    243 	case 'P':
    244 		Pflag = 1;
    245 		break;
    246 	case 'A':
    247 		Aflag = 1;
    248 		break;
    249 	case 'g':
    250 		gflag = 1;
    251 		break;
    252 	case 'u':
    253 		uflag = 1;
    254 		break;
    255 	case 'v':
    256 		vflag = 1;
    257 		break;
    258 	case 't':
    259 		t = EARGF(usage());
    260 		if (!strcmp(t, "o"))
    261 			radix = 8;
    262 		else if (!strcmp(t, "d"))
    263 			radix = 10;
    264 		else if (!strcmp(t, "x"))
    265 			radix = 16;
    266 		else
    267 			usage();
    268 		break;
    269 	default:
    270 		usage();
    271 	} ARGEND
    272 
    273 	if (argc == 0) {
    274 		doit("a.out");
    275 	} else {
    276 		while (argc-- > 0)
    277 			doit(*++argv);
    278 	}
    279 
    280 	return 0;
    281 }