scc

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

nm.c (4289B)


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