xref: /openbsd-src/gnu/usr.bin/binutils-2.17/binutils/nm.c (revision 3d8817e467ea46cf4772788d6804dd293abfb01a)
1*3d8817e4Smiod /* nm.c -- Describe symbol table of a rel file.
2*3d8817e4Smiod    Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3*3d8817e4Smiod    2001, 2002, 2003, 2004, 2005
4*3d8817e4Smiod    Free Software Foundation, Inc.
5*3d8817e4Smiod 
6*3d8817e4Smiod    This file is part of GNU Binutils.
7*3d8817e4Smiod 
8*3d8817e4Smiod    This program is free software; you can redistribute it and/or modify
9*3d8817e4Smiod    it under the terms of the GNU General Public License as published by
10*3d8817e4Smiod    the Free Software Foundation; either version 2 of the License, or
11*3d8817e4Smiod    (at your option) any later version.
12*3d8817e4Smiod 
13*3d8817e4Smiod    This program is distributed in the hope that it will be useful,
14*3d8817e4Smiod    but WITHOUT ANY WARRANTY; without even the implied warranty of
15*3d8817e4Smiod    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16*3d8817e4Smiod    GNU General Public License for more details.
17*3d8817e4Smiod 
18*3d8817e4Smiod    You should have received a copy of the GNU General Public License
19*3d8817e4Smiod    along with this program; if not, write to the Free Software
20*3d8817e4Smiod    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
21*3d8817e4Smiod    02110-1301, USA.  */
22*3d8817e4Smiod 
23*3d8817e4Smiod #include "bfd.h"
24*3d8817e4Smiod #include "progress.h"
25*3d8817e4Smiod #include "bucomm.h"
26*3d8817e4Smiod #include "budemang.h"
27*3d8817e4Smiod #include "getopt.h"
28*3d8817e4Smiod #include "aout/stab_gnu.h"
29*3d8817e4Smiod #include "aout/ranlib.h"
30*3d8817e4Smiod #include "demangle.h"
31*3d8817e4Smiod #include "libiberty.h"
32*3d8817e4Smiod #include "elf-bfd.h"
33*3d8817e4Smiod #include "elf/common.h"
34*3d8817e4Smiod 
35*3d8817e4Smiod /* When sorting by size, we use this structure to hold the size and a
36*3d8817e4Smiod    pointer to the minisymbol.  */
37*3d8817e4Smiod 
38*3d8817e4Smiod struct size_sym
39*3d8817e4Smiod {
40*3d8817e4Smiod   const void *minisym;
41*3d8817e4Smiod   bfd_vma size;
42*3d8817e4Smiod };
43*3d8817e4Smiod 
44*3d8817e4Smiod /* When fetching relocs, we use this structure to pass information to
45*3d8817e4Smiod    get_relocs.  */
46*3d8817e4Smiod 
47*3d8817e4Smiod struct get_relocs_info
48*3d8817e4Smiod {
49*3d8817e4Smiod   asection **secs;
50*3d8817e4Smiod   arelent ***relocs;
51*3d8817e4Smiod   long *relcount;
52*3d8817e4Smiod   asymbol **syms;
53*3d8817e4Smiod };
54*3d8817e4Smiod 
55*3d8817e4Smiod struct extended_symbol_info
56*3d8817e4Smiod {
57*3d8817e4Smiod   symbol_info *sinfo;
58*3d8817e4Smiod   bfd_vma ssize;
59*3d8817e4Smiod   elf_symbol_type *elfinfo;
60*3d8817e4Smiod   /* FIXME: We should add more fields for Type, Line, Section.  */
61*3d8817e4Smiod };
62*3d8817e4Smiod #define SYM_NAME(sym)        (sym->sinfo->name)
63*3d8817e4Smiod #define SYM_VALUE(sym)       (sym->sinfo->value)
64*3d8817e4Smiod #define SYM_TYPE(sym)        (sym->sinfo->type)
65*3d8817e4Smiod #define SYM_STAB_NAME(sym)   (sym->sinfo->stab_name)
66*3d8817e4Smiod #define SYM_STAB_DESC(sym)   (sym->sinfo->stab_desc)
67*3d8817e4Smiod #define SYM_STAB_OTHER(sym)  (sym->sinfo->stab_other)
68*3d8817e4Smiod #define SYM_SIZE(sym) \
69*3d8817e4Smiod   (sym->elfinfo ? sym->elfinfo->internal_elf_sym.st_size: sym->ssize)
70*3d8817e4Smiod 
71*3d8817e4Smiod /* The output formatting functions.  */
72*3d8817e4Smiod static void print_object_filename_bsd (char *);
73*3d8817e4Smiod static void print_object_filename_sysv (char *);
74*3d8817e4Smiod static void print_object_filename_posix (char *);
75*3d8817e4Smiod static void print_archive_filename_bsd (char *);
76*3d8817e4Smiod static void print_archive_filename_sysv (char *);
77*3d8817e4Smiod static void print_archive_filename_posix (char *);
78*3d8817e4Smiod static void print_archive_member_bsd (char *, const char *);
79*3d8817e4Smiod static void print_archive_member_sysv (char *, const char *);
80*3d8817e4Smiod static void print_archive_member_posix (char *, const char *);
81*3d8817e4Smiod static void print_symbol_filename_bsd (bfd *, bfd *);
82*3d8817e4Smiod static void print_symbol_filename_sysv (bfd *, bfd *);
83*3d8817e4Smiod static void print_symbol_filename_posix (bfd *, bfd *);
84*3d8817e4Smiod static void print_value (bfd *, bfd_vma);
85*3d8817e4Smiod static void print_symbol_info_bsd (struct extended_symbol_info *, bfd *);
86*3d8817e4Smiod static void print_symbol_info_sysv (struct extended_symbol_info *, bfd *);
87*3d8817e4Smiod static void print_symbol_info_posix (struct extended_symbol_info *, bfd *);
88*3d8817e4Smiod 
89*3d8817e4Smiod /* Support for different output formats.  */
90*3d8817e4Smiod struct output_fns
91*3d8817e4Smiod   {
92*3d8817e4Smiod     /* Print the name of an object file given on the command line.  */
93*3d8817e4Smiod     void (*print_object_filename) (char *);
94*3d8817e4Smiod 
95*3d8817e4Smiod     /* Print the name of an archive file given on the command line.  */
96*3d8817e4Smiod     void (*print_archive_filename) (char *);
97*3d8817e4Smiod 
98*3d8817e4Smiod     /* Print the name of an archive member file.  */
99*3d8817e4Smiod     void (*print_archive_member) (char *, const char *);
100*3d8817e4Smiod 
101*3d8817e4Smiod     /* Print the name of the file (and archive, if there is one)
102*3d8817e4Smiod        containing a symbol.  */
103*3d8817e4Smiod     void (*print_symbol_filename) (bfd *, bfd *);
104*3d8817e4Smiod 
105*3d8817e4Smiod     /* Print a line of information about a symbol.  */
106*3d8817e4Smiod     void (*print_symbol_info) (struct extended_symbol_info *, bfd *);
107*3d8817e4Smiod   };
108*3d8817e4Smiod 
109*3d8817e4Smiod static struct output_fns formats[] =
110*3d8817e4Smiod {
111*3d8817e4Smiod   {print_object_filename_bsd,
112*3d8817e4Smiod    print_archive_filename_bsd,
113*3d8817e4Smiod    print_archive_member_bsd,
114*3d8817e4Smiod    print_symbol_filename_bsd,
115*3d8817e4Smiod    print_symbol_info_bsd},
116*3d8817e4Smiod   {print_object_filename_sysv,
117*3d8817e4Smiod    print_archive_filename_sysv,
118*3d8817e4Smiod    print_archive_member_sysv,
119*3d8817e4Smiod    print_symbol_filename_sysv,
120*3d8817e4Smiod    print_symbol_info_sysv},
121*3d8817e4Smiod   {print_object_filename_posix,
122*3d8817e4Smiod    print_archive_filename_posix,
123*3d8817e4Smiod    print_archive_member_posix,
124*3d8817e4Smiod    print_symbol_filename_posix,
125*3d8817e4Smiod    print_symbol_info_posix}
126*3d8817e4Smiod };
127*3d8817e4Smiod 
128*3d8817e4Smiod /* Indices in `formats'.  */
129*3d8817e4Smiod #define FORMAT_BSD 0
130*3d8817e4Smiod #define FORMAT_SYSV 1
131*3d8817e4Smiod #define FORMAT_POSIX 2
132*3d8817e4Smiod #define FORMAT_DEFAULT FORMAT_BSD
133*3d8817e4Smiod 
134*3d8817e4Smiod /* The output format to use.  */
135*3d8817e4Smiod static struct output_fns *format = &formats[FORMAT_DEFAULT];
136*3d8817e4Smiod 
137*3d8817e4Smiod /* Command options.  */
138*3d8817e4Smiod 
139*3d8817e4Smiod static int do_demangle = 0;	/* Pretty print C++ symbol names.  */
140*3d8817e4Smiod static int external_only = 0;	/* Print external symbols only.  */
141*3d8817e4Smiod static int defined_only = 0;	/* Print defined symbols only.  */
142*3d8817e4Smiod static int no_sort = 0;		/* Don't sort; print syms in order found.  */
143*3d8817e4Smiod static int print_debug_syms = 0;/* Print debugger-only symbols too.  */
144*3d8817e4Smiod static int print_armap = 0;	/* Describe __.SYMDEF data in archive files.  */
145*3d8817e4Smiod static int print_size = 0;	/* Print size of defined symbols.  */
146*3d8817e4Smiod static int reverse_sort = 0;	/* Sort in downward(alpha or numeric) order.  */
147*3d8817e4Smiod static int sort_numerically = 0;/* Sort in numeric rather than alpha order.  */
148*3d8817e4Smiod static int sort_by_size = 0;	/* Sort by size of symbol.  */
149*3d8817e4Smiod static int undefined_only = 0;	/* Print undefined symbols only.  */
150*3d8817e4Smiod static int dynamic = 0;		/* Print dynamic symbols.  */
151*3d8817e4Smiod static int show_version = 0;	/* Show the version number.  */
152*3d8817e4Smiod static int show_stats = 0;	/* Show statistics.  */
153*3d8817e4Smiod static int show_synthetic = 0;	/* Display synthesized symbols too.  */
154*3d8817e4Smiod static int line_numbers = 0;	/* Print line numbers for symbols.  */
155*3d8817e4Smiod static int allow_special_symbols = 0;  /* Allow special symbols.  */
156*3d8817e4Smiod 
157*3d8817e4Smiod /* When to print the names of files.  Not mutually exclusive in SYSV format.  */
158*3d8817e4Smiod static int filename_per_file = 0;	/* Once per file, on its own line.  */
159*3d8817e4Smiod static int filename_per_symbol = 0;	/* Once per symbol, at start of line.  */
160*3d8817e4Smiod 
161*3d8817e4Smiod /* Print formats for printing a symbol value.  */
162*3d8817e4Smiod #ifndef BFD64
163*3d8817e4Smiod static char value_format[] = "%08lx";
164*3d8817e4Smiod #else
165*3d8817e4Smiod #if BFD_HOST_64BIT_LONG
166*3d8817e4Smiod static char value_format[] = "%016lx";
167*3d8817e4Smiod #else
168*3d8817e4Smiod /* We don't use value_format for this case.  */
169*3d8817e4Smiod #endif
170*3d8817e4Smiod #endif
171*3d8817e4Smiod #ifdef BFD64
172*3d8817e4Smiod static int print_width = 16;
173*3d8817e4Smiod #else
174*3d8817e4Smiod static int print_width = 8;
175*3d8817e4Smiod #endif
176*3d8817e4Smiod static int print_radix = 16;
177*3d8817e4Smiod /* Print formats for printing stab info.  */
178*3d8817e4Smiod static char other_format[] = "%02x";
179*3d8817e4Smiod static char desc_format[] = "%04x";
180*3d8817e4Smiod 
181*3d8817e4Smiod static char *target = NULL;
182*3d8817e4Smiod 
183*3d8817e4Smiod /* Used to cache the line numbers for a BFD.  */
184*3d8817e4Smiod static bfd *lineno_cache_bfd;
185*3d8817e4Smiod static bfd *lineno_cache_rel_bfd;
186*3d8817e4Smiod 
187*3d8817e4Smiod #define OPTION_TARGET 200
188*3d8817e4Smiod 
189*3d8817e4Smiod static struct option long_options[] =
190*3d8817e4Smiod {
191*3d8817e4Smiod   {"debug-syms", no_argument, &print_debug_syms, 1},
192*3d8817e4Smiod   {"demangle", optional_argument, 0, 'C'},
193*3d8817e4Smiod   {"dynamic", no_argument, &dynamic, 1},
194*3d8817e4Smiod   {"extern-only", no_argument, &external_only, 1},
195*3d8817e4Smiod   {"format", required_argument, 0, 'f'},
196*3d8817e4Smiod   {"help", no_argument, 0, 'h'},
197*3d8817e4Smiod   {"line-numbers", no_argument, 0, 'l'},
198*3d8817e4Smiod   {"no-cplus", no_argument, &do_demangle, 0},  /* Linux compatibility.  */
199*3d8817e4Smiod   {"no-demangle", no_argument, &do_demangle, 0},
200*3d8817e4Smiod   {"no-sort", no_argument, &no_sort, 1},
201*3d8817e4Smiod   {"numeric-sort", no_argument, &sort_numerically, 1},
202*3d8817e4Smiod   {"portability", no_argument, 0, 'P'},
203*3d8817e4Smiod   {"print-armap", no_argument, &print_armap, 1},
204*3d8817e4Smiod   {"print-file-name", no_argument, 0, 'o'},
205*3d8817e4Smiod   {"print-size", no_argument, 0, 'S'},
206*3d8817e4Smiod   {"radix", required_argument, 0, 't'},
207*3d8817e4Smiod   {"reverse-sort", no_argument, &reverse_sort, 1},
208*3d8817e4Smiod   {"size-sort", no_argument, &sort_by_size, 1},
209*3d8817e4Smiod   {"special-syms", no_argument, &allow_special_symbols, 1},
210*3d8817e4Smiod   {"stats", no_argument, &show_stats, 1},
211*3d8817e4Smiod   {"synthetic", no_argument, &show_synthetic, 1},
212*3d8817e4Smiod   {"target", required_argument, 0, OPTION_TARGET},
213*3d8817e4Smiod   {"defined-only", no_argument, &defined_only, 1},
214*3d8817e4Smiod   {"undefined-only", no_argument, &undefined_only, 1},
215*3d8817e4Smiod   {"version", no_argument, &show_version, 1},
216*3d8817e4Smiod   {0, no_argument, 0, 0}
217*3d8817e4Smiod };
218*3d8817e4Smiod 
219*3d8817e4Smiod /* Some error-reporting functions.  */
220*3d8817e4Smiod 
221*3d8817e4Smiod static void
usage(FILE * stream,int status)222*3d8817e4Smiod usage (FILE *stream, int status)
223*3d8817e4Smiod {
224*3d8817e4Smiod   fprintf (stream, _("Usage: %s [option(s)] [file(s)]\n"), program_name);
225*3d8817e4Smiod   fprintf (stream, _(" List symbols in [file(s)] (a.out by default).\n"));
226*3d8817e4Smiod   fprintf (stream, _(" The options are:\n\
227*3d8817e4Smiod   -a, --debug-syms       Display debugger-only symbols\n\
228*3d8817e4Smiod   -A, --print-file-name  Print name of the input file before every symbol\n\
229*3d8817e4Smiod   -B                     Same as --format=bsd\n\
230*3d8817e4Smiod   -C, --demangle[=STYLE] Decode low-level symbol names into user-level names\n\
231*3d8817e4Smiod                           The STYLE, if specified, can be `auto' (the default),\n\
232*3d8817e4Smiod                           `gnu', `lucid', `arm', `hp', `edg', `gnu-v3', `java'\n\
233*3d8817e4Smiod                           or `gnat'\n\
234*3d8817e4Smiod       --no-demangle      Do not demangle low-level symbol names\n\
235*3d8817e4Smiod   -D, --dynamic          Display dynamic symbols instead of normal symbols\n\
236*3d8817e4Smiod       --defined-only     Display only defined symbols\n\
237*3d8817e4Smiod   -e                     (ignored)\n\
238*3d8817e4Smiod   -f, --format=FORMAT    Use the output format FORMAT.  FORMAT can be `bsd',\n\
239*3d8817e4Smiod                            `sysv' or `posix'.  The default is `bsd'\n\
240*3d8817e4Smiod   -g, --extern-only      Display only external symbols\n\
241*3d8817e4Smiod   -l, --line-numbers     Use debugging information to find a filename and\n\
242*3d8817e4Smiod                            line number for each symbol\n\
243*3d8817e4Smiod   -n, --numeric-sort     Sort symbols numerically by address\n\
244*3d8817e4Smiod   -o                     Same as -A\n\
245*3d8817e4Smiod   -p, --no-sort          Do not sort the symbols\n\
246*3d8817e4Smiod   -P, --portability      Same as --format=posix\n\
247*3d8817e4Smiod   -r, --reverse-sort     Reverse the sense of the sort\n\
248*3d8817e4Smiod   -S, --print-size       Print size of defined symbols\n\
249*3d8817e4Smiod   -s, --print-armap      Include index for symbols from archive members\n\
250*3d8817e4Smiod       --size-sort        Sort symbols by size\n\
251*3d8817e4Smiod       --special-syms     Include special symbols in the output\n\
252*3d8817e4Smiod       --synthetic        Display synthetic symbols as well\n\
253*3d8817e4Smiod   -t, --radix=RADIX      Use RADIX for printing symbol values\n\
254*3d8817e4Smiod       --target=BFDNAME   Specify the target object format as BFDNAME\n\
255*3d8817e4Smiod   -u, --undefined-only   Display only undefined symbols\n\
256*3d8817e4Smiod   -X 32_64               (ignored)\n\
257*3d8817e4Smiod   @FILE                  Read options from FILE\n\
258*3d8817e4Smiod   -h, --help             Display this information\n\
259*3d8817e4Smiod   -V, --version          Display this program's version number\n\
260*3d8817e4Smiod \n"));
261*3d8817e4Smiod   list_supported_targets (program_name, stream);
262*3d8817e4Smiod   if (status == 0)
263*3d8817e4Smiod     fprintf (stream, _("Report bugs to %s.\n"), REPORT_BUGS_TO);
264*3d8817e4Smiod   exit (status);
265*3d8817e4Smiod }
266*3d8817e4Smiod 
267*3d8817e4Smiod /* Set the radix for the symbol value and size according to RADIX.  */
268*3d8817e4Smiod 
269*3d8817e4Smiod static void
set_print_radix(char * radix)270*3d8817e4Smiod set_print_radix (char *radix)
271*3d8817e4Smiod {
272*3d8817e4Smiod   switch (*radix)
273*3d8817e4Smiod     {
274*3d8817e4Smiod     case 'x':
275*3d8817e4Smiod       break;
276*3d8817e4Smiod     case 'd':
277*3d8817e4Smiod     case 'o':
278*3d8817e4Smiod       if (*radix == 'd')
279*3d8817e4Smiod 	print_radix = 10;
280*3d8817e4Smiod       else
281*3d8817e4Smiod 	print_radix = 8;
282*3d8817e4Smiod #ifndef BFD64
283*3d8817e4Smiod       value_format[4] = *radix;
284*3d8817e4Smiod #else
285*3d8817e4Smiod #if BFD_HOST_64BIT_LONG
286*3d8817e4Smiod       value_format[5] = *radix;
287*3d8817e4Smiod #else
288*3d8817e4Smiod       /* This case requires special handling for octal and decimal
289*3d8817e4Smiod          printing.  */
290*3d8817e4Smiod #endif
291*3d8817e4Smiod #endif
292*3d8817e4Smiod       other_format[3] = desc_format[3] = *radix;
293*3d8817e4Smiod       break;
294*3d8817e4Smiod     default:
295*3d8817e4Smiod       fatal (_("%s: invalid radix"), radix);
296*3d8817e4Smiod     }
297*3d8817e4Smiod }
298*3d8817e4Smiod 
299*3d8817e4Smiod static void
set_output_format(char * f)300*3d8817e4Smiod set_output_format (char *f)
301*3d8817e4Smiod {
302*3d8817e4Smiod   int i;
303*3d8817e4Smiod 
304*3d8817e4Smiod   switch (*f)
305*3d8817e4Smiod     {
306*3d8817e4Smiod     case 'b':
307*3d8817e4Smiod     case 'B':
308*3d8817e4Smiod       i = FORMAT_BSD;
309*3d8817e4Smiod       break;
310*3d8817e4Smiod     case 'p':
311*3d8817e4Smiod     case 'P':
312*3d8817e4Smiod       i = FORMAT_POSIX;
313*3d8817e4Smiod       break;
314*3d8817e4Smiod     case 's':
315*3d8817e4Smiod     case 'S':
316*3d8817e4Smiod       i = FORMAT_SYSV;
317*3d8817e4Smiod       break;
318*3d8817e4Smiod     default:
319*3d8817e4Smiod       fatal (_("%s: invalid output format"), f);
320*3d8817e4Smiod     }
321*3d8817e4Smiod   format = &formats[i];
322*3d8817e4Smiod }
323*3d8817e4Smiod 
324*3d8817e4Smiod static const char *
get_symbol_type(unsigned int type)325*3d8817e4Smiod get_symbol_type (unsigned int type)
326*3d8817e4Smiod {
327*3d8817e4Smiod   static char buff [32];
328*3d8817e4Smiod 
329*3d8817e4Smiod   switch (type)
330*3d8817e4Smiod     {
331*3d8817e4Smiod     case STT_NOTYPE:   return "NOTYPE";
332*3d8817e4Smiod     case STT_OBJECT:   return "OBJECT";
333*3d8817e4Smiod     case STT_FUNC:     return "FUNC";
334*3d8817e4Smiod     case STT_SECTION:  return "SECTION";
335*3d8817e4Smiod     case STT_FILE:     return "FILE";
336*3d8817e4Smiod     case STT_COMMON:   return "COMMON";
337*3d8817e4Smiod     case STT_TLS:      return "TLS";
338*3d8817e4Smiod     default:
339*3d8817e4Smiod       if (type >= STT_LOPROC && type <= STT_HIPROC)
340*3d8817e4Smiod 	sprintf (buff, _("<processor specific>: %d"), type);
341*3d8817e4Smiod       else if (type >= STT_LOOS && type <= STT_HIOS)
342*3d8817e4Smiod 	sprintf (buff, _("<OS specific>: %d"), type);
343*3d8817e4Smiod       else
344*3d8817e4Smiod 	sprintf (buff, _("<unknown>: %d"), type);
345*3d8817e4Smiod       return buff;
346*3d8817e4Smiod     }
347*3d8817e4Smiod }
348*3d8817e4Smiod 
349*3d8817e4Smiod /* Print symbol name NAME, read from ABFD, with printf format FORMAT,
350*3d8817e4Smiod    demangling it if requested.  */
351*3d8817e4Smiod 
352*3d8817e4Smiod static void
print_symname(const char * format,const char * name,bfd * abfd)353*3d8817e4Smiod print_symname (const char *format, const char *name, bfd *abfd)
354*3d8817e4Smiod {
355*3d8817e4Smiod   if (do_demangle && *name)
356*3d8817e4Smiod     {
357*3d8817e4Smiod       char *res = demangle (abfd, name);
358*3d8817e4Smiod 
359*3d8817e4Smiod       printf (format, res);
360*3d8817e4Smiod       free (res);
361*3d8817e4Smiod       return;
362*3d8817e4Smiod     }
363*3d8817e4Smiod 
364*3d8817e4Smiod   printf (format, name);
365*3d8817e4Smiod }
366*3d8817e4Smiod 
367*3d8817e4Smiod static void
print_symdef_entry(bfd * abfd)368*3d8817e4Smiod print_symdef_entry (bfd *abfd)
369*3d8817e4Smiod {
370*3d8817e4Smiod   symindex idx = BFD_NO_MORE_SYMBOLS;
371*3d8817e4Smiod   carsym *thesym;
372*3d8817e4Smiod   bfd_boolean everprinted = FALSE;
373*3d8817e4Smiod 
374*3d8817e4Smiod   for (idx = bfd_get_next_mapent (abfd, idx, &thesym);
375*3d8817e4Smiod        idx != BFD_NO_MORE_SYMBOLS;
376*3d8817e4Smiod        idx = bfd_get_next_mapent (abfd, idx, &thesym))
377*3d8817e4Smiod     {
378*3d8817e4Smiod       bfd *elt;
379*3d8817e4Smiod       if (!everprinted)
380*3d8817e4Smiod 	{
381*3d8817e4Smiod 	  printf (_("\nArchive index:\n"));
382*3d8817e4Smiod 	  everprinted = TRUE;
383*3d8817e4Smiod 	}
384*3d8817e4Smiod       elt = bfd_get_elt_at_index (abfd, idx);
385*3d8817e4Smiod       if (elt == NULL)
386*3d8817e4Smiod 	bfd_fatal ("bfd_get_elt_at_index");
387*3d8817e4Smiod       if (thesym->name != (char *) NULL)
388*3d8817e4Smiod 	{
389*3d8817e4Smiod 	  print_symname ("%s", thesym->name, abfd);
390*3d8817e4Smiod 	  printf (" in %s\n", bfd_get_filename (elt));
391*3d8817e4Smiod 	}
392*3d8817e4Smiod     }
393*3d8817e4Smiod }
394*3d8817e4Smiod 
395*3d8817e4Smiod /* Choose which symbol entries to print;
396*3d8817e4Smiod    compact them downward to get rid of the rest.
397*3d8817e4Smiod    Return the number of symbols to be printed.  */
398*3d8817e4Smiod 
399*3d8817e4Smiod static long
filter_symbols(bfd * abfd,bfd_boolean dynamic,void * minisyms,long symcount,unsigned int size)400*3d8817e4Smiod filter_symbols (bfd *abfd, bfd_boolean dynamic, void *minisyms,
401*3d8817e4Smiod 		long symcount, unsigned int size)
402*3d8817e4Smiod {
403*3d8817e4Smiod   bfd_byte *from, *fromend, *to;
404*3d8817e4Smiod   asymbol *store;
405*3d8817e4Smiod 
406*3d8817e4Smiod   store = bfd_make_empty_symbol (abfd);
407*3d8817e4Smiod   if (store == NULL)
408*3d8817e4Smiod     bfd_fatal (bfd_get_filename (abfd));
409*3d8817e4Smiod 
410*3d8817e4Smiod   from = (bfd_byte *) minisyms;
411*3d8817e4Smiod   fromend = from + symcount * size;
412*3d8817e4Smiod   to = (bfd_byte *) minisyms;
413*3d8817e4Smiod 
414*3d8817e4Smiod   for (; from < fromend; from += size)
415*3d8817e4Smiod     {
416*3d8817e4Smiod       int keep = 0;
417*3d8817e4Smiod       asymbol *sym;
418*3d8817e4Smiod 
419*3d8817e4Smiod       PROGRESS (1);
420*3d8817e4Smiod 
421*3d8817e4Smiod       sym = bfd_minisymbol_to_symbol (abfd, dynamic, (const void *) from, store);
422*3d8817e4Smiod       if (sym == NULL)
423*3d8817e4Smiod 	bfd_fatal (bfd_get_filename (abfd));
424*3d8817e4Smiod 
425*3d8817e4Smiod       if (undefined_only)
426*3d8817e4Smiod 	keep = bfd_is_und_section (sym->section);
427*3d8817e4Smiod       else if (external_only)
428*3d8817e4Smiod 	keep = ((sym->flags & BSF_GLOBAL) != 0
429*3d8817e4Smiod 		|| (sym->flags & BSF_WEAK) != 0
430*3d8817e4Smiod 		|| bfd_is_und_section (sym->section)
431*3d8817e4Smiod 		|| bfd_is_com_section (sym->section));
432*3d8817e4Smiod       else
433*3d8817e4Smiod 	keep = 1;
434*3d8817e4Smiod 
435*3d8817e4Smiod       if (keep
436*3d8817e4Smiod 	  && ! print_debug_syms
437*3d8817e4Smiod 	  && (sym->flags & BSF_DEBUGGING) != 0)
438*3d8817e4Smiod 	keep = 0;
439*3d8817e4Smiod 
440*3d8817e4Smiod       if (keep
441*3d8817e4Smiod 	  && sort_by_size
442*3d8817e4Smiod 	  && (bfd_is_abs_section (sym->section)
443*3d8817e4Smiod 	      || bfd_is_und_section (sym->section)))
444*3d8817e4Smiod 	keep = 0;
445*3d8817e4Smiod 
446*3d8817e4Smiod       if (keep
447*3d8817e4Smiod 	  && defined_only)
448*3d8817e4Smiod 	{
449*3d8817e4Smiod 	  if (bfd_is_und_section (sym->section))
450*3d8817e4Smiod 	    keep = 0;
451*3d8817e4Smiod 	}
452*3d8817e4Smiod 
453*3d8817e4Smiod       if (keep
454*3d8817e4Smiod 	  && bfd_is_target_special_symbol (abfd, sym)
455*3d8817e4Smiod 	  && ! allow_special_symbols)
456*3d8817e4Smiod 	keep = 0;
457*3d8817e4Smiod 
458*3d8817e4Smiod       if (keep)
459*3d8817e4Smiod 	{
460*3d8817e4Smiod 	  memcpy (to, from, size);
461*3d8817e4Smiod 	  to += size;
462*3d8817e4Smiod 	}
463*3d8817e4Smiod     }
464*3d8817e4Smiod 
465*3d8817e4Smiod   return (to - (bfd_byte *) minisyms) / size;
466*3d8817e4Smiod }
467*3d8817e4Smiod 
468*3d8817e4Smiod /* These globals are used to pass information into the sorting
469*3d8817e4Smiod    routines.  */
470*3d8817e4Smiod static bfd *sort_bfd;
471*3d8817e4Smiod static bfd_boolean sort_dynamic;
472*3d8817e4Smiod static asymbol *sort_x;
473*3d8817e4Smiod static asymbol *sort_y;
474*3d8817e4Smiod 
475*3d8817e4Smiod /* Symbol-sorting predicates */
476*3d8817e4Smiod #define valueof(x) ((x)->section->vma + (x)->value)
477*3d8817e4Smiod 
478*3d8817e4Smiod /* Numeric sorts.  Undefined symbols are always considered "less than"
479*3d8817e4Smiod    defined symbols with zero values.  Common symbols are not treated
480*3d8817e4Smiod    specially -- i.e., their sizes are used as their "values".  */
481*3d8817e4Smiod 
482*3d8817e4Smiod static int
non_numeric_forward(const void * P_x,const void * P_y)483*3d8817e4Smiod non_numeric_forward (const void *P_x, const void *P_y)
484*3d8817e4Smiod {
485*3d8817e4Smiod   asymbol *x, *y;
486*3d8817e4Smiod   const char *xn, *yn;
487*3d8817e4Smiod 
488*3d8817e4Smiod   x = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_x, sort_x);
489*3d8817e4Smiod   y = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_y, sort_y);
490*3d8817e4Smiod   if (x == NULL || y == NULL)
491*3d8817e4Smiod     bfd_fatal (bfd_get_filename (sort_bfd));
492*3d8817e4Smiod 
493*3d8817e4Smiod   xn = bfd_asymbol_name (x);
494*3d8817e4Smiod   yn = bfd_asymbol_name (y);
495*3d8817e4Smiod 
496*3d8817e4Smiod   if (yn == NULL)
497*3d8817e4Smiod     return xn != NULL;
498*3d8817e4Smiod   if (xn == NULL)
499*3d8817e4Smiod     return -1;
500*3d8817e4Smiod 
501*3d8817e4Smiod #ifdef HAVE_STRCOLL
502*3d8817e4Smiod   /* Solaris 2.5 has a bug in strcoll.
503*3d8817e4Smiod      strcoll returns invalid values when confronted with empty strings.  */
504*3d8817e4Smiod   if (*yn == '\0')
505*3d8817e4Smiod     return *xn != '\0';
506*3d8817e4Smiod   if (*xn == '\0')
507*3d8817e4Smiod     return -1;
508*3d8817e4Smiod 
509*3d8817e4Smiod   return strcoll (xn, yn);
510*3d8817e4Smiod #else
511*3d8817e4Smiod   return strcmp (xn, yn);
512*3d8817e4Smiod #endif
513*3d8817e4Smiod }
514*3d8817e4Smiod 
515*3d8817e4Smiod static int
non_numeric_reverse(const void * x,const void * y)516*3d8817e4Smiod non_numeric_reverse (const void *x, const void *y)
517*3d8817e4Smiod {
518*3d8817e4Smiod   return - non_numeric_forward (x, y);
519*3d8817e4Smiod }
520*3d8817e4Smiod 
521*3d8817e4Smiod static int
numeric_forward(const void * P_x,const void * P_y)522*3d8817e4Smiod numeric_forward (const void *P_x, const void *P_y)
523*3d8817e4Smiod {
524*3d8817e4Smiod   asymbol *x, *y;
525*3d8817e4Smiod   asection *xs, *ys;
526*3d8817e4Smiod 
527*3d8817e4Smiod   x = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_x, sort_x);
528*3d8817e4Smiod   y =  bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_y, sort_y);
529*3d8817e4Smiod   if (x == NULL || y == NULL)
530*3d8817e4Smiod     bfd_fatal (bfd_get_filename (sort_bfd));
531*3d8817e4Smiod 
532*3d8817e4Smiod   xs = bfd_get_section (x);
533*3d8817e4Smiod   ys = bfd_get_section (y);
534*3d8817e4Smiod 
535*3d8817e4Smiod   if (bfd_is_und_section (xs))
536*3d8817e4Smiod     {
537*3d8817e4Smiod       if (! bfd_is_und_section (ys))
538*3d8817e4Smiod 	return -1;
539*3d8817e4Smiod     }
540*3d8817e4Smiod   else if (bfd_is_und_section (ys))
541*3d8817e4Smiod     return 1;
542*3d8817e4Smiod   else if (valueof (x) != valueof (y))
543*3d8817e4Smiod     return valueof (x) < valueof (y) ? -1 : 1;
544*3d8817e4Smiod 
545*3d8817e4Smiod   return non_numeric_forward (P_x, P_y);
546*3d8817e4Smiod }
547*3d8817e4Smiod 
548*3d8817e4Smiod static int
numeric_reverse(const void * x,const void * y)549*3d8817e4Smiod numeric_reverse (const void *x, const void *y)
550*3d8817e4Smiod {
551*3d8817e4Smiod   return - numeric_forward (x, y);
552*3d8817e4Smiod }
553*3d8817e4Smiod 
554*3d8817e4Smiod static int (*(sorters[2][2])) (const void *, const void *) =
555*3d8817e4Smiod {
556*3d8817e4Smiod   { non_numeric_forward, non_numeric_reverse },
557*3d8817e4Smiod   { numeric_forward, numeric_reverse }
558*3d8817e4Smiod };
559*3d8817e4Smiod 
560*3d8817e4Smiod /* This sort routine is used by sort_symbols_by_size.  It is similar
561*3d8817e4Smiod    to numeric_forward, but when symbols have the same value it sorts
562*3d8817e4Smiod    by section VMA.  This simplifies the sort_symbols_by_size code
563*3d8817e4Smiod    which handles symbols at the end of sections.  Also, this routine
564*3d8817e4Smiod    tries to sort file names before other symbols with the same value.
565*3d8817e4Smiod    That will make the file name have a zero size, which will make
566*3d8817e4Smiod    sort_symbols_by_size choose the non file name symbol, leading to
567*3d8817e4Smiod    more meaningful output.  For similar reasons, this code sorts
568*3d8817e4Smiod    gnu_compiled_* and gcc2_compiled before other symbols with the same
569*3d8817e4Smiod    value.  */
570*3d8817e4Smiod 
571*3d8817e4Smiod static int
size_forward1(const void * P_x,const void * P_y)572*3d8817e4Smiod size_forward1 (const void *P_x, const void *P_y)
573*3d8817e4Smiod {
574*3d8817e4Smiod   asymbol *x, *y;
575*3d8817e4Smiod   asection *xs, *ys;
576*3d8817e4Smiod   const char *xn, *yn;
577*3d8817e4Smiod   size_t xnl, ynl;
578*3d8817e4Smiod   int xf, yf;
579*3d8817e4Smiod 
580*3d8817e4Smiod   x = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_x, sort_x);
581*3d8817e4Smiod   y = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_y, sort_y);
582*3d8817e4Smiod   if (x == NULL || y == NULL)
583*3d8817e4Smiod     bfd_fatal (bfd_get_filename (sort_bfd));
584*3d8817e4Smiod 
585*3d8817e4Smiod   xs = bfd_get_section (x);
586*3d8817e4Smiod   ys = bfd_get_section (y);
587*3d8817e4Smiod 
588*3d8817e4Smiod   if (bfd_is_und_section (xs))
589*3d8817e4Smiod     abort ();
590*3d8817e4Smiod   if (bfd_is_und_section (ys))
591*3d8817e4Smiod     abort ();
592*3d8817e4Smiod 
593*3d8817e4Smiod   if (valueof (x) != valueof (y))
594*3d8817e4Smiod     return valueof (x) < valueof (y) ? -1 : 1;
595*3d8817e4Smiod 
596*3d8817e4Smiod   if (xs->vma != ys->vma)
597*3d8817e4Smiod     return xs->vma < ys->vma ? -1 : 1;
598*3d8817e4Smiod 
599*3d8817e4Smiod   xn = bfd_asymbol_name (x);
600*3d8817e4Smiod   yn = bfd_asymbol_name (y);
601*3d8817e4Smiod   xnl = strlen (xn);
602*3d8817e4Smiod   ynl = strlen (yn);
603*3d8817e4Smiod 
604*3d8817e4Smiod   /* The symbols gnu_compiled and gcc2_compiled convey even less
605*3d8817e4Smiod      information than the file name, so sort them out first.  */
606*3d8817e4Smiod 
607*3d8817e4Smiod   xf = (strstr (xn, "gnu_compiled") != NULL
608*3d8817e4Smiod 	|| strstr (xn, "gcc2_compiled") != NULL);
609*3d8817e4Smiod   yf = (strstr (yn, "gnu_compiled") != NULL
610*3d8817e4Smiod 	|| strstr (yn, "gcc2_compiled") != NULL);
611*3d8817e4Smiod 
612*3d8817e4Smiod   if (xf && ! yf)
613*3d8817e4Smiod     return -1;
614*3d8817e4Smiod   if (! xf && yf)
615*3d8817e4Smiod     return 1;
616*3d8817e4Smiod 
617*3d8817e4Smiod   /* We use a heuristic for the file name.  It may not work on non
618*3d8817e4Smiod      Unix systems, but it doesn't really matter; the only difference
619*3d8817e4Smiod      is precisely which symbol names get printed.  */
620*3d8817e4Smiod 
621*3d8817e4Smiod #define file_symbol(s, sn, snl)			\
622*3d8817e4Smiod   (((s)->flags & BSF_FILE) != 0			\
623*3d8817e4Smiod    || ((sn)[(snl) - 2] == '.'			\
624*3d8817e4Smiod        && ((sn)[(snl) - 1] == 'o'		\
625*3d8817e4Smiod 	   || (sn)[(snl) - 1] == 'a')))
626*3d8817e4Smiod 
627*3d8817e4Smiod   xf = file_symbol (x, xn, xnl);
628*3d8817e4Smiod   yf = file_symbol (y, yn, ynl);
629*3d8817e4Smiod 
630*3d8817e4Smiod   if (xf && ! yf)
631*3d8817e4Smiod     return -1;
632*3d8817e4Smiod   if (! xf && yf)
633*3d8817e4Smiod     return 1;
634*3d8817e4Smiod 
635*3d8817e4Smiod   return non_numeric_forward (P_x, P_y);
636*3d8817e4Smiod }
637*3d8817e4Smiod 
638*3d8817e4Smiod /* This sort routine is used by sort_symbols_by_size.  It is sorting
639*3d8817e4Smiod    an array of size_sym structures into size order.  */
640*3d8817e4Smiod 
641*3d8817e4Smiod static int
size_forward2(const void * P_x,const void * P_y)642*3d8817e4Smiod size_forward2 (const void *P_x, const void *P_y)
643*3d8817e4Smiod {
644*3d8817e4Smiod   const struct size_sym *x = (const struct size_sym *) P_x;
645*3d8817e4Smiod   const struct size_sym *y = (const struct size_sym *) P_y;
646*3d8817e4Smiod 
647*3d8817e4Smiod   if (x->size < y->size)
648*3d8817e4Smiod     return reverse_sort ? 1 : -1;
649*3d8817e4Smiod   else if (x->size > y->size)
650*3d8817e4Smiod     return reverse_sort ? -1 : 1;
651*3d8817e4Smiod   else
652*3d8817e4Smiod     return sorters[0][reverse_sort] (x->minisym, y->minisym);
653*3d8817e4Smiod }
654*3d8817e4Smiod 
655*3d8817e4Smiod /* Sort the symbols by size.  ELF provides a size but for other formats
656*3d8817e4Smiod    we have to make a guess by assuming that the difference between the
657*3d8817e4Smiod    address of a symbol and the address of the next higher symbol is the
658*3d8817e4Smiod    size.  */
659*3d8817e4Smiod 
660*3d8817e4Smiod static long
sort_symbols_by_size(bfd * abfd,bfd_boolean dynamic,void * minisyms,long symcount,unsigned int size,struct size_sym ** symsizesp)661*3d8817e4Smiod sort_symbols_by_size (bfd *abfd, bfd_boolean dynamic, void *minisyms,
662*3d8817e4Smiod 		      long symcount, unsigned int size,
663*3d8817e4Smiod 		      struct size_sym **symsizesp)
664*3d8817e4Smiod {
665*3d8817e4Smiod   struct size_sym *symsizes;
666*3d8817e4Smiod   bfd_byte *from, *fromend;
667*3d8817e4Smiod   asymbol *sym = NULL;
668*3d8817e4Smiod   asymbol *store_sym, *store_next;
669*3d8817e4Smiod 
670*3d8817e4Smiod   qsort (minisyms, symcount, size, size_forward1);
671*3d8817e4Smiod 
672*3d8817e4Smiod   /* We are going to return a special set of symbols and sizes to
673*3d8817e4Smiod      print.  */
674*3d8817e4Smiod   symsizes = xmalloc (symcount * sizeof (struct size_sym));
675*3d8817e4Smiod   *symsizesp = symsizes;
676*3d8817e4Smiod 
677*3d8817e4Smiod   /* Note that filter_symbols has already removed all absolute and
678*3d8817e4Smiod      undefined symbols.  Here we remove all symbols whose size winds
679*3d8817e4Smiod      up as zero.  */
680*3d8817e4Smiod   from = (bfd_byte *) minisyms;
681*3d8817e4Smiod   fromend = from + symcount * size;
682*3d8817e4Smiod 
683*3d8817e4Smiod   store_sym = sort_x;
684*3d8817e4Smiod   store_next = sort_y;
685*3d8817e4Smiod 
686*3d8817e4Smiod   if (from < fromend)
687*3d8817e4Smiod     {
688*3d8817e4Smiod       sym = bfd_minisymbol_to_symbol (abfd, dynamic, (const void *) from,
689*3d8817e4Smiod 				      store_sym);
690*3d8817e4Smiod       if (sym == NULL)
691*3d8817e4Smiod 	bfd_fatal (bfd_get_filename (abfd));
692*3d8817e4Smiod     }
693*3d8817e4Smiod 
694*3d8817e4Smiod   for (; from < fromend; from += size)
695*3d8817e4Smiod     {
696*3d8817e4Smiod       asymbol *next;
697*3d8817e4Smiod       asection *sec;
698*3d8817e4Smiod       bfd_vma sz;
699*3d8817e4Smiod       asymbol *temp;
700*3d8817e4Smiod 
701*3d8817e4Smiod       if (from + size < fromend)
702*3d8817e4Smiod 	{
703*3d8817e4Smiod 	  next = bfd_minisymbol_to_symbol (abfd,
704*3d8817e4Smiod 					   dynamic,
705*3d8817e4Smiod 					   (const void *) (from + size),
706*3d8817e4Smiod 					   store_next);
707*3d8817e4Smiod 	  if (next == NULL)
708*3d8817e4Smiod 	    bfd_fatal (bfd_get_filename (abfd));
709*3d8817e4Smiod 	}
710*3d8817e4Smiod       else
711*3d8817e4Smiod 	next = NULL;
712*3d8817e4Smiod 
713*3d8817e4Smiod       sec = bfd_get_section (sym);
714*3d8817e4Smiod 
715*3d8817e4Smiod       if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
716*3d8817e4Smiod 	sz = ((elf_symbol_type *) sym)->internal_elf_sym.st_size;
717*3d8817e4Smiod       else if (bfd_is_com_section (sec))
718*3d8817e4Smiod 	sz = sym->value;
719*3d8817e4Smiod       else
720*3d8817e4Smiod 	{
721*3d8817e4Smiod 	  if (from + size < fromend
722*3d8817e4Smiod 	      && sec == bfd_get_section (next))
723*3d8817e4Smiod 	    sz = valueof (next) - valueof (sym);
724*3d8817e4Smiod 	  else
725*3d8817e4Smiod 	    sz = (bfd_get_section_vma (abfd, sec)
726*3d8817e4Smiod 		  + bfd_section_size (abfd, sec)
727*3d8817e4Smiod 		  - valueof (sym));
728*3d8817e4Smiod 	}
729*3d8817e4Smiod 
730*3d8817e4Smiod       if (sz != 0)
731*3d8817e4Smiod 	{
732*3d8817e4Smiod 	  symsizes->minisym = (const void *) from;
733*3d8817e4Smiod 	  symsizes->size = sz;
734*3d8817e4Smiod 	  ++symsizes;
735*3d8817e4Smiod 	}
736*3d8817e4Smiod 
737*3d8817e4Smiod       sym = next;
738*3d8817e4Smiod 
739*3d8817e4Smiod       temp = store_sym;
740*3d8817e4Smiod       store_sym = store_next;
741*3d8817e4Smiod       store_next = temp;
742*3d8817e4Smiod     }
743*3d8817e4Smiod 
744*3d8817e4Smiod   symcount = symsizes - *symsizesp;
745*3d8817e4Smiod 
746*3d8817e4Smiod   /* We must now sort again by size.  */
747*3d8817e4Smiod   qsort ((void *) *symsizesp, symcount, sizeof (struct size_sym), size_forward2);
748*3d8817e4Smiod 
749*3d8817e4Smiod   return symcount;
750*3d8817e4Smiod }
751*3d8817e4Smiod 
752*3d8817e4Smiod /* This function is used to get the relocs for a particular section.
753*3d8817e4Smiod    It is called via bfd_map_over_sections.  */
754*3d8817e4Smiod 
755*3d8817e4Smiod static void
get_relocs(bfd * abfd,asection * sec,void * dataarg)756*3d8817e4Smiod get_relocs (bfd *abfd, asection *sec, void *dataarg)
757*3d8817e4Smiod {
758*3d8817e4Smiod   struct get_relocs_info *data = (struct get_relocs_info *) dataarg;
759*3d8817e4Smiod 
760*3d8817e4Smiod   *data->secs = sec;
761*3d8817e4Smiod 
762*3d8817e4Smiod   if ((sec->flags & SEC_RELOC) == 0)
763*3d8817e4Smiod     {
764*3d8817e4Smiod       *data->relocs = NULL;
765*3d8817e4Smiod       *data->relcount = 0;
766*3d8817e4Smiod     }
767*3d8817e4Smiod   else
768*3d8817e4Smiod     {
769*3d8817e4Smiod       long relsize;
770*3d8817e4Smiod 
771*3d8817e4Smiod       relsize = bfd_get_reloc_upper_bound (abfd, sec);
772*3d8817e4Smiod       if (relsize < 0)
773*3d8817e4Smiod 	bfd_fatal (bfd_get_filename (abfd));
774*3d8817e4Smiod 
775*3d8817e4Smiod       *data->relocs = xmalloc (relsize);
776*3d8817e4Smiod       *data->relcount = bfd_canonicalize_reloc (abfd, sec, *data->relocs,
777*3d8817e4Smiod 						data->syms);
778*3d8817e4Smiod       if (*data->relcount < 0)
779*3d8817e4Smiod 	bfd_fatal (bfd_get_filename (abfd));
780*3d8817e4Smiod     }
781*3d8817e4Smiod 
782*3d8817e4Smiod   ++data->secs;
783*3d8817e4Smiod   ++data->relocs;
784*3d8817e4Smiod   ++data->relcount;
785*3d8817e4Smiod }
786*3d8817e4Smiod 
787*3d8817e4Smiod /* Print a single symbol.  */
788*3d8817e4Smiod 
789*3d8817e4Smiod static void
print_symbol(bfd * abfd,asymbol * sym,bfd_vma ssize,bfd * archive_bfd)790*3d8817e4Smiod print_symbol (bfd *abfd, asymbol *sym, bfd_vma ssize, bfd *archive_bfd)
791*3d8817e4Smiod {
792*3d8817e4Smiod   symbol_info syminfo;
793*3d8817e4Smiod   struct extended_symbol_info info;
794*3d8817e4Smiod 
795*3d8817e4Smiod   PROGRESS (1);
796*3d8817e4Smiod 
797*3d8817e4Smiod   format->print_symbol_filename (archive_bfd, abfd);
798*3d8817e4Smiod 
799*3d8817e4Smiod   bfd_get_symbol_info (abfd, sym, &syminfo);
800*3d8817e4Smiod   info.sinfo = &syminfo;
801*3d8817e4Smiod   info.ssize = ssize;
802*3d8817e4Smiod   if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
803*3d8817e4Smiod     info.elfinfo = (elf_symbol_type *) sym;
804*3d8817e4Smiod   else
805*3d8817e4Smiod     info.elfinfo = NULL;
806*3d8817e4Smiod   format->print_symbol_info (&info, abfd);
807*3d8817e4Smiod 
808*3d8817e4Smiod   if (line_numbers)
809*3d8817e4Smiod     {
810*3d8817e4Smiod       static asymbol **syms;
811*3d8817e4Smiod       static long symcount;
812*3d8817e4Smiod       const char *filename, *functionname;
813*3d8817e4Smiod       unsigned int lineno;
814*3d8817e4Smiod 
815*3d8817e4Smiod       /* We need to get the canonical symbols in order to call
816*3d8817e4Smiod          bfd_find_nearest_line.  This is inefficient, but, then, you
817*3d8817e4Smiod          don't have to use --line-numbers.  */
818*3d8817e4Smiod       if (abfd != lineno_cache_bfd && syms != NULL)
819*3d8817e4Smiod 	{
820*3d8817e4Smiod 	  free (syms);
821*3d8817e4Smiod 	  syms = NULL;
822*3d8817e4Smiod 	}
823*3d8817e4Smiod       if (syms == NULL)
824*3d8817e4Smiod 	{
825*3d8817e4Smiod 	  long symsize;
826*3d8817e4Smiod 
827*3d8817e4Smiod 	  symsize = bfd_get_symtab_upper_bound (abfd);
828*3d8817e4Smiod 	  if (symsize < 0)
829*3d8817e4Smiod 	    bfd_fatal (bfd_get_filename (abfd));
830*3d8817e4Smiod 	  syms = xmalloc (symsize);
831*3d8817e4Smiod 	  symcount = bfd_canonicalize_symtab (abfd, syms);
832*3d8817e4Smiod 	  if (symcount < 0)
833*3d8817e4Smiod 	    bfd_fatal (bfd_get_filename (abfd));
834*3d8817e4Smiod 	  lineno_cache_bfd = abfd;
835*3d8817e4Smiod 	}
836*3d8817e4Smiod 
837*3d8817e4Smiod       if (bfd_is_und_section (bfd_get_section (sym)))
838*3d8817e4Smiod 	{
839*3d8817e4Smiod 	  static asection **secs;
840*3d8817e4Smiod 	  static arelent ***relocs;
841*3d8817e4Smiod 	  static long *relcount;
842*3d8817e4Smiod 	  static unsigned int seccount;
843*3d8817e4Smiod 	  unsigned int i;
844*3d8817e4Smiod 	  const char *symname;
845*3d8817e4Smiod 
846*3d8817e4Smiod 	  /* For an undefined symbol, we try to find a reloc for the
847*3d8817e4Smiod              symbol, and print the line number of the reloc.  */
848*3d8817e4Smiod 	  if (abfd != lineno_cache_rel_bfd && relocs != NULL)
849*3d8817e4Smiod 	    {
850*3d8817e4Smiod 	      for (i = 0; i < seccount; i++)
851*3d8817e4Smiod 		if (relocs[i] != NULL)
852*3d8817e4Smiod 		  free (relocs[i]);
853*3d8817e4Smiod 	      free (secs);
854*3d8817e4Smiod 	      free (relocs);
855*3d8817e4Smiod 	      free (relcount);
856*3d8817e4Smiod 	      secs = NULL;
857*3d8817e4Smiod 	      relocs = NULL;
858*3d8817e4Smiod 	      relcount = NULL;
859*3d8817e4Smiod 	    }
860*3d8817e4Smiod 
861*3d8817e4Smiod 	  if (relocs == NULL)
862*3d8817e4Smiod 	    {
863*3d8817e4Smiod 	      struct get_relocs_info info;
864*3d8817e4Smiod 
865*3d8817e4Smiod 	      seccount = bfd_count_sections (abfd);
866*3d8817e4Smiod 
867*3d8817e4Smiod 	      secs = xmalloc (seccount * sizeof *secs);
868*3d8817e4Smiod 	      relocs = xmalloc (seccount * sizeof *relocs);
869*3d8817e4Smiod 	      relcount = xmalloc (seccount * sizeof *relcount);
870*3d8817e4Smiod 
871*3d8817e4Smiod 	      info.secs = secs;
872*3d8817e4Smiod 	      info.relocs = relocs;
873*3d8817e4Smiod 	      info.relcount = relcount;
874*3d8817e4Smiod 	      info.syms = syms;
875*3d8817e4Smiod 	      bfd_map_over_sections (abfd, get_relocs, (void *) &info);
876*3d8817e4Smiod 	      lineno_cache_rel_bfd = abfd;
877*3d8817e4Smiod 	    }
878*3d8817e4Smiod 
879*3d8817e4Smiod 	  symname = bfd_asymbol_name (sym);
880*3d8817e4Smiod 	  for (i = 0; i < seccount; i++)
881*3d8817e4Smiod 	    {
882*3d8817e4Smiod 	      long j;
883*3d8817e4Smiod 
884*3d8817e4Smiod 	      for (j = 0; j < relcount[i]; j++)
885*3d8817e4Smiod 		{
886*3d8817e4Smiod 		  arelent *r;
887*3d8817e4Smiod 
888*3d8817e4Smiod 		  r = relocs[i][j];
889*3d8817e4Smiod 		  if (r->sym_ptr_ptr != NULL
890*3d8817e4Smiod 		      && (*r->sym_ptr_ptr)->section == sym->section
891*3d8817e4Smiod 		      && (*r->sym_ptr_ptr)->value == sym->value
892*3d8817e4Smiod 		      && strcmp (symname,
893*3d8817e4Smiod 				 bfd_asymbol_name (*r->sym_ptr_ptr)) == 0
894*3d8817e4Smiod 		      && bfd_find_nearest_line (abfd, secs[i], syms,
895*3d8817e4Smiod 						r->address, &filename,
896*3d8817e4Smiod 						&functionname, &lineno)
897*3d8817e4Smiod 		      && filename != NULL)
898*3d8817e4Smiod 		    {
899*3d8817e4Smiod 		      /* We only print the first one we find.  */
900*3d8817e4Smiod 		      printf ("\t%s:%u", filename, lineno);
901*3d8817e4Smiod 		      i = seccount;
902*3d8817e4Smiod 		      break;
903*3d8817e4Smiod 		    }
904*3d8817e4Smiod 		}
905*3d8817e4Smiod 	    }
906*3d8817e4Smiod 	}
907*3d8817e4Smiod       else if (bfd_get_section (sym)->owner == abfd)
908*3d8817e4Smiod 	{
909*3d8817e4Smiod 	  if ((bfd_find_line (abfd, syms, sym, &filename, &lineno)
910*3d8817e4Smiod 	       || bfd_find_nearest_line (abfd, bfd_get_section (sym),
911*3d8817e4Smiod 					 syms, sym->value, &filename,
912*3d8817e4Smiod 					 &functionname, &lineno))
913*3d8817e4Smiod 	      && filename != NULL
914*3d8817e4Smiod 	      && lineno != 0)
915*3d8817e4Smiod 	    printf ("\t%s:%u", filename, lineno);
916*3d8817e4Smiod 	}
917*3d8817e4Smiod     }
918*3d8817e4Smiod 
919*3d8817e4Smiod   putchar ('\n');
920*3d8817e4Smiod }
921*3d8817e4Smiod 
922*3d8817e4Smiod /* Print the symbols when sorting by size.  */
923*3d8817e4Smiod 
924*3d8817e4Smiod static void
print_size_symbols(bfd * abfd,bfd_boolean dynamic,struct size_sym * symsizes,long symcount,bfd * archive_bfd)925*3d8817e4Smiod print_size_symbols (bfd *abfd, bfd_boolean dynamic,
926*3d8817e4Smiod 		    struct size_sym *symsizes, long symcount,
927*3d8817e4Smiod 		    bfd *archive_bfd)
928*3d8817e4Smiod {
929*3d8817e4Smiod   asymbol *store;
930*3d8817e4Smiod   struct size_sym *from, *fromend;
931*3d8817e4Smiod 
932*3d8817e4Smiod   store = bfd_make_empty_symbol (abfd);
933*3d8817e4Smiod   if (store == NULL)
934*3d8817e4Smiod     bfd_fatal (bfd_get_filename (abfd));
935*3d8817e4Smiod 
936*3d8817e4Smiod   from = symsizes;
937*3d8817e4Smiod   fromend = from + symcount;
938*3d8817e4Smiod   for (; from < fromend; from++)
939*3d8817e4Smiod     {
940*3d8817e4Smiod       asymbol *sym;
941*3d8817e4Smiod       bfd_vma ssize;
942*3d8817e4Smiod 
943*3d8817e4Smiod       sym = bfd_minisymbol_to_symbol (abfd, dynamic, from->minisym, store);
944*3d8817e4Smiod       if (sym == NULL)
945*3d8817e4Smiod 	bfd_fatal (bfd_get_filename (abfd));
946*3d8817e4Smiod 
947*3d8817e4Smiod       /* For elf we have already computed the correct symbol size.  */
948*3d8817e4Smiod       if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
949*3d8817e4Smiod 	ssize = from->size;
950*3d8817e4Smiod       else
951*3d8817e4Smiod 	ssize = from->size - bfd_section_vma (abfd, bfd_get_section (sym));
952*3d8817e4Smiod 
953*3d8817e4Smiod       print_symbol (abfd, sym, ssize, archive_bfd);
954*3d8817e4Smiod     }
955*3d8817e4Smiod }
956*3d8817e4Smiod 
957*3d8817e4Smiod 
958*3d8817e4Smiod /* Print the symbols.  If ARCHIVE_BFD is non-NULL, it is the archive
959*3d8817e4Smiod    containing ABFD.  */
960*3d8817e4Smiod 
961*3d8817e4Smiod static void
print_symbols(bfd * abfd,bfd_boolean dynamic,void * minisyms,long symcount,unsigned int size,bfd * archive_bfd)962*3d8817e4Smiod print_symbols (bfd *abfd, bfd_boolean dynamic, void *minisyms, long symcount,
963*3d8817e4Smiod 	       unsigned int size, bfd *archive_bfd)
964*3d8817e4Smiod {
965*3d8817e4Smiod   asymbol *store;
966*3d8817e4Smiod   bfd_byte *from, *fromend;
967*3d8817e4Smiod 
968*3d8817e4Smiod   store = bfd_make_empty_symbol (abfd);
969*3d8817e4Smiod   if (store == NULL)
970*3d8817e4Smiod     bfd_fatal (bfd_get_filename (abfd));
971*3d8817e4Smiod 
972*3d8817e4Smiod   from = (bfd_byte *) minisyms;
973*3d8817e4Smiod   fromend = from + symcount * size;
974*3d8817e4Smiod   for (; from < fromend; from += size)
975*3d8817e4Smiod     {
976*3d8817e4Smiod       asymbol *sym;
977*3d8817e4Smiod 
978*3d8817e4Smiod       sym = bfd_minisymbol_to_symbol (abfd, dynamic, from, store);
979*3d8817e4Smiod       if (sym == NULL)
980*3d8817e4Smiod 	bfd_fatal (bfd_get_filename (abfd));
981*3d8817e4Smiod 
982*3d8817e4Smiod       print_symbol (abfd, sym, (bfd_vma) 0, archive_bfd);
983*3d8817e4Smiod     }
984*3d8817e4Smiod }
985*3d8817e4Smiod 
986*3d8817e4Smiod /* If ARCHIVE_BFD is non-NULL, it is the archive containing ABFD.  */
987*3d8817e4Smiod 
988*3d8817e4Smiod static void
display_rel_file(bfd * abfd,bfd * archive_bfd)989*3d8817e4Smiod display_rel_file (bfd *abfd, bfd *archive_bfd)
990*3d8817e4Smiod {
991*3d8817e4Smiod   long symcount;
992*3d8817e4Smiod   void *minisyms;
993*3d8817e4Smiod   unsigned int size;
994*3d8817e4Smiod   struct size_sym *symsizes;
995*3d8817e4Smiod 
996*3d8817e4Smiod   if (! dynamic)
997*3d8817e4Smiod     {
998*3d8817e4Smiod       if (!(bfd_get_file_flags (abfd) & HAS_SYMS))
999*3d8817e4Smiod 	{
1000*3d8817e4Smiod 	  non_fatal (_("%s: no symbols"), bfd_get_filename (abfd));
1001*3d8817e4Smiod 	  return;
1002*3d8817e4Smiod 	}
1003*3d8817e4Smiod     }
1004*3d8817e4Smiod 
1005*3d8817e4Smiod   symcount = bfd_read_minisymbols (abfd, dynamic, &minisyms, &size);
1006*3d8817e4Smiod   if (symcount < 0)
1007*3d8817e4Smiod     bfd_fatal (bfd_get_filename (abfd));
1008*3d8817e4Smiod 
1009*3d8817e4Smiod   if (symcount == 0)
1010*3d8817e4Smiod     {
1011*3d8817e4Smiod       non_fatal (_("%s: no symbols"), bfd_get_filename (abfd));
1012*3d8817e4Smiod       return;
1013*3d8817e4Smiod     }
1014*3d8817e4Smiod 
1015*3d8817e4Smiod   if (show_synthetic && size == sizeof (asymbol *))
1016*3d8817e4Smiod     {
1017*3d8817e4Smiod       asymbol *synthsyms;
1018*3d8817e4Smiod       long synth_count;
1019*3d8817e4Smiod       asymbol **static_syms = NULL;
1020*3d8817e4Smiod       asymbol **dyn_syms = NULL;
1021*3d8817e4Smiod       long static_count = 0;
1022*3d8817e4Smiod       long dyn_count = 0;
1023*3d8817e4Smiod 
1024*3d8817e4Smiod       if (dynamic)
1025*3d8817e4Smiod 	{
1026*3d8817e4Smiod 	  dyn_count = symcount;
1027*3d8817e4Smiod 	  dyn_syms = minisyms;
1028*3d8817e4Smiod 	}
1029*3d8817e4Smiod       else
1030*3d8817e4Smiod 	{
1031*3d8817e4Smiod 	  long storage = bfd_get_dynamic_symtab_upper_bound (abfd);
1032*3d8817e4Smiod 
1033*3d8817e4Smiod 	  static_count = symcount;
1034*3d8817e4Smiod 	  static_syms = minisyms;
1035*3d8817e4Smiod 
1036*3d8817e4Smiod 	  if (storage > 0)
1037*3d8817e4Smiod 	    {
1038*3d8817e4Smiod 	      dyn_syms = xmalloc (storage);
1039*3d8817e4Smiod 	      dyn_count = bfd_canonicalize_dynamic_symtab (abfd, dyn_syms);
1040*3d8817e4Smiod 	      if (dyn_count < 0)
1041*3d8817e4Smiod 		bfd_fatal (bfd_get_filename (abfd));
1042*3d8817e4Smiod 	    }
1043*3d8817e4Smiod 	}
1044*3d8817e4Smiod       synth_count = bfd_get_synthetic_symtab (abfd, static_count, static_syms,
1045*3d8817e4Smiod 					      dyn_count, dyn_syms, &synthsyms);
1046*3d8817e4Smiod       if (synth_count > 0)
1047*3d8817e4Smiod 	{
1048*3d8817e4Smiod 	  asymbol **symp;
1049*3d8817e4Smiod 	  void *new_mini;
1050*3d8817e4Smiod 	  long i;
1051*3d8817e4Smiod 
1052*3d8817e4Smiod 	  new_mini = xmalloc ((symcount + synth_count + 1) * sizeof (*symp));
1053*3d8817e4Smiod 	  symp = new_mini;
1054*3d8817e4Smiod 	  memcpy (symp, minisyms, symcount * sizeof (*symp));
1055*3d8817e4Smiod 	  symp += symcount;
1056*3d8817e4Smiod 	  for (i = 0; i < synth_count; i++)
1057*3d8817e4Smiod 	    *symp++ = synthsyms + i;
1058*3d8817e4Smiod 	  *symp = 0;
1059*3d8817e4Smiod 	  minisyms = new_mini;
1060*3d8817e4Smiod 	  symcount += synth_count;
1061*3d8817e4Smiod 	}
1062*3d8817e4Smiod     }
1063*3d8817e4Smiod 
1064*3d8817e4Smiod   /* Discard the symbols we don't want to print.
1065*3d8817e4Smiod      It's OK to do this in place; we'll free the storage anyway
1066*3d8817e4Smiod      (after printing).  */
1067*3d8817e4Smiod 
1068*3d8817e4Smiod   symcount = filter_symbols (abfd, dynamic, minisyms, symcount, size);
1069*3d8817e4Smiod 
1070*3d8817e4Smiod   symsizes = NULL;
1071*3d8817e4Smiod   if (! no_sort)
1072*3d8817e4Smiod     {
1073*3d8817e4Smiod       sort_bfd = abfd;
1074*3d8817e4Smiod       sort_dynamic = dynamic;
1075*3d8817e4Smiod       sort_x = bfd_make_empty_symbol (abfd);
1076*3d8817e4Smiod       sort_y = bfd_make_empty_symbol (abfd);
1077*3d8817e4Smiod       if (sort_x == NULL || sort_y == NULL)
1078*3d8817e4Smiod 	bfd_fatal (bfd_get_filename (abfd));
1079*3d8817e4Smiod 
1080*3d8817e4Smiod       if (! sort_by_size)
1081*3d8817e4Smiod 	qsort (minisyms, symcount, size,
1082*3d8817e4Smiod 	       sorters[sort_numerically][reverse_sort]);
1083*3d8817e4Smiod       else
1084*3d8817e4Smiod 	symcount = sort_symbols_by_size (abfd, dynamic, minisyms, symcount,
1085*3d8817e4Smiod 					 size, &symsizes);
1086*3d8817e4Smiod     }
1087*3d8817e4Smiod 
1088*3d8817e4Smiod   if (! sort_by_size)
1089*3d8817e4Smiod     print_symbols (abfd, dynamic, minisyms, symcount, size, archive_bfd);
1090*3d8817e4Smiod   else
1091*3d8817e4Smiod     print_size_symbols (abfd, dynamic, symsizes, symcount, archive_bfd);
1092*3d8817e4Smiod 
1093*3d8817e4Smiod   free (minisyms);
1094*3d8817e4Smiod }
1095*3d8817e4Smiod 
1096*3d8817e4Smiod static void
display_archive(bfd * file)1097*3d8817e4Smiod display_archive (bfd *file)
1098*3d8817e4Smiod {
1099*3d8817e4Smiod   bfd *arfile = NULL;
1100*3d8817e4Smiod   bfd *last_arfile = NULL;
1101*3d8817e4Smiod   char **matching;
1102*3d8817e4Smiod 
1103*3d8817e4Smiod   format->print_archive_filename (bfd_get_filename (file));
1104*3d8817e4Smiod 
1105*3d8817e4Smiod   if (print_armap)
1106*3d8817e4Smiod     print_symdef_entry (file);
1107*3d8817e4Smiod 
1108*3d8817e4Smiod   for (;;)
1109*3d8817e4Smiod     {
1110*3d8817e4Smiod       PROGRESS (1);
1111*3d8817e4Smiod 
1112*3d8817e4Smiod       arfile = bfd_openr_next_archived_file (file, arfile);
1113*3d8817e4Smiod 
1114*3d8817e4Smiod       if (arfile == NULL)
1115*3d8817e4Smiod 	{
1116*3d8817e4Smiod 	  if (bfd_get_error () != bfd_error_no_more_archived_files)
1117*3d8817e4Smiod 	    bfd_fatal (bfd_get_filename (file));
1118*3d8817e4Smiod 	  break;
1119*3d8817e4Smiod 	}
1120*3d8817e4Smiod 
1121*3d8817e4Smiod       if (bfd_check_format_matches (arfile, bfd_object, &matching))
1122*3d8817e4Smiod 	{
1123*3d8817e4Smiod 	  char buf[30];
1124*3d8817e4Smiod 
1125*3d8817e4Smiod 	  bfd_sprintf_vma (arfile, buf, (bfd_vma) -1);
1126*3d8817e4Smiod 	  print_width = strlen (buf);
1127*3d8817e4Smiod 	  format->print_archive_member (bfd_get_filename (file),
1128*3d8817e4Smiod 					bfd_get_filename (arfile));
1129*3d8817e4Smiod 	  display_rel_file (arfile, file);
1130*3d8817e4Smiod 	}
1131*3d8817e4Smiod       else
1132*3d8817e4Smiod 	{
1133*3d8817e4Smiod 	  bfd_nonfatal (bfd_get_filename (arfile));
1134*3d8817e4Smiod 	  if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
1135*3d8817e4Smiod 	    {
1136*3d8817e4Smiod 	      list_matching_formats (matching);
1137*3d8817e4Smiod 	      free (matching);
1138*3d8817e4Smiod 	    }
1139*3d8817e4Smiod 	}
1140*3d8817e4Smiod 
1141*3d8817e4Smiod       if (last_arfile != NULL)
1142*3d8817e4Smiod 	{
1143*3d8817e4Smiod 	  bfd_close (last_arfile);
1144*3d8817e4Smiod 	  lineno_cache_bfd = NULL;
1145*3d8817e4Smiod 	  lineno_cache_rel_bfd = NULL;
1146*3d8817e4Smiod 	}
1147*3d8817e4Smiod       last_arfile = arfile;
1148*3d8817e4Smiod     }
1149*3d8817e4Smiod 
1150*3d8817e4Smiod   if (last_arfile != NULL)
1151*3d8817e4Smiod     {
1152*3d8817e4Smiod       bfd_close (last_arfile);
1153*3d8817e4Smiod       lineno_cache_bfd = NULL;
1154*3d8817e4Smiod       lineno_cache_rel_bfd = NULL;
1155*3d8817e4Smiod     }
1156*3d8817e4Smiod }
1157*3d8817e4Smiod 
1158*3d8817e4Smiod static bfd_boolean
display_file(char * filename)1159*3d8817e4Smiod display_file (char *filename)
1160*3d8817e4Smiod {
1161*3d8817e4Smiod   bfd_boolean retval = TRUE;
1162*3d8817e4Smiod   bfd *file;
1163*3d8817e4Smiod   char **matching;
1164*3d8817e4Smiod 
1165*3d8817e4Smiod   if (get_file_size (filename) < 1)
1166*3d8817e4Smiod     return FALSE;
1167*3d8817e4Smiod 
1168*3d8817e4Smiod   file = bfd_openr (filename, target);
1169*3d8817e4Smiod   if (file == NULL)
1170*3d8817e4Smiod     {
1171*3d8817e4Smiod       bfd_nonfatal (filename);
1172*3d8817e4Smiod       return FALSE;
1173*3d8817e4Smiod     }
1174*3d8817e4Smiod 
1175*3d8817e4Smiod   if (bfd_check_format (file, bfd_archive))
1176*3d8817e4Smiod     {
1177*3d8817e4Smiod       display_archive (file);
1178*3d8817e4Smiod     }
1179*3d8817e4Smiod   else if (bfd_check_format_matches (file, bfd_object, &matching))
1180*3d8817e4Smiod     {
1181*3d8817e4Smiod       char buf[30];
1182*3d8817e4Smiod 
1183*3d8817e4Smiod       bfd_sprintf_vma (file, buf, (bfd_vma) -1);
1184*3d8817e4Smiod       print_width = strlen (buf);
1185*3d8817e4Smiod       format->print_object_filename (filename);
1186*3d8817e4Smiod       display_rel_file (file, NULL);
1187*3d8817e4Smiod     }
1188*3d8817e4Smiod   else
1189*3d8817e4Smiod     {
1190*3d8817e4Smiod       bfd_nonfatal (filename);
1191*3d8817e4Smiod       if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
1192*3d8817e4Smiod 	{
1193*3d8817e4Smiod 	  list_matching_formats (matching);
1194*3d8817e4Smiod 	  free (matching);
1195*3d8817e4Smiod 	}
1196*3d8817e4Smiod       retval = FALSE;
1197*3d8817e4Smiod     }
1198*3d8817e4Smiod 
1199*3d8817e4Smiod   if (!bfd_close (file))
1200*3d8817e4Smiod     bfd_fatal (filename);
1201*3d8817e4Smiod 
1202*3d8817e4Smiod   lineno_cache_bfd = NULL;
1203*3d8817e4Smiod   lineno_cache_rel_bfd = NULL;
1204*3d8817e4Smiod 
1205*3d8817e4Smiod   return retval;
1206*3d8817e4Smiod }
1207*3d8817e4Smiod 
1208*3d8817e4Smiod /* The following 3 groups of functions are called unconditionally,
1209*3d8817e4Smiod    once at the start of processing each file of the appropriate type.
1210*3d8817e4Smiod    They should check `filename_per_file' and `filename_per_symbol',
1211*3d8817e4Smiod    as appropriate for their output format, to determine whether to
1212*3d8817e4Smiod    print anything.  */
1213*3d8817e4Smiod 
1214*3d8817e4Smiod /* Print the name of an object file given on the command line.  */
1215*3d8817e4Smiod 
1216*3d8817e4Smiod static void
print_object_filename_bsd(char * filename)1217*3d8817e4Smiod print_object_filename_bsd (char *filename)
1218*3d8817e4Smiod {
1219*3d8817e4Smiod   if (filename_per_file && !filename_per_symbol)
1220*3d8817e4Smiod     printf ("\n%s:\n", filename);
1221*3d8817e4Smiod }
1222*3d8817e4Smiod 
1223*3d8817e4Smiod static void
print_object_filename_sysv(char * filename)1224*3d8817e4Smiod print_object_filename_sysv (char *filename)
1225*3d8817e4Smiod {
1226*3d8817e4Smiod   if (undefined_only)
1227*3d8817e4Smiod     printf (_("\n\nUndefined symbols from %s:\n\n"), filename);
1228*3d8817e4Smiod   else
1229*3d8817e4Smiod     printf (_("\n\nSymbols from %s:\n\n"), filename);
1230*3d8817e4Smiod   if (print_width == 8)
1231*3d8817e4Smiod     printf (_("\
1232*3d8817e4Smiod Name                  Value   Class        Type         Size     Line  Section\n\n"));
1233*3d8817e4Smiod   else
1234*3d8817e4Smiod     printf (_("\
1235*3d8817e4Smiod Name                  Value           Class        Type         Size             Line  Section\n\n"));
1236*3d8817e4Smiod }
1237*3d8817e4Smiod 
1238*3d8817e4Smiod static void
print_object_filename_posix(char * filename)1239*3d8817e4Smiod print_object_filename_posix (char *filename)
1240*3d8817e4Smiod {
1241*3d8817e4Smiod   if (filename_per_file && !filename_per_symbol)
1242*3d8817e4Smiod     printf ("%s:\n", filename);
1243*3d8817e4Smiod }
1244*3d8817e4Smiod 
1245*3d8817e4Smiod /* Print the name of an archive file given on the command line.  */
1246*3d8817e4Smiod 
1247*3d8817e4Smiod static void
print_archive_filename_bsd(char * filename)1248*3d8817e4Smiod print_archive_filename_bsd (char *filename)
1249*3d8817e4Smiod {
1250*3d8817e4Smiod   if (filename_per_file)
1251*3d8817e4Smiod     printf ("\n%s:\n", filename);
1252*3d8817e4Smiod }
1253*3d8817e4Smiod 
1254*3d8817e4Smiod static void
print_archive_filename_sysv(char * filename ATTRIBUTE_UNUSED)1255*3d8817e4Smiod print_archive_filename_sysv (char *filename ATTRIBUTE_UNUSED)
1256*3d8817e4Smiod {
1257*3d8817e4Smiod }
1258*3d8817e4Smiod 
1259*3d8817e4Smiod static void
print_archive_filename_posix(char * filename ATTRIBUTE_UNUSED)1260*3d8817e4Smiod print_archive_filename_posix (char *filename ATTRIBUTE_UNUSED)
1261*3d8817e4Smiod {
1262*3d8817e4Smiod }
1263*3d8817e4Smiod 
1264*3d8817e4Smiod /* Print the name of an archive member file.  */
1265*3d8817e4Smiod 
1266*3d8817e4Smiod static void
print_archive_member_bsd(char * archive ATTRIBUTE_UNUSED,const char * filename)1267*3d8817e4Smiod print_archive_member_bsd (char *archive ATTRIBUTE_UNUSED,
1268*3d8817e4Smiod 			  const char *filename)
1269*3d8817e4Smiod {
1270*3d8817e4Smiod   if (!filename_per_symbol)
1271*3d8817e4Smiod     printf ("\n%s:\n", filename);
1272*3d8817e4Smiod }
1273*3d8817e4Smiod 
1274*3d8817e4Smiod static void
print_archive_member_sysv(char * archive,const char * filename)1275*3d8817e4Smiod print_archive_member_sysv (char *archive, const char *filename)
1276*3d8817e4Smiod {
1277*3d8817e4Smiod   if (undefined_only)
1278*3d8817e4Smiod     printf (_("\n\nUndefined symbols from %s[%s]:\n\n"), archive, filename);
1279*3d8817e4Smiod   else
1280*3d8817e4Smiod     printf (_("\n\nSymbols from %s[%s]:\n\n"), archive, filename);
1281*3d8817e4Smiod   if (print_width == 8)
1282*3d8817e4Smiod     printf (_("\
1283*3d8817e4Smiod Name                  Value   Class        Type         Size     Line  Section\n\n"));
1284*3d8817e4Smiod   else
1285*3d8817e4Smiod     printf (_("\
1286*3d8817e4Smiod Name                  Value           Class        Type         Size             Line  Section\n\n"));
1287*3d8817e4Smiod }
1288*3d8817e4Smiod 
1289*3d8817e4Smiod static void
print_archive_member_posix(char * archive,const char * filename)1290*3d8817e4Smiod print_archive_member_posix (char *archive, const char *filename)
1291*3d8817e4Smiod {
1292*3d8817e4Smiod   if (!filename_per_symbol)
1293*3d8817e4Smiod     printf ("%s[%s]:\n", archive, filename);
1294*3d8817e4Smiod }
1295*3d8817e4Smiod 
1296*3d8817e4Smiod /* Print the name of the file (and archive, if there is one)
1297*3d8817e4Smiod    containing a symbol.  */
1298*3d8817e4Smiod 
1299*3d8817e4Smiod static void
print_symbol_filename_bsd(bfd * archive_bfd,bfd * abfd)1300*3d8817e4Smiod print_symbol_filename_bsd (bfd *archive_bfd, bfd *abfd)
1301*3d8817e4Smiod {
1302*3d8817e4Smiod   if (filename_per_symbol)
1303*3d8817e4Smiod     {
1304*3d8817e4Smiod       if (archive_bfd)
1305*3d8817e4Smiod 	printf ("%s:", bfd_get_filename (archive_bfd));
1306*3d8817e4Smiod       printf ("%s:", bfd_get_filename (abfd));
1307*3d8817e4Smiod     }
1308*3d8817e4Smiod }
1309*3d8817e4Smiod 
1310*3d8817e4Smiod static void
print_symbol_filename_sysv(bfd * archive_bfd,bfd * abfd)1311*3d8817e4Smiod print_symbol_filename_sysv (bfd *archive_bfd, bfd *abfd)
1312*3d8817e4Smiod {
1313*3d8817e4Smiod   if (filename_per_symbol)
1314*3d8817e4Smiod     {
1315*3d8817e4Smiod       if (archive_bfd)
1316*3d8817e4Smiod 	printf ("%s:", bfd_get_filename (archive_bfd));
1317*3d8817e4Smiod       printf ("%s:", bfd_get_filename (abfd));
1318*3d8817e4Smiod     }
1319*3d8817e4Smiod }
1320*3d8817e4Smiod 
1321*3d8817e4Smiod static void
print_symbol_filename_posix(bfd * archive_bfd,bfd * abfd)1322*3d8817e4Smiod print_symbol_filename_posix (bfd *archive_bfd, bfd *abfd)
1323*3d8817e4Smiod {
1324*3d8817e4Smiod   if (filename_per_symbol)
1325*3d8817e4Smiod     {
1326*3d8817e4Smiod       if (archive_bfd)
1327*3d8817e4Smiod 	printf ("%s[%s]: ", bfd_get_filename (archive_bfd),
1328*3d8817e4Smiod 		bfd_get_filename (abfd));
1329*3d8817e4Smiod       else
1330*3d8817e4Smiod 	printf ("%s: ", bfd_get_filename (abfd));
1331*3d8817e4Smiod     }
1332*3d8817e4Smiod }
1333*3d8817e4Smiod 
1334*3d8817e4Smiod /* Print a symbol value.  */
1335*3d8817e4Smiod 
1336*3d8817e4Smiod static void
print_value(bfd * abfd ATTRIBUTE_UNUSED,bfd_vma val)1337*3d8817e4Smiod print_value (bfd *abfd ATTRIBUTE_UNUSED, bfd_vma val)
1338*3d8817e4Smiod {
1339*3d8817e4Smiod #if ! defined (BFD64) || BFD_HOST_64BIT_LONG
1340*3d8817e4Smiod   printf (value_format, val);
1341*3d8817e4Smiod #else
1342*3d8817e4Smiod   /* We have a 64 bit value to print, but the host is only 32 bit.  */
1343*3d8817e4Smiod   if (print_radix == 16)
1344*3d8817e4Smiod     bfd_fprintf_vma (abfd, stdout, val);
1345*3d8817e4Smiod   else
1346*3d8817e4Smiod     {
1347*3d8817e4Smiod       char buf[30];
1348*3d8817e4Smiod       char *s;
1349*3d8817e4Smiod 
1350*3d8817e4Smiod       s = buf + sizeof buf;
1351*3d8817e4Smiod       *--s = '\0';
1352*3d8817e4Smiod       while (val > 0)
1353*3d8817e4Smiod 	{
1354*3d8817e4Smiod 	  *--s = (val % print_radix) + '0';
1355*3d8817e4Smiod 	  val /= print_radix;
1356*3d8817e4Smiod 	}
1357*3d8817e4Smiod       while ((buf + sizeof buf - 1) - s < 16)
1358*3d8817e4Smiod 	*--s = '0';
1359*3d8817e4Smiod       printf ("%s", s);
1360*3d8817e4Smiod     }
1361*3d8817e4Smiod #endif
1362*3d8817e4Smiod }
1363*3d8817e4Smiod 
1364*3d8817e4Smiod /* Print a line of information about a symbol.  */
1365*3d8817e4Smiod 
1366*3d8817e4Smiod static void
print_symbol_info_bsd(struct extended_symbol_info * info,bfd * abfd)1367*3d8817e4Smiod print_symbol_info_bsd (struct extended_symbol_info *info, bfd *abfd)
1368*3d8817e4Smiod {
1369*3d8817e4Smiod   if (bfd_is_undefined_symclass (SYM_TYPE (info)))
1370*3d8817e4Smiod     {
1371*3d8817e4Smiod       if (print_width == 16)
1372*3d8817e4Smiod 	printf ("        ");
1373*3d8817e4Smiod       printf ("        ");
1374*3d8817e4Smiod     }
1375*3d8817e4Smiod   else
1376*3d8817e4Smiod     {
1377*3d8817e4Smiod       /* Normally we print the value of the symbol.  If we are printing the
1378*3d8817e4Smiod 	 size or sorting by size then we print its size, except for the
1379*3d8817e4Smiod 	 (weird) special case where both flags are defined, in which case we
1380*3d8817e4Smiod 	 print both values.  This conforms to documented behaviour.  */
1381*3d8817e4Smiod       if (sort_by_size && !print_size)
1382*3d8817e4Smiod 	print_value (abfd, SYM_SIZE (info));
1383*3d8817e4Smiod       else
1384*3d8817e4Smiod 	print_value (abfd, SYM_VALUE (info));
1385*3d8817e4Smiod 
1386*3d8817e4Smiod       if (print_size && SYM_SIZE (info))
1387*3d8817e4Smiod 	{
1388*3d8817e4Smiod 	  printf (" ");
1389*3d8817e4Smiod 	  print_value (abfd, SYM_SIZE (info));
1390*3d8817e4Smiod 	}
1391*3d8817e4Smiod     }
1392*3d8817e4Smiod 
1393*3d8817e4Smiod   printf (" %c", SYM_TYPE (info));
1394*3d8817e4Smiod 
1395*3d8817e4Smiod   if (SYM_TYPE (info) == '-')
1396*3d8817e4Smiod     {
1397*3d8817e4Smiod       /* A stab.  */
1398*3d8817e4Smiod       printf (" ");
1399*3d8817e4Smiod       printf (other_format, SYM_STAB_OTHER (info));
1400*3d8817e4Smiod       printf (" ");
1401*3d8817e4Smiod       printf (desc_format, SYM_STAB_DESC (info));
1402*3d8817e4Smiod       printf (" %5s", SYM_STAB_NAME (info));
1403*3d8817e4Smiod     }
1404*3d8817e4Smiod   print_symname (" %s", SYM_NAME (info), abfd);
1405*3d8817e4Smiod }
1406*3d8817e4Smiod 
1407*3d8817e4Smiod static void
print_symbol_info_sysv(struct extended_symbol_info * info,bfd * abfd)1408*3d8817e4Smiod print_symbol_info_sysv (struct extended_symbol_info *info, bfd *abfd)
1409*3d8817e4Smiod {
1410*3d8817e4Smiod   print_symname ("%-20s|", SYM_NAME (info), abfd);
1411*3d8817e4Smiod 
1412*3d8817e4Smiod   if (bfd_is_undefined_symclass (SYM_TYPE (info)))
1413*3d8817e4Smiod     {
1414*3d8817e4Smiod       if (print_width == 8)
1415*3d8817e4Smiod 	printf ("        ");
1416*3d8817e4Smiod       else
1417*3d8817e4Smiod 	printf ("                ");
1418*3d8817e4Smiod     }
1419*3d8817e4Smiod   else
1420*3d8817e4Smiod     print_value (abfd, SYM_VALUE (info));
1421*3d8817e4Smiod 
1422*3d8817e4Smiod   printf ("|   %c  |", SYM_TYPE (info));
1423*3d8817e4Smiod 
1424*3d8817e4Smiod   if (SYM_TYPE (info) == '-')
1425*3d8817e4Smiod     {
1426*3d8817e4Smiod       /* A stab.  */
1427*3d8817e4Smiod       printf ("%18s|  ", SYM_STAB_NAME (info));		/* (C) Type.  */
1428*3d8817e4Smiod       printf (desc_format, SYM_STAB_DESC (info));	/* Size.  */
1429*3d8817e4Smiod       printf ("|     |");				/* Line, Section.  */
1430*3d8817e4Smiod     }
1431*3d8817e4Smiod   else
1432*3d8817e4Smiod     {
1433*3d8817e4Smiod       /* Type, Size, Line, Section */
1434*3d8817e4Smiod       if (info->elfinfo)
1435*3d8817e4Smiod 	printf ("%18s|",
1436*3d8817e4Smiod 		get_symbol_type (ELF_ST_TYPE (info->elfinfo->internal_elf_sym.st_info)));
1437*3d8817e4Smiod       else
1438*3d8817e4Smiod 	printf ("                  |");
1439*3d8817e4Smiod 
1440*3d8817e4Smiod       if (SYM_SIZE (info))
1441*3d8817e4Smiod 	print_value (abfd, SYM_SIZE (info));
1442*3d8817e4Smiod       else
1443*3d8817e4Smiod 	{
1444*3d8817e4Smiod 	  if (print_width == 8)
1445*3d8817e4Smiod 	    printf ("        ");
1446*3d8817e4Smiod 	  else
1447*3d8817e4Smiod 	    printf ("                ");
1448*3d8817e4Smiod 	}
1449*3d8817e4Smiod 
1450*3d8817e4Smiod       if (info->elfinfo)
1451*3d8817e4Smiod 	printf("|     |%s", info->elfinfo->symbol.section->name);
1452*3d8817e4Smiod       else
1453*3d8817e4Smiod 	printf("|     |");
1454*3d8817e4Smiod     }
1455*3d8817e4Smiod }
1456*3d8817e4Smiod 
1457*3d8817e4Smiod static void
print_symbol_info_posix(struct extended_symbol_info * info,bfd * abfd)1458*3d8817e4Smiod print_symbol_info_posix (struct extended_symbol_info *info, bfd *abfd)
1459*3d8817e4Smiod {
1460*3d8817e4Smiod   print_symname ("%s ", SYM_NAME (info), abfd);
1461*3d8817e4Smiod   printf ("%c ", SYM_TYPE (info));
1462*3d8817e4Smiod 
1463*3d8817e4Smiod   if (bfd_is_undefined_symclass (SYM_TYPE (info)))
1464*3d8817e4Smiod     printf ("        ");
1465*3d8817e4Smiod   else
1466*3d8817e4Smiod     {
1467*3d8817e4Smiod       print_value (abfd, SYM_VALUE (info));
1468*3d8817e4Smiod       printf (" ");
1469*3d8817e4Smiod       if (SYM_SIZE (info))
1470*3d8817e4Smiod 	print_value (abfd, SYM_SIZE (info));
1471*3d8817e4Smiod     }
1472*3d8817e4Smiod }
1473*3d8817e4Smiod 
1474*3d8817e4Smiod int
main(int argc,char ** argv)1475*3d8817e4Smiod main (int argc, char **argv)
1476*3d8817e4Smiod {
1477*3d8817e4Smiod   int c;
1478*3d8817e4Smiod   int retval;
1479*3d8817e4Smiod 
1480*3d8817e4Smiod #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
1481*3d8817e4Smiod   setlocale (LC_MESSAGES, "");
1482*3d8817e4Smiod #endif
1483*3d8817e4Smiod #if defined (HAVE_SETLOCALE)
1484*3d8817e4Smiod   setlocale (LC_CTYPE, "");
1485*3d8817e4Smiod   setlocale (LC_COLLATE, "");
1486*3d8817e4Smiod #endif
1487*3d8817e4Smiod   bindtextdomain (PACKAGE, LOCALEDIR);
1488*3d8817e4Smiod   textdomain (PACKAGE);
1489*3d8817e4Smiod 
1490*3d8817e4Smiod   program_name = *argv;
1491*3d8817e4Smiod   xmalloc_set_program_name (program_name);
1492*3d8817e4Smiod 
1493*3d8817e4Smiod   START_PROGRESS (program_name, 0);
1494*3d8817e4Smiod 
1495*3d8817e4Smiod   expandargv (&argc, &argv);
1496*3d8817e4Smiod 
1497*3d8817e4Smiod   bfd_init ();
1498*3d8817e4Smiod   set_default_bfd_target ();
1499*3d8817e4Smiod 
1500*3d8817e4Smiod   while ((c = getopt_long (argc, argv, "aABCDef:gHhlnopPrSst:uvVvX:",
1501*3d8817e4Smiod 			   long_options, (int *) 0)) != EOF)
1502*3d8817e4Smiod     {
1503*3d8817e4Smiod       switch (c)
1504*3d8817e4Smiod 	{
1505*3d8817e4Smiod 	case 'a':
1506*3d8817e4Smiod 	  print_debug_syms = 1;
1507*3d8817e4Smiod 	  break;
1508*3d8817e4Smiod 	case 'A':
1509*3d8817e4Smiod 	case 'o':
1510*3d8817e4Smiod 	  filename_per_symbol = 1;
1511*3d8817e4Smiod 	  break;
1512*3d8817e4Smiod 	case 'B':		/* For MIPS compatibility.  */
1513*3d8817e4Smiod 	  set_output_format ("bsd");
1514*3d8817e4Smiod 	  break;
1515*3d8817e4Smiod 	case 'C':
1516*3d8817e4Smiod 	  do_demangle = 1;
1517*3d8817e4Smiod 	  if (optarg != NULL)
1518*3d8817e4Smiod 	    {
1519*3d8817e4Smiod 	      enum demangling_styles style;
1520*3d8817e4Smiod 
1521*3d8817e4Smiod 	      style = cplus_demangle_name_to_style (optarg);
1522*3d8817e4Smiod 	      if (style == unknown_demangling)
1523*3d8817e4Smiod 		fatal (_("unknown demangling style `%s'"),
1524*3d8817e4Smiod 		       optarg);
1525*3d8817e4Smiod 
1526*3d8817e4Smiod 	      cplus_demangle_set_style (style);
1527*3d8817e4Smiod 	    }
1528*3d8817e4Smiod 	  break;
1529*3d8817e4Smiod 	case 'D':
1530*3d8817e4Smiod 	  dynamic = 1;
1531*3d8817e4Smiod 	  break;
1532*3d8817e4Smiod 	case 'e':
1533*3d8817e4Smiod 	  /* Ignored for HP/UX compatibility.  */
1534*3d8817e4Smiod 	  break;
1535*3d8817e4Smiod 	case 'f':
1536*3d8817e4Smiod 	  set_output_format (optarg);
1537*3d8817e4Smiod 	  break;
1538*3d8817e4Smiod 	case 'g':
1539*3d8817e4Smiod 	  external_only = 1;
1540*3d8817e4Smiod 	  break;
1541*3d8817e4Smiod 	case 'H':
1542*3d8817e4Smiod 	case 'h':
1543*3d8817e4Smiod 	  usage (stdout, 0);
1544*3d8817e4Smiod 	case 'l':
1545*3d8817e4Smiod 	  line_numbers = 1;
1546*3d8817e4Smiod 	  break;
1547*3d8817e4Smiod 	case 'n':
1548*3d8817e4Smiod 	case 'v':
1549*3d8817e4Smiod 	  sort_numerically = 1;
1550*3d8817e4Smiod 	  break;
1551*3d8817e4Smiod 	case 'p':
1552*3d8817e4Smiod 	  no_sort = 1;
1553*3d8817e4Smiod 	  break;
1554*3d8817e4Smiod 	case 'P':
1555*3d8817e4Smiod 	  set_output_format ("posix");
1556*3d8817e4Smiod 	  break;
1557*3d8817e4Smiod 	case 'r':
1558*3d8817e4Smiod 	  reverse_sort = 1;
1559*3d8817e4Smiod 	  break;
1560*3d8817e4Smiod 	case 's':
1561*3d8817e4Smiod 	  print_armap = 1;
1562*3d8817e4Smiod 	  break;
1563*3d8817e4Smiod 	case 'S':
1564*3d8817e4Smiod 	  print_size = 1;
1565*3d8817e4Smiod 	  break;
1566*3d8817e4Smiod 	case 't':
1567*3d8817e4Smiod 	  set_print_radix (optarg);
1568*3d8817e4Smiod 	  break;
1569*3d8817e4Smiod 	case 'u':
1570*3d8817e4Smiod 	  undefined_only = 1;
1571*3d8817e4Smiod 	  break;
1572*3d8817e4Smiod 	case 'V':
1573*3d8817e4Smiod 	  show_version = 1;
1574*3d8817e4Smiod 	  break;
1575*3d8817e4Smiod 	case 'X':
1576*3d8817e4Smiod 	  /* Ignored for (partial) AIX compatibility.  On AIX, the
1577*3d8817e4Smiod 	     argument has values 32, 64, or 32_64, and specifies that
1578*3d8817e4Smiod 	     only 32-bit, only 64-bit, or both kinds of objects should
1579*3d8817e4Smiod 	     be examined.  The default is 32.  So plain AIX nm on a
1580*3d8817e4Smiod 	     library archive with both kinds of objects will ignore
1581*3d8817e4Smiod 	     the 64-bit ones.  For GNU nm, the default is and always
1582*3d8817e4Smiod 	     has been -X 32_64, and other options are not supported.  */
1583*3d8817e4Smiod 	  if (strcmp (optarg, "32_64") != 0)
1584*3d8817e4Smiod 	    fatal (_("Only -X 32_64 is supported"));
1585*3d8817e4Smiod 	  break;
1586*3d8817e4Smiod 
1587*3d8817e4Smiod 	case OPTION_TARGET:	/* --target */
1588*3d8817e4Smiod 	  target = optarg;
1589*3d8817e4Smiod 	  break;
1590*3d8817e4Smiod 
1591*3d8817e4Smiod 	case 0:		/* A long option that just sets a flag.  */
1592*3d8817e4Smiod 	  break;
1593*3d8817e4Smiod 
1594*3d8817e4Smiod 	default:
1595*3d8817e4Smiod 	  usage (stderr, 1);
1596*3d8817e4Smiod 	}
1597*3d8817e4Smiod     }
1598*3d8817e4Smiod 
1599*3d8817e4Smiod   if (show_version)
1600*3d8817e4Smiod     print_version ("nm");
1601*3d8817e4Smiod 
1602*3d8817e4Smiod   if (sort_by_size && undefined_only)
1603*3d8817e4Smiod     {
1604*3d8817e4Smiod       non_fatal (_("Using the --size-sort and --undefined-only options together"));
1605*3d8817e4Smiod       non_fatal (_("will produce no output, since undefined symbols have no size."));
1606*3d8817e4Smiod       return 0;
1607*3d8817e4Smiod     }
1608*3d8817e4Smiod 
1609*3d8817e4Smiod   /* OK, all options now parsed.  If no filename specified, do a.out.  */
1610*3d8817e4Smiod   if (optind == argc)
1611*3d8817e4Smiod     return !display_file ("a.out");
1612*3d8817e4Smiod 
1613*3d8817e4Smiod   retval = 0;
1614*3d8817e4Smiod 
1615*3d8817e4Smiod   if (argc - optind > 1)
1616*3d8817e4Smiod     filename_per_file = 1;
1617*3d8817e4Smiod 
1618*3d8817e4Smiod   /* We were given several filenames to do.  */
1619*3d8817e4Smiod   while (optind < argc)
1620*3d8817e4Smiod     {
1621*3d8817e4Smiod       PROGRESS (1);
1622*3d8817e4Smiod       if (!display_file (argv[optind++]))
1623*3d8817e4Smiod 	retval++;
1624*3d8817e4Smiod     }
1625*3d8817e4Smiod 
1626*3d8817e4Smiod   END_PROGRESS (program_name);
1627*3d8817e4Smiod 
1628*3d8817e4Smiod #ifdef HAVE_SBRK
1629*3d8817e4Smiod   if (show_stats)
1630*3d8817e4Smiod     {
1631*3d8817e4Smiod       char *lim = (char *) sbrk (0);
1632*3d8817e4Smiod 
1633*3d8817e4Smiod       non_fatal (_("data size %ld"), (long) (lim - (char *) &environ));
1634*3d8817e4Smiod     }
1635*3d8817e4Smiod #endif
1636*3d8817e4Smiod 
1637*3d8817e4Smiod   exit (retval);
1638*3d8817e4Smiod   return retval;
1639*3d8817e4Smiod }
1640