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