2 a84cbb2a 2004-04-19 devnull * nm.c -- drive nm
4 a84cbb2a 2004-04-19 devnull #include <u.h>
5 a84cbb2a 2004-04-19 devnull #include <libc.h>
6 a84cbb2a 2004-04-19 devnull #include <ar.h>
7 a84cbb2a 2004-04-19 devnull #include <bio.h>
8 a84cbb2a 2004-04-19 devnull #include <mach.h>
11 a84cbb2a 2004-04-19 devnull CHUNK = 256 /* must be power of 2 */
14 a84cbb2a 2004-04-19 devnull char *errs; /* exit status */
15 a84cbb2a 2004-04-19 devnull char *filename; /* current file */
16 a84cbb2a 2004-04-19 devnull char symname[]="__.SYMDEF"; /* table of contents file name */
17 a84cbb2a 2004-04-19 devnull int multifile; /* processing multiple files */
18 a84cbb2a 2004-04-19 devnull int aflag;
19 a84cbb2a 2004-04-19 devnull int gflag;
20 a84cbb2a 2004-04-19 devnull int hflag;
21 a84cbb2a 2004-04-19 devnull int nflag;
22 a84cbb2a 2004-04-19 devnull int sflag;
23 a84cbb2a 2004-04-19 devnull int uflag;
25 a84cbb2a 2004-04-19 devnull Symbol **fnames; /* file path translation table */
26 a84cbb2a 2004-04-19 devnull Symbol **symptr;
27 a84cbb2a 2004-04-19 devnull int nsym;
28 a84cbb2a 2004-04-19 devnull Biobuf bout;
30 a84cbb2a 2004-04-19 devnull int cmp(void*, void*);
31 a84cbb2a 2004-04-19 devnull void error(char*, ...);
32 a84cbb2a 2004-04-19 devnull void execsyms(int);
33 a84cbb2a 2004-04-19 devnull void psym(Symbol*, void*);
34 a84cbb2a 2004-04-19 devnull void printsyms(Symbol**, long);
35 a84cbb2a 2004-04-19 devnull void doar(Biobuf*);
36 a84cbb2a 2004-04-19 devnull void dofile(Biobuf*);
37 a84cbb2a 2004-04-19 devnull void zenter(Symbol*);
40 a84cbb2a 2004-04-19 devnull main(int argc, char *argv[])
43 a84cbb2a 2004-04-19 devnull Biobuf *bin;
45 a84cbb2a 2004-04-19 devnull Binit(&bout, 1, OWRITE);
46 a84cbb2a 2004-04-19 devnull argv0 = argv[0];
47 a84cbb2a 2004-04-19 devnull ARGBEGIN {
48 a84cbb2a 2004-04-19 devnull case 'a': aflag = 1; break;
49 a84cbb2a 2004-04-19 devnull case 'g': gflag = 1; break;
50 a84cbb2a 2004-04-19 devnull case 'h': hflag = 1; break;
51 a84cbb2a 2004-04-19 devnull case 'n': nflag = 1; break;
52 a84cbb2a 2004-04-19 devnull case 's': sflag = 1; break;
53 a84cbb2a 2004-04-19 devnull case 'u': uflag = 1; break;
55 a84cbb2a 2004-04-19 devnull if (argc > 1)
56 a84cbb2a 2004-04-19 devnull multifile++;
57 a84cbb2a 2004-04-19 devnull for(i=0; i<argc; i++){
58 a84cbb2a 2004-04-19 devnull filename = argv[i];
59 a84cbb2a 2004-04-19 devnull bin = Bopen(filename, OREAD);
60 a84cbb2a 2004-04-19 devnull if(bin == 0){
61 a84cbb2a 2004-04-19 devnull error("cannot open %s", filename);
62 a84cbb2a 2004-04-19 devnull continue;
64 a84cbb2a 2004-04-19 devnull if (isar(bin))
65 a84cbb2a 2004-04-19 devnull doar(bin);
67 a84cbb2a 2004-04-19 devnull Bseek(bin, 0, 0);
68 a84cbb2a 2004-04-19 devnull dofile(bin);
70 a84cbb2a 2004-04-19 devnull Bterm(bin);
72 a84cbb2a 2004-04-19 devnull exits(errs);
76 a84cbb2a 2004-04-19 devnull * read an archive file,
77 a84cbb2a 2004-04-19 devnull * processing the symbols for each intermediate file in it.
80 a84cbb2a 2004-04-19 devnull doar(Biobuf *bp)
82 a84cbb2a 2004-04-19 devnull int offset, size, obj;
83 a84cbb2a 2004-04-19 devnull char membername[SARNAME];
85 a84cbb2a 2004-04-19 devnull multifile = 1;
86 a84cbb2a 2004-04-19 devnull for (offset = Boffset(bp);;offset += size) {
87 a84cbb2a 2004-04-19 devnull size = nextar(bp, offset, membername);
88 a84cbb2a 2004-04-19 devnull if (size < 0) {
89 a84cbb2a 2004-04-19 devnull error("phase error on ar header %ld", offset);
92 a84cbb2a 2004-04-19 devnull if (size == 0)
94 a84cbb2a 2004-04-19 devnull if (strcmp(membername, symname) == 0)
95 a84cbb2a 2004-04-19 devnull continue;
96 a84cbb2a 2004-04-19 devnull obj = objtype(bp, 0);
97 a84cbb2a 2004-04-19 devnull if (obj < 0) {
98 a84cbb2a 2004-04-19 devnull error("inconsistent file %s in %s",
99 a84cbb2a 2004-04-19 devnull membername, filename);
102 a84cbb2a 2004-04-19 devnull if (!readar(bp, obj, offset+size, 1)) {
103 a84cbb2a 2004-04-19 devnull error("invalid symbol reference in file %s",
104 a84cbb2a 2004-04-19 devnull membername);
107 a84cbb2a 2004-04-19 devnull filename = membername;
109 a84cbb2a 2004-04-19 devnull objtraverse(psym, 0);
110 a84cbb2a 2004-04-19 devnull printsyms(symptr, nsym);
115 a84cbb2a 2004-04-19 devnull * process symbols in a file
118 a84cbb2a 2004-04-19 devnull dofile(Biobuf *bp)
120 a84cbb2a 2004-04-19 devnull int obj;
122 a84cbb2a 2004-04-19 devnull obj = objtype(bp, 0);
123 a84cbb2a 2004-04-19 devnull if (obj < 0)
124 a84cbb2a 2004-04-19 devnull execsyms(Bfildes(bp));
126 a84cbb2a 2004-04-19 devnull if (readobj(bp, obj)) {
127 a84cbb2a 2004-04-19 devnull nsym = 0;
128 a84cbb2a 2004-04-19 devnull objtraverse(psym, 0);
129 a84cbb2a 2004-04-19 devnull printsyms(symptr, nsym);
134 a84cbb2a 2004-04-19 devnull * comparison routine for sorting the symbol table
135 a84cbb2a 2004-04-19 devnull * this screws up on 'z' records when aflag == 1
138 a84cbb2a 2004-04-19 devnull cmp(void *vs, void *vt)
140 a84cbb2a 2004-04-19 devnull Symbol **s, **t;
144 a84cbb2a 2004-04-19 devnull if(nflag)
145 a84cbb2a 2004-04-19 devnull if((*s)->value < (*t)->value)
146 a84cbb2a 2004-04-19 devnull return -1;
148 a84cbb2a 2004-04-19 devnull return (*s)->value > (*t)->value;
149 a84cbb2a 2004-04-19 devnull return strcmp((*s)->name, (*t)->name);
152 a84cbb2a 2004-04-19 devnull * enter a symbol in the table of filename elements
155 a84cbb2a 2004-04-19 devnull zenter(Symbol *s)
157 a84cbb2a 2004-04-19 devnull static int maxf = 0;
159 a84cbb2a 2004-04-19 devnull if (s->value > maxf) {
160 a84cbb2a 2004-04-19 devnull maxf = (s->value+CHUNK-1) &~ (CHUNK-1);
161 a84cbb2a 2004-04-19 devnull fnames = realloc(fnames, (maxf+1)*sizeof(*fnames));
162 a84cbb2a 2004-04-19 devnull if(fnames == 0) {
163 a84cbb2a 2004-04-19 devnull error("out of memory", argv0);
164 a84cbb2a 2004-04-19 devnull exits("memory");
167 a84cbb2a 2004-04-19 devnull fnames[s->value] = s;
171 a84cbb2a 2004-04-19 devnull * get the symbol table from an executable file, if it has one
174 a84cbb2a 2004-04-19 devnull execsyms(int fd)
177 a84cbb2a 2004-04-19 devnull Symbol *s;
180 a84cbb2a 2004-04-19 devnull seek(fd, 0, 0);
181 a84cbb2a 2004-04-19 devnull if (crackhdr(fd, &f) == 0) {
182 a84cbb2a 2004-04-19 devnull error("Can't read header for %s", filename);
185 a84cbb2a 2004-04-19 devnull if (syminit(fd, &f) < 0)
187 a84cbb2a 2004-04-19 devnull s = symbase(&n);
188 a84cbb2a 2004-04-19 devnull nsym = 0;
189 a84cbb2a 2004-04-19 devnull while(n--)
190 a84cbb2a 2004-04-19 devnull psym(s++, 0);
192 a84cbb2a 2004-04-19 devnull printsyms(symptr, nsym);
196 a84cbb2a 2004-04-19 devnull psym(Symbol *s, void* p)
198 a84cbb2a 2004-04-19 devnull USED(p);
199 a84cbb2a 2004-04-19 devnull switch(s->type) {
200 a84cbb2a 2004-04-19 devnull case 'T':
201 a84cbb2a 2004-04-19 devnull case 'L':
202 a84cbb2a 2004-04-19 devnull case 'D':
203 a84cbb2a 2004-04-19 devnull case 'B':
204 a84cbb2a 2004-04-19 devnull if (uflag)
206 a84cbb2a 2004-04-19 devnull if (!aflag && ((s->name[0] == '.' || s->name[0] == '$')))
209 a84cbb2a 2004-04-19 devnull case 'b':
210 a84cbb2a 2004-04-19 devnull case 'd':
211 a84cbb2a 2004-04-19 devnull case 'l':
212 a84cbb2a 2004-04-19 devnull case 't':
213 a84cbb2a 2004-04-19 devnull if (uflag || gflag)
215 a84cbb2a 2004-04-19 devnull if (!aflag && ((s->name[0] == '.' || s->name[0] == '$')))
218 a84cbb2a 2004-04-19 devnull case 'U':
219 a84cbb2a 2004-04-19 devnull if (gflag)
222 a84cbb2a 2004-04-19 devnull case 'Z':
223 a84cbb2a 2004-04-19 devnull if (!aflag)
226 a84cbb2a 2004-04-19 devnull case 'm':
227 a84cbb2a 2004-04-19 devnull case 'f': /* we only see a 'z' when the following is true*/
228 a84cbb2a 2004-04-19 devnull if(!aflag || uflag || gflag)
230 a84cbb2a 2004-04-19 devnull if (strcmp(s->name, ".frame"))
231 a84cbb2a 2004-04-19 devnull zenter(s);
233 a84cbb2a 2004-04-19 devnull case 'a':
234 a84cbb2a 2004-04-19 devnull case 'p':
235 a84cbb2a 2004-04-19 devnull case 'z':
236 a84cbb2a 2004-04-19 devnull default:
237 a84cbb2a 2004-04-19 devnull if(!aflag || uflag || gflag)
241 a84cbb2a 2004-04-19 devnull symptr = realloc(symptr, (nsym+1)*sizeof(Sym*));
242 a84cbb2a 2004-04-19 devnull if (symptr == 0) {
243 a84cbb2a 2004-04-19 devnull error("out of memory");
244 a84cbb2a 2004-04-19 devnull exits("memory");
246 a84cbb2a 2004-04-19 devnull symptr[nsym++] = s;
250 a84cbb2a 2004-04-19 devnull printsyms(Symbol **symptr, long nsym)
252 a84cbb2a 2004-04-19 devnull Symbol *s;
253 a84cbb2a 2004-04-19 devnull char *cp;
254 a84cbb2a 2004-04-19 devnull char path[512];
256 a84cbb2a 2004-04-19 devnull if(!sflag)
257 a84cbb2a 2004-04-19 devnull qsort(symptr, nsym, sizeof(*symptr), cmp);
258 a84cbb2a 2004-04-19 devnull while (nsym-- > 0) {
259 a84cbb2a 2004-04-19 devnull s = *symptr++;
260 a84cbb2a 2004-04-19 devnull if (multifile && !hflag)
261 a84cbb2a 2004-04-19 devnull Bprint(&bout, "%s:", filename);
262 a84cbb2a 2004-04-19 devnull if (s->type == 'z') {
263 a84cbb2a 2004-04-19 devnull fileelem(fnames, (uchar *) s->name, path, 512);
264 a84cbb2a 2004-04-19 devnull cp = path;
266 a84cbb2a 2004-04-19 devnull cp = s->name;
267 a84cbb2a 2004-04-19 devnull if (s->value || s->type == 'a' || s->type == 'p')
268 a84cbb2a 2004-04-19 devnull Bprint(&bout, "%8lux %c %s\n", s->value, s->type, cp);
270 a84cbb2a 2004-04-19 devnull Bprint(&bout, " %c %s\n", s->type, cp);
275 a84cbb2a 2004-04-19 devnull error(char *fmt, ...)
278 a84cbb2a 2004-04-19 devnull char buf[128];
279 a84cbb2a 2004-04-19 devnull va_list arg;
281 a84cbb2a 2004-04-19 devnull fmtfdinit(&f, 2, buf, sizeof buf);
282 a84cbb2a 2004-04-19 devnull fmtprint(&f, "%s: ", argv0);
283 a84cbb2a 2004-04-19 devnull va_start(arg, fmt);
284 a84cbb2a 2004-04-19 devnull fmtvprint(&f, fmt, arg);
285 a84cbb2a 2004-04-19 devnull va_end(arg);
286 a84cbb2a 2004-04-19 devnull fmtprint(&f, "\n");
287 a84cbb2a 2004-04-19 devnull fmtfdflush(&f);
288 a84cbb2a 2004-04-19 devnull errs = "errors";