Blame


1 a84cbb2a 2004-04-19 devnull /*
2 a84cbb2a 2004-04-19 devnull * nm.c -- drive nm
3 a84cbb2a 2004-04-19 devnull */
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>
9 a84cbb2a 2004-04-19 devnull
10 a84cbb2a 2004-04-19 devnull enum{
11 a84cbb2a 2004-04-19 devnull CHUNK = 256 /* must be power of 2 */
12 a84cbb2a 2004-04-19 devnull };
13 a84cbb2a 2004-04-19 devnull
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;
24 a84cbb2a 2004-04-19 devnull
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;
29 a84cbb2a 2004-04-19 devnull
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*);
38 a84cbb2a 2004-04-19 devnull
39 a84cbb2a 2004-04-19 devnull void
40 a84cbb2a 2004-04-19 devnull main(int argc, char *argv[])
41 a84cbb2a 2004-04-19 devnull {
42 a84cbb2a 2004-04-19 devnull int i;
43 a84cbb2a 2004-04-19 devnull Biobuf *bin;
44 a84cbb2a 2004-04-19 devnull
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;
54 a84cbb2a 2004-04-19 devnull } ARGEND
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;
63 a84cbb2a 2004-04-19 devnull }
64 a84cbb2a 2004-04-19 devnull if (isar(bin))
65 a84cbb2a 2004-04-19 devnull doar(bin);
66 a84cbb2a 2004-04-19 devnull else{
67 a84cbb2a 2004-04-19 devnull Bseek(bin, 0, 0);
68 a84cbb2a 2004-04-19 devnull dofile(bin);
69 a84cbb2a 2004-04-19 devnull }
70 a84cbb2a 2004-04-19 devnull Bterm(bin);
71 a84cbb2a 2004-04-19 devnull }
72 a84cbb2a 2004-04-19 devnull exits(errs);
73 a84cbb2a 2004-04-19 devnull }
74 a84cbb2a 2004-04-19 devnull
75 a84cbb2a 2004-04-19 devnull /*
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.
78 a84cbb2a 2004-04-19 devnull */
79 a84cbb2a 2004-04-19 devnull void
80 a84cbb2a 2004-04-19 devnull doar(Biobuf *bp)
81 a84cbb2a 2004-04-19 devnull {
82 a84cbb2a 2004-04-19 devnull int offset, size, obj;
83 a84cbb2a 2004-04-19 devnull char membername[SARNAME];
84 a84cbb2a 2004-04-19 devnull
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);
90 a84cbb2a 2004-04-19 devnull return;
91 a84cbb2a 2004-04-19 devnull }
92 a84cbb2a 2004-04-19 devnull if (size == 0)
93 a84cbb2a 2004-04-19 devnull return;
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);
100 a84cbb2a 2004-04-19 devnull return;
101 a84cbb2a 2004-04-19 devnull }
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);
105 a84cbb2a 2004-04-19 devnull return;
106 a84cbb2a 2004-04-19 devnull }
107 a84cbb2a 2004-04-19 devnull filename = membername;
108 a84cbb2a 2004-04-19 devnull nsym=0;
109 a84cbb2a 2004-04-19 devnull objtraverse(psym, 0);
110 a84cbb2a 2004-04-19 devnull printsyms(symptr, nsym);
111 a84cbb2a 2004-04-19 devnull }
112 a84cbb2a 2004-04-19 devnull }
113 a84cbb2a 2004-04-19 devnull
114 a84cbb2a 2004-04-19 devnull /*
115 a84cbb2a 2004-04-19 devnull * process symbols in a file
116 a84cbb2a 2004-04-19 devnull */
117 a84cbb2a 2004-04-19 devnull void
118 a84cbb2a 2004-04-19 devnull dofile(Biobuf *bp)
119 a84cbb2a 2004-04-19 devnull {
120 a84cbb2a 2004-04-19 devnull int obj;
121 a84cbb2a 2004-04-19 devnull
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));
125 a84cbb2a 2004-04-19 devnull else
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);
130 a84cbb2a 2004-04-19 devnull }
131 a84cbb2a 2004-04-19 devnull }
132 a84cbb2a 2004-04-19 devnull
133 a84cbb2a 2004-04-19 devnull /*
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
136 a84cbb2a 2004-04-19 devnull */
137 a84cbb2a 2004-04-19 devnull int
138 a84cbb2a 2004-04-19 devnull cmp(void *vs, void *vt)
139 a84cbb2a 2004-04-19 devnull {
140 a84cbb2a 2004-04-19 devnull Symbol **s, **t;
141 a84cbb2a 2004-04-19 devnull
142 a84cbb2a 2004-04-19 devnull s = vs;
143 a84cbb2a 2004-04-19 devnull t = vt;
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;
147 a84cbb2a 2004-04-19 devnull else
148 a84cbb2a 2004-04-19 devnull return (*s)->value > (*t)->value;
149 a84cbb2a 2004-04-19 devnull return strcmp((*s)->name, (*t)->name);
150 a84cbb2a 2004-04-19 devnull }
151 a84cbb2a 2004-04-19 devnull /*
152 a84cbb2a 2004-04-19 devnull * enter a symbol in the table of filename elements
153 a84cbb2a 2004-04-19 devnull */
154 a84cbb2a 2004-04-19 devnull void
155 a84cbb2a 2004-04-19 devnull zenter(Symbol *s)
156 a84cbb2a 2004-04-19 devnull {
157 a84cbb2a 2004-04-19 devnull static int maxf = 0;
158 a84cbb2a 2004-04-19 devnull
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");
165 a84cbb2a 2004-04-19 devnull }
166 a84cbb2a 2004-04-19 devnull }
167 a84cbb2a 2004-04-19 devnull fnames[s->value] = s;
168 a84cbb2a 2004-04-19 devnull }
169 a84cbb2a 2004-04-19 devnull
170 a84cbb2a 2004-04-19 devnull /*
171 a84cbb2a 2004-04-19 devnull * get the symbol table from an executable file, if it has one
172 a84cbb2a 2004-04-19 devnull */
173 a84cbb2a 2004-04-19 devnull void
174 a84cbb2a 2004-04-19 devnull execsyms(int fd)
175 a84cbb2a 2004-04-19 devnull {
176 a84cbb2a 2004-04-19 devnull Fhdr f;
177 a84cbb2a 2004-04-19 devnull Symbol *s;
178 a84cbb2a 2004-04-19 devnull long n;
179 a84cbb2a 2004-04-19 devnull
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);
183 a84cbb2a 2004-04-19 devnull return;
184 a84cbb2a 2004-04-19 devnull }
185 a84cbb2a 2004-04-19 devnull if (syminit(fd, &f) < 0)
186 a84cbb2a 2004-04-19 devnull return;
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);
191 a84cbb2a 2004-04-19 devnull
192 a84cbb2a 2004-04-19 devnull printsyms(symptr, nsym);
193 a84cbb2a 2004-04-19 devnull }
194 a84cbb2a 2004-04-19 devnull
195 a84cbb2a 2004-04-19 devnull void
196 a84cbb2a 2004-04-19 devnull psym(Symbol *s, void* p)
197 a84cbb2a 2004-04-19 devnull {
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)
205 a84cbb2a 2004-04-19 devnull return;
206 a84cbb2a 2004-04-19 devnull if (!aflag && ((s->name[0] == '.' || s->name[0] == '$')))
207 a84cbb2a 2004-04-19 devnull return;
208 a84cbb2a 2004-04-19 devnull break;
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)
214 a84cbb2a 2004-04-19 devnull return;
215 a84cbb2a 2004-04-19 devnull if (!aflag && ((s->name[0] == '.' || s->name[0] == '$')))
216 a84cbb2a 2004-04-19 devnull return;
217 a84cbb2a 2004-04-19 devnull break;
218 a84cbb2a 2004-04-19 devnull case 'U':
219 a84cbb2a 2004-04-19 devnull if (gflag)
220 a84cbb2a 2004-04-19 devnull return;
221 a84cbb2a 2004-04-19 devnull break;
222 a84cbb2a 2004-04-19 devnull case 'Z':
223 a84cbb2a 2004-04-19 devnull if (!aflag)
224 a84cbb2a 2004-04-19 devnull return;
225 a84cbb2a 2004-04-19 devnull break;
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)
229 a84cbb2a 2004-04-19 devnull return;
230 a84cbb2a 2004-04-19 devnull if (strcmp(s->name, ".frame"))
231 a84cbb2a 2004-04-19 devnull zenter(s);
232 a84cbb2a 2004-04-19 devnull break;
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)
238 a84cbb2a 2004-04-19 devnull return;
239 a84cbb2a 2004-04-19 devnull break;
240 a84cbb2a 2004-04-19 devnull }
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");
245 a84cbb2a 2004-04-19 devnull }
246 a84cbb2a 2004-04-19 devnull symptr[nsym++] = s;
247 a84cbb2a 2004-04-19 devnull }
248 a84cbb2a 2004-04-19 devnull
249 a84cbb2a 2004-04-19 devnull void
250 a84cbb2a 2004-04-19 devnull printsyms(Symbol **symptr, long nsym)
251 a84cbb2a 2004-04-19 devnull {
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];
255 a84cbb2a 2004-04-19 devnull
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;
265 a84cbb2a 2004-04-19 devnull } else
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);
269 a84cbb2a 2004-04-19 devnull else
270 a84cbb2a 2004-04-19 devnull Bprint(&bout, " %c %s\n", s->type, cp);
271 a84cbb2a 2004-04-19 devnull }
272 a84cbb2a 2004-04-19 devnull }
273 a84cbb2a 2004-04-19 devnull
274 a84cbb2a 2004-04-19 devnull void
275 a84cbb2a 2004-04-19 devnull error(char *fmt, ...)
276 a84cbb2a 2004-04-19 devnull {
277 a84cbb2a 2004-04-19 devnull Fmt f;
278 a84cbb2a 2004-04-19 devnull char buf[128];
279 a84cbb2a 2004-04-19 devnull va_list arg;
280 a84cbb2a 2004-04-19 devnull
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";
289 a84cbb2a 2004-04-19 devnull }