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