📄 nm.c
字号:
/* nm.c -- Describe symbol table of a rel file. Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This file is part of GNU Binutils. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include "bfd.h"#include "progress.h"#include "bucomm.h"#include "getopt.h"#include "aout/stab_gnu.h"#include "aout/ranlib.h"#include "demangle.h"#include "libiberty.h"/* When sorting by size, we use this structure to hold the size and a pointer to the minisymbol. */struct size_sym{ const PTR minisym; bfd_vma size;};/* When fetching relocs, we use this structure to pass information to get_relocs. */struct get_relocs_info{ asection **secs; arelent ***relocs; long *relcount; asymbol **syms;};static voidusage PARAMS ((FILE *, int));static voidset_print_radix PARAMS ((char *));static voidset_output_format PARAMS ((char *));static voiddisplay_archive PARAMS ((bfd *));static booleandisplay_file PARAMS ((char *filename));static voiddisplay_rel_file PARAMS ((bfd * file, bfd * archive));static longfilter_symbols PARAMS ((bfd *, boolean, PTR, long, unsigned int));static longsort_symbols_by_size PARAMS ((bfd *, boolean, PTR, long, unsigned int, struct size_sym **));static voidprint_symbols PARAMS ((bfd *, boolean, PTR, long, unsigned int, bfd *));static voidprint_size_symbols PARAMS ((bfd *, boolean, struct size_sym *, long, bfd *));static voidprint_symname PARAMS ((const char *, const char *, bfd *));static voidprint_symbol PARAMS ((bfd *, asymbol *, bfd *));static voidprint_symdef_entry PARAMS ((bfd * abfd));/* The sorting functions. */static intnumeric_forward PARAMS ((const PTR, const PTR));static intnumeric_reverse PARAMS ((const PTR, const PTR));static intnon_numeric_forward PARAMS ((const PTR, const PTR));static intnon_numeric_reverse PARAMS ((const PTR, const PTR));static intsize_forward1 PARAMS ((const PTR, const PTR));static intsize_forward2 PARAMS ((const PTR, const PTR));/* The output formatting functions. */static voidprint_object_filename_bsd PARAMS ((char *filename));static voidprint_object_filename_sysv PARAMS ((char *filename));static voidprint_object_filename_posix PARAMS ((char *filename));static voidprint_archive_filename_bsd PARAMS ((char *filename));static voidprint_archive_filename_sysv PARAMS ((char *filename));static voidprint_archive_filename_posix PARAMS ((char *filename));static voidprint_archive_member_bsd PARAMS ((char *archive, CONST char *filename));static voidprint_archive_member_sysv PARAMS ((char *archive, CONST char *filename));static voidprint_archive_member_posix PARAMS ((char *archive, CONST char *filename));static voidprint_symbol_filename_bsd PARAMS ((bfd * archive_bfd, bfd * abfd));static voidprint_symbol_filename_sysv PARAMS ((bfd * archive_bfd, bfd * abfd));static voidprint_symbol_filename_posix PARAMS ((bfd * archive_bfd, bfd * abfd));static voidprint_value PARAMS ((bfd_vma));static voidprint_symbol_info_bsd PARAMS ((symbol_info * info, bfd * abfd));static voidprint_symbol_info_sysv PARAMS ((symbol_info * info, bfd * abfd));static voidprint_symbol_info_posix PARAMS ((symbol_info * info, bfd * abfd));static voidget_relocs PARAMS ((bfd *, asection *, PTR));/* Support for different output formats. */struct output_fns { /* Print the name of an object file given on the command line. */ void (*print_object_filename) PARAMS ((char *filename)); /* Print the name of an archive file given on the command line. */ void (*print_archive_filename) PARAMS ((char *filename)); /* Print the name of an archive member file. */ void (*print_archive_member) PARAMS ((char *archive, CONST char *filename)); /* Print the name of the file (and archive, if there is one) containing a symbol. */ void (*print_symbol_filename) PARAMS ((bfd * archive_bfd, bfd * abfd)); /* Print a line of information about a symbol. */ void (*print_symbol_info) PARAMS ((symbol_info * info, bfd * abfd)); };static struct output_fns formats[] ={ {print_object_filename_bsd, print_archive_filename_bsd, print_archive_member_bsd, print_symbol_filename_bsd, print_symbol_info_bsd}, {print_object_filename_sysv, print_archive_filename_sysv, print_archive_member_sysv, print_symbol_filename_sysv, print_symbol_info_sysv}, {print_object_filename_posix, print_archive_filename_posix, print_archive_member_posix, print_symbol_filename_posix, print_symbol_info_posix}};/* Indices in `formats'. */#define FORMAT_BSD 0#define FORMAT_SYSV 1#define FORMAT_POSIX 2#define FORMAT_DEFAULT FORMAT_BSD/* The output format to use. */static struct output_fns *format = &formats[FORMAT_DEFAULT];/* Command options. */static int do_demangle = 0; /* Pretty print C++ symbol names. */static int external_only = 0; /* print external symbols only */static int defined_only = 0; /* Print defined symbols only */static int no_sort = 0; /* don't sort; print syms in order found */static int print_debug_syms = 0; /* print debugger-only symbols too */static int print_armap = 0; /* describe __.SYMDEF data in archive files. */static int reverse_sort = 0; /* sort in downward(alpha or numeric) order */static int sort_numerically = 0; /* sort in numeric rather than alpha order */static int sort_by_size = 0; /* sort by size of symbol */static int undefined_only = 0; /* print undefined symbols only */static int dynamic = 0; /* print dynamic symbols. */static int show_version = 0; /* show the version number */static int show_stats = 0; /* show statistics */static int line_numbers = 0; /* print line numbers for symbols *//* When to print the names of files. Not mutually exclusive in SYSV format. */static int filename_per_file = 0; /* Once per file, on its own line. */static int filename_per_symbol = 0; /* Once per symbol, at start of line. *//* Print formats for printing a symbol value. */#ifndef BFD64static char value_format[] = "%08lx";#else#if BFD_HOST_64BIT_LONGstatic char value_format[] = "%016lx";#else/* We don't use value_format for this case. */#endif#endifstatic int print_radix = 16;/* Print formats for printing stab info. */static char other_format[] = "%02x";static char desc_format[] = "%04x";static char *target = NULL;/* Used to cache the line numbers for a BFD. */static bfd *lineno_cache_bfd;static bfd *lineno_cache_rel_bfd;#define OPTION_TARGET 200static struct option long_options[] ={ {"debug-syms", no_argument, &print_debug_syms, 1}, {"demangle", optional_argument, 0, 'C'}, {"dynamic", no_argument, &dynamic, 1}, {"extern-only", no_argument, &external_only, 1}, {"format", required_argument, 0, 'f'}, {"help", no_argument, 0, 'h'}, {"line-numbers", no_argument, 0, 'l'}, {"no-cplus", no_argument, &do_demangle, 0}, /* Linux compatibility. */ {"no-demangle", no_argument, &do_demangle, 0}, {"no-sort", no_argument, &no_sort, 1}, {"numeric-sort", no_argument, &sort_numerically, 1}, {"portability", no_argument, 0, 'P'}, {"print-armap", no_argument, &print_armap, 1}, {"print-file-name", no_argument, 0, 'o'}, {"radix", required_argument, 0, 't'}, {"reverse-sort", no_argument, &reverse_sort, 1}, {"size-sort", no_argument, &sort_by_size, 1}, {"stats", no_argument, &show_stats, 1}, {"target", required_argument, 0, OPTION_TARGET}, {"defined-only", no_argument, &defined_only, 1}, {"undefined-only", no_argument, &undefined_only, 1}, {"version", no_argument, &show_version, 1}, {0, no_argument, 0, 0}};/* Some error-reporting functions */static voidusage (stream, status) FILE *stream; int status;{ fprintf (stream, _("Usage: %s [OPTION]... [FILE]...\n"), program_name); fprintf (stream, _("List symbols from FILEs (a.out by default).\n")); fprintf (stream, _("\n\ -a, --debug-syms Display debugger-only symbols\n\ -A, --print-file-name Print name of the input file before every symbol\n\ -B Same as --format=bsd\n\ -C, --demangle[=STYLE] Decode low-level symbol names into user-level names\n\ The STYLE, if specified, can be `auto' (the default),\n\ `gnu', 'lucid', 'arm', 'hp', 'edg' or 'gnu-new-abi'\n\ --no-demangle Do not demangle low-level symbol names\n\ -D, --dynamic Display dynamic symbols instead of normal symbols\n\ --defined-only Display only defined symbols\n\ -e (ignored)\n\ -f, --format=FORMAT Use the output format FORMAT. FORMAT can be `bsd',\n\ `sysv' or `posix'. The default is `bsd'\n\ -g, --extern-only Display only external symbols\n\ -h, --help Display this information\n\ -l, --line-numbers Use debugging information to find a filename and\n\ line number for each symbol\n\ -n, --numeric-sort Sort symbols numerically by address\n\ -o Same as -A\n\ -p, --no-sort Do not sort the symbols\n\ -P, --portability Same as --format=posix\n\ -r, --reverse-sort Reverse the sense of the sort\n\ -s, --print-armap Include index for symbols from archive members\n\ --size-sort Sort symbols by size\n\ -t, --radix=RADIX Use RADIX for printing symbol values\n\ --target=BFDNAME Specify the target object format as BFDNAME\n\ -u, --undefined-only Display only undefined symbols\n\ -V, --version Display this program's version number\n\ -X 32_64 (ignored)\n\\n")); list_supported_targets (program_name, stream); if (status == 0) fprintf (stream, _("Report bugs to %s.\n"), REPORT_BUGS_TO); exit (status);}/* Set the radix for the symbol value and size according to RADIX. */static voidset_print_radix (radix) char *radix;{ switch (*radix) { case 'x': break; case 'd': case 'o': if (*radix == 'd') print_radix = 10; else print_radix = 8;#ifndef BFD64 value_format[4] = *radix;#else#if BFD_HOST_64BIT_LONG value_format[5] = *radix;#else /* This case requires special handling for octal and decimal printing. */#endif#endif other_format[3] = desc_format[3] = *radix; break; default: fatal (_("%s: invalid radix"), radix); }}static voidset_output_format (f) char *f;{ int i; switch (*f) { case 'b': case 'B': i = FORMAT_BSD; break; case 'p': case 'P': i = FORMAT_POSIX; break; case 's': case 'S': i = FORMAT_SYSV; break; default: fatal (_("%s: invalid output format"), f); } format = &formats[i];}intmain (argc, argv) int argc; char **argv;{ int c; int retval;#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES) setlocale (LC_MESSAGES, "");#endif bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); program_name = *argv; xmalloc_set_program_name (program_name); START_PROGRESS (program_name, 0); bfd_init (); set_default_bfd_target (); while ((c = getopt_long (argc, argv, "aABCDef:glnopPrst:uvVX:", long_options, (int *) 0)) != EOF) { switch (c) { case 'a': print_debug_syms = 1; break; case 'A': case 'o': filename_per_symbol = 1; break; case 'B': /* For MIPS compatibility. */ set_output_format ("bsd"); break; case 'C': do_demangle = 1; if (optarg != NULL) { enum demangling_styles style; style = cplus_demangle_name_to_style (optarg); if (style == unknown_demangling) fatal (_("unknown demangling style `%s'"), optarg); cplus_demangle_set_style (style); } break; case 'D': dynamic = 1; break; case 'e': /* Ignored for HP/UX compatibility. */ break; case 'f': set_output_format (optarg); break; case 'g': external_only = 1; break; case 'h': usage (stdout, 0); case 'l': line_numbers = 1; break; case 'n': case 'v': sort_numerically = 1; break; case 'p': no_sort = 1; break; case 'P': set_output_format ("posix"); break; case 'r': reverse_sort = 1; break; case 's': print_armap = 1; break; case 't': set_print_radix (optarg); break; case 'u': undefined_only = 1; break; case 'V': show_version = 1; break; case 'X': /* Ignored for (partial) AIX compatibility. On AIX, the argument has values 32, 64, or 32_64, and specfies that only 32-bit, only 64-bit, or both kinds of objects should be examined. The default is 32. So plain AIX nm on a library archive with both kinds of objects will ignore the 64-bit ones. For GNU nm, the default is and always has been -X 32_64, and other options are not supported. */ if (strcmp (optarg, "32_64") != 0) fatal (_("Only -X 32_64 is supported")); break; case OPTION_TARGET: /* --target */ target = optarg; break; case 0: /* A long option that just sets a flag. */ break; default: usage (stderr, 1); } } if (show_version) print_version ("nm"); /* OK, all options now parsed. If no filename specified, do a.out. */ if (optind == argc) return !display_file ("a.out"); retval = 0; if (argc - optind > 1) filename_per_file = 1; /* We were given several filenames to do. */ while (optind < argc) { PROGRESS (1); if (!display_file (argv[optind++])) retval++; } END_PROGRESS (program_name);#ifdef HAVE_SBRK if (show_stats) { char *lim = (char *) sbrk (0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -