source: trunk/minix/commands/simple/nm.c@ 15

Last change on this file since 15 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 5.1 KB
Line 
1/* nm - print name list. Author: Dick van Veen */
2
3/* Dick van Veen: veench@cs.vu.nl */
4
5#include <sys/types.h>
6#include <a.out.h>
7#include <fcntl.h>
8#include <unistd.h>
9#include <stdlib.h>
10#include <string.h>
11#include <stdio.h>
12
13/* Read the name list in memory, sort it, and print it. */
14
15/* Nm [-gnopru] [file] ...
16 *
17 * flags:
18 * -d address in decimal
19 * -g print only external symbols.
20 * -n sort numerically rather than alphabetically.
21 * -o prepend file name to each line rather than only once.
22 * -p don't sort, pint n symbol-table order.
23 * -r sort in reverse order.
24 * -u print only undefined symbols.
25 *
26 * - when no file name is present, a.out is assumed.
27 *
28 * NOTE: no archives are supported because assembly files don't
29 * have symbol tables.
30 *
31 */
32
33#define A_OUT "a.out"
34
35int d_flag;
36int g_flag;
37int n_flag;
38int o_flag;
39int p_flag;
40int r_flag;
41int u_flag;
42
43char io_buf[BUFSIZ]; /* io buffer */
44struct exec header; /* header of a.out file */
45int stbl_elems; /* #elements in symbol table */
46
47_PROTOTYPE(int main, (int argc, char **argv));
48_PROTOTYPE(int nm_sort, (const void *tmp_stbl1, const void *tmp_stbl2));
49_PROTOTYPE(void nm, (char *file));
50_PROTOTYPE(int read_header, (int fd));
51_PROTOTYPE(void nm_print, (char *file, struct nlist *stbl));
52
53int main(argc, argv)
54int argc;
55char **argv;
56{
57 argv++;
58 while (*argv != 0 && **argv == '-') {
59 *argv += 1;
60 while (**argv != '\0') {
61 switch (**argv) {
62 case 'd': d_flag = 1; break;
63 case 'g': g_flag = 1; break;
64 case 'n': n_flag = 1; break;
65 case 'o': o_flag = 1; break;
66 case 'p': p_flag = 1; break;
67 case 'r': r_flag = 1; break;
68 case 'u': u_flag = 1; break;
69 default:
70 fprintf(stderr, "illegal flag: -%c\n", **argv);
71 exit(-1);
72 }
73 *argv += 1;
74 }
75 argv++;
76 }
77 setbuf(stdin, io_buf);
78 if (*argv == 0)
79 nm(A_OUT);
80 else
81 while (*argv != 0) {
82 nm(*argv);
83 argv++;
84 }
85 return(0);
86}
87
88int nm_sort(tmp_stbl1, tmp_stbl2)
89_CONST void *tmp_stbl1, *tmp_stbl2;
90{
91
92 struct nlist *stbl1 = (struct nlist *)tmp_stbl1;
93 struct nlist *stbl2 = (struct nlist *)tmp_stbl2;
94 int cmp;
95
96 if (n_flag) { /* sort numerically */
97 if ((stbl1->n_sclass & N_SECT) <
98 (stbl2->n_sclass & N_SECT))
99 cmp = -1;
100 else if ((stbl1->n_sclass & N_SECT) >
101 (stbl2->n_sclass & N_SECT))
102 cmp = 1;
103 else if (stbl1->n_value < stbl2->n_value)
104 cmp = -1;
105 else if (stbl1->n_value > stbl2->n_value)
106 cmp = 1;
107 else
108 cmp = strncmp(stbl1->n_name, stbl2->n_name, (size_t)8);
109 } else {
110 cmp = strncmp(stbl1->n_name, stbl2->n_name, (size_t)8);
111 if (cmp == 0) {
112 if (stbl1->n_value < stbl2->n_value)
113 cmp = -1;
114 else if (stbl1->n_value > stbl2->n_value)
115 cmp = 1;
116 }
117 }
118
119 if (r_flag) cmp = -cmp; /* reverse sort */
120 return(cmp);
121}
122
123void nm(file)
124char *file;
125{
126 struct nlist *stbl;
127 int fd;
128
129 fd = open(file, O_RDONLY);
130 if (fd == -1) {
131 fprintf(stderr, "can't open %s\n", file);
132 return;
133 }
134 if (read_header(fd)) {
135 fprintf(stderr, "%s: no executable file\n", file);
136 close(fd);
137 return;
138 }
139 if (header.a_syms == 0) {
140 close(fd);
141 return;
142 }
143 if ((size_t) header.a_syms != header.a_syms) {
144 fprintf(stderr, "%s: symbol table too large to allocate\n", file);
145 close(fd);
146 return;
147 }
148 if ((int) header.a_syms != header.a_syms) {
149 /* This is necessary because we are too lazy to iterate the read. */
150 fprintf(stderr, "%s: symbol table too large to read\n", file);
151 close(fd);
152 return;
153 }
154 stbl = (struct nlist *) malloc((size_t) header.a_syms);
155 if (stbl == NULL) {
156 fprintf(stderr, "%s: can't allocate symbol table\n", file);
157 close(fd);
158 return;
159 }
160 if (read(fd, (char *) stbl, (unsigned) header.a_syms) != header.a_syms) {
161 fprintf(stderr, "%s: can't read symbol table\n", file);
162 free(stbl);
163 close(fd);
164 return;
165 }
166 stbl_elems = (int) header.a_syms / sizeof(struct nlist);
167 if (!p_flag) qsort(stbl, (size_t)stbl_elems, sizeof(struct nlist), nm_sort);
168 nm_print(file, stbl);
169 free(stbl);
170 close(fd);
171}
172
173int read_header(fd)
174int fd;
175{
176 if (read(fd, (char *) &header, sizeof(struct exec)) != sizeof(struct exec))
177 return(1);
178 if (BADMAG(header)) return(1);
179 lseek(fd, A_SYMPOS(header), SEEK_SET);
180
181 return(0);
182}
183
184void nm_print(file, stbl)
185char *file;
186register struct nlist *stbl;
187{
188 struct nlist *last;
189 char name[9];
190 int n_sclass;
191 char type;
192
193 name[8] = '\0';
194 if (!o_flag) printf("%s:\n", file);
195 for (last = &stbl[stbl_elems]; stbl != last; stbl++) {
196 if (g_flag && (stbl->n_sclass & N_CLASS) != C_EXT) continue;
197 if (u_flag && (stbl->n_sclass & N_SECT) != N_UNDF) continue;
198
199 n_sclass = stbl->n_sclass & N_SECT;
200 if (n_sclass == N_ABS)
201 type = 'a';
202 else if (n_sclass == N_TEXT)
203 type = 't';
204 else if (n_sclass == N_DATA)
205 type = 'd';
206 else if (n_sclass == N_BSS)
207 type = 'b';
208 else
209 type = 'u';
210 if ((stbl->n_sclass & N_CLASS) == C_EXT) type += 'A' - 'a';
211 strncpy(name, stbl->n_name, (size_t)8);
212 if (d_flag) {
213 /* Offsets in decimal. */
214 if (o_flag)
215 printf("%s:%08ld %c %s\n",file,stbl->n_value,type,name);
216 else
217 printf("%08ld %c %s\n", stbl->n_value, type, name);
218 } else {
219 /* Offsets in hex. */
220 if (o_flag)
221 printf("%s:%08lx %c %s\n",file,stbl->n_value,type,name);
222 else
223 printf("%08lx %c %s\n", stbl->n_value, type, name);
224 }
225 }
226}
Note: See TracBrowser for help on using the repository browser.