BSD 3 development
[unix-history] / usr / src / cmd / nm.c
CommitLineData
f512a36d
BJ
1/*
2** print symbol tables for
3** object or archive files
4**
5** nm [-goprun] [name ...]
6*/
7
8
9
10#include <ar.h>
11#include <stdio.h>
12#include <ctype.h>
13#include <a.out.h>
14#include <pagsiz.h>
15
16#define MAGIC exp.a_magic
17#define BADMAG MAGIC!=A_MAGIC1 && MAGIC!=A_MAGIC2 \
18 && MAGIC!=A_MAGIC3 && MAGIC!=A_MAGIC4 && MAGIC != 0412 && MAGIC != 0413
19#define SELECT arch_flg ? arp.ar_name : *argv
20int numsort_flg;
21int undef_flg;
22int revsort_flg = 1;
23int globl_flg;
24int nosort_flg;
25int arch_flg;
26int prep_flg;
27struct ar_hdr arp;
28struct exec exp;
29FILE *fi;
30long off;
31long ftell();
32char *malloc();
33char *realloc();
34
35main(argc, argv)
36char **argv;
37{
38 int narg;
39 int compare();
40
41 if (--argc>0 && argv[1][0]=='-' && argv[1][1]!=0) {
42 argv++;
43 while (*++*argv) switch (**argv) {
44 case 'n': /* sort numerically */
45 numsort_flg++;
46 continue;
47
48 case 'g': /* globl symbols only */
49 globl_flg++;
50 continue;
51
52 case 'u': /* undefined symbols only */
53 undef_flg++;
54 continue;
55
56 case 'r': /* sort in reverse order */
57 revsort_flg = -1;
58 continue;
59
60 case 'p': /* don't sort -- symbol table order */
61 nosort_flg++;
62 continue;
63
64 case 'o': /* prepend a name to each line */
65 prep_flg++;
66 continue;
67
68 default: /* oops */
69 fprintf(stderr, "nm: invalid argument -%c\n", *argv[0]);
70 exit(1);
71 }
72 argc--;
73 }
74 if (argc == 0) {
75 argc = 1;
76 argv[1] = "a.out";
77 }
78 narg = argc;
79 while(argc--) {
80 fi = fopen(*++argv,"r");
81 if (fi == NULL) {
82 fprintf(stderr, "nm: cannot open %s\n", *argv);
83 continue;
84 }
85 off = sizeof(exp.a_magic);
86 fread((char *)&exp, 1, sizeof(MAGIC), fi); /* get magic no. */
87 if (MAGIC == ARMAG)
88 arch_flg++;
89 else if (BADMAG) {
90 fprintf(stderr, "nm: %s-- bad format\n", *argv);
91 continue;
92 }
93 fseek(fi, 0L, 0);
94 if (arch_flg) {
95 nextel(fi);
96 if (narg > 1)
97 printf("\n%s:\n", *argv);
98 }
99 do {
100 long o;
101 register i, n, c;
102 struct nlist *symp = NULL;
103 struct nlist sym;
104
105 fread((char *)&exp, 1, sizeof(struct exec), fi);
106 if (BADMAG) /* archive element not in */
107 continue; /* proper format - skip it */
108 o = (long)exp.a_text + exp.a_data + exp.a_trsize + exp.a_drsize;
109 if (MAGIC==0412 || MAGIC==0413)
110 o += PAGSIZ - sizeof(struct exec);
111 fseek(fi, o, 1);
112 n = exp.a_syms / sizeof(struct nlist);
113 if (n == 0) {
114 fprintf(stderr, "nm: %s-- no name list\n", SELECT);
115 continue;
116 }
117 i = 0;
118 while (--n >= 0) {
119 fread((char *)&sym, 1, sizeof(sym), fi);
120 if (globl_flg && (sym.n_type&N_EXT)==0)
121 continue;
122 if (symp==NULL)
123 symp = (struct nlist *)malloc(sizeof(struct nlist));
124 else {
125 symp = (struct nlist *)realloc(symp, (i+1)*sizeof(struct nlist));
126 }
127 if (symp == NULL) {
128 fprintf(stderr, "nm: out of memory on %s\n", *argv);
129 exit(2);
130 }
131 symp[i++] = sym;
132 }
133 if (nosort_flg==0)
134 qsort(symp, i, sizeof(struct nlist), compare);
135 if ((arch_flg || narg>1) && prep_flg==0)
136 printf("\n%s:\n", SELECT);
137 for (n=0; n<i; n++) {
138 if (prep_flg) {
139 if (arch_flg)
140 printf("%s:", *argv);
141 printf("%s:", SELECT);
142 }
143 c = symp[n].n_type;
144
145 if (c & STABTYPE) {
146 printf("%08x - %-8.8s %02x %02x %04x\n",
147 symp[n].n_value,
148 symp[n].n_name,
149 symp[n].n_type & 0xff,
150 symp[n].n_other & 0xff,
151 symp[n].n_desc & 0xffff);
152 continue;
153 }
154 switch (c&(N_TYPE-N_EXT)) {
155
156 case N_UNDF:
157 c = 'u';
158 if (symp[n].n_value)
159 c = 'c';
160 break;
161
162 case N_ABS:
163 c = 'a';
164 break;
165
166 case N_TEXT:
167 c = 't';
168 break;
169
170 case N_DATA:
171 c = 'd';
172 break;
173
174 case N_BSS:
175 c = 'b';
176 break;
177
178 case N_FN:
179 c = 'f';
180 break;
181
182/*
183 case N_REG:
184 c = 'r';
185 break;
186 */
187 }
188 if (undef_flg && c!='u')
189 continue;
190 if (symp[n].n_type&N_EXT)
191 c = toupper(c);
192 if (!undef_flg) {
193 if (c=='u' || c=='U')
194 printf(" ");
195 else
196 printf(FORMAT, symp[n].n_value);
197 printf(" %c ", c);
198 }
199 printf("%.8s\n", symp[n].n_name);
200 l1:; }
201 if (symp)
202 free((char *)symp);
203 } while(arch_flg && nextel(fi));
204 fclose(fi);
205 }
206 exit(0);
207}
208
209compare(p1, p2)
210struct nlist *p1, *p2;
211{
212 register i;
213
214 if (numsort_flg) {
215 if (p1->n_value > p2->n_value)
216 return(revsort_flg);
217 if (p1->n_value < p2->n_value)
218 return(-revsort_flg);
219 }
220 for(i=0; i<sizeof(p1->n_name); i++)
221 if (p1->n_name[i] != p2->n_name[i]) {
222 if (p1->n_name[i] > p2->n_name[i])
223 return(revsort_flg);
224 else
225 return(-revsort_flg);
226 }
227 return(0);
228}
229
230nextel(af)
231FILE *af;
232{
233 register r;
234
235 fseek(af, off, 0);
236 r = fread((char *)&arp, 1, sizeof(struct ar_hdr), af); /* read archive header */
237 if (r <= 0)
238 return(0);
239 if (arp.ar_size & 1)
240 ++arp.ar_size;
241 off = ftell(af) + arp.ar_size; /* offset to next element */
242 return(1);
243}