13d8817e4Smiod /* objdump.c -- dump information about an object file.
23d8817e4Smiod Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
33d8817e4Smiod 2000, 2001, 2002, 2003, 2004, 2005, 2006
43d8817e4Smiod Free Software Foundation, Inc.
53d8817e4Smiod
63d8817e4Smiod This file is part of GNU Binutils.
73d8817e4Smiod
83d8817e4Smiod This program is free software; you can redistribute it and/or modify
93d8817e4Smiod it under the terms of the GNU General Public License as published by
103d8817e4Smiod the Free Software Foundation; either version 2, or (at your option)
113d8817e4Smiod any later version.
123d8817e4Smiod
133d8817e4Smiod This program is distributed in the hope that it will be useful,
143d8817e4Smiod but WITHOUT ANY WARRANTY; without even the implied warranty of
153d8817e4Smiod MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
163d8817e4Smiod GNU General Public License for more details.
173d8817e4Smiod
183d8817e4Smiod You should have received a copy of the GNU General Public License
193d8817e4Smiod along with this program; if not, write to the Free Software
203d8817e4Smiod Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
213d8817e4Smiod
223d8817e4Smiod /* Objdump overview.
233d8817e4Smiod
243d8817e4Smiod Objdump displays information about one or more object files, either on
253d8817e4Smiod their own, or inside libraries. It is commonly used as a disassembler,
263d8817e4Smiod but it can also display information about file headers, symbol tables,
273d8817e4Smiod relocations, debugging directives and more.
283d8817e4Smiod
293d8817e4Smiod The flow of execution is as follows:
303d8817e4Smiod
313d8817e4Smiod 1. Command line arguments are checked for control switches and the
323d8817e4Smiod information to be displayed is selected.
333d8817e4Smiod
343d8817e4Smiod 2. Any remaining arguments are assumed to be object files, and they are
353d8817e4Smiod processed in order by display_bfd(). If the file is an archive each
363d8817e4Smiod of its elements is processed in turn.
373d8817e4Smiod
383d8817e4Smiod 3. The file's target architecture and binary file format are determined
393d8817e4Smiod by bfd_check_format(). If they are recognised, then dump_bfd() is
403d8817e4Smiod called.
413d8817e4Smiod
423d8817e4Smiod 4. dump_bfd() in turn calls separate functions to display the requested
433d8817e4Smiod item(s) of information(s). For example disassemble_data() is called if
443d8817e4Smiod a disassembly has been requested.
453d8817e4Smiod
463d8817e4Smiod When disassembling the code loops through blocks of instructions bounded
473d8817e4Smiod by symbols, calling disassemble_bytes() on each block. The actual
483d8817e4Smiod disassembling is done by the libopcodes library, via a function pointer
493d8817e4Smiod supplied by the disassembler() function. */
503d8817e4Smiod
513d8817e4Smiod #include "bfd.h"
523d8817e4Smiod #include "bfdver.h"
533d8817e4Smiod #include "progress.h"
543d8817e4Smiod #include "bucomm.h"
553d8817e4Smiod #include "dwarf.h"
563d8817e4Smiod #include "budemang.h"
573d8817e4Smiod #include "getopt.h"
583d8817e4Smiod #include "safe-ctype.h"
593d8817e4Smiod #include "dis-asm.h"
603d8817e4Smiod #include "libiberty.h"
613d8817e4Smiod #include "demangle.h"
623d8817e4Smiod #include "debug.h"
633d8817e4Smiod #include "budbg.h"
643d8817e4Smiod
653d8817e4Smiod /* Internal headers for the ELF .stab-dump code - sorry. */
663d8817e4Smiod #define BYTES_IN_WORD 32
673d8817e4Smiod #include "aout/aout64.h"
683d8817e4Smiod
693d8817e4Smiod /* Exit status. */
703d8817e4Smiod static int exit_status = 0;
713d8817e4Smiod
723d8817e4Smiod static char *default_target = NULL; /* Default at runtime. */
733d8817e4Smiod
743d8817e4Smiod /* The following variables are set based on arguments passed on the
753d8817e4Smiod command line. */
763d8817e4Smiod static int show_version = 0; /* Show the version number. */
773d8817e4Smiod static int dump_section_contents; /* -s */
783d8817e4Smiod static int dump_section_headers; /* -h */
793d8817e4Smiod static bfd_boolean dump_file_header; /* -f */
803d8817e4Smiod static int dump_symtab; /* -t */
813d8817e4Smiod static int dump_dynamic_symtab; /* -T */
823d8817e4Smiod static int dump_reloc_info; /* -r */
833d8817e4Smiod static int dump_dynamic_reloc_info; /* -R */
843d8817e4Smiod static int dump_ar_hdrs; /* -a */
853d8817e4Smiod static int dump_private_headers; /* -p */
863d8817e4Smiod static int prefix_addresses; /* --prefix-addresses */
873d8817e4Smiod static int with_line_numbers; /* -l */
883d8817e4Smiod static bfd_boolean with_source_code; /* -S */
893d8817e4Smiod static int show_raw_insn; /* --show-raw-insn */
903d8817e4Smiod static int dump_dwarf_section_info; /* --dwarf */
913d8817e4Smiod static int dump_stab_section_info; /* --stabs */
923d8817e4Smiod static int do_demangle; /* -C, --demangle */
933d8817e4Smiod static bfd_boolean disassemble; /* -d */
943d8817e4Smiod static bfd_boolean disassemble_all; /* -D */
953d8817e4Smiod static int disassemble_zeroes; /* --disassemble-zeroes */
963d8817e4Smiod static bfd_boolean formats_info; /* -i */
973d8817e4Smiod static int wide_output; /* -w */
983d8817e4Smiod static bfd_vma start_address = (bfd_vma) -1; /* --start-address */
993d8817e4Smiod static bfd_vma stop_address = (bfd_vma) -1; /* --stop-address */
1003d8817e4Smiod static int dump_debugging; /* --debugging */
1013d8817e4Smiod static int dump_debugging_tags; /* --debugging-tags */
1023d8817e4Smiod static int dump_special_syms = 0; /* --special-syms */
1033d8817e4Smiod static bfd_vma adjust_section_vma = 0; /* --adjust-vma */
1043d8817e4Smiod static int file_start_context = 0; /* --file-start-context */
1053d8817e4Smiod
1063d8817e4Smiod /* Pointer to an array of section names provided by
1073d8817e4Smiod one or more "-j secname" command line options. */
1083d8817e4Smiod static char **only;
1093d8817e4Smiod /* The total number of slots in the only[] array. */
1103d8817e4Smiod static size_t only_size = 0;
1113d8817e4Smiod /* The number of occupied slots in the only[] array. */
1123d8817e4Smiod static size_t only_used = 0;
1133d8817e4Smiod
1143d8817e4Smiod /* Variables for handling include file path table. */
1153d8817e4Smiod static const char **include_paths;
1163d8817e4Smiod static int include_path_count;
1173d8817e4Smiod
1183d8817e4Smiod /* Extra info to pass to the section disassembler and address printing
1193d8817e4Smiod function. */
1203d8817e4Smiod struct objdump_disasm_info
1213d8817e4Smiod {
1223d8817e4Smiod bfd * abfd;
1233d8817e4Smiod asection * sec;
1243d8817e4Smiod bfd_boolean require_sec;
1253d8817e4Smiod arelent ** dynrelbuf;
1263d8817e4Smiod long dynrelcount;
1273d8817e4Smiod disassembler_ftype disassemble_fn;
1283d8817e4Smiod arelent * reloc;
1293d8817e4Smiod };
1303d8817e4Smiod
1313d8817e4Smiod /* Architecture to disassemble for, or default if NULL. */
1323d8817e4Smiod static char *machine = NULL;
1333d8817e4Smiod
1343d8817e4Smiod /* Target specific options to the disassembler. */
1353d8817e4Smiod static char *disassembler_options = NULL;
1363d8817e4Smiod
1373d8817e4Smiod /* Endianness to disassemble for, or default if BFD_ENDIAN_UNKNOWN. */
1383d8817e4Smiod static enum bfd_endian endian = BFD_ENDIAN_UNKNOWN;
1393d8817e4Smiod
1403d8817e4Smiod /* The symbol table. */
1413d8817e4Smiod static asymbol **syms;
1423d8817e4Smiod
1433d8817e4Smiod /* Number of symbols in `syms'. */
1443d8817e4Smiod static long symcount = 0;
1453d8817e4Smiod
1463d8817e4Smiod /* The sorted symbol table. */
1473d8817e4Smiod static asymbol **sorted_syms;
1483d8817e4Smiod
1493d8817e4Smiod /* Number of symbols in `sorted_syms'. */
1503d8817e4Smiod static long sorted_symcount = 0;
1513d8817e4Smiod
1523d8817e4Smiod /* The dynamic symbol table. */
1533d8817e4Smiod static asymbol **dynsyms;
1543d8817e4Smiod
1553d8817e4Smiod /* The synthetic symbol table. */
1563d8817e4Smiod static asymbol *synthsyms;
1573d8817e4Smiod static long synthcount = 0;
1583d8817e4Smiod
1593d8817e4Smiod /* Number of symbols in `dynsyms'. */
1603d8817e4Smiod static long dynsymcount = 0;
1613d8817e4Smiod
1623d8817e4Smiod static bfd_byte *stabs;
1633d8817e4Smiod static bfd_size_type stab_size;
1643d8817e4Smiod
1653d8817e4Smiod static char *strtab;
1663d8817e4Smiod static bfd_size_type stabstr_size;
1673d8817e4Smiod
1683d8817e4Smiod static void
usage(FILE * stream,int status)1693d8817e4Smiod usage (FILE *stream, int status)
1703d8817e4Smiod {
1713d8817e4Smiod fprintf (stream, _("Usage: %s <option(s)> <file(s)>\n"), program_name);
1723d8817e4Smiod fprintf (stream, _(" Display information from object <file(s)>.\n"));
1733d8817e4Smiod fprintf (stream, _(" At least one of the following switches must be given:\n"));
1743d8817e4Smiod fprintf (stream, _("\
1753d8817e4Smiod -a, --archive-headers Display archive header information\n\
1763d8817e4Smiod -f, --file-headers Display the contents of the overall file header\n\
1773d8817e4Smiod -p, --private-headers Display object format specific file header contents\n\
1783d8817e4Smiod -h, --[section-]headers Display the contents of the section headers\n\
1793d8817e4Smiod -x, --all-headers Display the contents of all headers\n\
1803d8817e4Smiod -d, --disassemble Display assembler contents of executable sections\n\
1813d8817e4Smiod -D, --disassemble-all Display assembler contents of all sections\n\
1823d8817e4Smiod -S, --source Intermix source code with disassembly\n\
1833d8817e4Smiod -s, --full-contents Display the full contents of all sections requested\n\
1843d8817e4Smiod -g, --debugging Display debug information in object file\n\
1853d8817e4Smiod -e, --debugging-tags Display debug information using ctags style\n\
1863d8817e4Smiod -G, --stabs Display (in raw form) any STABS info in the file\n\
1873d8817e4Smiod -W, --dwarf Display DWARF info in the file\n\
1883d8817e4Smiod -t, --syms Display the contents of the symbol table(s)\n\
1893d8817e4Smiod -T, --dynamic-syms Display the contents of the dynamic symbol table\n\
1903d8817e4Smiod -r, --reloc Display the relocation entries in the file\n\
1913d8817e4Smiod -R, --dynamic-reloc Display the dynamic relocation entries in the file\n\
1923d8817e4Smiod @<file> Read options from <file>\n\
1933d8817e4Smiod -v, --version Display this program's version number\n\
1943d8817e4Smiod -i, --info List object formats and architectures supported\n\
1953d8817e4Smiod -H, --help Display this information\n\
1963d8817e4Smiod "));
1973d8817e4Smiod if (status != 2)
1983d8817e4Smiod {
1993d8817e4Smiod fprintf (stream, _("\n The following switches are optional:\n"));
2003d8817e4Smiod fprintf (stream, _("\
2013d8817e4Smiod -b, --target=BFDNAME Specify the target object format as BFDNAME\n\
2023d8817e4Smiod -m, --architecture=MACHINE Specify the target architecture as MACHINE\n\
2033d8817e4Smiod -j, --section=NAME Only display information for section NAME\n\
2043d8817e4Smiod -M, --disassembler-options=OPT Pass text OPT on to the disassembler\n\
2053d8817e4Smiod -EB --endian=big Assume big endian format when disassembling\n\
2063d8817e4Smiod -EL --endian=little Assume little endian format when disassembling\n\
2073d8817e4Smiod --file-start-context Include context from start of file (with -S)\n\
2083d8817e4Smiod -I, --include=DIR Add DIR to search list for source files\n\
2093d8817e4Smiod -l, --line-numbers Include line numbers and filenames in output\n\
2103d8817e4Smiod -C, --demangle[=STYLE] Decode mangled/processed symbol names\n\
2113d8817e4Smiod The STYLE, if specified, can be `auto', `gnu',\n\
2123d8817e4Smiod `lucid', `arm', `hp', `edg', `gnu-v3', `java'\n\
2133d8817e4Smiod or `gnat'\n\
2143d8817e4Smiod -w, --wide Format output for more than 80 columns\n\
2153d8817e4Smiod -z, --disassemble-zeroes Do not skip blocks of zeroes when disassembling\n\
2163d8817e4Smiod --start-address=ADDR Only process data whose address is >= ADDR\n\
2173d8817e4Smiod --stop-address=ADDR Only process data whose address is <= ADDR\n\
2183d8817e4Smiod --prefix-addresses Print complete address alongside disassembly\n\
2193d8817e4Smiod --[no-]show-raw-insn Display hex alongside symbolic disassembly\n\
2203d8817e4Smiod --adjust-vma=OFFSET Add OFFSET to all displayed section addresses\n\
2213d8817e4Smiod --special-syms Include special symbols in symbol dumps\n\
2223d8817e4Smiod \n"));
2233d8817e4Smiod list_supported_targets (program_name, stream);
2243d8817e4Smiod list_supported_architectures (program_name, stream);
2253d8817e4Smiod
2263d8817e4Smiod disassembler_usage (stream);
2273d8817e4Smiod }
2283d8817e4Smiod if (status == 0)
2293d8817e4Smiod fprintf (stream, _("Report bugs to %s.\n"), REPORT_BUGS_TO);
2303d8817e4Smiod exit (status);
2313d8817e4Smiod }
2323d8817e4Smiod
2333d8817e4Smiod /* 150 isn't special; it's just an arbitrary non-ASCII char value. */
2343d8817e4Smiod enum option_values
2353d8817e4Smiod {
2363d8817e4Smiod OPTION_ENDIAN=150,
2373d8817e4Smiod OPTION_START_ADDRESS,
2383d8817e4Smiod OPTION_STOP_ADDRESS,
2393d8817e4Smiod OPTION_ADJUST_VMA
2403d8817e4Smiod };
2413d8817e4Smiod
2423d8817e4Smiod static struct option long_options[]=
2433d8817e4Smiod {
2443d8817e4Smiod {"adjust-vma", required_argument, NULL, OPTION_ADJUST_VMA},
2453d8817e4Smiod {"all-headers", no_argument, NULL, 'x'},
2463d8817e4Smiod {"private-headers", no_argument, NULL, 'p'},
2473d8817e4Smiod {"architecture", required_argument, NULL, 'm'},
2483d8817e4Smiod {"archive-headers", no_argument, NULL, 'a'},
2493d8817e4Smiod {"debugging", no_argument, NULL, 'g'},
2503d8817e4Smiod {"debugging-tags", no_argument, NULL, 'e'},
2513d8817e4Smiod {"demangle", optional_argument, NULL, 'C'},
2523d8817e4Smiod {"disassemble", no_argument, NULL, 'd'},
2533d8817e4Smiod {"disassemble-all", no_argument, NULL, 'D'},
2543d8817e4Smiod {"disassembler-options", required_argument, NULL, 'M'},
2553d8817e4Smiod {"disassemble-zeroes", no_argument, NULL, 'z'},
2563d8817e4Smiod {"dynamic-reloc", no_argument, NULL, 'R'},
2573d8817e4Smiod {"dynamic-syms", no_argument, NULL, 'T'},
2583d8817e4Smiod {"endian", required_argument, NULL, OPTION_ENDIAN},
2593d8817e4Smiod {"file-headers", no_argument, NULL, 'f'},
2603d8817e4Smiod {"file-start-context", no_argument, &file_start_context, 1},
2613d8817e4Smiod {"full-contents", no_argument, NULL, 's'},
2623d8817e4Smiod {"headers", no_argument, NULL, 'h'},
2633d8817e4Smiod {"help", no_argument, NULL, 'H'},
2643d8817e4Smiod {"info", no_argument, NULL, 'i'},
2653d8817e4Smiod {"line-numbers", no_argument, NULL, 'l'},
2663d8817e4Smiod {"no-show-raw-insn", no_argument, &show_raw_insn, -1},
2673d8817e4Smiod {"prefix-addresses", no_argument, &prefix_addresses, 1},
2683d8817e4Smiod {"reloc", no_argument, NULL, 'r'},
2693d8817e4Smiod {"section", required_argument, NULL, 'j'},
2703d8817e4Smiod {"section-headers", no_argument, NULL, 'h'},
2713d8817e4Smiod {"show-raw-insn", no_argument, &show_raw_insn, 1},
2723d8817e4Smiod {"source", no_argument, NULL, 'S'},
2733d8817e4Smiod {"special-syms", no_argument, &dump_special_syms, 1},
2743d8817e4Smiod {"include", required_argument, NULL, 'I'},
2753d8817e4Smiod {"dwarf", no_argument, NULL, 'W'},
2763d8817e4Smiod {"stabs", no_argument, NULL, 'G'},
2773d8817e4Smiod {"start-address", required_argument, NULL, OPTION_START_ADDRESS},
2783d8817e4Smiod {"stop-address", required_argument, NULL, OPTION_STOP_ADDRESS},
2793d8817e4Smiod {"syms", no_argument, NULL, 't'},
2803d8817e4Smiod {"target", required_argument, NULL, 'b'},
2813d8817e4Smiod {"version", no_argument, NULL, 'V'},
2823d8817e4Smiod {"wide", no_argument, NULL, 'w'},
2833d8817e4Smiod {0, no_argument, 0, 0}
2843d8817e4Smiod };
2853d8817e4Smiod
2863d8817e4Smiod static void
nonfatal(const char * msg)2873d8817e4Smiod nonfatal (const char *msg)
2883d8817e4Smiod {
2893d8817e4Smiod bfd_nonfatal (msg);
2903d8817e4Smiod exit_status = 1;
2913d8817e4Smiod }
2923d8817e4Smiod
2933d8817e4Smiod static void
dump_section_header(bfd * abfd,asection * section,void * ignored ATTRIBUTE_UNUSED)2943d8817e4Smiod dump_section_header (bfd *abfd, asection *section,
2953d8817e4Smiod void *ignored ATTRIBUTE_UNUSED)
2963d8817e4Smiod {
2973d8817e4Smiod char *comma = "";
2983d8817e4Smiod unsigned int opb = bfd_octets_per_byte (abfd);
2993d8817e4Smiod
3003d8817e4Smiod /* Ignore linker created section. See elfNN_ia64_object_p in
3013d8817e4Smiod bfd/elfxx-ia64.c. */
3023d8817e4Smiod if (section->flags & SEC_LINKER_CREATED)
3033d8817e4Smiod return;
3043d8817e4Smiod
3053d8817e4Smiod printf ("%3d %-13s %08lx ", section->index,
3063d8817e4Smiod bfd_get_section_name (abfd, section),
3073d8817e4Smiod (unsigned long) bfd_section_size (abfd, section) / opb);
3083d8817e4Smiod bfd_printf_vma (abfd, bfd_get_section_vma (abfd, section));
3093d8817e4Smiod printf (" ");
3103d8817e4Smiod bfd_printf_vma (abfd, section->lma);
3113d8817e4Smiod printf (" %08lx 2**%u", (unsigned long) section->filepos,
3123d8817e4Smiod bfd_get_section_alignment (abfd, section));
3133d8817e4Smiod if (! wide_output)
3143d8817e4Smiod printf ("\n ");
3153d8817e4Smiod printf (" ");
3163d8817e4Smiod
3173d8817e4Smiod #define PF(x, y) \
3183d8817e4Smiod if (section->flags & x) { printf ("%s%s", comma, y); comma = ", "; }
3193d8817e4Smiod
3203d8817e4Smiod PF (SEC_HAS_CONTENTS, "CONTENTS");
3213d8817e4Smiod PF (SEC_ALLOC, "ALLOC");
3223d8817e4Smiod PF (SEC_CONSTRUCTOR, "CONSTRUCTOR");
3233d8817e4Smiod PF (SEC_LOAD, "LOAD");
3243d8817e4Smiod PF (SEC_RELOC, "RELOC");
3253d8817e4Smiod PF (SEC_READONLY, "READONLY");
3263d8817e4Smiod PF (SEC_CODE, "CODE");
3273d8817e4Smiod PF (SEC_DATA, "DATA");
3283d8817e4Smiod PF (SEC_ROM, "ROM");
3293d8817e4Smiod PF (SEC_DEBUGGING, "DEBUGGING");
3303d8817e4Smiod PF (SEC_NEVER_LOAD, "NEVER_LOAD");
3313d8817e4Smiod PF (SEC_EXCLUDE, "EXCLUDE");
3323d8817e4Smiod PF (SEC_SORT_ENTRIES, "SORT_ENTRIES");
3333d8817e4Smiod if (bfd_get_arch (abfd) == bfd_arch_tic54x)
3343d8817e4Smiod {
3353d8817e4Smiod PF (SEC_TIC54X_BLOCK, "BLOCK");
3363d8817e4Smiod PF (SEC_TIC54X_CLINK, "CLINK");
3373d8817e4Smiod }
3383d8817e4Smiod PF (SEC_SMALL_DATA, "SMALL_DATA");
3393d8817e4Smiod if (bfd_get_flavour (abfd) == bfd_target_coff_flavour)
3403d8817e4Smiod PF (SEC_COFF_SHARED, "SHARED");
3413d8817e4Smiod PF (SEC_THREAD_LOCAL, "THREAD_LOCAL");
3423d8817e4Smiod PF (SEC_GROUP, "GROUP");
3433d8817e4Smiod
3443d8817e4Smiod if ((section->flags & SEC_LINK_ONCE) != 0)
3453d8817e4Smiod {
3463d8817e4Smiod const char *ls;
3473d8817e4Smiod struct coff_comdat_info *comdat;
3483d8817e4Smiod
3493d8817e4Smiod switch (section->flags & SEC_LINK_DUPLICATES)
3503d8817e4Smiod {
3513d8817e4Smiod default:
3523d8817e4Smiod abort ();
3533d8817e4Smiod case SEC_LINK_DUPLICATES_DISCARD:
3543d8817e4Smiod ls = "LINK_ONCE_DISCARD";
3553d8817e4Smiod break;
3563d8817e4Smiod case SEC_LINK_DUPLICATES_ONE_ONLY:
3573d8817e4Smiod ls = "LINK_ONCE_ONE_ONLY";
3583d8817e4Smiod break;
3593d8817e4Smiod case SEC_LINK_DUPLICATES_SAME_SIZE:
3603d8817e4Smiod ls = "LINK_ONCE_SAME_SIZE";
3613d8817e4Smiod break;
3623d8817e4Smiod case SEC_LINK_DUPLICATES_SAME_CONTENTS:
3633d8817e4Smiod ls = "LINK_ONCE_SAME_CONTENTS";
3643d8817e4Smiod break;
3653d8817e4Smiod }
3663d8817e4Smiod printf ("%s%s", comma, ls);
3673d8817e4Smiod
3683d8817e4Smiod comdat = bfd_coff_get_comdat_section (abfd, section);
3693d8817e4Smiod if (comdat != NULL)
3703d8817e4Smiod printf (" (COMDAT %s %ld)", comdat->name, comdat->symbol);
3713d8817e4Smiod
3723d8817e4Smiod comma = ", ";
3733d8817e4Smiod }
3743d8817e4Smiod
3753d8817e4Smiod printf ("\n");
3763d8817e4Smiod #undef PF
3773d8817e4Smiod }
3783d8817e4Smiod
3793d8817e4Smiod static void
dump_headers(bfd * abfd)3803d8817e4Smiod dump_headers (bfd *abfd)
3813d8817e4Smiod {
3823d8817e4Smiod printf (_("Sections:\n"));
3833d8817e4Smiod
3843d8817e4Smiod #ifndef BFD64
3853d8817e4Smiod printf (_("Idx Name Size VMA LMA File off Algn"));
3863d8817e4Smiod #else
3873d8817e4Smiod /* With BFD64, non-ELF returns -1 and wants always 64 bit addresses. */
3883d8817e4Smiod if (bfd_get_arch_size (abfd) == 32)
3893d8817e4Smiod printf (_("Idx Name Size VMA LMA File off Algn"));
3903d8817e4Smiod else
3913d8817e4Smiod printf (_("Idx Name Size VMA LMA File off Algn"));
3923d8817e4Smiod #endif
3933d8817e4Smiod
3943d8817e4Smiod if (wide_output)
3953d8817e4Smiod printf (_(" Flags"));
3963d8817e4Smiod if (abfd->flags & HAS_LOAD_PAGE)
3973d8817e4Smiod printf (_(" Pg"));
3983d8817e4Smiod printf ("\n");
3993d8817e4Smiod
4003d8817e4Smiod bfd_map_over_sections (abfd, dump_section_header, NULL);
4013d8817e4Smiod }
4023d8817e4Smiod
4033d8817e4Smiod static asymbol **
slurp_symtab(bfd * abfd)4043d8817e4Smiod slurp_symtab (bfd *abfd)
4053d8817e4Smiod {
4063d8817e4Smiod asymbol **sy = NULL;
4073d8817e4Smiod long storage;
4083d8817e4Smiod
4093d8817e4Smiod if (!(bfd_get_file_flags (abfd) & HAS_SYMS))
4103d8817e4Smiod {
4113d8817e4Smiod symcount = 0;
4123d8817e4Smiod return NULL;
4133d8817e4Smiod }
4143d8817e4Smiod
4153d8817e4Smiod storage = bfd_get_symtab_upper_bound (abfd);
4163d8817e4Smiod if (storage < 0)
4173d8817e4Smiod bfd_fatal (bfd_get_filename (abfd));
4183d8817e4Smiod if (storage)
4193d8817e4Smiod sy = xmalloc (storage);
4203d8817e4Smiod
4213d8817e4Smiod symcount = bfd_canonicalize_symtab (abfd, sy);
4223d8817e4Smiod if (symcount < 0)
4233d8817e4Smiod bfd_fatal (bfd_get_filename (abfd));
4243d8817e4Smiod return sy;
4253d8817e4Smiod }
4263d8817e4Smiod
4273d8817e4Smiod /* Read in the dynamic symbols. */
4283d8817e4Smiod
4293d8817e4Smiod static asymbol **
slurp_dynamic_symtab(bfd * abfd)4303d8817e4Smiod slurp_dynamic_symtab (bfd *abfd)
4313d8817e4Smiod {
4323d8817e4Smiod asymbol **sy = NULL;
4333d8817e4Smiod long storage;
4343d8817e4Smiod
4353d8817e4Smiod storage = bfd_get_dynamic_symtab_upper_bound (abfd);
4363d8817e4Smiod if (storage < 0)
4373d8817e4Smiod {
4383d8817e4Smiod if (!(bfd_get_file_flags (abfd) & DYNAMIC))
4393d8817e4Smiod {
4403d8817e4Smiod non_fatal (_("%s: not a dynamic object"), bfd_get_filename (abfd));
4413d8817e4Smiod dynsymcount = 0;
4423d8817e4Smiod return NULL;
4433d8817e4Smiod }
4443d8817e4Smiod
4453d8817e4Smiod bfd_fatal (bfd_get_filename (abfd));
4463d8817e4Smiod }
4473d8817e4Smiod if (storage)
4483d8817e4Smiod sy = xmalloc (storage);
4493d8817e4Smiod
4503d8817e4Smiod dynsymcount = bfd_canonicalize_dynamic_symtab (abfd, sy);
4513d8817e4Smiod if (dynsymcount < 0)
4523d8817e4Smiod bfd_fatal (bfd_get_filename (abfd));
4533d8817e4Smiod return sy;
4543d8817e4Smiod }
4553d8817e4Smiod
4563d8817e4Smiod /* Filter out (in place) symbols that are useless for disassembly.
4573d8817e4Smiod COUNT is the number of elements in SYMBOLS.
4583d8817e4Smiod Return the number of useful symbols. */
4593d8817e4Smiod
4603d8817e4Smiod static long
remove_useless_symbols(asymbol ** symbols,long count)4613d8817e4Smiod remove_useless_symbols (asymbol **symbols, long count)
4623d8817e4Smiod {
4633d8817e4Smiod asymbol **in_ptr = symbols, **out_ptr = symbols;
4643d8817e4Smiod
4653d8817e4Smiod while (--count >= 0)
4663d8817e4Smiod {
4673d8817e4Smiod asymbol *sym = *in_ptr++;
4683d8817e4Smiod
4693d8817e4Smiod if (sym->name == NULL || sym->name[0] == '\0')
4703d8817e4Smiod continue;
4713d8817e4Smiod if (sym->flags & (BSF_DEBUGGING | BSF_SECTION_SYM))
4723d8817e4Smiod continue;
4733d8817e4Smiod if (bfd_is_und_section (sym->section)
4743d8817e4Smiod || bfd_is_com_section (sym->section))
4753d8817e4Smiod continue;
4763d8817e4Smiod
4773d8817e4Smiod *out_ptr++ = sym;
4783d8817e4Smiod }
4793d8817e4Smiod return out_ptr - symbols;
4803d8817e4Smiod }
4813d8817e4Smiod
4823d8817e4Smiod /* Sort symbols into value order. */
4833d8817e4Smiod
4843d8817e4Smiod static int
compare_symbols(const void * ap,const void * bp)4853d8817e4Smiod compare_symbols (const void *ap, const void *bp)
4863d8817e4Smiod {
4873d8817e4Smiod const asymbol *a = * (const asymbol **) ap;
4883d8817e4Smiod const asymbol *b = * (const asymbol **) bp;
4893d8817e4Smiod const char *an;
4903d8817e4Smiod const char *bn;
4913d8817e4Smiod size_t anl;
4923d8817e4Smiod size_t bnl;
4933d8817e4Smiod bfd_boolean af;
4943d8817e4Smiod bfd_boolean bf;
4953d8817e4Smiod flagword aflags;
4963d8817e4Smiod flagword bflags;
4973d8817e4Smiod
4983d8817e4Smiod if (bfd_asymbol_value (a) > bfd_asymbol_value (b))
4993d8817e4Smiod return 1;
5003d8817e4Smiod else if (bfd_asymbol_value (a) < bfd_asymbol_value (b))
5013d8817e4Smiod return -1;
5023d8817e4Smiod
5033d8817e4Smiod if (a->section > b->section)
5043d8817e4Smiod return 1;
5053d8817e4Smiod else if (a->section < b->section)
5063d8817e4Smiod return -1;
5073d8817e4Smiod
5083d8817e4Smiod an = bfd_asymbol_name (a);
5093d8817e4Smiod bn = bfd_asymbol_name (b);
5103d8817e4Smiod anl = strlen (an);
5113d8817e4Smiod bnl = strlen (bn);
5123d8817e4Smiod
5133d8817e4Smiod /* The symbols gnu_compiled and gcc2_compiled convey no real
5143d8817e4Smiod information, so put them after other symbols with the same value. */
5153d8817e4Smiod af = (strstr (an, "gnu_compiled") != NULL
5163d8817e4Smiod || strstr (an, "gcc2_compiled") != NULL);
5173d8817e4Smiod bf = (strstr (bn, "gnu_compiled") != NULL
5183d8817e4Smiod || strstr (bn, "gcc2_compiled") != NULL);
5193d8817e4Smiod
5203d8817e4Smiod if (af && ! bf)
5213d8817e4Smiod return 1;
5223d8817e4Smiod if (! af && bf)
5233d8817e4Smiod return -1;
5243d8817e4Smiod
5253d8817e4Smiod /* We use a heuristic for the file name, to try to sort it after
5263d8817e4Smiod more useful symbols. It may not work on non Unix systems, but it
5273d8817e4Smiod doesn't really matter; the only difference is precisely which
5283d8817e4Smiod symbol names get printed. */
5293d8817e4Smiod
5303d8817e4Smiod #define file_symbol(s, sn, snl) \
5313d8817e4Smiod (((s)->flags & BSF_FILE) != 0 \
5323d8817e4Smiod || ((sn)[(snl) - 2] == '.' \
5333d8817e4Smiod && ((sn)[(snl) - 1] == 'o' \
5343d8817e4Smiod || (sn)[(snl) - 1] == 'a')))
5353d8817e4Smiod
5363d8817e4Smiod af = file_symbol (a, an, anl);
5373d8817e4Smiod bf = file_symbol (b, bn, bnl);
5383d8817e4Smiod
5393d8817e4Smiod if (af && ! bf)
5403d8817e4Smiod return 1;
5413d8817e4Smiod if (! af && bf)
5423d8817e4Smiod return -1;
5433d8817e4Smiod
5443d8817e4Smiod /* Try to sort global symbols before local symbols before function
5453d8817e4Smiod symbols before debugging symbols. */
5463d8817e4Smiod
5473d8817e4Smiod aflags = a->flags;
5483d8817e4Smiod bflags = b->flags;
5493d8817e4Smiod
5503d8817e4Smiod if ((aflags & BSF_DEBUGGING) != (bflags & BSF_DEBUGGING))
5513d8817e4Smiod {
5523d8817e4Smiod if ((aflags & BSF_DEBUGGING) != 0)
5533d8817e4Smiod return 1;
5543d8817e4Smiod else
5553d8817e4Smiod return -1;
5563d8817e4Smiod }
5573d8817e4Smiod if ((aflags & BSF_FUNCTION) != (bflags & BSF_FUNCTION))
5583d8817e4Smiod {
5593d8817e4Smiod if ((aflags & BSF_FUNCTION) != 0)
5603d8817e4Smiod return -1;
5613d8817e4Smiod else
5623d8817e4Smiod return 1;
5633d8817e4Smiod }
5643d8817e4Smiod if ((aflags & BSF_LOCAL) != (bflags & BSF_LOCAL))
5653d8817e4Smiod {
5663d8817e4Smiod if ((aflags & BSF_LOCAL) != 0)
5673d8817e4Smiod return 1;
5683d8817e4Smiod else
5693d8817e4Smiod return -1;
5703d8817e4Smiod }
5713d8817e4Smiod if ((aflags & BSF_GLOBAL) != (bflags & BSF_GLOBAL))
5723d8817e4Smiod {
5733d8817e4Smiod if ((aflags & BSF_GLOBAL) != 0)
5743d8817e4Smiod return -1;
5753d8817e4Smiod else
5763d8817e4Smiod return 1;
5773d8817e4Smiod }
5783d8817e4Smiod
5793d8817e4Smiod /* Symbols that start with '.' might be section names, so sort them
5803d8817e4Smiod after symbols that don't start with '.'. */
5813d8817e4Smiod if (an[0] == '.' && bn[0] != '.')
5823d8817e4Smiod return 1;
5833d8817e4Smiod if (an[0] != '.' && bn[0] == '.')
5843d8817e4Smiod return -1;
5853d8817e4Smiod
5863d8817e4Smiod /* Finally, if we can't distinguish them in any other way, try to
5873d8817e4Smiod get consistent results by sorting the symbols by name. */
5883d8817e4Smiod return strcmp (an, bn);
5893d8817e4Smiod }
5903d8817e4Smiod
5913d8817e4Smiod /* Sort relocs into address order. */
5923d8817e4Smiod
5933d8817e4Smiod static int
compare_relocs(const void * ap,const void * bp)5943d8817e4Smiod compare_relocs (const void *ap, const void *bp)
5953d8817e4Smiod {
5963d8817e4Smiod const arelent *a = * (const arelent **) ap;
5973d8817e4Smiod const arelent *b = * (const arelent **) bp;
5983d8817e4Smiod
5993d8817e4Smiod if (a->address > b->address)
6003d8817e4Smiod return 1;
6013d8817e4Smiod else if (a->address < b->address)
6023d8817e4Smiod return -1;
6033d8817e4Smiod
6043d8817e4Smiod /* So that associated relocations tied to the same address show up
6053d8817e4Smiod in the correct order, we don't do any further sorting. */
6063d8817e4Smiod if (a > b)
6073d8817e4Smiod return 1;
6083d8817e4Smiod else if (a < b)
6093d8817e4Smiod return -1;
6103d8817e4Smiod else
6113d8817e4Smiod return 0;
6123d8817e4Smiod }
6133d8817e4Smiod
6143d8817e4Smiod /* Print an address (VMA) to the output stream in INFO.
6153d8817e4Smiod If SKIP_ZEROES is TRUE, omit leading zeroes. */
6163d8817e4Smiod
6173d8817e4Smiod static void
objdump_print_value(bfd_vma vma,struct disassemble_info * info,bfd_boolean skip_zeroes)6183d8817e4Smiod objdump_print_value (bfd_vma vma, struct disassemble_info *info,
6193d8817e4Smiod bfd_boolean skip_zeroes)
6203d8817e4Smiod {
6213d8817e4Smiod char buf[30];
6223d8817e4Smiod char *p;
6233d8817e4Smiod struct objdump_disasm_info *aux;
6243d8817e4Smiod
6253d8817e4Smiod aux = (struct objdump_disasm_info *) info->application_data;
6263d8817e4Smiod bfd_sprintf_vma (aux->abfd, buf, vma);
6273d8817e4Smiod if (! skip_zeroes)
6283d8817e4Smiod p = buf;
6293d8817e4Smiod else
6303d8817e4Smiod {
6313d8817e4Smiod for (p = buf; *p == '0'; ++p)
6323d8817e4Smiod ;
6333d8817e4Smiod if (*p == '\0')
6343d8817e4Smiod --p;
6353d8817e4Smiod }
6363d8817e4Smiod (*info->fprintf_func) (info->stream, "%s", p);
6373d8817e4Smiod }
6383d8817e4Smiod
6393d8817e4Smiod /* Print the name of a symbol. */
6403d8817e4Smiod
6413d8817e4Smiod static void
objdump_print_symname(bfd * abfd,struct disassemble_info * info,asymbol * sym)6423d8817e4Smiod objdump_print_symname (bfd *abfd, struct disassemble_info *info,
6433d8817e4Smiod asymbol *sym)
6443d8817e4Smiod {
6453d8817e4Smiod char *alloc;
6463d8817e4Smiod const char *name;
6473d8817e4Smiod
6483d8817e4Smiod alloc = NULL;
6493d8817e4Smiod name = bfd_asymbol_name (sym);
6503d8817e4Smiod if (do_demangle && name[0] != '\0')
6513d8817e4Smiod {
6523d8817e4Smiod /* Demangle the name. */
6533d8817e4Smiod alloc = demangle (abfd, name);
6543d8817e4Smiod name = alloc;
6553d8817e4Smiod }
6563d8817e4Smiod
6573d8817e4Smiod if (info != NULL)
6583d8817e4Smiod (*info->fprintf_func) (info->stream, "%s", name);
6593d8817e4Smiod else
6603d8817e4Smiod printf ("%s", name);
6613d8817e4Smiod
6623d8817e4Smiod if (alloc != NULL)
6633d8817e4Smiod free (alloc);
6643d8817e4Smiod }
6653d8817e4Smiod
6663d8817e4Smiod /* Locate a symbol given a bfd and a section (from INFO->application_data),
6673d8817e4Smiod and a VMA. If INFO->application_data->require_sec is TRUE, then always
6683d8817e4Smiod require the symbol to be in the section. Returns NULL if there is no
6693d8817e4Smiod suitable symbol. If PLACE is not NULL, then *PLACE is set to the index
6703d8817e4Smiod of the symbol in sorted_syms. */
6713d8817e4Smiod
6723d8817e4Smiod static asymbol *
find_symbol_for_address(bfd_vma vma,struct disassemble_info * info,long * place)6733d8817e4Smiod find_symbol_for_address (bfd_vma vma,
6743d8817e4Smiod struct disassemble_info *info,
6753d8817e4Smiod long *place)
6763d8817e4Smiod {
6773d8817e4Smiod /* @@ Would it speed things up to cache the last two symbols returned,
6783d8817e4Smiod and maybe their address ranges? For many processors, only one memory
6793d8817e4Smiod operand can be present at a time, so the 2-entry cache wouldn't be
6803d8817e4Smiod constantly churned by code doing heavy memory accesses. */
6813d8817e4Smiod
6823d8817e4Smiod /* Indices in `sorted_syms'. */
6833d8817e4Smiod long min = 0;
6843d8817e4Smiod long max = sorted_symcount;
6853d8817e4Smiod long thisplace;
6863d8817e4Smiod struct objdump_disasm_info *aux;
6873d8817e4Smiod bfd *abfd;
6883d8817e4Smiod asection *sec;
6893d8817e4Smiod unsigned int opb;
6903d8817e4Smiod
6913d8817e4Smiod if (sorted_symcount < 1)
6923d8817e4Smiod return NULL;
6933d8817e4Smiod
6943d8817e4Smiod aux = (struct objdump_disasm_info *) info->application_data;
6953d8817e4Smiod abfd = aux->abfd;
6963d8817e4Smiod sec = aux->sec;
6973d8817e4Smiod opb = bfd_octets_per_byte (abfd);
6983d8817e4Smiod
6993d8817e4Smiod /* Perform a binary search looking for the closest symbol to the
7003d8817e4Smiod required value. We are searching the range (min, max]. */
7013d8817e4Smiod while (min + 1 < max)
7023d8817e4Smiod {
7033d8817e4Smiod asymbol *sym;
7043d8817e4Smiod
7053d8817e4Smiod thisplace = (max + min) / 2;
7063d8817e4Smiod sym = sorted_syms[thisplace];
7073d8817e4Smiod
7083d8817e4Smiod if (bfd_asymbol_value (sym) > vma)
7093d8817e4Smiod max = thisplace;
7103d8817e4Smiod else if (bfd_asymbol_value (sym) < vma)
7113d8817e4Smiod min = thisplace;
7123d8817e4Smiod else
7133d8817e4Smiod {
7143d8817e4Smiod min = thisplace;
7153d8817e4Smiod break;
7163d8817e4Smiod }
7173d8817e4Smiod }
7183d8817e4Smiod
7193d8817e4Smiod /* The symbol we want is now in min, the low end of the range we
7203d8817e4Smiod were searching. If there are several symbols with the same
7213d8817e4Smiod value, we want the first one. */
7223d8817e4Smiod thisplace = min;
7233d8817e4Smiod while (thisplace > 0
7243d8817e4Smiod && (bfd_asymbol_value (sorted_syms[thisplace])
7253d8817e4Smiod == bfd_asymbol_value (sorted_syms[thisplace - 1])))
7263d8817e4Smiod --thisplace;
7273d8817e4Smiod
7283d8817e4Smiod /* If the file is relocatable, and the symbol could be from this
7293d8817e4Smiod section, prefer a symbol from this section over symbols from
7303d8817e4Smiod others, even if the other symbol's value might be closer.
7313d8817e4Smiod
7323d8817e4Smiod Note that this may be wrong for some symbol references if the
7333d8817e4Smiod sections have overlapping memory ranges, but in that case there's
7343d8817e4Smiod no way to tell what's desired without looking at the relocation
7353d8817e4Smiod table. */
7363d8817e4Smiod if (sorted_syms[thisplace]->section != sec
7373d8817e4Smiod && (aux->require_sec
7383d8817e4Smiod || ((abfd->flags & HAS_RELOC) != 0
7393d8817e4Smiod && vma >= bfd_get_section_vma (abfd, sec)
7403d8817e4Smiod && vma < (bfd_get_section_vma (abfd, sec)
7413d8817e4Smiod + bfd_section_size (abfd, sec) / opb))))
7423d8817e4Smiod {
7433d8817e4Smiod long i;
7443d8817e4Smiod
7453d8817e4Smiod for (i = thisplace + 1; i < sorted_symcount; i++)
7463d8817e4Smiod {
7473d8817e4Smiod if (bfd_asymbol_value (sorted_syms[i])
7483d8817e4Smiod != bfd_asymbol_value (sorted_syms[thisplace]))
7493d8817e4Smiod break;
7503d8817e4Smiod }
7513d8817e4Smiod
7523d8817e4Smiod --i;
7533d8817e4Smiod
7543d8817e4Smiod for (; i >= 0; i--)
7553d8817e4Smiod {
7563d8817e4Smiod if (sorted_syms[i]->section == sec
7573d8817e4Smiod && (i == 0
7583d8817e4Smiod || sorted_syms[i - 1]->section != sec
7593d8817e4Smiod || (bfd_asymbol_value (sorted_syms[i])
7603d8817e4Smiod != bfd_asymbol_value (sorted_syms[i - 1]))))
7613d8817e4Smiod {
7623d8817e4Smiod thisplace = i;
7633d8817e4Smiod break;
7643d8817e4Smiod }
7653d8817e4Smiod }
7663d8817e4Smiod
7673d8817e4Smiod if (sorted_syms[thisplace]->section != sec)
7683d8817e4Smiod {
7693d8817e4Smiod /* We didn't find a good symbol with a smaller value.
7703d8817e4Smiod Look for one with a larger value. */
7713d8817e4Smiod for (i = thisplace + 1; i < sorted_symcount; i++)
7723d8817e4Smiod {
7733d8817e4Smiod if (sorted_syms[i]->section == sec)
7743d8817e4Smiod {
7753d8817e4Smiod thisplace = i;
7763d8817e4Smiod break;
7773d8817e4Smiod }
7783d8817e4Smiod }
7793d8817e4Smiod }
7803d8817e4Smiod
7813d8817e4Smiod if (sorted_syms[thisplace]->section != sec
7823d8817e4Smiod && (aux->require_sec
7833d8817e4Smiod || ((abfd->flags & HAS_RELOC) != 0
7843d8817e4Smiod && vma >= bfd_get_section_vma (abfd, sec)
7853d8817e4Smiod && vma < (bfd_get_section_vma (abfd, sec)
7863d8817e4Smiod + bfd_section_size (abfd, sec)))))
7873d8817e4Smiod /* There is no suitable symbol. */
7883d8817e4Smiod return NULL;
7893d8817e4Smiod }
7903d8817e4Smiod
7913d8817e4Smiod /* Give the target a chance to reject the symbol. */
7923d8817e4Smiod while (! info->symbol_is_valid (sorted_syms [thisplace], info))
7933d8817e4Smiod {
7943d8817e4Smiod ++ thisplace;
7953d8817e4Smiod if (thisplace >= sorted_symcount
7963d8817e4Smiod || bfd_asymbol_value (sorted_syms [thisplace]) > vma)
7973d8817e4Smiod return NULL;
7983d8817e4Smiod }
7993d8817e4Smiod
8003d8817e4Smiod if (place != NULL)
8013d8817e4Smiod *place = thisplace;
8023d8817e4Smiod
8033d8817e4Smiod return sorted_syms[thisplace];
8043d8817e4Smiod }
8053d8817e4Smiod
8063d8817e4Smiod /* Print an address and the offset to the nearest symbol. */
8073d8817e4Smiod
8083d8817e4Smiod static void
objdump_print_addr_with_sym(bfd * abfd,asection * sec,asymbol * sym,bfd_vma vma,struct disassemble_info * info,bfd_boolean skip_zeroes)8093d8817e4Smiod objdump_print_addr_with_sym (bfd *abfd, asection *sec, asymbol *sym,
8103d8817e4Smiod bfd_vma vma, struct disassemble_info *info,
8113d8817e4Smiod bfd_boolean skip_zeroes)
8123d8817e4Smiod {
8133d8817e4Smiod objdump_print_value (vma, info, skip_zeroes);
8143d8817e4Smiod
8153d8817e4Smiod if (sym == NULL)
8163d8817e4Smiod {
8173d8817e4Smiod bfd_vma secaddr;
8183d8817e4Smiod
8193d8817e4Smiod (*info->fprintf_func) (info->stream, " <%s",
8203d8817e4Smiod bfd_get_section_name (abfd, sec));
8213d8817e4Smiod secaddr = bfd_get_section_vma (abfd, sec);
8223d8817e4Smiod if (vma < secaddr)
8233d8817e4Smiod {
8243d8817e4Smiod (*info->fprintf_func) (info->stream, "-0x");
8253d8817e4Smiod objdump_print_value (secaddr - vma, info, TRUE);
8263d8817e4Smiod }
8273d8817e4Smiod else if (vma > secaddr)
8283d8817e4Smiod {
8293d8817e4Smiod (*info->fprintf_func) (info->stream, "+0x");
8303d8817e4Smiod objdump_print_value (vma - secaddr, info, TRUE);
8313d8817e4Smiod }
8323d8817e4Smiod (*info->fprintf_func) (info->stream, ">");
8333d8817e4Smiod }
8343d8817e4Smiod else
8353d8817e4Smiod {
8363d8817e4Smiod (*info->fprintf_func) (info->stream, " <");
8373d8817e4Smiod objdump_print_symname (abfd, info, sym);
8383d8817e4Smiod if (bfd_asymbol_value (sym) > vma)
8393d8817e4Smiod {
8403d8817e4Smiod (*info->fprintf_func) (info->stream, "-0x");
8413d8817e4Smiod objdump_print_value (bfd_asymbol_value (sym) - vma, info, TRUE);
8423d8817e4Smiod }
8433d8817e4Smiod else if (vma > bfd_asymbol_value (sym))
8443d8817e4Smiod {
8453d8817e4Smiod (*info->fprintf_func) (info->stream, "+0x");
8463d8817e4Smiod objdump_print_value (vma - bfd_asymbol_value (sym), info, TRUE);
8473d8817e4Smiod }
8483d8817e4Smiod (*info->fprintf_func) (info->stream, ">");
8493d8817e4Smiod }
8503d8817e4Smiod }
8513d8817e4Smiod
8523d8817e4Smiod /* Print an address (VMA), symbolically if possible.
8533d8817e4Smiod If SKIP_ZEROES is TRUE, don't output leading zeroes. */
8543d8817e4Smiod
8553d8817e4Smiod static void
objdump_print_addr(bfd_vma vma,struct disassemble_info * info,bfd_boolean skip_zeroes)8563d8817e4Smiod objdump_print_addr (bfd_vma vma,
8573d8817e4Smiod struct disassemble_info *info,
8583d8817e4Smiod bfd_boolean skip_zeroes)
8593d8817e4Smiod {
8603d8817e4Smiod struct objdump_disasm_info *aux;
8613d8817e4Smiod asymbol *sym = NULL; /* Initialize to avoid compiler warning. */
8623d8817e4Smiod bfd_boolean skip_find = FALSE;
8633d8817e4Smiod
8643d8817e4Smiod if (sorted_symcount < 1)
8653d8817e4Smiod {
8663d8817e4Smiod (*info->fprintf_func) (info->stream, "0x");
8673d8817e4Smiod objdump_print_value (vma, info, skip_zeroes);
8683d8817e4Smiod return;
8693d8817e4Smiod }
8703d8817e4Smiod
8713d8817e4Smiod aux = (struct objdump_disasm_info *) info->application_data;
8723d8817e4Smiod
8733d8817e4Smiod if (aux->reloc != NULL
8743d8817e4Smiod && aux->reloc->sym_ptr_ptr != NULL
8753d8817e4Smiod && * aux->reloc->sym_ptr_ptr != NULL)
8763d8817e4Smiod {
8773d8817e4Smiod sym = * aux->reloc->sym_ptr_ptr;
8783d8817e4Smiod
8793d8817e4Smiod /* Adjust the vma to the reloc. */
8803d8817e4Smiod vma += bfd_asymbol_value (sym);
8813d8817e4Smiod
8823d8817e4Smiod if (bfd_is_und_section (bfd_get_section (sym)))
8833d8817e4Smiod skip_find = TRUE;
8843d8817e4Smiod }
8853d8817e4Smiod
8863d8817e4Smiod if (!skip_find)
8873d8817e4Smiod sym = find_symbol_for_address (vma, info, NULL);
8883d8817e4Smiod
8893d8817e4Smiod objdump_print_addr_with_sym (aux->abfd, aux->sec, sym, vma, info,
8903d8817e4Smiod skip_zeroes);
8913d8817e4Smiod }
8923d8817e4Smiod
8933d8817e4Smiod /* Print VMA to INFO. This function is passed to the disassembler
8943d8817e4Smiod routine. */
8953d8817e4Smiod
8963d8817e4Smiod static void
objdump_print_address(bfd_vma vma,struct disassemble_info * info)8973d8817e4Smiod objdump_print_address (bfd_vma vma, struct disassemble_info *info)
8983d8817e4Smiod {
8993d8817e4Smiod objdump_print_addr (vma, info, ! prefix_addresses);
9003d8817e4Smiod }
9013d8817e4Smiod
9023d8817e4Smiod /* Determine if the given address has a symbol associated with it. */
9033d8817e4Smiod
9043d8817e4Smiod static int
objdump_symbol_at_address(bfd_vma vma,struct disassemble_info * info)9053d8817e4Smiod objdump_symbol_at_address (bfd_vma vma, struct disassemble_info * info)
9063d8817e4Smiod {
9073d8817e4Smiod asymbol * sym;
9083d8817e4Smiod
9093d8817e4Smiod sym = find_symbol_for_address (vma, info, NULL);
9103d8817e4Smiod
9113d8817e4Smiod return (sym != NULL && (bfd_asymbol_value (sym) == vma));
9123d8817e4Smiod }
9133d8817e4Smiod
9143d8817e4Smiod /* Hold the last function name and the last line number we displayed
9153d8817e4Smiod in a disassembly. */
9163d8817e4Smiod
9173d8817e4Smiod static char *prev_functionname;
9183d8817e4Smiod static unsigned int prev_line;
9193d8817e4Smiod
9203d8817e4Smiod /* We keep a list of all files that we have seen when doing a
9213d8817e4Smiod disassembly with source, so that we know how much of the file to
9223d8817e4Smiod display. This can be important for inlined functions. */
9233d8817e4Smiod
9243d8817e4Smiod struct print_file_list
9253d8817e4Smiod {
9263d8817e4Smiod struct print_file_list *next;
9273d8817e4Smiod const char *filename;
9283d8817e4Smiod const char *modname;
9293d8817e4Smiod unsigned int line;
9303d8817e4Smiod FILE *f;
9313d8817e4Smiod };
9323d8817e4Smiod
9333d8817e4Smiod static struct print_file_list *print_files;
9343d8817e4Smiod
9353d8817e4Smiod /* The number of preceding context lines to show when we start
9363d8817e4Smiod displaying a file for the first time. */
9373d8817e4Smiod
9383d8817e4Smiod #define SHOW_PRECEDING_CONTEXT_LINES (5)
9393d8817e4Smiod
9403d8817e4Smiod /* Tries to open MODNAME, and if successful adds a node to print_files
9413d8817e4Smiod linked list and returns that node. Returns NULL on failure. */
9423d8817e4Smiod
9433d8817e4Smiod static struct print_file_list *
try_print_file_open(const char * origname,const char * modname)9443d8817e4Smiod try_print_file_open (const char *origname, const char *modname)
9453d8817e4Smiod {
9463d8817e4Smiod struct print_file_list *p;
9473d8817e4Smiod FILE *f;
9483d8817e4Smiod
9493d8817e4Smiod f = fopen (modname, "r");
9503d8817e4Smiod if (f == NULL)
9513d8817e4Smiod return NULL;
9523d8817e4Smiod
9533d8817e4Smiod if (print_files != NULL && print_files->f != NULL)
9543d8817e4Smiod {
9553d8817e4Smiod fclose (print_files->f);
9563d8817e4Smiod print_files->f = NULL;
9573d8817e4Smiod }
9583d8817e4Smiod
9593d8817e4Smiod p = xmalloc (sizeof (struct print_file_list));
9603d8817e4Smiod p->filename = origname;
9613d8817e4Smiod p->modname = modname;
9623d8817e4Smiod p->line = 0;
9633d8817e4Smiod p->f = f;
9643d8817e4Smiod p->next = print_files;
9653d8817e4Smiod print_files = p;
9663d8817e4Smiod return p;
9673d8817e4Smiod }
9683d8817e4Smiod
9693d8817e4Smiod /* If the the source file, as described in the symtab, is not found
9703d8817e4Smiod try to locate it in one of the paths specified with -I
9713d8817e4Smiod If found, add location to print_files linked list. */
9723d8817e4Smiod
9733d8817e4Smiod static struct print_file_list *
update_source_path(const char * filename)9743d8817e4Smiod update_source_path (const char *filename)
9753d8817e4Smiod {
9763d8817e4Smiod struct print_file_list *p;
9773d8817e4Smiod const char *fname;
9783d8817e4Smiod int i;
9793d8817e4Smiod
9803d8817e4Smiod if (filename == NULL)
9813d8817e4Smiod return NULL;
9823d8817e4Smiod
9833d8817e4Smiod p = try_print_file_open (filename, filename);
9843d8817e4Smiod if (p != NULL)
9853d8817e4Smiod return p;
9863d8817e4Smiod
9873d8817e4Smiod if (include_path_count == 0)
9883d8817e4Smiod return NULL;
9893d8817e4Smiod
9903d8817e4Smiod /* Get the name of the file. */
9913d8817e4Smiod fname = strrchr (filename, '/');
9923d8817e4Smiod #ifdef HAVE_DOS_BASED_FILE_SYSTEM
9933d8817e4Smiod {
9943d8817e4Smiod /* We could have a mixed forward/back slash case. */
9953d8817e4Smiod char *backslash = strrchr (filename, '\\');
9963d8817e4Smiod if (fname == NULL || (backslash != NULL && backslash > fname))
9973d8817e4Smiod fname = backslash;
9983d8817e4Smiod if (fname == NULL && filename[0] != '\0' && filename[1] == ':')
9993d8817e4Smiod fname = filename + 1;
10003d8817e4Smiod }
10013d8817e4Smiod #endif
10023d8817e4Smiod if (fname == NULL)
10033d8817e4Smiod fname = filename;
10043d8817e4Smiod else
10053d8817e4Smiod ++fname;
10063d8817e4Smiod
10073d8817e4Smiod /* If file exists under a new path, we need to add it to the list
10083d8817e4Smiod so that show_line knows about it. */
10093d8817e4Smiod for (i = 0; i < include_path_count; i++)
10103d8817e4Smiod {
10113d8817e4Smiod char *modname = concat (include_paths[i], "/", fname, (const char *) 0);
10123d8817e4Smiod
10133d8817e4Smiod p = try_print_file_open (filename, modname);
10143d8817e4Smiod if (p)
10153d8817e4Smiod return p;
10163d8817e4Smiod
10173d8817e4Smiod free (modname);
10183d8817e4Smiod }
10193d8817e4Smiod
10203d8817e4Smiod return NULL;
10213d8817e4Smiod }
10223d8817e4Smiod
10233d8817e4Smiod /* Skip ahead to a given line in a file, optionally printing each
10243d8817e4Smiod line. */
10253d8817e4Smiod
10263d8817e4Smiod static void
skip_to_line(struct print_file_list * p,unsigned int line,bfd_boolean show)10273d8817e4Smiod skip_to_line (struct print_file_list *p, unsigned int line,
10283d8817e4Smiod bfd_boolean show)
10293d8817e4Smiod {
10303d8817e4Smiod while (p->line < line)
10313d8817e4Smiod {
10323d8817e4Smiod char buf[100];
10333d8817e4Smiod
10343d8817e4Smiod if (fgets (buf, sizeof buf, p->f) == NULL)
10353d8817e4Smiod {
10363d8817e4Smiod fclose (p->f);
10373d8817e4Smiod p->f = NULL;
10383d8817e4Smiod break;
10393d8817e4Smiod }
10403d8817e4Smiod
10413d8817e4Smiod if (show)
10423d8817e4Smiod printf ("%s", buf);
10433d8817e4Smiod
10443d8817e4Smiod if (strchr (buf, '\n') != NULL)
10453d8817e4Smiod ++p->line;
10463d8817e4Smiod }
10473d8817e4Smiod }
10483d8817e4Smiod
10493d8817e4Smiod /* Show the line number, or the source line, in a disassembly
10503d8817e4Smiod listing. */
10513d8817e4Smiod
10523d8817e4Smiod static void
show_line(bfd * abfd,asection * section,bfd_vma addr_offset)10533d8817e4Smiod show_line (bfd *abfd, asection *section, bfd_vma addr_offset)
10543d8817e4Smiod {
10553d8817e4Smiod const char *filename;
10563d8817e4Smiod const char *functionname;
10573d8817e4Smiod unsigned int line;
10583d8817e4Smiod
10593d8817e4Smiod if (! with_line_numbers && ! with_source_code)
10603d8817e4Smiod return;
10613d8817e4Smiod
10623d8817e4Smiod if (! bfd_find_nearest_line (abfd, section, syms, addr_offset, &filename,
10633d8817e4Smiod &functionname, &line))
10643d8817e4Smiod return;
10653d8817e4Smiod
10663d8817e4Smiod if (filename != NULL && *filename == '\0')
10673d8817e4Smiod filename = NULL;
10683d8817e4Smiod if (functionname != NULL && *functionname == '\0')
10693d8817e4Smiod functionname = NULL;
10703d8817e4Smiod
10713d8817e4Smiod if (with_line_numbers)
10723d8817e4Smiod {
10733d8817e4Smiod if (functionname != NULL
10743d8817e4Smiod && (prev_functionname == NULL
10753d8817e4Smiod || strcmp (functionname, prev_functionname) != 0))
10763d8817e4Smiod printf ("%s():\n", functionname);
10773d8817e4Smiod if (line > 0 && line != prev_line)
10783d8817e4Smiod printf ("%s:%u\n", filename == NULL ? "???" : filename, line);
10793d8817e4Smiod }
10803d8817e4Smiod
10813d8817e4Smiod if (with_source_code
10823d8817e4Smiod && filename != NULL
10833d8817e4Smiod && line > 0)
10843d8817e4Smiod {
10853d8817e4Smiod struct print_file_list **pp, *p;
10863d8817e4Smiod
10873d8817e4Smiod for (pp = &print_files; *pp != NULL; pp = &(*pp)->next)
10883d8817e4Smiod if (strcmp ((*pp)->filename, filename) == 0)
10893d8817e4Smiod break;
10903d8817e4Smiod p = *pp;
10913d8817e4Smiod
10923d8817e4Smiod if (p != NULL)
10933d8817e4Smiod {
10943d8817e4Smiod if (p != print_files)
10953d8817e4Smiod {
10963d8817e4Smiod int l;
10973d8817e4Smiod
10983d8817e4Smiod /* We have reencountered a file name which we saw
10993d8817e4Smiod earlier. This implies that either we are dumping out
11003d8817e4Smiod code from an included file, or the same file was
11013d8817e4Smiod linked in more than once. There are two common cases
11023d8817e4Smiod of an included file: inline functions in a header
11033d8817e4Smiod file, and a bison or flex skeleton file. In the
11043d8817e4Smiod former case we want to just start printing (but we
11053d8817e4Smiod back up a few lines to give context); in the latter
11063d8817e4Smiod case we want to continue from where we left off. I
11073d8817e4Smiod can't think of a good way to distinguish the cases,
11083d8817e4Smiod so I used a heuristic based on the file name. */
11093d8817e4Smiod if (strcmp (p->filename + strlen (p->filename) - 2, ".h") != 0)
11103d8817e4Smiod l = p->line;
11113d8817e4Smiod else
11123d8817e4Smiod {
11133d8817e4Smiod l = line - SHOW_PRECEDING_CONTEXT_LINES;
11143d8817e4Smiod if (l < 0)
11153d8817e4Smiod l = 0;
11163d8817e4Smiod }
11173d8817e4Smiod
11183d8817e4Smiod if (p->f == NULL)
11193d8817e4Smiod {
11203d8817e4Smiod p->f = fopen (p->modname, "r");
11213d8817e4Smiod p->line = 0;
11223d8817e4Smiod }
11233d8817e4Smiod if (p->f != NULL)
11243d8817e4Smiod skip_to_line (p, l, FALSE);
11253d8817e4Smiod
11263d8817e4Smiod if (print_files->f != NULL)
11273d8817e4Smiod {
11283d8817e4Smiod fclose (print_files->f);
11293d8817e4Smiod print_files->f = NULL;
11303d8817e4Smiod }
11313d8817e4Smiod }
11323d8817e4Smiod
11333d8817e4Smiod if (p->f != NULL)
11343d8817e4Smiod {
11353d8817e4Smiod skip_to_line (p, line, TRUE);
11363d8817e4Smiod *pp = p->next;
11373d8817e4Smiod p->next = print_files;
11383d8817e4Smiod print_files = p;
11393d8817e4Smiod }
11403d8817e4Smiod }
11413d8817e4Smiod else
11423d8817e4Smiod {
11433d8817e4Smiod p = update_source_path (filename);
11443d8817e4Smiod
11453d8817e4Smiod if (p != NULL)
11463d8817e4Smiod {
11473d8817e4Smiod int l;
11483d8817e4Smiod
11493d8817e4Smiod if (file_start_context)
11503d8817e4Smiod l = 0;
11513d8817e4Smiod else
11523d8817e4Smiod l = line - SHOW_PRECEDING_CONTEXT_LINES;
11533d8817e4Smiod if (l < 0)
11543d8817e4Smiod l = 0;
11553d8817e4Smiod skip_to_line (p, l, FALSE);
11563d8817e4Smiod if (p->f != NULL)
11573d8817e4Smiod skip_to_line (p, line, TRUE);
11583d8817e4Smiod }
11593d8817e4Smiod }
11603d8817e4Smiod }
11613d8817e4Smiod
11623d8817e4Smiod if (functionname != NULL
11633d8817e4Smiod && (prev_functionname == NULL
11643d8817e4Smiod || strcmp (functionname, prev_functionname) != 0))
11653d8817e4Smiod {
11663d8817e4Smiod if (prev_functionname != NULL)
11673d8817e4Smiod free (prev_functionname);
11683d8817e4Smiod prev_functionname = xmalloc (strlen (functionname) + 1);
11693d8817e4Smiod strcpy (prev_functionname, functionname);
11703d8817e4Smiod }
11713d8817e4Smiod
11723d8817e4Smiod if (line > 0 && line != prev_line)
11733d8817e4Smiod prev_line = line;
11743d8817e4Smiod }
11753d8817e4Smiod
11763d8817e4Smiod /* Pseudo FILE object for strings. */
11773d8817e4Smiod typedef struct
11783d8817e4Smiod {
11793d8817e4Smiod char *buffer;
11803d8817e4Smiod size_t pos;
11813d8817e4Smiod size_t alloc;
11823d8817e4Smiod } SFILE;
11833d8817e4Smiod
11843d8817e4Smiod /* sprintf to a "stream". */
11853d8817e4Smiod
11863d8817e4Smiod static int ATTRIBUTE_PRINTF_2
objdump_sprintf(SFILE * f,const char * format,...)11873d8817e4Smiod objdump_sprintf (SFILE *f, const char *format, ...)
11883d8817e4Smiod {
11893d8817e4Smiod size_t n;
11903d8817e4Smiod va_list args;
11913d8817e4Smiod
11923d8817e4Smiod while (1)
11933d8817e4Smiod {
11943d8817e4Smiod size_t space = f->alloc - f->pos;
11953d8817e4Smiod
11963d8817e4Smiod va_start (args, format);
11973d8817e4Smiod n = vsnprintf (f->buffer + f->pos, space, format, args);
11983d8817e4Smiod va_end (args);
11993d8817e4Smiod
12003d8817e4Smiod if (space > n)
12013d8817e4Smiod break;
12023d8817e4Smiod
12033d8817e4Smiod f->alloc = (f->alloc + n) * 2;
12043d8817e4Smiod f->buffer = xrealloc (f->buffer, f->alloc);
12053d8817e4Smiod }
12063d8817e4Smiod f->pos += n;
12073d8817e4Smiod
12083d8817e4Smiod return n;
12093d8817e4Smiod }
12103d8817e4Smiod
12113d8817e4Smiod /* Returns TRUE if the specified section should be dumped. */
12123d8817e4Smiod
12133d8817e4Smiod static bfd_boolean
process_section_p(asection * section)12143d8817e4Smiod process_section_p (asection * section)
12153d8817e4Smiod {
12163d8817e4Smiod size_t i;
12173d8817e4Smiod
12183d8817e4Smiod if (only == NULL)
12193d8817e4Smiod return TRUE;
12203d8817e4Smiod
12213d8817e4Smiod for (i = 0; i < only_used; i++)
12223d8817e4Smiod if (strcmp (only [i], section->name) == 0)
12233d8817e4Smiod return TRUE;
12243d8817e4Smiod
12253d8817e4Smiod return FALSE;
12263d8817e4Smiod }
12273d8817e4Smiod
12283d8817e4Smiod
12293d8817e4Smiod /* The number of zeroes we want to see before we start skipping them.
12303d8817e4Smiod The number is arbitrarily chosen. */
12313d8817e4Smiod
12323d8817e4Smiod #define DEFAULT_SKIP_ZEROES 8
12333d8817e4Smiod
12343d8817e4Smiod /* The number of zeroes to skip at the end of a section. If the
12353d8817e4Smiod number of zeroes at the end is between SKIP_ZEROES_AT_END and
12363d8817e4Smiod SKIP_ZEROES, they will be disassembled. If there are fewer than
12373d8817e4Smiod SKIP_ZEROES_AT_END, they will be skipped. This is a heuristic
12383d8817e4Smiod attempt to avoid disassembling zeroes inserted by section
12393d8817e4Smiod alignment. */
12403d8817e4Smiod
12413d8817e4Smiod #define DEFAULT_SKIP_ZEROES_AT_END 3
12423d8817e4Smiod
12433d8817e4Smiod /* Disassemble some data in memory between given values. */
12443d8817e4Smiod
12453d8817e4Smiod static void
disassemble_bytes(struct disassemble_info * info,disassembler_ftype disassemble_fn,bfd_boolean insns,bfd_byte * data,bfd_vma start_offset,bfd_vma stop_offset,bfd_vma rel_offset,arelent *** relppp,arelent ** relppend)12463d8817e4Smiod disassemble_bytes (struct disassemble_info * info,
12473d8817e4Smiod disassembler_ftype disassemble_fn,
12483d8817e4Smiod bfd_boolean insns,
12493d8817e4Smiod bfd_byte * data,
12503d8817e4Smiod bfd_vma start_offset,
12513d8817e4Smiod bfd_vma stop_offset,
12523d8817e4Smiod bfd_vma rel_offset,
12533d8817e4Smiod arelent *** relppp,
12543d8817e4Smiod arelent ** relppend)
12553d8817e4Smiod {
12563d8817e4Smiod struct objdump_disasm_info *aux;
12573d8817e4Smiod asection *section;
12583d8817e4Smiod int octets_per_line;
12593d8817e4Smiod bfd_boolean done_dot;
12603d8817e4Smiod int skip_addr_chars;
12613d8817e4Smiod bfd_vma addr_offset;
12623d8817e4Smiod unsigned int opb = info->octets_per_byte;
12633d8817e4Smiod unsigned int skip_zeroes = info->skip_zeroes;
12643d8817e4Smiod unsigned int skip_zeroes_at_end = info->skip_zeroes_at_end;
12653d8817e4Smiod int octets = opb;
12663d8817e4Smiod SFILE sfile;
12673d8817e4Smiod
12683d8817e4Smiod aux = (struct objdump_disasm_info *) info->application_data;
12693d8817e4Smiod section = aux->sec;
12703d8817e4Smiod
12713d8817e4Smiod sfile.alloc = 120;
12723d8817e4Smiod sfile.buffer = xmalloc (sfile.alloc);
12733d8817e4Smiod sfile.pos = 0;
12743d8817e4Smiod
12753d8817e4Smiod if (insns)
12763d8817e4Smiod octets_per_line = 4;
12773d8817e4Smiod else
12783d8817e4Smiod octets_per_line = 16;
12793d8817e4Smiod
12803d8817e4Smiod /* Figure out how many characters to skip at the start of an
12813d8817e4Smiod address, to make the disassembly look nicer. We discard leading
12823d8817e4Smiod zeroes in chunks of 4, ensuring that there is always a leading
12833d8817e4Smiod zero remaining. */
12843d8817e4Smiod skip_addr_chars = 0;
12853d8817e4Smiod if (! prefix_addresses)
12863d8817e4Smiod {
12873d8817e4Smiod char buf[30];
12883d8817e4Smiod char *s;
12893d8817e4Smiod
12903d8817e4Smiod bfd_sprintf_vma
12913d8817e4Smiod (aux->abfd, buf,
12923d8817e4Smiod (section->vma
12933d8817e4Smiod + bfd_section_size (section->owner, section) / opb));
12943d8817e4Smiod s = buf;
12953d8817e4Smiod while (s[0] == '0' && s[1] == '0' && s[2] == '0' && s[3] == '0'
12963d8817e4Smiod && s[4] == '0')
12973d8817e4Smiod {
12983d8817e4Smiod skip_addr_chars += 4;
12993d8817e4Smiod s += 4;
13003d8817e4Smiod }
13013d8817e4Smiod }
13023d8817e4Smiod
13033d8817e4Smiod info->insn_info_valid = 0;
13043d8817e4Smiod
13053d8817e4Smiod done_dot = FALSE;
13063d8817e4Smiod addr_offset = start_offset;
13073d8817e4Smiod while (addr_offset < stop_offset)
13083d8817e4Smiod {
13093d8817e4Smiod bfd_vma z;
13103d8817e4Smiod bfd_boolean need_nl = FALSE;
13113d8817e4Smiod int previous_octets;
13123d8817e4Smiod
13133d8817e4Smiod /* Remember the length of the previous instruction. */
13143d8817e4Smiod previous_octets = octets;
13153d8817e4Smiod octets = 0;
13163d8817e4Smiod
13173d8817e4Smiod /* If we see more than SKIP_ZEROES octets of zeroes, we just
13183d8817e4Smiod print `...'. */
13193d8817e4Smiod for (z = addr_offset * opb; z < stop_offset * opb; z++)
13203d8817e4Smiod if (data[z] != 0)
13213d8817e4Smiod break;
13223d8817e4Smiod if (! disassemble_zeroes
13233d8817e4Smiod && (info->insn_info_valid == 0
13243d8817e4Smiod || info->branch_delay_insns == 0)
13253d8817e4Smiod && (z - addr_offset * opb >= skip_zeroes
13263d8817e4Smiod || (z == stop_offset * opb &&
13273d8817e4Smiod z - addr_offset * opb < skip_zeroes_at_end)))
13283d8817e4Smiod {
13293d8817e4Smiod printf ("\t...\n");
13303d8817e4Smiod
13313d8817e4Smiod /* If there are more nonzero octets to follow, we only skip
13323d8817e4Smiod zeroes in multiples of 4, to try to avoid running over
13333d8817e4Smiod the start of an instruction which happens to start with
13343d8817e4Smiod zero. */
13353d8817e4Smiod if (z != stop_offset * opb)
13363d8817e4Smiod z = addr_offset * opb + ((z - addr_offset * opb) &~ 3);
13373d8817e4Smiod
13383d8817e4Smiod octets = z - addr_offset * opb;
13393d8817e4Smiod }
13403d8817e4Smiod else
13413d8817e4Smiod {
13423d8817e4Smiod char buf[50];
13433d8817e4Smiod int bpc = 0;
13443d8817e4Smiod int pb = 0;
13453d8817e4Smiod
13463d8817e4Smiod done_dot = FALSE;
13473d8817e4Smiod
13483d8817e4Smiod if (with_line_numbers || with_source_code)
13493d8817e4Smiod show_line (aux->abfd, section, addr_offset);
13503d8817e4Smiod
13513d8817e4Smiod if (! prefix_addresses)
13523d8817e4Smiod {
13533d8817e4Smiod char *s;
13543d8817e4Smiod
13553d8817e4Smiod bfd_sprintf_vma (aux->abfd, buf, section->vma + addr_offset);
13563d8817e4Smiod for (s = buf + skip_addr_chars; *s == '0'; s++)
13573d8817e4Smiod *s = ' ';
13583d8817e4Smiod if (*s == '\0')
13593d8817e4Smiod *--s = '0';
13603d8817e4Smiod printf ("%s:\t", buf + skip_addr_chars);
13613d8817e4Smiod }
13623d8817e4Smiod else
13633d8817e4Smiod {
13643d8817e4Smiod aux->require_sec = TRUE;
13653d8817e4Smiod objdump_print_address (section->vma + addr_offset, info);
13663d8817e4Smiod aux->require_sec = FALSE;
13673d8817e4Smiod putchar (' ');
13683d8817e4Smiod }
13693d8817e4Smiod
13703d8817e4Smiod if (insns)
13713d8817e4Smiod {
13723d8817e4Smiod sfile.pos = 0;
13733d8817e4Smiod info->fprintf_func = (fprintf_ftype) objdump_sprintf;
13743d8817e4Smiod info->stream = &sfile;
13753d8817e4Smiod info->bytes_per_line = 0;
13763d8817e4Smiod info->bytes_per_chunk = 0;
13773d8817e4Smiod info->flags = 0;
13783d8817e4Smiod
13793d8817e4Smiod if (info->disassembler_needs_relocs
13803d8817e4Smiod && *relppp < relppend)
13813d8817e4Smiod {
13823d8817e4Smiod bfd_signed_vma distance_to_rel;
13833d8817e4Smiod
13843d8817e4Smiod distance_to_rel = (**relppp)->address
13853d8817e4Smiod - (rel_offset + addr_offset);
13863d8817e4Smiod
13873d8817e4Smiod /* Check to see if the current reloc is associated with
13883d8817e4Smiod the instruction that we are about to disassemble. */
13893d8817e4Smiod if (distance_to_rel == 0
13903d8817e4Smiod /* FIXME: This is wrong. We are trying to catch
13913d8817e4Smiod relocs that are addressed part way through the
13923d8817e4Smiod current instruction, as might happen with a packed
13933d8817e4Smiod VLIW instruction. Unfortunately we do not know the
13943d8817e4Smiod length of the current instruction since we have not
13953d8817e4Smiod disassembled it yet. Instead we take a guess based
13963d8817e4Smiod upon the length of the previous instruction. The
13973d8817e4Smiod proper solution is to have a new target-specific
13983d8817e4Smiod disassembler function which just returns the length
13993d8817e4Smiod of an instruction at a given address without trying
14003d8817e4Smiod to display its disassembly. */
14013d8817e4Smiod || (distance_to_rel > 0
14023d8817e4Smiod && distance_to_rel < (bfd_signed_vma) (previous_octets/ opb)))
14033d8817e4Smiod {
14043d8817e4Smiod info->flags = INSN_HAS_RELOC;
14053d8817e4Smiod aux->reloc = **relppp;
14063d8817e4Smiod }
14073d8817e4Smiod else
14083d8817e4Smiod aux->reloc = NULL;
14093d8817e4Smiod }
14103d8817e4Smiod
14113d8817e4Smiod octets = (*disassemble_fn) (section->vma + addr_offset, info);
14123d8817e4Smiod info->fprintf_func = (fprintf_ftype) fprintf;
14133d8817e4Smiod info->stream = stdout;
14143d8817e4Smiod if (info->bytes_per_line != 0)
14153d8817e4Smiod octets_per_line = info->bytes_per_line;
14163d8817e4Smiod if (octets < 0)
14173d8817e4Smiod {
14183d8817e4Smiod if (sfile.pos)
14193d8817e4Smiod printf ("%s\n", sfile.buffer);
14203d8817e4Smiod break;
14213d8817e4Smiod }
14223d8817e4Smiod }
14233d8817e4Smiod else
14243d8817e4Smiod {
14253d8817e4Smiod bfd_vma j;
14263d8817e4Smiod
14273d8817e4Smiod octets = octets_per_line;
14283d8817e4Smiod if (addr_offset + octets / opb > stop_offset)
14293d8817e4Smiod octets = (stop_offset - addr_offset) * opb;
14303d8817e4Smiod
14313d8817e4Smiod for (j = addr_offset * opb; j < addr_offset * opb + octets; ++j)
14323d8817e4Smiod {
14333d8817e4Smiod if (ISPRINT (data[j]))
14343d8817e4Smiod buf[j - addr_offset * opb] = data[j];
14353d8817e4Smiod else
14363d8817e4Smiod buf[j - addr_offset * opb] = '.';
14373d8817e4Smiod }
14383d8817e4Smiod buf[j - addr_offset * opb] = '\0';
14393d8817e4Smiod }
14403d8817e4Smiod
14413d8817e4Smiod if (prefix_addresses
14423d8817e4Smiod ? show_raw_insn > 0
14433d8817e4Smiod : show_raw_insn >= 0)
14443d8817e4Smiod {
14453d8817e4Smiod bfd_vma j;
14463d8817e4Smiod
14473d8817e4Smiod /* If ! prefix_addresses and ! wide_output, we print
14483d8817e4Smiod octets_per_line octets per line. */
14493d8817e4Smiod pb = octets;
14503d8817e4Smiod if (pb > octets_per_line && ! prefix_addresses && ! wide_output)
14513d8817e4Smiod pb = octets_per_line;
14523d8817e4Smiod
14533d8817e4Smiod if (info->bytes_per_chunk)
14543d8817e4Smiod bpc = info->bytes_per_chunk;
14553d8817e4Smiod else
14563d8817e4Smiod bpc = 1;
14573d8817e4Smiod
14583d8817e4Smiod for (j = addr_offset * opb; j < addr_offset * opb + pb; j += bpc)
14593d8817e4Smiod {
14603d8817e4Smiod int k;
14613d8817e4Smiod
14623d8817e4Smiod if (bpc > 1 && info->display_endian == BFD_ENDIAN_LITTLE)
14633d8817e4Smiod {
14643d8817e4Smiod for (k = bpc - 1; k >= 0; k--)
14653d8817e4Smiod printf ("%02x", (unsigned) data[j + k]);
14663d8817e4Smiod putchar (' ');
14673d8817e4Smiod }
14683d8817e4Smiod else
14693d8817e4Smiod {
14703d8817e4Smiod for (k = 0; k < bpc; k++)
14713d8817e4Smiod printf ("%02x", (unsigned) data[j + k]);
14723d8817e4Smiod putchar (' ');
14733d8817e4Smiod }
14743d8817e4Smiod }
14753d8817e4Smiod
14763d8817e4Smiod for (; pb < octets_per_line; pb += bpc)
14773d8817e4Smiod {
14783d8817e4Smiod int k;
14793d8817e4Smiod
14803d8817e4Smiod for (k = 0; k < bpc; k++)
14813d8817e4Smiod printf (" ");
14823d8817e4Smiod putchar (' ');
14833d8817e4Smiod }
14843d8817e4Smiod
14853d8817e4Smiod /* Separate raw data from instruction by extra space. */
14863d8817e4Smiod if (insns)
14873d8817e4Smiod putchar ('\t');
14883d8817e4Smiod else
14893d8817e4Smiod printf (" ");
14903d8817e4Smiod }
14913d8817e4Smiod
14923d8817e4Smiod if (! insns)
14933d8817e4Smiod printf ("%s", buf);
14943d8817e4Smiod else if (sfile.pos)
14953d8817e4Smiod printf ("%s", sfile.buffer);
14963d8817e4Smiod
14973d8817e4Smiod if (prefix_addresses
14983d8817e4Smiod ? show_raw_insn > 0
14993d8817e4Smiod : show_raw_insn >= 0)
15003d8817e4Smiod {
15013d8817e4Smiod while (pb < octets)
15023d8817e4Smiod {
15033d8817e4Smiod bfd_vma j;
15043d8817e4Smiod char *s;
15053d8817e4Smiod
15063d8817e4Smiod putchar ('\n');
15073d8817e4Smiod j = addr_offset * opb + pb;
15083d8817e4Smiod
15093d8817e4Smiod bfd_sprintf_vma (aux->abfd, buf, section->vma + j / opb);
15103d8817e4Smiod for (s = buf + skip_addr_chars; *s == '0'; s++)
15113d8817e4Smiod *s = ' ';
15123d8817e4Smiod if (*s == '\0')
15133d8817e4Smiod *--s = '0';
15143d8817e4Smiod printf ("%s:\t", buf + skip_addr_chars);
15153d8817e4Smiod
15163d8817e4Smiod pb += octets_per_line;
15173d8817e4Smiod if (pb > octets)
15183d8817e4Smiod pb = octets;
15193d8817e4Smiod for (; j < addr_offset * opb + pb; j += bpc)
15203d8817e4Smiod {
15213d8817e4Smiod int k;
15223d8817e4Smiod
15233d8817e4Smiod if (bpc > 1 && info->display_endian == BFD_ENDIAN_LITTLE)
15243d8817e4Smiod {
15253d8817e4Smiod for (k = bpc - 1; k >= 0; k--)
15263d8817e4Smiod printf ("%02x", (unsigned) data[j + k]);
15273d8817e4Smiod putchar (' ');
15283d8817e4Smiod }
15293d8817e4Smiod else
15303d8817e4Smiod {
15313d8817e4Smiod for (k = 0; k < bpc; k++)
15323d8817e4Smiod printf ("%02x", (unsigned) data[j + k]);
15333d8817e4Smiod putchar (' ');
15343d8817e4Smiod }
15353d8817e4Smiod }
15363d8817e4Smiod }
15373d8817e4Smiod }
15383d8817e4Smiod
15393d8817e4Smiod if (!wide_output)
15403d8817e4Smiod putchar ('\n');
15413d8817e4Smiod else
15423d8817e4Smiod need_nl = TRUE;
15433d8817e4Smiod }
15443d8817e4Smiod
15453d8817e4Smiod while ((*relppp) < relppend
15463d8817e4Smiod && (**relppp)->address < rel_offset + addr_offset + octets / opb)
15473d8817e4Smiod {
15483d8817e4Smiod if (dump_reloc_info || dump_dynamic_reloc_info)
15493d8817e4Smiod {
15503d8817e4Smiod arelent *q;
15513d8817e4Smiod
15523d8817e4Smiod q = **relppp;
15533d8817e4Smiod
15543d8817e4Smiod if (wide_output)
15553d8817e4Smiod putchar ('\t');
15563d8817e4Smiod else
15573d8817e4Smiod printf ("\t\t\t");
15583d8817e4Smiod
15593d8817e4Smiod objdump_print_value (section->vma - rel_offset + q->address,
15603d8817e4Smiod info, TRUE);
15613d8817e4Smiod
15623d8817e4Smiod if (q->howto == NULL)
15633d8817e4Smiod printf (": *unknown*\t");
15643d8817e4Smiod else if (q->howto->name)
15653d8817e4Smiod printf (": %s\t", q->howto->name);
15663d8817e4Smiod else
15673d8817e4Smiod printf (": %d\t", q->howto->type);
15683d8817e4Smiod
15693d8817e4Smiod if (q->sym_ptr_ptr == NULL || *q->sym_ptr_ptr == NULL)
15703d8817e4Smiod printf ("*unknown*");
15713d8817e4Smiod else
15723d8817e4Smiod {
15733d8817e4Smiod const char *sym_name;
15743d8817e4Smiod
15753d8817e4Smiod sym_name = bfd_asymbol_name (*q->sym_ptr_ptr);
15763d8817e4Smiod if (sym_name != NULL && *sym_name != '\0')
15773d8817e4Smiod objdump_print_symname (aux->abfd, info, *q->sym_ptr_ptr);
15783d8817e4Smiod else
15793d8817e4Smiod {
15803d8817e4Smiod asection *sym_sec;
15813d8817e4Smiod
15823d8817e4Smiod sym_sec = bfd_get_section (*q->sym_ptr_ptr);
15833d8817e4Smiod sym_name = bfd_get_section_name (aux->abfd, sym_sec);
15843d8817e4Smiod if (sym_name == NULL || *sym_name == '\0')
15853d8817e4Smiod sym_name = "*unknown*";
15863d8817e4Smiod printf ("%s", sym_name);
15873d8817e4Smiod }
15883d8817e4Smiod }
15893d8817e4Smiod
15903d8817e4Smiod if (q->addend)
15913d8817e4Smiod {
15923d8817e4Smiod printf ("+0x");
15933d8817e4Smiod objdump_print_value (q->addend, info, TRUE);
15943d8817e4Smiod }
15953d8817e4Smiod
15963d8817e4Smiod printf ("\n");
15973d8817e4Smiod need_nl = FALSE;
15983d8817e4Smiod }
15993d8817e4Smiod ++(*relppp);
16003d8817e4Smiod }
16013d8817e4Smiod
16023d8817e4Smiod if (need_nl)
16033d8817e4Smiod printf ("\n");
16043d8817e4Smiod
16053d8817e4Smiod addr_offset += octets / opb;
16063d8817e4Smiod }
16073d8817e4Smiod
16083d8817e4Smiod free (sfile.buffer);
16093d8817e4Smiod }
16103d8817e4Smiod
16113d8817e4Smiod static void
disassemble_section(bfd * abfd,asection * section,void * info)16123d8817e4Smiod disassemble_section (bfd *abfd, asection *section, void *info)
16133d8817e4Smiod {
16143d8817e4Smiod struct disassemble_info * pinfo = (struct disassemble_info *) info;
16153d8817e4Smiod struct objdump_disasm_info * paux;
16163d8817e4Smiod unsigned int opb = pinfo->octets_per_byte;
16173d8817e4Smiod bfd_byte * data = NULL;
16183d8817e4Smiod bfd_size_type datasize = 0;
16193d8817e4Smiod arelent ** rel_pp = NULL;
16203d8817e4Smiod arelent ** rel_ppstart = NULL;
16213d8817e4Smiod arelent ** rel_ppend;
16223d8817e4Smiod unsigned long stop_offset;
16233d8817e4Smiod asymbol * sym = NULL;
16243d8817e4Smiod long place = 0;
16253d8817e4Smiod long rel_count;
16263d8817e4Smiod bfd_vma rel_offset;
16273d8817e4Smiod unsigned long addr_offset;
16283d8817e4Smiod
16293d8817e4Smiod /* Sections that do not contain machine
16303d8817e4Smiod code are not normally disassembled. */
16313d8817e4Smiod if (! disassemble_all
16323d8817e4Smiod && only == NULL
16333d8817e4Smiod && ((section->flags & (SEC_CODE | SEC_HAS_CONTENTS))
16343d8817e4Smiod != (SEC_CODE | SEC_HAS_CONTENTS)))
16353d8817e4Smiod return;
16363d8817e4Smiod
16373d8817e4Smiod if (! process_section_p (section))
16383d8817e4Smiod return;
16393d8817e4Smiod
16403d8817e4Smiod datasize = bfd_get_section_size (section);
16413d8817e4Smiod if (datasize == 0)
16423d8817e4Smiod return;
16433d8817e4Smiod
16443d8817e4Smiod /* Decide which set of relocs to use. Load them if necessary. */
16453d8817e4Smiod paux = (struct objdump_disasm_info *) pinfo->application_data;
16463d8817e4Smiod if (paux->dynrelbuf)
16473d8817e4Smiod {
16483d8817e4Smiod rel_pp = paux->dynrelbuf;
16493d8817e4Smiod rel_count = paux->dynrelcount;
16503d8817e4Smiod /* Dynamic reloc addresses are absolute, non-dynamic are section
16513d8817e4Smiod relative. REL_OFFSET specifies the reloc address corresponding
16523d8817e4Smiod to the start of this section. */
16533d8817e4Smiod rel_offset = section->vma;
16543d8817e4Smiod }
16553d8817e4Smiod else
16563d8817e4Smiod {
16573d8817e4Smiod rel_count = 0;
16583d8817e4Smiod rel_pp = NULL;
16593d8817e4Smiod rel_offset = 0;
16603d8817e4Smiod
16613d8817e4Smiod if ((section->flags & SEC_RELOC) != 0
16623d8817e4Smiod && (dump_reloc_info || pinfo->disassembler_needs_relocs))
16633d8817e4Smiod {
16643d8817e4Smiod long relsize;
16653d8817e4Smiod
16663d8817e4Smiod relsize = bfd_get_reloc_upper_bound (abfd, section);
16673d8817e4Smiod if (relsize < 0)
16683d8817e4Smiod bfd_fatal (bfd_get_filename (abfd));
16693d8817e4Smiod
16703d8817e4Smiod if (relsize > 0)
16713d8817e4Smiod {
16723d8817e4Smiod rel_ppstart = rel_pp = xmalloc (relsize);
16733d8817e4Smiod rel_count = bfd_canonicalize_reloc (abfd, section, rel_pp, syms);
16743d8817e4Smiod if (rel_count < 0)
16753d8817e4Smiod bfd_fatal (bfd_get_filename (abfd));
16763d8817e4Smiod
16773d8817e4Smiod /* Sort the relocs by address. */
16783d8817e4Smiod qsort (rel_pp, rel_count, sizeof (arelent *), compare_relocs);
16793d8817e4Smiod }
16803d8817e4Smiod }
16813d8817e4Smiod
16823d8817e4Smiod }
16833d8817e4Smiod rel_ppend = rel_pp + rel_count;
16843d8817e4Smiod
16853d8817e4Smiod data = xmalloc (datasize);
16863d8817e4Smiod
16873d8817e4Smiod bfd_get_section_contents (abfd, section, data, 0, datasize);
16883d8817e4Smiod
16893d8817e4Smiod paux->sec = section;
16903d8817e4Smiod pinfo->buffer = data;
16913d8817e4Smiod pinfo->buffer_vma = section->vma;
16923d8817e4Smiod pinfo->buffer_length = datasize;
16933d8817e4Smiod pinfo->section = section;
16943d8817e4Smiod
16953d8817e4Smiod if (start_address == (bfd_vma) -1
16963d8817e4Smiod || start_address < pinfo->buffer_vma)
16973d8817e4Smiod addr_offset = 0;
16983d8817e4Smiod else
16993d8817e4Smiod addr_offset = start_address - pinfo->buffer_vma;
17003d8817e4Smiod
17013d8817e4Smiod if (stop_address == (bfd_vma) -1)
17023d8817e4Smiod stop_offset = datasize / opb;
17033d8817e4Smiod else
17043d8817e4Smiod {
17053d8817e4Smiod if (stop_address < pinfo->buffer_vma)
17063d8817e4Smiod stop_offset = 0;
17073d8817e4Smiod else
17083d8817e4Smiod stop_offset = stop_address - pinfo->buffer_vma;
17093d8817e4Smiod if (stop_offset > pinfo->buffer_length / opb)
17103d8817e4Smiod stop_offset = pinfo->buffer_length / opb;
17113d8817e4Smiod }
17123d8817e4Smiod
17133d8817e4Smiod /* Skip over the relocs belonging to addresses below the
17143d8817e4Smiod start address. */
17153d8817e4Smiod while (rel_pp < rel_ppend
17163d8817e4Smiod && (*rel_pp)->address < rel_offset + addr_offset)
17173d8817e4Smiod ++rel_pp;
17183d8817e4Smiod
17193d8817e4Smiod printf (_("Disassembly of section %s:\n"), section->name);
17203d8817e4Smiod
17213d8817e4Smiod /* Find the nearest symbol forwards from our current position. */
17223d8817e4Smiod paux->require_sec = TRUE;
17233d8817e4Smiod sym = find_symbol_for_address (section->vma + addr_offset, info, &place);
17243d8817e4Smiod paux->require_sec = FALSE;
17253d8817e4Smiod
17263d8817e4Smiod /* Disassemble a block of instructions up to the address associated with
17273d8817e4Smiod the symbol we have just found. Then print the symbol and find the
17283d8817e4Smiod next symbol on. Repeat until we have disassembled the entire section
17293d8817e4Smiod or we have reached the end of the address range we are interested in. */
17303d8817e4Smiod while (addr_offset < stop_offset)
17313d8817e4Smiod {
17323d8817e4Smiod bfd_vma addr;
17333d8817e4Smiod asymbol *nextsym;
17343d8817e4Smiod unsigned long nextstop_offset;
17353d8817e4Smiod bfd_boolean insns;
17363d8817e4Smiod
17373d8817e4Smiod addr = section->vma + addr_offset;
17383d8817e4Smiod
17393d8817e4Smiod if (sym != NULL && bfd_asymbol_value (sym) <= addr)
17403d8817e4Smiod {
17413d8817e4Smiod int x;
17423d8817e4Smiod
17433d8817e4Smiod for (x = place;
17443d8817e4Smiod (x < sorted_symcount
17453d8817e4Smiod && (bfd_asymbol_value (sorted_syms[x]) <= addr));
17463d8817e4Smiod ++x)
17473d8817e4Smiod continue;
17483d8817e4Smiod
17493d8817e4Smiod pinfo->symbols = sorted_syms + place;
17503d8817e4Smiod pinfo->num_symbols = x - place;
17513d8817e4Smiod }
17523d8817e4Smiod else
17533d8817e4Smiod {
17543d8817e4Smiod pinfo->symbols = NULL;
17553d8817e4Smiod pinfo->num_symbols = 0;
17563d8817e4Smiod }
17573d8817e4Smiod
17583d8817e4Smiod if (! prefix_addresses)
17593d8817e4Smiod {
17603d8817e4Smiod pinfo->fprintf_func (pinfo->stream, "\n");
17613d8817e4Smiod objdump_print_addr_with_sym (abfd, section, sym, addr,
17623d8817e4Smiod pinfo, FALSE);
17633d8817e4Smiod pinfo->fprintf_func (pinfo->stream, ":\n");
17643d8817e4Smiod }
17653d8817e4Smiod
17663d8817e4Smiod if (sym != NULL && bfd_asymbol_value (sym) > addr)
17673d8817e4Smiod nextsym = sym;
17683d8817e4Smiod else if (sym == NULL)
17693d8817e4Smiod nextsym = NULL;
17703d8817e4Smiod else
17713d8817e4Smiod {
17723d8817e4Smiod #define is_valid_next_sym(SYM) \
17733d8817e4Smiod ((SYM)->section == section \
17743d8817e4Smiod && (bfd_asymbol_value (SYM) > bfd_asymbol_value (sym)) \
17753d8817e4Smiod && pinfo->symbol_is_valid (SYM, pinfo))
17763d8817e4Smiod
17773d8817e4Smiod /* Search forward for the next appropriate symbol in
17783d8817e4Smiod SECTION. Note that all the symbols are sorted
17793d8817e4Smiod together into one big array, and that some sections
17803d8817e4Smiod may have overlapping addresses. */
17813d8817e4Smiod while (place < sorted_symcount
17823d8817e4Smiod && ! is_valid_next_sym (sorted_syms [place]))
17833d8817e4Smiod ++place;
17843d8817e4Smiod
17853d8817e4Smiod if (place >= sorted_symcount)
17863d8817e4Smiod nextsym = NULL;
17873d8817e4Smiod else
17883d8817e4Smiod nextsym = sorted_syms[place];
17893d8817e4Smiod }
17903d8817e4Smiod
17913d8817e4Smiod if (sym != NULL && bfd_asymbol_value (sym) > addr)
17923d8817e4Smiod nextstop_offset = bfd_asymbol_value (sym) - section->vma;
17933d8817e4Smiod else if (nextsym == NULL)
17943d8817e4Smiod nextstop_offset = stop_offset;
17953d8817e4Smiod else
17963d8817e4Smiod nextstop_offset = bfd_asymbol_value (nextsym) - section->vma;
17973d8817e4Smiod
17983d8817e4Smiod if (nextstop_offset > stop_offset)
17993d8817e4Smiod nextstop_offset = stop_offset;
18003d8817e4Smiod
18013d8817e4Smiod /* If a symbol is explicitly marked as being an object
18023d8817e4Smiod rather than a function, just dump the bytes without
18033d8817e4Smiod disassembling them. */
18043d8817e4Smiod if (disassemble_all
18053d8817e4Smiod || sym == NULL
18063d8817e4Smiod || bfd_asymbol_value (sym) > addr
18073d8817e4Smiod || ((sym->flags & BSF_OBJECT) == 0
18083d8817e4Smiod && (strstr (bfd_asymbol_name (sym), "gnu_compiled")
18093d8817e4Smiod == NULL)
18103d8817e4Smiod && (strstr (bfd_asymbol_name (sym), "gcc2_compiled")
18113d8817e4Smiod == NULL))
18123d8817e4Smiod || (sym->flags & BSF_FUNCTION) != 0)
18133d8817e4Smiod insns = TRUE;
18143d8817e4Smiod else
18153d8817e4Smiod insns = FALSE;
18163d8817e4Smiod
18173d8817e4Smiod disassemble_bytes (pinfo, paux->disassemble_fn, insns, data,
18183d8817e4Smiod addr_offset, nextstop_offset,
18193d8817e4Smiod rel_offset, &rel_pp, rel_ppend);
18203d8817e4Smiod
18213d8817e4Smiod addr_offset = nextstop_offset;
18223d8817e4Smiod sym = nextsym;
18233d8817e4Smiod }
18243d8817e4Smiod
18253d8817e4Smiod free (data);
18263d8817e4Smiod
18273d8817e4Smiod if (rel_ppstart != NULL)
18283d8817e4Smiod free (rel_ppstart);
18293d8817e4Smiod }
18303d8817e4Smiod
18313d8817e4Smiod /* Disassemble the contents of an object file. */
18323d8817e4Smiod
18333d8817e4Smiod static void
disassemble_data(bfd * abfd)18343d8817e4Smiod disassemble_data (bfd *abfd)
18353d8817e4Smiod {
18363d8817e4Smiod struct disassemble_info disasm_info;
18373d8817e4Smiod struct objdump_disasm_info aux;
18383d8817e4Smiod long i;
18393d8817e4Smiod
18403d8817e4Smiod print_files = NULL;
18413d8817e4Smiod prev_functionname = NULL;
18423d8817e4Smiod prev_line = -1;
18433d8817e4Smiod
18443d8817e4Smiod /* We make a copy of syms to sort. We don't want to sort syms
18453d8817e4Smiod because that will screw up the relocs. */
18463d8817e4Smiod sorted_symcount = symcount ? symcount : dynsymcount;
18473d8817e4Smiod sorted_syms = xmalloc ((sorted_symcount + synthcount) * sizeof (asymbol *));
18483d8817e4Smiod memcpy (sorted_syms, symcount ? syms : dynsyms,
18493d8817e4Smiod sorted_symcount * sizeof (asymbol *));
18503d8817e4Smiod
18513d8817e4Smiod sorted_symcount = remove_useless_symbols (sorted_syms, sorted_symcount);
18523d8817e4Smiod
18533d8817e4Smiod for (i = 0; i < synthcount; ++i)
18543d8817e4Smiod {
18553d8817e4Smiod sorted_syms[sorted_symcount] = synthsyms + i;
18563d8817e4Smiod ++sorted_symcount;
18573d8817e4Smiod }
18583d8817e4Smiod
18593d8817e4Smiod /* Sort the symbols into section and symbol order. */
18603d8817e4Smiod qsort (sorted_syms, sorted_symcount, sizeof (asymbol *), compare_symbols);
18613d8817e4Smiod
18623d8817e4Smiod init_disassemble_info (&disasm_info, stdout, (fprintf_ftype) fprintf);
18633d8817e4Smiod
18643d8817e4Smiod disasm_info.application_data = (void *) &aux;
18653d8817e4Smiod aux.abfd = abfd;
18663d8817e4Smiod aux.require_sec = FALSE;
18673d8817e4Smiod aux.dynrelbuf = NULL;
18683d8817e4Smiod aux.dynrelcount = 0;
18693d8817e4Smiod aux.reloc = NULL;
18703d8817e4Smiod
18713d8817e4Smiod disasm_info.print_address_func = objdump_print_address;
18723d8817e4Smiod disasm_info.symbol_at_address_func = objdump_symbol_at_address;
18733d8817e4Smiod
18743d8817e4Smiod if (machine != NULL)
18753d8817e4Smiod {
18763d8817e4Smiod const bfd_arch_info_type *info = bfd_scan_arch (machine);
18773d8817e4Smiod
18783d8817e4Smiod if (info == NULL)
18793d8817e4Smiod fatal (_("Can't use supplied machine %s"), machine);
18803d8817e4Smiod
18813d8817e4Smiod abfd->arch_info = info;
18823d8817e4Smiod }
18833d8817e4Smiod
18843d8817e4Smiod if (endian != BFD_ENDIAN_UNKNOWN)
18853d8817e4Smiod {
18863d8817e4Smiod struct bfd_target *xvec;
18873d8817e4Smiod
18883d8817e4Smiod xvec = xmalloc (sizeof (struct bfd_target));
18893d8817e4Smiod memcpy (xvec, abfd->xvec, sizeof (struct bfd_target));
18903d8817e4Smiod xvec->byteorder = endian;
18913d8817e4Smiod abfd->xvec = xvec;
18923d8817e4Smiod }
18933d8817e4Smiod
18943d8817e4Smiod /* Use libopcodes to locate a suitable disassembler. */
18953d8817e4Smiod aux.disassemble_fn = disassembler (abfd);
18963d8817e4Smiod if (!aux.disassemble_fn)
18973d8817e4Smiod {
18983d8817e4Smiod non_fatal (_("Can't disassemble for architecture %s\n"),
18993d8817e4Smiod bfd_printable_arch_mach (bfd_get_arch (abfd), 0));
19003d8817e4Smiod exit_status = 1;
19013d8817e4Smiod return;
19023d8817e4Smiod }
19033d8817e4Smiod
19043d8817e4Smiod disasm_info.flavour = bfd_get_flavour (abfd);
19053d8817e4Smiod disasm_info.arch = bfd_get_arch (abfd);
19063d8817e4Smiod disasm_info.mach = bfd_get_mach (abfd);
19073d8817e4Smiod disasm_info.disassembler_options = disassembler_options;
19083d8817e4Smiod disasm_info.octets_per_byte = bfd_octets_per_byte (abfd);
19093d8817e4Smiod disasm_info.skip_zeroes = DEFAULT_SKIP_ZEROES;
19103d8817e4Smiod disasm_info.skip_zeroes_at_end = DEFAULT_SKIP_ZEROES_AT_END;
19113d8817e4Smiod disasm_info.disassembler_needs_relocs = FALSE;
19123d8817e4Smiod
19133d8817e4Smiod if (bfd_big_endian (abfd))
19143d8817e4Smiod disasm_info.display_endian = disasm_info.endian = BFD_ENDIAN_BIG;
19153d8817e4Smiod else if (bfd_little_endian (abfd))
19163d8817e4Smiod disasm_info.display_endian = disasm_info.endian = BFD_ENDIAN_LITTLE;
19173d8817e4Smiod else
19183d8817e4Smiod /* ??? Aborting here seems too drastic. We could default to big or little
19193d8817e4Smiod instead. */
19203d8817e4Smiod disasm_info.endian = BFD_ENDIAN_UNKNOWN;
19213d8817e4Smiod
19223d8817e4Smiod /* Allow the target to customize the info structure. */
19233d8817e4Smiod disassemble_init_for_target (& disasm_info);
19243d8817e4Smiod
19253d8817e4Smiod /* Pre-load the dynamic relocs if we are going
19263d8817e4Smiod to be dumping them along with the disassembly. */
19273d8817e4Smiod if (dump_dynamic_reloc_info)
19283d8817e4Smiod {
19293d8817e4Smiod long relsize = bfd_get_dynamic_reloc_upper_bound (abfd);
19303d8817e4Smiod
19313d8817e4Smiod if (relsize < 0)
19323d8817e4Smiod bfd_fatal (bfd_get_filename (abfd));
19333d8817e4Smiod
19343d8817e4Smiod if (relsize > 0)
19353d8817e4Smiod {
19363d8817e4Smiod aux.dynrelbuf = xmalloc (relsize);
19373d8817e4Smiod aux.dynrelcount = bfd_canonicalize_dynamic_reloc (abfd,
19383d8817e4Smiod aux.dynrelbuf,
19393d8817e4Smiod dynsyms);
19403d8817e4Smiod if (aux.dynrelcount < 0)
19413d8817e4Smiod bfd_fatal (bfd_get_filename (abfd));
19423d8817e4Smiod
19433d8817e4Smiod /* Sort the relocs by address. */
19443d8817e4Smiod qsort (aux.dynrelbuf, aux.dynrelcount, sizeof (arelent *),
19453d8817e4Smiod compare_relocs);
19463d8817e4Smiod }
19473d8817e4Smiod }
19483d8817e4Smiod
19493d8817e4Smiod bfd_map_over_sections (abfd, disassemble_section, & disasm_info);
19503d8817e4Smiod
19513d8817e4Smiod if (aux.dynrelbuf != NULL)
19523d8817e4Smiod free (aux.dynrelbuf);
19533d8817e4Smiod free (sorted_syms);
19543d8817e4Smiod }
19553d8817e4Smiod
19563d8817e4Smiod int
load_debug_section(enum dwarf_section_display_enum debug,void * file)19573d8817e4Smiod load_debug_section (enum dwarf_section_display_enum debug, void *file)
19583d8817e4Smiod {
19593d8817e4Smiod struct dwarf_section *section = &debug_displays [debug].section;
19603d8817e4Smiod bfd *abfd = file;
19613d8817e4Smiod asection *sec;
19623d8817e4Smiod bfd_boolean ret;
19633d8817e4Smiod
19643d8817e4Smiod /* If it is already loaded, do nothing. */
19653d8817e4Smiod if (section->start != NULL)
19663d8817e4Smiod return 1;
19673d8817e4Smiod
19683d8817e4Smiod /* Locate the debug section. */
19693d8817e4Smiod sec = bfd_get_section_by_name (abfd, section->name);
19703d8817e4Smiod if (sec == NULL)
19713d8817e4Smiod return 0;
19723d8817e4Smiod
19733d8817e4Smiod section->address = bfd_get_section_vma (abfd, sec);
19743d8817e4Smiod section->size = bfd_get_section_size (sec);
19753d8817e4Smiod section->start = xmalloc (section->size);
19763d8817e4Smiod
19773d8817e4Smiod if (is_relocatable && debug_displays [debug].relocate)
19783d8817e4Smiod ret = bfd_simple_get_relocated_section_contents (abfd,
19793d8817e4Smiod sec,
19803d8817e4Smiod section->start,
19813d8817e4Smiod syms) != NULL;
19823d8817e4Smiod else
19833d8817e4Smiod ret = bfd_get_section_contents (abfd, sec, section->start, 0,
19843d8817e4Smiod section->size);
19853d8817e4Smiod
19863d8817e4Smiod if (!ret)
19873d8817e4Smiod {
19883d8817e4Smiod free_debug_section (debug);
19893d8817e4Smiod printf (_("\nCan't get contents for section '%s'.\n"),
19903d8817e4Smiod section->name);
19913d8817e4Smiod }
19923d8817e4Smiod
19933d8817e4Smiod return ret;
19943d8817e4Smiod }
19953d8817e4Smiod
19963d8817e4Smiod void
free_debug_section(enum dwarf_section_display_enum debug)19973d8817e4Smiod free_debug_section (enum dwarf_section_display_enum debug)
19983d8817e4Smiod {
19993d8817e4Smiod struct dwarf_section *section = &debug_displays [debug].section;
20003d8817e4Smiod
20013d8817e4Smiod if (section->start == NULL)
20023d8817e4Smiod return;
20033d8817e4Smiod
20043d8817e4Smiod free ((char *) section->start);
20053d8817e4Smiod section->start = NULL;
20063d8817e4Smiod section->address = 0;
20073d8817e4Smiod section->size = 0;
20083d8817e4Smiod }
20093d8817e4Smiod
20103d8817e4Smiod static void
dump_dwarf_section(bfd * abfd,asection * section,void * arg ATTRIBUTE_UNUSED)20113d8817e4Smiod dump_dwarf_section (bfd *abfd, asection *section,
20123d8817e4Smiod void *arg ATTRIBUTE_UNUSED)
20133d8817e4Smiod {
20143d8817e4Smiod const char *name = bfd_get_section_name (abfd, section);
20153d8817e4Smiod const char *match;
20163d8817e4Smiod enum dwarf_section_display_enum i;
20173d8817e4Smiod
20183d8817e4Smiod if (strncmp (name, ".gnu.linkonce.wi.", 17) == 0)
20193d8817e4Smiod match = ".debug_info";
20203d8817e4Smiod else
20213d8817e4Smiod match = name;
20223d8817e4Smiod
20233d8817e4Smiod for (i = 0; i < max; i++)
20243d8817e4Smiod if (strcmp (debug_displays[i].section.name, match) == 0)
20253d8817e4Smiod {
20263d8817e4Smiod if (!debug_displays[i].eh_frame)
20273d8817e4Smiod {
20283d8817e4Smiod struct dwarf_section *sec = &debug_displays [i].section;
20293d8817e4Smiod
20303d8817e4Smiod if (load_debug_section (i, abfd))
20313d8817e4Smiod {
20323d8817e4Smiod debug_displays[i].display (sec, abfd);
20333d8817e4Smiod
20343d8817e4Smiod if (i != info && i != abbrev)
20353d8817e4Smiod free_debug_section (i);
20363d8817e4Smiod }
20373d8817e4Smiod }
20383d8817e4Smiod break;
20393d8817e4Smiod }
20403d8817e4Smiod }
20413d8817e4Smiod
20423d8817e4Smiod static const char *mach_o_dwarf_sections [] = {
20433d8817e4Smiod "LC_SEGMENT.__DWARFA.__debug_abbrev", /* .debug_abbrev */
20443d8817e4Smiod "LC_SEGMENT.__DWARFA.__debug_aranges", /* .debug_aranges */
20453d8817e4Smiod "LC_SEGMENT.__DWARFA.__debug_frame", /* .debug_frame */
20463d8817e4Smiod "LC_SEGMENT.__DWARFA.__debug_info", /* .debug_info */
20473d8817e4Smiod "LC_SEGMENT.__DWARFA.__debug_line", /* .debug_line */
20483d8817e4Smiod "LC_SEGMENT.__DWARFA.__debug_pubnames", /* .debug_pubnames */
20493d8817e4Smiod ".eh_frame", /* .eh_frame */
20503d8817e4Smiod "LC_SEGMENT.__DWARFA.__debug_macinfo", /* .debug_macinfo */
20513d8817e4Smiod "LC_SEGMENT.__DWARFA.__debug_str", /* .debug_str */
20523d8817e4Smiod "LC_SEGMENT.__DWARFA.__debug_loc", /* .debug_loc */
20533d8817e4Smiod "LC_SEGMENT.__DWARFA.__debug_pubtypes", /* .debug_pubtypes */
20543d8817e4Smiod "LC_SEGMENT.__DWARFA.__debug_ranges", /* .debug_ranges */
20553d8817e4Smiod "LC_SEGMENT.__DWARFA.__debug_static_func", /* .debug_static_func */
20563d8817e4Smiod "LC_SEGMENT.__DWARFA.__debug_static_vars", /* .debug_static_vars */
20573d8817e4Smiod "LC_SEGMENT.__DWARFA.__debug_types", /* .debug_types */
20583d8817e4Smiod "LC_SEGMENT.__DWARFA.__debug_weaknames" /* .debug_weaknames */
20593d8817e4Smiod };
20603d8817e4Smiod
20613d8817e4Smiod static const char *generic_dwarf_sections [max];
20623d8817e4Smiod
20633d8817e4Smiod static void
check_mach_o_dwarf(bfd * abfd)20643d8817e4Smiod check_mach_o_dwarf (bfd *abfd)
20653d8817e4Smiod {
20663d8817e4Smiod static enum bfd_flavour old_flavour = bfd_target_unknown_flavour;
20673d8817e4Smiod enum bfd_flavour current_flavour = bfd_get_flavour (abfd);
20683d8817e4Smiod enum dwarf_section_display_enum i;
20693d8817e4Smiod
20703d8817e4Smiod if (generic_dwarf_sections [0] == NULL)
20713d8817e4Smiod for (i = 0; i < max; i++)
20723d8817e4Smiod generic_dwarf_sections [i] = debug_displays[i].section.name;
20733d8817e4Smiod
20743d8817e4Smiod if (old_flavour != current_flavour)
20753d8817e4Smiod {
20763d8817e4Smiod if (current_flavour == bfd_target_mach_o_flavour)
20773d8817e4Smiod for (i = 0; i < max; i++)
20783d8817e4Smiod debug_displays[i].section.name = mach_o_dwarf_sections [i];
20793d8817e4Smiod else if (old_flavour == bfd_target_mach_o_flavour)
20803d8817e4Smiod for (i = 0; i < max; i++)
20813d8817e4Smiod debug_displays[i].section.name = generic_dwarf_sections [i];
20823d8817e4Smiod
20833d8817e4Smiod old_flavour = current_flavour;
20843d8817e4Smiod }
20853d8817e4Smiod }
20863d8817e4Smiod
20873d8817e4Smiod /* Dump the dwarf debugging information. */
20883d8817e4Smiod
20893d8817e4Smiod static void
dump_dwarf(bfd * abfd)20903d8817e4Smiod dump_dwarf (bfd *abfd)
20913d8817e4Smiod {
20923d8817e4Smiod is_relocatable = ((abfd->flags & (HAS_RELOC | EXEC_P | DYNAMIC))
20933d8817e4Smiod == HAS_RELOC);
20943d8817e4Smiod
20953d8817e4Smiod /* FIXME: bfd_get_arch_size may return -1. We assume that 64bit
20963d8817e4Smiod targets will return 64. */
20973d8817e4Smiod eh_addr_size = bfd_get_arch_size (abfd) == 64 ? 8 : 4;
20983d8817e4Smiod
20993d8817e4Smiod if (bfd_big_endian (abfd))
21003d8817e4Smiod byte_get = byte_get_big_endian;
21013d8817e4Smiod else if (bfd_little_endian (abfd))
21023d8817e4Smiod byte_get = byte_get_little_endian;
21033d8817e4Smiod else
21043d8817e4Smiod abort ();
21053d8817e4Smiod
21063d8817e4Smiod check_mach_o_dwarf (abfd);
21073d8817e4Smiod
21083d8817e4Smiod bfd_map_over_sections (abfd, dump_dwarf_section, NULL);
21093d8817e4Smiod
21103d8817e4Smiod free_debug_memory ();
21113d8817e4Smiod }
21123d8817e4Smiod
21133d8817e4Smiod /* Read ABFD's stabs section STABSECT_NAME, and return a pointer to
21143d8817e4Smiod it. Return NULL on failure. */
21153d8817e4Smiod
21163d8817e4Smiod static char *
read_section_stabs(bfd * abfd,const char * sect_name,bfd_size_type * size_ptr)21173d8817e4Smiod read_section_stabs (bfd *abfd, const char *sect_name, bfd_size_type *size_ptr)
21183d8817e4Smiod {
21193d8817e4Smiod asection *stabsect;
21203d8817e4Smiod bfd_size_type size;
21213d8817e4Smiod char *contents;
21223d8817e4Smiod
21233d8817e4Smiod stabsect = bfd_get_section_by_name (abfd, sect_name);
21243d8817e4Smiod if (stabsect == NULL)
21253d8817e4Smiod {
21263d8817e4Smiod printf (_("No %s section present\n\n"), sect_name);
21273d8817e4Smiod return FALSE;
21283d8817e4Smiod }
21293d8817e4Smiod
21303d8817e4Smiod size = bfd_section_size (abfd, stabsect);
21313d8817e4Smiod contents = xmalloc (size);
21323d8817e4Smiod
21333d8817e4Smiod if (! bfd_get_section_contents (abfd, stabsect, contents, 0, size))
21343d8817e4Smiod {
21353d8817e4Smiod non_fatal (_("Reading %s section of %s failed: %s"),
21363d8817e4Smiod sect_name, bfd_get_filename (abfd),
21373d8817e4Smiod bfd_errmsg (bfd_get_error ()));
21383d8817e4Smiod free (contents);
21393d8817e4Smiod exit_status = 1;
21403d8817e4Smiod return NULL;
21413d8817e4Smiod }
21423d8817e4Smiod
21433d8817e4Smiod *size_ptr = size;
21443d8817e4Smiod
21453d8817e4Smiod return contents;
21463d8817e4Smiod }
21473d8817e4Smiod
21483d8817e4Smiod /* Stabs entries use a 12 byte format:
21493d8817e4Smiod 4 byte string table index
21503d8817e4Smiod 1 byte stab type
21513d8817e4Smiod 1 byte stab other field
21523d8817e4Smiod 2 byte stab desc field
21533d8817e4Smiod 4 byte stab value
21543d8817e4Smiod FIXME: This will have to change for a 64 bit object format. */
21553d8817e4Smiod
21563d8817e4Smiod #define STRDXOFF (0)
21573d8817e4Smiod #define TYPEOFF (4)
21583d8817e4Smiod #define OTHEROFF (5)
21593d8817e4Smiod #define DESCOFF (6)
21603d8817e4Smiod #define VALOFF (8)
21613d8817e4Smiod #define STABSIZE (12)
21623d8817e4Smiod
21633d8817e4Smiod /* Print ABFD's stabs section STABSECT_NAME (in `stabs'),
21643d8817e4Smiod using string table section STRSECT_NAME (in `strtab'). */
21653d8817e4Smiod
21663d8817e4Smiod static void
print_section_stabs(bfd * abfd,const char * stabsect_name,unsigned * string_offset_ptr)21673d8817e4Smiod print_section_stabs (bfd *abfd,
21683d8817e4Smiod const char *stabsect_name,
21693d8817e4Smiod unsigned *string_offset_ptr)
21703d8817e4Smiod {
21713d8817e4Smiod int i;
21723d8817e4Smiod unsigned file_string_table_offset = 0;
21733d8817e4Smiod unsigned next_file_string_table_offset = *string_offset_ptr;
21743d8817e4Smiod bfd_byte *stabp, *stabs_end;
21753d8817e4Smiod
21763d8817e4Smiod stabp = stabs;
21773d8817e4Smiod stabs_end = stabp + stab_size;
21783d8817e4Smiod
21793d8817e4Smiod printf (_("Contents of %s section:\n\n"), stabsect_name);
21803d8817e4Smiod printf ("Symnum n_type n_othr n_desc n_value n_strx String\n");
21813d8817e4Smiod
21823d8817e4Smiod /* Loop through all symbols and print them.
21833d8817e4Smiod
21843d8817e4Smiod We start the index at -1 because there is a dummy symbol on
21853d8817e4Smiod the front of stabs-in-{coff,elf} sections that supplies sizes. */
21863d8817e4Smiod for (i = -1; stabp < stabs_end; stabp += STABSIZE, i++)
21873d8817e4Smiod {
21883d8817e4Smiod const char *name;
21893d8817e4Smiod unsigned long strx;
21903d8817e4Smiod unsigned char type, other;
21913d8817e4Smiod unsigned short desc;
21923d8817e4Smiod bfd_vma value;
21933d8817e4Smiod
21943d8817e4Smiod strx = bfd_h_get_32 (abfd, stabp + STRDXOFF);
21953d8817e4Smiod type = bfd_h_get_8 (abfd, stabp + TYPEOFF);
21963d8817e4Smiod other = bfd_h_get_8 (abfd, stabp + OTHEROFF);
21973d8817e4Smiod desc = bfd_h_get_16 (abfd, stabp + DESCOFF);
21983d8817e4Smiod value = bfd_h_get_32 (abfd, stabp + VALOFF);
21993d8817e4Smiod
22003d8817e4Smiod printf ("\n%-6d ", i);
22013d8817e4Smiod /* Either print the stab name, or, if unnamed, print its number
22023d8817e4Smiod again (makes consistent formatting for tools like awk). */
22033d8817e4Smiod name = bfd_get_stab_name (type);
22043d8817e4Smiod if (name != NULL)
22053d8817e4Smiod printf ("%-6s", name);
22063d8817e4Smiod else if (type == N_UNDF)
22073d8817e4Smiod printf ("HdrSym");
22083d8817e4Smiod else
22093d8817e4Smiod printf ("%-6d", type);
22103d8817e4Smiod printf (" %-6d %-6d ", other, desc);
22113d8817e4Smiod bfd_printf_vma (abfd, value);
22123d8817e4Smiod printf (" %-6lu", strx);
22133d8817e4Smiod
22143d8817e4Smiod /* Symbols with type == 0 (N_UNDF) specify the length of the
22153d8817e4Smiod string table associated with this file. We use that info
22163d8817e4Smiod to know how to relocate the *next* file's string table indices. */
22173d8817e4Smiod if (type == N_UNDF)
22183d8817e4Smiod {
22193d8817e4Smiod file_string_table_offset = next_file_string_table_offset;
22203d8817e4Smiod next_file_string_table_offset += value;
22213d8817e4Smiod }
22223d8817e4Smiod else
22233d8817e4Smiod {
22243d8817e4Smiod /* Using the (possibly updated) string table offset, print the
22253d8817e4Smiod string (if any) associated with this symbol. */
22263d8817e4Smiod if ((strx + file_string_table_offset) < stabstr_size)
22273d8817e4Smiod printf (" %s", &strtab[strx + file_string_table_offset]);
22283d8817e4Smiod else
22293d8817e4Smiod printf (" *");
22303d8817e4Smiod }
22313d8817e4Smiod }
22323d8817e4Smiod printf ("\n\n");
22333d8817e4Smiod *string_offset_ptr = next_file_string_table_offset;
22343d8817e4Smiod }
22353d8817e4Smiod
22363d8817e4Smiod typedef struct
22373d8817e4Smiod {
22383d8817e4Smiod const char * section_name;
22393d8817e4Smiod const char * string_section_name;
22403d8817e4Smiod unsigned string_offset;
22413d8817e4Smiod }
22423d8817e4Smiod stab_section_names;
22433d8817e4Smiod
22443d8817e4Smiod static void
find_stabs_section(bfd * abfd,asection * section,void * names)22453d8817e4Smiod find_stabs_section (bfd *abfd, asection *section, void *names)
22463d8817e4Smiod {
22473d8817e4Smiod int len;
22483d8817e4Smiod stab_section_names * sought = (stab_section_names *) names;
22493d8817e4Smiod
22503d8817e4Smiod /* Check for section names for which stabsect_name is a prefix, to
22513d8817e4Smiod handle .stab.N, etc. */
22523d8817e4Smiod len = strlen (sought->section_name);
22533d8817e4Smiod
22543d8817e4Smiod /* If the prefix matches, and the files section name ends with a
22553d8817e4Smiod nul or a digit, then we match. I.e., we want either an exact
22563d8817e4Smiod match or a section followed by a number. */
22573d8817e4Smiod if (strncmp (sought->section_name, section->name, len) == 0
22583d8817e4Smiod && (section->name[len] == 0
22593d8817e4Smiod || (section->name[len] == '.' && ISDIGIT (section->name[len + 1]))))
22603d8817e4Smiod {
22613d8817e4Smiod if (strtab == NULL)
22623d8817e4Smiod strtab = read_section_stabs (abfd, sought->string_section_name,
22633d8817e4Smiod &stabstr_size);
22643d8817e4Smiod
22653d8817e4Smiod if (strtab)
22663d8817e4Smiod {
22673d8817e4Smiod stabs = (bfd_byte *) read_section_stabs (abfd, section->name,
22683d8817e4Smiod &stab_size);
22693d8817e4Smiod if (stabs)
22703d8817e4Smiod print_section_stabs (abfd, section->name, &sought->string_offset);
22713d8817e4Smiod }
22723d8817e4Smiod }
22733d8817e4Smiod }
22743d8817e4Smiod
22753d8817e4Smiod static void
dump_stabs_section(bfd * abfd,char * stabsect_name,char * strsect_name)22763d8817e4Smiod dump_stabs_section (bfd *abfd, char *stabsect_name, char *strsect_name)
22773d8817e4Smiod {
22783d8817e4Smiod stab_section_names s;
22793d8817e4Smiod
22803d8817e4Smiod s.section_name = stabsect_name;
22813d8817e4Smiod s.string_section_name = strsect_name;
22823d8817e4Smiod s.string_offset = 0;
22833d8817e4Smiod
22843d8817e4Smiod bfd_map_over_sections (abfd, find_stabs_section, & s);
22853d8817e4Smiod
22863d8817e4Smiod free (strtab);
22873d8817e4Smiod strtab = NULL;
22883d8817e4Smiod }
22893d8817e4Smiod
22903d8817e4Smiod /* Dump the any sections containing stabs debugging information. */
22913d8817e4Smiod
22923d8817e4Smiod static void
dump_stabs(bfd * abfd)22933d8817e4Smiod dump_stabs (bfd *abfd)
22943d8817e4Smiod {
22953d8817e4Smiod dump_stabs_section (abfd, ".stab", ".stabstr");
22963d8817e4Smiod dump_stabs_section (abfd, ".stab.excl", ".stab.exclstr");
22973d8817e4Smiod dump_stabs_section (abfd, ".stab.index", ".stab.indexstr");
22983d8817e4Smiod dump_stabs_section (abfd, "$GDB_SYMBOLS$", "$GDB_STRINGS$");
22993d8817e4Smiod }
23003d8817e4Smiod
23013d8817e4Smiod static void
dump_bfd_header(bfd * abfd)23023d8817e4Smiod dump_bfd_header (bfd *abfd)
23033d8817e4Smiod {
23043d8817e4Smiod char *comma = "";
23053d8817e4Smiod
23063d8817e4Smiod printf (_("architecture: %s, "),
23073d8817e4Smiod bfd_printable_arch_mach (bfd_get_arch (abfd),
23083d8817e4Smiod bfd_get_mach (abfd)));
23093d8817e4Smiod printf (_("flags 0x%08x:\n"), abfd->flags);
23103d8817e4Smiod
23113d8817e4Smiod #define PF(x, y) if (abfd->flags & x) {printf("%s%s", comma, y); comma=", ";}
23123d8817e4Smiod PF (HAS_RELOC, "HAS_RELOC");
23133d8817e4Smiod PF (EXEC_P, "EXEC_P");
23143d8817e4Smiod PF (HAS_LINENO, "HAS_LINENO");
23153d8817e4Smiod PF (HAS_DEBUG, "HAS_DEBUG");
23163d8817e4Smiod PF (HAS_SYMS, "HAS_SYMS");
23173d8817e4Smiod PF (HAS_LOCALS, "HAS_LOCALS");
23183d8817e4Smiod PF (DYNAMIC, "DYNAMIC");
23193d8817e4Smiod PF (WP_TEXT, "WP_TEXT");
23203d8817e4Smiod PF (D_PAGED, "D_PAGED");
23213d8817e4Smiod PF (BFD_IS_RELAXABLE, "BFD_IS_RELAXABLE");
23223d8817e4Smiod PF (HAS_LOAD_PAGE, "HAS_LOAD_PAGE");
23233d8817e4Smiod printf (_("\nstart address 0x"));
23243d8817e4Smiod bfd_printf_vma (abfd, abfd->start_address);
23253d8817e4Smiod printf ("\n");
23263d8817e4Smiod }
23273d8817e4Smiod
23283d8817e4Smiod
23293d8817e4Smiod static void
dump_bfd_private_header(bfd * abfd)23303d8817e4Smiod dump_bfd_private_header (bfd *abfd)
23313d8817e4Smiod {
23323d8817e4Smiod bfd_print_private_bfd_data (abfd, stdout);
23333d8817e4Smiod }
23343d8817e4Smiod
23353d8817e4Smiod
23363d8817e4Smiod /* Display a section in hexadecimal format with associated characters.
23373d8817e4Smiod Each line prefixed by the zero padded address. */
23383d8817e4Smiod
23393d8817e4Smiod static void
dump_section(bfd * abfd,asection * section,void * dummy ATTRIBUTE_UNUSED)23403d8817e4Smiod dump_section (bfd *abfd, asection *section, void *dummy ATTRIBUTE_UNUSED)
23413d8817e4Smiod {
23423d8817e4Smiod bfd_byte *data = 0;
23433d8817e4Smiod bfd_size_type datasize;
23443d8817e4Smiod bfd_size_type addr_offset;
23453d8817e4Smiod bfd_size_type start_offset;
23463d8817e4Smiod bfd_size_type stop_offset;
23473d8817e4Smiod unsigned int opb = bfd_octets_per_byte (abfd);
23483d8817e4Smiod /* Bytes per line. */
23493d8817e4Smiod const int onaline = 16;
23503d8817e4Smiod char buf[64];
23513d8817e4Smiod int count;
23523d8817e4Smiod int width;
23533d8817e4Smiod
23543d8817e4Smiod if ((section->flags & SEC_HAS_CONTENTS) == 0)
23553d8817e4Smiod return;
23563d8817e4Smiod
23573d8817e4Smiod if (! process_section_p (section))
23583d8817e4Smiod return;
23593d8817e4Smiod
23603d8817e4Smiod if ((datasize = bfd_section_size (abfd, section)) == 0)
23613d8817e4Smiod return;
23623d8817e4Smiod
23633d8817e4Smiod printf (_("Contents of section %s:\n"), section->name);
23643d8817e4Smiod
23653d8817e4Smiod data = xmalloc (datasize);
23663d8817e4Smiod
23673d8817e4Smiod bfd_get_section_contents (abfd, section, data, 0, datasize);
23683d8817e4Smiod
23693d8817e4Smiod /* Compute the address range to display. */
23703d8817e4Smiod if (start_address == (bfd_vma) -1
23713d8817e4Smiod || start_address < section->vma)
23723d8817e4Smiod start_offset = 0;
23733d8817e4Smiod else
23743d8817e4Smiod start_offset = start_address - section->vma;
23753d8817e4Smiod
23763d8817e4Smiod if (stop_address == (bfd_vma) -1)
23773d8817e4Smiod stop_offset = datasize / opb;
23783d8817e4Smiod else
23793d8817e4Smiod {
23803d8817e4Smiod if (stop_address < section->vma)
23813d8817e4Smiod stop_offset = 0;
23823d8817e4Smiod else
23833d8817e4Smiod stop_offset = stop_address - section->vma;
23843d8817e4Smiod
23853d8817e4Smiod if (stop_offset > datasize / opb)
23863d8817e4Smiod stop_offset = datasize / opb;
23873d8817e4Smiod }
23883d8817e4Smiod
23893d8817e4Smiod width = 4;
23903d8817e4Smiod
23913d8817e4Smiod bfd_sprintf_vma (abfd, buf, start_offset + section->vma);
23923d8817e4Smiod if (strlen (buf) >= sizeof (buf))
23933d8817e4Smiod abort ();
23943d8817e4Smiod
23953d8817e4Smiod count = 0;
23963d8817e4Smiod while (buf[count] == '0' && buf[count+1] != '\0')
23973d8817e4Smiod count++;
23983d8817e4Smiod count = strlen (buf) - count;
23993d8817e4Smiod if (count > width)
24003d8817e4Smiod width = count;
24013d8817e4Smiod
24023d8817e4Smiod bfd_sprintf_vma (abfd, buf, stop_offset + section->vma - 1);
24033d8817e4Smiod if (strlen (buf) >= sizeof (buf))
24043d8817e4Smiod abort ();
24053d8817e4Smiod
24063d8817e4Smiod count = 0;
24073d8817e4Smiod while (buf[count] == '0' && buf[count+1] != '\0')
24083d8817e4Smiod count++;
24093d8817e4Smiod count = strlen (buf) - count;
24103d8817e4Smiod if (count > width)
24113d8817e4Smiod width = count;
24123d8817e4Smiod
24133d8817e4Smiod for (addr_offset = start_offset;
24143d8817e4Smiod addr_offset < stop_offset; addr_offset += onaline / opb)
24153d8817e4Smiod {
24163d8817e4Smiod bfd_size_type j;
24173d8817e4Smiod
24183d8817e4Smiod bfd_sprintf_vma (abfd, buf, (addr_offset + section->vma));
24193d8817e4Smiod count = strlen (buf);
24203d8817e4Smiod if ((size_t) count >= sizeof (buf))
24213d8817e4Smiod abort ();
24223d8817e4Smiod
24233d8817e4Smiod putchar (' ');
24243d8817e4Smiod while (count < width)
24253d8817e4Smiod {
24263d8817e4Smiod putchar ('0');
24273d8817e4Smiod count++;
24283d8817e4Smiod }
24293d8817e4Smiod fputs (buf + count - width, stdout);
24303d8817e4Smiod putchar (' ');
24313d8817e4Smiod
24323d8817e4Smiod for (j = addr_offset * opb;
24333d8817e4Smiod j < addr_offset * opb + onaline; j++)
24343d8817e4Smiod {
24353d8817e4Smiod if (j < stop_offset * opb)
24363d8817e4Smiod printf ("%02x", (unsigned) (data[j]));
24373d8817e4Smiod else
24383d8817e4Smiod printf (" ");
24393d8817e4Smiod if ((j & 3) == 3)
24403d8817e4Smiod printf (" ");
24413d8817e4Smiod }
24423d8817e4Smiod
24433d8817e4Smiod printf (" ");
24443d8817e4Smiod for (j = addr_offset * opb;
24453d8817e4Smiod j < addr_offset * opb + onaline; j++)
24463d8817e4Smiod {
24473d8817e4Smiod if (j >= stop_offset * opb)
24483d8817e4Smiod printf (" ");
24493d8817e4Smiod else
24503d8817e4Smiod printf ("%c", ISPRINT (data[j]) ? data[j] : '.');
24513d8817e4Smiod }
24523d8817e4Smiod putchar ('\n');
24533d8817e4Smiod }
24543d8817e4Smiod free (data);
24553d8817e4Smiod }
24563d8817e4Smiod
24573d8817e4Smiod /* Actually display the various requested regions. */
24583d8817e4Smiod
24593d8817e4Smiod static void
dump_data(bfd * abfd)24603d8817e4Smiod dump_data (bfd *abfd)
24613d8817e4Smiod {
24623d8817e4Smiod bfd_map_over_sections (abfd, dump_section, NULL);
24633d8817e4Smiod }
24643d8817e4Smiod
24653d8817e4Smiod /* Should perhaps share code and display with nm? */
24663d8817e4Smiod
24673d8817e4Smiod static void
dump_symbols(bfd * abfd ATTRIBUTE_UNUSED,bfd_boolean dynamic)24683d8817e4Smiod dump_symbols (bfd *abfd ATTRIBUTE_UNUSED, bfd_boolean dynamic)
24693d8817e4Smiod {
24703d8817e4Smiod asymbol **current;
24713d8817e4Smiod long max;
24723d8817e4Smiod long count;
24733d8817e4Smiod
24743d8817e4Smiod if (dynamic)
24753d8817e4Smiod {
24763d8817e4Smiod current = dynsyms;
24773d8817e4Smiod max = dynsymcount;
24783d8817e4Smiod printf ("DYNAMIC SYMBOL TABLE:\n");
24793d8817e4Smiod }
24803d8817e4Smiod else
24813d8817e4Smiod {
24823d8817e4Smiod current = syms;
24833d8817e4Smiod max = symcount;
24843d8817e4Smiod printf ("SYMBOL TABLE:\n");
24853d8817e4Smiod }
24863d8817e4Smiod
24873d8817e4Smiod if (max == 0)
24883d8817e4Smiod printf (_("no symbols\n"));
24893d8817e4Smiod
24903d8817e4Smiod for (count = 0; count < max; count++)
24913d8817e4Smiod {
24923d8817e4Smiod bfd *cur_bfd;
24933d8817e4Smiod
24943d8817e4Smiod if (*current == NULL)
24953d8817e4Smiod printf (_("no information for symbol number %ld\n"), count);
24963d8817e4Smiod
24973d8817e4Smiod else if ((cur_bfd = bfd_asymbol_bfd (*current)) == NULL)
24983d8817e4Smiod printf (_("could not determine the type of symbol number %ld\n"),
24993d8817e4Smiod count);
25003d8817e4Smiod
25013d8817e4Smiod else if (process_section_p ((* current)->section)
25023d8817e4Smiod && (dump_special_syms
25033d8817e4Smiod || !bfd_is_target_special_symbol (cur_bfd, *current)))
25043d8817e4Smiod {
25053d8817e4Smiod const char *name = (*current)->name;
25063d8817e4Smiod
25073d8817e4Smiod if (do_demangle && name != NULL && *name != '\0')
25083d8817e4Smiod {
25093d8817e4Smiod char *alloc;
25103d8817e4Smiod
25113d8817e4Smiod /* If we want to demangle the name, we demangle it
25123d8817e4Smiod here, and temporarily clobber it while calling
25133d8817e4Smiod bfd_print_symbol. FIXME: This is a gross hack. */
25143d8817e4Smiod alloc = demangle (cur_bfd, name);
25153d8817e4Smiod (*current)->name = alloc;
25163d8817e4Smiod bfd_print_symbol (cur_bfd, stdout, *current,
25173d8817e4Smiod bfd_print_symbol_all);
25183d8817e4Smiod (*current)->name = name;
25193d8817e4Smiod free (alloc);
25203d8817e4Smiod }
25213d8817e4Smiod else
25223d8817e4Smiod bfd_print_symbol (cur_bfd, stdout, *current,
25233d8817e4Smiod bfd_print_symbol_all);
25243d8817e4Smiod printf ("\n");
25253d8817e4Smiod }
25263d8817e4Smiod
25273d8817e4Smiod current++;
25283d8817e4Smiod }
25293d8817e4Smiod printf ("\n\n");
25303d8817e4Smiod }
25313d8817e4Smiod
25323d8817e4Smiod static void
dump_reloc_set(bfd * abfd,asection * sec,arelent ** relpp,long relcount)25333d8817e4Smiod dump_reloc_set (bfd *abfd, asection *sec, arelent **relpp, long relcount)
25343d8817e4Smiod {
25353d8817e4Smiod arelent **p;
25363d8817e4Smiod char *last_filename, *last_functionname;
25373d8817e4Smiod unsigned int last_line;
25383d8817e4Smiod
25393d8817e4Smiod /* Get column headers lined up reasonably. */
25403d8817e4Smiod {
25413d8817e4Smiod static int width;
25423d8817e4Smiod
25433d8817e4Smiod if (width == 0)
25443d8817e4Smiod {
25453d8817e4Smiod char buf[30];
25463d8817e4Smiod
25473d8817e4Smiod bfd_sprintf_vma (abfd, buf, (bfd_vma) -1);
25483d8817e4Smiod width = strlen (buf) - 7;
25493d8817e4Smiod }
25503d8817e4Smiod printf ("OFFSET %*s TYPE %*s VALUE \n", width, "", 12, "");
25513d8817e4Smiod }
25523d8817e4Smiod
25533d8817e4Smiod last_filename = NULL;
25543d8817e4Smiod last_functionname = NULL;
25553d8817e4Smiod last_line = 0;
25563d8817e4Smiod
25573d8817e4Smiod for (p = relpp; relcount && *p != NULL; p++, relcount--)
25583d8817e4Smiod {
25593d8817e4Smiod arelent *q = *p;
25603d8817e4Smiod const char *filename, *functionname;
25613d8817e4Smiod unsigned int line;
25623d8817e4Smiod const char *sym_name;
25633d8817e4Smiod const char *section_name;
25643d8817e4Smiod
25653d8817e4Smiod if (start_address != (bfd_vma) -1
25663d8817e4Smiod && q->address < start_address)
25673d8817e4Smiod continue;
25683d8817e4Smiod if (stop_address != (bfd_vma) -1
25693d8817e4Smiod && q->address > stop_address)
25703d8817e4Smiod continue;
25713d8817e4Smiod
25723d8817e4Smiod if (with_line_numbers
25733d8817e4Smiod && sec != NULL
25743d8817e4Smiod && bfd_find_nearest_line (abfd, sec, syms, q->address,
25753d8817e4Smiod &filename, &functionname, &line))
25763d8817e4Smiod {
25773d8817e4Smiod if (functionname != NULL
25783d8817e4Smiod && (last_functionname == NULL
25793d8817e4Smiod || strcmp (functionname, last_functionname) != 0))
25803d8817e4Smiod {
25813d8817e4Smiod printf ("%s():\n", functionname);
25823d8817e4Smiod if (last_functionname != NULL)
25833d8817e4Smiod free (last_functionname);
25843d8817e4Smiod last_functionname = xstrdup (functionname);
25853d8817e4Smiod }
25863d8817e4Smiod
25873d8817e4Smiod if (line > 0
25883d8817e4Smiod && (line != last_line
25893d8817e4Smiod || (filename != NULL
25903d8817e4Smiod && last_filename != NULL
25913d8817e4Smiod && strcmp (filename, last_filename) != 0)))
25923d8817e4Smiod {
25933d8817e4Smiod printf ("%s:%u\n", filename == NULL ? "???" : filename, line);
25943d8817e4Smiod last_line = line;
25953d8817e4Smiod if (last_filename != NULL)
25963d8817e4Smiod free (last_filename);
25973d8817e4Smiod if (filename == NULL)
25983d8817e4Smiod last_filename = NULL;
25993d8817e4Smiod else
26003d8817e4Smiod last_filename = xstrdup (filename);
26013d8817e4Smiod }
26023d8817e4Smiod }
26033d8817e4Smiod
26043d8817e4Smiod if (q->sym_ptr_ptr && *q->sym_ptr_ptr)
26053d8817e4Smiod {
26063d8817e4Smiod sym_name = (*(q->sym_ptr_ptr))->name;
26073d8817e4Smiod section_name = (*(q->sym_ptr_ptr))->section->name;
26083d8817e4Smiod }
26093d8817e4Smiod else
26103d8817e4Smiod {
26113d8817e4Smiod sym_name = NULL;
26123d8817e4Smiod section_name = NULL;
26133d8817e4Smiod }
26143d8817e4Smiod
26153d8817e4Smiod bfd_printf_vma (abfd, q->address);
26163d8817e4Smiod if (q->howto == NULL)
26173d8817e4Smiod printf (" *unknown* ");
26183d8817e4Smiod else if (q->howto->name)
26193d8817e4Smiod printf (" %-16s ", q->howto->name);
26203d8817e4Smiod else
26213d8817e4Smiod printf (" %-16d ", q->howto->type);
26223d8817e4Smiod if (sym_name)
26233d8817e4Smiod objdump_print_symname (abfd, NULL, *q->sym_ptr_ptr);
26243d8817e4Smiod else
26253d8817e4Smiod {
26263d8817e4Smiod if (section_name == NULL)
26273d8817e4Smiod section_name = "*unknown*";
26283d8817e4Smiod printf ("[%s]", section_name);
26293d8817e4Smiod }
26303d8817e4Smiod
26313d8817e4Smiod if (q->addend)
26323d8817e4Smiod {
26333d8817e4Smiod printf ("+0x");
26343d8817e4Smiod bfd_printf_vma (abfd, q->addend);
26353d8817e4Smiod }
26363d8817e4Smiod
26373d8817e4Smiod printf ("\n");
26383d8817e4Smiod }
26393d8817e4Smiod }
26403d8817e4Smiod
26413d8817e4Smiod static void
dump_relocs_in_section(bfd * abfd,asection * section,void * dummy ATTRIBUTE_UNUSED)26423d8817e4Smiod dump_relocs_in_section (bfd *abfd,
26433d8817e4Smiod asection *section,
26443d8817e4Smiod void *dummy ATTRIBUTE_UNUSED)
26453d8817e4Smiod {
26463d8817e4Smiod arelent **relpp;
26473d8817e4Smiod long relcount;
26483d8817e4Smiod long relsize;
26493d8817e4Smiod
26503d8817e4Smiod if ( bfd_is_abs_section (section)
26513d8817e4Smiod || bfd_is_und_section (section)
26523d8817e4Smiod || bfd_is_com_section (section)
26533d8817e4Smiod || (! process_section_p (section))
26543d8817e4Smiod || ((section->flags & SEC_RELOC) == 0))
26553d8817e4Smiod return;
26563d8817e4Smiod
26573d8817e4Smiod relsize = bfd_get_reloc_upper_bound (abfd, section);
26583d8817e4Smiod if (relsize < 0)
26593d8817e4Smiod bfd_fatal (bfd_get_filename (abfd));
26603d8817e4Smiod
26613d8817e4Smiod printf ("RELOCATION RECORDS FOR [%s]:", section->name);
26623d8817e4Smiod
26633d8817e4Smiod if (relsize == 0)
26643d8817e4Smiod {
26653d8817e4Smiod printf (" (none)\n\n");
26663d8817e4Smiod return;
26673d8817e4Smiod }
26683d8817e4Smiod
26693d8817e4Smiod relpp = xmalloc (relsize);
26703d8817e4Smiod relcount = bfd_canonicalize_reloc (abfd, section, relpp, syms);
26713d8817e4Smiod
26723d8817e4Smiod if (relcount < 0)
26733d8817e4Smiod bfd_fatal (bfd_get_filename (abfd));
26743d8817e4Smiod else if (relcount == 0)
26753d8817e4Smiod printf (" (none)\n\n");
26763d8817e4Smiod else
26773d8817e4Smiod {
26783d8817e4Smiod printf ("\n");
26793d8817e4Smiod dump_reloc_set (abfd, section, relpp, relcount);
26803d8817e4Smiod printf ("\n\n");
26813d8817e4Smiod }
26823d8817e4Smiod free (relpp);
26833d8817e4Smiod }
26843d8817e4Smiod
26853d8817e4Smiod static void
dump_relocs(bfd * abfd)26863d8817e4Smiod dump_relocs (bfd *abfd)
26873d8817e4Smiod {
26883d8817e4Smiod bfd_map_over_sections (abfd, dump_relocs_in_section, NULL);
26893d8817e4Smiod }
26903d8817e4Smiod
26913d8817e4Smiod static void
dump_dynamic_relocs(bfd * abfd)26923d8817e4Smiod dump_dynamic_relocs (bfd *abfd)
26933d8817e4Smiod {
26943d8817e4Smiod long relsize;
26953d8817e4Smiod arelent **relpp;
26963d8817e4Smiod long relcount;
26973d8817e4Smiod
26983d8817e4Smiod relsize = bfd_get_dynamic_reloc_upper_bound (abfd);
26993d8817e4Smiod if (relsize < 0)
27003d8817e4Smiod bfd_fatal (bfd_get_filename (abfd));
27013d8817e4Smiod
27023d8817e4Smiod printf ("DYNAMIC RELOCATION RECORDS");
27033d8817e4Smiod
27043d8817e4Smiod if (relsize == 0)
27053d8817e4Smiod printf (" (none)\n\n");
27063d8817e4Smiod else
27073d8817e4Smiod {
27083d8817e4Smiod relpp = xmalloc (relsize);
27093d8817e4Smiod relcount = bfd_canonicalize_dynamic_reloc (abfd, relpp, dynsyms);
27103d8817e4Smiod
27113d8817e4Smiod if (relcount < 0)
27123d8817e4Smiod bfd_fatal (bfd_get_filename (abfd));
27133d8817e4Smiod else if (relcount == 0)
27143d8817e4Smiod printf (" (none)\n\n");
27153d8817e4Smiod else
27163d8817e4Smiod {
27173d8817e4Smiod printf ("\n");
27183d8817e4Smiod dump_reloc_set (abfd, NULL, relpp, relcount);
27193d8817e4Smiod printf ("\n\n");
27203d8817e4Smiod }
27213d8817e4Smiod free (relpp);
27223d8817e4Smiod }
27233d8817e4Smiod }
27243d8817e4Smiod
27253d8817e4Smiod /* Creates a table of paths, to search for source files. */
27263d8817e4Smiod
27273d8817e4Smiod static void
add_include_path(const char * path)27283d8817e4Smiod add_include_path (const char *path)
27293d8817e4Smiod {
27303d8817e4Smiod if (path[0] == 0)
27313d8817e4Smiod return;
27323d8817e4Smiod include_path_count++;
27333d8817e4Smiod include_paths = xrealloc (include_paths,
27343d8817e4Smiod include_path_count * sizeof (*include_paths));
27353d8817e4Smiod #ifdef HAVE_DOS_BASED_FILE_SYSTEM
27363d8817e4Smiod if (path[1] == ':' && path[2] == 0)
27373d8817e4Smiod path = concat (path, ".", (const char *) 0);
27383d8817e4Smiod #endif
27393d8817e4Smiod include_paths[include_path_count - 1] = path;
27403d8817e4Smiod }
27413d8817e4Smiod
27423d8817e4Smiod static void
adjust_addresses(bfd * abfd ATTRIBUTE_UNUSED,asection * section,void * arg)27433d8817e4Smiod adjust_addresses (bfd *abfd ATTRIBUTE_UNUSED,
27443d8817e4Smiod asection *section,
27453d8817e4Smiod void *arg)
27463d8817e4Smiod {
27473d8817e4Smiod if ((section->flags & SEC_DEBUGGING) == 0)
27483d8817e4Smiod {
27493d8817e4Smiod bfd_boolean *has_reloc_p = (bfd_boolean *) arg;
27503d8817e4Smiod section->vma += adjust_section_vma;
27513d8817e4Smiod if (*has_reloc_p)
27523d8817e4Smiod section->lma += adjust_section_vma;
27533d8817e4Smiod }
27543d8817e4Smiod }
27553d8817e4Smiod
27563d8817e4Smiod /* Dump selected contents of ABFD. */
27573d8817e4Smiod
27583d8817e4Smiod static void
dump_bfd(bfd * abfd)27593d8817e4Smiod dump_bfd (bfd *abfd)
27603d8817e4Smiod {
27613d8817e4Smiod /* If we are adjusting section VMA's, change them all now. Changing
27623d8817e4Smiod the BFD information is a hack. However, we must do it, or
27633d8817e4Smiod bfd_find_nearest_line will not do the right thing. */
27643d8817e4Smiod if (adjust_section_vma != 0)
27653d8817e4Smiod {
27663d8817e4Smiod bfd_boolean has_reloc = (abfd->flags & HAS_RELOC);
27673d8817e4Smiod bfd_map_over_sections (abfd, adjust_addresses, &has_reloc);
27683d8817e4Smiod }
27693d8817e4Smiod
27703d8817e4Smiod if (! dump_debugging_tags)
27713d8817e4Smiod printf (_("\n%s: file format %s\n"), bfd_get_filename (abfd),
27723d8817e4Smiod abfd->xvec->name);
27733d8817e4Smiod if (dump_ar_hdrs)
27743d8817e4Smiod print_arelt_descr (stdout, abfd, TRUE);
27753d8817e4Smiod if (dump_file_header)
27763d8817e4Smiod dump_bfd_header (abfd);
27773d8817e4Smiod if (dump_private_headers)
27783d8817e4Smiod dump_bfd_private_header (abfd);
27793d8817e4Smiod if (! dump_debugging_tags)
27803d8817e4Smiod putchar ('\n');
27813d8817e4Smiod if (dump_section_headers)
27823d8817e4Smiod dump_headers (abfd);
27833d8817e4Smiod
27843d8817e4Smiod if (dump_symtab
27853d8817e4Smiod || dump_reloc_info
27863d8817e4Smiod || disassemble
27873d8817e4Smiod || dump_debugging
27883d8817e4Smiod || dump_dwarf_section_info)
27893d8817e4Smiod syms = slurp_symtab (abfd);
27903d8817e4Smiod if (dump_dynamic_symtab || dump_dynamic_reloc_info
27913d8817e4Smiod || (disassemble && bfd_get_dynamic_symtab_upper_bound (abfd) > 0))
27923d8817e4Smiod dynsyms = slurp_dynamic_symtab (abfd);
27933d8817e4Smiod if (disassemble)
27943d8817e4Smiod {
27953d8817e4Smiod synthcount = bfd_get_synthetic_symtab (abfd, symcount, syms,
27963d8817e4Smiod dynsymcount, dynsyms, &synthsyms);
27973d8817e4Smiod if (synthcount < 0)
27983d8817e4Smiod synthcount = 0;
27993d8817e4Smiod }
28003d8817e4Smiod
28013d8817e4Smiod if (dump_symtab)
28023d8817e4Smiod dump_symbols (abfd, FALSE);
28033d8817e4Smiod if (dump_dynamic_symtab)
28043d8817e4Smiod dump_symbols (abfd, TRUE);
28053d8817e4Smiod if (dump_dwarf_section_info)
28063d8817e4Smiod dump_dwarf (abfd);
28073d8817e4Smiod if (dump_stab_section_info)
28083d8817e4Smiod dump_stabs (abfd);
28093d8817e4Smiod if (dump_reloc_info && ! disassemble)
28103d8817e4Smiod dump_relocs (abfd);
28113d8817e4Smiod if (dump_dynamic_reloc_info && ! disassemble)
28123d8817e4Smiod dump_dynamic_relocs (abfd);
28133d8817e4Smiod if (dump_section_contents)
28143d8817e4Smiod dump_data (abfd);
28153d8817e4Smiod if (disassemble)
28163d8817e4Smiod disassemble_data (abfd);
28173d8817e4Smiod
28183d8817e4Smiod if (dump_debugging)
28193d8817e4Smiod {
28203d8817e4Smiod void *dhandle;
28213d8817e4Smiod
28223d8817e4Smiod dhandle = read_debugging_info (abfd, syms, symcount);
28233d8817e4Smiod if (dhandle != NULL)
28243d8817e4Smiod {
28253d8817e4Smiod if (! print_debugging_info (stdout, dhandle, abfd, syms, demangle,
28263d8817e4Smiod dump_debugging_tags ? TRUE : FALSE))
28273d8817e4Smiod {
28283d8817e4Smiod non_fatal (_("%s: printing debugging information failed"),
28293d8817e4Smiod bfd_get_filename (abfd));
28303d8817e4Smiod exit_status = 1;
28313d8817e4Smiod }
28323d8817e4Smiod }
28333d8817e4Smiod }
28343d8817e4Smiod
28353d8817e4Smiod if (syms)
28363d8817e4Smiod {
28373d8817e4Smiod free (syms);
28383d8817e4Smiod syms = NULL;
28393d8817e4Smiod }
28403d8817e4Smiod
28413d8817e4Smiod if (dynsyms)
28423d8817e4Smiod {
28433d8817e4Smiod free (dynsyms);
28443d8817e4Smiod dynsyms = NULL;
28453d8817e4Smiod }
28463d8817e4Smiod
28473d8817e4Smiod if (synthsyms)
28483d8817e4Smiod {
28493d8817e4Smiod free (synthsyms);
28503d8817e4Smiod synthsyms = NULL;
28513d8817e4Smiod }
28523d8817e4Smiod
28533d8817e4Smiod symcount = 0;
28543d8817e4Smiod dynsymcount = 0;
28553d8817e4Smiod synthcount = 0;
28563d8817e4Smiod }
28573d8817e4Smiod
28583d8817e4Smiod static void
display_bfd(bfd * abfd)28593d8817e4Smiod display_bfd (bfd *abfd)
28603d8817e4Smiod {
28613d8817e4Smiod char **matching;
28623d8817e4Smiod
28633d8817e4Smiod if (bfd_check_format_matches (abfd, bfd_object, &matching))
28643d8817e4Smiod {
28653d8817e4Smiod dump_bfd (abfd);
28663d8817e4Smiod return;
28673d8817e4Smiod }
28683d8817e4Smiod
28693d8817e4Smiod if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
28703d8817e4Smiod {
28713d8817e4Smiod nonfatal (bfd_get_filename (abfd));
28723d8817e4Smiod list_matching_formats (matching);
28733d8817e4Smiod free (matching);
28743d8817e4Smiod return;
28753d8817e4Smiod }
28763d8817e4Smiod
28773d8817e4Smiod if (bfd_get_error () != bfd_error_file_not_recognized)
28783d8817e4Smiod {
28793d8817e4Smiod nonfatal (bfd_get_filename (abfd));
28803d8817e4Smiod return;
28813d8817e4Smiod }
28823d8817e4Smiod
28833d8817e4Smiod if (bfd_check_format_matches (abfd, bfd_core, &matching))
28843d8817e4Smiod {
28853d8817e4Smiod dump_bfd (abfd);
28863d8817e4Smiod return;
28873d8817e4Smiod }
28883d8817e4Smiod
28893d8817e4Smiod nonfatal (bfd_get_filename (abfd));
28903d8817e4Smiod
28913d8817e4Smiod if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
28923d8817e4Smiod {
28933d8817e4Smiod list_matching_formats (matching);
28943d8817e4Smiod free (matching);
28953d8817e4Smiod }
28963d8817e4Smiod }
28973d8817e4Smiod
28983d8817e4Smiod static void
display_file(char * filename,char * target)28993d8817e4Smiod display_file (char *filename, char *target)
29003d8817e4Smiod {
29013d8817e4Smiod bfd *file;
29023d8817e4Smiod bfd *arfile = NULL;
29033d8817e4Smiod
29043d8817e4Smiod if (get_file_size (filename) < 1)
29053d8817e4Smiod return;
29063d8817e4Smiod
29073d8817e4Smiod file = bfd_openr (filename, target);
29083d8817e4Smiod if (file == NULL)
29093d8817e4Smiod {
29103d8817e4Smiod nonfatal (filename);
29113d8817e4Smiod return;
29123d8817e4Smiod }
29133d8817e4Smiod
29143d8817e4Smiod /* If the file is an archive, process all of its elements. */
29153d8817e4Smiod if (bfd_check_format (file, bfd_archive))
29163d8817e4Smiod {
29173d8817e4Smiod bfd *last_arfile = NULL;
29183d8817e4Smiod
29193d8817e4Smiod printf (_("In archive %s:\n"), bfd_get_filename (file));
29203d8817e4Smiod for (;;)
29213d8817e4Smiod {
29223d8817e4Smiod bfd_set_error (bfd_error_no_error);
29233d8817e4Smiod
29243d8817e4Smiod arfile = bfd_openr_next_archived_file (file, arfile);
29253d8817e4Smiod if (arfile == NULL)
29263d8817e4Smiod {
29273d8817e4Smiod if (bfd_get_error () != bfd_error_no_more_archived_files)
29283d8817e4Smiod nonfatal (bfd_get_filename (file));
29293d8817e4Smiod break;
29303d8817e4Smiod }
29313d8817e4Smiod
29323d8817e4Smiod display_bfd (arfile);
29333d8817e4Smiod
29343d8817e4Smiod if (last_arfile != NULL)
29353d8817e4Smiod bfd_close (last_arfile);
29363d8817e4Smiod last_arfile = arfile;
29373d8817e4Smiod }
29383d8817e4Smiod
29393d8817e4Smiod if (last_arfile != NULL)
29403d8817e4Smiod bfd_close (last_arfile);
29413d8817e4Smiod }
29423d8817e4Smiod else
29433d8817e4Smiod display_bfd (file);
29443d8817e4Smiod
29453d8817e4Smiod bfd_close (file);
29463d8817e4Smiod }
29473d8817e4Smiod
29483d8817e4Smiod int
main(int argc,char ** argv)29493d8817e4Smiod main (int argc, char **argv)
29503d8817e4Smiod {
29513d8817e4Smiod int c;
29523d8817e4Smiod char *target = default_target;
29533d8817e4Smiod bfd_boolean seenflag = FALSE;
29543d8817e4Smiod
29553d8817e4Smiod #if defined (HAVE_SETLOCALE)
29563d8817e4Smiod #if defined (HAVE_LC_MESSAGES)
29573d8817e4Smiod setlocale (LC_MESSAGES, "");
29583d8817e4Smiod #endif
29593d8817e4Smiod setlocale (LC_CTYPE, "");
29603d8817e4Smiod #endif
29613d8817e4Smiod
29623d8817e4Smiod bindtextdomain (PACKAGE, LOCALEDIR);
29633d8817e4Smiod textdomain (PACKAGE);
29643d8817e4Smiod
2965*c1f838d9Spascal if (pledge ("stdio rpath tmppath", NULL) == -1)
2966*c1f838d9Spascal fatal (_("Failed to pledge"));
2967*c1f838d9Spascal
29683d8817e4Smiod program_name = *argv;
29693d8817e4Smiod xmalloc_set_program_name (program_name);
29703d8817e4Smiod
29713d8817e4Smiod START_PROGRESS (program_name, 0);
29723d8817e4Smiod
29733d8817e4Smiod expandargv (&argc, &argv);
29743d8817e4Smiod
29753d8817e4Smiod bfd_init ();
29763d8817e4Smiod set_default_bfd_target ();
29773d8817e4Smiod
29783d8817e4Smiod while ((c = getopt_long (argc, argv, "pib:m:M:VvCdDlfaHhrRtTxsSI:j:wE:zgeGW",
29793d8817e4Smiod long_options, (int *) 0))
29803d8817e4Smiod != EOF)
29813d8817e4Smiod {
29823d8817e4Smiod switch (c)
29833d8817e4Smiod {
29843d8817e4Smiod case 0:
29853d8817e4Smiod break; /* We've been given a long option. */
29863d8817e4Smiod case 'm':
29873d8817e4Smiod machine = optarg;
29883d8817e4Smiod break;
29893d8817e4Smiod case 'M':
29903d8817e4Smiod if (disassembler_options)
29913d8817e4Smiod /* Ignore potential memory leak for now. */
29923d8817e4Smiod disassembler_options = concat (disassembler_options, ",",
29933d8817e4Smiod optarg, NULL);
29943d8817e4Smiod else
29953d8817e4Smiod disassembler_options = optarg;
29963d8817e4Smiod break;
29973d8817e4Smiod case 'j':
29983d8817e4Smiod if (only_used == only_size)
29993d8817e4Smiod {
30003d8817e4Smiod only_size += 8;
30013d8817e4Smiod only = xrealloc (only, only_size * sizeof (char *));
30023d8817e4Smiod }
30033d8817e4Smiod only [only_used++] = optarg;
30043d8817e4Smiod break;
30053d8817e4Smiod case 'l':
30063d8817e4Smiod with_line_numbers = TRUE;
30073d8817e4Smiod break;
30083d8817e4Smiod case 'b':
30093d8817e4Smiod target = optarg;
30103d8817e4Smiod break;
30113d8817e4Smiod case 'C':
30123d8817e4Smiod do_demangle = TRUE;
30133d8817e4Smiod if (optarg != NULL)
30143d8817e4Smiod {
30153d8817e4Smiod enum demangling_styles style;
30163d8817e4Smiod
30173d8817e4Smiod style = cplus_demangle_name_to_style (optarg);
30183d8817e4Smiod if (style == unknown_demangling)
30193d8817e4Smiod fatal (_("unknown demangling style `%s'"),
30203d8817e4Smiod optarg);
30213d8817e4Smiod
30223d8817e4Smiod cplus_demangle_set_style (style);
30233d8817e4Smiod }
30243d8817e4Smiod break;
30253d8817e4Smiod case 'w':
30263d8817e4Smiod wide_output = TRUE;
30273d8817e4Smiod break;
30283d8817e4Smiod case OPTION_ADJUST_VMA:
30293d8817e4Smiod adjust_section_vma = parse_vma (optarg, "--adjust-vma");
30303d8817e4Smiod break;
30313d8817e4Smiod case OPTION_START_ADDRESS:
30323d8817e4Smiod start_address = parse_vma (optarg, "--start-address");
30333d8817e4Smiod break;
30343d8817e4Smiod case OPTION_STOP_ADDRESS:
30353d8817e4Smiod stop_address = parse_vma (optarg, "--stop-address");
30363d8817e4Smiod break;
30373d8817e4Smiod case 'E':
30383d8817e4Smiod if (strcmp (optarg, "B") == 0)
30393d8817e4Smiod endian = BFD_ENDIAN_BIG;
30403d8817e4Smiod else if (strcmp (optarg, "L") == 0)
30413d8817e4Smiod endian = BFD_ENDIAN_LITTLE;
30423d8817e4Smiod else
30433d8817e4Smiod {
30443d8817e4Smiod non_fatal (_("unrecognized -E option"));
30453d8817e4Smiod usage (stderr, 1);
30463d8817e4Smiod }
30473d8817e4Smiod break;
30483d8817e4Smiod case OPTION_ENDIAN:
30493d8817e4Smiod if (strncmp (optarg, "big", strlen (optarg)) == 0)
30503d8817e4Smiod endian = BFD_ENDIAN_BIG;
30513d8817e4Smiod else if (strncmp (optarg, "little", strlen (optarg)) == 0)
30523d8817e4Smiod endian = BFD_ENDIAN_LITTLE;
30533d8817e4Smiod else
30543d8817e4Smiod {
30553d8817e4Smiod non_fatal (_("unrecognized --endian type `%s'"), optarg);
30563d8817e4Smiod usage (stderr, 1);
30573d8817e4Smiod }
30583d8817e4Smiod break;
30593d8817e4Smiod
30603d8817e4Smiod case 'f':
30613d8817e4Smiod dump_file_header = TRUE;
30623d8817e4Smiod seenflag = TRUE;
30633d8817e4Smiod break;
30643d8817e4Smiod case 'i':
30653d8817e4Smiod formats_info = TRUE;
30663d8817e4Smiod seenflag = TRUE;
30673d8817e4Smiod break;
30683d8817e4Smiod case 'I':
30693d8817e4Smiod add_include_path (optarg);
30703d8817e4Smiod break;
30713d8817e4Smiod case 'p':
30723d8817e4Smiod dump_private_headers = TRUE;
30733d8817e4Smiod seenflag = TRUE;
30743d8817e4Smiod break;
30753d8817e4Smiod case 'x':
30763d8817e4Smiod dump_private_headers = TRUE;
30773d8817e4Smiod dump_symtab = TRUE;
30783d8817e4Smiod dump_reloc_info = TRUE;
30793d8817e4Smiod dump_file_header = TRUE;
30803d8817e4Smiod dump_ar_hdrs = TRUE;
30813d8817e4Smiod dump_section_headers = TRUE;
30823d8817e4Smiod seenflag = TRUE;
30833d8817e4Smiod break;
30843d8817e4Smiod case 't':
30853d8817e4Smiod dump_symtab = TRUE;
30863d8817e4Smiod seenflag = TRUE;
30873d8817e4Smiod break;
30883d8817e4Smiod case 'T':
30893d8817e4Smiod dump_dynamic_symtab = TRUE;
30903d8817e4Smiod seenflag = TRUE;
30913d8817e4Smiod break;
30923d8817e4Smiod case 'd':
30933d8817e4Smiod disassemble = TRUE;
30943d8817e4Smiod seenflag = TRUE;
30953d8817e4Smiod break;
30963d8817e4Smiod case 'z':
30973d8817e4Smiod disassemble_zeroes = TRUE;
30983d8817e4Smiod break;
30993d8817e4Smiod case 'D':
31003d8817e4Smiod disassemble = TRUE;
31013d8817e4Smiod disassemble_all = TRUE;
31023d8817e4Smiod seenflag = TRUE;
31033d8817e4Smiod break;
31043d8817e4Smiod case 'S':
31053d8817e4Smiod disassemble = TRUE;
31063d8817e4Smiod with_source_code = TRUE;
31073d8817e4Smiod seenflag = TRUE;
31083d8817e4Smiod break;
31093d8817e4Smiod case 'g':
31103d8817e4Smiod dump_debugging = 1;
31113d8817e4Smiod seenflag = TRUE;
31123d8817e4Smiod break;
31133d8817e4Smiod case 'e':
31143d8817e4Smiod dump_debugging = 1;
31153d8817e4Smiod dump_debugging_tags = 1;
31163d8817e4Smiod do_demangle = TRUE;
31173d8817e4Smiod seenflag = TRUE;
31183d8817e4Smiod break;
31193d8817e4Smiod case 'W':
31203d8817e4Smiod dump_dwarf_section_info = TRUE;
31213d8817e4Smiod seenflag = TRUE;
31223d8817e4Smiod do_debug_info = 1;
31233d8817e4Smiod do_debug_abbrevs = 1;
31243d8817e4Smiod do_debug_lines = 1;
31253d8817e4Smiod do_debug_pubnames = 1;
31263d8817e4Smiod do_debug_aranges = 1;
31273d8817e4Smiod do_debug_ranges = 1;
31283d8817e4Smiod do_debug_frames = 1;
31293d8817e4Smiod do_debug_macinfo = 1;
31303d8817e4Smiod do_debug_str = 1;
31313d8817e4Smiod do_debug_loc = 1;
31323d8817e4Smiod break;
31333d8817e4Smiod case 'G':
31343d8817e4Smiod dump_stab_section_info = TRUE;
31353d8817e4Smiod seenflag = TRUE;
31363d8817e4Smiod break;
31373d8817e4Smiod case 's':
31383d8817e4Smiod dump_section_contents = TRUE;
31393d8817e4Smiod seenflag = TRUE;
31403d8817e4Smiod break;
31413d8817e4Smiod case 'r':
31423d8817e4Smiod dump_reloc_info = TRUE;
31433d8817e4Smiod seenflag = TRUE;
31443d8817e4Smiod break;
31453d8817e4Smiod case 'R':
31463d8817e4Smiod dump_dynamic_reloc_info = TRUE;
31473d8817e4Smiod seenflag = TRUE;
31483d8817e4Smiod break;
31493d8817e4Smiod case 'a':
31503d8817e4Smiod dump_ar_hdrs = TRUE;
31513d8817e4Smiod seenflag = TRUE;
31523d8817e4Smiod break;
31533d8817e4Smiod case 'h':
31543d8817e4Smiod dump_section_headers = TRUE;
31553d8817e4Smiod seenflag = TRUE;
31563d8817e4Smiod break;
31573d8817e4Smiod case 'H':
31583d8817e4Smiod usage (stdout, 0);
31593d8817e4Smiod seenflag = TRUE;
31603d8817e4Smiod case 'v':
31613d8817e4Smiod case 'V':
31623d8817e4Smiod show_version = TRUE;
31633d8817e4Smiod seenflag = TRUE;
31643d8817e4Smiod break;
31653d8817e4Smiod
31663d8817e4Smiod default:
31673d8817e4Smiod usage (stderr, 1);
31683d8817e4Smiod }
31693d8817e4Smiod }
31703d8817e4Smiod
31713d8817e4Smiod if (show_version)
31723d8817e4Smiod print_version ("objdump");
31733d8817e4Smiod
31743d8817e4Smiod if (!seenflag)
31753d8817e4Smiod usage (stderr, 2);
31763d8817e4Smiod
31773d8817e4Smiod if (formats_info)
31783d8817e4Smiod exit_status = display_info ();
31793d8817e4Smiod else
31803d8817e4Smiod {
31813d8817e4Smiod if (optind == argc)
31823d8817e4Smiod display_file ("a.out", target);
31833d8817e4Smiod else
31843d8817e4Smiod for (; optind < argc;)
31853d8817e4Smiod display_file (argv[optind++], target);
31863d8817e4Smiod }
31873d8817e4Smiod
31883d8817e4Smiod END_PROGRESS (program_name);
31893d8817e4Smiod
31903d8817e4Smiod return exit_status;
31913d8817e4Smiod }
3192