scc

A fork of https://git.simple-cc.org/scc/ for Qute

git clone https://git.8pit.net/scc.git

  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
 14struct symtbl {
 15	Symbol **buf;
 16	size_t nsyms;
 17};
 18
 19char *argv0;
 20static int status, multi;
 21static int radix = 16;
 22static int Pflag;
 23static int Aflag;
 24static int vflag;
 25static int gflag;
 26static int uflag;
 27static int fflag;
 28static char *filename, *membname;
 29
 30static void
 31error(char *fmt, ...)
 32{
 33	va_list va;
 34
 35	va_start(va, fmt);
 36	fprintf(stderr, "scc-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
 46static int
 47cmp(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
 68static void
 69printsyms(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
121static int
122newsym(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
154static void
155nmobj(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
178err3:
179	free(tbl.buf);
180err2:
181	delobj(obj);
182err1: 
183	if (err)
184		error("object file corrupted");
185}
186
187static void
188nmlib(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
216static void
217nm(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
240static void
241usage(void)
242{
243	fputs("scc-nm [-APvfagu][-t format] [file...]\n", stderr);
244	exit(1);
245}
246
247int
248main(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}