scc-nm.c - scc - simple c99 compiler
(HTM) git clone git://git.simple-cc.org/scc
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) Submodules
(DIR) README
(DIR) LICENSE
---
scc-nm.c (4779B)
---
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 [-APvfagu][-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 }