scc

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

nm.c (4666B)


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