Warn 'ar q' doesn't update archive ST index.
[deliverable/binutils-gdb.git] / binutils / nm.c
1 /*** nm.c -- Describe symbol table of a rel file. */
2 #include "sysdep.h"
3 #include "bfd.h"
4 #include "getopt.h"
5 #include "stab.gnu.h"
6 #include <ranlib.h>
7
8
9
10 PROTO(static boolean, display_file, (char *filename));
11 PROTO(static boolean, do_one_rel_file, (bfd *file));
12 PROTO(static unsigned int, filter_symbols, (bfd *file, asymbol **syms,
13 unsigned long symcount));
14
15 PROTO(static void, print_symbols, (bfd *file, asymbol **syms,
16 unsigned long symcount));
17 extern PROTO(int, (*sorters[2][2]), (char *x, char *y));
18 PROTO(static void, print_symdef_entry, (bfd * abfd));
19
20 /* Command options. */
21
22 int external_only = 0; /* print external symbols only */
23 int file_on_each_line = 0; /* print file name on each line */
24 int no_sort = 0; /* don't sort; print syms in order found */
25 int print_debug_syms = 0; /* print debugger-only symbols too */
26 int print_armap = 0; /* describe __.SYMDEF data in archive files. */
27 int reverse_sort = 0; /* sort in downward(alpha or numeric) order */
28 int sort_numerically = 0; /* sort in numeric rather than alpha order */
29 int undefined_only = 0; /* print undefined symbols only */
30
31 boolean print_each_filename = false; /* Ick. Used in archives. */
32
33 /* IMPORT */
34 extern char *program_name;
35 extern char *program_version;
36 extern char *target;
37
38 struct option long_options[] = {
39 {"debug-syms", 0, &print_debug_syms, 1},
40 {"extern-only", 0, &external_only, 1},
41 {"no-sort", 0, &no_sort, 1},
42 {"numeric-sort", 0, &sort_numerically, 1},
43 {"print-armap", 0, &print_armap, 1},
44 {"print-file-name", 0, &file_on_each_line, 1},
45 {"reverse-sort", 0, &reverse_sort, 1},
46 {"target", 2, (int *)NULL, 0},
47 {"undefined-only", 0, &undefined_only, 1},
48 {0, 0, 0, 0}
49 };
50 \f
51 /* Some error-reporting functions */
52
53 void
54 usage ()
55 {
56 fprintf(stderr, "nm %s\nUsage: %s [-agnoprsu] filename...\n",
57 program_version, program_name);
58 exit(0);
59 }
60
61 int
62 main (argc, argv)
63 int argc;
64 char **argv;
65 {
66 int c; /* sez which option char */
67 int ind = 0; /* used by getopt and ignored by us */
68 extern int optind; /* steps thru options */
69
70 program_name = *argv;
71
72 while ((c = getopt_long(argc, argv, "agnoprsu", long_options, &ind)) != EOF) {
73 switch (c) {
74 case 'a': print_debug_syms = 1; break;
75 case 'g': external_only = 1; break;
76 case 'n': sort_numerically = 1; break;
77 case 'o': file_on_each_line = 1; break;
78 case 'p': no_sort = 1; break;
79 case 'r': reverse_sort = 1; break;
80 case 's': print_armap = 1; break;
81 case 'u': undefined_only = 1; break;
82
83 case 0:
84 if (!strcmp("target",(long_options[option_index]).name)) {
85 target = optarg;
86 }
87
88 break; /* we've been given a long option */
89
90 default:
91 usage ();
92 }
93 }
94
95 /* Strangely, for the shell you should return only a nonzero value
96 on sucess -- the inverse of the C sense. */
97
98 /* OK, all options now parsed. If no filename specified, do a.out. */
99 if (optind == argc) return !display_file ("a.out");
100
101 /* We were given several filenames to do: */
102 while (optind < argc)
103 if (!display_file (argv[optind++])) return 1;
104
105 return 0;
106 }
107 \f
108 /** Display a file's stats */
109
110 /* goto here is marginally cleaner than the nested if syntax */
111
112 static boolean
113 display_file (filename)
114 char *filename;
115 {
116 boolean retval = false;
117 bfd *file;
118 bfd *arfile = NULL;
119
120 file = bfd_openr(filename, target);
121 if (file == NULL) {
122 bfd_fatal (filename);
123 }
124
125 if (bfd_check_format(file, bfd_object)) {
126 retval = do_one_rel_file (file);
127 goto closer;
128 }
129
130 if (!bfd_check_format (file, bfd_archive)) {
131 fprintf (stderr, "%s: %s: unknown format.\n", program_name, filename);
132 retval = false;
133 goto closer;
134 }
135
136 printf("In archive %s:\n", filename);
137 if (print_armap) print_symdef_entry (file);
138 for (;;) {
139 arfile = bfd_openr_next_archived_file (file, arfile);
140
141 if (arfile == NULL) {
142 if (bfd_error != no_more_archived_files)
143 bfd_fatal (filename);
144 goto closer;
145 }
146
147 if (!bfd_check_format(arfile, bfd_object))
148 printf("%s: not an object file\n", arfile->filename);
149 else {
150 printf ("\n%s:\n", arfile->filename);
151 if (!do_one_rel_file (arfile)) return false;
152 }
153 }
154
155 closer:
156 if (bfd_close(file) == false)
157 bfd_fatal (filename);
158
159 return retval;
160 }
161 \f
162
163 static boolean
164 do_one_rel_file (abfd)
165 bfd *abfd;
166 {
167 unsigned int storage;
168 asymbol **syms;
169 unsigned int symcount = 0;
170
171 if (!(bfd_get_file_flags (abfd) & HAS_SYMS)) {
172 (void) printf ("No symbols in \"%s\".\n", bfd_get_filename (abfd));
173 return true;
174 }
175
176
177 storage = get_symtab_upper_bound (abfd);
178 if (storage == 0) {
179 nosymz:
180 fprintf (stderr, "%s: Symflags set but there are none?\n",
181 bfd_get_filename (abfd));
182 exit (1);
183 }
184
185 syms = (asymbol **) xmalloc (storage);
186
187 symcount = bfd_canonicalize_symtab (abfd, syms);
188 if (symcount == 0) goto nosymz;
189
190 /* Discard the symbols we don't want to print.
191 It's OK to do this in place; we'll free the storage anyway
192 (after printing) */
193
194 symcount = filter_symbols (abfd, syms, symcount);
195
196 if (!no_sort)
197 qsort((char *) syms, symcount, sizeof (asymbol *),
198 sorters[sort_numerically][reverse_sort]);
199
200 if (print_each_filename && !file_on_each_line)
201 printf("\n%s:\n", bfd_get_filename(abfd));
202
203 print_symbols (abfd, syms, symcount);
204 free (syms);
205 return true;
206 }
207 \f
208 /* Symbol-sorting predicates */
209 #define valueof(x) ((x)->section ? (x)->section->vma + (x)->value : (x)->value)
210 int
211 numeric_forward (x, y)
212 char *x;
213 char *y;
214 {
215
216 return (valueof(*(asymbol **)x) - valueof(*(asymbol **) y));;
217 }
218
219 int
220 numeric_reverse (x, y)
221 char *x;
222 char *y;
223 {
224 return (valueof(*(asymbol **)y) - valueof(*(asymbol **) x));
225
226 }
227
228 int
229 non_numeric_forward (x, y)
230 char *x;
231 char *y;
232 {
233 CONST char *xn = (*(asymbol **) x)->name;
234 CONST char *yn = (*(asymbol **) y)->name;
235
236 return ((xn == NULL) ? ((yn == NULL) ? 0 : -1) :
237 ((yn == NULL) ? 1 : strcmp (xn, yn)));
238 }
239
240 int
241 non_numeric_reverse (x, y)
242 char *x;
243 char *y;
244 {
245 return -(non_numeric_forward (x, y));
246 }
247
248 int (*sorters[2][2])() = {
249 {non_numeric_forward, non_numeric_reverse},
250 {numeric_forward, numeric_reverse},
251 };
252 \f
253
254 /* Choose which symbol entries to print;
255 compact them downward to get rid of the rest.
256 Return the number of symbols to be printed. */
257 static unsigned int
258 filter_symbols (abfd, syms, symcount)
259 bfd *abfd;
260 asymbol **syms;
261 unsigned long symcount;
262 {
263 asymbol **from, **to;
264 unsigned int dst_count = 0;
265 unsigned int src_count;
266 for (from = to = syms, src_count = 0; src_count <symcount; src_count++) {
267 int keep = 0;
268 flagword flags = (from[src_count])->flags;
269
270 if (undefined_only) {
271 keep = (flags & BSF_UNDEFINED);
272 } else if (external_only) {
273 keep = ((flags & BSF_GLOBAL) || (flags & BSF_UNDEFINED) ||
274 (flags & BSF_FORT_COMM));
275 } else {
276 keep = 1;
277 }
278
279 if (!print_debug_syms && ((flags & BSF_DEBUGGING) != 0)) {
280 keep = 0;
281 }
282
283 if (keep) {
284 to[dst_count++] = from[src_count];
285 }
286 }
287
288 return dst_count;
289 }
290 \f
291
292 /* Return a lower-case character corresponding to the symbol class of sym */
293 char
294 decode_symclass (sym)
295 asymbol *sym;
296 {
297 flagword flags = sym->flags;
298
299 if ((sym->value == 0) && (sym->section != NULL))
300 /* Huh? All section names don't begin with "." */
301 return (sym->section->name)[1];
302
303 if (flags & BSF_FORT_COMM) return 'C';
304 if (flags & BSF_UNDEFINED) return 'U';
305 if (flags & BSF_ABSOLUTE) return 'a';
306
307
308 if ( (flags & BSF_GLOBAL) || (flags & BSF_LOCAL) ){
309 if ( !strcmp(sym->section->name, ".text") ){
310 return 't';
311 } else if ( !strcmp(sym->section->name, ".data") ){
312 return 'd';
313 } else if ( !strcmp(sym->section->name, ".bss") ){
314 return 'b';
315 } else {
316 return 'o';
317 }
318 }
319
320 /* We don't have to handle these cases just yet, but we will soon:
321 N_SETV: 'v';
322 N_SETA: 'l';
323 N_SETT: 'x';
324 N_SETD: 'z';
325 N_SETB: 's';
326 N_INDR: 'i';
327 */
328
329 return '?';
330 }
331
332 static void
333 print_symbols (abfd, syms, symcount)
334 bfd *abfd;
335 asymbol **syms;
336 unsigned long symcount;
337 {
338 asymbol **sym = syms, **end = syms + symcount;
339 char class;
340
341 for (; sym < end; ++sym) {
342 if (file_on_each_line) printf("%s:", bfd_get_filename(abfd));
343
344 if (undefined_only) {
345 if ((*sym)->flags & BSF_UNDEFINED)
346 puts ((*sym)->name);
347 }
348 else {
349 asymbol *p = *sym;
350 if (p) {
351 class = decode_symclass (p);
352
353 if (p->flags & BSF_GLOBAL)
354 class = toupper (class);
355
356 if (p->value || ((p->flags & BSF_UNDEFINED) != BSF_UNDEFINED))
357 printf_vma( (p->section ? p->value + p->section->vma : p->value));
358 else fputs (" ", stdout);
359
360 printf (" %c %s\n", class, p->name);
361 }
362 }
363 }
364 }
365
366 static void
367 print_symdef_entry (abfd)
368 bfd * abfd;
369 {
370 symindex idx = BFD_NO_MORE_SYMBOLS;
371 carsym *thesym;
372 boolean everprinted = false;
373
374 for (idx = bfd_get_next_mapent (abfd, idx, &thesym);
375 idx != BFD_NO_MORE_SYMBOLS;
376 idx = bfd_get_next_mapent (abfd, idx, &thesym)) {
377 bfd *elt;
378 if (!everprinted) {
379 printf ("\nArchive index:\n");
380 everprinted = true;
381 }
382 elt = bfd_get_elt_at_index (abfd, idx);
383 if (thesym->name != (char *)NULL) {
384 printf ("%s in %s\n", thesym->name, bfd_get_filename (elt));
385 }
386 }
387 }
This page took 0.036911 seconds and 4 git commands to generate.