Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature-vt/sys/src/cmd/nm.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/*
2
 * nm.c -- drive nm
3
 */
4
#include <u.h>
5
#include <libc.h>
6
#include <ar.h>
7
#include <bio.h>
8
#include <mach.h>
9
 
10
enum{
11
	CHUNK	=	256	/* must be power of 2 */
12
};
13
 
14
char	*errs;			/* exit status */
15
char	*filename;		/* current file */
16
char	symname[]="__.SYMDEF";	/* table of contents file name */
17
int	multifile;		/* processing multiple files */
18
int	aflag;
19
int	gflag;
20
int	hflag;
21
int	nflag;
22
int	sflag;
23
int	uflag;
24
int	Tflag;
25
 
26
Sym	**fnames;		/* file path translation table */
27
Sym	**symptr;
28
int	nsym;
29
Biobuf	bout;
30
 
31
int	cmp(void*, void*);
32
void	error(char*, ...);
33
void	execsyms(int);
34
void	psym(Sym*, void*);
35
void	printsyms(Sym**, long);
36
void	doar(Biobuf*);
37
void	dofile(Biobuf*);
38
void	zenter(Sym*);
39
 
40
void
41
usage(void)
42
{
43
	fprint(2, "usage: nm [-aghnsTu] file ...\n");
44
	exits("usage");
45
}
46
 
47
void
48
main(int argc, char *argv[])
49
{
50
	int i;
51
	Biobuf	*bin;
52
 
53
	Binit(&bout, 1, OWRITE);
54
	argv0 = argv[0];
55
	ARGBEGIN {
56
	default:	usage();
57
	case 'a':	aflag = 1; break;
58
	case 'g':	gflag = 1; break;
59
	case 'h':	hflag = 1; break;
60
	case 'n':	nflag = 1; break;
61
	case 's':	sflag = 1; break;
62
	case 'u':	uflag = 1; break;
63
	case 'T':	Tflag = 1; break;
64
	} ARGEND
65
	if (argc == 0)
66
		usage();
67
	if (argc > 1)
68
		multifile++;
69
	for(i=0; i<argc; i++){
70
		filename = argv[i];
71
		bin = Bopen(filename, OREAD);
72
		if(bin == 0){
73
			error("cannot open %s", filename);
74
			continue;
75
		}
76
		if (isar(bin))
77
			doar(bin);
78
		else{
79
			Bseek(bin, 0, 0);
80
			dofile(bin);
81
		}
82
		Bterm(bin);
83
	}
84
	exits(errs);
85
}
86
 
87
/*
88
 * read an archive file,
89
 * processing the symbols for each intermediate file in it.
90
 */
91
void
92
doar(Biobuf *bp)
93
{
94
	int offset, size, obj;
95
	char membername[SARNAME];
96
 
97
	multifile = 1;
98
	for (offset = Boffset(bp);;offset += size) {
99
		size = nextar(bp, offset, membername);
100
		if (size < 0) {
101
			error("phase error on ar header %ld", offset);
102
			return;
103
		}
104
		if (size == 0)
105
			return;
106
		if (strcmp(membername, symname) == 0)
107
			continue;
108
		obj = objtype(bp, 0);
109
		if (obj < 0) {
110
			error("inconsistent file %s in %s",
111
					membername, filename);
112
			return;
113
		}
114
		if (!readar(bp, obj, offset+size, 1)) {
115
			error("invalid symbol reference in file %s",
116
					membername);
117
			return;
118
		}
119
		filename = membername;
120
		nsym=0;
121
		objtraverse(psym, 0);
122
		printsyms(symptr, nsym);
123
	}
124
}
125
 
126
/*
127
 * process symbols in a file
128
 */
129
void
130
dofile(Biobuf *bp)
131
{
132
	int obj;
133
 
134
	obj = objtype(bp, 0);
135
	if (obj < 0)
136
		execsyms(Bfildes(bp));
137
	else
138
	if (readobj(bp, obj)) {
139
		nsym = 0;
140
		objtraverse(psym, 0);
141
		printsyms(symptr, nsym);
142
	}
143
}
144
 
145
/*
146
 * comparison routine for sorting the symbol table
147
 *	this screws up on 'z' records when aflag == 1
148
 */
149
int
150
cmp(void *vs, void *vt)
151
{
152
	Sym **s, **t;
153
 
154
	s = vs;
155
	t = vt;
156
	if(nflag)
157
		if((*s)->value < (*t)->value)
158
			return -1;
159
		else
160
			return (*s)->value > (*t)->value;
161
	return strcmp((*s)->name, (*t)->name);
162
}
163
/*
164
 * enter a symbol in the table of filename elements
165
 */
