scc

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

nm.c (4797B)


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