scc

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

scc-nm.c (4784B)


      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 	}
     64 
     65 	return strcmp(sym1->name, sym2->name);
     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 	int stype = sym->stype;
    128 
    129 	if (type == '?' && !fflag
    130 	|| type == 'N' && !fflag
    131 	|| (stype == SYMSECTION || stype == SYMFILE) && !fflag
    132 	|| uflag && type != 'U'
    133 	|| gflag && !isupper(type)) {
    134 		return 0;
    135 	}
    136 
    137 	n = tbl->nsyms+1;
    138 	size = n *sizeof(*p);
    139 	p = realloc(tbl->buf, size);
    140 	s = malloc(sizeof(*s));
    141 	if (!p || !s) {
    142 		free(p);
    143 		free(s);
    144 		error(strerror(errno));
    145 		return -1;
    146 	}
    147 
    148 	*s = *sym;
    149 	tbl->buf = p;
    150 	p[tbl->nsyms++] = s;
    151 	return 0;
    152 }
    153 
    154 static void
    155 nmobj(FILE *fp, int type)
    156 {
    157 	int i, err = 1;
    158 	Obj *obj;
    159 	Symbol sym;
    160 	struct symtbl tbl = {NULL, 0};
    161 
    162 	if ((obj = newobj(type)) == NULL) {
    163 		error(strerror(errno));
    164 		goto err1;
    165 	}
    166 
    167 	if (readobj(obj, fp) < 0)
    168 		goto err2;
    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, NULL);
    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 = objprobe(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 = objprobe(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 [-APvfa][-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 'a':
    263 	case 'f':
    264 		fflag = 1;
    265 		break;
    266 	case 'u':
    267 		uflag = 1;
    268 		break;
    269 	case 'v':
    270 		vflag = 1;
    271 		break;
    272 	case 't':
    273 		t = EARGF(usage());
    274 		if (!strcmp(t, "o"))
    275 			radix = 8;
    276 		else if (!strcmp(t, "d"))
    277 			radix = 10;
    278 		else if (!strcmp(t, "x"))
    279 			radix = 16;
    280 		else
    281 			usage();
    282 		break;
    283 	default:
    284 		usage();
    285 	} ARGEND
    286 
    287 	if (argc == 0) {
    288 		nm("a.out");
    289 	} else {
    290 		if (argc > 1)
    291 			multi = 1;
    292 		for ( ; *argv; ++argv)
    293 			nm(*argv);
    294 	}
    295 
    296 	if (fflush(stdout) == EOF) {
    297 		fprintf(stderr,
    298 		        "nm: error writing in output:%s\n",
    299 		        strerror(errno));
    300 		status = 1;
    301 	}
    302 
    303 	return status;
    304 }