166
void
167
zenter(Sym *s)
168
{
169
	static int maxf = 0;
170
 
171
	if (s->value > maxf) {
172
		maxf = (s->value+CHUNK-1) &~ (CHUNK-1);
173
		fnames = realloc(fnames, (maxf+1)*sizeof(*fnames));
174
		if(fnames == 0) {
175
			error("out of memory", argv0);
176
			exits("memory");
177
		}
178
	}
179
	fnames[s->value] = s;
180
}
181
 
182
/*
183
 * get the symbol table from an executable file, if it has one
184
 */
185
void
186
execsyms(int fd)
187
{
188
	Fhdr f;
189
	Sym *s;
190
	long n;
191
 
192
	seek(fd, 0, 0);
193
	if (crackhdr(fd, &f) == 0) {
194
		error("Can't read header for %s", filename);
195
		return;
196
	}
197
	if (syminit(fd, &f) < 0)
198
		return;
199
	s = symbase(&n);
200
	nsym = 0;
201
	while(n--)
202
		psym(s++, 0);
203
 
204
	printsyms(symptr, nsym);
205
}
206
 
207
void
208
psym(Sym *s, void* p)
209
{
210
	USED(p);
211
	switch(s->type) {
212
	case 'T':
213
	case 'L':
214
	case 'D':
215
	case 'B':
216
		if (uflag)
217
			return;
218
		if (!aflag && ((s->name[0] == '.' || s->name[0] == '$')))
219
			return;
220
		break;
221
	case 'b':
222
	case 'd':
223
	case 'l':
224
	case 't':
225
		if (uflag || gflag)
226
			return;
227
		if (!aflag && ((s->name[0] == '.' || s->name[0] == '$')))
228
			return;
229
		break;
230
	case 'U':
231
		if (gflag)
232
			return;
233
		break;
234
	case 'Z':
235
		if (!aflag)
236
			return;
237
		break;
238
	case 'm':
239
	case 'f':	/* we only see a 'z' when the following is true*/
240
		if(!aflag || uflag || gflag)
241
			return;
242
		if (strcmp(s->name, ".frame"))
243
			zenter(s);
244
		break;
245
	case 'a':
246
	case 'p':
247
	case 'z':
248
	default:
249
		if(!aflag || uflag || gflag)
250
			return;
251
		break;
252
	}
253
	symptr = realloc(symptr, (nsym+1)*sizeof(Sym*));
254
	if (symptr == 0) {
255
		error("out of memory");
256
		exits("memory");
257
	}
258
	symptr[nsym++] = s;
259
}
260
 
261
void
262
printsyms(Sym **symptr, long nsym)
263
{
264
	int i, wid;
265
	Sym *s;
266
	char *cp;
267
	char path[512];
268
 
269
	if(!sflag)
270
		qsort(symptr, nsym, sizeof(*symptr), cmp);
271
 
272
	wid = 0;
273
	for (i=0; i<nsym; i++) {
274
		s = symptr[i];
275
		if (s->value && wid == 0)
276
			wid = 8;
277
		else if (s->value >= 0x100000000LL && wid == 8)
278
			wid = 16;
279
	}	
280
	for (i=0; i<nsym; i++) {
281
		s = symptr[i];
282
		if (multifile && !hflag)
283
			Bprint(&bout, "%s:", filename);
284
		if (s->type == 'z') {
285
			fileelem(fnames, (uchar *) s->name, path, 512);
286
			cp = path;
287
		} else
288
			cp = s->name;
289
		if (Tflag)
290
			Bprint(&bout, "%8ux ", s->sig);
291
		if (s->value || s->type == 'a' || s->type == 'p')
292
			Bprint(&bout, "%*llux ", wid, s->value);
293
		else
294
			Bprint(&bout, "%*s ", wid, "");
295
		Bprint(&bout, "%c %s\n", s->type, cp);
296
	}
297
}
298
 
299
void
300
error(char *fmt, ...)
301
{
302
	Fmt f;
303
	char buf[128];
304
	va_list arg;
305
 
306
	fmtfdinit(&f, 2, buf, sizeof buf);
307
	fmtprint(&f, "%s: ", argv0);
308
	va_start(arg, fmt);
309
	fmtvprint(&f, fmt, arg);
310
	va_end(arg);
311
	fmtprint(&f, "\n");
312
	fmtfdflush(&f);
313
	errs = "errors";
314
}