xref: /netbsd-src/external/gpl3/binutils.old/dist/binutils/nm.c (revision e992f068c547fd6e84b3f104dc2340adcc955732)
175fd0b74Schristos /* nm.c -- Describe symbol table of a rel file.
2*e992f068Schristos    Copyright (C) 1991-2022 Free Software Foundation, Inc.
375fd0b74Schristos 
475fd0b74Schristos    This file is part of GNU Binutils.
575fd0b74Schristos 
675fd0b74Schristos    This program is free software; you can redistribute it and/or modify
775fd0b74Schristos    it under the terms of the GNU General Public License as published by
875fd0b74Schristos    the Free Software Foundation; either version 3 of the License, or
975fd0b74Schristos    (at your option) any later version.
1075fd0b74Schristos 
1175fd0b74Schristos    This program is distributed in the hope that it will be useful,
1275fd0b74Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
1375fd0b74Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1475fd0b74Schristos    GNU General Public License for more details.
1575fd0b74Schristos 
1675fd0b74Schristos    You should have received a copy of the GNU General Public License
1775fd0b74Schristos    along with this program; if not, write to the Free Software
1875fd0b74Schristos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
1975fd0b74Schristos    02110-1301, USA.  */
2075fd0b74Schristos 
2175fd0b74Schristos #include "sysdep.h"
2275fd0b74Schristos #include "bfd.h"
2375fd0b74Schristos #include "progress.h"
2475fd0b74Schristos #include "getopt.h"
2575fd0b74Schristos #include "aout/stab_gnu.h"
2675fd0b74Schristos #include "aout/ranlib.h"
2775fd0b74Schristos #include "demangle.h"
2875fd0b74Schristos #include "libiberty.h"
2975fd0b74Schristos #include "elf-bfd.h"
3075fd0b74Schristos #include "elf/common.h"
3175fd0b74Schristos #define DO_NOT_DEFINE_AOUTHDR
3275fd0b74Schristos #define DO_NOT_DEFINE_FILHDR
3375fd0b74Schristos #define DO_NOT_DEFINE_LINENO
3475fd0b74Schristos #define DO_NOT_DEFINE_SCNHDR
3575fd0b74Schristos #include "coff/external.h"
3675fd0b74Schristos #include "coff/internal.h"
3775fd0b74Schristos #include "libcoff.h"
3875fd0b74Schristos #include "bucomm.h"
39*e992f068Schristos #include "demanguse.h"
40ede78133Schristos #include "plugin-api.h"
4175fd0b74Schristos #include "plugin.h"
42*e992f068Schristos #include "safe-ctype.h"
43*e992f068Schristos 
44*e992f068Schristos #ifndef streq
45*e992f068Schristos #define streq(a,b) (strcmp ((a),(b)) == 0)
46*e992f068Schristos #endif
4775fd0b74Schristos 
4875fd0b74Schristos /* When sorting by size, we use this structure to hold the size and a
4975fd0b74Schristos    pointer to the minisymbol.  */
5075fd0b74Schristos 
5175fd0b74Schristos struct size_sym
5275fd0b74Schristos {
5375fd0b74Schristos   const void *minisym;
5475fd0b74Schristos   bfd_vma size;
5575fd0b74Schristos };
5675fd0b74Schristos 
5775fd0b74Schristos /* When fetching relocs, we use this structure to pass information to
5875fd0b74Schristos    get_relocs.  */
5975fd0b74Schristos 
6075fd0b74Schristos struct get_relocs_info
6175fd0b74Schristos {
6275fd0b74Schristos   asection **secs;
6375fd0b74Schristos   arelent ***relocs;
6475fd0b74Schristos   long *relcount;
6575fd0b74Schristos   asymbol **syms;
6675fd0b74Schristos };
6775fd0b74Schristos 
6875fd0b74Schristos struct extended_symbol_info
6975fd0b74Schristos {
7075fd0b74Schristos   symbol_info *sinfo;
7175fd0b74Schristos   bfd_vma ssize;
7275fd0b74Schristos   elf_symbol_type *elfinfo;
7375fd0b74Schristos   coff_symbol_type *coffinfo;
7475fd0b74Schristos   /* FIXME: We should add more fields for Type, Line, Section.  */
7575fd0b74Schristos };
7675fd0b74Schristos #define SYM_VALUE(sym)       (sym->sinfo->value)
7775fd0b74Schristos #define SYM_TYPE(sym)        (sym->sinfo->type)
7875fd0b74Schristos #define SYM_STAB_NAME(sym)   (sym->sinfo->stab_name)
7975fd0b74Schristos #define SYM_STAB_DESC(sym)   (sym->sinfo->stab_desc)
8075fd0b74Schristos #define SYM_STAB_OTHER(sym)  (sym->sinfo->stab_other)
8175fd0b74Schristos #define SYM_SIZE(sym) \
8275fd0b74Schristos   (sym->elfinfo ? sym->elfinfo->internal_elf_sym.st_size: sym->ssize)
8375fd0b74Schristos 
8475fd0b74Schristos /* The output formatting functions.  */
85012573ebSchristos static void print_object_filename_bsd (const char *);
86012573ebSchristos static void print_object_filename_sysv (const char *);
87012573ebSchristos static void print_object_filename_posix (const char *);
88*e992f068Schristos static void do_not_print_object_filename (const char *);
89*e992f068Schristos 
90012573ebSchristos static void print_archive_filename_bsd (const char *);
91012573ebSchristos static void print_archive_filename_sysv (const char *);
92012573ebSchristos static void print_archive_filename_posix (const char *);
93*e992f068Schristos static void do_not_print_archive_filename (const char *);
94*e992f068Schristos 
95012573ebSchristos static void print_archive_member_bsd (const char *, const char *);
96012573ebSchristos static void print_archive_member_sysv (const char *, const char *);
97012573ebSchristos static void print_archive_member_posix (const char *, const char *);
98*e992f068Schristos static void do_not_print_archive_member (const char *, const char *);
99*e992f068Schristos 
10075fd0b74Schristos static void print_symbol_filename_bsd (bfd *, bfd *);
10175fd0b74Schristos static void print_symbol_filename_sysv (bfd *, bfd *);
10275fd0b74Schristos static void print_symbol_filename_posix (bfd *, bfd *);
103*e992f068Schristos static void do_not_print_symbol_filename (bfd *, bfd *);
104*e992f068Schristos 
10575fd0b74Schristos static void print_symbol_info_bsd (struct extended_symbol_info *, bfd *);
10675fd0b74Schristos static void print_symbol_info_sysv (struct extended_symbol_info *, bfd *);
10775fd0b74Schristos static void print_symbol_info_posix (struct extended_symbol_info *, bfd *);
108*e992f068Schristos static void just_print_symbol_name (struct extended_symbol_info *, bfd *);
109*e992f068Schristos 
110*e992f068Schristos static void print_value (bfd *, bfd_vma);
11175fd0b74Schristos 
11275fd0b74Schristos /* Support for different output formats.  */
11375fd0b74Schristos struct output_fns
11475fd0b74Schristos {
11575fd0b74Schristos   /* Print the name of an object file given on the command line.  */
116012573ebSchristos   void (*print_object_filename) (const char *);
11775fd0b74Schristos 
11875fd0b74Schristos   /* Print the name of an archive file given on the command line.  */
119012573ebSchristos   void (*print_archive_filename) (const char *);
12075fd0b74Schristos 
12175fd0b74Schristos   /* Print the name of an archive member file.  */
122012573ebSchristos   void (*print_archive_member) (const char *, const char *);
12375fd0b74Schristos 
12475fd0b74Schristos   /* Print the name of the file (and archive, if there is one)
12575fd0b74Schristos      containing a symbol.  */
12675fd0b74Schristos   void (*print_symbol_filename) (bfd *, bfd *);
12775fd0b74Schristos 
12875fd0b74Schristos   /* Print a line of information about a symbol.  */
12975fd0b74Schristos   void (*print_symbol_info) (struct extended_symbol_info *, bfd *);
13075fd0b74Schristos };
13175fd0b74Schristos 
132*e992f068Schristos /* Indices in `formats'.  */
133*e992f068Schristos enum formats
134*e992f068Schristos {
135*e992f068Schristos   FORMAT_BSD = 0,
136*e992f068Schristos   FORMAT_SYSV,
137*e992f068Schristos   FORMAT_POSIX,
138*e992f068Schristos   FORMAT_JUST_SYMBOLS,
139*e992f068Schristos   FORMAT_MAX
140*e992f068Schristos };
141*e992f068Schristos 
142*e992f068Schristos #define FORMAT_DEFAULT FORMAT_BSD
143*e992f068Schristos 
144*e992f068Schristos static struct output_fns formats[FORMAT_MAX] =
14575fd0b74Schristos {
14675fd0b74Schristos   {print_object_filename_bsd,
14775fd0b74Schristos    print_archive_filename_bsd,
14875fd0b74Schristos    print_archive_member_bsd,
14975fd0b74Schristos    print_symbol_filename_bsd,
15075fd0b74Schristos    print_symbol_info_bsd},
15175fd0b74Schristos   {print_object_filename_sysv,
15275fd0b74Schristos    print_archive_filename_sysv,
15375fd0b74Schristos    print_archive_member_sysv,
15475fd0b74Schristos    print_symbol_filename_sysv,
15575fd0b74Schristos    print_symbol_info_sysv},
15675fd0b74Schristos   {print_object_filename_posix,
15775fd0b74Schristos    print_archive_filename_posix,
15875fd0b74Schristos    print_archive_member_posix,
15975fd0b74Schristos    print_symbol_filename_posix,
160*e992f068Schristos    print_symbol_info_posix},
161*e992f068Schristos   {do_not_print_object_filename,
162*e992f068Schristos    do_not_print_archive_filename,
163*e992f068Schristos    do_not_print_archive_member,
164*e992f068Schristos    do_not_print_symbol_filename,
165*e992f068Schristos    just_print_symbol_name}
16675fd0b74Schristos };
16775fd0b74Schristos 
16875fd0b74Schristos 
16975fd0b74Schristos /* The output format to use.  */
17075fd0b74Schristos static struct output_fns *format = &formats[FORMAT_DEFAULT];
171012573ebSchristos static unsigned int print_format = FORMAT_DEFAULT;
172012573ebSchristos static const char *print_format_string = NULL;
17375fd0b74Schristos 
17475fd0b74Schristos /* Command options.  */
17575fd0b74Schristos 
17675fd0b74Schristos static int do_demangle = 0;	/* Pretty print C++ symbol names.  */
17775fd0b74Schristos static int external_only = 0;	/* Print external symbols only.  */
17875fd0b74Schristos static int defined_only = 0;	/* Print defined symbols only.  */
179*e992f068Schristos static int non_weak = 0;	/* Ignore weak symbols.  */
18075fd0b74Schristos static int no_sort = 0;		/* Don't sort; print syms in order found.  */
18175fd0b74Schristos static int print_debug_syms = 0;/* Print debugger-only symbols too.  */
18275fd0b74Schristos static int print_armap = 0;	/* Describe __.SYMDEF data in archive files.  */
18375fd0b74Schristos static int print_size = 0;	/* Print size of defined symbols.  */
18475fd0b74Schristos static int reverse_sort = 0;	/* Sort in downward(alpha or numeric) order.  */
18575fd0b74Schristos static int sort_numerically = 0;/* Sort in numeric rather than alpha order.  */
18675fd0b74Schristos static int sort_by_size = 0;	/* Sort by size of symbol.  */
18775fd0b74Schristos static int undefined_only = 0;	/* Print undefined symbols only.  */
18875fd0b74Schristos static int dynamic = 0;		/* Print dynamic symbols.  */
18975fd0b74Schristos static int show_version = 0;	/* Show the version number.  */
19075fd0b74Schristos static int show_synthetic = 0;	/* Display synthesized symbols too.  */
19175fd0b74Schristos static int line_numbers = 0;	/* Print line numbers for symbols.  */
19275fd0b74Schristos static int allow_special_symbols = 0;  /* Allow special symbols.  */
193*e992f068Schristos static int with_symbol_versions = -1; /* Output symbol version information.  */
194*e992f068Schristos static int quiet = 0;		/* Suppress "no symbols" diagnostic.  */
195*e992f068Schristos 
196*e992f068Schristos /* The characters to use for global and local ifunc symbols.  */
197*e992f068Schristos #if DEFAULT_F_FOR_IFUNC_SYMBOLS
198*e992f068Schristos static const char * ifunc_type_chars = "Ff";
199*e992f068Schristos #else
200*e992f068Schristos static const char * ifunc_type_chars = NULL;
201*e992f068Schristos #endif
20275fd0b74Schristos 
203012573ebSchristos static int demangle_flags = DMGL_ANSI | DMGL_PARAMS;
204012573ebSchristos 
20575fd0b74Schristos /* When to print the names of files.  Not mutually exclusive in SYSV format.  */
20675fd0b74Schristos static int filename_per_file = 0;	/* Once per file, on its own line.  */
20775fd0b74Schristos static int filename_per_symbol = 0;	/* Once per symbol, at start of line.  */
20875fd0b74Schristos 
20975fd0b74Schristos static int print_width = 0;
21075fd0b74Schristos static int print_radix = 16;
21175fd0b74Schristos /* Print formats for printing stab info.  */
21275fd0b74Schristos static char other_format[] = "%02x";
21375fd0b74Schristos static char desc_format[] = "%04x";
21475fd0b74Schristos 
21575fd0b74Schristos static char *target = NULL;
21675fd0b74Schristos #if BFD_SUPPORTS_PLUGINS
21775fd0b74Schristos static const char *plugin_target = "plugin";
21875fd0b74Schristos #else
21975fd0b74Schristos static const char *plugin_target = NULL;
22075fd0b74Schristos #endif
22175fd0b74Schristos 
22275fd0b74Schristos /* Used to cache the line numbers for a BFD.  */
22375fd0b74Schristos static bfd *lineno_cache_bfd;
22475fd0b74Schristos static bfd *lineno_cache_rel_bfd;
22575fd0b74Schristos 
226*e992f068Schristos typedef enum unicode_display_type
227*e992f068Schristos {
228*e992f068Schristos   unicode_default = 0,
229*e992f068Schristos   unicode_locale,
230*e992f068Schristos   unicode_escape,
231*e992f068Schristos   unicode_hex,
232*e992f068Schristos   unicode_highlight,
233*e992f068Schristos   unicode_invalid
234*e992f068Schristos } unicode_display_type;
235*e992f068Schristos 
236*e992f068Schristos static unicode_display_type unicode_display = unicode_default;
237*e992f068Schristos 
238012573ebSchristos enum long_option_values
239012573ebSchristos {
240012573ebSchristos   OPTION_TARGET = 200,
241012573ebSchristos   OPTION_PLUGIN,
242012573ebSchristos   OPTION_SIZE_SORT,
243012573ebSchristos   OPTION_RECURSE_LIMIT,
244*e992f068Schristos   OPTION_NO_RECURSE_LIMIT,
245*e992f068Schristos   OPTION_IFUNC_CHARS,
246*e992f068Schristos   OPTION_UNICODE,
247*e992f068Schristos   OPTION_QUIET
248012573ebSchristos };
24975fd0b74Schristos 
25075fd0b74Schristos static struct option long_options[] =
25175fd0b74Schristos {
25275fd0b74Schristos   {"debug-syms", no_argument, &print_debug_syms, 1},
25375fd0b74Schristos   {"demangle", optional_argument, 0, 'C'},
25475fd0b74Schristos   {"dynamic", no_argument, &dynamic, 1},
25575fd0b74Schristos   {"extern-only", no_argument, &external_only, 1},
25675fd0b74Schristos   {"format", required_argument, 0, 'f'},
25775fd0b74Schristos   {"help", no_argument, 0, 'h'},
258*e992f068Schristos   {"ifunc-chars", required_argument, 0, OPTION_IFUNC_CHARS},
259*e992f068Schristos   {"just-symbols", no_argument, 0, 'j'},
26075fd0b74Schristos   {"line-numbers", no_argument, 0, 'l'},
26175fd0b74Schristos   {"no-cplus", no_argument, &do_demangle, 0},  /* Linux compatibility.  */
26275fd0b74Schristos   {"no-demangle", no_argument, &do_demangle, 0},
263012573ebSchristos   {"no-recurse-limit", no_argument, NULL, OPTION_NO_RECURSE_LIMIT},
264012573ebSchristos   {"no-recursion-limit", no_argument, NULL, OPTION_NO_RECURSE_LIMIT},
26575fd0b74Schristos   {"no-sort", no_argument, 0, 'p'},
26675fd0b74Schristos   {"numeric-sort", no_argument, 0, 'n'},
26775fd0b74Schristos   {"plugin", required_argument, 0, OPTION_PLUGIN},
26875fd0b74Schristos   {"portability", no_argument, 0, 'P'},
26975fd0b74Schristos   {"print-armap", no_argument, &print_armap, 1},
27075fd0b74Schristos   {"print-file-name", no_argument, 0, 'o'},
27175fd0b74Schristos   {"print-size", no_argument, 0, 'S'},
272*e992f068Schristos   {"quiet", no_argument, 0, OPTION_QUIET},
27375fd0b74Schristos   {"radix", required_argument, 0, 't'},
274012573ebSchristos   {"recurse-limit", no_argument, NULL, OPTION_RECURSE_LIMIT},
275012573ebSchristos   {"recursion-limit", no_argument, NULL, OPTION_RECURSE_LIMIT},
27675fd0b74Schristos   {"reverse-sort", no_argument, &reverse_sort, 1},
27775fd0b74Schristos   {"size-sort", no_argument, 0, OPTION_SIZE_SORT},
27875fd0b74Schristos   {"special-syms", no_argument, &allow_special_symbols, 1},
27975fd0b74Schristos   {"synthetic", no_argument, &show_synthetic, 1},
28075fd0b74Schristos   {"target", required_argument, 0, OPTION_TARGET},
281*e992f068Schristos   {"defined-only", no_argument, 0, 'U'},
282*e992f068Schristos   {"undefined-only", no_argument, 0, 'u'},
283*e992f068Schristos   {"unicode", required_argument, NULL, OPTION_UNICODE},
28475fd0b74Schristos   {"version", no_argument, &show_version, 1},
285*e992f068Schristos   {"no-weak", no_argument, 0, 'W'},
286ede78133Schristos   {"with-symbol-versions", no_argument, &with_symbol_versions, 1},
287*e992f068Schristos   {"without-symbol-versions", no_argument, &with_symbol_versions, 0},
28875fd0b74Schristos   {0, no_argument, 0, 0}
28975fd0b74Schristos };
29075fd0b74Schristos 
29175fd0b74Schristos /* Some error-reporting functions.  */
29275fd0b74Schristos 
293ede78133Schristos ATTRIBUTE_NORETURN static void
usage(FILE * stream,int status)29475fd0b74Schristos usage (FILE *stream, int status)
29575fd0b74Schristos {
29675fd0b74Schristos   fprintf (stream, _("Usage: %s [option(s)] [file(s)]\n"), program_name);
29775fd0b74Schristos   fprintf (stream, _(" List symbols in [file(s)] (a.out by default).\n"));
298*e992f068Schristos   fprintf (stream, _(" The options are:\n"));
299*e992f068Schristos   fprintf (stream, _("\
300*e992f068Schristos   -a, --debug-syms       Display debugger-only symbols\n"));
301*e992f068Schristos   fprintf (stream, _("\
302*e992f068Schristos   -A, --print-file-name  Print name of the input file before every symbol\n"));
303*e992f068Schristos   fprintf (stream, _("\
304*e992f068Schristos   -B                     Same as --format=bsd\n"));
305*e992f068Schristos   fprintf (stream, _("\
306*e992f068Schristos   -C, --demangle[=STYLE] Decode mangled/processed symbol names\n"));
307*e992f068Schristos   display_demangler_styles (stream, _("\
308*e992f068Schristos                            STYLE can be "));
309*e992f068Schristos   fprintf (stream, _("\
310*e992f068Schristos       --no-demangle      Do not demangle low-level symbol names\n"));
311*e992f068Schristos   fprintf (stream, _("\
312*e992f068Schristos       --recurse-limit    Enable a demangling recursion limit.  (default)\n"));
313*e992f068Schristos   fprintf (stream, _("\
314*e992f068Schristos       --no-recurse-limit Disable a demangling recursion limit.\n"));
315*e992f068Schristos   fprintf (stream, _("\
316*e992f068Schristos   -D, --dynamic          Display dynamic symbols instead of normal symbols\n"));
317*e992f068Schristos   fprintf (stream, _("\
318*e992f068Schristos   -e                     (ignored)\n"));
319*e992f068Schristos   fprintf (stream, _("\
32075fd0b74Schristos   -f, --format=FORMAT    Use the output format FORMAT.  FORMAT can be `bsd',\n\
321*e992f068Schristos                            `sysv', `posix' or 'just-symbols'.\n\
322*e992f068Schristos                            The default is `bsd'\n"));
323*e992f068Schristos   fprintf (stream, _("\
324*e992f068Schristos   -g, --extern-only      Display only external symbols\n"));
325*e992f068Schristos   fprintf (stream, _("\
326*e992f068Schristos     --ifunc-chars=CHARS  Characters to use when displaying ifunc symbols\n"));
327*e992f068Schristos   fprintf (stream, _("\
328*e992f068Schristos   -j, --just-symbols     Same as --format=just-symbols\n"));
329*e992f068Schristos   fprintf (stream, _("\
33075fd0b74Schristos   -l, --line-numbers     Use debugging information to find a filename and\n\
331*e992f068Schristos                            line number for each symbol\n"));
332*e992f068Schristos   fprintf (stream, _("\
333*e992f068Schristos   -n, --numeric-sort     Sort symbols numerically by address\n"));
334*e992f068Schristos   fprintf (stream, _("\
335*e992f068Schristos   -o                     Same as -A\n"));
336*e992f068Schristos   fprintf (stream, _("\
337*e992f068Schristos   -p, --no-sort          Do not sort the symbols\n"));
338*e992f068Schristos   fprintf (stream, _("\
339*e992f068Schristos   -P, --portability      Same as --format=posix\n"));
340*e992f068Schristos   fprintf (stream, _("\
34175fd0b74Schristos   -r, --reverse-sort     Reverse the sense of the sort\n"));
34275fd0b74Schristos #if BFD_SUPPORTS_PLUGINS
34375fd0b74Schristos   fprintf (stream, _("\
34475fd0b74Schristos       --plugin NAME      Load the specified plugin\n"));
34575fd0b74Schristos #endif
34675fd0b74Schristos   fprintf (stream, _("\
347*e992f068Schristos   -S, --print-size       Print size of defined symbols\n"));
348*e992f068Schristos   fprintf (stream, _("\
349*e992f068Schristos   -s, --print-armap      Include index for symbols from archive members\n"));
350*e992f068Schristos   fprintf (stream, _("\
351*e992f068Schristos       --quiet            Suppress \"no symbols\" diagnostic\n"));
352*e992f068Schristos   fprintf (stream, _("\
353*e992f068Schristos       --size-sort        Sort symbols by size\n"));
354*e992f068Schristos   fprintf (stream, _("\
355*e992f068Schristos       --special-syms     Include special symbols in the output\n"));
356*e992f068Schristos   fprintf (stream, _("\
357*e992f068Schristos       --synthetic        Display synthetic symbols as well\n"));
358*e992f068Schristos   fprintf (stream, _("\
359*e992f068Schristos   -t, --radix=RADIX      Use RADIX for printing symbol values\n"));
360*e992f068Schristos   fprintf (stream, _("\
361*e992f068Schristos       --target=BFDNAME   Specify the target object format as BFDNAME\n"));
362*e992f068Schristos   fprintf (stream, _("\
363*e992f068Schristos   -u, --undefined-only   Display only undefined symbols\n"));
364*e992f068Schristos   fprintf (stream, _("\
365*e992f068Schristos   -U, --defined-only     Display only defined symbols\n"));
366*e992f068Schristos   fprintf (stream, _("\
367*e992f068Schristos       --unicode={default|show|invalid|hex|escape|highlight}\n\
368*e992f068Schristos                          Specify how to treat UTF-8 encoded unicode characters\n"));
369*e992f068Schristos   fprintf (stream, _("\
370*e992f068Schristos   -W, --no-weak          Ignore weak symbols\n"));
371*e992f068Schristos   fprintf (stream, _("\
372*e992f068Schristos       --with-symbol-versions  Display version strings after symbol names\n"));
373*e992f068Schristos   fprintf (stream, _("\
374*e992f068Schristos   -X 32_64               (ignored)\n"));
375*e992f068Schristos   fprintf (stream, _("\
376*e992f068Schristos   @FILE                  Read options from FILE\n"));
377*e992f068Schristos   fprintf (stream, _("\
378*e992f068Schristos   -h, --help             Display this information\n"));
379*e992f068Schristos   fprintf (stream, _("\
380*e992f068Schristos   -V, --version          Display this program's version number\n"));
381*e992f068Schristos 
38275fd0b74Schristos   list_supported_targets (program_name, stream);
38375fd0b74Schristos   if (REPORT_BUGS_TO[0] && status == 0)
38475fd0b74Schristos     fprintf (stream, _("Report bugs to %s.\n"), REPORT_BUGS_TO);
38575fd0b74Schristos   exit (status);
38675fd0b74Schristos }
38775fd0b74Schristos 
38875fd0b74Schristos /* Set the radix for the symbol value and size according to RADIX.  */
38975fd0b74Schristos 
39075fd0b74Schristos static void
set_print_radix(char * radix)39175fd0b74Schristos set_print_radix (char *radix)
39275fd0b74Schristos {
39375fd0b74Schristos   switch (*radix)
39475fd0b74Schristos     {
395012573ebSchristos     case 'x': print_radix = 16; break;
396012573ebSchristos     case 'd': print_radix = 10; break;
397012573ebSchristos     case 'o': print_radix =  8; break;
398012573ebSchristos 
39975fd0b74Schristos     default:
40075fd0b74Schristos       fatal (_("%s: invalid radix"), radix);
40175fd0b74Schristos     }
402012573ebSchristos 
403012573ebSchristos   other_format[3] = desc_format[3] = *radix;
40475fd0b74Schristos }
40575fd0b74Schristos 
40675fd0b74Schristos static void
set_output_format(char * f)40775fd0b74Schristos set_output_format (char *f)
40875fd0b74Schristos {
40975fd0b74Schristos   int i;
41075fd0b74Schristos 
41175fd0b74Schristos   switch (*f)
41275fd0b74Schristos     {
41375fd0b74Schristos     case 'b':
41475fd0b74Schristos     case 'B':
41575fd0b74Schristos       i = FORMAT_BSD;
41675fd0b74Schristos       break;
41775fd0b74Schristos     case 'p':
41875fd0b74Schristos     case 'P':
41975fd0b74Schristos       i = FORMAT_POSIX;
42075fd0b74Schristos       break;
42175fd0b74Schristos     case 's':
42275fd0b74Schristos     case 'S':
42375fd0b74Schristos       i = FORMAT_SYSV;
42475fd0b74Schristos       break;
425*e992f068Schristos     case 'j':
426*e992f068Schristos     case 'J':
427*e992f068Schristos       i = FORMAT_JUST_SYMBOLS;
428*e992f068Schristos       break;
42975fd0b74Schristos     default:
43075fd0b74Schristos       fatal (_("%s: invalid output format"), f);
43175fd0b74Schristos     }
43275fd0b74Schristos   format = &formats[i];
433012573ebSchristos   print_format = i;
43475fd0b74Schristos }
43575fd0b74Schristos 
43675fd0b74Schristos static const char *
get_elf_symbol_type(unsigned int type)43775fd0b74Schristos get_elf_symbol_type (unsigned int type)
43875fd0b74Schristos {
439ede78133Schristos   static char *bufp;
440ede78133Schristos   int n;
44175fd0b74Schristos 
44275fd0b74Schristos   switch (type)
44375fd0b74Schristos     {
44475fd0b74Schristos     case STT_NOTYPE:   return "NOTYPE";
44575fd0b74Schristos     case STT_OBJECT:   return "OBJECT";
44675fd0b74Schristos     case STT_FUNC:     return "FUNC";
44775fd0b74Schristos     case STT_SECTION:  return "SECTION";
44875fd0b74Schristos     case STT_FILE:     return "FILE";
44975fd0b74Schristos     case STT_COMMON:   return "COMMON";
45075fd0b74Schristos     case STT_TLS:      return "TLS";
45175fd0b74Schristos     }
452ede78133Schristos 
453ede78133Schristos   free (bufp);
454ede78133Schristos   if (type >= STT_LOPROC && type <= STT_HIPROC)
455ede78133Schristos     n = asprintf (&bufp, _("<processor specific>: %d"), type);
456ede78133Schristos   else if (type >= STT_LOOS && type <= STT_HIOS)
457ede78133Schristos     n = asprintf (&bufp, _("<OS specific>: %d"), type);
458ede78133Schristos   else
459ede78133Schristos     n = asprintf (&bufp, _("<unknown>: %d"), type);
460ede78133Schristos   if (n < 0)
461ede78133Schristos     fatal ("%s", xstrerror (errno));
462ede78133Schristos   return bufp;
46375fd0b74Schristos }
46475fd0b74Schristos 
46575fd0b74Schristos static const char *
get_coff_symbol_type(const struct internal_syment * sym)46675fd0b74Schristos get_coff_symbol_type (const struct internal_syment *sym)
46775fd0b74Schristos {
468ede78133Schristos   static char *bufp;
469ede78133Schristos   int n;
47075fd0b74Schristos 
47175fd0b74Schristos   switch (sym->n_sclass)
47275fd0b74Schristos     {
47375fd0b74Schristos     case C_BLOCK: return "Block";
47475fd0b74Schristos     case C_FILE:  return "File";
47575fd0b74Schristos     case C_LINE:  return "Line";
47675fd0b74Schristos     }
47775fd0b74Schristos 
47875fd0b74Schristos   if (!sym->n_type)
47975fd0b74Schristos     return "None";
48075fd0b74Schristos 
48175fd0b74Schristos   switch (DTYPE(sym->n_type))
48275fd0b74Schristos     {
48375fd0b74Schristos     case DT_FCN: return "Function";
48475fd0b74Schristos     case DT_PTR: return "Pointer";
48575fd0b74Schristos     case DT_ARY: return "Array";
48675fd0b74Schristos     }
48775fd0b74Schristos 
488ede78133Schristos   free (bufp);
489ede78133Schristos   n = asprintf (&bufp, _("<unknown>: %d/%d"), sym->n_sclass, sym->n_type);
490ede78133Schristos   if (n < 0)
491ede78133Schristos     fatal ("%s", xstrerror (errno));
492ede78133Schristos   return bufp;
49375fd0b74Schristos }
49475fd0b74Schristos 
495*e992f068Schristos /* Convert a potential UTF-8 encoded sequence in IN into characters in OUT.
496*e992f068Schristos    The conversion format is controlled by the unicode_display variable.
497*e992f068Schristos    Returns the number of characters added to OUT.
498*e992f068Schristos    Returns the number of bytes consumed from IN in CONSUMED.
499*e992f068Schristos    Always consumes at least one byte and displays at least one character.  */
500*e992f068Schristos 
501*e992f068Schristos static unsigned int
display_utf8(const unsigned char * in,char * out,unsigned int * consumed)502*e992f068Schristos display_utf8 (const unsigned char * in, char * out, unsigned int * consumed)
503*e992f068Schristos {
504*e992f068Schristos   char *        orig_out = out;
505*e992f068Schristos   unsigned int  nchars = 0;
506*e992f068Schristos   unsigned int j;
507*e992f068Schristos 
508*e992f068Schristos   if (unicode_display == unicode_default)
509*e992f068Schristos     goto invalid;
510*e992f068Schristos 
511*e992f068Schristos   if (in[0] < 0xc0)
512*e992f068Schristos     goto invalid;
513*e992f068Schristos 
514*e992f068Schristos   if ((in[1] & 0xc0) != 0x80)
515*e992f068Schristos     goto invalid;
516*e992f068Schristos 
517*e992f068Schristos   if ((in[0] & 0x20) == 0)
518*e992f068Schristos     {
519*e992f068Schristos       nchars = 2;
520*e992f068Schristos       goto valid;
521*e992f068Schristos     }
522*e992f068Schristos 
523*e992f068Schristos   if ((in[2] & 0xc0) != 0x80)
524*e992f068Schristos     goto invalid;
525*e992f068Schristos 
526*e992f068Schristos   if ((in[0] & 0x10) == 0)
527*e992f068Schristos     {
528*e992f068Schristos       nchars = 3;
529*e992f068Schristos       goto valid;
530*e992f068Schristos     }
531*e992f068Schristos 
532*e992f068Schristos   if ((in[3] & 0xc0) != 0x80)
533*e992f068Schristos     goto invalid;
534*e992f068Schristos 
535*e992f068Schristos   nchars = 4;
536*e992f068Schristos 
537*e992f068Schristos  valid:
538*e992f068Schristos   switch (unicode_display)
539*e992f068Schristos     {
540*e992f068Schristos     case unicode_locale:
541*e992f068Schristos       /* Copy the bytes into the output buffer as is.  */
542*e992f068Schristos       memcpy (out, in, nchars);
543*e992f068Schristos       out += nchars;
544*e992f068Schristos       break;
545*e992f068Schristos 
546*e992f068Schristos     case unicode_invalid:
547*e992f068Schristos     case unicode_hex:
548*e992f068Schristos       out += sprintf (out, "%c", unicode_display == unicode_hex ? '<' : '{');
549*e992f068Schristos       out += sprintf (out, "0x");
550*e992f068Schristos       for (j = 0; j < nchars; j++)
551*e992f068Schristos 	out += sprintf (out, "%02x", in [j]);
552*e992f068Schristos       out += sprintf (out, "%c", unicode_display == unicode_hex ? '>' : '}');
553*e992f068Schristos       break;
554*e992f068Schristos 
555*e992f068Schristos     case unicode_highlight:
556*e992f068Schristos       if (isatty (1))
557*e992f068Schristos 	out += sprintf (out, "\x1B[31;47m"); /* Red.  */
558*e992f068Schristos       /* Fall through.  */
559*e992f068Schristos     case unicode_escape:
560*e992f068Schristos       switch (nchars)
561*e992f068Schristos 	{
562*e992f068Schristos 	case 2:
563*e992f068Schristos 	  out += sprintf (out, "\\u%02x%02x",
564*e992f068Schristos 		  ((in[0] & 0x1c) >> 2),
565*e992f068Schristos 		  ((in[0] & 0x03) << 6) | (in[1] & 0x3f));
566*e992f068Schristos 	  break;
567*e992f068Schristos 
568*e992f068Schristos 	case 3:
569*e992f068Schristos 	  out += sprintf (out, "\\u%02x%02x",
570*e992f068Schristos 		  ((in[0] & 0x0f) << 4) | ((in[1] & 0x3c) >> 2),
571*e992f068Schristos 		  ((in[1] & 0x03) << 6) | ((in[2] & 0x3f)));
572*e992f068Schristos 	  break;
573*e992f068Schristos 
574*e992f068Schristos 	case 4:
575*e992f068Schristos 	  out += sprintf (out, "\\u%02x%02x%02x",
576*e992f068Schristos 		  ((in[0] & 0x07) << 6) | ((in[1] & 0x3c) >> 2),
577*e992f068Schristos 		  ((in[1] & 0x03) << 6) | ((in[2] & 0x3c) >> 2),
578*e992f068Schristos 		  ((in[2] & 0x03) << 6) | ((in[3] & 0x3f)));
579*e992f068Schristos 	  break;
580*e992f068Schristos 	default:
581*e992f068Schristos 	  /* URG.  */
582*e992f068Schristos 	  break;
583*e992f068Schristos 	}
584*e992f068Schristos 
585*e992f068Schristos       if (unicode_display == unicode_highlight && isatty (1))
586*e992f068Schristos 	out += sprintf (out, "\033[0m"); /* Default colour.  */
587*e992f068Schristos       break;
588*e992f068Schristos 
589*e992f068Schristos     default:
590*e992f068Schristos       /* URG */
591*e992f068Schristos       break;
592*e992f068Schristos     }
593*e992f068Schristos 
594*e992f068Schristos   * consumed = nchars;
595*e992f068Schristos   return out - orig_out;
596*e992f068Schristos 
597*e992f068Schristos  invalid:
598*e992f068Schristos   /* Not a valid UTF-8 sequence.  */
599*e992f068Schristos   *out = *in;
600*e992f068Schristos   * consumed = 1;
601*e992f068Schristos   return 1;
602*e992f068Schristos }
603*e992f068Schristos 
604*e992f068Schristos /* Convert any UTF-8 encoded characters in NAME into the form specified by
605*e992f068Schristos    unicode_display.  Also converts control characters.  Returns a static
606*e992f068Schristos    buffer if conversion was necessary.
607*e992f068Schristos    Code stolen from objdump.c:sanitize_string().  */
608*e992f068Schristos 
609*e992f068Schristos static const char *
convert_utf8(const char * in)610*e992f068Schristos convert_utf8 (const char * in)
611*e992f068Schristos {
612*e992f068Schristos   static char *  buffer = NULL;
613*e992f068Schristos   static size_t  buffer_len = 0;
614*e992f068Schristos   const char *   original = in;
615*e992f068Schristos   char *         out;
616*e992f068Schristos 
617*e992f068Schristos   /* Paranoia.  */
618*e992f068Schristos   if (in == NULL)
619*e992f068Schristos     return "";
620*e992f068Schristos 
621*e992f068Schristos   /* See if any conversion is necessary.
622*e992f068Schristos      In the majority of cases it will not be needed.  */
623*e992f068Schristos   do
624*e992f068Schristos     {
625*e992f068Schristos       unsigned char c = *in++;
626*e992f068Schristos 
627*e992f068Schristos       if (c == 0)
628*e992f068Schristos 	return original;
629*e992f068Schristos 
630*e992f068Schristos       if (ISCNTRL (c))
631*e992f068Schristos 	break;
632*e992f068Schristos 
633*e992f068Schristos       if (unicode_display != unicode_default && c >= 0xc0)
634*e992f068Schristos 	break;
635*e992f068Schristos     }
636*e992f068Schristos   while (1);
637*e992f068Schristos 
638*e992f068Schristos   /* Copy the input, translating as needed.  */
639*e992f068Schristos   in = original;
640*e992f068Schristos   if (buffer_len < (strlen (in) * 9))
641*e992f068Schristos     {
642*e992f068Schristos       free ((void *) buffer);
643*e992f068Schristos       buffer_len = strlen (in) * 9;
644*e992f068Schristos       buffer = xmalloc (buffer_len + 1);
645*e992f068Schristos     }
646*e992f068Schristos 
647*e992f068Schristos   out = buffer;
648*e992f068Schristos   do
649*e992f068Schristos     {
650*e992f068Schristos       unsigned char c = *in++;
651*e992f068Schristos 
652*e992f068Schristos       if (c == 0)
653*e992f068Schristos 	break;
654*e992f068Schristos 
655*e992f068Schristos       if (ISCNTRL (c))
656*e992f068Schristos 	{
657*e992f068Schristos 	  *out++ = '^';
658*e992f068Schristos 	  *out++ = c + 0x40;
659*e992f068Schristos 	}
660*e992f068Schristos       else if (unicode_display != unicode_default && c >= 0xc0)
661*e992f068Schristos 	{
662*e992f068Schristos 	  unsigned int num_consumed;
663*e992f068Schristos 
664*e992f068Schristos 	  out += display_utf8 ((const unsigned char *)(in - 1), out, & num_consumed);
665*e992f068Schristos 	  in += num_consumed - 1;
666*e992f068Schristos 	}
667*e992f068Schristos       else
668*e992f068Schristos 	*out++ = c;
669*e992f068Schristos     }
670*e992f068Schristos   while (1);
671*e992f068Schristos 
672*e992f068Schristos   *out = 0;
673*e992f068Schristos   return buffer;
674*e992f068Schristos }
675*e992f068Schristos 
67675fd0b74Schristos /* Print symbol name NAME, read from ABFD, with printf format FORM,
67775fd0b74Schristos    demangling it if requested.  */
67875fd0b74Schristos 
67975fd0b74Schristos static void
print_symname(const char * form,struct extended_symbol_info * info,const char * name,bfd * abfd)680*e992f068Schristos print_symname (const char *form, struct extended_symbol_info *info,
681*e992f068Schristos 	       const char *name, bfd *abfd)
68275fd0b74Schristos {
683*e992f068Schristos   char *alloc = NULL;
684*e992f068Schristos   char *atver = NULL;
685*e992f068Schristos 
686*e992f068Schristos   if (name == NULL)
687*e992f068Schristos     name = info->sinfo->name;
688*e992f068Schristos 
689*e992f068Schristos   if (!with_symbol_versions
690*e992f068Schristos       && bfd_get_flavour (abfd) == bfd_target_elf_flavour)
691*e992f068Schristos     {
692*e992f068Schristos       atver = strchr (name, '@');
693*e992f068Schristos       if (atver)
694*e992f068Schristos 	*atver = 0;
695*e992f068Schristos     }
696*e992f068Schristos 
69775fd0b74Schristos   if (do_demangle && *name)
69875fd0b74Schristos     {
699*e992f068Schristos       alloc = bfd_demangle (abfd, name, demangle_flags);
700*e992f068Schristos       if (alloc != NULL)
701*e992f068Schristos 	name = alloc;
702*e992f068Schristos     }
70375fd0b74Schristos 
704*e992f068Schristos   if (unicode_display != unicode_default)
70575fd0b74Schristos     {
706*e992f068Schristos       name = convert_utf8 (name);
70775fd0b74Schristos     }
70875fd0b74Schristos 
709*e992f068Schristos   if (info != NULL && info->elfinfo && with_symbol_versions)
710*e992f068Schristos     {
711*e992f068Schristos       const char *version_string;
712*e992f068Schristos       bool hidden;
713*e992f068Schristos 
714*e992f068Schristos       version_string
715*e992f068Schristos 	= bfd_get_symbol_version_string (abfd, &info->elfinfo->symbol,
716*e992f068Schristos 					 false, &hidden);
717*e992f068Schristos       if (version_string && version_string[0])
718*e992f068Schristos 	{
719*e992f068Schristos 	  const char *at = "@@";
720*e992f068Schristos 	  if (hidden || bfd_is_und_section (info->elfinfo->symbol.section))
721*e992f068Schristos 	    at = "@";
722*e992f068Schristos 	  alloc = reconcat (alloc, name, at, version_string, NULL);
723*e992f068Schristos 	  if (alloc != NULL)
724*e992f068Schristos 	    name = alloc;
725*e992f068Schristos 	}
726*e992f068Schristos     }
72775fd0b74Schristos   printf (form, name);
728*e992f068Schristos   if (atver)
729*e992f068Schristos     *atver = '@';
730*e992f068Schristos   free (alloc);
73175fd0b74Schristos }
73275fd0b74Schristos 
73375fd0b74Schristos static void
print_symdef_entry(bfd * abfd)73475fd0b74Schristos print_symdef_entry (bfd *abfd)
73575fd0b74Schristos {
73675fd0b74Schristos   symindex idx = BFD_NO_MORE_SYMBOLS;
73775fd0b74Schristos   carsym *thesym;
738*e992f068Schristos   bool everprinted = false;
73975fd0b74Schristos 
74075fd0b74Schristos   for (idx = bfd_get_next_mapent (abfd, idx, &thesym);
74175fd0b74Schristos        idx != BFD_NO_MORE_SYMBOLS;
74275fd0b74Schristos        idx = bfd_get_next_mapent (abfd, idx, &thesym))
74375fd0b74Schristos     {
74475fd0b74Schristos       bfd *elt;
74575fd0b74Schristos       if (!everprinted)
74675fd0b74Schristos 	{
74775fd0b74Schristos 	  printf (_("\nArchive index:\n"));
748*e992f068Schristos 	  everprinted = true;
74975fd0b74Schristos 	}
75075fd0b74Schristos       elt = bfd_get_elt_at_index (abfd, idx);
75175fd0b74Schristos       if (elt == NULL)
75275fd0b74Schristos 	bfd_fatal ("bfd_get_elt_at_index");
75375fd0b74Schristos       if (thesym->name != (char *) NULL)
75475fd0b74Schristos 	{
755*e992f068Schristos 	  print_symname ("%s", NULL, thesym->name, abfd);
75675fd0b74Schristos 	  printf (" in %s\n", bfd_get_filename (elt));
75775fd0b74Schristos 	}
75875fd0b74Schristos     }
75975fd0b74Schristos }
76075fd0b74Schristos 
761012573ebSchristos 
762012573ebSchristos /* True when we can report missing plugin error.  */
763*e992f068Schristos bool report_plugin_err = true;
764012573ebSchristos 
76575fd0b74Schristos /* Choose which symbol entries to print;
76675fd0b74Schristos    compact them downward to get rid of the rest.
76775fd0b74Schristos    Return the number of symbols to be printed.  */
76875fd0b74Schristos 
76975fd0b74Schristos static long
filter_symbols(bfd * abfd,bool is_dynamic,void * minisyms,long symcount,unsigned int size)770*e992f068Schristos filter_symbols (bfd *abfd, bool is_dynamic, void *minisyms,
77175fd0b74Schristos 		long symcount, unsigned int size)
77275fd0b74Schristos {
77375fd0b74Schristos   bfd_byte *from, *fromend, *to;
77475fd0b74Schristos   asymbol *store;
77575fd0b74Schristos 
77675fd0b74Schristos   store = bfd_make_empty_symbol (abfd);
77775fd0b74Schristos   if (store == NULL)
77875fd0b74Schristos     bfd_fatal (bfd_get_filename (abfd));
77975fd0b74Schristos 
78075fd0b74Schristos   from = (bfd_byte *) minisyms;
78175fd0b74Schristos   fromend = from + symcount * size;
78275fd0b74Schristos   to = (bfd_byte *) minisyms;
78375fd0b74Schristos 
78475fd0b74Schristos   for (; from < fromend; from += size)
78575fd0b74Schristos     {
78675fd0b74Schristos       int keep = 0;
78775fd0b74Schristos       asymbol *sym;
78875fd0b74Schristos 
78975fd0b74Schristos       PROGRESS (1);
79075fd0b74Schristos 
79175fd0b74Schristos       sym = bfd_minisymbol_to_symbol (abfd, is_dynamic, (const void *) from, store);
79275fd0b74Schristos       if (sym == NULL)
79375fd0b74Schristos 	bfd_fatal (bfd_get_filename (abfd));
79475fd0b74Schristos 
795*e992f068Schristos       if (sym->name != NULL
796*e992f068Schristos 	  && sym->name[0] == '_'
797ede78133Schristos 	  && sym->name[1] == '_'
798012573ebSchristos 	  && strcmp (sym->name + (sym->name[2] == '_'), "__gnu_lto_slim") == 0
799012573ebSchristos 	  && report_plugin_err)
800012573ebSchristos 	{
801*e992f068Schristos 	  report_plugin_err = false;
80275fd0b74Schristos 	  non_fatal (_("%s: plugin needed to handle lto object"),
80375fd0b74Schristos 		     bfd_get_filename (abfd));
804012573ebSchristos 	}
80575fd0b74Schristos 
80675fd0b74Schristos       if (undefined_only)
80775fd0b74Schristos 	keep = bfd_is_und_section (sym->section);
80875fd0b74Schristos       else if (external_only)
80975fd0b74Schristos 	/* PR binutls/12753: Unique symbols are global too.  */
81075fd0b74Schristos 	keep = ((sym->flags & (BSF_GLOBAL
81175fd0b74Schristos 			       | BSF_WEAK
81275fd0b74Schristos 			       | BSF_GNU_UNIQUE)) != 0
81375fd0b74Schristos 		|| bfd_is_und_section (sym->section)
81475fd0b74Schristos 		|| bfd_is_com_section (sym->section));
815*e992f068Schristos       else if (non_weak)
816*e992f068Schristos 	keep = ((sym->flags & BSF_WEAK) == 0);
81775fd0b74Schristos       else
81875fd0b74Schristos 	keep = 1;
81975fd0b74Schristos 
82075fd0b74Schristos       if (keep
82175fd0b74Schristos 	  && ! print_debug_syms
82275fd0b74Schristos 	  && (sym->flags & BSF_DEBUGGING) != 0)
82375fd0b74Schristos 	keep = 0;
82475fd0b74Schristos 
82575fd0b74Schristos       if (keep
82675fd0b74Schristos 	  && sort_by_size
82775fd0b74Schristos 	  && (bfd_is_abs_section (sym->section)
82875fd0b74Schristos 	      || bfd_is_und_section (sym->section)))
82975fd0b74Schristos 	keep = 0;
83075fd0b74Schristos 
83175fd0b74Schristos       if (keep
83275fd0b74Schristos 	  && defined_only)
83375fd0b74Schristos 	{
83475fd0b74Schristos 	  if (bfd_is_und_section (sym->section))
83575fd0b74Schristos 	    keep = 0;
83675fd0b74Schristos 	}
83775fd0b74Schristos 
83875fd0b74Schristos       if (keep
83975fd0b74Schristos 	  && bfd_is_target_special_symbol (abfd, sym)
84075fd0b74Schristos 	  && ! allow_special_symbols)
84175fd0b74Schristos 	keep = 0;
84275fd0b74Schristos 
84375fd0b74Schristos       if (keep)
84475fd0b74Schristos 	{
84575fd0b74Schristos 	  if (to != from)
84675fd0b74Schristos 	    memcpy (to, from, size);
84775fd0b74Schristos 	  to += size;
84875fd0b74Schristos 	}
84975fd0b74Schristos     }
85075fd0b74Schristos 
85175fd0b74Schristos   return (to - (bfd_byte *) minisyms) / size;
85275fd0b74Schristos }
85375fd0b74Schristos 
85475fd0b74Schristos /* These globals are used to pass information into the sorting
85575fd0b74Schristos    routines.  */
85675fd0b74Schristos static bfd *sort_bfd;
857*e992f068Schristos static bool sort_dynamic;
85875fd0b74Schristos static asymbol *sort_x;
85975fd0b74Schristos static asymbol *sort_y;
86075fd0b74Schristos 
86175fd0b74Schristos /* Symbol-sorting predicates */
86275fd0b74Schristos #define valueof(x) ((x)->section->vma + (x)->value)
86375fd0b74Schristos 
86475fd0b74Schristos /* Numeric sorts.  Undefined symbols are always considered "less than"
86575fd0b74Schristos    defined symbols with zero values.  Common symbols are not treated
86675fd0b74Schristos    specially -- i.e., their sizes are used as their "values".  */
86775fd0b74Schristos 
86875fd0b74Schristos static int
non_numeric_forward(const void * P_x,const void * P_y)86975fd0b74Schristos non_numeric_forward (const void *P_x, const void *P_y)
87075fd0b74Schristos {
87175fd0b74Schristos   asymbol *x, *y;
87275fd0b74Schristos   const char *xn, *yn;
87375fd0b74Schristos 
87475fd0b74Schristos   x = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_x, sort_x);
87575fd0b74Schristos   y = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_y, sort_y);
87675fd0b74Schristos   if (x == NULL || y == NULL)
87775fd0b74Schristos     bfd_fatal (bfd_get_filename (sort_bfd));
87875fd0b74Schristos 
87975fd0b74Schristos   xn = bfd_asymbol_name (x);
88075fd0b74Schristos   yn = bfd_asymbol_name (y);
88175fd0b74Schristos 
88275fd0b74Schristos   if (yn == NULL)
88375fd0b74Schristos     return xn != NULL;
88475fd0b74Schristos   if (xn == NULL)
88575fd0b74Schristos     return -1;
88675fd0b74Schristos 
88775fd0b74Schristos   /* Solaris 2.5 has a bug in strcoll.
88875fd0b74Schristos      strcoll returns invalid values when confronted with empty strings.  */
88975fd0b74Schristos   if (*yn == '\0')
89075fd0b74Schristos     return *xn != '\0';
89175fd0b74Schristos   if (*xn == '\0')
89275fd0b74Schristos     return -1;
89375fd0b74Schristos 
89475fd0b74Schristos   return strcoll (xn, yn);
89575fd0b74Schristos }
89675fd0b74Schristos 
89775fd0b74Schristos static int
non_numeric_reverse(const void * x,const void * y)89875fd0b74Schristos non_numeric_reverse (const void *x, const void *y)
89975fd0b74Schristos {
90075fd0b74Schristos   return - non_numeric_forward (x, y);
90175fd0b74Schristos }
90275fd0b74Schristos 
90375fd0b74Schristos static int
numeric_forward(const void * P_x,const void * P_y)90475fd0b74Schristos numeric_forward (const void *P_x, const void *P_y)
90575fd0b74Schristos {
90675fd0b74Schristos   asymbol *x, *y;
90775fd0b74Schristos   asection *xs, *ys;
90875fd0b74Schristos 
90975fd0b74Schristos   x = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_x, sort_x);
91075fd0b74Schristos   y =  bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_y, sort_y);
91175fd0b74Schristos   if (x == NULL || y == NULL)
91275fd0b74Schristos     bfd_fatal (bfd_get_filename (sort_bfd));
91375fd0b74Schristos 
914012573ebSchristos   xs = bfd_asymbol_section (x);
915012573ebSchristos   ys = bfd_asymbol_section (y);
91675fd0b74Schristos 
91775fd0b74Schristos   if (bfd_is_und_section (xs))
91875fd0b74Schristos     {
91975fd0b74Schristos       if (! bfd_is_und_section (ys))
92075fd0b74Schristos 	return -1;
92175fd0b74Schristos     }
92275fd0b74Schristos   else if (bfd_is_und_section (ys))
92375fd0b74Schristos     return 1;
92475fd0b74Schristos   else if (valueof (x) != valueof (y))
92575fd0b74Schristos     return valueof (x) < valueof (y) ? -1 : 1;
92675fd0b74Schristos 
92775fd0b74Schristos   return non_numeric_forward (P_x, P_y);
92875fd0b74Schristos }
92975fd0b74Schristos 
93075fd0b74Schristos static int
numeric_reverse(const void * x,const void * y)93175fd0b74Schristos numeric_reverse (const void *x, const void *y)
93275fd0b74Schristos {
93375fd0b74Schristos   return - numeric_forward (x, y);
93475fd0b74Schristos }
93575fd0b74Schristos 
93675fd0b74Schristos static int (*(sorters[2][2])) (const void *, const void *) =
93775fd0b74Schristos {
93875fd0b74Schristos   { non_numeric_forward, non_numeric_reverse },
93975fd0b74Schristos   { numeric_forward, numeric_reverse }
94075fd0b74Schristos };
94175fd0b74Schristos 
94275fd0b74Schristos /* This sort routine is used by sort_symbols_by_size.  It is similar
94375fd0b74Schristos    to numeric_forward, but when symbols have the same value it sorts
94475fd0b74Schristos    by section VMA.  This simplifies the sort_symbols_by_size code
94575fd0b74Schristos    which handles symbols at the end of sections.  Also, this routine
94675fd0b74Schristos    tries to sort file names before other symbols with the same value.
94775fd0b74Schristos    That will make the file name have a zero size, which will make
94875fd0b74Schristos    sort_symbols_by_size choose the non file name symbol, leading to
94975fd0b74Schristos    more meaningful output.  For similar reasons, this code sorts
95075fd0b74Schristos    gnu_compiled_* and gcc2_compiled before other symbols with the same
95175fd0b74Schristos    value.  */
95275fd0b74Schristos 
95375fd0b74Schristos static int
size_forward1(const void * P_x,const void * P_y)95475fd0b74Schristos size_forward1 (const void *P_x, const void *P_y)
95575fd0b74Schristos {
95675fd0b74Schristos   asymbol *x, *y;
95775fd0b74Schristos   asection *xs, *ys;
95875fd0b74Schristos   const char *xn, *yn;
95975fd0b74Schristos   size_t xnl, ynl;
96075fd0b74Schristos   int xf, yf;
96175fd0b74Schristos 
96275fd0b74Schristos   x = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_x, sort_x);
96375fd0b74Schristos   y = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_y, sort_y);
96475fd0b74Schristos   if (x == NULL || y == NULL)
96575fd0b74Schristos     bfd_fatal (bfd_get_filename (sort_bfd));
96675fd0b74Schristos 
967012573ebSchristos   xs = bfd_asymbol_section (x);
968012573ebSchristos   ys = bfd_asymbol_section (y);
96975fd0b74Schristos 
97075fd0b74Schristos   if (bfd_is_und_section (xs))
97175fd0b74Schristos     abort ();
97275fd0b74Schristos   if (bfd_is_und_section (ys))
97375fd0b74Schristos     abort ();
97475fd0b74Schristos 
97575fd0b74Schristos   if (valueof (x) != valueof (y))
97675fd0b74Schristos     return valueof (x) < valueof (y) ? -1 : 1;
97775fd0b74Schristos 
97875fd0b74Schristos   if (xs->vma != ys->vma)
97975fd0b74Schristos     return xs->vma < ys->vma ? -1 : 1;
98075fd0b74Schristos 
98175fd0b74Schristos   xn = bfd_asymbol_name (x);
98275fd0b74Schristos   yn = bfd_asymbol_name (y);
98375fd0b74Schristos   xnl = strlen (xn);
98475fd0b74Schristos   ynl = strlen (yn);
98575fd0b74Schristos 
98675fd0b74Schristos   /* The symbols gnu_compiled and gcc2_compiled convey even less
98775fd0b74Schristos      information than the file name, so sort them out first.  */
98875fd0b74Schristos 
98975fd0b74Schristos   xf = (strstr (xn, "gnu_compiled") != NULL
99075fd0b74Schristos 	|| strstr (xn, "gcc2_compiled") != NULL);
99175fd0b74Schristos   yf = (strstr (yn, "gnu_compiled") != NULL
99275fd0b74Schristos 	|| strstr (yn, "gcc2_compiled") != NULL);
99375fd0b74Schristos 
99475fd0b74Schristos   if (xf && ! yf)
99575fd0b74Schristos     return -1;
99675fd0b74Schristos   if (! xf && yf)
99775fd0b74Schristos     return 1;
99875fd0b74Schristos 
99975fd0b74Schristos   /* We use a heuristic for the file name.  It may not work on non
100075fd0b74Schristos      Unix systems, but it doesn't really matter; the only difference
100175fd0b74Schristos      is precisely which symbol names get printed.  */
100275fd0b74Schristos 
100375fd0b74Schristos #define file_symbol(s, sn, snl)			\
100475fd0b74Schristos   (((s)->flags & BSF_FILE) != 0			\
1005ede78133Schristos    || ((snl) > 2				\
1006ede78133Schristos        && (sn)[(snl) - 2] == '.'		\
100775fd0b74Schristos        && ((sn)[(snl) - 1] == 'o'		\
100875fd0b74Schristos 	   || (sn)[(snl) - 1] == 'a')))
100975fd0b74Schristos 
101075fd0b74Schristos   xf = file_symbol (x, xn, xnl);
101175fd0b74Schristos   yf = file_symbol (y, yn, ynl);
101275fd0b74Schristos 
101375fd0b74Schristos   if (xf && ! yf)
101475fd0b74Schristos     return -1;
101575fd0b74Schristos   if (! xf && yf)
101675fd0b74Schristos     return 1;
101775fd0b74Schristos 
101875fd0b74Schristos   return non_numeric_forward (P_x, P_y);
101975fd0b74Schristos }
102075fd0b74Schristos 
102175fd0b74Schristos /* This sort routine is used by sort_symbols_by_size.  It is sorting
102275fd0b74Schristos    an array of size_sym structures into size order.  */
102375fd0b74Schristos 
102475fd0b74Schristos static int
size_forward2(const void * P_x,const void * P_y)102575fd0b74Schristos size_forward2 (const void *P_x, const void *P_y)
102675fd0b74Schristos {
102775fd0b74Schristos   const struct size_sym *x = (const struct size_sym *) P_x;
102875fd0b74Schristos   const struct size_sym *y = (const struct size_sym *) P_y;
102975fd0b74Schristos 
103075fd0b74Schristos   if (x->size < y->size)
103175fd0b74Schristos     return reverse_sort ? 1 : -1;
103275fd0b74Schristos   else if (x->size > y->size)
103375fd0b74Schristos     return reverse_sort ? -1 : 1;
103475fd0b74Schristos   else
103575fd0b74Schristos     return sorters[0][reverse_sort] (x->minisym, y->minisym);
103675fd0b74Schristos }
103775fd0b74Schristos 
103875fd0b74Schristos /* Sort the symbols by size.  ELF provides a size but for other formats
103975fd0b74Schristos    we have to make a guess by assuming that the difference between the
104075fd0b74Schristos    address of a symbol and the address of the next higher symbol is the
104175fd0b74Schristos    size.  */
104275fd0b74Schristos 
104375fd0b74Schristos static long
sort_symbols_by_size(bfd * abfd,bool is_dynamic,void * minisyms,long symcount,unsigned int size,struct size_sym ** symsizesp)1044*e992f068Schristos sort_symbols_by_size (bfd *abfd, bool is_dynamic, void *minisyms,
104575fd0b74Schristos 		      long symcount, unsigned int size,
104675fd0b74Schristos 		      struct size_sym **symsizesp)
104775fd0b74Schristos {
104875fd0b74Schristos   struct size_sym *symsizes;
104975fd0b74Schristos   bfd_byte *from, *fromend;
105075fd0b74Schristos   asymbol *sym = NULL;
105175fd0b74Schristos   asymbol *store_sym, *store_next;
105275fd0b74Schristos 
105375fd0b74Schristos   qsort (minisyms, symcount, size, size_forward1);
105475fd0b74Schristos 
105575fd0b74Schristos   /* We are going to return a special set of symbols and sizes to
105675fd0b74Schristos      print.  */
105775fd0b74Schristos   symsizes = (struct size_sym *) xmalloc (symcount * sizeof (struct size_sym));
105875fd0b74Schristos   *symsizesp = symsizes;
105975fd0b74Schristos 
106075fd0b74Schristos   /* Note that filter_symbols has already removed all absolute and
106175fd0b74Schristos      undefined symbols.  Here we remove all symbols whose size winds
106275fd0b74Schristos      up as zero.  */
106375fd0b74Schristos   from = (bfd_byte *) minisyms;
106475fd0b74Schristos   fromend = from + symcount * size;
106575fd0b74Schristos 
106675fd0b74Schristos   store_sym = sort_x;
106775fd0b74Schristos   store_next = sort_y;
106875fd0b74Schristos 
106975fd0b74Schristos   if (from < fromend)
107075fd0b74Schristos     {
107175fd0b74Schristos       sym = bfd_minisymbol_to_symbol (abfd, is_dynamic, (const void *) from,
107275fd0b74Schristos 				      store_sym);
107375fd0b74Schristos       if (sym == NULL)
107475fd0b74Schristos 	bfd_fatal (bfd_get_filename (abfd));
107575fd0b74Schristos     }
107675fd0b74Schristos 
107775fd0b74Schristos   for (; from < fromend; from += size)
107875fd0b74Schristos     {
107975fd0b74Schristos       asymbol *next;
108075fd0b74Schristos       asection *sec;
108175fd0b74Schristos       bfd_vma sz;
108275fd0b74Schristos       asymbol *temp;
108375fd0b74Schristos 
108475fd0b74Schristos       if (from + size < fromend)
108575fd0b74Schristos 	{
108675fd0b74Schristos 	  next = bfd_minisymbol_to_symbol (abfd,
108775fd0b74Schristos 					   is_dynamic,
108875fd0b74Schristos 					   (const void *) (from + size),
108975fd0b74Schristos 					   store_next);
109075fd0b74Schristos 	  if (next == NULL)
109175fd0b74Schristos 	    bfd_fatal (bfd_get_filename (abfd));
109275fd0b74Schristos 	}
109375fd0b74Schristos       else
109475fd0b74Schristos 	next = NULL;
109575fd0b74Schristos 
1096012573ebSchristos       sec = bfd_asymbol_section (sym);
109775fd0b74Schristos 
1098ede78133Schristos       /* Synthetic symbols don't have a full type set of data available, thus
1099ede78133Schristos 	 we can't rely on that information for the symbol size.  Ditto for
1100ede78133Schristos 	 bfd/section.c:global_syms like *ABS*.  */
1101ede78133Schristos       if ((sym->flags & (BSF_SECTION_SYM | BSF_SYNTHETIC)) == 0
1102ede78133Schristos 	  && bfd_get_flavour (abfd) == bfd_target_elf_flavour)
110375fd0b74Schristos 	sz = ((elf_symbol_type *) sym)->internal_elf_sym.st_size;
1104ede78133Schristos       else if ((sym->flags & (BSF_SECTION_SYM | BSF_SYNTHETIC)) == 0
1105ede78133Schristos 	       && bfd_is_com_section (sec))
110675fd0b74Schristos 	sz = sym->value;
110775fd0b74Schristos       else
110875fd0b74Schristos 	{
110975fd0b74Schristos 	  if (from + size < fromend
1110012573ebSchristos 	      && sec == bfd_asymbol_section (next))
111175fd0b74Schristos 	    sz = valueof (next) - valueof (sym);
111275fd0b74Schristos 	  else
1113012573ebSchristos 	    sz = (bfd_section_vma (sec)
1114012573ebSchristos 		  + bfd_section_size (sec)
111575fd0b74Schristos 		  - valueof (sym));
111675fd0b74Schristos 	}
111775fd0b74Schristos 
111875fd0b74Schristos       if (sz != 0)
111975fd0b74Schristos 	{
112075fd0b74Schristos 	  symsizes->minisym = (const void *) from;
112175fd0b74Schristos 	  symsizes->size = sz;
112275fd0b74Schristos 	  ++symsizes;
112375fd0b74Schristos 	}
112475fd0b74Schristos 
112575fd0b74Schristos       sym = next;
112675fd0b74Schristos 
112775fd0b74Schristos       temp = store_sym;
112875fd0b74Schristos       store_sym = store_next;
112975fd0b74Schristos       store_next = temp;
113075fd0b74Schristos     }
113175fd0b74Schristos 
113275fd0b74Schristos   symcount = symsizes - *symsizesp;
113375fd0b74Schristos 
113475fd0b74Schristos   /* We must now sort again by size.  */
113575fd0b74Schristos   qsort ((void *) *symsizesp, symcount, sizeof (struct size_sym), size_forward2);
113675fd0b74Schristos 
113775fd0b74Schristos   return symcount;
113875fd0b74Schristos }
113975fd0b74Schristos 
114075fd0b74Schristos /* This function is used to get the relocs for a particular section.
114175fd0b74Schristos    It is called via bfd_map_over_sections.  */
114275fd0b74Schristos 
114375fd0b74Schristos static void
get_relocs(bfd * abfd,asection * sec,void * dataarg)114475fd0b74Schristos get_relocs (bfd *abfd, asection *sec, void *dataarg)
114575fd0b74Schristos {
114675fd0b74Schristos   struct get_relocs_info *data = (struct get_relocs_info *) dataarg;
114775fd0b74Schristos 
114875fd0b74Schristos   *data->secs = sec;
114975fd0b74Schristos 
115075fd0b74Schristos   if ((sec->flags & SEC_RELOC) == 0)
115175fd0b74Schristos     {
115275fd0b74Schristos       *data->relocs = NULL;
115375fd0b74Schristos       *data->relcount = 0;
115475fd0b74Schristos     }
115575fd0b74Schristos   else
115675fd0b74Schristos     {
115775fd0b74Schristos       long relsize;
115875fd0b74Schristos 
115975fd0b74Schristos       relsize = bfd_get_reloc_upper_bound (abfd, sec);
116075fd0b74Schristos       if (relsize < 0)
116175fd0b74Schristos 	bfd_fatal (bfd_get_filename (abfd));
116275fd0b74Schristos 
116375fd0b74Schristos       *data->relocs = (arelent **) xmalloc (relsize);
116475fd0b74Schristos       *data->relcount = bfd_canonicalize_reloc (abfd, sec, *data->relocs,
116575fd0b74Schristos 						data->syms);
116675fd0b74Schristos       if (*data->relcount < 0)
116775fd0b74Schristos 	bfd_fatal (bfd_get_filename (abfd));
116875fd0b74Schristos     }
116975fd0b74Schristos 
117075fd0b74Schristos   ++data->secs;
117175fd0b74Schristos   ++data->relocs;
117275fd0b74Schristos   ++data->relcount;
117375fd0b74Schristos }
117475fd0b74Schristos 
117575fd0b74Schristos /* Print a single symbol.  */
117675fd0b74Schristos 
117775fd0b74Schristos static void
print_symbol(bfd * abfd,asymbol * sym,bfd_vma ssize,bfd * archive_bfd)117875fd0b74Schristos print_symbol (bfd *        abfd,
117975fd0b74Schristos 	      asymbol *    sym,
118075fd0b74Schristos 	      bfd_vma      ssize,
1181ede78133Schristos 	      bfd *        archive_bfd)
118275fd0b74Schristos {
118375fd0b74Schristos   symbol_info syminfo;
118475fd0b74Schristos   struct extended_symbol_info info;
118575fd0b74Schristos 
118675fd0b74Schristos   PROGRESS (1);
118775fd0b74Schristos 
118875fd0b74Schristos   format->print_symbol_filename (archive_bfd, abfd);
118975fd0b74Schristos 
119075fd0b74Schristos   bfd_get_symbol_info (abfd, sym, &syminfo);
119175fd0b74Schristos 
1192*e992f068Schristos   /* PR 22967 - Distinguish between local and global ifunc symbols.  */
1193*e992f068Schristos   if (syminfo.type == 'i'
1194*e992f068Schristos       && sym->flags & BSF_GNU_INDIRECT_FUNCTION)
1195*e992f068Schristos     {
1196*e992f068Schristos       if (ifunc_type_chars == NULL || ifunc_type_chars[0] == 0)
1197*e992f068Schristos 	; /* Change nothing.  */
1198*e992f068Schristos       else if (sym->flags & BSF_GLOBAL)
1199*e992f068Schristos 	syminfo.type = ifunc_type_chars[0];
1200*e992f068Schristos       else if (ifunc_type_chars[1] != 0)
1201*e992f068Schristos 	syminfo.type = ifunc_type_chars[1];
1202*e992f068Schristos     }
1203*e992f068Schristos 
120475fd0b74Schristos   info.sinfo = &syminfo;
120575fd0b74Schristos   info.ssize = ssize;
1206ede78133Schristos   /* Synthetic symbols do not have a full symbol type set of data available.
1207ede78133Schristos      Nor do bfd/section.c:global_syms like *ABS*.  */
1208ede78133Schristos   if ((sym->flags & (BSF_SECTION_SYM | BSF_SYNTHETIC)) != 0)
120975fd0b74Schristos     {
121075fd0b74Schristos       info.elfinfo = NULL;
121175fd0b74Schristos       info.coffinfo = NULL;
121275fd0b74Schristos     }
121375fd0b74Schristos   else
121475fd0b74Schristos     {
1215*e992f068Schristos       info.elfinfo = elf_symbol_from (sym);
121675fd0b74Schristos       info.coffinfo = coff_symbol_from (sym);
121775fd0b74Schristos     }
121875fd0b74Schristos 
121975fd0b74Schristos   format->print_symbol_info (&info, abfd);
122075fd0b74Schristos 
122175fd0b74Schristos   if (line_numbers)
122275fd0b74Schristos     {
122375fd0b74Schristos       static asymbol **syms;
122475fd0b74Schristos       static long symcount;
122575fd0b74Schristos       const char *filename, *functionname;
122675fd0b74Schristos       unsigned int lineno;
122775fd0b74Schristos 
122875fd0b74Schristos       /* We need to get the canonical symbols in order to call
122975fd0b74Schristos          bfd_find_nearest_line.  This is inefficient, but, then, you
123075fd0b74Schristos          don't have to use --line-numbers.  */
123175fd0b74Schristos       if (abfd != lineno_cache_bfd && syms != NULL)
123275fd0b74Schristos 	{
123375fd0b74Schristos 	  free (syms);
123475fd0b74Schristos 	  syms = NULL;
123575fd0b74Schristos 	}
123675fd0b74Schristos       if (syms == NULL)
123775fd0b74Schristos 	{
123875fd0b74Schristos 	  long symsize;
123975fd0b74Schristos 
124075fd0b74Schristos 	  symsize = bfd_get_symtab_upper_bound (abfd);
124175fd0b74Schristos 	  if (symsize < 0)
124275fd0b74Schristos 	    bfd_fatal (bfd_get_filename (abfd));
124375fd0b74Schristos 	  syms = (asymbol **) xmalloc (symsize);
124475fd0b74Schristos 	  symcount = bfd_canonicalize_symtab (abfd, syms);
124575fd0b74Schristos 	  if (symcount < 0)
124675fd0b74Schristos 	    bfd_fatal (bfd_get_filename (abfd));
124775fd0b74Schristos 	  lineno_cache_bfd = abfd;
124875fd0b74Schristos 	}
124975fd0b74Schristos 
1250012573ebSchristos       if (bfd_is_und_section (bfd_asymbol_section (sym)))
125175fd0b74Schristos 	{
125275fd0b74Schristos 	  static asection **secs;
125375fd0b74Schristos 	  static arelent ***relocs;
125475fd0b74Schristos 	  static long *relcount;
125575fd0b74Schristos 	  static unsigned int seccount;
125675fd0b74Schristos 	  unsigned int i;
125775fd0b74Schristos 	  const char *symname;
125875fd0b74Schristos 
125975fd0b74Schristos 	  /* For an undefined symbol, we try to find a reloc for the
126075fd0b74Schristos              symbol, and print the line number of the reloc.  */
126175fd0b74Schristos 	  if (abfd != lineno_cache_rel_bfd && relocs != NULL)
126275fd0b74Schristos 	    {
126375fd0b74Schristos 	      for (i = 0; i < seccount; i++)
126475fd0b74Schristos 		if (relocs[i] != NULL)
126575fd0b74Schristos 		  free (relocs[i]);
126675fd0b74Schristos 	      free (secs);
126775fd0b74Schristos 	      free (relocs);
126875fd0b74Schristos 	      free (relcount);
126975fd0b74Schristos 	      secs = NULL;
127075fd0b74Schristos 	      relocs = NULL;
127175fd0b74Schristos 	      relcount = NULL;
127275fd0b74Schristos 	    }
127375fd0b74Schristos 
127475fd0b74Schristos 	  if (relocs == NULL)
127575fd0b74Schristos 	    {
127675fd0b74Schristos 	      struct get_relocs_info rinfo;
127775fd0b74Schristos 
127875fd0b74Schristos 	      seccount = bfd_count_sections (abfd);
127975fd0b74Schristos 
128075fd0b74Schristos 	      secs = (asection **) xmalloc (seccount * sizeof *secs);
128175fd0b74Schristos 	      relocs = (arelent ***) xmalloc (seccount * sizeof *relocs);
128275fd0b74Schristos 	      relcount = (long *) xmalloc (seccount * sizeof *relcount);
128375fd0b74Schristos 
128475fd0b74Schristos 	      rinfo.secs = secs;
128575fd0b74Schristos 	      rinfo.relocs = relocs;
128675fd0b74Schristos 	      rinfo.relcount = relcount;
128775fd0b74Schristos 	      rinfo.syms = syms;
128875fd0b74Schristos 	      bfd_map_over_sections (abfd, get_relocs, (void *) &rinfo);
128975fd0b74Schristos 	      lineno_cache_rel_bfd = abfd;
129075fd0b74Schristos 	    }
129175fd0b74Schristos 
129275fd0b74Schristos 	  symname = bfd_asymbol_name (sym);
129375fd0b74Schristos 	  for (i = 0; i < seccount; i++)
129475fd0b74Schristos 	    {
129575fd0b74Schristos 	      long j;
129675fd0b74Schristos 
129775fd0b74Schristos 	      for (j = 0; j < relcount[i]; j++)
129875fd0b74Schristos 		{
129975fd0b74Schristos 		  arelent *r;
130075fd0b74Schristos 
130175fd0b74Schristos 		  r = relocs[i][j];
130275fd0b74Schristos 		  if (r->sym_ptr_ptr != NULL
130375fd0b74Schristos 		      && (*r->sym_ptr_ptr)->section == sym->section
130475fd0b74Schristos 		      && (*r->sym_ptr_ptr)->value == sym->value
130575fd0b74Schristos 		      && strcmp (symname,
130675fd0b74Schristos 				 bfd_asymbol_name (*r->sym_ptr_ptr)) == 0
130775fd0b74Schristos 		      && bfd_find_nearest_line (abfd, secs[i], syms,
130875fd0b74Schristos 						r->address, &filename,
130975fd0b74Schristos 						&functionname, &lineno)
131075fd0b74Schristos 		      && filename != NULL)
131175fd0b74Schristos 		    {
131275fd0b74Schristos 		      /* We only print the first one we find.  */
131375fd0b74Schristos 		      printf ("\t%s:%u", filename, lineno);
131475fd0b74Schristos 		      i = seccount;
131575fd0b74Schristos 		      break;
131675fd0b74Schristos 		    }
131775fd0b74Schristos 		}
131875fd0b74Schristos 	    }
131975fd0b74Schristos 	}
1320012573ebSchristos       else if (bfd_asymbol_section (sym)->owner == abfd)
132175fd0b74Schristos 	{
132275fd0b74Schristos 	  if ((bfd_find_line (abfd, syms, sym, &filename, &lineno)
1323012573ebSchristos 	       || bfd_find_nearest_line (abfd, bfd_asymbol_section (sym),
132475fd0b74Schristos 					 syms, sym->value, &filename,
132575fd0b74Schristos 					 &functionname, &lineno))
132675fd0b74Schristos 	      && filename != NULL
132775fd0b74Schristos 	      && lineno != 0)
132875fd0b74Schristos 	    printf ("\t%s:%u", filename, lineno);
132975fd0b74Schristos 	}
133075fd0b74Schristos     }
133175fd0b74Schristos 
133275fd0b74Schristos   putchar ('\n');
133375fd0b74Schristos }
133475fd0b74Schristos 
133575fd0b74Schristos /* Print the symbols when sorting by size.  */
133675fd0b74Schristos 
133775fd0b74Schristos static void
print_size_symbols(bfd * abfd,bool is_dynamic,struct size_sym * symsizes,long symcount,bfd * archive_bfd)133875fd0b74Schristos print_size_symbols (bfd *abfd,
1339*e992f068Schristos 		    bool is_dynamic,
134075fd0b74Schristos 		    struct size_sym *symsizes,
134175fd0b74Schristos 		    long symcount,
134275fd0b74Schristos 		    bfd *archive_bfd)
134375fd0b74Schristos {
134475fd0b74Schristos   asymbol *store;
134575fd0b74Schristos   struct size_sym *from;
134675fd0b74Schristos   struct size_sym *fromend;
134775fd0b74Schristos 
134875fd0b74Schristos   store = bfd_make_empty_symbol (abfd);
134975fd0b74Schristos   if (store == NULL)
135075fd0b74Schristos     bfd_fatal (bfd_get_filename (abfd));
135175fd0b74Schristos 
135275fd0b74Schristos   from = symsizes;
135375fd0b74Schristos   fromend = from + symcount;
135475fd0b74Schristos 
135575fd0b74Schristos   for (; from < fromend; from++)
135675fd0b74Schristos     {
135775fd0b74Schristos       asymbol *sym;
135875fd0b74Schristos 
135975fd0b74Schristos       sym = bfd_minisymbol_to_symbol (abfd, is_dynamic, from->minisym, store);
136075fd0b74Schristos       if (sym == NULL)
136175fd0b74Schristos 	bfd_fatal (bfd_get_filename (abfd));
136275fd0b74Schristos 
1363ede78133Schristos       print_symbol (abfd, sym, from->size, archive_bfd);
136475fd0b74Schristos     }
136575fd0b74Schristos }
136675fd0b74Schristos 
136775fd0b74Schristos 
136875fd0b74Schristos /* Print the symbols of ABFD that are held in MINISYMS.
136975fd0b74Schristos 
137075fd0b74Schristos    If ARCHIVE_BFD is non-NULL, it is the archive containing ABFD.
137175fd0b74Schristos 
1372ede78133Schristos    SYMCOUNT is the number of symbols in MINISYMS.
137375fd0b74Schristos 
137475fd0b74Schristos    SIZE is the size of a symbol in MINISYMS.  */
137575fd0b74Schristos 
137675fd0b74Schristos static void
print_symbols(bfd * abfd,bool is_dynamic,void * minisyms,long symcount,unsigned int size,bfd * archive_bfd)137775fd0b74Schristos print_symbols (bfd *abfd,
1378*e992f068Schristos 	       bool is_dynamic,
137975fd0b74Schristos 	       void *minisyms,
138075fd0b74Schristos 	       long symcount,
138175fd0b74Schristos 	       unsigned int size,
138275fd0b74Schristos 	       bfd *archive_bfd)
138375fd0b74Schristos {
138475fd0b74Schristos   asymbol *store;
138575fd0b74Schristos   bfd_byte *from;
138675fd0b74Schristos   bfd_byte *fromend;
138775fd0b74Schristos 
138875fd0b74Schristos   store = bfd_make_empty_symbol (abfd);
138975fd0b74Schristos   if (store == NULL)
139075fd0b74Schristos     bfd_fatal (bfd_get_filename (abfd));
139175fd0b74Schristos 
139275fd0b74Schristos   from = (bfd_byte *) minisyms;
139375fd0b74Schristos   fromend = from + symcount * size;
139475fd0b74Schristos 
139575fd0b74Schristos   for (; from < fromend; from += size)
139675fd0b74Schristos     {
139775fd0b74Schristos       asymbol *sym;
139875fd0b74Schristos 
139975fd0b74Schristos       sym = bfd_minisymbol_to_symbol (abfd, is_dynamic, from, store);
140075fd0b74Schristos       if (sym == NULL)
140175fd0b74Schristos 	bfd_fatal (bfd_get_filename (abfd));
140275fd0b74Schristos 
1403ede78133Schristos       print_symbol (abfd, sym, (bfd_vma) 0, archive_bfd);
140475fd0b74Schristos     }
140575fd0b74Schristos }
140675fd0b74Schristos 
140775fd0b74Schristos /* If ARCHIVE_BFD is non-NULL, it is the archive containing ABFD.  */
140875fd0b74Schristos 
140975fd0b74Schristos static void
display_rel_file(bfd * abfd,bfd * archive_bfd)141075fd0b74Schristos display_rel_file (bfd *abfd, bfd *archive_bfd)
141175fd0b74Schristos {
141275fd0b74Schristos   long symcount;
141375fd0b74Schristos   void *minisyms;
141475fd0b74Schristos   unsigned int size;
141575fd0b74Schristos   struct size_sym *symsizes;
1416ede78133Schristos   asymbol *synthsyms = NULL;
141775fd0b74Schristos 
141875fd0b74Schristos   if (! dynamic)
141975fd0b74Schristos     {
142075fd0b74Schristos       if (!(bfd_get_file_flags (abfd) & HAS_SYMS))
142175fd0b74Schristos 	{
1422*e992f068Schristos 	  if (!quiet)
142375fd0b74Schristos 	    non_fatal (_("%s: no symbols"), bfd_get_filename (abfd));
142475fd0b74Schristos 	  return;
142575fd0b74Schristos 	}
142675fd0b74Schristos     }
142775fd0b74Schristos 
142875fd0b74Schristos   symcount = bfd_read_minisymbols (abfd, dynamic, &minisyms, &size);
142975fd0b74Schristos   if (symcount < 0)
143075fd0b74Schristos     {
143175fd0b74Schristos       if (dynamic && bfd_get_error () == bfd_error_no_symbols)
143275fd0b74Schristos 	{
1433*e992f068Schristos 	  if (!quiet)
143475fd0b74Schristos 	    non_fatal (_("%s: no symbols"), bfd_get_filename (abfd));
143575fd0b74Schristos 	  return;
143675fd0b74Schristos 	}
143775fd0b74Schristos 
143875fd0b74Schristos       bfd_fatal (bfd_get_filename (abfd));
143975fd0b74Schristos     }
144075fd0b74Schristos 
144175fd0b74Schristos   if (symcount == 0)
144275fd0b74Schristos     {
1443*e992f068Schristos       if (!quiet)
144475fd0b74Schristos 	non_fatal (_("%s: no symbols"), bfd_get_filename (abfd));
144575fd0b74Schristos       return;
144675fd0b74Schristos     }
144775fd0b74Schristos 
144875fd0b74Schristos   if (show_synthetic && size == sizeof (asymbol *))
144975fd0b74Schristos     {
145075fd0b74Schristos       asymbol **static_syms = NULL;
145175fd0b74Schristos       asymbol **dyn_syms = NULL;
145275fd0b74Schristos       long static_count = 0;
145375fd0b74Schristos       long dyn_count = 0;
1454ede78133Schristos       long synth_count;
145575fd0b74Schristos 
145675fd0b74Schristos       if (dynamic)
145775fd0b74Schristos 	{
145875fd0b74Schristos 	  dyn_count = symcount;
145975fd0b74Schristos 	  dyn_syms = (asymbol **) minisyms;
146075fd0b74Schristos 	}
146175fd0b74Schristos       else
146275fd0b74Schristos 	{
146375fd0b74Schristos 	  long storage = bfd_get_dynamic_symtab_upper_bound (abfd);
146475fd0b74Schristos 
146575fd0b74Schristos 	  static_count = symcount;
146675fd0b74Schristos 	  static_syms = (asymbol **) minisyms;
146775fd0b74Schristos 
146875fd0b74Schristos 	  if (storage > 0)
146975fd0b74Schristos 	    {
147075fd0b74Schristos 	      dyn_syms = (asymbol **) xmalloc (storage);
147175fd0b74Schristos 	      dyn_count = bfd_canonicalize_dynamic_symtab (abfd, dyn_syms);
147275fd0b74Schristos 	      if (dyn_count < 0)
147375fd0b74Schristos 		bfd_fatal (bfd_get_filename (abfd));
147475fd0b74Schristos 	    }
147575fd0b74Schristos 	}
147675fd0b74Schristos 
147775fd0b74Schristos       synth_count = bfd_get_synthetic_symtab (abfd, static_count, static_syms,
147875fd0b74Schristos 					      dyn_count, dyn_syms, &synthsyms);
147975fd0b74Schristos       if (synth_count > 0)
148075fd0b74Schristos 	{
148175fd0b74Schristos 	  asymbol **symp;
148275fd0b74Schristos 	  long i;
148375fd0b74Schristos 
1484012573ebSchristos 	  minisyms = xrealloc (minisyms,
1485012573ebSchristos 			       (symcount + synth_count + 1) * sizeof (*symp));
1486012573ebSchristos 	  symp = (asymbol **) minisyms + symcount;
148775fd0b74Schristos 	  for (i = 0; i < synth_count; i++)
148875fd0b74Schristos 	    *symp++ = synthsyms + i;
148975fd0b74Schristos 	  *symp = 0;
149075fd0b74Schristos 	  symcount += synth_count;
149175fd0b74Schristos 	}
1492012573ebSchristos       if (!dynamic && dyn_syms != NULL)
1493012573ebSchristos 	free (dyn_syms);
1494012573ebSchristos     }
1495012573ebSchristos 
1496012573ebSchristos   /* lto_slim_object is set to false when a bfd is loaded with a compiler
1497012573ebSchristos      LTO plugin.  */
1498012573ebSchristos   if (abfd->lto_slim_object)
1499012573ebSchristos     {
1500*e992f068Schristos       report_plugin_err = false;
1501012573ebSchristos       non_fatal (_("%s: plugin needed to handle lto object"),
1502012573ebSchristos 		 bfd_get_filename (abfd));
150375fd0b74Schristos     }
150475fd0b74Schristos 
150575fd0b74Schristos   /* Discard the symbols we don't want to print.
150675fd0b74Schristos      It's OK to do this in place; we'll free the storage anyway
150775fd0b74Schristos      (after printing).  */
150875fd0b74Schristos 
150975fd0b74Schristos   symcount = filter_symbols (abfd, dynamic, minisyms, symcount, size);
151075fd0b74Schristos 
151175fd0b74Schristos   symsizes = NULL;
151275fd0b74Schristos   if (! no_sort)
151375fd0b74Schristos     {
151475fd0b74Schristos       sort_bfd = abfd;
151575fd0b74Schristos       sort_dynamic = dynamic;
151675fd0b74Schristos       sort_x = bfd_make_empty_symbol (abfd);
151775fd0b74Schristos       sort_y = bfd_make_empty_symbol (abfd);
151875fd0b74Schristos       if (sort_x == NULL || sort_y == NULL)
151975fd0b74Schristos 	bfd_fatal (bfd_get_filename (abfd));
152075fd0b74Schristos 
152175fd0b74Schristos       if (! sort_by_size)
152275fd0b74Schristos 	qsort (minisyms, symcount, size,
152375fd0b74Schristos 	       sorters[sort_numerically][reverse_sort]);
152475fd0b74Schristos       else
152575fd0b74Schristos 	symcount = sort_symbols_by_size (abfd, dynamic, minisyms, symcount,
152675fd0b74Schristos 					 size, &symsizes);
152775fd0b74Schristos     }
152875fd0b74Schristos 
152975fd0b74Schristos   if (! sort_by_size)
1530ede78133Schristos     print_symbols (abfd, dynamic, minisyms, symcount, size, archive_bfd);
153175fd0b74Schristos   else
1532ede78133Schristos     print_size_symbols (abfd, dynamic, symsizes, symcount, archive_bfd);
153375fd0b74Schristos 
1534ede78133Schristos   if (synthsyms)
1535ede78133Schristos     free (synthsyms);
153675fd0b74Schristos   free (minisyms);
153775fd0b74Schristos   free (symsizes);
153875fd0b74Schristos }
153975fd0b74Schristos 
1540012573ebSchristos /* Construct a formatting string for printing symbol values.  */
1541012573ebSchristos 
1542012573ebSchristos static const char *
get_print_format(void)1543012573ebSchristos get_print_format (void)
1544012573ebSchristos {
1545012573ebSchristos   const char * padding;
1546*e992f068Schristos   if (print_format == FORMAT_POSIX || print_format == FORMAT_JUST_SYMBOLS)
1547012573ebSchristos     {
1548012573ebSchristos       /* POSIX compatible output does not have any padding.  */
1549012573ebSchristos       padding = "";
1550012573ebSchristos     }
1551012573ebSchristos   else if (print_width == 32)
1552012573ebSchristos     {
1553012573ebSchristos       padding ="08";
1554012573ebSchristos     }
1555012573ebSchristos   else /* print_width == 64 */
1556012573ebSchristos     {
1557012573ebSchristos       padding = "016";
1558012573ebSchristos     }
1559012573ebSchristos 
1560012573ebSchristos   const char * radix = NULL;
1561012573ebSchristos   switch (print_radix)
1562012573ebSchristos     {
1563*e992f068Schristos     case 8:  radix = PRIo64; break;
1564*e992f068Schristos     case 10: radix = PRId64; break;
1565*e992f068Schristos     case 16: radix = PRIx64; break;
1566012573ebSchristos     }
1567012573ebSchristos 
1568*e992f068Schristos   return concat ("%", padding, radix, NULL);
1569012573ebSchristos }
1570012573ebSchristos 
157175fd0b74Schristos static void
set_print_width(bfd * file)157275fd0b74Schristos set_print_width (bfd *file)
157375fd0b74Schristos {
157475fd0b74Schristos   print_width = bfd_get_arch_size (file);
157575fd0b74Schristos 
157675fd0b74Schristos   if (print_width == -1)
157775fd0b74Schristos     {
157875fd0b74Schristos       /* PR binutils/4292
157975fd0b74Schristos 	 Guess the target's bitsize based on its name.
158075fd0b74Schristos 	 We assume here than any 64-bit format will include
158175fd0b74Schristos 	 "64" somewhere in its name.  The only known exception
158275fd0b74Schristos 	 is the MMO object file format.  */
158375fd0b74Schristos       if (strstr (bfd_get_target (file), "64") != NULL
158475fd0b74Schristos 	  || strcmp (bfd_get_target (file), "mmo") == 0)
158575fd0b74Schristos 	print_width = 64;
158675fd0b74Schristos       else
158775fd0b74Schristos 	print_width = 32;
158875fd0b74Schristos     }
1589012573ebSchristos   free ((char *) print_format_string);
1590012573ebSchristos   print_format_string = get_print_format ();
159175fd0b74Schristos }
159275fd0b74Schristos 
159375fd0b74Schristos static void
display_archive(bfd * file)159475fd0b74Schristos display_archive (bfd *file)
159575fd0b74Schristos {
159675fd0b74Schristos   bfd *arfile = NULL;
159775fd0b74Schristos   bfd *last_arfile = NULL;
159875fd0b74Schristos   char **matching;
159975fd0b74Schristos 
160075fd0b74Schristos   format->print_archive_filename (bfd_get_filename (file));
160175fd0b74Schristos 
160275fd0b74Schristos   if (print_armap)
160375fd0b74Schristos     print_symdef_entry (file);
160475fd0b74Schristos 
160575fd0b74Schristos   for (;;)
160675fd0b74Schristos     {
160775fd0b74Schristos       PROGRESS (1);
160875fd0b74Schristos 
160975fd0b74Schristos       arfile = bfd_openr_next_archived_file (file, arfile);
161075fd0b74Schristos 
161175fd0b74Schristos       if (arfile == NULL)
161275fd0b74Schristos 	{
161375fd0b74Schristos 	  if (bfd_get_error () != bfd_error_no_more_archived_files)
161475fd0b74Schristos 	    bfd_fatal (bfd_get_filename (file));
161575fd0b74Schristos 	  break;
161675fd0b74Schristos 	}
161775fd0b74Schristos 
161875fd0b74Schristos       if (bfd_check_format_matches (arfile, bfd_object, &matching))
161975fd0b74Schristos 	{
162075fd0b74Schristos 	  set_print_width (arfile);
162175fd0b74Schristos 	  format->print_archive_member (bfd_get_filename (file),
162275fd0b74Schristos 					bfd_get_filename (arfile));
162375fd0b74Schristos 	  display_rel_file (arfile, file);
162475fd0b74Schristos 	}
162575fd0b74Schristos       else
162675fd0b74Schristos 	{
162775fd0b74Schristos 	  bfd_nonfatal (bfd_get_filename (arfile));
162875fd0b74Schristos 	  if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
162975fd0b74Schristos 	    list_matching_formats (matching);
163075fd0b74Schristos 	}
163175fd0b74Schristos 
163275fd0b74Schristos       if (last_arfile != NULL)
163375fd0b74Schristos 	{
163475fd0b74Schristos 	  bfd_close (last_arfile);
163575fd0b74Schristos 	  lineno_cache_bfd = NULL;
163675fd0b74Schristos 	  lineno_cache_rel_bfd = NULL;
163775fd0b74Schristos 	  if (arfile == last_arfile)
163875fd0b74Schristos 	    return;
163975fd0b74Schristos 	}
164075fd0b74Schristos       last_arfile = arfile;
164175fd0b74Schristos     }
164275fd0b74Schristos 
164375fd0b74Schristos   if (last_arfile != NULL)
164475fd0b74Schristos     {
164575fd0b74Schristos       bfd_close (last_arfile);
164675fd0b74Schristos       lineno_cache_bfd = NULL;
164775fd0b74Schristos       lineno_cache_rel_bfd = NULL;
164875fd0b74Schristos     }
164975fd0b74Schristos }
165075fd0b74Schristos 
1651*e992f068Schristos static bool
display_file(char * filename)165275fd0b74Schristos display_file (char *filename)
165375fd0b74Schristos {
1654*e992f068Schristos   bool retval = true;
165575fd0b74Schristos   bfd *file;
165675fd0b74Schristos   char **matching;
165775fd0b74Schristos 
165875fd0b74Schristos   if (get_file_size (filename) < 1)
1659*e992f068Schristos     return false;
166075fd0b74Schristos 
166175fd0b74Schristos   file = bfd_openr (filename, target ? target : plugin_target);
166275fd0b74Schristos   if (file == NULL)
166375fd0b74Schristos     {
166475fd0b74Schristos       bfd_nonfatal (filename);
1665*e992f068Schristos       return false;
166675fd0b74Schristos     }
166775fd0b74Schristos 
166875fd0b74Schristos   /* If printing line numbers, decompress the debug sections.  */
166975fd0b74Schristos   if (line_numbers)
167075fd0b74Schristos     file->flags |= BFD_DECOMPRESS;
167175fd0b74Schristos 
167275fd0b74Schristos   if (bfd_check_format (file, bfd_archive))
167375fd0b74Schristos     {
167475fd0b74Schristos       display_archive (file);
167575fd0b74Schristos     }
167675fd0b74Schristos   else if (bfd_check_format_matches (file, bfd_object, &matching))
167775fd0b74Schristos     {
167875fd0b74Schristos       set_print_width (file);
167975fd0b74Schristos       format->print_object_filename (filename);
168075fd0b74Schristos       display_rel_file (file, NULL);
168175fd0b74Schristos     }
168275fd0b74Schristos   else
168375fd0b74Schristos     {
168475fd0b74Schristos       bfd_nonfatal (filename);
168575fd0b74Schristos       if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
168675fd0b74Schristos 	list_matching_formats (matching);
1687*e992f068Schristos       retval = false;
168875fd0b74Schristos     }
168975fd0b74Schristos 
169075fd0b74Schristos   if (!bfd_close (file))
169175fd0b74Schristos     bfd_fatal (filename);
169275fd0b74Schristos 
169375fd0b74Schristos   lineno_cache_bfd = NULL;
169475fd0b74Schristos   lineno_cache_rel_bfd = NULL;
169575fd0b74Schristos 
169675fd0b74Schristos   return retval;
169775fd0b74Schristos }
169875fd0b74Schristos 
169975fd0b74Schristos /* The following 3 groups of functions are called unconditionally,
170075fd0b74Schristos    once at the start of processing each file of the appropriate type.
170175fd0b74Schristos    They should check `filename_per_file' and `filename_per_symbol',
170275fd0b74Schristos    as appropriate for their output format, to determine whether to
170375fd0b74Schristos    print anything.  */
170475fd0b74Schristos 
170575fd0b74Schristos /* Print the name of an object file given on the command line.  */
170675fd0b74Schristos 
170775fd0b74Schristos static void
print_object_filename_bsd(const char * filename)1708012573ebSchristos print_object_filename_bsd (const char *filename)
170975fd0b74Schristos {
171075fd0b74Schristos   if (filename_per_file && !filename_per_symbol)
171175fd0b74Schristos     printf ("\n%s:\n", filename);
171275fd0b74Schristos }
171375fd0b74Schristos 
171475fd0b74Schristos static void
print_object_filename_sysv(const char * filename)1715012573ebSchristos print_object_filename_sysv (const char *filename)
171675fd0b74Schristos {
171775fd0b74Schristos   if (undefined_only)
171875fd0b74Schristos     printf (_("\n\nUndefined symbols from %s:\n\n"), filename);
171975fd0b74Schristos   else
172075fd0b74Schristos     printf (_("\n\nSymbols from %s:\n\n"), filename);
172175fd0b74Schristos   if (print_width == 32)
172275fd0b74Schristos     printf (_("\
172375fd0b74Schristos Name                  Value   Class        Type         Size     Line  Section\n\n"));
172475fd0b74Schristos   else
172575fd0b74Schristos     printf (_("\
172675fd0b74Schristos Name                  Value           Class        Type         Size             Line  Section\n\n"));
172775fd0b74Schristos }
172875fd0b74Schristos 
172975fd0b74Schristos static void
print_object_filename_posix(const char * filename)1730012573ebSchristos print_object_filename_posix (const char *filename)
173175fd0b74Schristos {
173275fd0b74Schristos   if (filename_per_file && !filename_per_symbol)
173375fd0b74Schristos     printf ("%s:\n", filename);
173475fd0b74Schristos }
1735*e992f068Schristos 
1736*e992f068Schristos static void
do_not_print_object_filename(const char * filename ATTRIBUTE_UNUSED)1737*e992f068Schristos do_not_print_object_filename (const char *filename ATTRIBUTE_UNUSED)
1738*e992f068Schristos {
1739*e992f068Schristos }
174075fd0b74Schristos 
174175fd0b74Schristos /* Print the name of an archive file given on the command line.  */
174275fd0b74Schristos 
174375fd0b74Schristos static void
print_archive_filename_bsd(const char * filename)1744012573ebSchristos print_archive_filename_bsd (const char *filename)
174575fd0b74Schristos {
174675fd0b74Schristos   if (filename_per_file)
174775fd0b74Schristos     printf ("\n%s:\n", filename);
174875fd0b74Schristos }
174975fd0b74Schristos 
175075fd0b74Schristos static void
print_archive_filename_sysv(const char * filename ATTRIBUTE_UNUSED)1751012573ebSchristos print_archive_filename_sysv (const char *filename ATTRIBUTE_UNUSED)
175275fd0b74Schristos {
175375fd0b74Schristos }
175475fd0b74Schristos 
175575fd0b74Schristos static void
print_archive_filename_posix(const char * filename ATTRIBUTE_UNUSED)1756012573ebSchristos print_archive_filename_posix (const char *filename ATTRIBUTE_UNUSED)
175775fd0b74Schristos {
175875fd0b74Schristos }
1759*e992f068Schristos 
1760*e992f068Schristos static void
do_not_print_archive_filename(const char * filename ATTRIBUTE_UNUSED)1761*e992f068Schristos do_not_print_archive_filename (const char *filename ATTRIBUTE_UNUSED)
1762*e992f068Schristos {
1763*e992f068Schristos }
176475fd0b74Schristos 
176575fd0b74Schristos /* Print the name of an archive member file.  */
176675fd0b74Schristos 
176775fd0b74Schristos static void
print_archive_member_bsd(const char * archive ATTRIBUTE_UNUSED,const char * filename)1768012573ebSchristos print_archive_member_bsd (const char *archive ATTRIBUTE_UNUSED,
176975fd0b74Schristos 			  const char *filename)
177075fd0b74Schristos {
177175fd0b74Schristos   if (!filename_per_symbol)
177275fd0b74Schristos     printf ("\n%s:\n", filename);
177375fd0b74Schristos }
177475fd0b74Schristos 
177575fd0b74Schristos static void
print_archive_member_sysv(const char * archive,const char * filename)1776012573ebSchristos print_archive_member_sysv (const char *archive, const char *filename)
177775fd0b74Schristos {
177875fd0b74Schristos   if (undefined_only)
177975fd0b74Schristos     printf (_("\n\nUndefined symbols from %s[%s]:\n\n"), archive, filename);
178075fd0b74Schristos   else
178175fd0b74Schristos     printf (_("\n\nSymbols from %s[%s]:\n\n"), archive, filename);
178275fd0b74Schristos   if (print_width == 32)
178375fd0b74Schristos     printf (_("\
178475fd0b74Schristos Name                  Value   Class        Type         Size     Line  Section\n\n"));
178575fd0b74Schristos   else
178675fd0b74Schristos     printf (_("\
178775fd0b74Schristos Name                  Value           Class        Type         Size             Line  Section\n\n"));
178875fd0b74Schristos }
178975fd0b74Schristos 
179075fd0b74Schristos static void
print_archive_member_posix(const char * archive,const char * filename)1791012573ebSchristos print_archive_member_posix (const char *archive, const char *filename)
179275fd0b74Schristos {
179375fd0b74Schristos   if (!filename_per_symbol)
179475fd0b74Schristos     printf ("%s[%s]:\n", archive, filename);
179575fd0b74Schristos }
1796*e992f068Schristos 
1797*e992f068Schristos static void
do_not_print_archive_member(const char * archive ATTRIBUTE_UNUSED,const char * filename ATTRIBUTE_UNUSED)1798*e992f068Schristos do_not_print_archive_member (const char *archive ATTRIBUTE_UNUSED,
1799*e992f068Schristos 			     const char *filename ATTRIBUTE_UNUSED)
1800*e992f068Schristos {
1801*e992f068Schristos }
1802*e992f068Schristos 
180375fd0b74Schristos 
180475fd0b74Schristos /* Print the name of the file (and archive, if there is one)
180575fd0b74Schristos    containing a symbol.  */
180675fd0b74Schristos 
180775fd0b74Schristos static void
print_symbol_filename_bsd(bfd * archive_bfd,bfd * abfd)180875fd0b74Schristos print_symbol_filename_bsd (bfd *archive_bfd, bfd *abfd)
180975fd0b74Schristos {
181075fd0b74Schristos   if (filename_per_symbol)
181175fd0b74Schristos     {
181275fd0b74Schristos       if (archive_bfd)
181375fd0b74Schristos 	printf ("%s:", bfd_get_filename (archive_bfd));
181475fd0b74Schristos       printf ("%s:", bfd_get_filename (abfd));
181575fd0b74Schristos     }
181675fd0b74Schristos }
181775fd0b74Schristos 
181875fd0b74Schristos static void
print_symbol_filename_sysv(bfd * archive_bfd,bfd * abfd)181975fd0b74Schristos print_symbol_filename_sysv (bfd *archive_bfd, bfd *abfd)
182075fd0b74Schristos {
182175fd0b74Schristos   if (filename_per_symbol)
182275fd0b74Schristos     {
182375fd0b74Schristos       if (archive_bfd)
182475fd0b74Schristos 	printf ("%s:", bfd_get_filename (archive_bfd));
182575fd0b74Schristos       printf ("%s:", bfd_get_filename (abfd));
182675fd0b74Schristos     }
182775fd0b74Schristos }
182875fd0b74Schristos 
182975fd0b74Schristos static void
print_symbol_filename_posix(bfd * archive_bfd,bfd * abfd)183075fd0b74Schristos print_symbol_filename_posix (bfd *archive_bfd, bfd *abfd)
183175fd0b74Schristos {
183275fd0b74Schristos   if (filename_per_symbol)
183375fd0b74Schristos     {
183475fd0b74Schristos       if (archive_bfd)
183575fd0b74Schristos 	printf ("%s[%s]: ", bfd_get_filename (archive_bfd),
183675fd0b74Schristos 		bfd_get_filename (abfd));
183775fd0b74Schristos       else
183875fd0b74Schristos 	printf ("%s: ", bfd_get_filename (abfd));
183975fd0b74Schristos     }
184075fd0b74Schristos }
1841*e992f068Schristos 
1842*e992f068Schristos static void
do_not_print_symbol_filename(bfd * archive_bfd ATTRIBUTE_UNUSED,bfd * abfd ATTRIBUTE_UNUSED)1843*e992f068Schristos do_not_print_symbol_filename (bfd *archive_bfd ATTRIBUTE_UNUSED,
1844*e992f068Schristos 			      bfd *abfd ATTRIBUTE_UNUSED)
1845*e992f068Schristos {
1846*e992f068Schristos }
1847*e992f068Schristos 
184875fd0b74Schristos 
184975fd0b74Schristos /* Print a symbol value.  */
185075fd0b74Schristos 
185175fd0b74Schristos static void
print_value(bfd * abfd ATTRIBUTE_UNUSED,bfd_vma val)185275fd0b74Schristos print_value (bfd *abfd ATTRIBUTE_UNUSED, bfd_vma val)
185375fd0b74Schristos {
185475fd0b74Schristos   switch (print_width)
185575fd0b74Schristos     {
185675fd0b74Schristos     case 32:
185775fd0b74Schristos     case 64:
1858*e992f068Schristos       printf (print_format_string, (uint64_t) val);
185975fd0b74Schristos       break;
186075fd0b74Schristos 
186175fd0b74Schristos     default:
186275fd0b74Schristos       fatal (_("Print width has not been initialized (%d)"), print_width);
186375fd0b74Schristos       break;
186475fd0b74Schristos     }
186575fd0b74Schristos }
186675fd0b74Schristos 
186775fd0b74Schristos /* Print a line of information about a symbol.  */
186875fd0b74Schristos 
186975fd0b74Schristos static void
print_symbol_info_bsd(struct extended_symbol_info * info,bfd * abfd)187075fd0b74Schristos print_symbol_info_bsd (struct extended_symbol_info *info, bfd *abfd)
187175fd0b74Schristos {
187275fd0b74Schristos   if (bfd_is_undefined_symclass (SYM_TYPE (info)))
187375fd0b74Schristos     {
187475fd0b74Schristos       if (print_width == 64)
187575fd0b74Schristos 	printf ("        ");
187675fd0b74Schristos       printf ("        ");
187775fd0b74Schristos     }
187875fd0b74Schristos   else
187975fd0b74Schristos     {
188075fd0b74Schristos       /* Normally we print the value of the symbol.  If we are printing the
188175fd0b74Schristos 	 size or sorting by size then we print its size, except for the
188275fd0b74Schristos 	 (weird) special case where both flags are defined, in which case we
188375fd0b74Schristos 	 print both values.  This conforms to documented behaviour.  */
188475fd0b74Schristos       if (sort_by_size && !print_size)
188575fd0b74Schristos 	print_value (abfd, SYM_SIZE (info));
188675fd0b74Schristos       else
188775fd0b74Schristos 	print_value (abfd, SYM_VALUE (info));
188875fd0b74Schristos       if (print_size && SYM_SIZE (info))
188975fd0b74Schristos 	{
189075fd0b74Schristos 	  printf (" ");
189175fd0b74Schristos 	  print_value (abfd, SYM_SIZE (info));
189275fd0b74Schristos 	}
189375fd0b74Schristos     }
189475fd0b74Schristos 
189575fd0b74Schristos   printf (" %c", SYM_TYPE (info));
189675fd0b74Schristos 
189775fd0b74Schristos   if (SYM_TYPE (info) == '-')
189875fd0b74Schristos     {
189975fd0b74Schristos       /* A stab.  */
190075fd0b74Schristos       printf (" ");
190175fd0b74Schristos       printf (other_format, SYM_STAB_OTHER (info));
190275fd0b74Schristos       printf (" ");
190375fd0b74Schristos       printf (desc_format, SYM_STAB_DESC (info));
190475fd0b74Schristos       printf (" %5s", SYM_STAB_NAME (info));
190575fd0b74Schristos     }
1906*e992f068Schristos   print_symname (" %s", info, NULL, abfd);
190775fd0b74Schristos }
190875fd0b74Schristos 
190975fd0b74Schristos static void
print_symbol_info_sysv(struct extended_symbol_info * info,bfd * abfd)191075fd0b74Schristos print_symbol_info_sysv (struct extended_symbol_info *info, bfd *abfd)
191175fd0b74Schristos {
1912*e992f068Schristos   print_symname ("%-20s|", info, NULL, abfd);
191375fd0b74Schristos 
191475fd0b74Schristos   if (bfd_is_undefined_symclass (SYM_TYPE (info)))
191575fd0b74Schristos     {
191675fd0b74Schristos       if (print_width == 32)
191775fd0b74Schristos 	printf ("        ");
191875fd0b74Schristos       else
191975fd0b74Schristos 	printf ("                ");
192075fd0b74Schristos     }
192175fd0b74Schristos   else
192275fd0b74Schristos     print_value (abfd, SYM_VALUE (info));
192375fd0b74Schristos 
192475fd0b74Schristos   printf ("|   %c  |", SYM_TYPE (info));
192575fd0b74Schristos 
192675fd0b74Schristos   if (SYM_TYPE (info) == '-')
192775fd0b74Schristos     {
192875fd0b74Schristos       /* A stab.  */
192975fd0b74Schristos       printf ("%18s|  ", SYM_STAB_NAME (info));		/* (C) Type.  */
193075fd0b74Schristos       printf (desc_format, SYM_STAB_DESC (info));	/* Size.  */
193175fd0b74Schristos       printf ("|     |");				/* Line, Section.  */
193275fd0b74Schristos     }
193375fd0b74Schristos   else
193475fd0b74Schristos     {
193575fd0b74Schristos       /* Type, Size, Line, Section */
193675fd0b74Schristos       if (info->elfinfo)
193775fd0b74Schristos 	printf ("%18s|",
193875fd0b74Schristos 		get_elf_symbol_type (ELF_ST_TYPE (info->elfinfo->internal_elf_sym.st_info)));
193975fd0b74Schristos       else if (info->coffinfo)
194075fd0b74Schristos 	printf ("%18s|",
194175fd0b74Schristos 		get_coff_symbol_type (&info->coffinfo->native->u.syment));
194275fd0b74Schristos       else
194375fd0b74Schristos 	printf ("                  |");
194475fd0b74Schristos 
194575fd0b74Schristos       if (SYM_SIZE (info))
194675fd0b74Schristos 	print_value (abfd, SYM_SIZE (info));
194775fd0b74Schristos       else
194875fd0b74Schristos 	{
194975fd0b74Schristos 	  if (print_width == 32)
195075fd0b74Schristos 	    printf ("        ");
195175fd0b74Schristos 	  else
195275fd0b74Schristos 	    printf ("                ");
195375fd0b74Schristos 	}
195475fd0b74Schristos 
195575fd0b74Schristos       if (info->elfinfo)
195675fd0b74Schristos 	printf("|     |%s", info->elfinfo->symbol.section->name);
195775fd0b74Schristos       else if (info->coffinfo)
195875fd0b74Schristos 	printf("|     |%s", info->coffinfo->symbol.section->name);
195975fd0b74Schristos       else
196075fd0b74Schristos 	printf("|     |");
196175fd0b74Schristos     }
196275fd0b74Schristos }
196375fd0b74Schristos 
196475fd0b74Schristos static void
print_symbol_info_posix(struct extended_symbol_info * info,bfd * abfd)196575fd0b74Schristos print_symbol_info_posix (struct extended_symbol_info *info, bfd *abfd)
196675fd0b74Schristos {
1967*e992f068Schristos   print_symname ("%s ", info, NULL, abfd);
196875fd0b74Schristos   printf ("%c ", SYM_TYPE (info));
196975fd0b74Schristos 
197075fd0b74Schristos   if (bfd_is_undefined_symclass (SYM_TYPE (info)))
197175fd0b74Schristos     printf ("        ");
197275fd0b74Schristos   else
197375fd0b74Schristos     {
197475fd0b74Schristos       print_value (abfd, SYM_VALUE (info));
197575fd0b74Schristos       printf (" ");
197675fd0b74Schristos       if (SYM_SIZE (info))
197775fd0b74Schristos 	print_value (abfd, SYM_SIZE (info));
197875fd0b74Schristos     }
197975fd0b74Schristos }
1980*e992f068Schristos 
1981*e992f068Schristos static void
just_print_symbol_name(struct extended_symbol_info * info,bfd * abfd)1982*e992f068Schristos just_print_symbol_name (struct extended_symbol_info *info, bfd *abfd)
1983*e992f068Schristos {
1984*e992f068Schristos   print_symname ("%s", info, NULL, abfd);
1985*e992f068Schristos }
198675fd0b74Schristos 
198775fd0b74Schristos int
main(int argc,char ** argv)198875fd0b74Schristos main (int argc, char **argv)
198975fd0b74Schristos {
199075fd0b74Schristos   int c;
199175fd0b74Schristos   int retval;
199275fd0b74Schristos 
1993*e992f068Schristos #ifdef HAVE_LC_MESSAGES
199475fd0b74Schristos   setlocale (LC_MESSAGES, "");
199575fd0b74Schristos #endif
199675fd0b74Schristos   setlocale (LC_CTYPE, "");
199775fd0b74Schristos   setlocale (LC_COLLATE, "");
199875fd0b74Schristos   bindtextdomain (PACKAGE, LOCALEDIR);
199975fd0b74Schristos   textdomain (PACKAGE);
200075fd0b74Schristos 
200175fd0b74Schristos   program_name = *argv;
200275fd0b74Schristos   xmalloc_set_program_name (program_name);
200375fd0b74Schristos   bfd_set_error_program_name (program_name);
200475fd0b74Schristos #if BFD_SUPPORTS_PLUGINS
200575fd0b74Schristos   bfd_plugin_set_program_name (program_name);
200675fd0b74Schristos #endif
200775fd0b74Schristos 
200875fd0b74Schristos   START_PROGRESS (program_name, 0);
200975fd0b74Schristos 
201075fd0b74Schristos   expandargv (&argc, &argv);
201175fd0b74Schristos 
2012012573ebSchristos   if (bfd_init () != BFD_INIT_MAGIC)
2013012573ebSchristos     fatal (_("fatal error: libbfd ABI mismatch"));
201475fd0b74Schristos   set_default_bfd_target ();
201575fd0b74Schristos 
2016*e992f068Schristos   while ((c = getopt_long (argc, argv, "aABCDef:gHhjJlnopPrSst:uU:vVvWX:",
201775fd0b74Schristos 			   long_options, (int *) 0)) != EOF)
201875fd0b74Schristos     {
201975fd0b74Schristos       switch (c)
202075fd0b74Schristos 	{
202175fd0b74Schristos 	case 'a':
202275fd0b74Schristos 	  print_debug_syms = 1;
202375fd0b74Schristos 	  break;
202475fd0b74Schristos 	case 'A':
202575fd0b74Schristos 	case 'o':
202675fd0b74Schristos 	  filename_per_symbol = 1;
202775fd0b74Schristos 	  break;
202875fd0b74Schristos 	case 'B':		/* For MIPS compatibility.  */
202975fd0b74Schristos 	  set_output_format ("bsd");
203075fd0b74Schristos 	  break;
203175fd0b74Schristos 	case 'C':
203275fd0b74Schristos 	  do_demangle = 1;
203375fd0b74Schristos 	  if (optarg != NULL)
203475fd0b74Schristos 	    {
203575fd0b74Schristos 	      enum demangling_styles style;
203675fd0b74Schristos 
203775fd0b74Schristos 	      style = cplus_demangle_name_to_style (optarg);
203875fd0b74Schristos 	      if (style == unknown_demangling)
203975fd0b74Schristos 		fatal (_("unknown demangling style `%s'"),
204075fd0b74Schristos 		       optarg);
204175fd0b74Schristos 
204275fd0b74Schristos 	      cplus_demangle_set_style (style);
204375fd0b74Schristos 	    }
204475fd0b74Schristos 	  break;
2045012573ebSchristos 	case OPTION_RECURSE_LIMIT:
2046012573ebSchristos 	  demangle_flags &= ~ DMGL_NO_RECURSE_LIMIT;
2047012573ebSchristos 	  break;
2048012573ebSchristos 	case OPTION_NO_RECURSE_LIMIT:
2049012573ebSchristos 	  demangle_flags |= DMGL_NO_RECURSE_LIMIT;
2050012573ebSchristos 	  break;
2051*e992f068Schristos 	case OPTION_QUIET:
2052*e992f068Schristos 	  quiet = 1;
2053*e992f068Schristos 	  break;
205475fd0b74Schristos 	case 'D':
205575fd0b74Schristos 	  dynamic = 1;
205675fd0b74Schristos 	  break;
205775fd0b74Schristos 	case 'e':
205875fd0b74Schristos 	  /* Ignored for HP/UX compatibility.  */
205975fd0b74Schristos 	  break;
206075fd0b74Schristos 	case 'f':
206175fd0b74Schristos 	  set_output_format (optarg);
206275fd0b74Schristos 	  break;
206375fd0b74Schristos 	case 'g':
206475fd0b74Schristos 	  external_only = 1;
206575fd0b74Schristos 	  break;
206675fd0b74Schristos 	case 'H':
206775fd0b74Schristos 	case 'h':
206875fd0b74Schristos 	  usage (stdout, 0);
206975fd0b74Schristos 	case 'l':
207075fd0b74Schristos 	  line_numbers = 1;
207175fd0b74Schristos 	  break;
207275fd0b74Schristos 	case 'n':
207375fd0b74Schristos 	case 'v':
207475fd0b74Schristos 	  no_sort = 0;
207575fd0b74Schristos 	  sort_numerically = 1;
207675fd0b74Schristos 	  sort_by_size = 0;
207775fd0b74Schristos 	  break;
207875fd0b74Schristos 	case 'p':
207975fd0b74Schristos 	  no_sort = 1;
208075fd0b74Schristos 	  sort_numerically = 0;
208175fd0b74Schristos 	  sort_by_size = 0;
208275fd0b74Schristos 	  break;
208375fd0b74Schristos 	case OPTION_SIZE_SORT:
208475fd0b74Schristos 	  no_sort = 0;
208575fd0b74Schristos 	  sort_numerically = 0;
208675fd0b74Schristos 	  sort_by_size = 1;
208775fd0b74Schristos 	  break;
208875fd0b74Schristos 	case 'P':
208975fd0b74Schristos 	  set_output_format ("posix");
209075fd0b74Schristos 	  break;
2091*e992f068Schristos 	case 'j':
2092*e992f068Schristos 	  set_output_format ("just-symbols");
2093*e992f068Schristos 	  break;
209475fd0b74Schristos 	case 'r':
209575fd0b74Schristos 	  reverse_sort = 1;
209675fd0b74Schristos 	  break;
209775fd0b74Schristos 	case 's':
209875fd0b74Schristos 	  print_armap = 1;
209975fd0b74Schristos 	  break;
210075fd0b74Schristos 	case 'S':
210175fd0b74Schristos 	  print_size = 1;
210275fd0b74Schristos 	  break;
210375fd0b74Schristos 	case 't':
210475fd0b74Schristos 	  set_print_radix (optarg);
210575fd0b74Schristos 	  break;
210675fd0b74Schristos 	case 'u':
210775fd0b74Schristos 	  undefined_only = 1;
2108*e992f068Schristos 	  defined_only = 0;
210975fd0b74Schristos 	  break;
2110*e992f068Schristos 	case 'U':
2111*e992f068Schristos 	  defined_only = 1;
2112*e992f068Schristos 	  undefined_only = 0;
2113*e992f068Schristos 	  break;
2114*e992f068Schristos 
2115*e992f068Schristos 	case OPTION_UNICODE:
2116*e992f068Schristos 	  if (streq (optarg, "default") || streq (optarg, "d"))
2117*e992f068Schristos 	    unicode_display = unicode_default;
2118*e992f068Schristos 	  else if (streq (optarg, "locale") || streq (optarg, "l"))
2119*e992f068Schristos 	    unicode_display = unicode_locale;
2120*e992f068Schristos 	  else if (streq (optarg, "escape") || streq (optarg, "e"))
2121*e992f068Schristos 	    unicode_display = unicode_escape;
2122*e992f068Schristos 	  else if (streq (optarg, "invalid") || streq (optarg, "i"))
2123*e992f068Schristos 	    unicode_display = unicode_invalid;
2124*e992f068Schristos 	  else if (streq (optarg, "hex") || streq (optarg, "x"))
2125*e992f068Schristos 	    unicode_display = unicode_hex;
2126*e992f068Schristos 	  else if (streq (optarg, "highlight") || streq (optarg, "h"))
2127*e992f068Schristos 	    unicode_display = unicode_highlight;
2128*e992f068Schristos 	  else
2129*e992f068Schristos 	    fatal (_("invalid argument to -U/--unicode: %s"), optarg);
2130*e992f068Schristos 	  break;
2131*e992f068Schristos 
213275fd0b74Schristos 	case 'V':
213375fd0b74Schristos 	  show_version = 1;
213475fd0b74Schristos 	  break;
2135*e992f068Schristos 	case 'W':
2136*e992f068Schristos 	  non_weak = 1;
2137*e992f068Schristos 	  break;
213875fd0b74Schristos 	case 'X':
213975fd0b74Schristos 	  /* Ignored for (partial) AIX compatibility.  On AIX, the
214075fd0b74Schristos 	     argument has values 32, 64, or 32_64, and specifies that
214175fd0b74Schristos 	     only 32-bit, only 64-bit, or both kinds of objects should
214275fd0b74Schristos 	     be examined.  The default is 32.  So plain AIX nm on a
214375fd0b74Schristos 	     library archive with both kinds of objects will ignore
214475fd0b74Schristos 	     the 64-bit ones.  For GNU nm, the default is and always
214575fd0b74Schristos 	     has been -X 32_64, and other options are not supported.  */
214675fd0b74Schristos 	  if (strcmp (optarg, "32_64") != 0)
214775fd0b74Schristos 	    fatal (_("Only -X 32_64 is supported"));
214875fd0b74Schristos 	  break;
214975fd0b74Schristos 
215075fd0b74Schristos 	case OPTION_TARGET:	/* --target */
215175fd0b74Schristos 	  target = optarg;
215275fd0b74Schristos 	  break;
215375fd0b74Schristos 
215475fd0b74Schristos 	case OPTION_PLUGIN:	/* --plugin */
215575fd0b74Schristos #if BFD_SUPPORTS_PLUGINS
215675fd0b74Schristos 	  bfd_plugin_set_plugin (optarg);
215775fd0b74Schristos #else
215875fd0b74Schristos 	  fatal (_("sorry - this program has been built without plugin support\n"));
215975fd0b74Schristos #endif
216075fd0b74Schristos 	  break;
216175fd0b74Schristos 
2162*e992f068Schristos 	case OPTION_IFUNC_CHARS:
2163*e992f068Schristos 	  ifunc_type_chars = optarg;
2164*e992f068Schristos 	  break;
2165*e992f068Schristos 
216675fd0b74Schristos 	case 0:		/* A long option that just sets a flag.  */
216775fd0b74Schristos 	  break;
216875fd0b74Schristos 
216975fd0b74Schristos 	default:
217075fd0b74Schristos 	  usage (stderr, 1);
217175fd0b74Schristos 	}
217275fd0b74Schristos     }
217375fd0b74Schristos 
217475fd0b74Schristos   if (show_version)
217575fd0b74Schristos     print_version ("nm");
217675fd0b74Schristos 
217775fd0b74Schristos   if (sort_by_size && undefined_only)
217875fd0b74Schristos     {
217975fd0b74Schristos       non_fatal (_("Using the --size-sort and --undefined-only options together"));
218075fd0b74Schristos       non_fatal (_("will produce no output, since undefined symbols have no size."));
218175fd0b74Schristos       return 0;
218275fd0b74Schristos     }
218375fd0b74Schristos 
218475fd0b74Schristos   /* OK, all options now parsed.  If no filename specified, do a.out.  */
218575fd0b74Schristos   if (optind == argc)
218675fd0b74Schristos     return !display_file ("a.out");
218775fd0b74Schristos 
218875fd0b74Schristos   retval = 0;
218975fd0b74Schristos 
219075fd0b74Schristos   if (argc - optind > 1)
219175fd0b74Schristos     filename_per_file = 1;
219275fd0b74Schristos 
219375fd0b74Schristos   /* We were given several filenames to do.  */
219475fd0b74Schristos   while (optind < argc)
219575fd0b74Schristos     {
219675fd0b74Schristos       PROGRESS (1);
219775fd0b74Schristos       if (!display_file (argv[optind++]))
219875fd0b74Schristos 	retval++;
219975fd0b74Schristos     }
220075fd0b74Schristos 
220175fd0b74Schristos   END_PROGRESS (program_name);
220275fd0b74Schristos 
220375fd0b74Schristos   exit (retval);
220475fd0b74Schristos   return retval;
220575fd0b74Schristos }
2206