12159047fSniklas /* nm.c -- Describe symbol table of a rel file.
2b55d4692Sfgsch Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3c074d1c9Sdrahn 2001, 2002, 2003
4b305b0f1Sespie Free Software Foundation, Inc.
52159047fSniklas
62159047fSniklas This file is part of GNU Binutils.
72159047fSniklas
82159047fSniklas This program is free software; you can redistribute it and/or modify
92159047fSniklas it under the terms of the GNU General Public License as published by
102159047fSniklas the Free Software Foundation; either version 2 of the License, or
112159047fSniklas (at your option) any later version.
122159047fSniklas
132159047fSniklas This program is distributed in the hope that it will be useful,
142159047fSniklas but WITHOUT ANY WARRANTY; without even the implied warranty of
152159047fSniklas MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
162159047fSniklas GNU General Public License for more details.
172159047fSniklas
182159047fSniklas You should have received a copy of the GNU General Public License
192159047fSniklas along with this program; if not, write to the Free Software
20b305b0f1Sespie Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21b305b0f1Sespie 02111-1307, USA. */
222159047fSniklas
232159047fSniklas #include "bfd.h"
242159047fSniklas #include "progress.h"
252159047fSniklas #include "bucomm.h"
26c074d1c9Sdrahn #include "budemang.h"
272159047fSniklas #include "getopt.h"
282159047fSniklas #include "aout/stab_gnu.h"
292159047fSniklas #include "aout/ranlib.h"
302159047fSniklas #include "demangle.h"
312159047fSniklas #include "libiberty.h"
32c074d1c9Sdrahn #include "elf-bfd.h"
33c074d1c9Sdrahn #include "elf/common.h"
342159047fSniklas
352159047fSniklas /* When sorting by size, we use this structure to hold the size and a
362159047fSniklas pointer to the minisymbol. */
372159047fSniklas
382159047fSniklas struct size_sym
392159047fSniklas {
40007c2a45Smiod const void *minisym;
412159047fSniklas bfd_vma size;
422159047fSniklas };
432159047fSniklas
440c6d0228Sniklas /* When fetching relocs, we use this structure to pass information to
450c6d0228Sniklas get_relocs. */
460c6d0228Sniklas
470c6d0228Sniklas struct get_relocs_info
480c6d0228Sniklas {
490c6d0228Sniklas asection **secs;
500c6d0228Sniklas arelent ***relocs;
510c6d0228Sniklas long *relcount;
520c6d0228Sniklas asymbol **syms;
530c6d0228Sniklas };
540c6d0228Sniklas
55c074d1c9Sdrahn struct extended_symbol_info
56c074d1c9Sdrahn {
57c074d1c9Sdrahn symbol_info *sinfo;
58c074d1c9Sdrahn bfd_vma ssize;
59c074d1c9Sdrahn elf_symbol_type *elfinfo;
60c074d1c9Sdrahn /* FIXME: We should add more fields for Type, Line, Section. */
61c074d1c9Sdrahn };
62c074d1c9Sdrahn #define SYM_NAME(sym) (sym->sinfo->name)
63c074d1c9Sdrahn #define SYM_VALUE(sym) (sym->sinfo->value)
64c074d1c9Sdrahn #define SYM_TYPE(sym) (sym->sinfo->type)
65c074d1c9Sdrahn #define SYM_STAB_NAME(sym) (sym->sinfo->stab_name)
66c074d1c9Sdrahn #define SYM_STAB_DESC(sym) (sym->sinfo->stab_desc)
67c074d1c9Sdrahn #define SYM_STAB_OTHER(sym) (sym->sinfo->stab_other)
68c074d1c9Sdrahn #define SYM_SIZE(sym) \
69c074d1c9Sdrahn (sym->elfinfo ? sym->elfinfo->internal_elf_sym.st_size: sym->ssize)
70b305b0f1Sespie
71007c2a45Smiod static void usage (FILE *, int);
72007c2a45Smiod static void set_print_radix (char *);
73007c2a45Smiod static void set_output_format (char *);
74007c2a45Smiod static void display_archive (bfd *);
75007c2a45Smiod static bfd_boolean display_file (char *);
76007c2a45Smiod static void display_rel_file (bfd *, bfd *);
77007c2a45Smiod static long filter_symbols (bfd *, bfd_boolean, void *, long, unsigned int);
78c074d1c9Sdrahn static long sort_symbols_by_size
79007c2a45Smiod (bfd *, bfd_boolean, void *, long, unsigned int, struct size_sym **);
80c074d1c9Sdrahn static void print_symbols
81007c2a45Smiod (bfd *, bfd_boolean, void *, long, unsigned int, bfd *);
82c074d1c9Sdrahn static void print_size_symbols
83007c2a45Smiod (bfd *, bfd_boolean, struct size_sym *, long, bfd *);
84007c2a45Smiod static void print_symname (const char *, const char *, bfd *);
85007c2a45Smiod static void print_symbol (bfd *, asymbol *, bfd_vma ssize, bfd *);
86007c2a45Smiod static void print_symdef_entry (bfd *);
872159047fSniklas
882159047fSniklas /* The sorting functions. */
89007c2a45Smiod static int numeric_forward (const void *, const void *);
90007c2a45Smiod static int numeric_reverse (const void *, const void *);
91007c2a45Smiod static int non_numeric_forward (const void *, const void *);
92007c2a45Smiod static int non_numeric_reverse (const void *, const void *);
93007c2a45Smiod static int size_forward1 (const void *, const void *);
94007c2a45Smiod static int size_forward2 (const void *, const void *);
952159047fSniklas
962159047fSniklas /* The output formatting functions. */
97007c2a45Smiod static void print_object_filename_bsd (char *);
98007c2a45Smiod static void print_object_filename_sysv (char *);
99007c2a45Smiod static void print_object_filename_posix (char *);
100007c2a45Smiod static void print_archive_filename_bsd (char *);
101007c2a45Smiod static void print_archive_filename_sysv (char *);
102007c2a45Smiod static void print_archive_filename_posix (char *);
103007c2a45Smiod static void print_archive_member_bsd (char *, const char *);
104007c2a45Smiod static void print_archive_member_sysv (char *, const char *);
105007c2a45Smiod static void print_archive_member_posix (char *, const char *);
106007c2a45Smiod static void print_symbol_filename_bsd (bfd *, bfd *);
107007c2a45Smiod static void print_symbol_filename_sysv (bfd *, bfd *);
108007c2a45Smiod static void print_symbol_filename_posix (bfd *, bfd *);
109007c2a45Smiod static void print_value (bfd *, bfd_vma);
110007c2a45Smiod static void print_symbol_info_bsd (struct extended_symbol_info *, bfd *);
111007c2a45Smiod static void print_symbol_info_sysv (struct extended_symbol_info *, bfd *);
112007c2a45Smiod static void print_symbol_info_posix (struct extended_symbol_info *, bfd *);
113007c2a45Smiod static void get_relocs (bfd *, asection *, void *);
114007c2a45Smiod static const char * get_symbol_type (unsigned int);
1152159047fSniklas
1162159047fSniklas /* Support for different output formats. */
1172159047fSniklas struct output_fns
1182159047fSniklas {
1192159047fSniklas /* Print the name of an object file given on the command line. */
120007c2a45Smiod void (*print_object_filename) (char *);
1212159047fSniklas
1222159047fSniklas /* Print the name of an archive file given on the command line. */
123007c2a45Smiod void (*print_archive_filename) (char *);
1242159047fSniklas
1252159047fSniklas /* Print the name of an archive member file. */
126007c2a45Smiod void (*print_archive_member) (char *, const char *);
1272159047fSniklas
1282159047fSniklas /* Print the name of the file (and archive, if there is one)
1292159047fSniklas containing a symbol. */
130007c2a45Smiod void (*print_symbol_filename) (bfd *, bfd *);
1312159047fSniklas
1322159047fSniklas /* Print a line of information about a symbol. */
133007c2a45Smiod void (*print_symbol_info) (struct extended_symbol_info *, bfd *);
1342159047fSniklas };
135c074d1c9Sdrahn
1362159047fSniklas static struct output_fns formats[] =
1372159047fSniklas {
1382159047fSniklas {print_object_filename_bsd,
1392159047fSniklas print_archive_filename_bsd,
1402159047fSniklas print_archive_member_bsd,
1412159047fSniklas print_symbol_filename_bsd,
1422159047fSniklas print_symbol_info_bsd},
1432159047fSniklas {print_object_filename_sysv,
1442159047fSniklas print_archive_filename_sysv,
1452159047fSniklas print_archive_member_sysv,
1462159047fSniklas print_symbol_filename_sysv,
1472159047fSniklas print_symbol_info_sysv},
1482159047fSniklas {print_object_filename_posix,
1492159047fSniklas print_archive_filename_posix,
1502159047fSniklas print_archive_member_posix,
1512159047fSniklas print_symbol_filename_posix,
1522159047fSniklas print_symbol_info_posix}
1532159047fSniklas };
1542159047fSniklas
1552159047fSniklas /* Indices in `formats'. */
1562159047fSniklas #define FORMAT_BSD 0
1572159047fSniklas #define FORMAT_SYSV 1
1582159047fSniklas #define FORMAT_POSIX 2
1592159047fSniklas #define FORMAT_DEFAULT FORMAT_BSD
1602159047fSniklas
1612159047fSniklas /* The output format to use. */
1622159047fSniklas static struct output_fns *format = &formats[FORMAT_DEFAULT];
1632159047fSniklas
1642159047fSniklas /* Command options. */
1652159047fSniklas
1662159047fSniklas static int do_demangle = 0; /* Pretty print C++ symbol names. */
167c074d1c9Sdrahn static int external_only = 0; /* Print external symbols only. */
168c074d1c9Sdrahn static int defined_only = 0; /* Print defined symbols only. */
169c074d1c9Sdrahn static int no_sort = 0; /* Don't sort; print syms in order found. */
170c074d1c9Sdrahn static int print_debug_syms = 0;/* Print debugger-only symbols too. */
171c074d1c9Sdrahn static int print_armap = 0; /* Describe __.SYMDEF data in archive files. */
172c074d1c9Sdrahn static int print_size = 0; /* Print size of defined symbols. */
173c074d1c9Sdrahn static int reverse_sort = 0; /* Sort in downward(alpha or numeric) order. */
174c074d1c9Sdrahn static int sort_numerically = 0;/* Sort in numeric rather than alpha order. */
175c074d1c9Sdrahn static int sort_by_size = 0; /* Sort by size of symbol. */
176c074d1c9Sdrahn static int undefined_only = 0; /* Print undefined symbols only. */
177c074d1c9Sdrahn static int dynamic = 0; /* Print dynamic symbols. */
178c074d1c9Sdrahn static int show_version = 0; /* Show the version number. */
179c074d1c9Sdrahn static int show_stats = 0; /* Show statistics. */
180c074d1c9Sdrahn static int line_numbers = 0; /* Print line numbers for symbols. */
1812159047fSniklas
1822159047fSniklas /* When to print the names of files. Not mutually exclusive in SYSV format. */
1832159047fSniklas static int filename_per_file = 0; /* Once per file, on its own line. */
1842159047fSniklas static int filename_per_symbol = 0; /* Once per symbol, at start of line. */
1852159047fSniklas
1862159047fSniklas /* Print formats for printing a symbol value. */
1872159047fSniklas #ifndef BFD64
1882159047fSniklas static char value_format[] = "%08lx";
1892159047fSniklas #else
1902159047fSniklas #if BFD_HOST_64BIT_LONG
1912159047fSniklas static char value_format[] = "%016lx";
1922159047fSniklas #else
1932159047fSniklas /* We don't use value_format for this case. */
1942159047fSniklas #endif
1952159047fSniklas #endif
196c074d1c9Sdrahn #ifdef BFD64
197c074d1c9Sdrahn static int print_width = 16;
198c074d1c9Sdrahn #else
199c074d1c9Sdrahn static int print_width = 8;
200c074d1c9Sdrahn #endif
2012159047fSniklas static int print_radix = 16;
2022159047fSniklas /* Print formats for printing stab info. */
2032159047fSniklas static char other_format[] = "%02x";
2042159047fSniklas static char desc_format[] = "%04x";
2052159047fSniklas
206b305b0f1Sespie static char *target = NULL;
207b305b0f1Sespie
208b305b0f1Sespie /* Used to cache the line numbers for a BFD. */
209b305b0f1Sespie static bfd *lineno_cache_bfd;
210b305b0f1Sespie static bfd *lineno_cache_rel_bfd;
211b305b0f1Sespie
212b305b0f1Sespie #define OPTION_TARGET 200
2132159047fSniklas
2142159047fSniklas static struct option long_options[] =
2152159047fSniklas {
2162159047fSniklas {"debug-syms", no_argument, &print_debug_syms, 1},
217b55d4692Sfgsch {"demangle", optional_argument, 0, 'C'},
2182159047fSniklas {"dynamic", no_argument, &dynamic, 1},
2192159047fSniklas {"extern-only", no_argument, &external_only, 1},
2202159047fSniklas {"format", required_argument, 0, 'f'},
2212159047fSniklas {"help", no_argument, 0, 'h'},
2220c6d0228Sniklas {"line-numbers", no_argument, 0, 'l'},
2232159047fSniklas {"no-cplus", no_argument, &do_demangle, 0}, /* Linux compatibility. */
2242159047fSniklas {"no-demangle", no_argument, &do_demangle, 0},
2252159047fSniklas {"no-sort", no_argument, &no_sort, 1},
2262159047fSniklas {"numeric-sort", no_argument, &sort_numerically, 1},
2272159047fSniklas {"portability", no_argument, 0, 'P'},
2282159047fSniklas {"print-armap", no_argument, &print_armap, 1},
2292159047fSniklas {"print-file-name", no_argument, 0, 'o'},
230c074d1c9Sdrahn {"print-size", no_argument, 0, 'S'},
2312159047fSniklas {"radix", required_argument, 0, 't'},
2322159047fSniklas {"reverse-sort", no_argument, &reverse_sort, 1},
2332159047fSniklas {"size-sort", no_argument, &sort_by_size, 1},
2342159047fSniklas {"stats", no_argument, &show_stats, 1},
235b305b0f1Sespie {"target", required_argument, 0, OPTION_TARGET},
236c88b1d6cSniklas {"defined-only", no_argument, &defined_only, 1},
2372159047fSniklas {"undefined-only", no_argument, &undefined_only, 1},
2382159047fSniklas {"version", no_argument, &show_version, 1},
2392159047fSniklas {0, no_argument, 0, 0}
2402159047fSniklas };
2412159047fSniklas
242c074d1c9Sdrahn /* Some error-reporting functions. */
2432159047fSniklas
244b305b0f1Sespie static void
usage(FILE * stream,int status)245007c2a45Smiod usage (FILE *stream, int status)
2462159047fSniklas {
247c074d1c9Sdrahn fprintf (stream, _("Usage: %s [option(s)] [file(s)]\n"), program_name);
248c074d1c9Sdrahn fprintf (stream, _(" List symbols in [file(s)] (a.out by default).\n"));
249c074d1c9Sdrahn fprintf (stream, _(" The options are:\n\
2506978ef19Sespie -a, --debug-syms Display debugger-only symbols\n\
2516978ef19Sespie -A, --print-file-name Print name of the input file before every symbol\n\
2526978ef19Sespie -B Same as --format=bsd\n\
253b55d4692Sfgsch -C, --demangle[=STYLE] Decode low-level symbol names into user-level names\n\
254b55d4692Sfgsch The STYLE, if specified, can be `auto' (the default),\n\
255c074d1c9Sdrahn `gnu', `lucid', `arm', `hp', `edg', `gnu-v3', `java'\n\
256c074d1c9Sdrahn or `gnat'\n\
2576978ef19Sespie --no-demangle Do not demangle low-level symbol names\n\
2586978ef19Sespie -D, --dynamic Display dynamic symbols instead of normal symbols\n\
2596978ef19Sespie --defined-only Display only defined symbols\n\
2606978ef19Sespie -e (ignored)\n\
2616978ef19Sespie -f, --format=FORMAT Use the output format FORMAT. FORMAT can be `bsd',\n\
2626978ef19Sespie `sysv' or `posix'. The default is `bsd'\n\
2636978ef19Sespie -g, --extern-only Display only external symbols\n\
2646978ef19Sespie -l, --line-numbers Use debugging information to find a filename and\n\
2656978ef19Sespie line number for each symbol\n\
2666978ef19Sespie -n, --numeric-sort Sort symbols numerically by address\n\
2676978ef19Sespie -o Same as -A\n\
2686978ef19Sespie -p, --no-sort Do not sort the symbols\n\
2696978ef19Sespie -P, --portability Same as --format=posix\n\
2706978ef19Sespie -r, --reverse-sort Reverse the sense of the sort\n\
271c074d1c9Sdrahn -S, --print-size Print size of defined symbols\n\
2726978ef19Sespie -s, --print-armap Include index for symbols from archive members\n\
2736978ef19Sespie --size-sort Sort symbols by size\n\
2746978ef19Sespie -t, --radix=RADIX Use RADIX for printing symbol values\n\
2756978ef19Sespie --target=BFDNAME Specify the target object format as BFDNAME\n\
2766978ef19Sespie -u, --undefined-only Display only undefined symbols\n\
277b55d4692Sfgsch -X 32_64 (ignored)\n\
278c074d1c9Sdrahn -h, --help Display this information\n\
279c074d1c9Sdrahn -V, --version Display this program's version number\n\
2806978ef19Sespie \n"));
2812159047fSniklas list_supported_targets (program_name, stream);
282e93f7393Sniklas if (status == 0)
2836978ef19Sespie fprintf (stream, _("Report bugs to %s.\n"), REPORT_BUGS_TO);
2842159047fSniklas exit (status);
2852159047fSniklas }
2862159047fSniklas
2872159047fSniklas /* Set the radix for the symbol value and size according to RADIX. */
2882159047fSniklas
289b305b0f1Sespie static void
set_print_radix(char * radix)290007c2a45Smiod set_print_radix (char *radix)
2912159047fSniklas {
2922159047fSniklas switch (*radix)
2932159047fSniklas {
2942159047fSniklas case 'x':
2952159047fSniklas break;
2962159047fSniklas case 'd':
2972159047fSniklas case 'o':
2982159047fSniklas if (*radix == 'd')
2992159047fSniklas print_radix = 10;
3002159047fSniklas else
3012159047fSniklas print_radix = 8;
3022159047fSniklas #ifndef BFD64
3032159047fSniklas value_format[4] = *radix;
3042159047fSniklas #else
3052159047fSniklas #if BFD_HOST_64BIT_LONG
3062159047fSniklas value_format[5] = *radix;
3072159047fSniklas #else
3082159047fSniklas /* This case requires special handling for octal and decimal
3092159047fSniklas printing. */
3102159047fSniklas #endif
3112159047fSniklas #endif
3122159047fSniklas other_format[3] = desc_format[3] = *radix;
3132159047fSniklas break;
3142159047fSniklas default:
315b305b0f1Sespie fatal (_("%s: invalid radix"), radix);
3162159047fSniklas }
3172159047fSniklas }
3182159047fSniklas
319b305b0f1Sespie static void
set_output_format(char * f)320007c2a45Smiod set_output_format (char *f)
3212159047fSniklas {
3222159047fSniklas int i;
3232159047fSniklas
3242159047fSniklas switch (*f)
3252159047fSniklas {
3262159047fSniklas case 'b':
3272159047fSniklas case 'B':
3282159047fSniklas i = FORMAT_BSD;
3292159047fSniklas break;
3302159047fSniklas case 'p':
3312159047fSniklas case 'P':
3322159047fSniklas i = FORMAT_POSIX;
3332159047fSniklas break;
3342159047fSniklas case 's':
3352159047fSniklas case 'S':
3362159047fSniklas i = FORMAT_SYSV;
3372159047fSniklas break;
3382159047fSniklas default:
339b305b0f1Sespie fatal (_("%s: invalid output format"), f);
3402159047fSniklas }
3412159047fSniklas format = &formats[i];
3422159047fSniklas }
3432159047fSniklas
344007c2a45Smiod int main (int, char **);
345c074d1c9Sdrahn
3462159047fSniklas int
main(int argc,char ** argv)347007c2a45Smiod main (int argc, char **argv)
3482159047fSniklas {
3492159047fSniklas int c;
3502159047fSniklas int retval;
3512159047fSniklas
352b305b0f1Sespie #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
353b305b0f1Sespie setlocale (LC_MESSAGES, "");
354b305b0f1Sespie #endif
355c074d1c9Sdrahn #if defined (HAVE_SETLOCALE)
356c074d1c9Sdrahn setlocale (LC_CTYPE, "");
357c074d1c9Sdrahn setlocale (LC_COLLATE, "");
358c074d1c9Sdrahn #endif
359b305b0f1Sespie bindtextdomain (PACKAGE, LOCALEDIR);
360b305b0f1Sespie textdomain (PACKAGE);
361b305b0f1Sespie
3622159047fSniklas program_name = *argv;
3632159047fSniklas xmalloc_set_program_name (program_name);
3642159047fSniklas
3652159047fSniklas START_PROGRESS (program_name, 0);
3662159047fSniklas
367*a95e6fecStobiasu expandargv (&argc, &argv);
368*a95e6fecStobiasu
3692159047fSniklas bfd_init ();
370b305b0f1Sespie set_default_bfd_target ();
3712159047fSniklas
372c074d1c9Sdrahn while ((c = getopt_long (argc, argv, "aABCDef:gHhlnopPrSst:uvVvX:",
373b55d4692Sfgsch long_options, (int *) 0)) != EOF)
3742159047fSniklas {
3752159047fSniklas switch (c)
3762159047fSniklas {
3772159047fSniklas case 'a':
3782159047fSniklas print_debug_syms = 1;
3792159047fSniklas break;
3802159047fSniklas case 'A':
3812159047fSniklas case 'o':
3822159047fSniklas filename_per_symbol = 1;
3832159047fSniklas break;
3842159047fSniklas case 'B': /* For MIPS compatibility. */
3852159047fSniklas set_output_format ("bsd");
3862159047fSniklas break;
3872159047fSniklas case 'C':
3882159047fSniklas do_demangle = 1;
389b55d4692Sfgsch if (optarg != NULL)
390b55d4692Sfgsch {
391b55d4692Sfgsch enum demangling_styles style;
392b55d4692Sfgsch
393b55d4692Sfgsch style = cplus_demangle_name_to_style (optarg);
394b55d4692Sfgsch if (style == unknown_demangling)
395b55d4692Sfgsch fatal (_("unknown demangling style `%s'"),
396b55d4692Sfgsch optarg);
397b55d4692Sfgsch
398b55d4692Sfgsch cplus_demangle_set_style (style);
399b55d4692Sfgsch }
4002159047fSniklas break;
4012159047fSniklas case 'D':
4022159047fSniklas dynamic = 1;
4032159047fSniklas break;
4042159047fSniklas case 'e':
4052159047fSniklas /* Ignored for HP/UX compatibility. */
4062159047fSniklas break;
4072159047fSniklas case 'f':
4082159047fSniklas set_output_format (optarg);
4092159047fSniklas break;
4102159047fSniklas case 'g':
4112159047fSniklas external_only = 1;
4122159047fSniklas break;
413c074d1c9Sdrahn case 'H':
4142159047fSniklas case 'h':
4152159047fSniklas usage (stdout, 0);
4160c6d0228Sniklas case 'l':
4170c6d0228Sniklas line_numbers = 1;
4180c6d0228Sniklas break;
4192159047fSniklas case 'n':
4202159047fSniklas case 'v':
4212159047fSniklas sort_numerically = 1;
4222159047fSniklas break;
4232159047fSniklas case 'p':
4242159047fSniklas no_sort = 1;
4252159047fSniklas break;
4262159047fSniklas case 'P':
4272159047fSniklas set_output_format ("posix");
4282159047fSniklas break;
4292159047fSniklas case 'r':
4302159047fSniklas reverse_sort = 1;
4312159047fSniklas break;
4322159047fSniklas case 's':
4332159047fSniklas print_armap = 1;
4342159047fSniklas break;
435c074d1c9Sdrahn case 'S':
436c074d1c9Sdrahn print_size = 1;
437c074d1c9Sdrahn break;
4382159047fSniklas case 't':
4392159047fSniklas set_print_radix (optarg);
4402159047fSniklas break;
4412159047fSniklas case 'u':
4422159047fSniklas undefined_only = 1;
4432159047fSniklas break;
4442159047fSniklas case 'V':
4452159047fSniklas show_version = 1;
4462159047fSniklas break;
447b55d4692Sfgsch case 'X':
448b55d4692Sfgsch /* Ignored for (partial) AIX compatibility. On AIX, the
449007c2a45Smiod argument has values 32, 64, or 32_64, and specifies that
450b55d4692Sfgsch only 32-bit, only 64-bit, or both kinds of objects should
451b55d4692Sfgsch be examined. The default is 32. So plain AIX nm on a
452b55d4692Sfgsch library archive with both kinds of objects will ignore
453b55d4692Sfgsch the 64-bit ones. For GNU nm, the default is and always
454b55d4692Sfgsch has been -X 32_64, and other options are not supported. */
455b55d4692Sfgsch if (strcmp (optarg, "32_64") != 0)
456b55d4692Sfgsch fatal (_("Only -X 32_64 is supported"));
457b55d4692Sfgsch break;
4582159047fSniklas
459b305b0f1Sespie case OPTION_TARGET: /* --target */
4602159047fSniklas target = optarg;
4612159047fSniklas break;
4622159047fSniklas
4632159047fSniklas case 0: /* A long option that just sets a flag. */
4642159047fSniklas break;
4652159047fSniklas
4662159047fSniklas default:
4672159047fSniklas usage (stderr, 1);
4682159047fSniklas }
4692159047fSniklas }
4702159047fSniklas
4712159047fSniklas if (show_version)
472e93f7393Sniklas print_version ("nm");
4732159047fSniklas
474c074d1c9Sdrahn if (sort_by_size && undefined_only)
475c074d1c9Sdrahn {
476c074d1c9Sdrahn non_fatal (_("Using the --size-sort and --undefined-only options together"));
477c074d1c9Sdrahn non_fatal (_("will produce no output, since undefined symbols have no size."));
478c074d1c9Sdrahn return 0;
479c074d1c9Sdrahn }
480c074d1c9Sdrahn
4812159047fSniklas /* OK, all options now parsed. If no filename specified, do a.out. */
4822159047fSniklas if (optind == argc)
4832159047fSniklas return !display_file ("a.out");
4842159047fSniklas
4852159047fSniklas retval = 0;
4862159047fSniklas
4872159047fSniklas if (argc - optind > 1)
4882159047fSniklas filename_per_file = 1;
4892159047fSniklas
4902159047fSniklas /* We were given several filenames to do. */
4912159047fSniklas while (optind < argc)
4922159047fSniklas {
4932159047fSniklas PROGRESS (1);
4942159047fSniklas if (!display_file (argv[optind++]))
4952159047fSniklas retval++;
4962159047fSniklas }
4972159047fSniklas
4982159047fSniklas END_PROGRESS (program_name);
4992159047fSniklas
5002159047fSniklas #ifdef HAVE_SBRK
5012159047fSniklas if (show_stats)
5022159047fSniklas {
5032159047fSniklas char *lim = (char *) sbrk (0);
5042159047fSniklas
505b305b0f1Sespie non_fatal (_("data size %ld"), (long) (lim - (char *) &environ));
5062159047fSniklas }
5072159047fSniklas #endif
5082159047fSniklas
5092159047fSniklas exit (retval);
5102159047fSniklas return retval;
5112159047fSniklas }
5122159047fSniklas
513c074d1c9Sdrahn static const char *
get_symbol_type(unsigned int type)514007c2a45Smiod get_symbol_type (unsigned int type)
515c074d1c9Sdrahn {
516c074d1c9Sdrahn static char buff [32];
517c074d1c9Sdrahn
518c074d1c9Sdrahn switch (type)
519c074d1c9Sdrahn {
520c074d1c9Sdrahn case STT_NOTYPE: return "NOTYPE";
521c074d1c9Sdrahn case STT_OBJECT: return "OBJECT";
522c074d1c9Sdrahn case STT_FUNC: return "FUNC";
523c074d1c9Sdrahn case STT_SECTION: return "SECTION";
524c074d1c9Sdrahn case STT_FILE: return "FILE";
525c074d1c9Sdrahn case STT_COMMON: return "COMMON";
526c074d1c9Sdrahn case STT_TLS: return "TLS";
527c074d1c9Sdrahn default:
528c074d1c9Sdrahn if (type >= STT_LOPROC && type <= STT_HIPROC)
529c074d1c9Sdrahn sprintf (buff, _("<processor specific>: %d"), type);
530c074d1c9Sdrahn else if (type >= STT_LOOS && type <= STT_HIOS)
531c074d1c9Sdrahn sprintf (buff, _("<OS specific>: %d"), type);
532c074d1c9Sdrahn else
533c074d1c9Sdrahn sprintf (buff, _("<unknown>: %d"), type);
534c074d1c9Sdrahn return buff;
535c074d1c9Sdrahn }
536c074d1c9Sdrahn }
537c074d1c9Sdrahn
5382159047fSniklas static void
display_archive(bfd * file)539007c2a45Smiod display_archive (bfd *file)
5402159047fSniklas {
5412159047fSniklas bfd *arfile = NULL;
5422159047fSniklas bfd *last_arfile = NULL;
5432159047fSniklas char **matching;
5442159047fSniklas
5452159047fSniklas (*format->print_archive_filename) (bfd_get_filename (file));
5462159047fSniklas
5472159047fSniklas if (print_armap)
5482159047fSniklas print_symdef_entry (file);
5492159047fSniklas
5502159047fSniklas for (;;)
5512159047fSniklas {
5522159047fSniklas PROGRESS (1);
5532159047fSniklas
5542159047fSniklas arfile = bfd_openr_next_archived_file (file, arfile);
5552159047fSniklas
5562159047fSniklas if (arfile == NULL)
5572159047fSniklas {
5582159047fSniklas if (bfd_get_error () != bfd_error_no_more_archived_files)
5592159047fSniklas bfd_fatal (bfd_get_filename (file));
5602159047fSniklas break;
5612159047fSniklas }
5622159047fSniklas
5632159047fSniklas if (bfd_check_format_matches (arfile, bfd_object, &matching))
5642159047fSniklas {
565c074d1c9Sdrahn char buf[30];
566c074d1c9Sdrahn
567c074d1c9Sdrahn bfd_sprintf_vma (arfile, buf, (bfd_vma) -1);
568c074d1c9Sdrahn print_width = strlen (buf);
5692159047fSniklas (*format->print_archive_member) (bfd_get_filename (file),
5702159047fSniklas bfd_get_filename (arfile));
5712159047fSniklas display_rel_file (arfile, file);
5722159047fSniklas }
5732159047fSniklas else
5742159047fSniklas {
5752159047fSniklas bfd_nonfatal (bfd_get_filename (arfile));
5762159047fSniklas if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
5772159047fSniklas {
5782159047fSniklas list_matching_formats (matching);
5792159047fSniklas free (matching);
5802159047fSniklas }
5812159047fSniklas }
5822159047fSniklas
5832159047fSniklas if (last_arfile != NULL)
584b305b0f1Sespie {
5852159047fSniklas bfd_close (last_arfile);
586b305b0f1Sespie lineno_cache_bfd = NULL;
587b305b0f1Sespie lineno_cache_rel_bfd = NULL;
588b305b0f1Sespie }
5892159047fSniklas last_arfile = arfile;
5902159047fSniklas }
5912159047fSniklas
5922159047fSniklas if (last_arfile != NULL)
593b305b0f1Sespie {
5942159047fSniklas bfd_close (last_arfile);
595b305b0f1Sespie lineno_cache_bfd = NULL;
596b305b0f1Sespie lineno_cache_rel_bfd = NULL;
597b305b0f1Sespie }
5982159047fSniklas }
5992159047fSniklas
600c074d1c9Sdrahn static bfd_boolean
display_file(char * filename)601007c2a45Smiod display_file (char *filename)
6022159047fSniklas {
603c074d1c9Sdrahn bfd_boolean retval = TRUE;
6042159047fSniklas bfd *file;
6052159047fSniklas char **matching;
6062159047fSniklas
607007c2a45Smiod if (get_file_size (filename) < 1)
608007c2a45Smiod return FALSE;
609007c2a45Smiod
6102159047fSniklas file = bfd_openr (filename, target);
6112159047fSniklas if (file == NULL)
6122159047fSniklas {
6132159047fSniklas bfd_nonfatal (filename);
614c074d1c9Sdrahn return FALSE;
6152159047fSniklas }
6162159047fSniklas
6172159047fSniklas if (bfd_check_format (file, bfd_archive))
6182159047fSniklas {
6192159047fSniklas display_archive (file);
6202159047fSniklas }
6212159047fSniklas else if (bfd_check_format_matches (file, bfd_object, &matching))
6222159047fSniklas {
623c074d1c9Sdrahn char buf[30];
624c074d1c9Sdrahn
625c074d1c9Sdrahn bfd_sprintf_vma (file, buf, (bfd_vma) -1);
626c074d1c9Sdrahn print_width = strlen (buf);
6272159047fSniklas (*format->print_object_filename) (filename);
6282159047fSniklas display_rel_file (file, NULL);
6292159047fSniklas }
6302159047fSniklas else
6312159047fSniklas {
6322159047fSniklas bfd_nonfatal (filename);
6332159047fSniklas if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
6342159047fSniklas {
6352159047fSniklas list_matching_formats (matching);
6362159047fSniklas free (matching);
6372159047fSniklas }
638c074d1c9Sdrahn retval = FALSE;
6392159047fSniklas }
6402159047fSniklas
641c074d1c9Sdrahn if (!bfd_close (file))
6422159047fSniklas bfd_fatal (filename);
6432159047fSniklas
644b305b0f1Sespie lineno_cache_bfd = NULL;
645b305b0f1Sespie lineno_cache_rel_bfd = NULL;
646b305b0f1Sespie
6472159047fSniklas return retval;
6482159047fSniklas }
6492159047fSniklas
6502159047fSniklas /* These globals are used to pass information into the sorting
6512159047fSniklas routines. */
6522159047fSniklas static bfd *sort_bfd;
653c074d1c9Sdrahn static bfd_boolean sort_dynamic;
6542159047fSniklas static asymbol *sort_x;
6552159047fSniklas static asymbol *sort_y;
6562159047fSniklas
6572159047fSniklas /* Symbol-sorting predicates */
6582159047fSniklas #define valueof(x) ((x)->section->vma + (x)->value)
6592159047fSniklas
6602159047fSniklas /* Numeric sorts. Undefined symbols are always considered "less than"
6612159047fSniklas defined symbols with zero values. Common symbols are not treated
6622159047fSniklas specially -- i.e., their sizes are used as their "values". */
6632159047fSniklas
6642159047fSniklas static int
numeric_forward(const void * P_x,const void * P_y)665007c2a45Smiod numeric_forward (const void *P_x, const void *P_y)
6662159047fSniklas {
6672159047fSniklas asymbol *x, *y;
6682159047fSniklas asection *xs, *ys;
6692159047fSniklas
6702159047fSniklas x = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_x, sort_x);
6712159047fSniklas y = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_y, sort_y);
6722159047fSniklas if (x == NULL || y == NULL)
6732159047fSniklas bfd_fatal (bfd_get_filename (sort_bfd));
6742159047fSniklas
6752159047fSniklas xs = bfd_get_section (x);
6762159047fSniklas ys = bfd_get_section (y);
6772159047fSniklas
6782159047fSniklas if (bfd_is_und_section (xs))
6792159047fSniklas {
6802159047fSniklas if (! bfd_is_und_section (ys))
6812159047fSniklas return -1;
6822159047fSniklas }
6832159047fSniklas else if (bfd_is_und_section (ys))
6842159047fSniklas return 1;
6852159047fSniklas else if (valueof (x) != valueof (y))
6862159047fSniklas return valueof (x) < valueof (y) ? -1 : 1;
6872159047fSniklas
6882159047fSniklas return non_numeric_forward (P_x, P_y);
6892159047fSniklas }
6902159047fSniklas
6912159047fSniklas static int
numeric_reverse(const void * x,const void * y)692007c2a45Smiod numeric_reverse (const void *x, const void *y)
6932159047fSniklas {
6942159047fSniklas return - numeric_forward (x, y);
6952159047fSniklas }
6962159047fSniklas
6972159047fSniklas static int
non_numeric_forward(const void * P_x,const void * P_y)698007c2a45Smiod non_numeric_forward (const void *P_x, const void *P_y)
6992159047fSniklas {
7002159047fSniklas asymbol *x, *y;
7012159047fSniklas const char *xn, *yn;
7022159047fSniklas
7032159047fSniklas x = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_x, sort_x);
7042159047fSniklas y = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_y, sort_y);
7052159047fSniklas if (x == NULL || y == NULL)
7062159047fSniklas bfd_fatal (bfd_get_filename (sort_bfd));
7072159047fSniklas
7082159047fSniklas xn = bfd_asymbol_name (x);
7092159047fSniklas yn = bfd_asymbol_name (y);
7102159047fSniklas
711c074d1c9Sdrahn if (yn == NULL)
712c074d1c9Sdrahn return xn != NULL;
713c074d1c9Sdrahn if (xn == NULL)
714c074d1c9Sdrahn return -1;
715c074d1c9Sdrahn
716c074d1c9Sdrahn #ifdef HAVE_STRCOLL
717c074d1c9Sdrahn /* Solaris 2.5 has a bug in strcoll.
718c074d1c9Sdrahn strcoll returns invalid values when confronted with empty strings. */
719c074d1c9Sdrahn if (*yn == '\0')
720c074d1c9Sdrahn return *xn != '\0';
721c074d1c9Sdrahn if (*xn == '\0')
722c074d1c9Sdrahn return -1;
723c074d1c9Sdrahn
724c074d1c9Sdrahn return strcoll (xn, yn);
725c074d1c9Sdrahn #else
726c074d1c9Sdrahn return strcmp (xn, yn);
727c074d1c9Sdrahn #endif
7282159047fSniklas }
7292159047fSniklas
7302159047fSniklas static int
non_numeric_reverse(const void * x,const void * y)731007c2a45Smiod non_numeric_reverse (const void *x, const void *y)
7322159047fSniklas {
7332159047fSniklas return - non_numeric_forward (x, y);
7342159047fSniklas }
7352159047fSniklas
736007c2a45Smiod static int (*(sorters[2][2])) (const void *, const void *) =
7372159047fSniklas {
7382159047fSniklas { non_numeric_forward, non_numeric_reverse },
7392159047fSniklas { numeric_forward, numeric_reverse }
7402159047fSniklas };
7412159047fSniklas
7422159047fSniklas /* This sort routine is used by sort_symbols_by_size. It is similar
7432159047fSniklas to numeric_forward, but when symbols have the same value it sorts
7442159047fSniklas by section VMA. This simplifies the sort_symbols_by_size code
7452159047fSniklas which handles symbols at the end of sections. Also, this routine
7462159047fSniklas tries to sort file names before other symbols with the same value.
7472159047fSniklas That will make the file name have a zero size, which will make
7482159047fSniklas sort_symbols_by_size choose the non file name symbol, leading to
7492159047fSniklas more meaningful output. For similar reasons, this code sorts
7502159047fSniklas gnu_compiled_* and gcc2_compiled before other symbols with the same
7512159047fSniklas value. */
7522159047fSniklas
7532159047fSniklas static int
size_forward1(const void * P_x,const void * P_y)754007c2a45Smiod size_forward1 (const void *P_x, const void *P_y)
7552159047fSniklas {
7562159047fSniklas asymbol *x, *y;
7572159047fSniklas asection *xs, *ys;
7582159047fSniklas const char *xn, *yn;
7592159047fSniklas size_t xnl, ynl;
7602159047fSniklas int xf, yf;
7612159047fSniklas
7622159047fSniklas x = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_x, sort_x);
7632159047fSniklas y = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_y, sort_y);
7642159047fSniklas if (x == NULL || y == NULL)
7652159047fSniklas bfd_fatal (bfd_get_filename (sort_bfd));
7662159047fSniklas
7672159047fSniklas xs = bfd_get_section (x);
7682159047fSniklas ys = bfd_get_section (y);
7692159047fSniklas
7702159047fSniklas if (bfd_is_und_section (xs))
7712159047fSniklas abort ();
7722159047fSniklas if (bfd_is_und_section (ys))
7732159047fSniklas abort ();
7742159047fSniklas
7752159047fSniklas if (valueof (x) != valueof (y))
7762159047fSniklas return valueof (x) < valueof (y) ? -1 : 1;
7772159047fSniklas
7782159047fSniklas if (xs->vma != ys->vma)
7792159047fSniklas return xs->vma < ys->vma ? -1 : 1;
7802159047fSniklas
7812159047fSniklas xn = bfd_asymbol_name (x);
7822159047fSniklas yn = bfd_asymbol_name (y);
7832159047fSniklas xnl = strlen (xn);
7842159047fSniklas ynl = strlen (yn);
7852159047fSniklas
7862159047fSniklas /* The symbols gnu_compiled and gcc2_compiled convey even less
7872159047fSniklas information than the file name, so sort them out first. */
7882159047fSniklas
7892159047fSniklas xf = (strstr (xn, "gnu_compiled") != NULL
7902159047fSniklas || strstr (xn, "gcc2_compiled") != NULL);
7912159047fSniklas yf = (strstr (yn, "gnu_compiled") != NULL
7922159047fSniklas || strstr (yn, "gcc2_compiled") != NULL);
7932159047fSniklas
7942159047fSniklas if (xf && ! yf)
7952159047fSniklas return -1;
7962159047fSniklas if (! xf && yf)
7972159047fSniklas return 1;
7982159047fSniklas
7992159047fSniklas /* We use a heuristic for the file name. It may not work on non
8002159047fSniklas Unix systems, but it doesn't really matter; the only difference
8012159047fSniklas is precisely which symbol names get printed. */
8022159047fSniklas
8032159047fSniklas #define file_symbol(s, sn, snl) \
8042159047fSniklas (((s)->flags & BSF_FILE) != 0 \
8052159047fSniklas || ((sn)[(snl) - 2] == '.' \
8062159047fSniklas && ((sn)[(snl) - 1] == 'o' \
8072159047fSniklas || (sn)[(snl) - 1] == 'a')))
8082159047fSniklas
8092159047fSniklas xf = file_symbol (x, xn, xnl);
8102159047fSniklas yf = file_symbol (y, yn, ynl);
8112159047fSniklas
8122159047fSniklas if (xf && ! yf)
8132159047fSniklas return -1;
8142159047fSniklas if (! xf && yf)
8152159047fSniklas return 1;
8162159047fSniklas
8172159047fSniklas return non_numeric_forward (P_x, P_y);
8182159047fSniklas }
8192159047fSniklas
8202159047fSniklas /* This sort routine is used by sort_symbols_by_size. It is sorting
8212159047fSniklas an array of size_sym structures into size order. */
8222159047fSniklas
8232159047fSniklas static int
size_forward2(const void * P_x,const void * P_y)824007c2a45Smiod size_forward2 (const void *P_x, const void *P_y)
8252159047fSniklas {
8262159047fSniklas const struct size_sym *x = (const struct size_sym *) P_x;
8272159047fSniklas const struct size_sym *y = (const struct size_sym *) P_y;
8282159047fSniklas
8292159047fSniklas if (x->size < y->size)
8302159047fSniklas return reverse_sort ? 1 : -1;
8312159047fSniklas else if (x->size > y->size)
8322159047fSniklas return reverse_sort ? -1 : 1;
8332159047fSniklas else
8342159047fSniklas return sorters[0][reverse_sort] (x->minisym, y->minisym);
8352159047fSniklas }
8362159047fSniklas
837c074d1c9Sdrahn /* Sort the symbols by size. ELF provides a size but for other formats
838c074d1c9Sdrahn we have to make a guess by assuming that the difference between the
839c074d1c9Sdrahn address of a symbol and the address of the next higher symbol is the
840c074d1c9Sdrahn size. */
8412159047fSniklas
8422159047fSniklas static long
sort_symbols_by_size(bfd * abfd,bfd_boolean dynamic,void * minisyms,long symcount,unsigned int size,struct size_sym ** symsizesp)843007c2a45Smiod sort_symbols_by_size (bfd *abfd, bfd_boolean dynamic, void *minisyms,
844007c2a45Smiod long symcount, unsigned int size,
845007c2a45Smiod struct size_sym **symsizesp)
8462159047fSniklas {
8472159047fSniklas struct size_sym *symsizes;
8482159047fSniklas bfd_byte *from, *fromend;
849b305b0f1Sespie asymbol *sym = NULL;
8502159047fSniklas asymbol *store_sym, *store_next;
8512159047fSniklas
8522159047fSniklas qsort (minisyms, symcount, size, size_forward1);
8532159047fSniklas
8542159047fSniklas /* We are going to return a special set of symbols and sizes to
8552159047fSniklas print. */
8562159047fSniklas symsizes = (struct size_sym *) xmalloc (symcount * sizeof (struct size_sym));
8572159047fSniklas *symsizesp = symsizes;
8582159047fSniklas
8592159047fSniklas /* Note that filter_symbols has already removed all absolute and
8602159047fSniklas undefined symbols. Here we remove all symbols whose size winds
8612159047fSniklas up as zero. */
8622159047fSniklas from = (bfd_byte *) minisyms;
8632159047fSniklas fromend = from + symcount * size;
8642159047fSniklas
8652159047fSniklas store_sym = sort_x;
8662159047fSniklas store_next = sort_y;
8672159047fSniklas
8682159047fSniklas if (from < fromend)
8692159047fSniklas {
870007c2a45Smiod sym = bfd_minisymbol_to_symbol (abfd, dynamic, (const void *) from,
8712159047fSniklas store_sym);
8722159047fSniklas if (sym == NULL)
8732159047fSniklas bfd_fatal (bfd_get_filename (abfd));
8742159047fSniklas }
8752159047fSniklas
8762159047fSniklas for (; from < fromend; from += size)
8772159047fSniklas {
8782159047fSniklas asymbol *next;
8792159047fSniklas asection *sec;
8802159047fSniklas bfd_vma sz;
8812159047fSniklas asymbol *temp;
8822159047fSniklas
8832159047fSniklas if (from + size < fromend)
8842159047fSniklas {
8852159047fSniklas next = bfd_minisymbol_to_symbol (abfd,
8862159047fSniklas dynamic,
887007c2a45Smiod (const void *) (from + size),
8882159047fSniklas store_next);
8892159047fSniklas if (next == NULL)
8902159047fSniklas bfd_fatal (bfd_get_filename (abfd));
8912159047fSniklas }
8920c6d0228Sniklas else
8930c6d0228Sniklas next = NULL;
8942159047fSniklas
8952159047fSniklas sec = bfd_get_section (sym);
8962159047fSniklas
897c074d1c9Sdrahn if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
898c074d1c9Sdrahn sz = ((elf_symbol_type *) sym)->internal_elf_sym.st_size;
899c074d1c9Sdrahn else if (bfd_is_com_section (sec))
9002159047fSniklas sz = sym->value;
9012159047fSniklas else
9022159047fSniklas {
9032159047fSniklas if (from + size < fromend
9042159047fSniklas && sec == bfd_get_section (next))
9052159047fSniklas sz = valueof (next) - valueof (sym);
9062159047fSniklas else
9072159047fSniklas sz = (bfd_get_section_vma (abfd, sec)
9082159047fSniklas + bfd_section_size (abfd, sec)
9092159047fSniklas - valueof (sym));
9102159047fSniklas }
9112159047fSniklas
9122159047fSniklas if (sz != 0)
9132159047fSniklas {
914007c2a45Smiod symsizes->minisym = (const void *) from;
9152159047fSniklas symsizes->size = sz;
9162159047fSniklas ++symsizes;
9172159047fSniklas }
9182159047fSniklas
9192159047fSniklas sym = next;
9202159047fSniklas
9212159047fSniklas temp = store_sym;
9222159047fSniklas store_sym = store_next;
9232159047fSniklas store_next = temp;
9242159047fSniklas }
9252159047fSniklas
9262159047fSniklas symcount = symsizes - *symsizesp;
9272159047fSniklas
9282159047fSniklas /* We must now sort again by size. */
929007c2a45Smiod qsort ((void *) *symsizesp, symcount, sizeof (struct size_sym), size_forward2);
9302159047fSniklas
9312159047fSniklas return symcount;
9322159047fSniklas }
9332159047fSniklas
9342159047fSniklas /* If ARCHIVE_BFD is non-NULL, it is the archive containing ABFD. */
9352159047fSniklas
9362159047fSniklas static void
display_rel_file(bfd * abfd,bfd * archive_bfd)937007c2a45Smiod display_rel_file (bfd *abfd, bfd *archive_bfd)
9382159047fSniklas {
9392159047fSniklas long symcount;
940007c2a45Smiod void *minisyms;
9412159047fSniklas unsigned int size;
9422159047fSniklas struct size_sym *symsizes;
9432159047fSniklas
9442159047fSniklas if (! dynamic)
9452159047fSniklas {
9462159047fSniklas if (!(bfd_get_file_flags (abfd) & HAS_SYMS))
9472159047fSniklas {
948b305b0f1Sespie non_fatal (_("%s: no symbols"), bfd_get_filename (abfd));
9492159047fSniklas return;
9502159047fSniklas }
9512159047fSniklas }
9522159047fSniklas
9532159047fSniklas symcount = bfd_read_minisymbols (abfd, dynamic, &minisyms, &size);
9542159047fSniklas if (symcount < 0)
9552159047fSniklas bfd_fatal (bfd_get_filename (abfd));
9562159047fSniklas
9572159047fSniklas if (symcount == 0)
9582159047fSniklas {
959b305b0f1Sespie non_fatal (_("%s: no symbols"), bfd_get_filename (abfd));
9602159047fSniklas return;
9612159047fSniklas }
9622159047fSniklas
9632159047fSniklas /* Discard the symbols we don't want to print.
9642159047fSniklas It's OK to do this in place; we'll free the storage anyway
9652159047fSniklas (after printing). */
9662159047fSniklas
9672159047fSniklas symcount = filter_symbols (abfd, dynamic, minisyms, symcount, size);
9682159047fSniklas
9692159047fSniklas symsizes = NULL;
9702159047fSniklas if (! no_sort)
9712159047fSniklas {
9722159047fSniklas sort_bfd = abfd;
9732159047fSniklas sort_dynamic = dynamic;
9742159047fSniklas sort_x = bfd_make_empty_symbol (abfd);
9752159047fSniklas sort_y = bfd_make_empty_symbol (abfd);
9762159047fSniklas if (sort_x == NULL || sort_y == NULL)
9772159047fSniklas bfd_fatal (bfd_get_filename (abfd));
9782159047fSniklas
9792159047fSniklas if (! sort_by_size)
9802159047fSniklas qsort (minisyms, symcount, size,
9812159047fSniklas sorters[sort_numerically][reverse_sort]);
9822159047fSniklas else
9832159047fSniklas symcount = sort_symbols_by_size (abfd, dynamic, minisyms, symcount,
9842159047fSniklas size, &symsizes);
9852159047fSniklas }
9862159047fSniklas
9872159047fSniklas if (! sort_by_size)
9882159047fSniklas print_symbols (abfd, dynamic, minisyms, symcount, size, archive_bfd);
9892159047fSniklas else
9902159047fSniklas print_size_symbols (abfd, dynamic, symsizes, symcount, archive_bfd);
9912159047fSniklas
9922159047fSniklas free (minisyms);
9932159047fSniklas }
9942159047fSniklas
9952159047fSniklas /* Choose which symbol entries to print;
9962159047fSniklas compact them downward to get rid of the rest.
9972159047fSniklas Return the number of symbols to be printed. */
9982159047fSniklas
9992159047fSniklas static long
filter_symbols(bfd * abfd,bfd_boolean dynamic,void * minisyms,long symcount,unsigned int size)1000007c2a45Smiod filter_symbols (bfd *abfd, bfd_boolean dynamic, void *minisyms,
1001007c2a45Smiod long symcount, unsigned int size)
10022159047fSniklas {
10032159047fSniklas bfd_byte *from, *fromend, *to;
10042159047fSniklas asymbol *store;
10052159047fSniklas
10062159047fSniklas store = bfd_make_empty_symbol (abfd);
10072159047fSniklas if (store == NULL)
10082159047fSniklas bfd_fatal (bfd_get_filename (abfd));
10092159047fSniklas
10102159047fSniklas from = (bfd_byte *) minisyms;
10112159047fSniklas fromend = from + symcount * size;
10122159047fSniklas to = (bfd_byte *) minisyms;
10132159047fSniklas
10142159047fSniklas for (; from < fromend; from += size)
10152159047fSniklas {
10162159047fSniklas int keep = 0;
10172159047fSniklas asymbol *sym;
10182159047fSniklas
10192159047fSniklas PROGRESS (1);
10202159047fSniklas
1021007c2a45Smiod sym = bfd_minisymbol_to_symbol (abfd, dynamic, (const void *) from, store);
10222159047fSniklas if (sym == NULL)
10232159047fSniklas bfd_fatal (bfd_get_filename (abfd));
10242159047fSniklas
10252159047fSniklas if (undefined_only)
10262159047fSniklas keep = bfd_is_und_section (sym->section);
10272159047fSniklas else if (external_only)
10282159047fSniklas keep = ((sym->flags & BSF_GLOBAL) != 0
1029c88b1d6cSniklas || (sym->flags & BSF_WEAK) != 0
10302159047fSniklas || bfd_is_und_section (sym->section)
10312159047fSniklas || bfd_is_com_section (sym->section));
10322159047fSniklas else
10332159047fSniklas keep = 1;
10342159047fSniklas
10352159047fSniklas if (keep
10362159047fSniklas && ! print_debug_syms
10372159047fSniklas && (sym->flags & BSF_DEBUGGING) != 0)
10382159047fSniklas keep = 0;
10392159047fSniklas
10402159047fSniklas if (keep
10412159047fSniklas && sort_by_size
10422159047fSniklas && (bfd_is_abs_section (sym->section)
10432159047fSniklas || bfd_is_und_section (sym->section)))
10442159047fSniklas keep = 0;
10452159047fSniklas
1046c88b1d6cSniklas if (keep
1047c88b1d6cSniklas && defined_only)
1048c88b1d6cSniklas {
1049c88b1d6cSniklas if (bfd_is_und_section (sym->section))
1050c88b1d6cSniklas keep = 0;
1051c88b1d6cSniklas }
1052c88b1d6cSniklas
10532159047fSniklas if (keep)
10542159047fSniklas {
10552159047fSniklas memcpy (to, from, size);
10562159047fSniklas to += size;
10572159047fSniklas }
10582159047fSniklas }
10592159047fSniklas
10602159047fSniklas return (to - (bfd_byte *) minisyms) / size;
10612159047fSniklas }
10622159047fSniklas
10632159047fSniklas /* Print symbol name NAME, read from ABFD, with printf format FORMAT,
10642159047fSniklas demangling it if requested. */
10652159047fSniklas
10662159047fSniklas static void
print_symname(const char * format,const char * name,bfd * abfd)1067007c2a45Smiod print_symname (const char *format, const char *name, bfd *abfd)
10682159047fSniklas {
10692159047fSniklas if (do_demangle && *name)
10702159047fSniklas {
1071c074d1c9Sdrahn char *res = demangle (abfd, name);
10722159047fSniklas
10732159047fSniklas printf (format, res);
10742159047fSniklas free (res);
10752159047fSniklas return;
10762159047fSniklas }
10772159047fSniklas
10782159047fSniklas printf (format, name);
10792159047fSniklas }
10802159047fSniklas
10812159047fSniklas /* Print the symbols. If ARCHIVE_BFD is non-NULL, it is the archive
10822159047fSniklas containing ABFD. */
10832159047fSniklas
10842159047fSniklas static void
print_symbols(bfd * abfd,bfd_boolean dynamic,void * minisyms,long symcount,unsigned int size,bfd * archive_bfd)1085007c2a45Smiod print_symbols (bfd *abfd, bfd_boolean dynamic, void *minisyms, long symcount,
1086007c2a45Smiod unsigned int size, bfd *archive_bfd)
10872159047fSniklas {
10882159047fSniklas asymbol *store;
10892159047fSniklas bfd_byte *from, *fromend;
10902159047fSniklas
10912159047fSniklas store = bfd_make_empty_symbol (abfd);
10922159047fSniklas if (store == NULL)
10932159047fSniklas bfd_fatal (bfd_get_filename (abfd));
10942159047fSniklas
10952159047fSniklas from = (bfd_byte *) minisyms;
10962159047fSniklas fromend = from + symcount * size;
10972159047fSniklas for (; from < fromend; from += size)
10982159047fSniklas {
10992159047fSniklas asymbol *sym;
11002159047fSniklas
11012159047fSniklas sym = bfd_minisymbol_to_symbol (abfd, dynamic, from, store);
11022159047fSniklas if (sym == NULL)
11032159047fSniklas bfd_fatal (bfd_get_filename (abfd));
11042159047fSniklas
1105c074d1c9Sdrahn print_symbol (abfd, sym, (bfd_vma) 0, archive_bfd);
11062159047fSniklas }
11072159047fSniklas }
11082159047fSniklas
11092159047fSniklas /* Print the symbols when sorting by size. */
11102159047fSniklas
11112159047fSniklas static void
print_size_symbols(bfd * abfd,bfd_boolean dynamic,struct size_sym * symsizes,long symcount,bfd * archive_bfd)1112007c2a45Smiod print_size_symbols (bfd *abfd, bfd_boolean dynamic,
1113007c2a45Smiod struct size_sym *symsizes, long symcount,
1114007c2a45Smiod bfd *archive_bfd)
11152159047fSniklas {
11162159047fSniklas asymbol *store;
11172159047fSniklas struct size_sym *from, *fromend;
11182159047fSniklas
11192159047fSniklas store = bfd_make_empty_symbol (abfd);
11202159047fSniklas if (store == NULL)
11212159047fSniklas bfd_fatal (bfd_get_filename (abfd));
11222159047fSniklas
11232159047fSniklas from = symsizes;
11242159047fSniklas fromend = from + symcount;
11252159047fSniklas for (; from < fromend; from++)
11262159047fSniklas {
11272159047fSniklas asymbol *sym;
1128c074d1c9Sdrahn bfd_vma ssize;
11292159047fSniklas
11302159047fSniklas sym = bfd_minisymbol_to_symbol (abfd, dynamic, from->minisym, store);
11312159047fSniklas if (sym == NULL)
11322159047fSniklas bfd_fatal (bfd_get_filename (abfd));
11332159047fSniklas
1134c074d1c9Sdrahn /* For elf we have already computed the correct symbol size. */
1135c074d1c9Sdrahn if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
1136c074d1c9Sdrahn ssize = from->size;
1137c074d1c9Sdrahn else
1138c074d1c9Sdrahn ssize = from->size - bfd_section_vma (abfd, bfd_get_section (sym));
11392159047fSniklas
1140c074d1c9Sdrahn print_symbol (abfd, sym, ssize, archive_bfd);
11412159047fSniklas }
11422159047fSniklas }
11432159047fSniklas
11442159047fSniklas /* Print a single symbol. */
11452159047fSniklas
11462159047fSniklas static void
print_symbol(bfd * abfd,asymbol * sym,bfd_vma ssize,bfd * archive_bfd)1147007c2a45Smiod print_symbol (bfd *abfd, asymbol *sym, bfd_vma ssize, bfd *archive_bfd)
11482159047fSniklas {
1149c074d1c9Sdrahn symbol_info syminfo;
1150c074d1c9Sdrahn struct extended_symbol_info info;
1151c074d1c9Sdrahn
11522159047fSniklas PROGRESS (1);
11532159047fSniklas
11542159047fSniklas (*format->print_symbol_filename) (archive_bfd, abfd);
11552159047fSniklas
11562159047fSniklas bfd_get_symbol_info (abfd, sym, &syminfo);
1157c074d1c9Sdrahn info.sinfo = &syminfo;
1158c074d1c9Sdrahn info.ssize = ssize;
1159c074d1c9Sdrahn if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
1160c074d1c9Sdrahn info.elfinfo = (elf_symbol_type *) sym;
1161c074d1c9Sdrahn else
1162c074d1c9Sdrahn info.elfinfo = NULL;
1163c074d1c9Sdrahn (*format->print_symbol_info) (&info, abfd);
11640c6d0228Sniklas
11650c6d0228Sniklas if (line_numbers)
11660c6d0228Sniklas {
11670c6d0228Sniklas static asymbol **syms;
11680c6d0228Sniklas static long symcount;
11690c6d0228Sniklas const char *filename, *functionname;
11700c6d0228Sniklas unsigned int lineno;
11710c6d0228Sniklas
11720c6d0228Sniklas /* We need to get the canonical symbols in order to call
11730c6d0228Sniklas bfd_find_nearest_line. This is inefficient, but, then, you
11740c6d0228Sniklas don't have to use --line-numbers. */
1175b305b0f1Sespie if (abfd != lineno_cache_bfd && syms != NULL)
1176b305b0f1Sespie {
1177b305b0f1Sespie free (syms);
1178b305b0f1Sespie syms = NULL;
1179b305b0f1Sespie }
11800c6d0228Sniklas if (syms == NULL)
11810c6d0228Sniklas {
11820c6d0228Sniklas long symsize;
11830c6d0228Sniklas
11840c6d0228Sniklas symsize = bfd_get_symtab_upper_bound (abfd);
11850c6d0228Sniklas if (symsize < 0)
11860c6d0228Sniklas bfd_fatal (bfd_get_filename (abfd));
11870c6d0228Sniklas syms = (asymbol **) xmalloc (symsize);
11880c6d0228Sniklas symcount = bfd_canonicalize_symtab (abfd, syms);
11890c6d0228Sniklas if (symcount < 0)
11900c6d0228Sniklas bfd_fatal (bfd_get_filename (abfd));
1191b305b0f1Sespie lineno_cache_bfd = abfd;
11920c6d0228Sniklas }
11930c6d0228Sniklas
11940c6d0228Sniklas if (bfd_is_und_section (bfd_get_section (sym)))
11950c6d0228Sniklas {
11960c6d0228Sniklas static asection **secs;
11970c6d0228Sniklas static arelent ***relocs;
11980c6d0228Sniklas static long *relcount;
1199b305b0f1Sespie static unsigned int seccount;
1200b305b0f1Sespie unsigned int i;
12010c6d0228Sniklas const char *symname;
12020c6d0228Sniklas
12030c6d0228Sniklas /* For an undefined symbol, we try to find a reloc for the
12040c6d0228Sniklas symbol, and print the line number of the reloc. */
1205b305b0f1Sespie if (abfd != lineno_cache_rel_bfd && relocs != NULL)
1206b305b0f1Sespie {
1207b305b0f1Sespie for (i = 0; i < seccount; i++)
1208b305b0f1Sespie if (relocs[i] != NULL)
1209b305b0f1Sespie free (relocs[i]);
1210b305b0f1Sespie free (secs);
1211b305b0f1Sespie free (relocs);
1212b305b0f1Sespie free (relcount);
1213b305b0f1Sespie secs = NULL;
1214b305b0f1Sespie relocs = NULL;
1215b305b0f1Sespie relcount = NULL;
1216b305b0f1Sespie }
12170c6d0228Sniklas
12180c6d0228Sniklas if (relocs == NULL)
12190c6d0228Sniklas {
12200c6d0228Sniklas struct get_relocs_info info;
12210c6d0228Sniklas
1222b305b0f1Sespie seccount = bfd_count_sections (abfd);
1223b305b0f1Sespie
12240c6d0228Sniklas secs = (asection **) xmalloc (seccount * sizeof *secs);
12250c6d0228Sniklas relocs = (arelent ***) xmalloc (seccount * sizeof *relocs);
12260c6d0228Sniklas relcount = (long *) xmalloc (seccount * sizeof *relcount);
12270c6d0228Sniklas
12280c6d0228Sniklas info.secs = secs;
12290c6d0228Sniklas info.relocs = relocs;
12300c6d0228Sniklas info.relcount = relcount;
12310c6d0228Sniklas info.syms = syms;
1232007c2a45Smiod bfd_map_over_sections (abfd, get_relocs, (void *) &info);
1233b305b0f1Sespie lineno_cache_rel_bfd = abfd;
12340c6d0228Sniklas }
12350c6d0228Sniklas
12360c6d0228Sniklas symname = bfd_asymbol_name (sym);
12370c6d0228Sniklas for (i = 0; i < seccount; i++)
12380c6d0228Sniklas {
1239b305b0f1Sespie long j;
12400c6d0228Sniklas
12410c6d0228Sniklas for (j = 0; j < relcount[i]; j++)
12420c6d0228Sniklas {
12430c6d0228Sniklas arelent *r;
12440c6d0228Sniklas
12450c6d0228Sniklas r = relocs[i][j];
12460c6d0228Sniklas if (r->sym_ptr_ptr != NULL
12470c6d0228Sniklas && (*r->sym_ptr_ptr)->section == sym->section
12480c6d0228Sniklas && (*r->sym_ptr_ptr)->value == sym->value
12490c6d0228Sniklas && strcmp (symname,
12500c6d0228Sniklas bfd_asymbol_name (*r->sym_ptr_ptr)) == 0
12510c6d0228Sniklas && bfd_find_nearest_line (abfd, secs[i], syms,
12520c6d0228Sniklas r->address, &filename,
1253c074d1c9Sdrahn &functionname, &lineno)
1254c074d1c9Sdrahn && filename != NULL)
12550c6d0228Sniklas {
12560c6d0228Sniklas /* We only print the first one we find. */
12570c6d0228Sniklas printf ("\t%s:%u", filename, lineno);
12580c6d0228Sniklas i = seccount;
12590c6d0228Sniklas break;
12600c6d0228Sniklas }
12610c6d0228Sniklas }
12620c6d0228Sniklas }
12630c6d0228Sniklas }
12640c6d0228Sniklas else if (bfd_get_section (sym)->owner == abfd)
12650c6d0228Sniklas {
12660c6d0228Sniklas if (bfd_find_nearest_line (abfd, bfd_get_section (sym), syms,
12670c6d0228Sniklas sym->value, &filename, &functionname,
12680c6d0228Sniklas &lineno)
12690c6d0228Sniklas && filename != NULL
12700c6d0228Sniklas && lineno != 0)
12710c6d0228Sniklas {
12720c6d0228Sniklas printf ("\t%s:%u", filename, lineno);
12730c6d0228Sniklas }
12740c6d0228Sniklas }
12750c6d0228Sniklas }
12760c6d0228Sniklas
12770c6d0228Sniklas putchar ('\n');
12782159047fSniklas }
12792159047fSniklas
12802159047fSniklas /* The following 3 groups of functions are called unconditionally,
12812159047fSniklas once at the start of processing each file of the appropriate type.
12822159047fSniklas They should check `filename_per_file' and `filename_per_symbol',
12832159047fSniklas as appropriate for their output format, to determine whether to
12842159047fSniklas print anything. */
12852159047fSniklas
12862159047fSniklas /* Print the name of an object file given on the command line. */
12872159047fSniklas
12882159047fSniklas static void
print_object_filename_bsd(char * filename)1289007c2a45Smiod print_object_filename_bsd (char *filename)
12902159047fSniklas {
12912159047fSniklas if (filename_per_file && !filename_per_symbol)
12922159047fSniklas printf ("\n%s:\n", filename);
12932159047fSniklas }
12942159047fSniklas
12952159047fSniklas static void
print_object_filename_sysv(char * filename)1296007c2a45Smiod print_object_filename_sysv (char *filename)
12972159047fSniklas {
12982159047fSniklas if (undefined_only)
1299b305b0f1Sespie printf (_("\n\nUndefined symbols from %s:\n\n"), filename);
13002159047fSniklas else
1301b305b0f1Sespie printf (_("\n\nSymbols from %s:\n\n"), filename);
1302c074d1c9Sdrahn if (print_width == 8)
1303c074d1c9Sdrahn printf (_("\
1304c074d1c9Sdrahn Name Value Class Type Size Line Section\n\n"));
1305c074d1c9Sdrahn else
1306b305b0f1Sespie printf (_("\
1307b305b0f1Sespie Name Value Class Type Size Line Section\n\n"));
13082159047fSniklas }
13092159047fSniklas
13102159047fSniklas static void
print_object_filename_posix(char * filename)1311007c2a45Smiod print_object_filename_posix (char *filename)
13122159047fSniklas {
13132159047fSniklas if (filename_per_file && !filename_per_symbol)
13142159047fSniklas printf ("%s:\n", filename);
13152159047fSniklas }
13162159047fSniklas
13172159047fSniklas /* Print the name of an archive file given on the command line. */
13182159047fSniklas
13192159047fSniklas static void
print_archive_filename_bsd(char * filename)1320007c2a45Smiod print_archive_filename_bsd (char *filename)
13212159047fSniklas {
13222159047fSniklas if (filename_per_file)
13232159047fSniklas printf ("\n%s:\n", filename);
13242159047fSniklas }
13252159047fSniklas
13262159047fSniklas static void
print_archive_filename_sysv(char * filename ATTRIBUTE_UNUSED)1327007c2a45Smiod print_archive_filename_sysv (char *filename ATTRIBUTE_UNUSED)
13282159047fSniklas {
13292159047fSniklas }
13302159047fSniklas
13312159047fSniklas static void
print_archive_filename_posix(char * filename ATTRIBUTE_UNUSED)1332007c2a45Smiod print_archive_filename_posix (char *filename ATTRIBUTE_UNUSED)
13332159047fSniklas {
13342159047fSniklas }
13352159047fSniklas
13362159047fSniklas /* Print the name of an archive member file. */
13372159047fSniklas
13382159047fSniklas static void
print_archive_member_bsd(char * archive ATTRIBUTE_UNUSED,const char * filename)1339007c2a45Smiod print_archive_member_bsd (char *archive ATTRIBUTE_UNUSED,
1340007c2a45Smiod const char *filename)
13412159047fSniklas {
13422159047fSniklas if (!filename_per_symbol)
13432159047fSniklas printf ("\n%s:\n", filename);
13442159047fSniklas }
13452159047fSniklas
13462159047fSniklas static void
print_archive_member_sysv(char * archive,const char * filename)1347007c2a45Smiod print_archive_member_sysv (char *archive, const char *filename)
13482159047fSniklas {
13492159047fSniklas if (undefined_only)
1350b305b0f1Sespie printf (_("\n\nUndefined symbols from %s[%s]:\n\n"), archive, filename);
13512159047fSniklas else
1352b305b0f1Sespie printf (_("\n\nSymbols from %s[%s]:\n\n"), archive, filename);
1353c074d1c9Sdrahn if (print_width == 8)
1354c074d1c9Sdrahn printf (_("\
1355c074d1c9Sdrahn Name Value Class Type Size Line Section\n\n"));
1356c074d1c9Sdrahn else
1357b305b0f1Sespie printf (_("\
1358b305b0f1Sespie Name Value Class Type Size Line Section\n\n"));
13592159047fSniklas }
13602159047fSniklas
13612159047fSniklas static void
print_archive_member_posix(char * archive,const char * filename)1362007c2a45Smiod print_archive_member_posix (char *archive, const char *filename)
13632159047fSniklas {
13642159047fSniklas if (!filename_per_symbol)
13652159047fSniklas printf ("%s[%s]:\n", archive, filename);
13662159047fSniklas }
13672159047fSniklas
13682159047fSniklas /* Print the name of the file (and archive, if there is one)
13692159047fSniklas containing a symbol. */
13702159047fSniklas
13712159047fSniklas static void
print_symbol_filename_bsd(bfd * archive_bfd,bfd * abfd)1372007c2a45Smiod print_symbol_filename_bsd (bfd *archive_bfd, bfd *abfd)
13732159047fSniklas {
13742159047fSniklas if (filename_per_symbol)
13752159047fSniklas {
13762159047fSniklas if (archive_bfd)
13772159047fSniklas printf ("%s:", bfd_get_filename (archive_bfd));
13782159047fSniklas printf ("%s:", bfd_get_filename (abfd));
13792159047fSniklas }
13802159047fSniklas }
13812159047fSniklas
13822159047fSniklas static void
print_symbol_filename_sysv(bfd * archive_bfd,bfd * abfd)1383007c2a45Smiod print_symbol_filename_sysv (bfd *archive_bfd, bfd *abfd)
13842159047fSniklas {
13852159047fSniklas if (filename_per_symbol)
13862159047fSniklas {
13872159047fSniklas if (archive_bfd)
13882159047fSniklas printf ("%s:", bfd_get_filename (archive_bfd));
13892159047fSniklas printf ("%s:", bfd_get_filename (abfd));
13902159047fSniklas }
13912159047fSniklas }
13922159047fSniklas
13932159047fSniklas static void
print_symbol_filename_posix(bfd * archive_bfd,bfd * abfd)1394007c2a45Smiod print_symbol_filename_posix (bfd *archive_bfd, bfd *abfd)
13952159047fSniklas {
13962159047fSniklas if (filename_per_symbol)
13972159047fSniklas {
13982159047fSniklas if (archive_bfd)
13992159047fSniklas printf ("%s[%s]: ", bfd_get_filename (archive_bfd),
14002159047fSniklas bfd_get_filename (abfd));
14012159047fSniklas else
14022159047fSniklas printf ("%s: ", bfd_get_filename (abfd));
14032159047fSniklas }
14042159047fSniklas }
14052159047fSniklas
14062159047fSniklas /* Print a symbol value. */
14072159047fSniklas
14082159047fSniklas static void
print_value(bfd * abfd ATTRIBUTE_UNUSED,bfd_vma val)1409007c2a45Smiod print_value (bfd *abfd ATTRIBUTE_UNUSED, bfd_vma val)
14102159047fSniklas {
14112159047fSniklas #if ! defined (BFD64) || BFD_HOST_64BIT_LONG
14122159047fSniklas printf (value_format, val);
14132159047fSniklas #else
14142159047fSniklas /* We have a 64 bit value to print, but the host is only 32 bit. */
14152159047fSniklas if (print_radix == 16)
1416c074d1c9Sdrahn bfd_fprintf_vma (abfd, stdout, val);
14172159047fSniklas else
14182159047fSniklas {
14192159047fSniklas char buf[30];
14202159047fSniklas char *s;
14212159047fSniklas
14222159047fSniklas s = buf + sizeof buf;
14232159047fSniklas *--s = '\0';
14242159047fSniklas while (val > 0)
14252159047fSniklas {
14262159047fSniklas *--s = (val % print_radix) + '0';
14272159047fSniklas val /= print_radix;
14282159047fSniklas }
14292159047fSniklas while ((buf + sizeof buf - 1) - s < 16)
14302159047fSniklas *--s = '0';
14312159047fSniklas printf ("%s", s);
14322159047fSniklas }
14332159047fSniklas #endif
14342159047fSniklas }
14352159047fSniklas
14362159047fSniklas /* Print a line of information about a symbol. */
14372159047fSniklas
14382159047fSniklas static void
print_symbol_info_bsd(struct extended_symbol_info * info,bfd * abfd)1439007c2a45Smiod print_symbol_info_bsd (struct extended_symbol_info *info, bfd *abfd)
14402159047fSniklas {
1441c074d1c9Sdrahn if (bfd_is_undefined_symclass (SYM_TYPE (info)))
14422159047fSniklas {
1443c074d1c9Sdrahn if (print_width == 16)
1444b55d4692Sfgsch printf (" ");
1445b55d4692Sfgsch printf (" ");
14462159047fSniklas }
14472159047fSniklas else
1448c074d1c9Sdrahn {
1449c074d1c9Sdrahn /* Normally we print the value of the symbol. If we are printing the
1450007c2a45Smiod size or sorting by size then we print its size, except for the
1451c074d1c9Sdrahn (weird) special case where both flags are defined, in which case we
1452c074d1c9Sdrahn print both values. This conforms to documented behaviour. */
1453c074d1c9Sdrahn if (sort_by_size && !print_size)
1454c074d1c9Sdrahn print_value (abfd, SYM_SIZE (info));
1455c074d1c9Sdrahn else
1456c074d1c9Sdrahn print_value (abfd, SYM_VALUE (info));
1457c074d1c9Sdrahn
1458c074d1c9Sdrahn if (print_size && SYM_SIZE (info))
1459c074d1c9Sdrahn {
1460c074d1c9Sdrahn printf (" ");
1461c074d1c9Sdrahn print_value (abfd, SYM_SIZE (info));
1462c074d1c9Sdrahn }
1463c074d1c9Sdrahn }
1464c074d1c9Sdrahn
1465c074d1c9Sdrahn printf (" %c", SYM_TYPE (info));
1466c074d1c9Sdrahn
1467c074d1c9Sdrahn if (SYM_TYPE (info) == '-')
14682159047fSniklas {
14692159047fSniklas /* A stab. */
14702159047fSniklas printf (" ");
1471c074d1c9Sdrahn printf (other_format, SYM_STAB_OTHER (info));
14722159047fSniklas printf (" ");
1473c074d1c9Sdrahn printf (desc_format, SYM_STAB_DESC (info));
1474c074d1c9Sdrahn printf (" %5s", SYM_STAB_NAME (info));
14752159047fSniklas }
1476c074d1c9Sdrahn print_symname (" %s", SYM_NAME (info), abfd);
14772159047fSniklas }
14782159047fSniklas
14792159047fSniklas static void
print_symbol_info_sysv(struct extended_symbol_info * info,bfd * abfd)1480007c2a45Smiod print_symbol_info_sysv (struct extended_symbol_info *info, bfd *abfd)
14812159047fSniklas {
1482c074d1c9Sdrahn print_symname ("%-20s|", SYM_NAME (info), abfd);
1483c074d1c9Sdrahn
1484c074d1c9Sdrahn if (bfd_is_undefined_symclass (SYM_TYPE (info)))
14852159047fSniklas {
1486c074d1c9Sdrahn if (print_width == 8)
1487c074d1c9Sdrahn printf (" ");
1488c074d1c9Sdrahn else
1489c074d1c9Sdrahn printf (" ");
14902159047fSniklas }
14912159047fSniklas else
1492c074d1c9Sdrahn print_value (abfd, SYM_VALUE (info));
1493c074d1c9Sdrahn
1494c074d1c9Sdrahn printf ("| %c |", SYM_TYPE (info));
1495c074d1c9Sdrahn
1496c074d1c9Sdrahn if (SYM_TYPE (info) == '-')
1497c074d1c9Sdrahn {
1498c074d1c9Sdrahn /* A stab. */
1499c074d1c9Sdrahn printf ("%18s| ", SYM_STAB_NAME (info)); /* (C) Type. */
1500c074d1c9Sdrahn printf (desc_format, SYM_STAB_DESC (info)); /* Size. */
1501c074d1c9Sdrahn printf ("| |"); /* Line, Section. */
1502c074d1c9Sdrahn }
1503c074d1c9Sdrahn else
1504c074d1c9Sdrahn {
1505c074d1c9Sdrahn /* Type, Size, Line, Section */
1506c074d1c9Sdrahn if (info->elfinfo)
1507c074d1c9Sdrahn printf ("%18s|",
1508c074d1c9Sdrahn get_symbol_type (ELF_ST_TYPE (info->elfinfo->internal_elf_sym.st_info)));
1509c074d1c9Sdrahn else
1510c074d1c9Sdrahn printf (" |");
1511c074d1c9Sdrahn
1512c074d1c9Sdrahn if (SYM_SIZE (info))
1513c074d1c9Sdrahn print_value (abfd, SYM_SIZE (info));
1514c074d1c9Sdrahn else
1515c074d1c9Sdrahn {
1516c074d1c9Sdrahn if (print_width == 8)
1517c074d1c9Sdrahn printf (" ");
1518c074d1c9Sdrahn else
1519c074d1c9Sdrahn printf (" ");
1520c074d1c9Sdrahn }
1521c074d1c9Sdrahn
1522c074d1c9Sdrahn if (info->elfinfo)
1523c074d1c9Sdrahn printf("| |%s", info->elfinfo->symbol.section->name);
1524c074d1c9Sdrahn else
1525c074d1c9Sdrahn printf("| |");
1526c074d1c9Sdrahn }
15272159047fSniklas }
15282159047fSniklas
15292159047fSniklas static void
print_symbol_info_posix(struct extended_symbol_info * info,bfd * abfd)1530007c2a45Smiod print_symbol_info_posix (struct extended_symbol_info *info, bfd *abfd)
15312159047fSniklas {
1532c074d1c9Sdrahn print_symname ("%s ", SYM_NAME (info), abfd);
1533c074d1c9Sdrahn printf ("%c ", SYM_TYPE (info));
1534c074d1c9Sdrahn
1535c074d1c9Sdrahn if (bfd_is_undefined_symclass (SYM_TYPE (info)))
15362159047fSniklas printf (" ");
15372159047fSniklas else
1538c074d1c9Sdrahn {
1539c074d1c9Sdrahn print_value (abfd, SYM_VALUE (info));
1540c074d1c9Sdrahn printf (" ");
1541c074d1c9Sdrahn if (SYM_SIZE (info))
1542c074d1c9Sdrahn print_value (abfd, SYM_SIZE (info));
1543c074d1c9Sdrahn }
15442159047fSniklas }
15452159047fSniklas
15462159047fSniklas static void
print_symdef_entry(bfd * abfd)1547007c2a45Smiod print_symdef_entry (bfd *abfd)
15482159047fSniklas {
15492159047fSniklas symindex idx = BFD_NO_MORE_SYMBOLS;
15502159047fSniklas carsym *thesym;
1551c074d1c9Sdrahn bfd_boolean everprinted = FALSE;
15522159047fSniklas
15532159047fSniklas for (idx = bfd_get_next_mapent (abfd, idx, &thesym);
15542159047fSniklas idx != BFD_NO_MORE_SYMBOLS;
15552159047fSniklas idx = bfd_get_next_mapent (abfd, idx, &thesym))
15562159047fSniklas {
15572159047fSniklas bfd *elt;
15582159047fSniklas if (!everprinted)
15592159047fSniklas {
1560b305b0f1Sespie printf (_("\nArchive index:\n"));
1561c074d1c9Sdrahn everprinted = TRUE;
15622159047fSniklas }
15632159047fSniklas elt = bfd_get_elt_at_index (abfd, idx);
1564c88b1d6cSniklas if (elt == NULL)
1565c88b1d6cSniklas bfd_fatal ("bfd_get_elt_at_index");
15662159047fSniklas if (thesym->name != (char *) NULL)
15672159047fSniklas {
15682159047fSniklas print_symname ("%s", thesym->name, abfd);
15692159047fSniklas printf (" in %s\n", bfd_get_filename (elt));
15702159047fSniklas }
15712159047fSniklas }
15722159047fSniklas }
15730c6d0228Sniklas
15740c6d0228Sniklas /* This function is used to get the relocs for a particular section.
15750c6d0228Sniklas It is called via bfd_map_over_sections. */
15760c6d0228Sniklas
15770c6d0228Sniklas static void
get_relocs(bfd * abfd,asection * sec,void * dataarg)1578007c2a45Smiod get_relocs (bfd *abfd, asection *sec, void *dataarg)
15790c6d0228Sniklas {
15800c6d0228Sniklas struct get_relocs_info *data = (struct get_relocs_info *) dataarg;
15810c6d0228Sniklas
15820c6d0228Sniklas *data->secs = sec;
15830c6d0228Sniklas
15840c6d0228Sniklas if ((sec->flags & SEC_RELOC) == 0)
15850c6d0228Sniklas {
15860c6d0228Sniklas *data->relocs = NULL;
15870c6d0228Sniklas *data->relcount = 0;
15880c6d0228Sniklas }
15890c6d0228Sniklas else
15900c6d0228Sniklas {
15910c6d0228Sniklas long relsize;
15920c6d0228Sniklas
15930c6d0228Sniklas relsize = bfd_get_reloc_upper_bound (abfd, sec);
15940c6d0228Sniklas if (relsize < 0)
15950c6d0228Sniklas bfd_fatal (bfd_get_filename (abfd));
15960c6d0228Sniklas
15970c6d0228Sniklas *data->relocs = (arelent **) xmalloc (relsize);
15980c6d0228Sniklas *data->relcount = bfd_canonicalize_reloc (abfd, sec, *data->relocs,
15990c6d0228Sniklas data->syms);
16000c6d0228Sniklas if (*data->relcount < 0)
16010c6d0228Sniklas bfd_fatal (bfd_get_filename (abfd));
16020c6d0228Sniklas }
16030c6d0228Sniklas
16040c6d0228Sniklas ++data->secs;
16050c6d0228Sniklas ++data->relocs;
16060c6d0228Sniklas ++data->relcount;
16070c6d0228Sniklas }
1608