1 /* nm.c -- Describe symbol table of a rel file.
2 Copyright 1991, 1992 Free Software Foundation, Inc.
4 This file is part of GNU Binutils.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
24 #include "aout/stab_gnu.h"
25 #include "aout/ranlib.h"
28 display_file
PARAMS ((char *filename
));
31 do_one_rel_file
PARAMS ((bfd
* file
, bfd
*archive
));
34 filter_symbols
PARAMS ((bfd
*file
, asymbol
**syms
, unsigned long symcount
));
37 print_symbols
PARAMS ((bfd
*file
, asymbol
**syms
, unsigned long symcount
,
41 print_symdef_entry
PARAMS ((bfd
* abfd
));
43 /* Command options. */
45 int external_only
= 0; /* print external symbols only */
46 int file_on_each_line
= 0; /* print file name on each line */
47 int no_sort
= 0; /* don't sort; print syms in order found */
48 int print_debug_syms
= 0; /* print debugger-only symbols too */
49 int print_armap
= 0; /* describe __.SYMDEF data in archive files. */
50 int reverse_sort
= 0; /* sort in downward(alpha or numeric) order */
51 int sort_numerically
= 0; /* sort in numeric rather than alpha order */
52 int undefined_only
= 0; /* print undefined symbols only */
53 int show_version
= 0; /* show the version number */
55 boolean print_each_filename
= false; /* Ick. Used in archives. */
58 extern char *program_name
;
59 extern char *program_version
;
61 extern int print_version
;
63 struct option long_options
[] = {
64 {"debug-syms", no_argument
, &print_debug_syms
, 1},
65 {"extern-only", no_argument
, &external_only
, 1},
66 {"no-sort", no_argument
, &no_sort
, 1},
67 {"numeric-sort", no_argument
, &sort_numerically
, 1},
68 {"print-armap", no_argument
, &print_armap
, 1},
69 {"print-file-name", no_argument
, &file_on_each_line
, 1},
70 {"reverse-sort", no_argument
, &reverse_sort
, 1},
71 {"target", optional_argument
, 0, 200},
72 {"undefined-only", no_argument
, &undefined_only
, 1},
73 {"version", no_argument
, &show_version
, 1},
74 {0, no_argument
, 0, 0}
79 /* Some error-reporting functions */
84 fprintf(stderr
, "nm %s\n\
85 Usage: %s [-agnoprsuV] [--debug-syms] [--extern-only] [--print-armap]\n\
86 [--print-file-name] [--numeric-sort] [--no-sort] [--reverse-sort]\n\
87 [--undefined-only] [--target=bfdname] [file...]\n",
88 program_version
, program_name
);
97 int c
; /* sez which option char */
103 while ((c
= getopt_long(argc
, argv
, "agnoprsuvABV", long_options
, (int *) 0)) != EOF
) {
105 case 'a': print_debug_syms
= 1; break;
106 case 'g': external_only
= 1; break;
107 case 'n': sort_numerically
= 1; break;
108 case 'o': file_on_each_line
= 1; break;
109 case 'p': no_sort
= 1; break;
110 case 'r': reverse_sort
= 1; break;
111 case 's': print_armap
= 1; break;
112 case 'u': undefined_only
= 1; break;
114 case 'V': show_version
= 1; break;
116 /* For MIPS compatibility, -A selects System V style output, -B
117 selects BSD style output. These are not implemented. When
118 they are, they should be added to usage (). */
122 case 200: /* --target */
132 printf ("%s version %s\n", program_name
, program_version
);
134 /* Strangely, for the shell you should return only a nonzero value
135 on sucess -- the inverse of the C sense. */
137 /* OK, all options now parsed. If no filename specified, do a.out. */
138 if (optind
== argc
) return !display_file ("a.out");
141 show_names
= (argc
-optind
)>1;
142 /* We were given several filenames to do: */
143 while (optind
< argc
) {
144 if (!display_file (argv
[optind
++])) {
152 /* Display a file's stats */
154 /* goto here is marginally cleaner than the nested if syntax */
157 display_file (filename
)
160 boolean retval
= true;
164 file
= bfd_openr(filename
, target
);
166 fprintf (stderr
, "%s: ", program_name
);
167 bfd_perror (filename
);
171 if (bfd_check_format(file
, bfd_object
))
174 printf ("\n%s:\n",filename
);
176 do_one_rel_file (file
, NULL
);
178 else if (bfd_check_format (file
, bfd_archive
)) {
179 if (!bfd_check_format (file
, bfd_archive
)) {
180 fprintf (stderr
, "%s: %s: unknown format\n", program_name
, filename
);
185 if (!file_on_each_line
)
186 printf("\n%s:\n", filename
);
187 if (print_armap
) print_symdef_entry (file
);
189 arfile
= bfd_openr_next_archived_file (file
, arfile
);
191 if (arfile
== NULL
) {
192 if (bfd_error
!= no_more_archived_files
)
193 bfd_fatal (filename
);
197 if (!bfd_check_format(arfile
, bfd_object
))
198 printf("%s: not an object file\n", arfile
->filename
);
200 if (!file_on_each_line
)
201 printf ("\n%s:\n", arfile
->filename
);
202 do_one_rel_file (arfile
, file
) ;
207 fprintf (stderr
, "\n%s: %s: unknown format\n", program_name
, filename
);
212 if (bfd_close(file
) == false)
213 bfd_fatal (filename
);
218 /* Symbol-sorting predicates */
219 #define valueof(x) ((x)->section->vma + (x)->value)
221 numeric_forward (x
, y
)
225 return (valueof(*(asymbol
**)x
) - valueof(*(asymbol
**) y
));
229 numeric_reverse (x
, y
)
233 return (valueof(*(asymbol
**)y
) - valueof(*(asymbol
**) x
));
237 non_numeric_forward (x
, y
)
241 CONST
char *xn
= (*(asymbol
**) x
)->name
;
242 CONST
char *yn
= (*(asymbol
**) y
)->name
;
244 return ((xn
== NULL
) ? ((yn
== NULL
) ? 0 : -1) :
245 ((yn
== NULL
) ? 1 : strcmp (xn
, yn
)));
249 non_numeric_reverse (x
, y
)
253 return -(non_numeric_forward (x
, y
));
256 int (*(sorters
[2][2])) PARAMS ((CONST
void *, CONST
void *)) = {
257 {non_numeric_forward
, non_numeric_reverse
},
258 {numeric_forward
, numeric_reverse
},
262 do_one_rel_file (abfd
, archive_bfd
)
264 bfd
*archive_bfd
; /* If non-NULL: archive containing abfd. */
266 unsigned int storage
;
268 unsigned int symcount
= 0;
270 if (!(bfd_get_file_flags (abfd
) & HAS_SYMS
)) {
271 (void) printf ("No symbols in \"%s\".\n", bfd_get_filename (abfd
));
275 storage
= get_symtab_upper_bound (abfd
);
278 fprintf (stderr
, "%s: Symflags set but there are none?\n",
279 bfd_get_filename (abfd
));
283 syms
= (asymbol
**) xmalloc (storage
);
285 symcount
= bfd_canonicalize_symtab (abfd
, syms
);
286 if (symcount
== 0) goto nosymz
;
288 /* Discard the symbols we don't want to print.
289 It's OK to do this in place; we'll free the storage anyway
292 symcount
= filter_symbols (abfd
, syms
, symcount
);
295 qsort((char *) syms
, symcount
, sizeof (asymbol
*),
296 sorters
[sort_numerically
][reverse_sort
]);
298 if (print_each_filename
&& !file_on_each_line
)
299 printf("\n%s:\n", bfd_get_filename(abfd
));
301 print_symbols (abfd
, syms
, symcount
, archive_bfd
);
305 /* Choose which symbol entries to print;
306 compact them downward to get rid of the rest.
307 Return the number of symbols to be printed. */
309 filter_symbols (abfd
, syms
, symcount
)
312 unsigned long symcount
;
314 asymbol
**from
, **to
;
315 unsigned int dst_count
= 0;
318 unsigned int src_count
;
319 for (from
= to
= syms
, src_count
= 0; src_count
<symcount
; src_count
++) {
322 flagword flags
= (from
[src_count
])->flags
;
323 sym
= from
[src_count
];
324 if (undefined_only
) {
325 keep
= sym
->section
== &bfd_und_section
;
326 } else if (external_only
) {
327 keep
= ((flags
& BSF_GLOBAL
)
328 || (sym
->section
== &bfd_und_section
)
329 || (bfd_is_com_section (sym
->section
)));
334 if (!print_debug_syms
&& ((flags
& BSF_DEBUGGING
) != 0)) {
339 to
[dst_count
++] = from
[src_count
];
347 print_symbols (abfd
, syms
, symcount
, archive_bfd
)
350 unsigned long symcount
;
353 asymbol
**sym
= syms
, **end
= syms
+ symcount
;
355 for (; sym
< end
; ++sym
) {
356 if (file_on_each_line
) {
358 printf("%s:", bfd_get_filename(archive_bfd
));
359 printf("%s:", bfd_get_filename(abfd
));
362 if (undefined_only
) {
363 if ((*sym
)->section
== &bfd_und_section
)
369 bfd_print_symbol(abfd
, stdout
, p
, bfd_print_symbol_nm
);
377 print_symdef_entry (abfd
)
380 symindex idx
= BFD_NO_MORE_SYMBOLS
;
382 boolean everprinted
= false;
384 for (idx
= bfd_get_next_mapent (abfd
, idx
, &thesym
);
385 idx
!= BFD_NO_MORE_SYMBOLS
;
386 idx
= bfd_get_next_mapent (abfd
, idx
, &thesym
)) {
389 printf ("\nArchive index:\n");
392 elt
= bfd_get_elt_at_index (abfd
, idx
);
393 if (thesym
->name
!= (char *)NULL
) {
394 printf ("%s in %s\n", thesym
->name
, bfd_get_filename (elt
));