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