objdump.c revision 130561
133965Sjdp/* objdump.c -- dump information about an object file. 278828Sobrien Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 3130561Sobrien 2000, 2001, 2002, 2003 438889Sjdp Free Software Foundation, Inc. 533965Sjdp 6130561Sobrien This file is part of GNU Binutils. 733965Sjdp 8130561Sobrien This program is free software; you can redistribute it and/or modify 9130561Sobrien it under the terms of the GNU General Public License as published by 10130561Sobrien the Free Software Foundation; either version 2, or (at your option) 11130561Sobrien any later version. 1233965Sjdp 13130561Sobrien This program is distributed in the hope that it will be useful, 14130561Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 15130561Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16130561Sobrien GNU General Public License for more details. 1733965Sjdp 18130561Sobrien You should have received a copy of the GNU General Public License 19130561Sobrien along with this program; if not, write to the Free Software 20130561Sobrien Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 2133965Sjdp 22130561Sobrien/* Objdump overview. 23130561Sobrien 24130561Sobrien Objdump displays information about one or more object files, either on 25130561Sobrien their own, or inside libraries. It is commonly used as a disassembler, 26130561Sobrien but it can also display information about file headers, symbol tables, 27130561Sobrien relocations, debugging directives and more. 28130561Sobrien 29130561Sobrien The flow of execution is as follows: 30130561Sobrien 31130561Sobrien 1. Command line arguments are checked for control switches and the 32130561Sobrien information to be displayed is selected. 33130561Sobrien 34130561Sobrien 2. Any remaining arguments are assumed to be object files, and they are 35130561Sobrien processed in order by display_bfd(). If the file is an archive each 36130561Sobrien of its elements is processed in turn. 37130561Sobrien 38130561Sobrien 3. The file's target architecture and binary file format are determined 39130561Sobrien by bfd_check_format(). If they are recognised, then dump_bfd() is 40130561Sobrien called. 41130561Sobrien 42130561Sobrien 4. dump_bfd() in turn calls separate functions to display the requested 43130561Sobrien item(s) of information(s). For example disassemble_data() is called if 44130561Sobrien a disassembly has been requested. 45130561Sobrien 46130561Sobrien When disassembling the code loops through blocks of instructions bounded 47130561Sobrien by symbols, calling disassemble_bytes() on each block. The actual 48130561Sobrien disassembling is done by the libopcodes library, via a function pointer 49130561Sobrien supplied by the disassembler() function. */ 50130561Sobrien 5133965Sjdp#include "bfd.h" 52130561Sobrien#include "bfdver.h" 5333965Sjdp#include "progress.h" 5433965Sjdp#include "bucomm.h" 55104834Sobrien#include "budemang.h" 5691041Sobrien#include "getopt.h" 5789857Sobrien#include "safe-ctype.h" 5833965Sjdp#include "dis-asm.h" 5933965Sjdp#include "libiberty.h" 6033965Sjdp#include "demangle.h" 6133965Sjdp#include "debug.h" 6233965Sjdp#include "budbg.h" 6333965Sjdp 6433965Sjdp/* Internal headers for the ELF .stab-dump code - sorry. */ 6533965Sjdp#define BYTES_IN_WORD 32 6633965Sjdp#include "aout/aout64.h" 6733965Sjdp 6833965Sjdp#ifdef NEED_DECLARATION_FPRINTF 69130561Sobrien/* This is needed by init_disassemble_info(). */ 70130561Sobrienextern int fprintf (FILE *, const char *, ...); 7133965Sjdp#endif 7233965Sjdp 7360484Sobrien/* Exit status. */ 7460484Sobrienstatic int exit_status = 0; 7560484Sobrien 76130561Sobrienstatic char *default_target = NULL; /* Default at runtime. */ 7733965Sjdp 78130561Sobrien/* The following variables are set based on arguments passed on the 79130561Sobrien command line. */ 80130561Sobrienstatic int show_version = 0; /* Show the version number. */ 8133965Sjdpstatic int dump_section_contents; /* -s */ 8233965Sjdpstatic int dump_section_headers; /* -h */ 83130561Sobrienstatic bfd_boolean dump_file_header; /* -f */ 8433965Sjdpstatic int dump_symtab; /* -t */ 8533965Sjdpstatic int dump_dynamic_symtab; /* -T */ 8633965Sjdpstatic int dump_reloc_info; /* -r */ 8733965Sjdpstatic int dump_dynamic_reloc_info; /* -R */ 8833965Sjdpstatic int dump_ar_hdrs; /* -a */ 8933965Sjdpstatic int dump_private_headers; /* -p */ 9033965Sjdpstatic int prefix_addresses; /* --prefix-addresses */ 9133965Sjdpstatic int with_line_numbers; /* -l */ 92130561Sobrienstatic bfd_boolean with_source_code; /* -S */ 9333965Sjdpstatic int show_raw_insn; /* --show-raw-insn */ 9433965Sjdpstatic int dump_stab_section_info; /* --stabs */ 9533965Sjdpstatic int do_demangle; /* -C, --demangle */ 96130561Sobrienstatic bfd_boolean disassemble; /* -d */ 97130561Sobrienstatic bfd_boolean disassemble_all; /* -D */ 9833965Sjdpstatic int disassemble_zeroes; /* --disassemble-zeroes */ 99130561Sobrienstatic bfd_boolean formats_info; /* -i */ 10033965Sjdpstatic int wide_output; /* -w */ 10133965Sjdpstatic bfd_vma start_address = (bfd_vma) -1; /* --start-address */ 10233965Sjdpstatic bfd_vma stop_address = (bfd_vma) -1; /* --stop-address */ 10333965Sjdpstatic int dump_debugging; /* --debugging */ 104130561Sobrienstatic int dump_debugging_tags; /* --debugging-tags */ 10533965Sjdpstatic bfd_vma adjust_section_vma = 0; /* --adjust-vma */ 10660484Sobrienstatic int file_start_context = 0; /* --file-start-context */ 10733965Sjdp 108130561Sobrien/* Pointer to an array of section names provided by 109130561Sobrien one or more "-j secname" command line options. */ 110130561Sobrienstatic char **only; 111130561Sobrien/* The total number of slots in the only[] array. */ 112130561Sobrienstatic size_t only_size = 0; 113130561Sobrien/* The number of occupied slots in the only[] array. */ 114130561Sobrienstatic size_t only_used = 0; 115130561Sobrien 116130561Sobrien/* Variables for handling include file path table. */ 117130561Sobrienstatic const char **include_paths; 118130561Sobrienstatic int include_path_count; 119130561Sobrien 120130561Sobrien/* Extra info to pass to the section disassembler and address printing 121130561Sobrien function. */ 122130561Sobrienstruct objdump_disasm_info 123130561Sobrien{ 124130561Sobrien bfd * abfd; 125130561Sobrien asection * sec; 126130561Sobrien bfd_boolean require_sec; 127130561Sobrien arelent ** dynrelbuf; 128130561Sobrien long dynrelcount; 129130561Sobrien disassembler_ftype disassemble_fn; 13033965Sjdp}; 13133965Sjdp 13233965Sjdp/* Architecture to disassemble for, or default if NULL. */ 133130561Sobrienstatic char *machine = NULL; 13433965Sjdp 13560484Sobrien/* Target specific options to the disassembler. */ 136130561Sobrienstatic char *disassembler_options = NULL; 13760484Sobrien 13833965Sjdp/* Endianness to disassemble for, or default if BFD_ENDIAN_UNKNOWN. */ 13933965Sjdpstatic enum bfd_endian endian = BFD_ENDIAN_UNKNOWN; 14033965Sjdp 14133965Sjdp/* The symbol table. */ 14233965Sjdpstatic asymbol **syms; 14333965Sjdp 14433965Sjdp/* Number of symbols in `syms'. */ 14533965Sjdpstatic long symcount = 0; 14633965Sjdp 14733965Sjdp/* The sorted symbol table. */ 14833965Sjdpstatic asymbol **sorted_syms; 14933965Sjdp 15033965Sjdp/* Number of symbols in `sorted_syms'. */ 15133965Sjdpstatic long sorted_symcount = 0; 15233965Sjdp 15333965Sjdp/* The dynamic symbol table. */ 15433965Sjdpstatic asymbol **dynsyms; 15533965Sjdp 15633965Sjdp/* Number of symbols in `dynsyms'. */ 15733965Sjdpstatic long dynsymcount = 0; 15833965Sjdp 159130561Sobrienstatic bfd_byte *stabs; 160130561Sobrienstatic bfd_size_type stab_size; 16133965Sjdp 162130561Sobrienstatic char *strtab; 163130561Sobrienstatic bfd_size_type stabstr_size; 16433965Sjdp 16533965Sjdpstatic void 166130561Sobrienusage (FILE *stream, int status) 16733965Sjdp{ 16889857Sobrien fprintf (stream, _("Usage: %s <option(s)> <file(s)>\n"), program_name); 16989857Sobrien fprintf (stream, _(" Display information from object <file(s)>.\n")); 17089857Sobrien fprintf (stream, _(" At least one of the following switches must be given:\n")); 17160484Sobrien fprintf (stream, _("\ 17268765Sobrien -a, --archive-headers Display archive header information\n\ 17368765Sobrien -f, --file-headers Display the contents of the overall file header\n\ 17468765Sobrien -p, --private-headers Display object format specific file header contents\n\ 17568765Sobrien -h, --[section-]headers Display the contents of the section headers\n\ 17668765Sobrien -x, --all-headers Display the contents of all headers\n\ 17768765Sobrien -d, --disassemble Display assembler contents of executable sections\n\ 17868765Sobrien -D, --disassemble-all Display assembler contents of all sections\n\ 17968765Sobrien -S, --source Intermix source code with disassembly\n\ 18068765Sobrien -s, --full-contents Display the full contents of all sections requested\n\ 18168765Sobrien -g, --debugging Display debug information in object file\n\ 182130561Sobrien -e, --debugging-tags Display debug information using ctags style\n\ 18368765Sobrien -G, --stabs Display (in raw form) any STABS info in the file\n\ 18468765Sobrien -t, --syms Display the contents of the symbol table(s)\n\ 18568765Sobrien -T, --dynamic-syms Display the contents of the dynamic symbol table\n\ 18668765Sobrien -r, --reloc Display the relocation entries in the file\n\ 18768765Sobrien -R, --dynamic-reloc Display the dynamic relocation entries in the file\n\ 18889857Sobrien -v, --version Display this program's version number\n\ 18968765Sobrien -i, --info List object formats and architectures supported\n\ 19068765Sobrien -H, --help Display this information\n\ 19160484Sobrien")); 19260484Sobrien if (status != 2) 19360484Sobrien { 19460484Sobrien fprintf (stream, _("\n The following switches are optional:\n")); 19560484Sobrien fprintf (stream, _("\ 19668765Sobrien -b, --target=BFDNAME Specify the target object format as BFDNAME\n\ 19768765Sobrien -m, --architecture=MACHINE Specify the target architecture as MACHINE\n\ 19868765Sobrien -j, --section=NAME Only display information for section NAME\n\ 19968765Sobrien -M, --disassembler-options=OPT Pass text OPT on to the disassembler\n\ 20060484Sobrien -EB --endian=big Assume big endian format when disassembling\n\ 20160484Sobrien -EL --endian=little Assume little endian format when disassembling\n\ 20260484Sobrien --file-start-context Include context from start of file (with -S)\n\ 203130561Sobrien -I, --include=DIR Add DIR to search list for source files\n\ 20468765Sobrien -l, --line-numbers Include line numbers and filenames in output\n\ 20577298Sobrien -C, --demangle[=STYLE] Decode mangled/processed symbol names\n\ 206130561Sobrien The STYLE, if specified, can be `auto', `gnu',\n\ 207130561Sobrien `lucid', `arm', `hp', `edg', `gnu-v3', `java'\n\ 208130561Sobrien or `gnat'\n\ 20968765Sobrien -w, --wide Format output for more than 80 columns\n\ 21068765Sobrien -z, --disassemble-zeroes Do not skip blocks of zeroes when disassembling\n\ 211130561Sobrien --start-address=ADDR Only process data whose address is >= ADDR\n\ 212130561Sobrien --stop-address=ADDR Only process data whose address is <= ADDR\n\ 21360484Sobrien --prefix-addresses Print complete address alongside disassembly\n\ 21460484Sobrien --[no-]show-raw-insn Display hex alongside symbolic disassembly\n\ 21568765Sobrien --adjust-vma=OFFSET Add OFFSET to all displayed section addresses\n\ 21660484Sobrien\n")); 21760484Sobrien list_supported_targets (program_name, stream); 21889857Sobrien list_supported_architectures (program_name, stream); 21968765Sobrien 22060484Sobrien disassembler_usage (stream); 22160484Sobrien } 22233965Sjdp if (status == 0) 22368765Sobrien fprintf (stream, _("Report bugs to %s.\n"), REPORT_BUGS_TO); 22433965Sjdp exit (status); 22533965Sjdp} 22633965Sjdp 22733965Sjdp/* 150 isn't special; it's just an arbitrary non-ASCII char value. */ 228130561Sobrienenum option_values 229130561Sobrien { 230130561Sobrien OPTION_ENDIAN=150, 231130561Sobrien OPTION_START_ADDRESS, 232130561Sobrien OPTION_STOP_ADDRESS, 233130561Sobrien OPTION_ADJUST_VMA 234130561Sobrien }; 23533965Sjdp 23633965Sjdpstatic struct option long_options[]= 23733965Sjdp{ 23833965Sjdp {"adjust-vma", required_argument, NULL, OPTION_ADJUST_VMA}, 23933965Sjdp {"all-headers", no_argument, NULL, 'x'}, 24033965Sjdp {"private-headers", no_argument, NULL, 'p'}, 24133965Sjdp {"architecture", required_argument, NULL, 'm'}, 24233965Sjdp {"archive-headers", no_argument, NULL, 'a'}, 24360484Sobrien {"debugging", no_argument, NULL, 'g'}, 244130561Sobrien {"debugging-tags", no_argument, NULL, 'e'}, 24577298Sobrien {"demangle", optional_argument, NULL, 'C'}, 24633965Sjdp {"disassemble", no_argument, NULL, 'd'}, 24733965Sjdp {"disassemble-all", no_argument, NULL, 'D'}, 24860484Sobrien {"disassembler-options", required_argument, NULL, 'M'}, 24960484Sobrien {"disassemble-zeroes", no_argument, NULL, 'z'}, 25033965Sjdp {"dynamic-reloc", no_argument, NULL, 'R'}, 25133965Sjdp {"dynamic-syms", no_argument, NULL, 'T'}, 25233965Sjdp {"endian", required_argument, NULL, OPTION_ENDIAN}, 25333965Sjdp {"file-headers", no_argument, NULL, 'f'}, 25460484Sobrien {"file-start-context", no_argument, &file_start_context, 1}, 25533965Sjdp {"full-contents", no_argument, NULL, 's'}, 25633965Sjdp {"headers", no_argument, NULL, 'h'}, 25733965Sjdp {"help", no_argument, NULL, 'H'}, 25833965Sjdp {"info", no_argument, NULL, 'i'}, 25933965Sjdp {"line-numbers", no_argument, NULL, 'l'}, 26033965Sjdp {"no-show-raw-insn", no_argument, &show_raw_insn, -1}, 26133965Sjdp {"prefix-addresses", no_argument, &prefix_addresses, 1}, 26233965Sjdp {"reloc", no_argument, NULL, 'r'}, 26333965Sjdp {"section", required_argument, NULL, 'j'}, 26433965Sjdp {"section-headers", no_argument, NULL, 'h'}, 26533965Sjdp {"show-raw-insn", no_argument, &show_raw_insn, 1}, 26633965Sjdp {"source", no_argument, NULL, 'S'}, 267130561Sobrien {"include", required_argument, NULL, 'I'}, 26860484Sobrien {"stabs", no_argument, NULL, 'G'}, 26933965Sjdp {"start-address", required_argument, NULL, OPTION_START_ADDRESS}, 27033965Sjdp {"stop-address", required_argument, NULL, OPTION_STOP_ADDRESS}, 27133965Sjdp {"syms", no_argument, NULL, 't'}, 27233965Sjdp {"target", required_argument, NULL, 'b'}, 27360484Sobrien {"version", no_argument, NULL, 'V'}, 27460484Sobrien {"wide", no_argument, NULL, 'w'}, 27533965Sjdp {0, no_argument, 0, 0} 27633965Sjdp}; 27733965Sjdp 27833965Sjdpstatic void 279130561Sobriennonfatal (const char *msg) 28060484Sobrien{ 28160484Sobrien bfd_nonfatal (msg); 28260484Sobrien exit_status = 1; 28360484Sobrien} 28460484Sobrien 28560484Sobrienstatic void 286130561Sobriendump_section_header (bfd *abfd ATTRIBUTE_UNUSED, asection *section, 287130561Sobrien void *ignored ATTRIBUTE_UNUSED) 28833965Sjdp{ 28933965Sjdp char *comma = ""; 29060484Sobrien unsigned int opb = bfd_octets_per_byte (abfd); 29133965Sjdp 29233965Sjdp printf ("%3d %-13s %08lx ", section->index, 29333965Sjdp bfd_get_section_name (abfd, section), 29460484Sobrien (unsigned long) bfd_section_size (abfd, section) / opb); 29589857Sobrien bfd_printf_vma (abfd, bfd_get_section_vma (abfd, section)); 29633965Sjdp printf (" "); 29789857Sobrien bfd_printf_vma (abfd, section->lma); 29889857Sobrien printf (" %08lx 2**%u", (unsigned long) section->filepos, 29933965Sjdp bfd_get_section_alignment (abfd, section)); 30033965Sjdp if (! wide_output) 30133965Sjdp printf ("\n "); 30233965Sjdp printf (" "); 30333965Sjdp 30433965Sjdp#define PF(x, y) \ 30533965Sjdp if (section->flags & x) { printf ("%s%s", comma, y); comma = ", "; } 30633965Sjdp 30733965Sjdp PF (SEC_HAS_CONTENTS, "CONTENTS"); 30833965Sjdp PF (SEC_ALLOC, "ALLOC"); 30933965Sjdp PF (SEC_CONSTRUCTOR, "CONSTRUCTOR"); 31033965Sjdp PF (SEC_LOAD, "LOAD"); 31133965Sjdp PF (SEC_RELOC, "RELOC"); 31233965Sjdp PF (SEC_READONLY, "READONLY"); 31333965Sjdp PF (SEC_CODE, "CODE"); 31433965Sjdp PF (SEC_DATA, "DATA"); 31533965Sjdp PF (SEC_ROM, "ROM"); 31633965Sjdp PF (SEC_DEBUGGING, "DEBUGGING"); 31733965Sjdp PF (SEC_NEVER_LOAD, "NEVER_LOAD"); 31833965Sjdp PF (SEC_EXCLUDE, "EXCLUDE"); 31933965Sjdp PF (SEC_SORT_ENTRIES, "SORT_ENTRIES"); 32077298Sobrien PF (SEC_BLOCK, "BLOCK"); 32177298Sobrien PF (SEC_CLINK, "CLINK"); 32260484Sobrien PF (SEC_SMALL_DATA, "SMALL_DATA"); 32360484Sobrien PF (SEC_SHARED, "SHARED"); 32489857Sobrien PF (SEC_ARCH_BIT_0, "ARCH_BIT_0"); 325104834Sobrien PF (SEC_THREAD_LOCAL, "THREAD_LOCAL"); 32633965Sjdp 32733965Sjdp if ((section->flags & SEC_LINK_ONCE) != 0) 32833965Sjdp { 32933965Sjdp const char *ls; 33033965Sjdp 33133965Sjdp switch (section->flags & SEC_LINK_DUPLICATES) 33233965Sjdp { 33333965Sjdp default: 33433965Sjdp abort (); 33533965Sjdp case SEC_LINK_DUPLICATES_DISCARD: 33633965Sjdp ls = "LINK_ONCE_DISCARD"; 33733965Sjdp break; 33833965Sjdp case SEC_LINK_DUPLICATES_ONE_ONLY: 33933965Sjdp ls = "LINK_ONCE_ONE_ONLY"; 34033965Sjdp break; 34133965Sjdp case SEC_LINK_DUPLICATES_SAME_SIZE: 34233965Sjdp ls = "LINK_ONCE_SAME_SIZE"; 34333965Sjdp break; 34433965Sjdp case SEC_LINK_DUPLICATES_SAME_CONTENTS: 34533965Sjdp ls = "LINK_ONCE_SAME_CONTENTS"; 34633965Sjdp break; 34733965Sjdp } 34833965Sjdp printf ("%s%s", comma, ls); 34960484Sobrien 35060484Sobrien if (section->comdat != NULL) 35160484Sobrien printf (" (COMDAT %s %ld)", section->comdat->name, 35260484Sobrien section->comdat->symbol); 35360484Sobrien 35433965Sjdp comma = ", "; 35533965Sjdp } 35633965Sjdp 35733965Sjdp printf ("\n"); 35833965Sjdp#undef PF 35933965Sjdp} 36033965Sjdp 36133965Sjdpstatic void 362130561Sobriendump_headers (bfd *abfd) 36333965Sjdp{ 36460484Sobrien printf (_("Sections:\n")); 36560484Sobrien 36633965Sjdp#ifndef BFD64 36760484Sobrien printf (_("Idx Name Size VMA LMA File off Algn")); 36833965Sjdp#else 369104834Sobrien /* With BFD64, non-ELF returns -1 and wants always 64 bit addresses. */ 370104834Sobrien if (bfd_get_arch_size (abfd) == 32) 371104834Sobrien printf (_("Idx Name Size VMA LMA File off Algn")); 372104834Sobrien else 373104834Sobrien printf (_("Idx Name Size VMA LMA File off Algn")); 37433965Sjdp#endif 37560484Sobrien 37660484Sobrien if (wide_output) 37760484Sobrien printf (_(" Flags")); 378130561Sobrien if (abfd->flags & HAS_LOAD_PAGE) 379130561Sobrien printf (_(" Pg")); 38060484Sobrien printf ("\n"); 38160484Sobrien 382130561Sobrien bfd_map_over_sections (abfd, dump_section_header, NULL); 38333965Sjdp} 38433965Sjdp 38533965Sjdpstatic asymbol ** 386130561Sobrienslurp_symtab (bfd *abfd) 38733965Sjdp{ 388130561Sobrien asymbol **sy = NULL; 38933965Sjdp long storage; 39033965Sjdp 39133965Sjdp if (!(bfd_get_file_flags (abfd) & HAS_SYMS)) 39233965Sjdp { 39333965Sjdp symcount = 0; 39433965Sjdp return NULL; 39533965Sjdp } 39633965Sjdp 39733965Sjdp storage = bfd_get_symtab_upper_bound (abfd); 39833965Sjdp if (storage < 0) 39933965Sjdp bfd_fatal (bfd_get_filename (abfd)); 400104834Sobrien if (storage) 401130561Sobrien sy = xmalloc (storage); 40233965Sjdp 40333965Sjdp symcount = bfd_canonicalize_symtab (abfd, sy); 40433965Sjdp if (symcount < 0) 40533965Sjdp bfd_fatal (bfd_get_filename (abfd)); 40633965Sjdp return sy; 40733965Sjdp} 40833965Sjdp 40933965Sjdp/* Read in the dynamic symbols. */ 41033965Sjdp 41133965Sjdpstatic asymbol ** 412130561Sobrienslurp_dynamic_symtab (bfd *abfd) 41333965Sjdp{ 414130561Sobrien asymbol **sy = NULL; 41533965Sjdp long storage; 41633965Sjdp 41733965Sjdp storage = bfd_get_dynamic_symtab_upper_bound (abfd); 41833965Sjdp if (storage < 0) 41933965Sjdp { 42033965Sjdp if (!(bfd_get_file_flags (abfd) & DYNAMIC)) 42133965Sjdp { 42260484Sobrien non_fatal (_("%s: not a dynamic object"), bfd_get_filename (abfd)); 42333965Sjdp dynsymcount = 0; 42433965Sjdp return NULL; 42533965Sjdp } 42633965Sjdp 42733965Sjdp bfd_fatal (bfd_get_filename (abfd)); 42833965Sjdp } 429104834Sobrien if (storage) 430130561Sobrien sy = xmalloc (storage); 43133965Sjdp 43233965Sjdp dynsymcount = bfd_canonicalize_dynamic_symtab (abfd, sy); 43333965Sjdp if (dynsymcount < 0) 43433965Sjdp bfd_fatal (bfd_get_filename (abfd)); 43533965Sjdp return sy; 43633965Sjdp} 43733965Sjdp 43833965Sjdp/* Filter out (in place) symbols that are useless for disassembly. 43933965Sjdp COUNT is the number of elements in SYMBOLS. 440104834Sobrien Return the number of useful symbols. */ 44133965Sjdp 44233965Sjdpstatic long 443130561Sobrienremove_useless_symbols (asymbol **symbols, long count) 44433965Sjdp{ 445130561Sobrien asymbol **in_ptr = symbols, **out_ptr = symbols; 44633965Sjdp 44733965Sjdp while (--count >= 0) 44833965Sjdp { 44933965Sjdp asymbol *sym = *in_ptr++; 45033965Sjdp 45133965Sjdp if (sym->name == NULL || sym->name[0] == '\0') 45233965Sjdp continue; 45333965Sjdp if (sym->flags & (BSF_DEBUGGING)) 45433965Sjdp continue; 45533965Sjdp if (bfd_is_und_section (sym->section) 45633965Sjdp || bfd_is_com_section (sym->section)) 45733965Sjdp continue; 45833965Sjdp 45933965Sjdp *out_ptr++ = sym; 46033965Sjdp } 46133965Sjdp return out_ptr - symbols; 46233965Sjdp} 46333965Sjdp 46433965Sjdp/* Sort symbols into value order. */ 46533965Sjdp 466104834Sobrienstatic int 467130561Sobriencompare_symbols (const void *ap, const void *bp) 46833965Sjdp{ 469130561Sobrien const asymbol *a = * (const asymbol **) ap; 470130561Sobrien const asymbol *b = * (const asymbol **) bp; 471130561Sobrien const char *an; 472130561Sobrien const char *bn; 473130561Sobrien size_t anl; 474130561Sobrien size_t bnl; 475130561Sobrien bfd_boolean af; 476130561Sobrien bfd_boolean bf; 477130561Sobrien flagword aflags; 478130561Sobrien flagword bflags; 47933965Sjdp 48033965Sjdp if (bfd_asymbol_value (a) > bfd_asymbol_value (b)) 48133965Sjdp return 1; 48233965Sjdp else if (bfd_asymbol_value (a) < bfd_asymbol_value (b)) 48333965Sjdp return -1; 48433965Sjdp 48533965Sjdp if (a->section > b->section) 48633965Sjdp return 1; 48733965Sjdp else if (a->section < b->section) 48833965Sjdp return -1; 48933965Sjdp 49033965Sjdp an = bfd_asymbol_name (a); 49133965Sjdp bn = bfd_asymbol_name (b); 49233965Sjdp anl = strlen (an); 49333965Sjdp bnl = strlen (bn); 49433965Sjdp 49533965Sjdp /* The symbols gnu_compiled and gcc2_compiled convey no real 49633965Sjdp information, so put them after other symbols with the same value. */ 49733965Sjdp af = (strstr (an, "gnu_compiled") != NULL 49833965Sjdp || strstr (an, "gcc2_compiled") != NULL); 49933965Sjdp bf = (strstr (bn, "gnu_compiled") != NULL 50033965Sjdp || strstr (bn, "gcc2_compiled") != NULL); 50133965Sjdp 50233965Sjdp if (af && ! bf) 50333965Sjdp return 1; 50433965Sjdp if (! af && bf) 50533965Sjdp return -1; 50633965Sjdp 50733965Sjdp /* We use a heuristic for the file name, to try to sort it after 50833965Sjdp more useful symbols. It may not work on non Unix systems, but it 50933965Sjdp doesn't really matter; the only difference is precisely which 51033965Sjdp symbol names get printed. */ 51133965Sjdp 51233965Sjdp#define file_symbol(s, sn, snl) \ 51333965Sjdp (((s)->flags & BSF_FILE) != 0 \ 51433965Sjdp || ((sn)[(snl) - 2] == '.' \ 51533965Sjdp && ((sn)[(snl) - 1] == 'o' \ 51633965Sjdp || (sn)[(snl) - 1] == 'a'))) 51733965Sjdp 51833965Sjdp af = file_symbol (a, an, anl); 51933965Sjdp bf = file_symbol (b, bn, bnl); 52033965Sjdp 52133965Sjdp if (af && ! bf) 52233965Sjdp return 1; 52333965Sjdp if (! af && bf) 52433965Sjdp return -1; 52533965Sjdp 52633965Sjdp /* Try to sort global symbols before local symbols before function 52733965Sjdp symbols before debugging symbols. */ 52833965Sjdp 52933965Sjdp aflags = a->flags; 53033965Sjdp bflags = b->flags; 53133965Sjdp 53233965Sjdp if ((aflags & BSF_DEBUGGING) != (bflags & BSF_DEBUGGING)) 53333965Sjdp { 53433965Sjdp if ((aflags & BSF_DEBUGGING) != 0) 53533965Sjdp return 1; 53633965Sjdp else 53733965Sjdp return -1; 53833965Sjdp } 53933965Sjdp if ((aflags & BSF_FUNCTION) != (bflags & BSF_FUNCTION)) 54033965Sjdp { 54133965Sjdp if ((aflags & BSF_FUNCTION) != 0) 54233965Sjdp return -1; 54333965Sjdp else 54433965Sjdp return 1; 54533965Sjdp } 54633965Sjdp if ((aflags & BSF_LOCAL) != (bflags & BSF_LOCAL)) 54733965Sjdp { 54833965Sjdp if ((aflags & BSF_LOCAL) != 0) 54933965Sjdp return 1; 55033965Sjdp else 55133965Sjdp return -1; 55233965Sjdp } 55333965Sjdp if ((aflags & BSF_GLOBAL) != (bflags & BSF_GLOBAL)) 55433965Sjdp { 55533965Sjdp if ((aflags & BSF_GLOBAL) != 0) 55633965Sjdp return -1; 55733965Sjdp else 55833965Sjdp return 1; 55933965Sjdp } 56033965Sjdp 56133965Sjdp /* Symbols that start with '.' might be section names, so sort them 56233965Sjdp after symbols that don't start with '.'. */ 56333965Sjdp if (an[0] == '.' && bn[0] != '.') 56433965Sjdp return 1; 56533965Sjdp if (an[0] != '.' && bn[0] == '.') 56633965Sjdp return -1; 56733965Sjdp 56833965Sjdp /* Finally, if we can't distinguish them in any other way, try to 56933965Sjdp get consistent results by sorting the symbols by name. */ 57033965Sjdp return strcmp (an, bn); 57133965Sjdp} 57233965Sjdp 57333965Sjdp/* Sort relocs into address order. */ 57433965Sjdp 57533965Sjdpstatic int 576130561Sobriencompare_relocs (const void *ap, const void *bp) 57733965Sjdp{ 578130561Sobrien const arelent *a = * (const arelent **) ap; 579130561Sobrien const arelent *b = * (const arelent **) bp; 58033965Sjdp 58133965Sjdp if (a->address > b->address) 58233965Sjdp return 1; 58333965Sjdp else if (a->address < b->address) 58433965Sjdp return -1; 58533965Sjdp 58633965Sjdp /* So that associated relocations tied to the same address show up 58733965Sjdp in the correct order, we don't do any further sorting. */ 58833965Sjdp if (a > b) 58933965Sjdp return 1; 59033965Sjdp else if (a < b) 59133965Sjdp return -1; 59233965Sjdp else 59333965Sjdp return 0; 59433965Sjdp} 59533965Sjdp 596130561Sobrien/* Print an address (VMA) to the output stream in INFO. 597130561Sobrien If SKIP_ZEROES is TRUE, omit leading zeroes. */ 59833965Sjdp 59933965Sjdpstatic void 600130561Sobrienobjdump_print_value (bfd_vma vma, struct disassemble_info *info, 601130561Sobrien bfd_boolean skip_zeroes) 60233965Sjdp{ 60333965Sjdp char buf[30]; 60433965Sjdp char *p; 605130561Sobrien struct objdump_disasm_info *aux; 60633965Sjdp 607130561Sobrien aux = (struct objdump_disasm_info *) info->application_data; 60889857Sobrien bfd_sprintf_vma (aux->abfd, buf, vma); 60933965Sjdp if (! skip_zeroes) 61033965Sjdp p = buf; 61133965Sjdp else 61233965Sjdp { 61333965Sjdp for (p = buf; *p == '0'; ++p) 61433965Sjdp ; 61533965Sjdp if (*p == '\0') 61633965Sjdp --p; 61733965Sjdp } 61833965Sjdp (*info->fprintf_func) (info->stream, "%s", p); 61933965Sjdp} 62033965Sjdp 62133965Sjdp/* Print the name of a symbol. */ 62233965Sjdp 62333965Sjdpstatic void 624130561Sobrienobjdump_print_symname (bfd *abfd, struct disassemble_info *info, 625130561Sobrien asymbol *sym) 62633965Sjdp{ 62733965Sjdp char *alloc; 62833965Sjdp const char *name; 62933965Sjdp 63033965Sjdp alloc = NULL; 63133965Sjdp name = bfd_asymbol_name (sym); 632104834Sobrien if (do_demangle && name[0] != '\0') 63333965Sjdp { 63433965Sjdp /* Demangle the name. */ 635104834Sobrien alloc = demangle (abfd, name); 636104834Sobrien name = alloc; 63733965Sjdp } 63833965Sjdp 63933965Sjdp if (info != NULL) 640104834Sobrien (*info->fprintf_func) (info->stream, "%s", name); 64133965Sjdp else 642104834Sobrien printf ("%s", name); 64333965Sjdp 64433965Sjdp if (alloc != NULL) 64533965Sjdp free (alloc); 64633965Sjdp} 64733965Sjdp 648130561Sobrien/* Locate a symbol given a bfd and a section (from INFO->application_data), 649130561Sobrien and a VMA. If INFO->application_data->require_sec is TRUE, then always 650130561Sobrien require the symbol to be in the section. Returns NULL if there is no 651130561Sobrien suitable symbol. If PLACE is not NULL, then *PLACE is set to the index 652130561Sobrien of the symbol in sorted_syms. */ 65333965Sjdp 65433965Sjdpstatic asymbol * 655130561Sobrienfind_symbol_for_address (bfd_vma vma, 656130561Sobrien struct disassemble_info *info, 657130561Sobrien long *place) 65833965Sjdp{ 65933965Sjdp /* @@ Would it speed things up to cache the last two symbols returned, 66033965Sjdp and maybe their address ranges? For many processors, only one memory 66133965Sjdp operand can be present at a time, so the 2-entry cache wouldn't be 66233965Sjdp constantly churned by code doing heavy memory accesses. */ 66333965Sjdp 66433965Sjdp /* Indices in `sorted_syms'. */ 66533965Sjdp long min = 0; 66633965Sjdp long max = sorted_symcount; 66733965Sjdp long thisplace; 668130561Sobrien struct objdump_disasm_info *aux; 669130561Sobrien bfd *abfd; 670130561Sobrien asection *sec; 671130561Sobrien unsigned int opb; 67233965Sjdp 67333965Sjdp if (sorted_symcount < 1) 67433965Sjdp return NULL; 67533965Sjdp 676130561Sobrien aux = (struct objdump_disasm_info *) info->application_data; 677130561Sobrien abfd = aux->abfd; 678130561Sobrien sec = aux->sec; 679130561Sobrien opb = bfd_octets_per_byte (abfd); 680130561Sobrien 68133965Sjdp /* Perform a binary search looking for the closest symbol to the 68233965Sjdp required value. We are searching the range (min, max]. */ 68333965Sjdp while (min + 1 < max) 68433965Sjdp { 68533965Sjdp asymbol *sym; 68633965Sjdp 68733965Sjdp thisplace = (max + min) / 2; 68833965Sjdp sym = sorted_syms[thisplace]; 68933965Sjdp 69033965Sjdp if (bfd_asymbol_value (sym) > vma) 69133965Sjdp max = thisplace; 69233965Sjdp else if (bfd_asymbol_value (sym) < vma) 69333965Sjdp min = thisplace; 69433965Sjdp else 69533965Sjdp { 69633965Sjdp min = thisplace; 69733965Sjdp break; 69833965Sjdp } 69933965Sjdp } 70033965Sjdp 70133965Sjdp /* The symbol we want is now in min, the low end of the range we 70233965Sjdp were searching. If there are several symbols with the same 70333965Sjdp value, we want the first one. */ 70433965Sjdp thisplace = min; 70533965Sjdp while (thisplace > 0 70633965Sjdp && (bfd_asymbol_value (sorted_syms[thisplace]) 70733965Sjdp == bfd_asymbol_value (sorted_syms[thisplace - 1]))) 70833965Sjdp --thisplace; 70933965Sjdp 710130561Sobrien /* If the file is relocatable, and the symbol could be from this 71133965Sjdp section, prefer a symbol from this section over symbols from 71233965Sjdp others, even if the other symbol's value might be closer. 713104834Sobrien 71433965Sjdp Note that this may be wrong for some symbol references if the 71533965Sjdp sections have overlapping memory ranges, but in that case there's 71633965Sjdp no way to tell what's desired without looking at the relocation 71733965Sjdp table. */ 71833965Sjdp if (sorted_syms[thisplace]->section != sec 719130561Sobrien && (aux->require_sec 72033965Sjdp || ((abfd->flags & HAS_RELOC) != 0 72133965Sjdp && vma >= bfd_get_section_vma (abfd, sec) 72233965Sjdp && vma < (bfd_get_section_vma (abfd, sec) 72360484Sobrien + bfd_section_size (abfd, sec) / opb)))) 72433965Sjdp { 72533965Sjdp long i; 72633965Sjdp 72733965Sjdp for (i = thisplace + 1; i < sorted_symcount; i++) 72833965Sjdp { 72933965Sjdp if (bfd_asymbol_value (sorted_syms[i]) 73033965Sjdp != bfd_asymbol_value (sorted_syms[thisplace])) 73133965Sjdp break; 73233965Sjdp } 733130561Sobrien 73433965Sjdp --i; 735130561Sobrien 73633965Sjdp for (; i >= 0; i--) 73733965Sjdp { 73833965Sjdp if (sorted_syms[i]->section == sec 73933965Sjdp && (i == 0 74033965Sjdp || sorted_syms[i - 1]->section != sec 74133965Sjdp || (bfd_asymbol_value (sorted_syms[i]) 74233965Sjdp != bfd_asymbol_value (sorted_syms[i - 1])))) 74333965Sjdp { 74433965Sjdp thisplace = i; 74533965Sjdp break; 74633965Sjdp } 74733965Sjdp } 74833965Sjdp 74933965Sjdp if (sorted_syms[thisplace]->section != sec) 75033965Sjdp { 75133965Sjdp /* We didn't find a good symbol with a smaller value. 75233965Sjdp Look for one with a larger value. */ 75333965Sjdp for (i = thisplace + 1; i < sorted_symcount; i++) 75433965Sjdp { 75533965Sjdp if (sorted_syms[i]->section == sec) 75633965Sjdp { 75733965Sjdp thisplace = i; 75833965Sjdp break; 75933965Sjdp } 76033965Sjdp } 76133965Sjdp } 76233965Sjdp 76333965Sjdp if (sorted_syms[thisplace]->section != sec 764130561Sobrien && (aux->require_sec 76533965Sjdp || ((abfd->flags & HAS_RELOC) != 0 76633965Sjdp && vma >= bfd_get_section_vma (abfd, sec) 76733965Sjdp && vma < (bfd_get_section_vma (abfd, sec) 76833965Sjdp + bfd_section_size (abfd, sec))))) 769130561Sobrien /* There is no suitable symbol. */ 770130561Sobrien return NULL; 77133965Sjdp } 77233965Sjdp 773130561Sobrien /* Give the target a chance to reject the symbol. */ 774130561Sobrien while (! info->symbol_is_valid (sorted_syms [thisplace], info)) 775130561Sobrien { 776130561Sobrien ++ thisplace; 777130561Sobrien if (thisplace >= sorted_symcount 778130561Sobrien || bfd_asymbol_value (sorted_syms [thisplace]) > vma) 779130561Sobrien return NULL; 780130561Sobrien } 781130561Sobrien 78233965Sjdp if (place != NULL) 78333965Sjdp *place = thisplace; 78433965Sjdp 78533965Sjdp return sorted_syms[thisplace]; 78633965Sjdp} 78733965Sjdp 788130561Sobrien/* Print an address and the offset to the nearest symbol. */ 78933965Sjdp 79033965Sjdpstatic void 791130561Sobrienobjdump_print_addr_with_sym (bfd *abfd, asection *sec, asymbol *sym, 792130561Sobrien bfd_vma vma, struct disassemble_info *info, 793130561Sobrien bfd_boolean skip_zeroes) 79433965Sjdp{ 79533965Sjdp objdump_print_value (vma, info, skip_zeroes); 79633965Sjdp 79733965Sjdp if (sym == NULL) 79833965Sjdp { 79933965Sjdp bfd_vma secaddr; 80033965Sjdp 80133965Sjdp (*info->fprintf_func) (info->stream, " <%s", 80233965Sjdp bfd_get_section_name (abfd, sec)); 80333965Sjdp secaddr = bfd_get_section_vma (abfd, sec); 80433965Sjdp if (vma < secaddr) 80533965Sjdp { 80638889Sjdp (*info->fprintf_func) (info->stream, "-0x"); 807130561Sobrien objdump_print_value (secaddr - vma, info, TRUE); 80833965Sjdp } 80933965Sjdp else if (vma > secaddr) 81033965Sjdp { 81138889Sjdp (*info->fprintf_func) (info->stream, "+0x"); 812130561Sobrien objdump_print_value (vma - secaddr, info, TRUE); 81333965Sjdp } 81433965Sjdp (*info->fprintf_func) (info->stream, ">"); 81533965Sjdp } 81633965Sjdp else 81733965Sjdp { 81833965Sjdp (*info->fprintf_func) (info->stream, " <"); 81933965Sjdp objdump_print_symname (abfd, info, sym); 82033965Sjdp if (bfd_asymbol_value (sym) > vma) 82133965Sjdp { 82238889Sjdp (*info->fprintf_func) (info->stream, "-0x"); 823130561Sobrien objdump_print_value (bfd_asymbol_value (sym) - vma, info, TRUE); 82433965Sjdp } 82533965Sjdp else if (vma > bfd_asymbol_value (sym)) 82633965Sjdp { 82738889Sjdp (*info->fprintf_func) (info->stream, "+0x"); 828130561Sobrien objdump_print_value (vma - bfd_asymbol_value (sym), info, TRUE); 82933965Sjdp } 83033965Sjdp (*info->fprintf_func) (info->stream, ">"); 83133965Sjdp } 83233965Sjdp} 83333965Sjdp 834130561Sobrien/* Print an address (VMA), symbolically if possible. 835130561Sobrien If SKIP_ZEROES is TRUE, don't output leading zeroes. */ 83633965Sjdp 83733965Sjdpstatic void 838130561Sobrienobjdump_print_addr (bfd_vma vma, 839130561Sobrien struct disassemble_info *info, 840130561Sobrien bfd_boolean skip_zeroes) 84133965Sjdp{ 84233965Sjdp struct objdump_disasm_info *aux; 84333965Sjdp asymbol *sym; 84433965Sjdp 84533965Sjdp if (sorted_symcount < 1) 84633965Sjdp { 84738889Sjdp (*info->fprintf_func) (info->stream, "0x"); 84833965Sjdp objdump_print_value (vma, info, skip_zeroes); 84933965Sjdp return; 85033965Sjdp } 85133965Sjdp 85233965Sjdp aux = (struct objdump_disasm_info *) info->application_data; 853130561Sobrien sym = find_symbol_for_address (vma, info, NULL); 85433965Sjdp objdump_print_addr_with_sym (aux->abfd, aux->sec, sym, vma, info, 85533965Sjdp skip_zeroes); 85633965Sjdp} 85733965Sjdp 85833965Sjdp/* Print VMA to INFO. This function is passed to the disassembler 85933965Sjdp routine. */ 86033965Sjdp 86133965Sjdpstatic void 862130561Sobrienobjdump_print_address (bfd_vma vma, struct disassemble_info *info) 86333965Sjdp{ 86433965Sjdp objdump_print_addr (vma, info, ! prefix_addresses); 86533965Sjdp} 86633965Sjdp 86738889Sjdp/* Determine of the given address has a symbol associated with it. */ 86838889Sjdp 86938889Sjdpstatic int 870130561Sobrienobjdump_symbol_at_address (bfd_vma vma, struct disassemble_info * info) 87138889Sjdp{ 87238889Sjdp asymbol * sym; 87338889Sjdp 874130561Sobrien sym = find_symbol_for_address (vma, info, NULL); 87538889Sjdp 87638889Sjdp return (sym != NULL && (bfd_asymbol_value (sym) == vma)); 87738889Sjdp} 87838889Sjdp 87933965Sjdp/* Hold the last function name and the last line number we displayed 88033965Sjdp in a disassembly. */ 88133965Sjdp 88233965Sjdpstatic char *prev_functionname; 88333965Sjdpstatic unsigned int prev_line; 88433965Sjdp 88533965Sjdp/* We keep a list of all files that we have seen when doing a 886130561Sobrien disassembly with source, so that we know how much of the file to 88733965Sjdp display. This can be important for inlined functions. */ 88833965Sjdp 88933965Sjdpstruct print_file_list 89033965Sjdp{ 89133965Sjdp struct print_file_list *next; 892130561Sobrien const char *filename; 893130561Sobrien const char *modname; 89433965Sjdp unsigned int line; 89533965Sjdp FILE *f; 89633965Sjdp}; 89733965Sjdp 89833965Sjdpstatic struct print_file_list *print_files; 89933965Sjdp 90033965Sjdp/* The number of preceding context lines to show when we start 90133965Sjdp displaying a file for the first time. */ 90233965Sjdp 90333965Sjdp#define SHOW_PRECEDING_CONTEXT_LINES (5) 90433965Sjdp 905130561Sobrien/* Tries to open MODNAME, and if successful adds a node to print_files 906130561Sobrien linked list and returns that node. Returns NULL on failure. */ 907130561Sobrien 908130561Sobrienstatic struct print_file_list * 909130561Sobrientry_print_file_open (const char *origname, const char *modname) 910130561Sobrien{ 911130561Sobrien struct print_file_list *p; 912130561Sobrien FILE *f; 913130561Sobrien 914130561Sobrien f = fopen (modname, "r"); 915130561Sobrien if (f == NULL) 916130561Sobrien return NULL; 917130561Sobrien 918130561Sobrien if (print_files != NULL && print_files->f != NULL) 919130561Sobrien { 920130561Sobrien fclose (print_files->f); 921130561Sobrien print_files->f = NULL; 922130561Sobrien } 923130561Sobrien 924130561Sobrien p = xmalloc (sizeof (struct print_file_list)); 925130561Sobrien p->filename = origname; 926130561Sobrien p->modname = modname; 927130561Sobrien p->line = 0; 928130561Sobrien p->f = f; 929130561Sobrien p->next = print_files; 930130561Sobrien print_files = p; 931130561Sobrien return p; 932130561Sobrien} 933130561Sobrien 934130561Sobrien/* If the the source file, as described in the symtab, is not found 935130561Sobrien try to locate it in one of the paths specified with -I 936130561Sobrien If found, add location to print_files linked list. */ 937130561Sobrien 938130561Sobrienstatic struct print_file_list * 939130561Sobrienupdate_source_path (const char *filename) 940130561Sobrien{ 941130561Sobrien struct print_file_list *p; 942130561Sobrien const char *fname; 943130561Sobrien int i; 944130561Sobrien 945130561Sobrien if (filename == NULL) 946130561Sobrien return NULL; 947130561Sobrien 948130561Sobrien p = try_print_file_open (filename, filename); 949130561Sobrien if (p != NULL) 950130561Sobrien return p; 951130561Sobrien 952130561Sobrien if (include_path_count == 0) 953130561Sobrien return NULL; 954130561Sobrien 955130561Sobrien /* Get the name of the file. */ 956130561Sobrien fname = strrchr (filename, '/'); 957130561Sobrien#ifdef HAVE_DOS_BASED_FILE_SYSTEM 958130561Sobrien { 959130561Sobrien /* We could have a mixed forward/back slash case. */ 960130561Sobrien char *backslash = strrchr (filename, '\\'); 961130561Sobrien if (fname == NULL || (backslash != NULL && backslash > fname)) 962130561Sobrien fname = backslash; 963130561Sobrien if (fname == NULL && filename[0] != '\0' && filename[1] == ':') 964130561Sobrien fname = filename + 1; 965130561Sobrien } 966130561Sobrien#endif 967130561Sobrien if (fname == NULL) 968130561Sobrien fname = filename; 969130561Sobrien else 970130561Sobrien ++fname; 971130561Sobrien 972130561Sobrien /* If file exists under a new path, we need to add it to the list 973130561Sobrien so that show_line knows about it. */ 974130561Sobrien for (i = 0; i < include_path_count; i++) 975130561Sobrien { 976130561Sobrien char *modname = concat (include_paths[i], "/", fname, (const char *) 0); 977130561Sobrien 978130561Sobrien p = try_print_file_open (filename, modname); 979130561Sobrien if (p) 980130561Sobrien return p; 981130561Sobrien 982130561Sobrien free (modname); 983130561Sobrien } 984130561Sobrien 985130561Sobrien return NULL; 986130561Sobrien} 987130561Sobrien 98833965Sjdp/* Skip ahead to a given line in a file, optionally printing each 98933965Sjdp line. */ 99033965Sjdp 99133965Sjdpstatic void 992130561Sobrienskip_to_line (struct print_file_list *p, unsigned int line, 993130561Sobrien bfd_boolean show) 99433965Sjdp{ 99533965Sjdp while (p->line < line) 99633965Sjdp { 99733965Sjdp char buf[100]; 99833965Sjdp 99933965Sjdp if (fgets (buf, sizeof buf, p->f) == NULL) 100033965Sjdp { 100133965Sjdp fclose (p->f); 100233965Sjdp p->f = NULL; 100333965Sjdp break; 100433965Sjdp } 100533965Sjdp 100633965Sjdp if (show) 100733965Sjdp printf ("%s", buf); 100833965Sjdp 100933965Sjdp if (strchr (buf, '\n') != NULL) 101033965Sjdp ++p->line; 101133965Sjdp } 1012104834Sobrien} 101333965Sjdp 1014130561Sobrien/* Show the line number, or the source line, in a disassembly 101533965Sjdp listing. */ 101633965Sjdp 101733965Sjdpstatic void 1018130561Sobrienshow_line (bfd *abfd, asection *section, bfd_vma addr_offset) 101933965Sjdp{ 1020104834Sobrien const char *filename; 1021104834Sobrien const char *functionname; 102233965Sjdp unsigned int line; 102333965Sjdp 102433965Sjdp if (! with_line_numbers && ! with_source_code) 102533965Sjdp return; 102633965Sjdp 102760484Sobrien if (! bfd_find_nearest_line (abfd, section, syms, addr_offset, &filename, 102833965Sjdp &functionname, &line)) 102933965Sjdp return; 103033965Sjdp 103133965Sjdp if (filename != NULL && *filename == '\0') 103233965Sjdp filename = NULL; 103333965Sjdp if (functionname != NULL && *functionname == '\0') 103433965Sjdp functionname = NULL; 103533965Sjdp 103633965Sjdp if (with_line_numbers) 103733965Sjdp { 103833965Sjdp if (functionname != NULL 103933965Sjdp && (prev_functionname == NULL 104033965Sjdp || strcmp (functionname, prev_functionname) != 0)) 104133965Sjdp printf ("%s():\n", functionname); 104233965Sjdp if (line > 0 && line != prev_line) 104333965Sjdp printf ("%s:%u\n", filename == NULL ? "???" : filename, line); 104433965Sjdp } 104533965Sjdp 104633965Sjdp if (with_source_code 104733965Sjdp && filename != NULL 104833965Sjdp && line > 0) 104933965Sjdp { 105033965Sjdp struct print_file_list **pp, *p; 105133965Sjdp 105233965Sjdp for (pp = &print_files; *pp != NULL; pp = &(*pp)->next) 105333965Sjdp if (strcmp ((*pp)->filename, filename) == 0) 105433965Sjdp break; 105533965Sjdp p = *pp; 105633965Sjdp 105733965Sjdp if (p != NULL) 105833965Sjdp { 105933965Sjdp if (p != print_files) 106033965Sjdp { 106133965Sjdp int l; 106233965Sjdp 106333965Sjdp /* We have reencountered a file name which we saw 106433965Sjdp earlier. This implies that either we are dumping out 106533965Sjdp code from an included file, or the same file was 106633965Sjdp linked in more than once. There are two common cases 106733965Sjdp of an included file: inline functions in a header 106833965Sjdp file, and a bison or flex skeleton file. In the 106933965Sjdp former case we want to just start printing (but we 107033965Sjdp back up a few lines to give context); in the latter 107133965Sjdp case we want to continue from where we left off. I 107233965Sjdp can't think of a good way to distinguish the cases, 107333965Sjdp so I used a heuristic based on the file name. */ 107433965Sjdp if (strcmp (p->filename + strlen (p->filename) - 2, ".h") != 0) 107533965Sjdp l = p->line; 107633965Sjdp else 107733965Sjdp { 107833965Sjdp l = line - SHOW_PRECEDING_CONTEXT_LINES; 107960484Sobrien if (l < 0) 108060484Sobrien l = 0; 108133965Sjdp } 108233965Sjdp 108333965Sjdp if (p->f == NULL) 108433965Sjdp { 1085130561Sobrien p->f = fopen (p->modname, "r"); 108633965Sjdp p->line = 0; 108733965Sjdp } 108833965Sjdp if (p->f != NULL) 1089130561Sobrien skip_to_line (p, l, FALSE); 109033965Sjdp 109133965Sjdp if (print_files->f != NULL) 109233965Sjdp { 109333965Sjdp fclose (print_files->f); 109433965Sjdp print_files->f = NULL; 109533965Sjdp } 109633965Sjdp } 109733965Sjdp 109833965Sjdp if (p->f != NULL) 109933965Sjdp { 1100130561Sobrien skip_to_line (p, line, TRUE); 110133965Sjdp *pp = p->next; 110233965Sjdp p->next = print_files; 110333965Sjdp print_files = p; 110433965Sjdp } 110533965Sjdp } 110633965Sjdp else 110733965Sjdp { 1108130561Sobrien p = update_source_path (filename); 110933965Sjdp 1110130561Sobrien if (p != NULL) 111133965Sjdp { 111233965Sjdp int l; 111333965Sjdp 1114104834Sobrien if (file_start_context) 1115104834Sobrien l = 0; 1116104834Sobrien else 1117104834Sobrien l = line - SHOW_PRECEDING_CONTEXT_LINES; 111860484Sobrien if (l < 0) 111960484Sobrien l = 0; 1120130561Sobrien skip_to_line (p, l, FALSE); 112133965Sjdp if (p->f != NULL) 1122130561Sobrien skip_to_line (p, line, TRUE); 112333965Sjdp } 112433965Sjdp } 112533965Sjdp } 112633965Sjdp 112733965Sjdp if (functionname != NULL 112833965Sjdp && (prev_functionname == NULL 112933965Sjdp || strcmp (functionname, prev_functionname) != 0)) 113033965Sjdp { 113133965Sjdp if (prev_functionname != NULL) 113233965Sjdp free (prev_functionname); 113333965Sjdp prev_functionname = xmalloc (strlen (functionname) + 1); 113433965Sjdp strcpy (prev_functionname, functionname); 113533965Sjdp } 113633965Sjdp 113733965Sjdp if (line > 0 && line != prev_line) 113833965Sjdp prev_line = line; 113933965Sjdp} 114033965Sjdp 114133965Sjdp/* Pseudo FILE object for strings. */ 114260484Sobrientypedef struct 114360484Sobrien{ 114433965Sjdp char *buffer; 114560484Sobrien size_t size; 114633965Sjdp char *current; 114733965Sjdp} SFILE; 114833965Sjdp 1149130561Sobrien/* sprintf to a "stream". */ 115033965Sjdp 115160484Sobrienstatic int 1152130561Sobrienobjdump_sprintf (SFILE *f, const char *format, ...) 115333965Sjdp{ 115460484Sobrien char *buf; 115560484Sobrien size_t n; 1156130561Sobrien va_list args; 115733965Sjdp 1158130561Sobrien va_start (args, format); 115960484Sobrien 116060484Sobrien vasprintf (&buf, format, args); 116160484Sobrien 116260484Sobrien if (buf == NULL) 116360484Sobrien { 116489857Sobrien va_end (args); 116560484Sobrien fatal (_("Out of virtual memory")); 116660484Sobrien } 116760484Sobrien 116860484Sobrien n = strlen (buf); 116960484Sobrien 117060484Sobrien while ((size_t) ((f->buffer + f->size) - f->current) < n + 1) 117160484Sobrien { 117260484Sobrien size_t curroff; 117360484Sobrien 117460484Sobrien curroff = f->current - f->buffer; 117560484Sobrien f->size *= 2; 117660484Sobrien f->buffer = xrealloc (f->buffer, f->size); 117760484Sobrien f->current = f->buffer + curroff; 117860484Sobrien } 117960484Sobrien 118060484Sobrien memcpy (f->current, buf, n); 118160484Sobrien f->current += n; 118260484Sobrien f->current[0] = '\0'; 118360484Sobrien 118460484Sobrien free (buf); 118560484Sobrien 1186130561Sobrien va_end (args); 118733965Sjdp return n; 118833965Sjdp} 118933965Sjdp 1190130561Sobrien/* Returns TRUE if the specified section should be dumped. */ 1191130561Sobrien 1192130561Sobrienstatic bfd_boolean 1193130561Sobrienprocess_section_p (asection * section) 1194130561Sobrien{ 1195130561Sobrien size_t i; 1196130561Sobrien 1197130561Sobrien if (only == NULL) 1198130561Sobrien return TRUE; 1199130561Sobrien 1200130561Sobrien for (i = 0; i < only_used; i++) 1201130561Sobrien if (strcmp (only [i], section->name) == 0) 1202130561Sobrien return TRUE; 1203130561Sobrien 1204130561Sobrien return FALSE; 1205130561Sobrien} 1206130561Sobrien 1207130561Sobrien 120833965Sjdp/* The number of zeroes we want to see before we start skipping them. 120933965Sjdp The number is arbitrarily chosen. */ 121033965Sjdp 121189857Sobrien#ifndef SKIP_ZEROES 121233965Sjdp#define SKIP_ZEROES (8) 121389857Sobrien#endif 121433965Sjdp 121533965Sjdp/* The number of zeroes to skip at the end of a section. If the 121633965Sjdp number of zeroes at the end is between SKIP_ZEROES_AT_END and 121733965Sjdp SKIP_ZEROES, they will be disassembled. If there are fewer than 121833965Sjdp SKIP_ZEROES_AT_END, they will be skipped. This is a heuristic 121933965Sjdp attempt to avoid disassembling zeroes inserted by section 122033965Sjdp alignment. */ 122133965Sjdp 122289857Sobrien#ifndef SKIP_ZEROES_AT_END 122333965Sjdp#define SKIP_ZEROES_AT_END (3) 122489857Sobrien#endif 122533965Sjdp 122633965Sjdp/* Disassemble some data in memory between given values. */ 122733965Sjdp 122833965Sjdpstatic void 1229130561Sobriendisassemble_bytes (struct disassemble_info * info, 1230130561Sobrien disassembler_ftype disassemble_fn, 1231130561Sobrien bfd_boolean insns, 1232130561Sobrien bfd_byte * data, 1233130561Sobrien bfd_vma start_offset, 1234130561Sobrien bfd_vma stop_offset, 1235130561Sobrien bfd_vma rel_offset, 1236130561Sobrien arelent *** relppp, 1237130561Sobrien arelent ** relppend) 123833965Sjdp{ 123933965Sjdp struct objdump_disasm_info *aux; 124033965Sjdp asection *section; 124160484Sobrien int octets_per_line; 1242130561Sobrien bfd_boolean done_dot; 124333965Sjdp int skip_addr_chars; 124460484Sobrien bfd_vma addr_offset; 124560484Sobrien int opb = info->octets_per_byte; 124633965Sjdp 124733965Sjdp aux = (struct objdump_disasm_info *) info->application_data; 124833965Sjdp section = aux->sec; 124933965Sjdp 125033965Sjdp if (insns) 125160484Sobrien octets_per_line = 4; 125233965Sjdp else 125360484Sobrien octets_per_line = 16; 125433965Sjdp 125533965Sjdp /* Figure out how many characters to skip at the start of an 125633965Sjdp address, to make the disassembly look nicer. We discard leading 125733965Sjdp zeroes in chunks of 4, ensuring that there is always a leading 125833965Sjdp zero remaining. */ 125933965Sjdp skip_addr_chars = 0; 126033965Sjdp if (! prefix_addresses) 126133965Sjdp { 126233965Sjdp char buf[30]; 126333965Sjdp char *s; 126433965Sjdp 126589857Sobrien bfd_sprintf_vma 126689857Sobrien (aux->abfd, buf, 126789857Sobrien (section->vma 126889857Sobrien + bfd_section_size (section->owner, section) / opb)); 126933965Sjdp s = buf; 127033965Sjdp while (s[0] == '0' && s[1] == '0' && s[2] == '0' && s[3] == '0' 127133965Sjdp && s[4] == '0') 127233965Sjdp { 127333965Sjdp skip_addr_chars += 4; 127433965Sjdp s += 4; 127533965Sjdp } 127633965Sjdp } 127733965Sjdp 127833965Sjdp info->insn_info_valid = 0; 127933965Sjdp 1280130561Sobrien done_dot = FALSE; 128160484Sobrien addr_offset = start_offset; 128260484Sobrien while (addr_offset < stop_offset) 128333965Sjdp { 128460484Sobrien bfd_vma z; 128560484Sobrien int octets = 0; 1286130561Sobrien bfd_boolean need_nl = FALSE; 128733965Sjdp 128860484Sobrien /* If we see more than SKIP_ZEROES octets of zeroes, we just 1289130561Sobrien print `...'. */ 129060484Sobrien for (z = addr_offset * opb; z < stop_offset * opb; z++) 129133965Sjdp if (data[z] != 0) 129233965Sjdp break; 129333965Sjdp if (! disassemble_zeroes 129433965Sjdp && (info->insn_info_valid == 0 129533965Sjdp || info->branch_delay_insns == 0) 129660484Sobrien && (z - addr_offset * opb >= SKIP_ZEROES 1297104834Sobrien || (z == stop_offset * opb && 1298104834Sobrien z - addr_offset * opb < SKIP_ZEROES_AT_END))) 129933965Sjdp { 130033965Sjdp printf ("\t...\n"); 130133965Sjdp 130260484Sobrien /* If there are more nonzero octets to follow, we only skip 1303130561Sobrien zeroes in multiples of 4, to try to avoid running over 1304130561Sobrien the start of an instruction which happens to start with 1305130561Sobrien zero. */ 130660484Sobrien if (z != stop_offset * opb) 130760484Sobrien z = addr_offset * opb + ((z - addr_offset * opb) &~ 3); 130833965Sjdp 130960484Sobrien octets = z - addr_offset * opb; 131033965Sjdp } 131133965Sjdp else 131233965Sjdp { 131360484Sobrien char buf[50]; 131433965Sjdp SFILE sfile; 131538889Sjdp int bpc = 0; 131638889Sjdp int pb = 0; 131733965Sjdp 1318130561Sobrien done_dot = FALSE; 131933965Sjdp 132033965Sjdp if (with_line_numbers || with_source_code) 132189857Sobrien /* The line number tables will refer to unadjusted 132289857Sobrien section VMAs, so we must undo any VMA modifications 132389857Sobrien when calling show_line. */ 132489857Sobrien show_line (aux->abfd, section, addr_offset - adjust_section_vma); 132533965Sjdp 132633965Sjdp if (! prefix_addresses) 132733965Sjdp { 132833965Sjdp char *s; 132933965Sjdp 133089857Sobrien bfd_sprintf_vma (aux->abfd, buf, section->vma + addr_offset); 133133965Sjdp for (s = buf + skip_addr_chars; *s == '0'; s++) 133233965Sjdp *s = ' '; 133333965Sjdp if (*s == '\0') 133433965Sjdp *--s = '0'; 133533965Sjdp printf ("%s:\t", buf + skip_addr_chars); 133633965Sjdp } 133733965Sjdp else 133833965Sjdp { 1339130561Sobrien aux->require_sec = TRUE; 134060484Sobrien objdump_print_address (section->vma + addr_offset, info); 1341130561Sobrien aux->require_sec = FALSE; 134233965Sjdp putchar (' '); 134333965Sjdp } 134433965Sjdp 134533965Sjdp if (insns) 134633965Sjdp { 134760484Sobrien sfile.size = 120; 134860484Sobrien sfile.buffer = xmalloc (sfile.size); 134960484Sobrien sfile.current = sfile.buffer; 135033965Sjdp info->fprintf_func = (fprintf_ftype) objdump_sprintf; 135133965Sjdp info->stream = (FILE *) &sfile; 135233965Sjdp info->bytes_per_line = 0; 135333965Sjdp info->bytes_per_chunk = 0; 135460484Sobrien 135577298Sobrien#ifdef DISASSEMBLER_NEEDS_RELOCS 135660484Sobrien /* FIXME: This is wrong. It tests the number of octets 1357130561Sobrien in the last instruction, not the current one. */ 135860484Sobrien if (*relppp < relppend 1359130561Sobrien && (**relppp)->address >= rel_offset + addr_offset 1360130561Sobrien && ((**relppp)->address 1361130561Sobrien < rel_offset + addr_offset + octets / opb)) 136238889Sjdp info->flags = INSN_HAS_RELOC; 136338889Sjdp else 136477298Sobrien#endif 136538889Sjdp info->flags = 0; 136660484Sobrien 136760484Sobrien octets = (*disassemble_fn) (section->vma + addr_offset, info); 136833965Sjdp info->fprintf_func = (fprintf_ftype) fprintf; 136933965Sjdp info->stream = stdout; 137033965Sjdp if (info->bytes_per_line != 0) 137160484Sobrien octets_per_line = info->bytes_per_line; 137260484Sobrien if (octets < 0) 137360484Sobrien { 137460484Sobrien if (sfile.current != sfile.buffer) 137560484Sobrien printf ("%s\n", sfile.buffer); 137660484Sobrien free (sfile.buffer); 137760484Sobrien break; 137860484Sobrien } 137933965Sjdp } 138033965Sjdp else 138133965Sjdp { 138260484Sobrien bfd_vma j; 138333965Sjdp 138460484Sobrien octets = octets_per_line; 138560484Sobrien if (addr_offset + octets / opb > stop_offset) 138660484Sobrien octets = (stop_offset - addr_offset) * opb; 138733965Sjdp 138860484Sobrien for (j = addr_offset * opb; j < addr_offset * opb + octets; ++j) 138933965Sjdp { 139089857Sobrien if (ISPRINT (data[j])) 139160484Sobrien buf[j - addr_offset * opb] = data[j]; 139233965Sjdp else 139360484Sobrien buf[j - addr_offset * opb] = '.'; 139433965Sjdp } 139560484Sobrien buf[j - addr_offset * opb] = '\0'; 139633965Sjdp } 139733965Sjdp 139833965Sjdp if (prefix_addresses 139933965Sjdp ? show_raw_insn > 0 140033965Sjdp : show_raw_insn >= 0) 140133965Sjdp { 140260484Sobrien bfd_vma j; 140333965Sjdp 140433965Sjdp /* If ! prefix_addresses and ! wide_output, we print 1405130561Sobrien octets_per_line octets per line. */ 140660484Sobrien pb = octets; 140760484Sobrien if (pb > octets_per_line && ! prefix_addresses && ! wide_output) 140860484Sobrien pb = octets_per_line; 140933965Sjdp 141033965Sjdp if (info->bytes_per_chunk) 141133965Sjdp bpc = info->bytes_per_chunk; 141233965Sjdp else 141333965Sjdp bpc = 1; 141433965Sjdp 141560484Sobrien for (j = addr_offset * opb; j < addr_offset * opb + pb; j += bpc) 141633965Sjdp { 141733965Sjdp int k; 141833965Sjdp if (bpc > 1 && info->display_endian == BFD_ENDIAN_LITTLE) 141933965Sjdp { 142033965Sjdp for (k = bpc - 1; k >= 0; k--) 142133965Sjdp printf ("%02x", (unsigned) data[j + k]); 142233965Sjdp putchar (' '); 142333965Sjdp } 142433965Sjdp else 142533965Sjdp { 142633965Sjdp for (k = 0; k < bpc; k++) 142733965Sjdp printf ("%02x", (unsigned) data[j + k]); 142833965Sjdp putchar (' '); 142933965Sjdp } 143033965Sjdp } 143133965Sjdp 143260484Sobrien for (; pb < octets_per_line; pb += bpc) 143333965Sjdp { 143433965Sjdp int k; 143533965Sjdp 143633965Sjdp for (k = 0; k < bpc; k++) 143733965Sjdp printf (" "); 143833965Sjdp putchar (' '); 143933965Sjdp } 144033965Sjdp 144133965Sjdp /* Separate raw data from instruction by extra space. */ 144233965Sjdp if (insns) 144333965Sjdp putchar ('\t'); 144433965Sjdp else 144533965Sjdp printf (" "); 144633965Sjdp } 144733965Sjdp 144860484Sobrien if (! insns) 144960484Sobrien printf ("%s", buf); 145060484Sobrien else 145160484Sobrien { 145260484Sobrien printf ("%s", sfile.buffer); 145360484Sobrien free (sfile.buffer); 145460484Sobrien } 145533965Sjdp 145633965Sjdp if (prefix_addresses 145733965Sjdp ? show_raw_insn > 0 145833965Sjdp : show_raw_insn >= 0) 145933965Sjdp { 146060484Sobrien while (pb < octets) 146133965Sjdp { 146260484Sobrien bfd_vma j; 146333965Sjdp char *s; 146433965Sjdp 146533965Sjdp putchar ('\n'); 146660484Sobrien j = addr_offset * opb + pb; 146733965Sjdp 146889857Sobrien bfd_sprintf_vma (aux->abfd, buf, section->vma + j / opb); 146933965Sjdp for (s = buf + skip_addr_chars; *s == '0'; s++) 147033965Sjdp *s = ' '; 147133965Sjdp if (*s == '\0') 147233965Sjdp *--s = '0'; 147333965Sjdp printf ("%s:\t", buf + skip_addr_chars); 147433965Sjdp 147560484Sobrien pb += octets_per_line; 147660484Sobrien if (pb > octets) 147760484Sobrien pb = octets; 147860484Sobrien for (; j < addr_offset * opb + pb; j += bpc) 147933965Sjdp { 148033965Sjdp int k; 148133965Sjdp 148233965Sjdp if (bpc > 1 && info->display_endian == BFD_ENDIAN_LITTLE) 148333965Sjdp { 148433965Sjdp for (k = bpc - 1; k >= 0; k--) 148533965Sjdp printf ("%02x", (unsigned) data[j + k]); 148633965Sjdp putchar (' '); 148733965Sjdp } 148833965Sjdp else 148933965Sjdp { 149033965Sjdp for (k = 0; k < bpc; k++) 149133965Sjdp printf ("%02x", (unsigned) data[j + k]); 149233965Sjdp putchar (' '); 149333965Sjdp } 149433965Sjdp } 149533965Sjdp } 149633965Sjdp } 149733965Sjdp 149833965Sjdp if (!wide_output) 149933965Sjdp putchar ('\n'); 150033965Sjdp else 1501130561Sobrien need_nl = TRUE; 150233965Sjdp } 150333965Sjdp 1504130561Sobrien while ((*relppp) < relppend 1505130561Sobrien && (**relppp)->address < rel_offset + addr_offset + octets / opb) 150633965Sjdp { 1507130561Sobrien if (dump_reloc_info || dump_dynamic_reloc_info) 150833965Sjdp { 150933965Sjdp arelent *q; 151033965Sjdp 151133965Sjdp q = **relppp; 151233965Sjdp 151333965Sjdp if (wide_output) 151433965Sjdp putchar ('\t'); 151533965Sjdp else 151633965Sjdp printf ("\t\t\t"); 151733965Sjdp 1518130561Sobrien objdump_print_value (section->vma - rel_offset + q->address, 1519130561Sobrien info, TRUE); 152033965Sjdp 152133965Sjdp printf (": %s\t", q->howto->name); 152233965Sjdp 152333965Sjdp if (q->sym_ptr_ptr == NULL || *q->sym_ptr_ptr == NULL) 152433965Sjdp printf ("*unknown*"); 152533965Sjdp else 152633965Sjdp { 152733965Sjdp const char *sym_name; 152833965Sjdp 152933965Sjdp sym_name = bfd_asymbol_name (*q->sym_ptr_ptr); 153033965Sjdp if (sym_name != NULL && *sym_name != '\0') 153133965Sjdp objdump_print_symname (aux->abfd, info, *q->sym_ptr_ptr); 153233965Sjdp else 153333965Sjdp { 153433965Sjdp asection *sym_sec; 153533965Sjdp 153633965Sjdp sym_sec = bfd_get_section (*q->sym_ptr_ptr); 153733965Sjdp sym_name = bfd_get_section_name (aux->abfd, sym_sec); 153833965Sjdp if (sym_name == NULL || *sym_name == '\0') 153933965Sjdp sym_name = "*unknown*"; 154033965Sjdp printf ("%s", sym_name); 154133965Sjdp } 154233965Sjdp } 154333965Sjdp 154433965Sjdp if (q->addend) 154533965Sjdp { 154633965Sjdp printf ("+0x"); 1547130561Sobrien objdump_print_value (q->addend, info, TRUE); 154833965Sjdp } 154933965Sjdp 155033965Sjdp printf ("\n"); 1551130561Sobrien need_nl = FALSE; 155233965Sjdp } 1553130561Sobrien ++(*relppp); 155433965Sjdp } 155533965Sjdp 155633965Sjdp if (need_nl) 155733965Sjdp printf ("\n"); 155833965Sjdp 155960484Sobrien addr_offset += octets / opb; 156033965Sjdp } 156133965Sjdp} 156233965Sjdp 1563130561Sobrienstatic void 1564130561Sobriendisassemble_section (bfd *abfd, asection *section, void *info) 1565130561Sobrien{ 1566130561Sobrien struct disassemble_info * pinfo = (struct disassemble_info *) info; 1567130561Sobrien struct objdump_disasm_info * paux; 1568130561Sobrien unsigned int opb = pinfo->octets_per_byte; 1569130561Sobrien bfd_byte * data = NULL; 1570130561Sobrien bfd_size_type datasize = 0; 1571130561Sobrien arelent ** rel_pp = NULL; 1572130561Sobrien arelent ** rel_ppstart = NULL; 1573130561Sobrien arelent ** rel_ppend; 1574130561Sobrien unsigned long stop_offset; 1575130561Sobrien asymbol * sym = NULL; 1576130561Sobrien long place = 0; 1577130561Sobrien long rel_count; 1578130561Sobrien bfd_vma rel_offset; 1579130561Sobrien unsigned long addr_offset; 1580130561Sobrien 1581130561Sobrien /* Sections that do not contain machine 1582130561Sobrien code are not normally disassembled. */ 1583130561Sobrien if (! disassemble_all 1584130561Sobrien && only == NULL 1585130561Sobrien && (section->flags & SEC_CODE) == 0) 1586130561Sobrien return; 1587130561Sobrien 1588130561Sobrien if (! process_section_p (section)) 1589130561Sobrien return; 1590130561Sobrien 1591130561Sobrien datasize = bfd_get_section_size_before_reloc (section); 1592130561Sobrien if (datasize == 0) 1593130561Sobrien return; 1594130561Sobrien 1595130561Sobrien /* Decide which set of relocs to use. Load them if necessary. */ 1596130561Sobrien paux = (struct objdump_disasm_info *) pinfo->application_data; 1597130561Sobrien if (paux->dynrelbuf) 1598130561Sobrien { 1599130561Sobrien rel_pp = paux->dynrelbuf; 1600130561Sobrien rel_count = paux->dynrelcount; 1601130561Sobrien /* Dynamic reloc addresses are absolute, non-dynamic are section 1602130561Sobrien relative. REL_OFFSET specifies the reloc address corresponding 1603130561Sobrien to the start of this section. */ 1604130561Sobrien rel_offset = section->vma; 1605130561Sobrien } 1606130561Sobrien else 1607130561Sobrien { 1608130561Sobrien rel_count = 0; 1609130561Sobrien rel_pp = NULL; 1610130561Sobrien rel_offset = 0; 1611130561Sobrien 1612130561Sobrien if ((section->flags & SEC_RELOC) != 0 1613130561Sobrien#ifndef DISASSEMBLER_NEEDS_RELOCS 1614130561Sobrien && dump_reloc_info 1615130561Sobrien#endif 1616130561Sobrien ) 1617130561Sobrien { 1618130561Sobrien long relsize; 1619130561Sobrien 1620130561Sobrien relsize = bfd_get_reloc_upper_bound (abfd, section); 1621130561Sobrien if (relsize < 0) 1622130561Sobrien bfd_fatal (bfd_get_filename (abfd)); 1623130561Sobrien 1624130561Sobrien if (relsize > 0) 1625130561Sobrien { 1626130561Sobrien rel_ppstart = rel_pp = xmalloc (relsize); 1627130561Sobrien rel_count = bfd_canonicalize_reloc (abfd, section, rel_pp, syms); 1628130561Sobrien if (rel_count < 0) 1629130561Sobrien bfd_fatal (bfd_get_filename (abfd)); 1630130561Sobrien 1631130561Sobrien /* Sort the relocs by address. */ 1632130561Sobrien qsort (rel_pp, rel_count, sizeof (arelent *), compare_relocs); 1633130561Sobrien } 1634130561Sobrien } 1635130561Sobrien 1636130561Sobrien } 1637130561Sobrien rel_ppend = rel_pp + rel_count; 1638130561Sobrien 1639130561Sobrien data = xmalloc (datasize); 1640130561Sobrien 1641130561Sobrien bfd_get_section_contents (abfd, section, data, 0, datasize); 1642130561Sobrien 1643130561Sobrien paux->sec = section; 1644130561Sobrien pinfo->buffer = data; 1645130561Sobrien pinfo->buffer_vma = section->vma; 1646130561Sobrien pinfo->buffer_length = datasize; 1647130561Sobrien pinfo->section = section; 1648130561Sobrien 1649130561Sobrien if (start_address == (bfd_vma) -1 1650130561Sobrien || start_address < pinfo->buffer_vma) 1651130561Sobrien addr_offset = 0; 1652130561Sobrien else 1653130561Sobrien addr_offset = start_address - pinfo->buffer_vma; 1654130561Sobrien 1655130561Sobrien if (stop_address == (bfd_vma) -1) 1656130561Sobrien stop_offset = datasize / opb; 1657130561Sobrien else 1658130561Sobrien { 1659130561Sobrien if (stop_address < pinfo->buffer_vma) 1660130561Sobrien stop_offset = 0; 1661130561Sobrien else 1662130561Sobrien stop_offset = stop_address - pinfo->buffer_vma; 1663130561Sobrien if (stop_offset > pinfo->buffer_length / opb) 1664130561Sobrien stop_offset = pinfo->buffer_length / opb; 1665130561Sobrien } 1666130561Sobrien 1667130561Sobrien /* Skip over the relocs belonging to addresses below the 1668130561Sobrien start address. */ 1669130561Sobrien while (rel_pp < rel_ppend 1670130561Sobrien && (*rel_pp)->address < rel_offset + addr_offset) 1671130561Sobrien ++rel_pp; 1672130561Sobrien 1673130561Sobrien printf (_("Disassembly of section %s:\n"), section->name); 1674130561Sobrien 1675130561Sobrien /* Find the nearest symbol forwards from our current position. */ 1676130561Sobrien paux->require_sec = TRUE; 1677130561Sobrien sym = find_symbol_for_address (section->vma + addr_offset, info, &place); 1678130561Sobrien paux->require_sec = FALSE; 1679130561Sobrien 1680130561Sobrien /* Disassemble a block of instructions up to the address associated with 1681130561Sobrien the symbol we have just found. Then print the symbol and find the 1682130561Sobrien next symbol on. Repeat until we have disassembled the entire section 1683130561Sobrien or we have reached the end of the address range we are interested in. */ 1684130561Sobrien while (addr_offset < stop_offset) 1685130561Sobrien { 1686130561Sobrien bfd_vma addr; 1687130561Sobrien asymbol *nextsym; 1688130561Sobrien unsigned long nextstop_offset; 1689130561Sobrien bfd_boolean insns; 1690130561Sobrien 1691130561Sobrien addr = section->vma + addr_offset; 1692130561Sobrien 1693130561Sobrien if (sym != NULL && bfd_asymbol_value (sym) <= addr) 1694130561Sobrien { 1695130561Sobrien int x; 1696130561Sobrien 1697130561Sobrien for (x = place; 1698130561Sobrien (x < sorted_symcount 1699130561Sobrien && (bfd_asymbol_value (sorted_syms[x]) <= addr)); 1700130561Sobrien ++x) 1701130561Sobrien continue; 1702130561Sobrien 1703130561Sobrien pinfo->symbols = sorted_syms + place; 1704130561Sobrien pinfo->num_symbols = x - place; 1705130561Sobrien } 1706130561Sobrien else 1707130561Sobrien { 1708130561Sobrien pinfo->symbols = NULL; 1709130561Sobrien pinfo->num_symbols = 0; 1710130561Sobrien } 1711130561Sobrien 1712130561Sobrien if (! prefix_addresses) 1713130561Sobrien { 1714130561Sobrien pinfo->fprintf_func (pinfo->stream, "\n"); 1715130561Sobrien objdump_print_addr_with_sym (abfd, section, sym, addr, 1716130561Sobrien pinfo, FALSE); 1717130561Sobrien pinfo->fprintf_func (pinfo->stream, ":\n"); 1718130561Sobrien } 1719130561Sobrien 1720130561Sobrien if (sym != NULL && bfd_asymbol_value (sym) > addr) 1721130561Sobrien nextsym = sym; 1722130561Sobrien else if (sym == NULL) 1723130561Sobrien nextsym = NULL; 1724130561Sobrien else 1725130561Sobrien { 1726130561Sobrien#define is_valid_next_sym(SYM) \ 1727130561Sobrien ((SYM)->section == section \ 1728130561Sobrien && (bfd_asymbol_value (SYM) > bfd_asymbol_value (sym)) \ 1729130561Sobrien && pinfo->symbol_is_valid (SYM, pinfo)) 1730130561Sobrien 1731130561Sobrien /* Search forward for the next appropriate symbol in 1732130561Sobrien SECTION. Note that all the symbols are sorted 1733130561Sobrien together into one big array, and that some sections 1734130561Sobrien may have overlapping addresses. */ 1735130561Sobrien while (place < sorted_symcount 1736130561Sobrien && ! is_valid_next_sym (sorted_syms [place])) 1737130561Sobrien ++place; 1738130561Sobrien 1739130561Sobrien if (place >= sorted_symcount) 1740130561Sobrien nextsym = NULL; 1741130561Sobrien else 1742130561Sobrien nextsym = sorted_syms[place]; 1743130561Sobrien } 1744130561Sobrien 1745130561Sobrien if (sym != NULL && bfd_asymbol_value (sym) > addr) 1746130561Sobrien nextstop_offset = bfd_asymbol_value (sym) - section->vma; 1747130561Sobrien else if (nextsym == NULL) 1748130561Sobrien nextstop_offset = stop_offset; 1749130561Sobrien else 1750130561Sobrien nextstop_offset = bfd_asymbol_value (nextsym) - section->vma; 1751130561Sobrien 1752130561Sobrien if (nextstop_offset > stop_offset) 1753130561Sobrien nextstop_offset = stop_offset; 1754130561Sobrien 1755130561Sobrien /* If a symbol is explicitly marked as being an object 1756130561Sobrien rather than a function, just dump the bytes without 1757130561Sobrien disassembling them. */ 1758130561Sobrien if (disassemble_all 1759130561Sobrien || sym == NULL 1760130561Sobrien || bfd_asymbol_value (sym) > addr 1761130561Sobrien || ((sym->flags & BSF_OBJECT) == 0 1762130561Sobrien && (strstr (bfd_asymbol_name (sym), "gnu_compiled") 1763130561Sobrien == NULL) 1764130561Sobrien && (strstr (bfd_asymbol_name (sym), "gcc2_compiled") 1765130561Sobrien == NULL)) 1766130561Sobrien || (sym->flags & BSF_FUNCTION) != 0) 1767130561Sobrien insns = TRUE; 1768130561Sobrien else 1769130561Sobrien insns = FALSE; 1770130561Sobrien 1771130561Sobrien disassemble_bytes (pinfo, paux->disassemble_fn, insns, data, 1772130561Sobrien addr_offset, nextstop_offset, 1773130561Sobrien rel_offset, &rel_pp, rel_ppend); 1774130561Sobrien 1775130561Sobrien addr_offset = nextstop_offset; 1776130561Sobrien sym = nextsym; 1777130561Sobrien } 1778130561Sobrien 1779130561Sobrien free (data); 1780130561Sobrien 1781130561Sobrien if (rel_ppstart != NULL) 1782130561Sobrien free (rel_ppstart); 1783130561Sobrien} 1784130561Sobrien 178533965Sjdp/* Disassemble the contents of an object file. */ 178633965Sjdp 178733965Sjdpstatic void 1788130561Sobriendisassemble_data (bfd *abfd) 178933965Sjdp{ 179033965Sjdp struct disassemble_info disasm_info; 179133965Sjdp struct objdump_disasm_info aux; 179233965Sjdp 179333965Sjdp print_files = NULL; 179433965Sjdp prev_functionname = NULL; 179533965Sjdp prev_line = -1; 179633965Sjdp 179733965Sjdp /* We make a copy of syms to sort. We don't want to sort syms 179833965Sjdp because that will screw up the relocs. */ 1799130561Sobrien sorted_syms = xmalloc (symcount * sizeof (asymbol *)); 180033965Sjdp memcpy (sorted_syms, syms, symcount * sizeof (asymbol *)); 180133965Sjdp 180233965Sjdp sorted_symcount = remove_useless_symbols (sorted_syms, symcount); 180333965Sjdp 1804130561Sobrien /* Sort the symbols into section and symbol order. */ 180533965Sjdp qsort (sorted_syms, sorted_symcount, sizeof (asymbol *), compare_symbols); 180633965Sjdp 1807130561Sobrien init_disassemble_info (&disasm_info, stdout, (fprintf_ftype) fprintf); 1808130561Sobrien 1809130561Sobrien disasm_info.application_data = (void *) &aux; 181033965Sjdp aux.abfd = abfd; 1811130561Sobrien aux.require_sec = FALSE; 1812130561Sobrien aux.dynrelbuf = NULL; 1813130561Sobrien aux.dynrelcount = 0; 1814130561Sobrien 181533965Sjdp disasm_info.print_address_func = objdump_print_address; 181638889Sjdp disasm_info.symbol_at_address_func = objdump_symbol_at_address; 181733965Sjdp 1818130561Sobrien if (machine != NULL) 181933965Sjdp { 182033965Sjdp const bfd_arch_info_type *info = bfd_scan_arch (machine); 1821130561Sobrien 182233965Sjdp if (info == NULL) 1823130561Sobrien fatal (_("Can't use supplied machine %s"), machine); 1824130561Sobrien 182533965Sjdp abfd->arch_info = info; 182633965Sjdp } 182733965Sjdp 182833965Sjdp if (endian != BFD_ENDIAN_UNKNOWN) 182933965Sjdp { 183033965Sjdp struct bfd_target *xvec; 183133965Sjdp 1832130561Sobrien xvec = xmalloc (sizeof (struct bfd_target)); 183333965Sjdp memcpy (xvec, abfd->xvec, sizeof (struct bfd_target)); 183433965Sjdp xvec->byteorder = endian; 183533965Sjdp abfd->xvec = xvec; 183633965Sjdp } 183733965Sjdp 1838130561Sobrien /* Use libopcodes to locate a suitable disassembler. */ 1839130561Sobrien aux.disassemble_fn = disassembler (abfd); 1840130561Sobrien if (!aux.disassemble_fn) 184133965Sjdp { 184260484Sobrien non_fatal (_("Can't disassemble for architecture %s\n"), 184360484Sobrien bfd_printable_arch_mach (bfd_get_arch (abfd), 0)); 184460484Sobrien exit_status = 1; 184533965Sjdp return; 184633965Sjdp } 184733965Sjdp 184833965Sjdp disasm_info.flavour = bfd_get_flavour (abfd); 184933965Sjdp disasm_info.arch = bfd_get_arch (abfd); 185033965Sjdp disasm_info.mach = bfd_get_mach (abfd); 185160484Sobrien disasm_info.disassembler_options = disassembler_options; 1852130561Sobrien disasm_info.octets_per_byte = bfd_octets_per_byte (abfd); 1853104834Sobrien 185433965Sjdp if (bfd_big_endian (abfd)) 185560484Sobrien disasm_info.display_endian = disasm_info.endian = BFD_ENDIAN_BIG; 185633965Sjdp else if (bfd_little_endian (abfd)) 185760484Sobrien disasm_info.display_endian = disasm_info.endian = BFD_ENDIAN_LITTLE; 185833965Sjdp else 185933965Sjdp /* ??? Aborting here seems too drastic. We could default to big or little 186033965Sjdp instead. */ 186133965Sjdp disasm_info.endian = BFD_ENDIAN_UNKNOWN; 186233965Sjdp 1863130561Sobrien /* Allow the target to customize the info structure. */ 1864130561Sobrien disassemble_init_for_target (& disasm_info); 1865130561Sobrien 1866130561Sobrien /* Pre-load the dynamic relocs if we are going 1867130561Sobrien to be dumping them along with the disassembly. */ 1868130561Sobrien if (dump_dynamic_reloc_info) 186933965Sjdp { 1870130561Sobrien long relsize = bfd_get_dynamic_reloc_upper_bound (abfd); 1871130561Sobrien 1872130561Sobrien if (relsize < 0) 1873130561Sobrien bfd_fatal (bfd_get_filename (abfd)); 187433965Sjdp 1875130561Sobrien if (relsize > 0) 187633965Sjdp { 1877130561Sobrien aux.dynrelbuf = xmalloc (relsize); 1878130561Sobrien aux.dynrelcount = bfd_canonicalize_dynamic_reloc (abfd, 1879130561Sobrien aux.dynrelbuf, 1880130561Sobrien dynsyms); 1881130561Sobrien if (aux.dynrelcount < 0) 188233965Sjdp bfd_fatal (bfd_get_filename (abfd)); 188333965Sjdp 1884130561Sobrien /* Sort the relocs by address. */ 1885130561Sobrien qsort (aux.dynrelbuf, aux.dynrelcount, sizeof (arelent *), 1886130561Sobrien compare_relocs); 188733965Sjdp } 1888130561Sobrien } 188933965Sjdp 1890130561Sobrien bfd_map_over_sections (abfd, disassemble_section, & disasm_info); 189133965Sjdp 1892130561Sobrien if (aux.dynrelbuf != NULL) 1893130561Sobrien free (aux.dynrelbuf); 189433965Sjdp free (sorted_syms); 189533965Sjdp} 189633965Sjdp 1897130561Sobrien/* Read ABFD's stabs section STABSECT_NAME, and return a pointer to 1898130561Sobrien it. Return NULL on failure. */ 189933965Sjdp 1900130561Sobrienstatic char * 1901130561Sobrienread_section_stabs (bfd *abfd, const char *sect_name, bfd_size_type *size_ptr) 190233965Sjdp{ 1903130561Sobrien asection *stabsect; 1904130561Sobrien bfd_size_type size; 1905130561Sobrien char *contents; 190633965Sjdp 1907130561Sobrien stabsect = bfd_get_section_by_name (abfd, sect_name); 1908130561Sobrien if (stabsect == NULL) 190933965Sjdp { 1910130561Sobrien printf (_("No %s section present\n\n"), sect_name); 1911130561Sobrien return FALSE; 191233965Sjdp } 191333965Sjdp 1914130561Sobrien size = bfd_section_size (abfd, stabsect); 1915130561Sobrien contents = xmalloc (size); 1916104834Sobrien 1917130561Sobrien if (! bfd_get_section_contents (abfd, stabsect, contents, 0, size)) 191833965Sjdp { 191960484Sobrien non_fatal (_("Reading %s section of %s failed: %s"), 1920130561Sobrien sect_name, bfd_get_filename (abfd), 192160484Sobrien bfd_errmsg (bfd_get_error ())); 1922130561Sobrien free (contents); 192360484Sobrien exit_status = 1; 1924130561Sobrien return NULL; 192533965Sjdp } 192633965Sjdp 1927130561Sobrien *size_ptr = size; 192833965Sjdp 1929130561Sobrien return contents; 193033965Sjdp} 193133965Sjdp 193233965Sjdp/* Stabs entries use a 12 byte format: 193333965Sjdp 4 byte string table index 193433965Sjdp 1 byte stab type 193533965Sjdp 1 byte stab other field 193633965Sjdp 2 byte stab desc field 193733965Sjdp 4 byte stab value 193833965Sjdp FIXME: This will have to change for a 64 bit object format. */ 193933965Sjdp 1940130561Sobrien#define STRDXOFF (0) 1941130561Sobrien#define TYPEOFF (4) 1942130561Sobrien#define OTHEROFF (5) 1943130561Sobrien#define DESCOFF (6) 1944130561Sobrien#define VALOFF (8) 194533965Sjdp#define STABSIZE (12) 194633965Sjdp 194733965Sjdp/* Print ABFD's stabs section STABSECT_NAME (in `stabs'), 194833965Sjdp using string table section STRSECT_NAME (in `strtab'). */ 194933965Sjdp 195033965Sjdpstatic void 1951130561Sobrienprint_section_stabs (bfd *abfd, 1952130561Sobrien const char *stabsect_name, 1953130561Sobrien unsigned *string_offset_ptr) 195433965Sjdp{ 195533965Sjdp int i; 1956130561Sobrien unsigned file_string_table_offset = 0; 1957130561Sobrien unsigned next_file_string_table_offset = *string_offset_ptr; 195833965Sjdp bfd_byte *stabp, *stabs_end; 195933965Sjdp 196033965Sjdp stabp = stabs; 196133965Sjdp stabs_end = stabp + stab_size; 196233965Sjdp 196360484Sobrien printf (_("Contents of %s section:\n\n"), stabsect_name); 196433965Sjdp printf ("Symnum n_type n_othr n_desc n_value n_strx String\n"); 196533965Sjdp 196633965Sjdp /* Loop through all symbols and print them. 196733965Sjdp 196833965Sjdp We start the index at -1 because there is a dummy symbol on 196933965Sjdp the front of stabs-in-{coff,elf} sections that supplies sizes. */ 197033965Sjdp for (i = -1; stabp < stabs_end; stabp += STABSIZE, i++) 197133965Sjdp { 197233965Sjdp const char *name; 197333965Sjdp unsigned long strx; 197433965Sjdp unsigned char type, other; 197533965Sjdp unsigned short desc; 197633965Sjdp bfd_vma value; 197733965Sjdp 197833965Sjdp strx = bfd_h_get_32 (abfd, stabp + STRDXOFF); 197933965Sjdp type = bfd_h_get_8 (abfd, stabp + TYPEOFF); 198033965Sjdp other = bfd_h_get_8 (abfd, stabp + OTHEROFF); 198133965Sjdp desc = bfd_h_get_16 (abfd, stabp + DESCOFF); 198233965Sjdp value = bfd_h_get_32 (abfd, stabp + VALOFF); 198333965Sjdp 198433965Sjdp printf ("\n%-6d ", i); 198533965Sjdp /* Either print the stab name, or, if unnamed, print its number 1986104834Sobrien again (makes consistent formatting for tools like awk). */ 198733965Sjdp name = bfd_get_stab_name (type); 198833965Sjdp if (name != NULL) 198933965Sjdp printf ("%-6s", name); 199033965Sjdp else if (type == N_UNDF) 199133965Sjdp printf ("HdrSym"); 199233965Sjdp else 199333965Sjdp printf ("%-6d", type); 199433965Sjdp printf (" %-6d %-6d ", other, desc); 199589857Sobrien bfd_printf_vma (abfd, value); 199633965Sjdp printf (" %-6lu", strx); 199733965Sjdp 199833965Sjdp /* Symbols with type == 0 (N_UNDF) specify the length of the 199933965Sjdp string table associated with this file. We use that info 200033965Sjdp to know how to relocate the *next* file's string table indices. */ 200133965Sjdp if (type == N_UNDF) 200233965Sjdp { 200333965Sjdp file_string_table_offset = next_file_string_table_offset; 200433965Sjdp next_file_string_table_offset += value; 200533965Sjdp } 200633965Sjdp else 200733965Sjdp { 200833965Sjdp /* Using the (possibly updated) string table offset, print the 200933965Sjdp string (if any) associated with this symbol. */ 201033965Sjdp if ((strx + file_string_table_offset) < stabstr_size) 201133965Sjdp printf (" %s", &strtab[strx + file_string_table_offset]); 201233965Sjdp else 201333965Sjdp printf (" *"); 201433965Sjdp } 201533965Sjdp } 201633965Sjdp printf ("\n\n"); 2017130561Sobrien *string_offset_ptr = next_file_string_table_offset; 201833965Sjdp} 201933965Sjdp 2020130561Sobrientypedef struct 2021130561Sobrien{ 2022130561Sobrien const char * section_name; 2023130561Sobrien const char * string_section_name; 2024130561Sobrien unsigned string_offset; 2025130561Sobrien} 2026130561Sobrienstab_section_names; 2027130561Sobrien 202833965Sjdpstatic void 2029130561Sobrienfind_stabs_section (bfd *abfd, asection *section, void *names) 203033965Sjdp{ 2031130561Sobrien int len; 2032130561Sobrien stab_section_names * sought = (stab_section_names *) names; 203333965Sjdp 203433965Sjdp /* Check for section names for which stabsect_name is a prefix, to 2035130561Sobrien handle .stab.N, etc. */ 2036130561Sobrien len = strlen (sought->section_name); 2037130561Sobrien 2038130561Sobrien /* If the prefix matches, and the files section name ends with a 2039130561Sobrien nul or a digit, then we match. I.e., we want either an exact 2040130561Sobrien match or a section followed by a number. */ 2041130561Sobrien if (strncmp (sought->section_name, section->name, len) == 0 2042130561Sobrien && (section->name[len] == 0 2043130561Sobrien || (section->name[len] == '.' && ISDIGIT (section->name[len + 1])))) 204433965Sjdp { 2045130561Sobrien if (strtab == NULL) 2046130561Sobrien strtab = read_section_stabs (abfd, sought->string_section_name, 2047130561Sobrien &stabstr_size); 2048130561Sobrien 2049130561Sobrien if (strtab) 205033965Sjdp { 2051130561Sobrien stabs = read_section_stabs (abfd, section->name, &stab_size); 2052130561Sobrien if (stabs) 2053130561Sobrien print_section_stabs (abfd, section->name, &sought->string_offset); 205433965Sjdp } 205533965Sjdp } 205633965Sjdp} 2057130561Sobrien 2058130561Sobrienstatic void 2059130561Sobriendump_stabs_section (bfd *abfd, char *stabsect_name, char *strsect_name) 2060130561Sobrien{ 2061130561Sobrien stab_section_names s; 2062130561Sobrien 2063130561Sobrien s.section_name = stabsect_name; 2064130561Sobrien s.string_section_name = strsect_name; 2065130561Sobrien s.string_offset = 0; 2066130561Sobrien 2067130561Sobrien bfd_map_over_sections (abfd, find_stabs_section, & s); 2068130561Sobrien 2069130561Sobrien free (strtab); 2070130561Sobrien strtab = NULL; 2071130561Sobrien} 2072130561Sobrien 2073130561Sobrien/* Dump the any sections containing stabs debugging information. */ 2074130561Sobrien 2075130561Sobrienstatic void 2076130561Sobriendump_stabs (bfd *abfd) 2077130561Sobrien{ 2078130561Sobrien dump_stabs_section (abfd, ".stab", ".stabstr"); 2079130561Sobrien dump_stabs_section (abfd, ".stab.excl", ".stab.exclstr"); 2080130561Sobrien dump_stabs_section (abfd, ".stab.index", ".stab.indexstr"); 2081130561Sobrien dump_stabs_section (abfd, "$GDB_SYMBOLS$", "$GDB_STRINGS$"); 2082130561Sobrien} 208333965Sjdp 208433965Sjdpstatic void 2085130561Sobriendump_bfd_header (bfd *abfd) 208633965Sjdp{ 208733965Sjdp char *comma = ""; 208833965Sjdp 208960484Sobrien printf (_("architecture: %s, "), 209033965Sjdp bfd_printable_arch_mach (bfd_get_arch (abfd), 209133965Sjdp bfd_get_mach (abfd))); 209260484Sobrien printf (_("flags 0x%08x:\n"), abfd->flags); 209333965Sjdp 209433965Sjdp#define PF(x, y) if (abfd->flags & x) {printf("%s%s", comma, y); comma=", ";} 209533965Sjdp PF (HAS_RELOC, "HAS_RELOC"); 209633965Sjdp PF (EXEC_P, "EXEC_P"); 209733965Sjdp PF (HAS_LINENO, "HAS_LINENO"); 209833965Sjdp PF (HAS_DEBUG, "HAS_DEBUG"); 209933965Sjdp PF (HAS_SYMS, "HAS_SYMS"); 210033965Sjdp PF (HAS_LOCALS, "HAS_LOCALS"); 210133965Sjdp PF (DYNAMIC, "DYNAMIC"); 210233965Sjdp PF (WP_TEXT, "WP_TEXT"); 210333965Sjdp PF (D_PAGED, "D_PAGED"); 210433965Sjdp PF (BFD_IS_RELAXABLE, "BFD_IS_RELAXABLE"); 2105130561Sobrien PF (HAS_LOAD_PAGE, "HAS_LOAD_PAGE"); 210660484Sobrien printf (_("\nstart address 0x")); 210789857Sobrien bfd_printf_vma (abfd, abfd->start_address); 210833965Sjdp printf ("\n"); 210933965Sjdp} 2110130561Sobrien 211133965Sjdp 211233965Sjdpstatic void 2113130561Sobriendump_bfd_private_header (bfd *abfd) 211433965Sjdp{ 211533965Sjdp bfd_print_private_bfd_data (abfd, stdout); 211633965Sjdp} 211733965Sjdp 2118130561Sobrien 2119130561Sobrien/* Display a section in hexadecimal format with associated characters. 2120130561Sobrien Each line prefixed by the zero padded address. */ 212160484Sobrien 212233965Sjdpstatic void 2123130561Sobriendump_section (bfd *abfd, asection *section, void *dummy ATTRIBUTE_UNUSED) 212433965Sjdp{ 2125130561Sobrien bfd_byte *data = 0; 2126130561Sobrien bfd_size_type datasize; 2127130561Sobrien bfd_size_type addr_offset; 2128130561Sobrien bfd_size_type start_offset; 2129130561Sobrien bfd_size_type stop_offset; 2130130561Sobrien unsigned int opb = bfd_octets_per_byte (abfd); 2131130561Sobrien /* Bytes per line. */ 2132130561Sobrien const int onaline = 16; 2133130561Sobrien char buf[64]; 2134130561Sobrien int count; 2135130561Sobrien int width; 213633965Sjdp 2137130561Sobrien if ((section->flags & SEC_HAS_CONTENTS) == 0) 2138130561Sobrien return; 213933965Sjdp 2140130561Sobrien if (! process_section_p (section)) 2141130561Sobrien return; 2142130561Sobrien 2143130561Sobrien if ((datasize = bfd_section_size (abfd, section)) == 0) 2144130561Sobrien return; 214533965Sjdp 2146130561Sobrien printf (_("Contents of section %s:\n"), section->name); 214733965Sjdp 2148130561Sobrien data = xmalloc (datasize); 214960484Sobrien 2150130561Sobrien bfd_get_section_contents (abfd, section, data, 0, datasize); 215160484Sobrien 2152130561Sobrien /* Compute the address range to display. */ 2153130561Sobrien if (start_address == (bfd_vma) -1 2154130561Sobrien || start_address < section->vma) 2155130561Sobrien start_offset = 0; 2156130561Sobrien else 2157130561Sobrien start_offset = start_address - section->vma; 215860484Sobrien 2159130561Sobrien if (stop_address == (bfd_vma) -1) 2160130561Sobrien stop_offset = datasize / opb; 2161130561Sobrien else 216260484Sobrien { 2163130561Sobrien if (stop_address < section->vma) 2164130561Sobrien stop_offset = 0; 2165130561Sobrien else 2166130561Sobrien stop_offset = stop_address - section->vma; 216760484Sobrien 2168130561Sobrien if (stop_offset > datasize / opb) 2169130561Sobrien stop_offset = datasize / opb; 217060484Sobrien } 217160484Sobrien 2172130561Sobrien width = 4; 217360484Sobrien 2174130561Sobrien bfd_sprintf_vma (abfd, buf, start_offset + section->vma); 2175130561Sobrien if (strlen (buf) >= sizeof (buf)) 2176130561Sobrien abort (); 217760484Sobrien 2178130561Sobrien count = 0; 2179130561Sobrien while (buf[count] == '0' && buf[count+1] != '\0') 2180130561Sobrien count++; 2181130561Sobrien count = strlen (buf) - count; 2182130561Sobrien if (count > width) 2183130561Sobrien width = count; 218433965Sjdp 2185130561Sobrien bfd_sprintf_vma (abfd, buf, stop_offset + section->vma - 1); 2186130561Sobrien if (strlen (buf) >= sizeof (buf)) 2187130561Sobrien abort (); 218833965Sjdp 2189130561Sobrien count = 0; 2190130561Sobrien while (buf[count] == '0' && buf[count+1] != '\0') 2191130561Sobrien count++; 2192130561Sobrien count = strlen (buf) - count; 2193130561Sobrien if (count > width) 2194130561Sobrien width = count; 2195130561Sobrien 2196130561Sobrien for (addr_offset = start_offset; 2197130561Sobrien addr_offset < stop_offset; addr_offset += onaline / opb) 219833965Sjdp { 2199130561Sobrien bfd_size_type j; 220033965Sjdp 2201130561Sobrien bfd_sprintf_vma (abfd, buf, (addr_offset + section->vma)); 2202130561Sobrien count = strlen (buf); 2203130561Sobrien if ((size_t) count >= sizeof (buf)) 2204130561Sobrien abort (); 2205130561Sobrien 2206130561Sobrien putchar (' '); 2207130561Sobrien while (count < width) 220833965Sjdp { 2209130561Sobrien putchar ('0'); 2210130561Sobrien count++; 2211130561Sobrien } 2212130561Sobrien fputs (buf + count - width, stdout); 2213130561Sobrien putchar (' '); 221433965Sjdp 2215130561Sobrien for (j = addr_offset * opb; 2216130561Sobrien j < addr_offset * opb + onaline; j++) 2217130561Sobrien { 2218130561Sobrien if (j < stop_offset * opb) 2219130561Sobrien printf ("%02x", (unsigned) (data[j])); 2220130561Sobrien else 2221130561Sobrien printf (" "); 2222130561Sobrien if ((j & 3) == 3) 2223130561Sobrien printf (" "); 2224130561Sobrien } 222533965Sjdp 2226130561Sobrien printf (" "); 2227130561Sobrien for (j = addr_offset * opb; 2228130561Sobrien j < addr_offset * opb + onaline; j++) 2229130561Sobrien { 2230130561Sobrien if (j >= stop_offset * opb) 2231130561Sobrien printf (" "); 2232130561Sobrien else 2233130561Sobrien printf ("%c", ISPRINT (data[j]) ? data[j] : '.'); 223433965Sjdp } 2235130561Sobrien putchar ('\n'); 223633965Sjdp } 2237130561Sobrien free (data); 223833965Sjdp} 223933965Sjdp 2240130561Sobrien/* Actually display the various requested regions. */ 2241130561Sobrien 224233965Sjdpstatic void 2243130561Sobriendump_data (bfd *abfd) 224433965Sjdp{ 2245130561Sobrien bfd_map_over_sections (abfd, dump_section, NULL); 2246130561Sobrien} 224733965Sjdp 2248130561Sobrien/* Should perhaps share code and display with nm? */ 224933965Sjdp 225033965Sjdpstatic void 2251130561Sobriendump_symbols (bfd *abfd ATTRIBUTE_UNUSED, bfd_boolean dynamic) 225233965Sjdp{ 225333965Sjdp asymbol **current; 225433965Sjdp long max; 225533965Sjdp long count; 225633965Sjdp 225733965Sjdp if (dynamic) 225833965Sjdp { 225933965Sjdp current = dynsyms; 226033965Sjdp max = dynsymcount; 226133965Sjdp printf ("DYNAMIC SYMBOL TABLE:\n"); 226233965Sjdp } 226333965Sjdp else 226433965Sjdp { 226533965Sjdp current = syms; 226633965Sjdp max = symcount; 226733965Sjdp printf ("SYMBOL TABLE:\n"); 226833965Sjdp } 226933965Sjdp 2270130561Sobrien if (max == 0) 2271130561Sobrien printf (_("no symbols\n")); 2272130561Sobrien 227333965Sjdp for (count = 0; count < max; count++) 227433965Sjdp { 2275130561Sobrien bfd *cur_bfd; 2276130561Sobrien 2277130561Sobrien if (*current == NULL) 2278130561Sobrien printf (_("no information for the %ld'th symbol"), count); 2279130561Sobrien 2280130561Sobrien else if ((cur_bfd = bfd_asymbol_bfd (*current)) == NULL) 2281130561Sobrien printf (_("could not determine the type of the %ld'th symbol"), 2282130561Sobrien count); 2283130561Sobrien 2284130561Sobrien else 228533965Sjdp { 2286130561Sobrien const char *name = (*current)->name; 228733965Sjdp 2288130561Sobrien if (do_demangle && name != NULL && *name != '\0') 228933965Sjdp { 229033965Sjdp char *alloc; 229133965Sjdp 2292130561Sobrien /* If we want to demangle the name, we demangle it 2293130561Sobrien here, and temporarily clobber it while calling 2294130561Sobrien bfd_print_symbol. FIXME: This is a gross hack. */ 2295130561Sobrien alloc = demangle (cur_bfd, name); 2296130561Sobrien (*current)->name = alloc; 229733965Sjdp bfd_print_symbol (cur_bfd, stdout, *current, 229833965Sjdp bfd_print_symbol_all); 229933965Sjdp (*current)->name = name; 2300130561Sobrien free (alloc); 230133965Sjdp } 230233965Sjdp else 2303130561Sobrien bfd_print_symbol (cur_bfd, stdout, *current, 2304130561Sobrien bfd_print_symbol_all); 230533965Sjdp } 230633965Sjdp 2307130561Sobrien printf ("\n"); 2308130561Sobrien current++; 230933965Sjdp } 2310130561Sobrien printf ("\n\n"); 231133965Sjdp} 2312130561Sobrien 231333965Sjdpstatic void 2314130561Sobriendump_reloc_set (bfd *abfd, asection *sec, arelent **relpp, long relcount) 231533965Sjdp{ 231633965Sjdp arelent **p; 231733965Sjdp char *last_filename, *last_functionname; 231833965Sjdp unsigned int last_line; 231933965Sjdp 232033965Sjdp /* Get column headers lined up reasonably. */ 232133965Sjdp { 232233965Sjdp static int width; 2323130561Sobrien 232433965Sjdp if (width == 0) 232533965Sjdp { 232633965Sjdp char buf[30]; 2327130561Sobrien 232889857Sobrien bfd_sprintf_vma (abfd, buf, (bfd_vma) -1); 232933965Sjdp width = strlen (buf) - 7; 233033965Sjdp } 233133965Sjdp printf ("OFFSET %*s TYPE %*s VALUE \n", width, "", 12, ""); 233233965Sjdp } 233333965Sjdp 233433965Sjdp last_filename = NULL; 233533965Sjdp last_functionname = NULL; 233633965Sjdp last_line = 0; 233733965Sjdp 2338130561Sobrien for (p = relpp; relcount && *p != NULL; p++, relcount--) 233933965Sjdp { 234033965Sjdp arelent *q = *p; 234133965Sjdp const char *filename, *functionname; 234233965Sjdp unsigned int line; 234333965Sjdp const char *sym_name; 234433965Sjdp const char *section_name; 234533965Sjdp 234633965Sjdp if (start_address != (bfd_vma) -1 234733965Sjdp && q->address < start_address) 234833965Sjdp continue; 234933965Sjdp if (stop_address != (bfd_vma) -1 235033965Sjdp && q->address > stop_address) 235133965Sjdp continue; 235233965Sjdp 235333965Sjdp if (with_line_numbers 235433965Sjdp && sec != NULL 235533965Sjdp && bfd_find_nearest_line (abfd, sec, syms, q->address, 235633965Sjdp &filename, &functionname, &line)) 235733965Sjdp { 235833965Sjdp if (functionname != NULL 235933965Sjdp && (last_functionname == NULL 236033965Sjdp || strcmp (functionname, last_functionname) != 0)) 236133965Sjdp { 236233965Sjdp printf ("%s():\n", functionname); 236333965Sjdp if (last_functionname != NULL) 236433965Sjdp free (last_functionname); 236533965Sjdp last_functionname = xstrdup (functionname); 236633965Sjdp } 2367130561Sobrien 236833965Sjdp if (line > 0 236933965Sjdp && (line != last_line 237033965Sjdp || (filename != NULL 237133965Sjdp && last_filename != NULL 237233965Sjdp && strcmp (filename, last_filename) != 0))) 237333965Sjdp { 237433965Sjdp printf ("%s:%u\n", filename == NULL ? "???" : filename, line); 237533965Sjdp last_line = line; 237633965Sjdp if (last_filename != NULL) 237733965Sjdp free (last_filename); 237833965Sjdp if (filename == NULL) 237933965Sjdp last_filename = NULL; 238033965Sjdp else 238133965Sjdp last_filename = xstrdup (filename); 238233965Sjdp } 238333965Sjdp } 238433965Sjdp 238533965Sjdp if (q->sym_ptr_ptr && *q->sym_ptr_ptr) 238633965Sjdp { 238733965Sjdp sym_name = (*(q->sym_ptr_ptr))->name; 238833965Sjdp section_name = (*(q->sym_ptr_ptr))->section->name; 238933965Sjdp } 239033965Sjdp else 239133965Sjdp { 239233965Sjdp sym_name = NULL; 239333965Sjdp section_name = NULL; 239433965Sjdp } 2395130561Sobrien 239633965Sjdp if (sym_name) 239733965Sjdp { 239889857Sobrien bfd_printf_vma (abfd, q->address); 239960484Sobrien if (q->howto->name) 240060484Sobrien printf (" %-16s ", q->howto->name); 240160484Sobrien else 240260484Sobrien printf (" %-16d ", q->howto->type); 2403130561Sobrien objdump_print_symname (abfd, NULL, *q->sym_ptr_ptr); 240433965Sjdp } 240533965Sjdp else 240633965Sjdp { 2407130561Sobrien if (section_name == NULL) 240833965Sjdp section_name = "*unknown*"; 240989857Sobrien bfd_printf_vma (abfd, q->address); 241033965Sjdp printf (" %-16s [%s]", 241133965Sjdp q->howto->name, 241233965Sjdp section_name); 241333965Sjdp } 2414130561Sobrien 241533965Sjdp if (q->addend) 241633965Sjdp { 241733965Sjdp printf ("+0x"); 241889857Sobrien bfd_printf_vma (abfd, q->addend); 241933965Sjdp } 2420130561Sobrien 242133965Sjdp printf ("\n"); 242233965Sjdp } 242333965Sjdp} 242433965Sjdp 2425130561Sobrienstatic void 2426130561Sobriendump_relocs_in_section (bfd *abfd, 2427130561Sobrien asection *section, 2428130561Sobrien void *dummy ATTRIBUTE_UNUSED) 242933965Sjdp{ 2430130561Sobrien arelent **relpp; 2431130561Sobrien long relcount; 2432130561Sobrien long relsize; 2433130561Sobrien 2434130561Sobrien if ( bfd_is_abs_section (section) 2435130561Sobrien || bfd_is_und_section (section) 2436130561Sobrien || bfd_is_com_section (section) 2437130561Sobrien || (! process_section_p (section)) 2438130561Sobrien || ((section->flags & SEC_RELOC) == 0)) 2439130561Sobrien return; 2440130561Sobrien 2441130561Sobrien relsize = bfd_get_reloc_upper_bound (abfd, section); 2442130561Sobrien if (relsize < 0) 2443130561Sobrien bfd_fatal (bfd_get_filename (abfd)); 2444130561Sobrien 2445130561Sobrien printf ("RELOCATION RECORDS FOR [%s]:", section->name); 2446130561Sobrien 2447130561Sobrien if (relsize == 0) 2448130561Sobrien { 2449130561Sobrien printf (" (none)\n\n"); 2450130561Sobrien return; 2451130561Sobrien } 2452130561Sobrien 2453130561Sobrien relpp = xmalloc (relsize); 2454130561Sobrien relcount = bfd_canonicalize_reloc (abfd, section, relpp, syms); 2455130561Sobrien 2456130561Sobrien if (relcount < 0) 2457130561Sobrien bfd_fatal (bfd_get_filename (abfd)); 2458130561Sobrien else if (relcount == 0) 2459130561Sobrien printf (" (none)\n\n"); 246033965Sjdp else 2461130561Sobrien { 2462130561Sobrien printf ("\n"); 2463130561Sobrien dump_reloc_set (abfd, section, relpp, relcount); 2464130561Sobrien printf ("\n\n"); 2465130561Sobrien } 2466130561Sobrien free (relpp); 246733965Sjdp} 246833965Sjdp 2469130561Sobrienstatic void 2470130561Sobriendump_relocs (bfd *abfd) 2471130561Sobrien{ 2472130561Sobrien bfd_map_over_sections (abfd, dump_relocs_in_section, NULL); 2473130561Sobrien} 247433965Sjdp 247533965Sjdpstatic void 2476130561Sobriendump_dynamic_relocs (bfd *abfd) 247733965Sjdp{ 2478130561Sobrien long relsize; 2479130561Sobrien arelent **relpp; 2480130561Sobrien long relcount; 248133965Sjdp 2482130561Sobrien relsize = bfd_get_dynamic_reloc_upper_bound (abfd); 2483130561Sobrien if (relsize < 0) 2484130561Sobrien bfd_fatal (bfd_get_filename (abfd)); 2485130561Sobrien 2486130561Sobrien printf ("DYNAMIC RELOCATION RECORDS"); 2487130561Sobrien 2488130561Sobrien if (relsize == 0) 2489130561Sobrien printf (" (none)\n\n"); 2490130561Sobrien else 249133965Sjdp { 2492130561Sobrien relpp = xmalloc (relsize); 2493130561Sobrien relcount = bfd_canonicalize_dynamic_reloc (abfd, relpp, dynsyms); 249433965Sjdp 2495130561Sobrien if (relcount < 0) 2496130561Sobrien bfd_fatal (bfd_get_filename (abfd)); 2497130561Sobrien else if (relcount == 0) 2498130561Sobrien printf (" (none)\n\n"); 2499130561Sobrien else 250033965Sjdp { 2501130561Sobrien printf ("\n"); 2502130561Sobrien dump_reloc_set (abfd, NULL, relpp, relcount); 2503130561Sobrien printf ("\n\n"); 250433965Sjdp } 2505130561Sobrien free (relpp); 2506130561Sobrien } 2507130561Sobrien} 250833965Sjdp 2509130561Sobrien/* Creates a table of paths, to search for source files. */ 2510130561Sobrien 2511130561Sobrienstatic void 2512130561Sobrienadd_include_path (const char *path) 2513130561Sobrien{ 2514130561Sobrien if (path[0] == 0) 2515130561Sobrien return; 2516130561Sobrien include_path_count++; 2517130561Sobrien include_paths = xrealloc (include_paths, 2518130561Sobrien include_path_count * sizeof (*include_paths)); 2519130561Sobrien#ifdef HAVE_DOS_BASED_FILE_SYSTEM 2520130561Sobrien if (path[1] == ':' && path[2] == 0) 2521130561Sobrien path = concat (path, ".", (const char *) 0); 2522130561Sobrien#endif 2523130561Sobrien include_paths[include_path_count - 1] = path; 2524130561Sobrien} 2525130561Sobrien 2526130561Sobrienstatic void 2527130561Sobrienadjust_addresses (bfd *abfd ATTRIBUTE_UNUSED, 2528130561Sobrien asection *section, 2529130561Sobrien void *dummy ATTRIBUTE_UNUSED) 2530130561Sobrien{ 2531130561Sobrien section->vma += adjust_section_vma; 2532130561Sobrien section->lma += adjust_section_vma; 2533130561Sobrien} 2534130561Sobrien 2535130561Sobrien/* Dump selected contents of ABFD. */ 2536130561Sobrien 2537130561Sobrienstatic void 2538130561Sobriendump_bfd (bfd *abfd) 2539130561Sobrien{ 2540130561Sobrien /* If we are adjusting section VMA's, change them all now. Changing 2541130561Sobrien the BFD information is a hack. However, we must do it, or 2542130561Sobrien bfd_find_nearest_line will not do the right thing. */ 2543130561Sobrien if (adjust_section_vma != 0) 2544130561Sobrien bfd_map_over_sections (abfd, adjust_addresses, NULL); 2545130561Sobrien 2546130561Sobrien if (! dump_debugging_tags) 2547130561Sobrien printf (_("\n%s: file format %s\n"), bfd_get_filename (abfd), 2548130561Sobrien abfd->xvec->name); 2549130561Sobrien if (dump_ar_hdrs) 2550130561Sobrien print_arelt_descr (stdout, abfd, TRUE); 2551130561Sobrien if (dump_file_header) 2552130561Sobrien dump_bfd_header (abfd); 2553130561Sobrien if (dump_private_headers) 2554130561Sobrien dump_bfd_private_header (abfd); 2555130561Sobrien if (! dump_debugging_tags) 2556130561Sobrien putchar ('\n'); 2557130561Sobrien if (dump_section_headers) 2558130561Sobrien dump_headers (abfd); 2559130561Sobrien 2560130561Sobrien if (dump_symtab || dump_reloc_info || disassemble || dump_debugging) 2561130561Sobrien syms = slurp_symtab (abfd); 2562130561Sobrien if (dump_dynamic_symtab || dump_dynamic_reloc_info) 2563130561Sobrien dynsyms = slurp_dynamic_symtab (abfd); 2564130561Sobrien 2565130561Sobrien if (dump_symtab) 2566130561Sobrien dump_symbols (abfd, FALSE); 2567130561Sobrien if (dump_dynamic_symtab) 2568130561Sobrien dump_symbols (abfd, TRUE); 2569130561Sobrien if (dump_stab_section_info) 2570130561Sobrien dump_stabs (abfd); 2571130561Sobrien if (dump_reloc_info && ! disassemble) 2572130561Sobrien dump_relocs (abfd); 2573130561Sobrien if (dump_dynamic_reloc_info && ! disassemble) 2574130561Sobrien dump_dynamic_relocs (abfd); 2575130561Sobrien if (dump_section_contents) 2576130561Sobrien dump_data (abfd); 2577130561Sobrien if (disassemble) 2578130561Sobrien disassemble_data (abfd); 2579130561Sobrien 2580130561Sobrien if (dump_debugging) 2581130561Sobrien { 2582130561Sobrien void *dhandle; 2583130561Sobrien 2584130561Sobrien dhandle = read_debugging_info (abfd, syms, symcount); 2585130561Sobrien if (dhandle != NULL) 258633965Sjdp { 2587130561Sobrien if (! print_debugging_info (stdout, dhandle, abfd, syms, demangle, 2588130561Sobrien dump_debugging_tags ? TRUE : FALSE)) 2589130561Sobrien { 2590130561Sobrien non_fatal (_("%s: printing debugging information failed"), 2591130561Sobrien bfd_get_filename (abfd)); 2592130561Sobrien exit_status = 1; 2593130561Sobrien } 259433965Sjdp } 2595130561Sobrien } 259633965Sjdp 2597130561Sobrien if (syms) 2598130561Sobrien { 2599130561Sobrien free (syms); 2600130561Sobrien syms = NULL; 260133965Sjdp } 2602130561Sobrien 2603130561Sobrien if (dynsyms) 2604130561Sobrien { 2605130561Sobrien free (dynsyms); 2606130561Sobrien dynsyms = NULL; 2607130561Sobrien } 260833965Sjdp} 260933965Sjdp 261033965Sjdpstatic void 2611130561Sobriendisplay_bfd (bfd *abfd) 261233965Sjdp{ 2613130561Sobrien char **matching; 261433965Sjdp 2615130561Sobrien if (bfd_check_format_matches (abfd, bfd_object, &matching)) 2616130561Sobrien { 2617130561Sobrien dump_bfd (abfd); 2618130561Sobrien return; 2619130561Sobrien } 262033965Sjdp 2621130561Sobrien if (bfd_get_error () == bfd_error_file_ambiguously_recognized) 2622130561Sobrien { 2623130561Sobrien nonfatal (bfd_get_filename (abfd)); 2624130561Sobrien list_matching_formats (matching); 2625130561Sobrien free (matching); 2626130561Sobrien return; 2627130561Sobrien } 262833965Sjdp 2629130561Sobrien if (bfd_get_error () != bfd_error_file_not_recognized) 2630130561Sobrien { 2631130561Sobrien nonfatal (bfd_get_filename (abfd)); 2632130561Sobrien return; 2633130561Sobrien } 263433965Sjdp 2635130561Sobrien if (bfd_check_format_matches (abfd, bfd_core, &matching)) 2636130561Sobrien { 2637130561Sobrien dump_bfd (abfd); 2638130561Sobrien return; 2639130561Sobrien } 264033965Sjdp 2641130561Sobrien nonfatal (bfd_get_filename (abfd)); 264233965Sjdp 2643130561Sobrien if (bfd_get_error () == bfd_error_file_ambiguously_recognized) 2644130561Sobrien { 2645130561Sobrien list_matching_formats (matching); 2646130561Sobrien free (matching); 2647130561Sobrien } 264833965Sjdp} 264933965Sjdp 265033965Sjdpstatic void 2651130561Sobriendisplay_file (char *filename, char *target) 265233965Sjdp{ 2653130561Sobrien bfd *file; 2654130561Sobrien bfd *arfile = NULL; 265533965Sjdp 2656130561Sobrien if (get_file_size (filename) < 1) 2657130561Sobrien return; 265833965Sjdp 2659130561Sobrien file = bfd_openr (filename, target); 2660130561Sobrien if (file == NULL) 266133965Sjdp { 2662130561Sobrien nonfatal (filename); 2663130561Sobrien return; 2664130561Sobrien } 266533965Sjdp 2666130561Sobrien /* If the file is an archive, process all of its elements. */ 2667130561Sobrien if (bfd_check_format (file, bfd_archive)) 2668130561Sobrien { 2669130561Sobrien bfd *last_arfile = NULL; 2670130561Sobrien 2671130561Sobrien printf (_("In archive %s:\n"), bfd_get_filename (file)); 2672130561Sobrien for (;;) 267333965Sjdp { 2674130561Sobrien bfd_set_error (bfd_error_no_error); 267533965Sjdp 2676130561Sobrien arfile = bfd_openr_next_archived_file (file, arfile); 2677130561Sobrien if (arfile == NULL) 2678130561Sobrien { 2679130561Sobrien if (bfd_get_error () != bfd_error_no_more_archived_files) 2680130561Sobrien nonfatal (bfd_get_filename (file)); 2681130561Sobrien break; 2682130561Sobrien } 2683130561Sobrien 2684130561Sobrien display_bfd (arfile); 2685130561Sobrien 2686130561Sobrien if (last_arfile != NULL) 2687130561Sobrien bfd_close (last_arfile); 2688130561Sobrien last_arfile = arfile; 268933965Sjdp } 2690130561Sobrien 2691130561Sobrien if (last_arfile != NULL) 2692130561Sobrien bfd_close (last_arfile); 269333965Sjdp } 2694130561Sobrien else 2695130561Sobrien display_bfd (file); 269633965Sjdp 2697130561Sobrien bfd_close (file); 269833965Sjdp} 2699130561Sobrien 270033965Sjdpint 2701130561Sobrienmain (int argc, char **argv) 270233965Sjdp{ 270333965Sjdp int c; 270433965Sjdp char *target = default_target; 2705130561Sobrien bfd_boolean seenflag = FALSE; 270633965Sjdp 2707130561Sobrien#if defined (HAVE_SETLOCALE) 2708130561Sobrien#if defined (HAVE_LC_MESSAGES) 270960484Sobrien setlocale (LC_MESSAGES, ""); 271060484Sobrien#endif 271189857Sobrien setlocale (LC_CTYPE, ""); 271289857Sobrien#endif 2713130561Sobrien 271460484Sobrien bindtextdomain (PACKAGE, LOCALEDIR); 271560484Sobrien textdomain (PACKAGE); 271660484Sobrien 271733965Sjdp program_name = *argv; 271833965Sjdp xmalloc_set_program_name (program_name); 271933965Sjdp 272033965Sjdp START_PROGRESS (program_name, 0); 272133965Sjdp 272233965Sjdp bfd_init (); 272333965Sjdp set_default_bfd_target (); 272433965Sjdp 2725130561Sobrien while ((c = getopt_long (argc, argv, "pib:m:M:VvCdDlfaHhrRtTxsSI:j:wE:zgeG", 272633965Sjdp long_options, (int *) 0)) 272733965Sjdp != EOF) 272833965Sjdp { 272933965Sjdp switch (c) 273033965Sjdp { 273133965Sjdp case 0: 273289857Sobrien break; /* We've been given a long option. */ 273333965Sjdp case 'm': 273433965Sjdp machine = optarg; 273533965Sjdp break; 273660484Sobrien case 'M': 2737130561Sobrien if (disassembler_options) 2738130561Sobrien /* Ignore potential memory leak for now. */ 2739130561Sobrien disassembler_options = concat (disassembler_options, ",", 2740130561Sobrien optarg, NULL); 2741130561Sobrien else 2742130561Sobrien disassembler_options = optarg; 274360484Sobrien break; 274433965Sjdp case 'j': 2745130561Sobrien if (only_used == only_size) 2746130561Sobrien { 2747130561Sobrien only_size += 8; 2748130561Sobrien only = xrealloc (only, only_size * sizeof (char *)); 2749130561Sobrien } 2750130561Sobrien only [only_used++] = optarg; 275133965Sjdp break; 275233965Sjdp case 'l': 2753130561Sobrien with_line_numbers = TRUE; 275433965Sjdp break; 275533965Sjdp case 'b': 275633965Sjdp target = optarg; 275733965Sjdp break; 275860484Sobrien case 'C': 2759130561Sobrien do_demangle = TRUE; 276077298Sobrien if (optarg != NULL) 276177298Sobrien { 276277298Sobrien enum demangling_styles style; 276389857Sobrien 276477298Sobrien style = cplus_demangle_name_to_style (optarg); 2765104834Sobrien if (style == unknown_demangling) 276677298Sobrien fatal (_("unknown demangling style `%s'"), 276777298Sobrien optarg); 276889857Sobrien 276977298Sobrien cplus_demangle_set_style (style); 2770104834Sobrien } 277160484Sobrien break; 277260484Sobrien case 'w': 2773130561Sobrien wide_output = TRUE; 277460484Sobrien break; 277560484Sobrien case OPTION_ADJUST_VMA: 277660484Sobrien adjust_section_vma = parse_vma (optarg, "--adjust-vma"); 277760484Sobrien break; 277860484Sobrien case OPTION_START_ADDRESS: 277960484Sobrien start_address = parse_vma (optarg, "--start-address"); 278060484Sobrien break; 278160484Sobrien case OPTION_STOP_ADDRESS: 278260484Sobrien stop_address = parse_vma (optarg, "--stop-address"); 278360484Sobrien break; 278460484Sobrien case 'E': 278560484Sobrien if (strcmp (optarg, "B") == 0) 278660484Sobrien endian = BFD_ENDIAN_BIG; 278760484Sobrien else if (strcmp (optarg, "L") == 0) 278860484Sobrien endian = BFD_ENDIAN_LITTLE; 278960484Sobrien else 279060484Sobrien { 279160484Sobrien non_fatal (_("unrecognized -E option")); 279260484Sobrien usage (stderr, 1); 279360484Sobrien } 279460484Sobrien break; 279560484Sobrien case OPTION_ENDIAN: 279660484Sobrien if (strncmp (optarg, "big", strlen (optarg)) == 0) 279760484Sobrien endian = BFD_ENDIAN_BIG; 279860484Sobrien else if (strncmp (optarg, "little", strlen (optarg)) == 0) 279960484Sobrien endian = BFD_ENDIAN_LITTLE; 280060484Sobrien else 280160484Sobrien { 280260484Sobrien non_fatal (_("unrecognized --endian type `%s'"), optarg); 280360484Sobrien usage (stderr, 1); 280460484Sobrien } 280560484Sobrien break; 280689857Sobrien 280733965Sjdp case 'f': 2808130561Sobrien dump_file_header = TRUE; 2809130561Sobrien seenflag = TRUE; 281033965Sjdp break; 281133965Sjdp case 'i': 2812130561Sobrien formats_info = TRUE; 2813130561Sobrien seenflag = TRUE; 281433965Sjdp break; 2815130561Sobrien case 'I': 2816130561Sobrien add_include_path (optarg); 2817130561Sobrien break; 281833965Sjdp case 'p': 2819130561Sobrien dump_private_headers = TRUE; 2820130561Sobrien seenflag = TRUE; 282133965Sjdp break; 282233965Sjdp case 'x': 2823130561Sobrien dump_private_headers = TRUE; 2824130561Sobrien dump_symtab = TRUE; 2825130561Sobrien dump_reloc_info = TRUE; 2826130561Sobrien dump_file_header = TRUE; 2827130561Sobrien dump_ar_hdrs = TRUE; 2828130561Sobrien dump_section_headers = TRUE; 2829130561Sobrien seenflag = TRUE; 283033965Sjdp break; 283133965Sjdp case 't': 2832130561Sobrien dump_symtab = TRUE; 2833130561Sobrien seenflag = TRUE; 283433965Sjdp break; 283533965Sjdp case 'T': 2836130561Sobrien dump_dynamic_symtab = TRUE; 2837130561Sobrien seenflag = TRUE; 283833965Sjdp break; 283933965Sjdp case 'd': 2840130561Sobrien disassemble = TRUE; 2841130561Sobrien seenflag = TRUE; 284233965Sjdp break; 284360484Sobrien case 'z': 2844130561Sobrien disassemble_zeroes = TRUE; 284560484Sobrien break; 284633965Sjdp case 'D': 2847130561Sobrien disassemble = TRUE; 2848130561Sobrien disassemble_all = TRUE; 2849130561Sobrien seenflag = TRUE; 285033965Sjdp break; 285133965Sjdp case 'S': 2852130561Sobrien disassemble = TRUE; 2853130561Sobrien with_source_code = TRUE; 2854130561Sobrien seenflag = TRUE; 285533965Sjdp break; 285660484Sobrien case 'g': 285760484Sobrien dump_debugging = 1; 2858130561Sobrien seenflag = TRUE; 285960484Sobrien break; 2860130561Sobrien case 'e': 2861130561Sobrien dump_debugging = 1; 2862130561Sobrien dump_debugging_tags = 1; 2863130561Sobrien do_demangle = TRUE; 2864130561Sobrien seenflag = TRUE; 2865130561Sobrien break; 286660484Sobrien case 'G': 2867130561Sobrien dump_stab_section_info = TRUE; 2868130561Sobrien seenflag = TRUE; 286960484Sobrien break; 287033965Sjdp case 's': 2871130561Sobrien dump_section_contents = TRUE; 2872130561Sobrien seenflag = TRUE; 287333965Sjdp break; 287433965Sjdp case 'r': 2875130561Sobrien dump_reloc_info = TRUE; 2876130561Sobrien seenflag = TRUE; 287733965Sjdp break; 287833965Sjdp case 'R': 2879130561Sobrien dump_dynamic_reloc_info = TRUE; 2880130561Sobrien seenflag = TRUE; 288133965Sjdp break; 288233965Sjdp case 'a': 2883130561Sobrien dump_ar_hdrs = TRUE; 2884130561Sobrien seenflag = TRUE; 288533965Sjdp break; 288633965Sjdp case 'h': 2887130561Sobrien dump_section_headers = TRUE; 2888130561Sobrien seenflag = TRUE; 288933965Sjdp break; 289033965Sjdp case 'H': 289133965Sjdp usage (stdout, 0); 2892130561Sobrien seenflag = TRUE; 289389857Sobrien case 'v': 289433965Sjdp case 'V': 2895130561Sobrien show_version = TRUE; 2896130561Sobrien seenflag = TRUE; 289733965Sjdp break; 2898104834Sobrien 289933965Sjdp default: 290033965Sjdp usage (stderr, 1); 290133965Sjdp } 290233965Sjdp } 290333965Sjdp 290433965Sjdp if (show_version) 290533965Sjdp print_version ("objdump"); 290633965Sjdp 2907130561Sobrien if (!seenflag) 290860484Sobrien usage (stderr, 2); 290933965Sjdp 291033965Sjdp if (formats_info) 2911130561Sobrien exit_status = display_info (); 291233965Sjdp else 291333965Sjdp { 291433965Sjdp if (optind == argc) 291533965Sjdp display_file ("a.out", target); 291633965Sjdp else 291733965Sjdp for (; optind < argc;) 291833965Sjdp display_file (argv[optind++], target); 291933965Sjdp } 292033965Sjdp 292133965Sjdp END_PROGRESS (program_name); 292233965Sjdp 292360484Sobrien return exit_status; 292433965Sjdp} 2925