scc

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

nm.c (4333B)


      1 static char sccsid[] = "@(#) ./nm/main.c";
      2 
      3 #include <ctype.h>
      4 #include <errno.h>
      5 #include <stdarg.h>
      6 #include <stdint.h>
      7 #include <stdio.h>
      8 #include <stdlib.h>
      9 #include <string.h>
     10 
     11 #include <scc/arg.h>
     12 #include <scc/mach.h>
     13 
     14 
     15 struct symtbl {
     16 	Objsym **buf;
     17 	size_t nsyms;
     18 };
     19 
     20 char *argv0;
     21 static int status, multi;
     22 static int radix = 16;
     23 static int Pflag;
     24 static int Aflag;
     25 static int vflag;
     26 static int gflag;
     27 static int uflag;
     28 static char *filename, *membname;
     29 
     30 static void
     31 error(char *fmt, ...)
     32 {
     33 	va_list va;
     34 
     35 	va_start(va, fmt);
     36 	fprintf(stderr, "nm: %s: ", filename);
     37 	if (membname)
     38 		fprintf(stderr, "%s: ", membname);
     39 	vfprintf(stderr, fmt, va);
     40 	putc('\n', stderr);
     41 	va_end(va);
     42 
     43 	status = EXIT_FAILURE;
     44 }
     45 
     46 static int
     47 cmp(const void *p1, const void *p2)
     48 {
     49 	Objsym **s1 = (Objsym **) p1, **s2 = (Objsym **) p2;
     50 	Objsym *sym1 = *s1, *sym2 = *s2;
     51 
     52 	if (vflag) {
     53 		if (sym1->value > sym2->value)
     54 			return 1;
     55 		if (sym1->value < sym2->value)
     56 			return -1;
     57 		if (sym1->type == 'U' && sym2->type == 'U')
     58 			return 0;
     59 		if (sym1->type == 'U')
     60 			return -1;
     61 		if (sym2->type == 'U')
     62 			return 1;
     63 		return 0;
     64 	} else {
     65 		return strcmp(sym1->name, sym2->name);
     66 	}
     67 }
     68 
     69 static void
     70 printsyms(Objsym **syms, size_t nsym)
     71 {
     72 	size_t i;
     73 
     74 	qsort(syms, nsym, sizeof(syms), cmp);
     75 
     76 	if (multi)
     77 		printf("%s:\n", (membname) ? membname : filename);
     78 
     79 	for (i = 0; i < nsym; i++) {
     80 		Objsym *sym = syms[i];
     81 		int type = sym->type;
     82 		char *fmt;
     83 
     84 		if (Aflag) {
     85 			fmt = (membname) ? "%s[%s]: " : "%s: ";
     86 			printf(fmt, filename, membname);
     87 		}
     88 
     89 		if (Pflag) {
     90 			printf("%s %c", sym->name, sym->type);
     91 			if (type != 'U') {
     92 				if (radix == 8)
     93 					fmt = " %016.16llo %lo";
     94 				else if (radix == 10)
     95 					fmt = " %016.16llu %lu";
     96 				else
     97 					fmt = " %016.16llx %lx";
     98 				printf(fmt, sym->value, sym->size);
     99 			}
    100 		} else {
    101 			if (type == 'U')
    102 				fmt = "                ";
    103 			else if (radix == 8)
    104 				fmt = "%016.16llo";
    105 			else if (radix == 10)
    106 				fmt = "%016.16lld";
    107 			else
    108 				fmt = "%016.16llx";
    109 			printf(fmt, sym->value);
    110 			printf(" %c %s", sym->type, sym->name);
    111 		}
    112 		putchar('\n');
    113 	}
    114 }
    115 
    116 static int
    117 newsym(Objsym *sym, struct symtbl *tbl)
    118 {
    119 	Objsym **p;
    120 	size_t n, size;
    121 	int type = sym->type;
    122 
    123 	if (type == '?' || type == 'N')
    124 		return 1;
    125 
    126 	if (uflag && type != 'U')
    127 		return 1;
    128 
    129 	if (gflag && !isupper(type))
    130 		return 1;
    131 
    132 	n = tbl->nsyms+1;
    133 	if (n == 0 || n > SIZE_MAX / sizeof(*p))
    134 		return 0;
    135 	size = n *sizeof(*p);
    136 
    137 	if ((p = realloc(tbl->buf, size)) == NULL)
    138 		return 0;
    139 	tbl->buf = p;
    140 	p[tbl->nsyms++] = sym;
    141 
    142 	return 1;
    143 }
    144 
    145 static void
    146 newobject(FILE *fp, int type)
    147 {
    148 	int err = 1;
    149 	Obj *obj;
    150 	Objsym *sym;
    151 	struct symtbl tbl = {NULL, 0};
    152 
    153 	if ((obj = objnew(type)) == NULL) {
    154 		error("out of memory");
    155 		return;
    156 	}
    157 
    158 	if (objread(obj, fp) < 0 || objsyms(obj) < 0)
    159 		goto error;
    160 
    161 	for (sym = obj->syms; sym; sym = sym->next)
    162 		newsym(sym, &tbl);
    163 
    164 	printsyms(tbl.buf, tbl.nsyms);
    165 	err = 0;
    166 
    167 error:
    168 	free(tbl.buf);
    169 	objdel(obj);
    170 	if (err)
    171 		error("object file corrupted");
    172 }
    173 
    174 static int
    175 newmember(FILE *fp, char *name, void *data)
    176 {
    177 	int t;
    178 
    179 	multi = 1;
    180 	membname = name;
    181 	if ((t = objtype(fp, NULL)) != -1)
    182 		newobject(fp, t);
    183 
    184 	return 1;
    185 }
    186 
    187 static void
    188 nm(char *fname)
    189 {
    190 	int t;
    191 	FILE *fp;
    192 
    193 	filename = fname;
    194 	membname = NULL;
    195 
    196 	if ((fp = fopen(fname, "rb")) == NULL) {
    197 		error(strerror(errno));
    198 		return;
    199 	}
    200 
    201 	if ((t = objtype(fp, NULL)) != -1) {
    202 		newobject(fp, t);
    203 	} else if (archive(fp)) {
    204 		if (formember(fp, newmember, NULL) < 0)
    205 			error("library corrupted");
    206 	} else {
    207 		error("bad format");
    208 	}
    209 
    210 	if (ferror(fp))
    211 		error(strerror(errno));
    212 
    213 	fclose(fp);
    214 }
    215 
    216 static void
    217 usage(void)
    218 {
    219 	fputs("nm [-APv][ -g| -u][-t format] [file...]\n", stderr);
    220 	exit(1);
    221 }
    222 
    223 int
    224 main(int argc, char *argv[])
    225 {
    226 	char *t;
    227 
    228 	ARGBEGIN {
    229 	case 'P':
    230 		Pflag = 1;
    231 		break;
    232 	case 'A':
    233 		Aflag = 1;
    234 		break;
    235 	case 'g':
    236 		gflag = 1;
    237 		break;
    238 	case 'u':
    239 		uflag = 1;
    240 		break;
    241 	case 'v':
    242 		vflag = 1;
    243 		break;
    244 	case 't':
    245 		t = EARGF(usage());
    246 		if (!strcmp(t, "o"))
    247 			radix = 8;
    248 		else if (!strcmp(t, "d"))
    249 			radix = 10;
    250 		else if (!strcmp(t, "x"))
    251 			radix = 16;
    252 		else
    253 			usage();
    254 		break;
    255 	default:
    256 		usage();
    257 	} ARGEND
    258 
    259 	if (argc == 0) {
    260 		nm("a.out");
    261 	} else {
    262 		if (argc > 1)
    263 			multi = 1;
    264 		for ( ; *argv; ++argv)
    265 			nm(*argv);
    266 	}
    267 
    268 	if (fflush(stdout)) {
    269 		fprintf(stderr, "nm: error writing in output");
    270 		status = 1;
    271 	}
    272 
    273 	return status;
    274 }