133965Sjdp/* objdump.c -- dump information about an object file. 278828Sobrien Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 3218822Sdim 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 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 20218822Sdim Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, 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 51218822Sdim#include "sysdep.h" 5233965Sjdp#include "bfd.h" 5333965Sjdp#include "progress.h" 5433965Sjdp#include "bucomm.h" 55218822Sdim#include "dwarf.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 64218822Sdim#ifdef HAVE_MMAP 65218822Sdim#include <sys/mman.h> 66218822Sdim#endif 67218822Sdim 68218822Sdim#include <sys/stat.h> 69218822Sdim 7033965Sjdp/* Internal headers for the ELF .stab-dump code - sorry. */ 7133965Sjdp#define BYTES_IN_WORD 32 7233965Sjdp#include "aout/aout64.h" 7333965Sjdp 7460484Sobrien/* Exit status. */ 7560484Sobrienstatic int exit_status = 0; 7660484Sobrien 77130561Sobrienstatic char *default_target = NULL; /* Default at runtime. */ 7833965Sjdp 79130561Sobrien/* The following variables are set based on arguments passed on the 80130561Sobrien command line. */ 81130561Sobrienstatic int show_version = 0; /* Show the version number. */ 8233965Sjdpstatic int dump_section_contents; /* -s */ 8333965Sjdpstatic int dump_section_headers; /* -h */ 84130561Sobrienstatic bfd_boolean dump_file_header; /* -f */ 8533965Sjdpstatic int dump_symtab; /* -t */ 8633965Sjdpstatic int dump_dynamic_symtab; /* -T */ 8733965Sjdpstatic int dump_reloc_info; /* -r */ 8833965Sjdpstatic int dump_dynamic_reloc_info; /* -R */ 8933965Sjdpstatic int dump_ar_hdrs; /* -a */ 9033965Sjdpstatic int dump_private_headers; /* -p */ 9133965Sjdpstatic int prefix_addresses; /* --prefix-addresses */ 9233965Sjdpstatic int with_line_numbers; /* -l */ 93130561Sobrienstatic bfd_boolean with_source_code; /* -S */ 9433965Sjdpstatic int show_raw_insn; /* --show-raw-insn */ 95218822Sdimstatic int dump_dwarf_section_info; /* --dwarf */ 9633965Sjdpstatic int dump_stab_section_info; /* --stabs */ 9733965Sjdpstatic int do_demangle; /* -C, --demangle */ 98130561Sobrienstatic bfd_boolean disassemble; /* -d */ 99130561Sobrienstatic bfd_boolean disassemble_all; /* -D */ 10033965Sjdpstatic int disassemble_zeroes; /* --disassemble-zeroes */ 101130561Sobrienstatic bfd_boolean formats_info; /* -i */ 10233965Sjdpstatic int wide_output; /* -w */ 10333965Sjdpstatic bfd_vma start_address = (bfd_vma) -1; /* --start-address */ 10433965Sjdpstatic bfd_vma stop_address = (bfd_vma) -1; /* --stop-address */ 10533965Sjdpstatic int dump_debugging; /* --debugging */ 106130561Sobrienstatic int dump_debugging_tags; /* --debugging-tags */ 107218822Sdimstatic int dump_special_syms = 0; /* --special-syms */ 10833965Sjdpstatic bfd_vma adjust_section_vma = 0; /* --adjust-vma */ 10960484Sobrienstatic int file_start_context = 0; /* --file-start-context */ 11033965Sjdp 111130561Sobrien/* Pointer to an array of section names provided by 112130561Sobrien one or more "-j secname" command line options. */ 113130561Sobrienstatic char **only; 114130561Sobrien/* The total number of slots in the only[] array. */ 115130561Sobrienstatic size_t only_size = 0; 116130561Sobrien/* The number of occupied slots in the only[] array. */ 117130561Sobrienstatic size_t only_used = 0; 118130561Sobrien 119130561Sobrien/* Variables for handling include file path table. */ 120130561Sobrienstatic const char **include_paths; 121130561Sobrienstatic int include_path_count; 122130561Sobrien 123130561Sobrien/* Extra info to pass to the section disassembler and address printing 124130561Sobrien function. */ 125130561Sobrienstruct objdump_disasm_info 126130561Sobrien{ 127130561Sobrien bfd * abfd; 128130561Sobrien asection * sec; 129130561Sobrien bfd_boolean require_sec; 130130561Sobrien arelent ** dynrelbuf; 131130561Sobrien long dynrelcount; 132130561Sobrien disassembler_ftype disassemble_fn; 133218822Sdim arelent * reloc; 13433965Sjdp}; 13533965Sjdp 13633965Sjdp/* Architecture to disassemble for, or default if NULL. */ 137130561Sobrienstatic char *machine = NULL; 13833965Sjdp 13960484Sobrien/* Target specific options to the disassembler. */ 140130561Sobrienstatic char *disassembler_options = NULL; 14160484Sobrien 14233965Sjdp/* Endianness to disassemble for, or default if BFD_ENDIAN_UNKNOWN. */ 14333965Sjdpstatic enum bfd_endian endian = BFD_ENDIAN_UNKNOWN; 14433965Sjdp 14533965Sjdp/* The symbol table. */ 14633965Sjdpstatic asymbol **syms; 14733965Sjdp 14833965Sjdp/* Number of symbols in `syms'. */ 14933965Sjdpstatic long symcount = 0; 15033965Sjdp 15133965Sjdp/* The sorted symbol table. */ 15233965Sjdpstatic asymbol **sorted_syms; 15333965Sjdp 15433965Sjdp/* Number of symbols in `sorted_syms'. */ 15533965Sjdpstatic long sorted_symcount = 0; 15633965Sjdp 15733965Sjdp/* The dynamic symbol table. */ 15833965Sjdpstatic asymbol **dynsyms; 15933965Sjdp 160218822Sdim/* The synthetic symbol table. */ 161218822Sdimstatic asymbol *synthsyms; 162218822Sdimstatic long synthcount = 0; 163218822Sdim 16433965Sjdp/* Number of symbols in `dynsyms'. */ 16533965Sjdpstatic long dynsymcount = 0; 16633965Sjdp 167130561Sobrienstatic bfd_byte *stabs; 168130561Sobrienstatic bfd_size_type stab_size; 16933965Sjdp 170130561Sobrienstatic char *strtab; 171130561Sobrienstatic bfd_size_type stabstr_size; 17233965Sjdp 17333965Sjdpstatic void 174130561Sobrienusage (FILE *stream, int status) 17533965Sjdp{ 17689857Sobrien fprintf (stream, _("Usage: %s <option(s)> <file(s)>\n"), program_name); 17789857Sobrien fprintf (stream, _(" Display information from object <file(s)>.\n")); 17889857Sobrien fprintf (stream, _(" At least one of the following switches must be given:\n")); 17960484Sobrien fprintf (stream, _("\ 18068765Sobrien -a, --archive-headers Display archive header information\n\ 18168765Sobrien -f, --file-headers Display the contents of the overall file header\n\ 18268765Sobrien -p, --private-headers Display object format specific file header contents\n\ 18368765Sobrien -h, --[section-]headers Display the contents of the section headers\n\ 18468765Sobrien -x, --all-headers Display the contents of all headers\n\ 18568765Sobrien -d, --disassemble Display assembler contents of executable sections\n\ 18668765Sobrien -D, --disassemble-all Display assembler contents of all sections\n\ 18768765Sobrien -S, --source Intermix source code with disassembly\n\ 18868765Sobrien -s, --full-contents Display the full contents of all sections requested\n\ 18968765Sobrien -g, --debugging Display debug information in object file\n\ 190130561Sobrien -e, --debugging-tags Display debug information using ctags style\n\ 19168765Sobrien -G, --stabs Display (in raw form) any STABS info in the file\n\ 192218822Sdim -W, --dwarf Display DWARF info in the file\n\ 19368765Sobrien -t, --syms Display the contents of the symbol table(s)\n\ 19468765Sobrien -T, --dynamic-syms Display the contents of the dynamic symbol table\n\ 19568765Sobrien -r, --reloc Display the relocation entries in the file\n\ 19668765Sobrien -R, --dynamic-reloc Display the dynamic relocation entries in the file\n\ 197218822Sdim @<file> Read options from <file>\n\ 19889857Sobrien -v, --version Display this program's version number\n\ 19968765Sobrien -i, --info List object formats and architectures supported\n\ 20068765Sobrien -H, --help Display this information\n\ 20160484Sobrien")); 20260484Sobrien if (status != 2) 20360484Sobrien { 20460484Sobrien fprintf (stream, _("\n The following switches are optional:\n")); 20560484Sobrien fprintf (stream, _("\ 20668765Sobrien -b, --target=BFDNAME Specify the target object format as BFDNAME\n\ 20768765Sobrien -m, --architecture=MACHINE Specify the target architecture as MACHINE\n\ 20868765Sobrien -j, --section=NAME Only display information for section NAME\n\ 20968765Sobrien -M, --disassembler-options=OPT Pass text OPT on to the disassembler\n\ 21060484Sobrien -EB --endian=big Assume big endian format when disassembling\n\ 21160484Sobrien -EL --endian=little Assume little endian format when disassembling\n\ 21260484Sobrien --file-start-context Include context from start of file (with -S)\n\ 213130561Sobrien -I, --include=DIR Add DIR to search list for source files\n\ 21468765Sobrien -l, --line-numbers Include line numbers and filenames in output\n\ 21577298Sobrien -C, --demangle[=STYLE] Decode mangled/processed symbol names\n\ 216130561Sobrien The STYLE, if specified, can be `auto', `gnu',\n\ 217130561Sobrien `lucid', `arm', `hp', `edg', `gnu-v3', `java'\n\ 218130561Sobrien or `gnat'\n\ 21968765Sobrien -w, --wide Format output for more than 80 columns\n\ 22068765Sobrien -z, --disassemble-zeroes Do not skip blocks of zeroes when disassembling\n\ 221130561Sobrien --start-address=ADDR Only process data whose address is >= ADDR\n\ 222130561Sobrien --stop-address=ADDR Only process data whose address is <= ADDR\n\ 22360484Sobrien --prefix-addresses Print complete address alongside disassembly\n\ 22460484Sobrien --[no-]show-raw-insn Display hex alongside symbolic disassembly\n\ 22568765Sobrien --adjust-vma=OFFSET Add OFFSET to all displayed section addresses\n\ 226218822Sdim --special-syms Include special symbols in symbol dumps\n\ 22760484Sobrien\n")); 22860484Sobrien list_supported_targets (program_name, stream); 22989857Sobrien list_supported_architectures (program_name, stream); 23068765Sobrien 23160484Sobrien disassembler_usage (stream); 23260484Sobrien } 233218822Sdim if (REPORT_BUGS_TO[0] && status == 0) 23468765Sobrien fprintf (stream, _("Report bugs to %s.\n"), REPORT_BUGS_TO); 23533965Sjdp exit (status); 23633965Sjdp} 23733965Sjdp 23833965Sjdp/* 150 isn't special; it's just an arbitrary non-ASCII char value. */ 239130561Sobrienenum option_values 240130561Sobrien { 241130561Sobrien OPTION_ENDIAN=150, 242130561Sobrien OPTION_START_ADDRESS, 243130561Sobrien OPTION_STOP_ADDRESS, 244130561Sobrien OPTION_ADJUST_VMA 245130561Sobrien }; 24633965Sjdp 24733965Sjdpstatic struct option long_options[]= 24833965Sjdp{ 24933965Sjdp {"adjust-vma", required_argument, NULL, OPTION_ADJUST_VMA}, 25033965Sjdp {"all-headers", no_argument, NULL, 'x'}, 25133965Sjdp {"private-headers", no_argument, NULL, 'p'}, 25233965Sjdp {"architecture", required_argument, NULL, 'm'}, 25333965Sjdp {"archive-headers", no_argument, NULL, 'a'}, 25460484Sobrien {"debugging", no_argument, NULL, 'g'}, 255130561Sobrien {"debugging-tags", no_argument, NULL, 'e'}, 25677298Sobrien {"demangle", optional_argument, NULL, 'C'}, 25733965Sjdp {"disassemble", no_argument, NULL, 'd'}, 25833965Sjdp {"disassemble-all", no_argument, NULL, 'D'}, 25960484Sobrien {"disassembler-options", required_argument, NULL, 'M'}, 26060484Sobrien {"disassemble-zeroes", no_argument, NULL, 'z'}, 26133965Sjdp {"dynamic-reloc", no_argument, NULL, 'R'}, 26233965Sjdp {"dynamic-syms", no_argument, NULL, 'T'}, 26333965Sjdp {"endian", required_argument, NULL, OPTION_ENDIAN}, 26433965Sjdp {"file-headers", no_argument, NULL, 'f'}, 26560484Sobrien {"file-start-context", no_argument, &file_start_context, 1}, 26633965Sjdp {"full-contents", no_argument, NULL, 's'}, 26733965Sjdp {"headers", no_argument, NULL, 'h'}, 26833965Sjdp {"help", no_argument, NULL, 'H'}, 26933965Sjdp {"info", no_argument, NULL, 'i'}, 27033965Sjdp {"line-numbers", no_argument, NULL, 'l'}, 27133965Sjdp {"no-show-raw-insn", no_argument, &show_raw_insn, -1}, 27233965Sjdp {"prefix-addresses", no_argument, &prefix_addresses, 1}, 27333965Sjdp {"reloc", no_argument, NULL, 'r'}, 27433965Sjdp {"section", required_argument, NULL, 'j'}, 27533965Sjdp {"section-headers", no_argument, NULL, 'h'}, 27633965Sjdp {"show-raw-insn", no_argument, &show_raw_insn, 1}, 27733965Sjdp {"source", no_argument, NULL, 'S'}, 278218822Sdim {"special-syms", no_argument, &dump_special_syms, 1}, 279130561Sobrien {"include", required_argument, NULL, 'I'}, 280218822Sdim {"dwarf", no_argument, NULL, 'W'}, 28160484Sobrien {"stabs", no_argument, NULL, 'G'}, 28233965Sjdp {"start-address", required_argument, NULL, OPTION_START_ADDRESS}, 28333965Sjdp {"stop-address", required_argument, NULL, OPTION_STOP_ADDRESS}, 28433965Sjdp {"syms", no_argument, NULL, 't'}, 28533965Sjdp {"target", required_argument, NULL, 'b'}, 28660484Sobrien {"version", no_argument, NULL, 'V'}, 28760484Sobrien {"wide", no_argument, NULL, 'w'}, 28833965Sjdp {0, no_argument, 0, 0} 28933965Sjdp}; 29033965Sjdp 29133965Sjdpstatic void 292130561Sobriennonfatal (const char *msg) 29360484Sobrien{ 29460484Sobrien bfd_nonfatal (msg); 29560484Sobrien exit_status = 1; 29660484Sobrien} 29760484Sobrien 29860484Sobrienstatic void 299218822Sdimdump_section_header (bfd *abfd, asection *section, 300130561Sobrien void *ignored ATTRIBUTE_UNUSED) 30133965Sjdp{ 30233965Sjdp char *comma = ""; 30360484Sobrien unsigned int opb = bfd_octets_per_byte (abfd); 30433965Sjdp 305218822Sdim /* Ignore linker created section. See elfNN_ia64_object_p in 306218822Sdim bfd/elfxx-ia64.c. */ 307218822Sdim if (section->flags & SEC_LINKER_CREATED) 308218822Sdim return; 309218822Sdim 31033965Sjdp printf ("%3d %-13s %08lx ", section->index, 31133965Sjdp bfd_get_section_name (abfd, section), 31260484Sobrien (unsigned long) bfd_section_size (abfd, section) / opb); 31389857Sobrien bfd_printf_vma (abfd, bfd_get_section_vma (abfd, section)); 31433965Sjdp printf (" "); 31589857Sobrien bfd_printf_vma (abfd, section->lma); 31689857Sobrien printf (" %08lx 2**%u", (unsigned long) section->filepos, 31733965Sjdp bfd_get_section_alignment (abfd, section)); 31833965Sjdp if (! wide_output) 31933965Sjdp printf ("\n "); 32033965Sjdp printf (" "); 32133965Sjdp 32233965Sjdp#define PF(x, y) \ 32333965Sjdp if (section->flags & x) { printf ("%s%s", comma, y); comma = ", "; } 32433965Sjdp 32533965Sjdp PF (SEC_HAS_CONTENTS, "CONTENTS"); 32633965Sjdp PF (SEC_ALLOC, "ALLOC"); 32733965Sjdp PF (SEC_CONSTRUCTOR, "CONSTRUCTOR"); 32833965Sjdp PF (SEC_LOAD, "LOAD"); 32933965Sjdp PF (SEC_RELOC, "RELOC"); 33033965Sjdp PF (SEC_READONLY, "READONLY"); 33133965Sjdp PF (SEC_CODE, "CODE"); 33233965Sjdp PF (SEC_DATA, "DATA"); 33333965Sjdp PF (SEC_ROM, "ROM"); 33433965Sjdp PF (SEC_DEBUGGING, "DEBUGGING"); 33533965Sjdp PF (SEC_NEVER_LOAD, "NEVER_LOAD"); 33633965Sjdp PF (SEC_EXCLUDE, "EXCLUDE"); 33733965Sjdp PF (SEC_SORT_ENTRIES, "SORT_ENTRIES"); 338218822Sdim if (bfd_get_arch (abfd) == bfd_arch_tic54x) 339218822Sdim { 340218822Sdim PF (SEC_TIC54X_BLOCK, "BLOCK"); 341218822Sdim PF (SEC_TIC54X_CLINK, "CLINK"); 342218822Sdim } 34360484Sobrien PF (SEC_SMALL_DATA, "SMALL_DATA"); 344218822Sdim if (bfd_get_flavour (abfd) == bfd_target_coff_flavour) 345218822Sdim PF (SEC_COFF_SHARED, "SHARED"); 346104834Sobrien PF (SEC_THREAD_LOCAL, "THREAD_LOCAL"); 347218822Sdim PF (SEC_GROUP, "GROUP"); 34833965Sjdp 34933965Sjdp if ((section->flags & SEC_LINK_ONCE) != 0) 35033965Sjdp { 35133965Sjdp const char *ls; 352218822Sdim struct coff_comdat_info *comdat; 35333965Sjdp 35433965Sjdp switch (section->flags & SEC_LINK_DUPLICATES) 35533965Sjdp { 35633965Sjdp default: 35733965Sjdp abort (); 35833965Sjdp case SEC_LINK_DUPLICATES_DISCARD: 35933965Sjdp ls = "LINK_ONCE_DISCARD"; 36033965Sjdp break; 36133965Sjdp case SEC_LINK_DUPLICATES_ONE_ONLY: 36233965Sjdp ls = "LINK_ONCE_ONE_ONLY"; 36333965Sjdp break; 36433965Sjdp case SEC_LINK_DUPLICATES_SAME_SIZE: 36533965Sjdp ls = "LINK_ONCE_SAME_SIZE"; 36633965Sjdp break; 36733965Sjdp case SEC_LINK_DUPLICATES_SAME_CONTENTS: 36833965Sjdp ls = "LINK_ONCE_SAME_CONTENTS"; 36933965Sjdp break; 37033965Sjdp } 37133965Sjdp printf ("%s%s", comma, ls); 37260484Sobrien 373218822Sdim comdat = bfd_coff_get_comdat_section (abfd, section); 374218822Sdim if (comdat != NULL) 375218822Sdim printf (" (COMDAT %s %ld)", comdat->name, comdat->symbol); 37660484Sobrien 37733965Sjdp comma = ", "; 37833965Sjdp } 37933965Sjdp 38033965Sjdp printf ("\n"); 38133965Sjdp#undef PF 38233965Sjdp} 38333965Sjdp 38433965Sjdpstatic void 385130561Sobriendump_headers (bfd *abfd) 38633965Sjdp{ 38760484Sobrien printf (_("Sections:\n")); 38860484Sobrien 38933965Sjdp#ifndef BFD64 39060484Sobrien printf (_("Idx Name Size VMA LMA File off Algn")); 39133965Sjdp#else 392104834Sobrien /* With BFD64, non-ELF returns -1 and wants always 64 bit addresses. */ 393104834Sobrien if (bfd_get_arch_size (abfd) == 32) 394104834Sobrien printf (_("Idx Name Size VMA LMA File off Algn")); 395104834Sobrien else 396104834Sobrien printf (_("Idx Name Size VMA LMA File off Algn")); 39733965Sjdp#endif 39860484Sobrien 39960484Sobrien if (wide_output) 40060484Sobrien printf (_(" Flags")); 401130561Sobrien if (abfd->flags & HAS_LOAD_PAGE) 402130561Sobrien printf (_(" Pg")); 40360484Sobrien printf ("\n"); 40460484Sobrien 405130561Sobrien bfd_map_over_sections (abfd, dump_section_header, NULL); 40633965Sjdp} 40733965Sjdp 40833965Sjdpstatic asymbol ** 409130561Sobrienslurp_symtab (bfd *abfd) 41033965Sjdp{ 411130561Sobrien asymbol **sy = NULL; 41233965Sjdp long storage; 41333965Sjdp 41433965Sjdp if (!(bfd_get_file_flags (abfd) & HAS_SYMS)) 41533965Sjdp { 41633965Sjdp symcount = 0; 41733965Sjdp return NULL; 41833965Sjdp } 41933965Sjdp 42033965Sjdp storage = bfd_get_symtab_upper_bound (abfd); 42133965Sjdp if (storage < 0) 42233965Sjdp bfd_fatal (bfd_get_filename (abfd)); 423104834Sobrien if (storage) 424130561Sobrien sy = xmalloc (storage); 42533965Sjdp 42633965Sjdp symcount = bfd_canonicalize_symtab (abfd, sy); 42733965Sjdp if (symcount < 0) 42833965Sjdp bfd_fatal (bfd_get_filename (abfd)); 42933965Sjdp return sy; 43033965Sjdp} 43133965Sjdp 43233965Sjdp/* Read in the dynamic symbols. */ 43333965Sjdp 43433965Sjdpstatic asymbol ** 435130561Sobrienslurp_dynamic_symtab (bfd *abfd) 43633965Sjdp{ 437130561Sobrien asymbol **sy = NULL; 43833965Sjdp long storage; 43933965Sjdp 44033965Sjdp storage = bfd_get_dynamic_symtab_upper_bound (abfd); 44133965Sjdp if (storage < 0) 44233965Sjdp { 44333965Sjdp if (!(bfd_get_file_flags (abfd) & DYNAMIC)) 44433965Sjdp { 44560484Sobrien non_fatal (_("%s: not a dynamic object"), bfd_get_filename (abfd)); 44633965Sjdp dynsymcount = 0; 44733965Sjdp return NULL; 44833965Sjdp } 44933965Sjdp 45033965Sjdp bfd_fatal (bfd_get_filename (abfd)); 45133965Sjdp } 452104834Sobrien if (storage) 453130561Sobrien sy = xmalloc (storage); 45433965Sjdp 45533965Sjdp dynsymcount = bfd_canonicalize_dynamic_symtab (abfd, sy); 45633965Sjdp if (dynsymcount < 0) 45733965Sjdp bfd_fatal (bfd_get_filename (abfd)); 45833965Sjdp return sy; 45933965Sjdp} 46033965Sjdp 46133965Sjdp/* Filter out (in place) symbols that are useless for disassembly. 46233965Sjdp COUNT is the number of elements in SYMBOLS. 463104834Sobrien Return the number of useful symbols. */ 46433965Sjdp 46533965Sjdpstatic long 466130561Sobrienremove_useless_symbols (asymbol **symbols, long count) 46733965Sjdp{ 468130561Sobrien asymbol **in_ptr = symbols, **out_ptr = symbols; 46933965Sjdp 47033965Sjdp while (--count >= 0) 47133965Sjdp { 47233965Sjdp asymbol *sym = *in_ptr++; 47333965Sjdp 47433965Sjdp if (sym->name == NULL || sym->name[0] == '\0') 47533965Sjdp continue; 476218822Sdim if (sym->flags & (BSF_DEBUGGING | BSF_SECTION_SYM)) 47733965Sjdp continue; 47833965Sjdp if (bfd_is_und_section (sym->section) 47933965Sjdp || bfd_is_com_section (sym->section)) 48033965Sjdp continue; 48133965Sjdp 48233965Sjdp *out_ptr++ = sym; 48333965Sjdp } 48433965Sjdp return out_ptr - symbols; 48533965Sjdp} 48633965Sjdp 48733965Sjdp/* Sort symbols into value order. */ 48833965Sjdp 489104834Sobrienstatic int 490130561Sobriencompare_symbols (const void *ap, const void *bp) 49133965Sjdp{ 492130561Sobrien const asymbol *a = * (const asymbol **) ap; 493130561Sobrien const asymbol *b = * (const asymbol **) bp; 494130561Sobrien const char *an; 495130561Sobrien const char *bn; 496130561Sobrien size_t anl; 497130561Sobrien size_t bnl; 498130561Sobrien bfd_boolean af; 499130561Sobrien bfd_boolean bf; 500130561Sobrien flagword aflags; 501130561Sobrien flagword bflags; 50233965Sjdp 50333965Sjdp if (bfd_asymbol_value (a) > bfd_asymbol_value (b)) 50433965Sjdp return 1; 50533965Sjdp else if (bfd_asymbol_value (a) < bfd_asymbol_value (b)) 50633965Sjdp return -1; 50733965Sjdp 50833965Sjdp if (a->section > b->section) 50933965Sjdp return 1; 51033965Sjdp else if (a->section < b->section) 51133965Sjdp return -1; 51233965Sjdp 51333965Sjdp an = bfd_asymbol_name (a); 51433965Sjdp bn = bfd_asymbol_name (b); 51533965Sjdp anl = strlen (an); 51633965Sjdp bnl = strlen (bn); 51733965Sjdp 51833965Sjdp /* The symbols gnu_compiled and gcc2_compiled convey no real 51933965Sjdp information, so put them after other symbols with the same value. */ 52033965Sjdp af = (strstr (an, "gnu_compiled") != NULL 52133965Sjdp || strstr (an, "gcc2_compiled") != NULL); 52233965Sjdp bf = (strstr (bn, "gnu_compiled") != NULL 52333965Sjdp || strstr (bn, "gcc2_compiled") != NULL); 52433965Sjdp 52533965Sjdp if (af && ! bf) 52633965Sjdp return 1; 52733965Sjdp if (! af && bf) 52833965Sjdp return -1; 52933965Sjdp 53033965Sjdp /* We use a heuristic for the file name, to try to sort it after 53133965Sjdp more useful symbols. It may not work on non Unix systems, but it 53233965Sjdp doesn't really matter; the only difference is precisely which 53333965Sjdp symbol names get printed. */ 53433965Sjdp 53533965Sjdp#define file_symbol(s, sn, snl) \ 53633965Sjdp (((s)->flags & BSF_FILE) != 0 \ 53733965Sjdp || ((sn)[(snl) - 2] == '.' \ 53833965Sjdp && ((sn)[(snl) - 1] == 'o' \ 53933965Sjdp || (sn)[(snl) - 1] == 'a'))) 54033965Sjdp 54133965Sjdp af = file_symbol (a, an, anl); 54233965Sjdp bf = file_symbol (b, bn, bnl); 54333965Sjdp 54433965Sjdp if (af && ! bf) 54533965Sjdp return 1; 54633965Sjdp if (! af && bf) 54733965Sjdp return -1; 54833965Sjdp 54933965Sjdp /* Try to sort global symbols before local symbols before function 55033965Sjdp symbols before debugging symbols. */ 55133965Sjdp 55233965Sjdp aflags = a->flags; 55333965Sjdp bflags = b->flags; 55433965Sjdp 55533965Sjdp if ((aflags & BSF_DEBUGGING) != (bflags & BSF_DEBUGGING)) 55633965Sjdp { 55733965Sjdp if ((aflags & BSF_DEBUGGING) != 0) 55833965Sjdp return 1; 55933965Sjdp else 56033965Sjdp return -1; 56133965Sjdp } 56233965Sjdp if ((aflags & BSF_FUNCTION) != (bflags & BSF_FUNCTION)) 56333965Sjdp { 56433965Sjdp if ((aflags & BSF_FUNCTION) != 0) 56533965Sjdp return -1; 56633965Sjdp else 56733965Sjdp return 1; 56833965Sjdp } 56933965Sjdp if ((aflags & BSF_LOCAL) != (bflags & BSF_LOCAL)) 57033965Sjdp { 57133965Sjdp if ((aflags & BSF_LOCAL) != 0) 57233965Sjdp return 1; 57333965Sjdp else 57433965Sjdp return -1; 57533965Sjdp } 57633965Sjdp if ((aflags & BSF_GLOBAL) != (bflags & BSF_GLOBAL)) 57733965Sjdp { 57833965Sjdp if ((aflags & BSF_GLOBAL) != 0) 57933965Sjdp return -1; 58033965Sjdp else 58133965Sjdp return 1; 58233965Sjdp } 58333965Sjdp 58433965Sjdp /* Symbols that start with '.' might be section names, so sort them 58533965Sjdp after symbols that don't start with '.'. */ 58633965Sjdp if (an[0] == '.' && bn[0] != '.') 58733965Sjdp return 1; 58833965Sjdp if (an[0] != '.' && bn[0] == '.') 58933965Sjdp return -1; 59033965Sjdp 59133965Sjdp /* Finally, if we can't distinguish them in any other way, try to 59233965Sjdp get consistent results by sorting the symbols by name. */ 59333965Sjdp return strcmp (an, bn); 59433965Sjdp} 59533965Sjdp 59633965Sjdp/* Sort relocs into address order. */ 59733965Sjdp 59833965Sjdpstatic int 599130561Sobriencompare_relocs (const void *ap, const void *bp) 60033965Sjdp{ 601130561Sobrien const arelent *a = * (const arelent **) ap; 602130561Sobrien const arelent *b = * (const arelent **) bp; 60333965Sjdp 60433965Sjdp if (a->address > b->address) 60533965Sjdp return 1; 60633965Sjdp else if (a->address < b->address) 60733965Sjdp return -1; 60833965Sjdp 60933965Sjdp /* So that associated relocations tied to the same address show up 61033965Sjdp in the correct order, we don't do any further sorting. */ 61133965Sjdp if (a > b) 61233965Sjdp return 1; 61333965Sjdp else if (a < b) 61433965Sjdp return -1; 61533965Sjdp else 61633965Sjdp return 0; 61733965Sjdp} 61833965Sjdp 619130561Sobrien/* Print an address (VMA) to the output stream in INFO. 620130561Sobrien If SKIP_ZEROES is TRUE, omit leading zeroes. */ 62133965Sjdp 62233965Sjdpstatic void 623130561Sobrienobjdump_print_value (bfd_vma vma, struct disassemble_info *info, 624130561Sobrien bfd_boolean skip_zeroes) 62533965Sjdp{ 62633965Sjdp char buf[30]; 62733965Sjdp char *p; 628130561Sobrien struct objdump_disasm_info *aux; 62933965Sjdp 630130561Sobrien aux = (struct objdump_disasm_info *) info->application_data; 63189857Sobrien bfd_sprintf_vma (aux->abfd, buf, vma); 63233965Sjdp if (! skip_zeroes) 63333965Sjdp p = buf; 63433965Sjdp else 63533965Sjdp { 63633965Sjdp for (p = buf; *p == '0'; ++p) 63733965Sjdp ; 63833965Sjdp if (*p == '\0') 63933965Sjdp --p; 64033965Sjdp } 64133965Sjdp (*info->fprintf_func) (info->stream, "%s", p); 64233965Sjdp} 64333965Sjdp 64433965Sjdp/* Print the name of a symbol. */ 64533965Sjdp 64633965Sjdpstatic void 647130561Sobrienobjdump_print_symname (bfd *abfd, struct disassemble_info *info, 648130561Sobrien asymbol *sym) 64933965Sjdp{ 65033965Sjdp char *alloc; 65133965Sjdp const char *name; 65233965Sjdp 65333965Sjdp alloc = NULL; 65433965Sjdp name = bfd_asymbol_name (sym); 655104834Sobrien if (do_demangle && name[0] != '\0') 65633965Sjdp { 65733965Sjdp /* Demangle the name. */ 658218822Sdim alloc = bfd_demangle (abfd, name, DMGL_ANSI | DMGL_PARAMS); 659218822Sdim if (alloc != NULL) 660218822Sdim name = alloc; 66133965Sjdp } 66233965Sjdp 66333965Sjdp if (info != NULL) 664104834Sobrien (*info->fprintf_func) (info->stream, "%s", name); 66533965Sjdp else 666104834Sobrien printf ("%s", name); 66733965Sjdp 66833965Sjdp if (alloc != NULL) 66933965Sjdp free (alloc); 67033965Sjdp} 67133965Sjdp 672130561Sobrien/* Locate a symbol given a bfd and a section (from INFO->application_data), 673130561Sobrien and a VMA. If INFO->application_data->require_sec is TRUE, then always 674130561Sobrien require the symbol to be in the section. Returns NULL if there is no 675130561Sobrien suitable symbol. If PLACE is not NULL, then *PLACE is set to the index 676130561Sobrien of the symbol in sorted_syms. */ 67733965Sjdp 67833965Sjdpstatic asymbol * 679130561Sobrienfind_symbol_for_address (bfd_vma vma, 680130561Sobrien struct disassemble_info *info, 681130561Sobrien long *place) 68233965Sjdp{ 68333965Sjdp /* @@ Would it speed things up to cache the last two symbols returned, 68433965Sjdp and maybe their address ranges? For many processors, only one memory 68533965Sjdp operand can be present at a time, so the 2-entry cache wouldn't be 68633965Sjdp constantly churned by code doing heavy memory accesses. */ 68733965Sjdp 68833965Sjdp /* Indices in `sorted_syms'. */ 68933965Sjdp long min = 0; 69033965Sjdp long max = sorted_symcount; 69133965Sjdp long thisplace; 692130561Sobrien struct objdump_disasm_info *aux; 693130561Sobrien bfd *abfd; 694130561Sobrien asection *sec; 695130561Sobrien unsigned int opb; 696218822Sdim bfd_boolean want_section; 69733965Sjdp 69833965Sjdp if (sorted_symcount < 1) 69933965Sjdp return NULL; 70033965Sjdp 701130561Sobrien aux = (struct objdump_disasm_info *) info->application_data; 702130561Sobrien abfd = aux->abfd; 703130561Sobrien sec = aux->sec; 704130561Sobrien opb = bfd_octets_per_byte (abfd); 705130561Sobrien 70633965Sjdp /* Perform a binary search looking for the closest symbol to the 70733965Sjdp required value. We are searching the range (min, max]. */ 70833965Sjdp while (min + 1 < max) 70933965Sjdp { 71033965Sjdp asymbol *sym; 71133965Sjdp 71233965Sjdp thisplace = (max + min) / 2; 71333965Sjdp sym = sorted_syms[thisplace]; 71433965Sjdp 71533965Sjdp if (bfd_asymbol_value (sym) > vma) 71633965Sjdp max = thisplace; 71733965Sjdp else if (bfd_asymbol_value (sym) < vma) 71833965Sjdp min = thisplace; 71933965Sjdp else 72033965Sjdp { 72133965Sjdp min = thisplace; 72233965Sjdp break; 72333965Sjdp } 72433965Sjdp } 72533965Sjdp 72633965Sjdp /* The symbol we want is now in min, the low end of the range we 72733965Sjdp were searching. If there are several symbols with the same 72833965Sjdp value, we want the first one. */ 72933965Sjdp thisplace = min; 73033965Sjdp while (thisplace > 0 73133965Sjdp && (bfd_asymbol_value (sorted_syms[thisplace]) 73233965Sjdp == bfd_asymbol_value (sorted_syms[thisplace - 1]))) 73333965Sjdp --thisplace; 73433965Sjdp 735130561Sobrien /* If the file is relocatable, and the symbol could be from this 73633965Sjdp section, prefer a symbol from this section over symbols from 73733965Sjdp others, even if the other symbol's value might be closer. 738104834Sobrien 73933965Sjdp Note that this may be wrong for some symbol references if the 74033965Sjdp sections have overlapping memory ranges, but in that case there's 74133965Sjdp no way to tell what's desired without looking at the relocation 742218822Sdim table. 743218822Sdim 744218822Sdim Also give the target a chance to reject symbols. */ 745218822Sdim want_section = (aux->require_sec 746218822Sdim || ((abfd->flags & HAS_RELOC) != 0 747218822Sdim && vma >= bfd_get_section_vma (abfd, sec) 748218822Sdim && vma < (bfd_get_section_vma (abfd, sec) 749218822Sdim + bfd_section_size (abfd, sec) / opb))); 750218822Sdim if ((sorted_syms[thisplace]->section != sec && want_section) 751218822Sdim || !info->symbol_is_valid (sorted_syms[thisplace], info)) 75233965Sjdp { 75333965Sjdp long i; 754218822Sdim long newplace; 75533965Sjdp 75633965Sjdp for (i = thisplace + 1; i < sorted_symcount; i++) 75733965Sjdp { 75833965Sjdp if (bfd_asymbol_value (sorted_syms[i]) 75933965Sjdp != bfd_asymbol_value (sorted_syms[thisplace])) 76033965Sjdp break; 76133965Sjdp } 762130561Sobrien 76333965Sjdp --i; 764218822Sdim newplace = sorted_symcount; 765130561Sobrien 76633965Sjdp for (; i >= 0; i--) 76733965Sjdp { 768218822Sdim if ((sorted_syms[i]->section == sec || !want_section) 769218822Sdim && info->symbol_is_valid (sorted_syms[i], info)) 77033965Sjdp { 771218822Sdim if (newplace == sorted_symcount) 772218822Sdim newplace = i; 773218822Sdim 774218822Sdim if (bfd_asymbol_value (sorted_syms[i]) 775218822Sdim != bfd_asymbol_value (sorted_syms[newplace])) 776218822Sdim break; 777218822Sdim 778218822Sdim /* Remember this symbol and keep searching until we reach 779218822Sdim an earlier address. */ 780218822Sdim newplace = i; 78133965Sjdp } 78233965Sjdp } 78333965Sjdp 784218822Sdim if (newplace != sorted_symcount) 785218822Sdim thisplace = newplace; 786218822Sdim else 78733965Sjdp { 78833965Sjdp /* We didn't find a good symbol with a smaller value. 78933965Sjdp Look for one with a larger value. */ 79033965Sjdp for (i = thisplace + 1; i < sorted_symcount; i++) 79133965Sjdp { 792218822Sdim if ((sorted_syms[i]->section == sec || !want_section) 793218822Sdim && info->symbol_is_valid (sorted_syms[i], info)) 79433965Sjdp { 79533965Sjdp thisplace = i; 79633965Sjdp break; 79733965Sjdp } 79833965Sjdp } 79933965Sjdp } 80033965Sjdp 801218822Sdim if ((sorted_syms[thisplace]->section != sec && want_section) 802218822Sdim || !info->symbol_is_valid (sorted_syms[thisplace], info)) 803130561Sobrien /* There is no suitable symbol. */ 804130561Sobrien return NULL; 80533965Sjdp } 80633965Sjdp 80733965Sjdp if (place != NULL) 80833965Sjdp *place = thisplace; 80933965Sjdp 81033965Sjdp return sorted_syms[thisplace]; 81133965Sjdp} 81233965Sjdp 813130561Sobrien/* Print an address and the offset to the nearest symbol. */ 81433965Sjdp 81533965Sjdpstatic void 816130561Sobrienobjdump_print_addr_with_sym (bfd *abfd, asection *sec, asymbol *sym, 817130561Sobrien bfd_vma vma, struct disassemble_info *info, 818130561Sobrien bfd_boolean skip_zeroes) 81933965Sjdp{ 82033965Sjdp objdump_print_value (vma, info, skip_zeroes); 82133965Sjdp 82233965Sjdp if (sym == NULL) 82333965Sjdp { 82433965Sjdp bfd_vma secaddr; 82533965Sjdp 82633965Sjdp (*info->fprintf_func) (info->stream, " <%s", 82733965Sjdp bfd_get_section_name (abfd, sec)); 82833965Sjdp secaddr = bfd_get_section_vma (abfd, sec); 82933965Sjdp if (vma < secaddr) 83033965Sjdp { 83138889Sjdp (*info->fprintf_func) (info->stream, "-0x"); 832130561Sobrien objdump_print_value (secaddr - vma, info, TRUE); 83333965Sjdp } 83433965Sjdp else if (vma > secaddr) 83533965Sjdp { 83638889Sjdp (*info->fprintf_func) (info->stream, "+0x"); 837130561Sobrien objdump_print_value (vma - secaddr, info, TRUE); 83833965Sjdp } 83933965Sjdp (*info->fprintf_func) (info->stream, ">"); 84033965Sjdp } 84133965Sjdp else 84233965Sjdp { 84333965Sjdp (*info->fprintf_func) (info->stream, " <"); 84433965Sjdp objdump_print_symname (abfd, info, sym); 84533965Sjdp if (bfd_asymbol_value (sym) > vma) 84633965Sjdp { 84738889Sjdp (*info->fprintf_func) (info->stream, "-0x"); 848130561Sobrien objdump_print_value (bfd_asymbol_value (sym) - vma, info, TRUE); 84933965Sjdp } 85033965Sjdp else if (vma > bfd_asymbol_value (sym)) 85133965Sjdp { 85238889Sjdp (*info->fprintf_func) (info->stream, "+0x"); 853130561Sobrien objdump_print_value (vma - bfd_asymbol_value (sym), info, TRUE); 85433965Sjdp } 85533965Sjdp (*info->fprintf_func) (info->stream, ">"); 85633965Sjdp } 85733965Sjdp} 85833965Sjdp 859130561Sobrien/* Print an address (VMA), symbolically if possible. 860130561Sobrien If SKIP_ZEROES is TRUE, don't output leading zeroes. */ 86133965Sjdp 86233965Sjdpstatic void 863130561Sobrienobjdump_print_addr (bfd_vma vma, 864130561Sobrien struct disassemble_info *info, 865130561Sobrien bfd_boolean skip_zeroes) 86633965Sjdp{ 86733965Sjdp struct objdump_disasm_info *aux; 868218822Sdim asymbol *sym = NULL; /* Initialize to avoid compiler warning. */ 869218822Sdim bfd_boolean skip_find = FALSE; 87033965Sjdp 87133965Sjdp if (sorted_symcount < 1) 87233965Sjdp { 87338889Sjdp (*info->fprintf_func) (info->stream, "0x"); 87433965Sjdp objdump_print_value (vma, info, skip_zeroes); 87533965Sjdp return; 87633965Sjdp } 87733965Sjdp 87833965Sjdp aux = (struct objdump_disasm_info *) info->application_data; 879218822Sdim 880218822Sdim if (aux->reloc != NULL 881218822Sdim && aux->reloc->sym_ptr_ptr != NULL 882218822Sdim && * aux->reloc->sym_ptr_ptr != NULL) 883218822Sdim { 884218822Sdim sym = * aux->reloc->sym_ptr_ptr; 885218822Sdim 886218822Sdim /* Adjust the vma to the reloc. */ 887218822Sdim vma += bfd_asymbol_value (sym); 888218822Sdim 889218822Sdim if (bfd_is_und_section (bfd_get_section (sym))) 890218822Sdim skip_find = TRUE; 891218822Sdim } 892218822Sdim 893218822Sdim if (!skip_find) 894218822Sdim sym = find_symbol_for_address (vma, info, NULL); 895218822Sdim 89633965Sjdp objdump_print_addr_with_sym (aux->abfd, aux->sec, sym, vma, info, 89733965Sjdp skip_zeroes); 89833965Sjdp} 89933965Sjdp 90033965Sjdp/* Print VMA to INFO. This function is passed to the disassembler 90133965Sjdp routine. */ 90233965Sjdp 90333965Sjdpstatic void 904130561Sobrienobjdump_print_address (bfd_vma vma, struct disassemble_info *info) 90533965Sjdp{ 90633965Sjdp objdump_print_addr (vma, info, ! prefix_addresses); 90733965Sjdp} 90833965Sjdp 909218822Sdim/* Determine if the given address has a symbol associated with it. */ 91038889Sjdp 91138889Sjdpstatic int 912130561Sobrienobjdump_symbol_at_address (bfd_vma vma, struct disassemble_info * info) 91338889Sjdp{ 91438889Sjdp asymbol * sym; 91538889Sjdp 916130561Sobrien sym = find_symbol_for_address (vma, info, NULL); 91738889Sjdp 91838889Sjdp return (sym != NULL && (bfd_asymbol_value (sym) == vma)); 91938889Sjdp} 92038889Sjdp 92133965Sjdp/* Hold the last function name and the last line number we displayed 92233965Sjdp in a disassembly. */ 92333965Sjdp 92433965Sjdpstatic char *prev_functionname; 92533965Sjdpstatic unsigned int prev_line; 92633965Sjdp 92733965Sjdp/* We keep a list of all files that we have seen when doing a 928130561Sobrien disassembly with source, so that we know how much of the file to 92933965Sjdp display. This can be important for inlined functions. */ 93033965Sjdp 93133965Sjdpstruct print_file_list 93233965Sjdp{ 93333965Sjdp struct print_file_list *next; 934130561Sobrien const char *filename; 935130561Sobrien const char *modname; 936218822Sdim const char *map; 937218822Sdim size_t mapsize; 938218822Sdim const char **linemap; 939218822Sdim unsigned maxline; 940218822Sdim unsigned last_line; 941218822Sdim int first; 94233965Sjdp}; 94333965Sjdp 94433965Sjdpstatic struct print_file_list *print_files; 94533965Sjdp 94633965Sjdp/* The number of preceding context lines to show when we start 94733965Sjdp displaying a file for the first time. */ 94833965Sjdp 94933965Sjdp#define SHOW_PRECEDING_CONTEXT_LINES (5) 95033965Sjdp 951218822Sdim/* Read a complete file into memory. */ 952218822Sdim 953218822Sdimstatic const char * 954218822Sdimslurp_file (const char *fn, size_t *size) 955218822Sdim{ 956218822Sdim#ifdef HAVE_MMAP 957218822Sdim int ps = getpagesize (); 958218822Sdim size_t msize; 959218822Sdim#endif 960218822Sdim const char *map; 961218822Sdim struct stat st; 962218822Sdim int fd = open (fn, O_RDONLY); 963218822Sdim 964218822Sdim if (fd < 0) 965218822Sdim return NULL; 966218822Sdim if (fstat (fd, &st) < 0) 967218822Sdim return NULL; 968218822Sdim *size = st.st_size; 969218822Sdim#ifdef HAVE_MMAP 970218822Sdim msize = (*size + ps - 1) & ~(ps - 1); 971218822Sdim map = mmap (NULL, msize, PROT_READ, MAP_SHARED, fd, 0); 972218822Sdim if (map != (char *)-1L) 973218822Sdim { 974218822Sdim close(fd); 975218822Sdim return map; 976218822Sdim } 977218822Sdim#endif 978218822Sdim map = malloc (*size); 979218822Sdim if (!map || (size_t) read (fd, (char *)map, *size) != *size) 980218822Sdim { 981218822Sdim free ((void *)map); 982218822Sdim map = NULL; 983218822Sdim } 984218822Sdim close (fd); 985218822Sdim return map; 986218822Sdim} 987218822Sdim 988218822Sdim#define line_map_decrease 5 989218822Sdim 990218822Sdim/* Precompute array of lines for a mapped file. */ 991218822Sdim 992218822Sdimstatic const char ** 993218822Sdimindex_file (const char *map, size_t size, unsigned int *maxline) 994218822Sdim{ 995218822Sdim const char *p, *lstart, *end; 996218822Sdim int chars_per_line = 45; /* First iteration will use 40. */ 997218822Sdim unsigned int lineno; 998218822Sdim const char **linemap = NULL; 999218822Sdim unsigned long line_map_size = 0; 1000218822Sdim 1001218822Sdim lineno = 0; 1002218822Sdim lstart = map; 1003218822Sdim end = map + size; 1004218822Sdim 1005218822Sdim for (p = map; p < end; p++) 1006218822Sdim { 1007218822Sdim if (*p == '\n') 1008218822Sdim { 1009218822Sdim if (p + 1 < end && p[1] == '\r') 1010218822Sdim p++; 1011218822Sdim } 1012218822Sdim else if (*p == '\r') 1013218822Sdim { 1014218822Sdim if (p + 1 < end && p[1] == '\n') 1015218822Sdim p++; 1016218822Sdim } 1017218822Sdim else 1018218822Sdim continue; 1019218822Sdim 1020218822Sdim /* End of line found. */ 1021218822Sdim 1022218822Sdim if (linemap == NULL || line_map_size < lineno + 1) 1023218822Sdim { 1024218822Sdim unsigned long newsize; 1025218822Sdim 1026218822Sdim chars_per_line -= line_map_decrease; 1027218822Sdim if (chars_per_line <= 1) 1028218822Sdim chars_per_line = 1; 1029218822Sdim line_map_size = size / chars_per_line + 1; 1030218822Sdim if (line_map_size < lineno + 1) 1031218822Sdim line_map_size = lineno + 1; 1032218822Sdim newsize = line_map_size * sizeof (char *); 1033218822Sdim linemap = xrealloc (linemap, newsize); 1034218822Sdim } 1035218822Sdim 1036218822Sdim linemap[lineno++] = lstart; 1037218822Sdim lstart = p + 1; 1038218822Sdim } 1039218822Sdim 1040218822Sdim *maxline = lineno; 1041218822Sdim return linemap; 1042218822Sdim} 1043218822Sdim 1044130561Sobrien/* Tries to open MODNAME, and if successful adds a node to print_files 1045130561Sobrien linked list and returns that node. Returns NULL on failure. */ 1046130561Sobrien 1047130561Sobrienstatic struct print_file_list * 1048130561Sobrientry_print_file_open (const char *origname, const char *modname) 1049130561Sobrien{ 1050130561Sobrien struct print_file_list *p; 1051130561Sobrien 1052218822Sdim p = xmalloc (sizeof (struct print_file_list)); 1053130561Sobrien 1054218822Sdim p->map = slurp_file (modname, &p->mapsize); 1055218822Sdim if (p->map == NULL) 1056130561Sobrien { 1057218822Sdim free (p); 1058218822Sdim return NULL; 1059130561Sobrien } 1060218822Sdim 1061218822Sdim p->linemap = index_file (p->map, p->mapsize, &p->maxline); 1062218822Sdim p->last_line = 0; 1063130561Sobrien p->filename = origname; 1064130561Sobrien p->modname = modname; 1065130561Sobrien p->next = print_files; 1066218822Sdim p->first = 1; 1067130561Sobrien print_files = p; 1068130561Sobrien return p; 1069130561Sobrien} 1070130561Sobrien 1071130561Sobrien/* If the the source file, as described in the symtab, is not found 1072130561Sobrien try to locate it in one of the paths specified with -I 1073130561Sobrien If found, add location to print_files linked list. */ 1074130561Sobrien 1075130561Sobrienstatic struct print_file_list * 1076130561Sobrienupdate_source_path (const char *filename) 1077130561Sobrien{ 1078130561Sobrien struct print_file_list *p; 1079130561Sobrien const char *fname; 1080130561Sobrien int i; 1081130561Sobrien 1082130561Sobrien if (filename == NULL) 1083130561Sobrien return NULL; 1084130561Sobrien 1085130561Sobrien p = try_print_file_open (filename, filename); 1086130561Sobrien if (p != NULL) 1087130561Sobrien return p; 1088130561Sobrien 1089130561Sobrien if (include_path_count == 0) 1090130561Sobrien return NULL; 1091130561Sobrien 1092130561Sobrien /* Get the name of the file. */ 1093130561Sobrien fname = strrchr (filename, '/'); 1094130561Sobrien#ifdef HAVE_DOS_BASED_FILE_SYSTEM 1095130561Sobrien { 1096130561Sobrien /* We could have a mixed forward/back slash case. */ 1097130561Sobrien char *backslash = strrchr (filename, '\\'); 1098130561Sobrien if (fname == NULL || (backslash != NULL && backslash > fname)) 1099130561Sobrien fname = backslash; 1100130561Sobrien if (fname == NULL && filename[0] != '\0' && filename[1] == ':') 1101130561Sobrien fname = filename + 1; 1102130561Sobrien } 1103130561Sobrien#endif 1104130561Sobrien if (fname == NULL) 1105130561Sobrien fname = filename; 1106130561Sobrien else 1107130561Sobrien ++fname; 1108130561Sobrien 1109130561Sobrien /* If file exists under a new path, we need to add it to the list 1110130561Sobrien so that show_line knows about it. */ 1111130561Sobrien for (i = 0; i < include_path_count; i++) 1112130561Sobrien { 1113130561Sobrien char *modname = concat (include_paths[i], "/", fname, (const char *) 0); 1114130561Sobrien 1115130561Sobrien p = try_print_file_open (filename, modname); 1116130561Sobrien if (p) 1117130561Sobrien return p; 1118130561Sobrien 1119130561Sobrien free (modname); 1120130561Sobrien } 1121130561Sobrien 1122130561Sobrien return NULL; 1123130561Sobrien} 1124130561Sobrien 1125218822Sdim/* Print a source file line. */ 112633965Sjdp 1127218822Sdimstatic void 1128218822Sdimprint_line (struct print_file_list *p, unsigned int line) 1129218822Sdim{ 1130218822Sdim const char *l; 1131218822Sdim 1132218822Sdim --line; 1133218822Sdim if (line >= p->maxline) 1134218822Sdim return; 1135218822Sdim l = p->linemap [line]; 1136218822Sdim fwrite (l, 1, strcspn (l, "\n\r"), stdout); 1137218822Sdim putchar ('\n'); 1138218822Sdim} 1139218822Sdim 1140218822Sdim/* Print a range of source code lines. */ 1141218822Sdim 114233965Sjdpstatic void 1143218822Sdimdump_lines (struct print_file_list *p, unsigned int start, unsigned int end) 114433965Sjdp{ 1145218822Sdim if (p->map == NULL) 1146218822Sdim return; 1147218822Sdim while (start <= end) 114833965Sjdp { 1149218822Sdim print_line (p, start); 1150218822Sdim start++; 115133965Sjdp } 1152104834Sobrien} 115333965Sjdp 1154130561Sobrien/* Show the line number, or the source line, in a disassembly 115533965Sjdp listing. */ 115633965Sjdp 115733965Sjdpstatic void 1158130561Sobrienshow_line (bfd *abfd, asection *section, bfd_vma addr_offset) 115933965Sjdp{ 1160104834Sobrien const char *filename; 1161104834Sobrien const char *functionname; 116233965Sjdp unsigned int line; 116333965Sjdp 116433965Sjdp if (! with_line_numbers && ! with_source_code) 116533965Sjdp return; 116633965Sjdp 116760484Sobrien if (! bfd_find_nearest_line (abfd, section, syms, addr_offset, &filename, 116833965Sjdp &functionname, &line)) 116933965Sjdp return; 117033965Sjdp 117133965Sjdp if (filename != NULL && *filename == '\0') 117233965Sjdp filename = NULL; 117333965Sjdp if (functionname != NULL && *functionname == '\0') 117433965Sjdp functionname = NULL; 117533965Sjdp 117633965Sjdp if (with_line_numbers) 117733965Sjdp { 117833965Sjdp if (functionname != NULL 117933965Sjdp && (prev_functionname == NULL 118033965Sjdp || strcmp (functionname, prev_functionname) != 0)) 118133965Sjdp printf ("%s():\n", functionname); 118233965Sjdp if (line > 0 && line != prev_line) 118333965Sjdp printf ("%s:%u\n", filename == NULL ? "???" : filename, line); 118433965Sjdp } 118533965Sjdp 118633965Sjdp if (with_source_code 118733965Sjdp && filename != NULL 118833965Sjdp && line > 0) 118933965Sjdp { 119033965Sjdp struct print_file_list **pp, *p; 1191218822Sdim unsigned l; 119233965Sjdp 119333965Sjdp for (pp = &print_files; *pp != NULL; pp = &(*pp)->next) 119433965Sjdp if (strcmp ((*pp)->filename, filename) == 0) 119533965Sjdp break; 119633965Sjdp p = *pp; 119733965Sjdp 1198218822Sdim if (p == NULL) 1199218822Sdim p = update_source_path (filename); 120033965Sjdp 1201218822Sdim if (p != NULL && line != p->last_line) 120233965Sjdp { 1203218822Sdim if (file_start_context && p->first) 1204218822Sdim l = 1; 1205218822Sdim else 120633965Sjdp { 1207218822Sdim l = line - SHOW_PRECEDING_CONTEXT_LINES; 1208218822Sdim if (l >= line) 1209218822Sdim l = 1; 1210218822Sdim if (p->last_line >= l && p->last_line <= line) 1211218822Sdim l = p->last_line + 1; 121233965Sjdp } 1213218822Sdim dump_lines (p, l, line); 1214218822Sdim p->last_line = line; 1215218822Sdim p->first = 0; 121633965Sjdp } 121733965Sjdp } 121833965Sjdp 121933965Sjdp if (functionname != NULL 122033965Sjdp && (prev_functionname == NULL 122133965Sjdp || strcmp (functionname, prev_functionname) != 0)) 122233965Sjdp { 122333965Sjdp if (prev_functionname != NULL) 122433965Sjdp free (prev_functionname); 122533965Sjdp prev_functionname = xmalloc (strlen (functionname) + 1); 122633965Sjdp strcpy (prev_functionname, functionname); 122733965Sjdp } 122833965Sjdp 122933965Sjdp if (line > 0 && line != prev_line) 123033965Sjdp prev_line = line; 123133965Sjdp} 123233965Sjdp 123333965Sjdp/* Pseudo FILE object for strings. */ 123460484Sobrientypedef struct 123560484Sobrien{ 123633965Sjdp char *buffer; 1237218822Sdim size_t pos; 1238218822Sdim size_t alloc; 123933965Sjdp} SFILE; 124033965Sjdp 1241130561Sobrien/* sprintf to a "stream". */ 124233965Sjdp 1243218822Sdimstatic int ATTRIBUTE_PRINTF_2 1244130561Sobrienobjdump_sprintf (SFILE *f, const char *format, ...) 124533965Sjdp{ 124660484Sobrien size_t n; 1247130561Sobrien va_list args; 124833965Sjdp 1249218822Sdim while (1) 125060484Sobrien { 1251218822Sdim size_t space = f->alloc - f->pos; 1252218822Sdim 1253218822Sdim va_start (args, format); 1254218822Sdim n = vsnprintf (f->buffer + f->pos, space, format, args); 125589857Sobrien va_end (args); 125660484Sobrien 1257218822Sdim if (space > n) 1258218822Sdim break; 1259218822Sdim 1260218822Sdim f->alloc = (f->alloc + n) * 2; 1261218822Sdim f->buffer = xrealloc (f->buffer, f->alloc); 126260484Sobrien } 1263218822Sdim f->pos += n; 1264218822Sdim 126533965Sjdp return n; 126633965Sjdp} 126733965Sjdp 1268130561Sobrien/* Returns TRUE if the specified section should be dumped. */ 1269130561Sobrien 1270130561Sobrienstatic bfd_boolean 1271130561Sobrienprocess_section_p (asection * section) 1272130561Sobrien{ 1273130561Sobrien size_t i; 1274130561Sobrien 1275130561Sobrien if (only == NULL) 1276130561Sobrien return TRUE; 1277130561Sobrien 1278130561Sobrien for (i = 0; i < only_used; i++) 1279130561Sobrien if (strcmp (only [i], section->name) == 0) 1280130561Sobrien return TRUE; 1281130561Sobrien 1282130561Sobrien return FALSE; 1283130561Sobrien} 1284130561Sobrien 1285130561Sobrien 128633965Sjdp/* The number of zeroes we want to see before we start skipping them. 128733965Sjdp The number is arbitrarily chosen. */ 128833965Sjdp 1289218822Sdim#define DEFAULT_SKIP_ZEROES 8 129033965Sjdp 129133965Sjdp/* The number of zeroes to skip at the end of a section. If the 129233965Sjdp number of zeroes at the end is between SKIP_ZEROES_AT_END and 129333965Sjdp SKIP_ZEROES, they will be disassembled. If there are fewer than 129433965Sjdp SKIP_ZEROES_AT_END, they will be skipped. This is a heuristic 129533965Sjdp attempt to avoid disassembling zeroes inserted by section 129633965Sjdp alignment. */ 129733965Sjdp 1298218822Sdim#define DEFAULT_SKIP_ZEROES_AT_END 3 129933965Sjdp 130033965Sjdp/* Disassemble some data in memory between given values. */ 130133965Sjdp 130233965Sjdpstatic void 1303130561Sobriendisassemble_bytes (struct disassemble_info * info, 1304130561Sobrien disassembler_ftype disassemble_fn, 1305130561Sobrien bfd_boolean insns, 1306130561Sobrien bfd_byte * data, 1307130561Sobrien bfd_vma start_offset, 1308130561Sobrien bfd_vma stop_offset, 1309130561Sobrien bfd_vma rel_offset, 1310130561Sobrien arelent *** relppp, 1311130561Sobrien arelent ** relppend) 131233965Sjdp{ 131333965Sjdp struct objdump_disasm_info *aux; 131433965Sjdp asection *section; 131560484Sobrien int octets_per_line; 1316130561Sobrien bfd_boolean done_dot; 131733965Sjdp int skip_addr_chars; 131860484Sobrien bfd_vma addr_offset; 1319218822Sdim unsigned int opb = info->octets_per_byte; 1320218822Sdim unsigned int skip_zeroes = info->skip_zeroes; 1321218822Sdim unsigned int skip_zeroes_at_end = info->skip_zeroes_at_end; 1322218822Sdim int octets = opb; 1323218822Sdim SFILE sfile; 132433965Sjdp 132533965Sjdp aux = (struct objdump_disasm_info *) info->application_data; 132633965Sjdp section = aux->sec; 132733965Sjdp 1328218822Sdim sfile.alloc = 120; 1329218822Sdim sfile.buffer = xmalloc (sfile.alloc); 1330218822Sdim sfile.pos = 0; 1331218822Sdim 133233965Sjdp if (insns) 133360484Sobrien octets_per_line = 4; 133433965Sjdp else 133560484Sobrien octets_per_line = 16; 133633965Sjdp 133733965Sjdp /* Figure out how many characters to skip at the start of an 133833965Sjdp address, to make the disassembly look nicer. We discard leading 133933965Sjdp zeroes in chunks of 4, ensuring that there is always a leading 134033965Sjdp zero remaining. */ 134133965Sjdp skip_addr_chars = 0; 134233965Sjdp if (! prefix_addresses) 134333965Sjdp { 134433965Sjdp char buf[30]; 134533965Sjdp char *s; 134633965Sjdp 134789857Sobrien bfd_sprintf_vma 134889857Sobrien (aux->abfd, buf, 134989857Sobrien (section->vma 135089857Sobrien + bfd_section_size (section->owner, section) / opb)); 135133965Sjdp s = buf; 135233965Sjdp while (s[0] == '0' && s[1] == '0' && s[2] == '0' && s[3] == '0' 135333965Sjdp && s[4] == '0') 135433965Sjdp { 135533965Sjdp skip_addr_chars += 4; 135633965Sjdp s += 4; 135733965Sjdp } 135833965Sjdp } 135933965Sjdp 136033965Sjdp info->insn_info_valid = 0; 136133965Sjdp 1362130561Sobrien done_dot = FALSE; 136360484Sobrien addr_offset = start_offset; 136460484Sobrien while (addr_offset < stop_offset) 136533965Sjdp { 136660484Sobrien bfd_vma z; 1367130561Sobrien bfd_boolean need_nl = FALSE; 1368218822Sdim int previous_octets; 136933965Sjdp 1370218822Sdim /* Remember the length of the previous instruction. */ 1371218822Sdim previous_octets = octets; 1372218822Sdim octets = 0; 1373218822Sdim 137460484Sobrien /* If we see more than SKIP_ZEROES octets of zeroes, we just 1375130561Sobrien print `...'. */ 137660484Sobrien for (z = addr_offset * opb; z < stop_offset * opb; z++) 137733965Sjdp if (data[z] != 0) 137833965Sjdp break; 137933965Sjdp if (! disassemble_zeroes 138033965Sjdp && (info->insn_info_valid == 0 138133965Sjdp || info->branch_delay_insns == 0) 1382218822Sdim && (z - addr_offset * opb >= skip_zeroes 1383104834Sobrien || (z == stop_offset * opb && 1384218822Sdim z - addr_offset * opb < skip_zeroes_at_end))) 138533965Sjdp { 138633965Sjdp printf ("\t...\n"); 138733965Sjdp 138860484Sobrien /* If there are more nonzero octets to follow, we only skip 1389130561Sobrien zeroes in multiples of 4, to try to avoid running over 1390130561Sobrien the start of an instruction which happens to start with 1391130561Sobrien zero. */ 139260484Sobrien if (z != stop_offset * opb) 139360484Sobrien z = addr_offset * opb + ((z - addr_offset * opb) &~ 3); 139433965Sjdp 139560484Sobrien octets = z - addr_offset * opb; 139633965Sjdp } 139733965Sjdp else 139833965Sjdp { 139960484Sobrien char buf[50]; 140038889Sjdp int bpc = 0; 140138889Sjdp int pb = 0; 140233965Sjdp 1403130561Sobrien done_dot = FALSE; 140433965Sjdp 140533965Sjdp if (with_line_numbers || with_source_code) 1406218822Sdim show_line (aux->abfd, section, addr_offset); 140733965Sjdp 140833965Sjdp if (! prefix_addresses) 140933965Sjdp { 141033965Sjdp char *s; 141133965Sjdp 141289857Sobrien bfd_sprintf_vma (aux->abfd, buf, section->vma + addr_offset); 141333965Sjdp for (s = buf + skip_addr_chars; *s == '0'; s++) 141433965Sjdp *s = ' '; 141533965Sjdp if (*s == '\0') 141633965Sjdp *--s = '0'; 141733965Sjdp printf ("%s:\t", buf + skip_addr_chars); 141833965Sjdp } 141933965Sjdp else 142033965Sjdp { 1421130561Sobrien aux->require_sec = TRUE; 142260484Sobrien objdump_print_address (section->vma + addr_offset, info); 1423130561Sobrien aux->require_sec = FALSE; 142433965Sjdp putchar (' '); 142533965Sjdp } 142633965Sjdp 142733965Sjdp if (insns) 142833965Sjdp { 1429218822Sdim sfile.pos = 0; 143033965Sjdp info->fprintf_func = (fprintf_ftype) objdump_sprintf; 1431218822Sdim info->stream = &sfile; 143233965Sjdp info->bytes_per_line = 0; 143333965Sjdp info->bytes_per_chunk = 0; 1434218822Sdim info->flags = 0; 143560484Sobrien 1436218822Sdim if (info->disassembler_needs_relocs 1437218822Sdim && (bfd_get_file_flags (aux->abfd) & EXEC_P) == 0 1438218822Sdim && (bfd_get_file_flags (aux->abfd) & DYNAMIC) == 0 1439218822Sdim && *relppp < relppend) 1440218822Sdim { 1441218822Sdim bfd_signed_vma distance_to_rel; 144260484Sobrien 1443218822Sdim distance_to_rel = (**relppp)->address 1444218822Sdim - (rel_offset + addr_offset); 1445218822Sdim 1446218822Sdim /* Check to see if the current reloc is associated with 1447218822Sdim the instruction that we are about to disassemble. */ 1448218822Sdim if (distance_to_rel == 0 1449218822Sdim /* FIXME: This is wrong. We are trying to catch 1450218822Sdim relocs that are addressed part way through the 1451218822Sdim current instruction, as might happen with a packed 1452218822Sdim VLIW instruction. Unfortunately we do not know the 1453218822Sdim length of the current instruction since we have not 1454218822Sdim disassembled it yet. Instead we take a guess based 1455218822Sdim upon the length of the previous instruction. The 1456218822Sdim proper solution is to have a new target-specific 1457218822Sdim disassembler function which just returns the length 1458218822Sdim of an instruction at a given address without trying 1459218822Sdim to display its disassembly. */ 1460218822Sdim || (distance_to_rel > 0 1461218822Sdim && distance_to_rel < (bfd_signed_vma) (previous_octets/ opb))) 1462218822Sdim { 1463218822Sdim info->flags = INSN_HAS_RELOC; 1464218822Sdim aux->reloc = **relppp; 1465218822Sdim } 1466218822Sdim else 1467218822Sdim aux->reloc = NULL; 1468218822Sdim } 1469218822Sdim 147060484Sobrien octets = (*disassemble_fn) (section->vma + addr_offset, info); 147133965Sjdp info->fprintf_func = (fprintf_ftype) fprintf; 147233965Sjdp info->stream = stdout; 147333965Sjdp if (info->bytes_per_line != 0) 147460484Sobrien octets_per_line = info->bytes_per_line; 147560484Sobrien if (octets < 0) 147660484Sobrien { 1477218822Sdim if (sfile.pos) 147860484Sobrien printf ("%s\n", sfile.buffer); 147960484Sobrien break; 148060484Sobrien } 148133965Sjdp } 148233965Sjdp else 148333965Sjdp { 148460484Sobrien bfd_vma j; 148533965Sjdp 148660484Sobrien octets = octets_per_line; 148760484Sobrien if (addr_offset + octets / opb > stop_offset) 148860484Sobrien octets = (stop_offset - addr_offset) * opb; 148933965Sjdp 149060484Sobrien for (j = addr_offset * opb; j < addr_offset * opb + octets; ++j) 149133965Sjdp { 149289857Sobrien if (ISPRINT (data[j])) 149360484Sobrien buf[j - addr_offset * opb] = data[j]; 149433965Sjdp else 149560484Sobrien buf[j - addr_offset * opb] = '.'; 149633965Sjdp } 149760484Sobrien buf[j - addr_offset * opb] = '\0'; 149833965Sjdp } 149933965Sjdp 150033965Sjdp if (prefix_addresses 150133965Sjdp ? show_raw_insn > 0 150233965Sjdp : show_raw_insn >= 0) 150333965Sjdp { 150460484Sobrien bfd_vma j; 150533965Sjdp 150633965Sjdp /* If ! prefix_addresses and ! wide_output, we print 1507130561Sobrien octets_per_line octets per line. */ 150860484Sobrien pb = octets; 150960484Sobrien if (pb > octets_per_line && ! prefix_addresses && ! wide_output) 151060484Sobrien pb = octets_per_line; 151133965Sjdp 151233965Sjdp if (info->bytes_per_chunk) 151333965Sjdp bpc = info->bytes_per_chunk; 151433965Sjdp else 151533965Sjdp bpc = 1; 151633965Sjdp 151760484Sobrien for (j = addr_offset * opb; j < addr_offset * opb + pb; j += bpc) 151833965Sjdp { 151933965Sjdp int k; 1520218822Sdim 152133965Sjdp if (bpc > 1 && info->display_endian == BFD_ENDIAN_LITTLE) 152233965Sjdp { 152333965Sjdp for (k = bpc - 1; k >= 0; k--) 152433965Sjdp printf ("%02x", (unsigned) data[j + k]); 152533965Sjdp putchar (' '); 152633965Sjdp } 152733965Sjdp else 152833965Sjdp { 152933965Sjdp for (k = 0; k < bpc; k++) 153033965Sjdp printf ("%02x", (unsigned) data[j + k]); 153133965Sjdp putchar (' '); 153233965Sjdp } 153333965Sjdp } 153433965Sjdp 153560484Sobrien for (; pb < octets_per_line; pb += bpc) 153633965Sjdp { 153733965Sjdp int k; 153833965Sjdp 153933965Sjdp for (k = 0; k < bpc; k++) 154033965Sjdp printf (" "); 154133965Sjdp putchar (' '); 154233965Sjdp } 154333965Sjdp 154433965Sjdp /* Separate raw data from instruction by extra space. */ 154533965Sjdp if (insns) 154633965Sjdp putchar ('\t'); 154733965Sjdp else 154833965Sjdp printf (" "); 154933965Sjdp } 155033965Sjdp 155160484Sobrien if (! insns) 155260484Sobrien printf ("%s", buf); 1553218822Sdim else if (sfile.pos) 1554218822Sdim printf ("%s", sfile.buffer); 155533965Sjdp 155633965Sjdp if (prefix_addresses 155733965Sjdp ? show_raw_insn > 0 155833965Sjdp : show_raw_insn >= 0) 155933965Sjdp { 156060484Sobrien while (pb < octets) 156133965Sjdp { 156260484Sobrien bfd_vma j; 156333965Sjdp char *s; 156433965Sjdp 156533965Sjdp putchar ('\n'); 156660484Sobrien j = addr_offset * opb + pb; 156733965Sjdp 156889857Sobrien bfd_sprintf_vma (aux->abfd, buf, section->vma + j / opb); 156933965Sjdp for (s = buf + skip_addr_chars; *s == '0'; s++) 157033965Sjdp *s = ' '; 157133965Sjdp if (*s == '\0') 157233965Sjdp *--s = '0'; 157333965Sjdp printf ("%s:\t", buf + skip_addr_chars); 157433965Sjdp 157560484Sobrien pb += octets_per_line; 157660484Sobrien if (pb > octets) 157760484Sobrien pb = octets; 157860484Sobrien for (; j < addr_offset * opb + pb; j += bpc) 157933965Sjdp { 158033965Sjdp int k; 158133965Sjdp 158233965Sjdp if (bpc > 1 && info->display_endian == BFD_ENDIAN_LITTLE) 158333965Sjdp { 158433965Sjdp for (k = bpc - 1; k >= 0; k--) 158533965Sjdp printf ("%02x", (unsigned) data[j + k]); 158633965Sjdp putchar (' '); 158733965Sjdp } 158833965Sjdp else 158933965Sjdp { 159033965Sjdp for (k = 0; k < bpc; k++) 159133965Sjdp printf ("%02x", (unsigned) data[j + k]); 159233965Sjdp putchar (' '); 159333965Sjdp } 159433965Sjdp } 159533965Sjdp } 159633965Sjdp } 159733965Sjdp 159833965Sjdp if (!wide_output) 159933965Sjdp putchar ('\n'); 160033965Sjdp else 1601130561Sobrien need_nl = TRUE; 160233965Sjdp } 160333965Sjdp 1604130561Sobrien while ((*relppp) < relppend 1605130561Sobrien && (**relppp)->address < rel_offset + addr_offset + octets / opb) 160633965Sjdp { 1607130561Sobrien if (dump_reloc_info || dump_dynamic_reloc_info) 160833965Sjdp { 160933965Sjdp arelent *q; 161033965Sjdp 161133965Sjdp q = **relppp; 161233965Sjdp 161333965Sjdp if (wide_output) 161433965Sjdp putchar ('\t'); 161533965Sjdp else 161633965Sjdp printf ("\t\t\t"); 161733965Sjdp 1618130561Sobrien objdump_print_value (section->vma - rel_offset + q->address, 1619130561Sobrien info, TRUE); 162033965Sjdp 1621218822Sdim if (q->howto == NULL) 1622218822Sdim printf (": *unknown*\t"); 1623218822Sdim else if (q->howto->name) 1624218822Sdim printf (": %s\t", q->howto->name); 1625218822Sdim else 1626218822Sdim printf (": %d\t", q->howto->type); 162733965Sjdp 162833965Sjdp if (q->sym_ptr_ptr == NULL || *q->sym_ptr_ptr == NULL) 162933965Sjdp printf ("*unknown*"); 163033965Sjdp else 163133965Sjdp { 163233965Sjdp const char *sym_name; 163333965Sjdp 163433965Sjdp sym_name = bfd_asymbol_name (*q->sym_ptr_ptr); 163533965Sjdp if (sym_name != NULL && *sym_name != '\0') 163633965Sjdp objdump_print_symname (aux->abfd, info, *q->sym_ptr_ptr); 163733965Sjdp else 163833965Sjdp { 163933965Sjdp asection *sym_sec; 164033965Sjdp 164133965Sjdp sym_sec = bfd_get_section (*q->sym_ptr_ptr); 164233965Sjdp sym_name = bfd_get_section_name (aux->abfd, sym_sec); 164333965Sjdp if (sym_name == NULL || *sym_name == '\0') 164433965Sjdp sym_name = "*unknown*"; 164533965Sjdp printf ("%s", sym_name); 164633965Sjdp } 164733965Sjdp } 164833965Sjdp 164933965Sjdp if (q->addend) 165033965Sjdp { 165133965Sjdp printf ("+0x"); 1652130561Sobrien objdump_print_value (q->addend, info, TRUE); 165333965Sjdp } 165433965Sjdp 165533965Sjdp printf ("\n"); 1656130561Sobrien need_nl = FALSE; 165733965Sjdp } 1658130561Sobrien ++(*relppp); 165933965Sjdp } 166033965Sjdp 166133965Sjdp if (need_nl) 166233965Sjdp printf ("\n"); 166333965Sjdp 166460484Sobrien addr_offset += octets / opb; 166533965Sjdp } 1666218822Sdim 1667218822Sdim free (sfile.buffer); 166833965Sjdp} 166933965Sjdp 1670130561Sobrienstatic void 1671130561Sobriendisassemble_section (bfd *abfd, asection *section, void *info) 1672130561Sobrien{ 1673130561Sobrien struct disassemble_info * pinfo = (struct disassemble_info *) info; 1674130561Sobrien struct objdump_disasm_info * paux; 1675130561Sobrien unsigned int opb = pinfo->octets_per_byte; 1676130561Sobrien bfd_byte * data = NULL; 1677130561Sobrien bfd_size_type datasize = 0; 1678130561Sobrien arelent ** rel_pp = NULL; 1679130561Sobrien arelent ** rel_ppstart = NULL; 1680130561Sobrien arelent ** rel_ppend; 1681130561Sobrien unsigned long stop_offset; 1682130561Sobrien asymbol * sym = NULL; 1683130561Sobrien long place = 0; 1684130561Sobrien long rel_count; 1685130561Sobrien bfd_vma rel_offset; 1686130561Sobrien unsigned long addr_offset; 1687130561Sobrien 1688130561Sobrien /* Sections that do not contain machine 1689130561Sobrien code are not normally disassembled. */ 1690130561Sobrien if (! disassemble_all 1691130561Sobrien && only == NULL 1692218822Sdim && ((section->flags & (SEC_CODE | SEC_HAS_CONTENTS)) 1693218822Sdim != (SEC_CODE | SEC_HAS_CONTENTS))) 1694130561Sobrien return; 1695130561Sobrien 1696130561Sobrien if (! process_section_p (section)) 1697130561Sobrien return; 1698130561Sobrien 1699218822Sdim datasize = bfd_get_section_size (section); 1700130561Sobrien if (datasize == 0) 1701130561Sobrien return; 1702130561Sobrien 1703130561Sobrien /* Decide which set of relocs to use. Load them if necessary. */ 1704130561Sobrien paux = (struct objdump_disasm_info *) pinfo->application_data; 1705130561Sobrien if (paux->dynrelbuf) 1706130561Sobrien { 1707130561Sobrien rel_pp = paux->dynrelbuf; 1708130561Sobrien rel_count = paux->dynrelcount; 1709130561Sobrien /* Dynamic reloc addresses are absolute, non-dynamic are section 1710130561Sobrien relative. REL_OFFSET specifies the reloc address corresponding 1711130561Sobrien to the start of this section. */ 1712130561Sobrien rel_offset = section->vma; 1713130561Sobrien } 1714130561Sobrien else 1715130561Sobrien { 1716130561Sobrien rel_count = 0; 1717130561Sobrien rel_pp = NULL; 1718130561Sobrien rel_offset = 0; 1719130561Sobrien 1720130561Sobrien if ((section->flags & SEC_RELOC) != 0 1721218822Sdim && (dump_reloc_info || pinfo->disassembler_needs_relocs)) 1722130561Sobrien { 1723130561Sobrien long relsize; 1724130561Sobrien 1725130561Sobrien relsize = bfd_get_reloc_upper_bound (abfd, section); 1726130561Sobrien if (relsize < 0) 1727130561Sobrien bfd_fatal (bfd_get_filename (abfd)); 1728130561Sobrien 1729130561Sobrien if (relsize > 0) 1730130561Sobrien { 1731130561Sobrien rel_ppstart = rel_pp = xmalloc (relsize); 1732130561Sobrien rel_count = bfd_canonicalize_reloc (abfd, section, rel_pp, syms); 1733130561Sobrien if (rel_count < 0) 1734130561Sobrien bfd_fatal (bfd_get_filename (abfd)); 1735130561Sobrien 1736130561Sobrien /* Sort the relocs by address. */ 1737130561Sobrien qsort (rel_pp, rel_count, sizeof (arelent *), compare_relocs); 1738130561Sobrien } 1739130561Sobrien } 1740130561Sobrien 1741130561Sobrien } 1742130561Sobrien rel_ppend = rel_pp + rel_count; 1743130561Sobrien 1744130561Sobrien data = xmalloc (datasize); 1745130561Sobrien 1746130561Sobrien bfd_get_section_contents (abfd, section, data, 0, datasize); 1747130561Sobrien 1748130561Sobrien paux->sec = section; 1749130561Sobrien pinfo->buffer = data; 1750130561Sobrien pinfo->buffer_vma = section->vma; 1751130561Sobrien pinfo->buffer_length = datasize; 1752130561Sobrien pinfo->section = section; 1753130561Sobrien 1754130561Sobrien if (start_address == (bfd_vma) -1 1755130561Sobrien || start_address < pinfo->buffer_vma) 1756130561Sobrien addr_offset = 0; 1757130561Sobrien else 1758130561Sobrien addr_offset = start_address - pinfo->buffer_vma; 1759130561Sobrien 1760130561Sobrien if (stop_address == (bfd_vma) -1) 1761130561Sobrien stop_offset = datasize / opb; 1762130561Sobrien else 1763130561Sobrien { 1764130561Sobrien if (stop_address < pinfo->buffer_vma) 1765130561Sobrien stop_offset = 0; 1766130561Sobrien else 1767130561Sobrien stop_offset = stop_address - pinfo->buffer_vma; 1768130561Sobrien if (stop_offset > pinfo->buffer_length / opb) 1769130561Sobrien stop_offset = pinfo->buffer_length / opb; 1770130561Sobrien } 1771130561Sobrien 1772130561Sobrien /* Skip over the relocs belonging to addresses below the 1773130561Sobrien start address. */ 1774130561Sobrien while (rel_pp < rel_ppend 1775130561Sobrien && (*rel_pp)->address < rel_offset + addr_offset) 1776130561Sobrien ++rel_pp; 1777130561Sobrien 1778130561Sobrien printf (_("Disassembly of section %s:\n"), section->name); 1779130561Sobrien 1780130561Sobrien /* Find the nearest symbol forwards from our current position. */ 1781130561Sobrien paux->require_sec = TRUE; 1782130561Sobrien sym = find_symbol_for_address (section->vma + addr_offset, info, &place); 1783130561Sobrien paux->require_sec = FALSE; 1784130561Sobrien 1785130561Sobrien /* Disassemble a block of instructions up to the address associated with 1786130561Sobrien the symbol we have just found. Then print the symbol and find the 1787130561Sobrien next symbol on. Repeat until we have disassembled the entire section 1788130561Sobrien or we have reached the end of the address range we are interested in. */ 1789130561Sobrien while (addr_offset < stop_offset) 1790130561Sobrien { 1791130561Sobrien bfd_vma addr; 1792130561Sobrien asymbol *nextsym; 1793130561Sobrien unsigned long nextstop_offset; 1794130561Sobrien bfd_boolean insns; 1795130561Sobrien 1796130561Sobrien addr = section->vma + addr_offset; 1797130561Sobrien 1798130561Sobrien if (sym != NULL && bfd_asymbol_value (sym) <= addr) 1799130561Sobrien { 1800130561Sobrien int x; 1801130561Sobrien 1802130561Sobrien for (x = place; 1803130561Sobrien (x < sorted_symcount 1804130561Sobrien && (bfd_asymbol_value (sorted_syms[x]) <= addr)); 1805130561Sobrien ++x) 1806130561Sobrien continue; 1807130561Sobrien 1808130561Sobrien pinfo->symbols = sorted_syms + place; 1809130561Sobrien pinfo->num_symbols = x - place; 1810218822Sdim pinfo->symtab_pos = place; 1811130561Sobrien } 1812130561Sobrien else 1813130561Sobrien { 1814130561Sobrien pinfo->symbols = NULL; 1815130561Sobrien pinfo->num_symbols = 0; 1816218822Sdim pinfo->symtab_pos = -1; 1817130561Sobrien } 1818130561Sobrien 1819130561Sobrien if (! prefix_addresses) 1820130561Sobrien { 1821130561Sobrien pinfo->fprintf_func (pinfo->stream, "\n"); 1822130561Sobrien objdump_print_addr_with_sym (abfd, section, sym, addr, 1823130561Sobrien pinfo, FALSE); 1824130561Sobrien pinfo->fprintf_func (pinfo->stream, ":\n"); 1825130561Sobrien } 1826130561Sobrien 1827130561Sobrien if (sym != NULL && bfd_asymbol_value (sym) > addr) 1828130561Sobrien nextsym = sym; 1829130561Sobrien else if (sym == NULL) 1830130561Sobrien nextsym = NULL; 1831130561Sobrien else 1832130561Sobrien { 1833130561Sobrien#define is_valid_next_sym(SYM) \ 1834130561Sobrien ((SYM)->section == section \ 1835130561Sobrien && (bfd_asymbol_value (SYM) > bfd_asymbol_value (sym)) \ 1836130561Sobrien && pinfo->symbol_is_valid (SYM, pinfo)) 1837130561Sobrien 1838130561Sobrien /* Search forward for the next appropriate symbol in 1839130561Sobrien SECTION. Note that all the symbols are sorted 1840130561Sobrien together into one big array, and that some sections 1841130561Sobrien may have overlapping addresses. */ 1842130561Sobrien while (place < sorted_symcount 1843130561Sobrien && ! is_valid_next_sym (sorted_syms [place])) 1844130561Sobrien ++place; 1845130561Sobrien 1846130561Sobrien if (place >= sorted_symcount) 1847130561Sobrien nextsym = NULL; 1848130561Sobrien else 1849130561Sobrien nextsym = sorted_syms[place]; 1850130561Sobrien } 1851130561Sobrien 1852130561Sobrien if (sym != NULL && bfd_asymbol_value (sym) > addr) 1853130561Sobrien nextstop_offset = bfd_asymbol_value (sym) - section->vma; 1854130561Sobrien else if (nextsym == NULL) 1855130561Sobrien nextstop_offset = stop_offset; 1856130561Sobrien else 1857130561Sobrien nextstop_offset = bfd_asymbol_value (nextsym) - section->vma; 1858130561Sobrien 1859130561Sobrien if (nextstop_offset > stop_offset) 1860130561Sobrien nextstop_offset = stop_offset; 1861130561Sobrien 1862130561Sobrien /* If a symbol is explicitly marked as being an object 1863130561Sobrien rather than a function, just dump the bytes without 1864130561Sobrien disassembling them. */ 1865130561Sobrien if (disassemble_all 1866130561Sobrien || sym == NULL 1867130561Sobrien || bfd_asymbol_value (sym) > addr 1868130561Sobrien || ((sym->flags & BSF_OBJECT) == 0 1869130561Sobrien && (strstr (bfd_asymbol_name (sym), "gnu_compiled") 1870130561Sobrien == NULL) 1871130561Sobrien && (strstr (bfd_asymbol_name (sym), "gcc2_compiled") 1872130561Sobrien == NULL)) 1873130561Sobrien || (sym->flags & BSF_FUNCTION) != 0) 1874130561Sobrien insns = TRUE; 1875130561Sobrien else 1876130561Sobrien insns = FALSE; 1877130561Sobrien 1878130561Sobrien disassemble_bytes (pinfo, paux->disassemble_fn, insns, data, 1879130561Sobrien addr_offset, nextstop_offset, 1880130561Sobrien rel_offset, &rel_pp, rel_ppend); 1881130561Sobrien 1882130561Sobrien addr_offset = nextstop_offset; 1883130561Sobrien sym = nextsym; 1884130561Sobrien } 1885130561Sobrien 1886130561Sobrien free (data); 1887130561Sobrien 1888130561Sobrien if (rel_ppstart != NULL) 1889130561Sobrien free (rel_ppstart); 1890130561Sobrien} 1891130561Sobrien 189233965Sjdp/* Disassemble the contents of an object file. */ 189333965Sjdp 189433965Sjdpstatic void 1895130561Sobriendisassemble_data (bfd *abfd) 189633965Sjdp{ 189733965Sjdp struct disassemble_info disasm_info; 189833965Sjdp struct objdump_disasm_info aux; 1899218822Sdim long i; 190033965Sjdp 190133965Sjdp print_files = NULL; 190233965Sjdp prev_functionname = NULL; 190333965Sjdp prev_line = -1; 190433965Sjdp 190533965Sjdp /* We make a copy of syms to sort. We don't want to sort syms 190633965Sjdp because that will screw up the relocs. */ 1907218822Sdim sorted_symcount = symcount ? symcount : dynsymcount; 1908218822Sdim sorted_syms = xmalloc ((sorted_symcount + synthcount) * sizeof (asymbol *)); 1909218822Sdim memcpy (sorted_syms, symcount ? syms : dynsyms, 1910218822Sdim sorted_symcount * sizeof (asymbol *)); 191133965Sjdp 1912218822Sdim sorted_symcount = remove_useless_symbols (sorted_syms, sorted_symcount); 191333965Sjdp 1914218822Sdim for (i = 0; i < synthcount; ++i) 1915218822Sdim { 1916218822Sdim sorted_syms[sorted_symcount] = synthsyms + i; 1917218822Sdim ++sorted_symcount; 1918218822Sdim } 1919218822Sdim 1920130561Sobrien /* Sort the symbols into section and symbol order. */ 192133965Sjdp qsort (sorted_syms, sorted_symcount, sizeof (asymbol *), compare_symbols); 192233965Sjdp 1923130561Sobrien init_disassemble_info (&disasm_info, stdout, (fprintf_ftype) fprintf); 1924130561Sobrien 1925130561Sobrien disasm_info.application_data = (void *) &aux; 192633965Sjdp aux.abfd = abfd; 1927130561Sobrien aux.require_sec = FALSE; 1928130561Sobrien aux.dynrelbuf = NULL; 1929130561Sobrien aux.dynrelcount = 0; 1930218822Sdim aux.reloc = NULL; 1931130561Sobrien 193233965Sjdp disasm_info.print_address_func = objdump_print_address; 193338889Sjdp disasm_info.symbol_at_address_func = objdump_symbol_at_address; 193433965Sjdp 1935130561Sobrien if (machine != NULL) 193633965Sjdp { 193733965Sjdp const bfd_arch_info_type *info = bfd_scan_arch (machine); 1938130561Sobrien 193933965Sjdp if (info == NULL) 1940130561Sobrien fatal (_("Can't use supplied machine %s"), machine); 1941130561Sobrien 194233965Sjdp abfd->arch_info = info; 194333965Sjdp } 194433965Sjdp 194533965Sjdp if (endian != BFD_ENDIAN_UNKNOWN) 194633965Sjdp { 194733965Sjdp struct bfd_target *xvec; 194833965Sjdp 1949130561Sobrien xvec = xmalloc (sizeof (struct bfd_target)); 195033965Sjdp memcpy (xvec, abfd->xvec, sizeof (struct bfd_target)); 195133965Sjdp xvec->byteorder = endian; 195233965Sjdp abfd->xvec = xvec; 195333965Sjdp } 195433965Sjdp 1955130561Sobrien /* Use libopcodes to locate a suitable disassembler. */ 1956130561Sobrien aux.disassemble_fn = disassembler (abfd); 1957130561Sobrien if (!aux.disassemble_fn) 195833965Sjdp { 195960484Sobrien non_fatal (_("Can't disassemble for architecture %s\n"), 196060484Sobrien bfd_printable_arch_mach (bfd_get_arch (abfd), 0)); 196160484Sobrien exit_status = 1; 196233965Sjdp return; 196333965Sjdp } 196433965Sjdp 196533965Sjdp disasm_info.flavour = bfd_get_flavour (abfd); 196633965Sjdp disasm_info.arch = bfd_get_arch (abfd); 196733965Sjdp disasm_info.mach = bfd_get_mach (abfd); 196860484Sobrien disasm_info.disassembler_options = disassembler_options; 1969130561Sobrien disasm_info.octets_per_byte = bfd_octets_per_byte (abfd); 1970218822Sdim disasm_info.skip_zeroes = DEFAULT_SKIP_ZEROES; 1971218822Sdim disasm_info.skip_zeroes_at_end = DEFAULT_SKIP_ZEROES_AT_END; 1972218822Sdim disasm_info.disassembler_needs_relocs = FALSE; 1973104834Sobrien 197433965Sjdp if (bfd_big_endian (abfd)) 197560484Sobrien disasm_info.display_endian = disasm_info.endian = BFD_ENDIAN_BIG; 197633965Sjdp else if (bfd_little_endian (abfd)) 197760484Sobrien disasm_info.display_endian = disasm_info.endian = BFD_ENDIAN_LITTLE; 197833965Sjdp else 197933965Sjdp /* ??? Aborting here seems too drastic. We could default to big or little 198033965Sjdp instead. */ 198133965Sjdp disasm_info.endian = BFD_ENDIAN_UNKNOWN; 198233965Sjdp 1983130561Sobrien /* Allow the target to customize the info structure. */ 1984130561Sobrien disassemble_init_for_target (& disasm_info); 1985130561Sobrien 1986130561Sobrien /* Pre-load the dynamic relocs if we are going 1987130561Sobrien to be dumping them along with the disassembly. */ 1988130561Sobrien if (dump_dynamic_reloc_info) 198933965Sjdp { 1990130561Sobrien long relsize = bfd_get_dynamic_reloc_upper_bound (abfd); 1991130561Sobrien 1992130561Sobrien if (relsize < 0) 1993130561Sobrien bfd_fatal (bfd_get_filename (abfd)); 199433965Sjdp 1995130561Sobrien if (relsize > 0) 199633965Sjdp { 1997130561Sobrien aux.dynrelbuf = xmalloc (relsize); 1998130561Sobrien aux.dynrelcount = bfd_canonicalize_dynamic_reloc (abfd, 1999130561Sobrien aux.dynrelbuf, 2000130561Sobrien dynsyms); 2001130561Sobrien if (aux.dynrelcount < 0) 200233965Sjdp bfd_fatal (bfd_get_filename (abfd)); 200333965Sjdp 2004130561Sobrien /* Sort the relocs by address. */ 2005130561Sobrien qsort (aux.dynrelbuf, aux.dynrelcount, sizeof (arelent *), 2006130561Sobrien compare_relocs); 200733965Sjdp } 2008130561Sobrien } 2009218822Sdim disasm_info.symtab = sorted_syms; 2010218822Sdim disasm_info.symtab_size = sorted_symcount; 201133965Sjdp 2012130561Sobrien bfd_map_over_sections (abfd, disassemble_section, & disasm_info); 201333965Sjdp 2014130561Sobrien if (aux.dynrelbuf != NULL) 2015130561Sobrien free (aux.dynrelbuf); 201633965Sjdp free (sorted_syms); 201733965Sjdp} 201833965Sjdp 2019218822Sdimint 2020218822Sdimload_debug_section (enum dwarf_section_display_enum debug, void *file) 2021218822Sdim{ 2022218822Sdim struct dwarf_section *section = &debug_displays [debug].section; 2023218822Sdim bfd *abfd = file; 2024218822Sdim asection *sec; 2025218822Sdim bfd_boolean ret; 2026218822Sdim 2027218822Sdim /* If it is already loaded, do nothing. */ 2028218822Sdim if (section->start != NULL) 2029218822Sdim return 1; 2030218822Sdim 2031218822Sdim /* Locate the debug section. */ 2032218822Sdim sec = bfd_get_section_by_name (abfd, section->name); 2033218822Sdim if (sec == NULL) 2034218822Sdim return 0; 2035218822Sdim 2036218822Sdim /* Compute a bias to be added to offsets found within the DWARF debug 2037218822Sdim information. These offsets are meant to be relative to the start of 2038218822Sdim the dwarf section, and hence the bias should be 0. For MACH-O however 2039218822Sdim a dwarf section is really just a region of a much larger section and so 2040218822Sdim the bias is the address of the start of that area within the larger 2041218822Sdim section. This test is important for PE and COFF based targets which 2042218822Sdim use DWARF debug information, since unlike ELF, they do not allow the 2043218822Sdim dwarf sections to be placed at address 0. */ 2044218822Sdim if (bfd_get_flavour (abfd) == bfd_target_mach_o_flavour) 2045218822Sdim section->address = bfd_get_section_vma (abfd, sec); 2046218822Sdim else 2047218822Sdim section->address = 0; 2048218822Sdim 2049218822Sdim section->size = bfd_get_section_size (sec); 2050218822Sdim section->start = xmalloc (section->size); 2051218822Sdim 2052218822Sdim if (is_relocatable && debug_displays [debug].relocate) 2053218822Sdim ret = bfd_simple_get_relocated_section_contents (abfd, 2054218822Sdim sec, 2055218822Sdim section->start, 2056218822Sdim syms) != NULL; 2057218822Sdim else 2058218822Sdim ret = bfd_get_section_contents (abfd, sec, section->start, 0, 2059218822Sdim section->size); 2060218822Sdim 2061218822Sdim if (!ret) 2062218822Sdim { 2063218822Sdim free_debug_section (debug); 2064218822Sdim printf (_("\nCan't get contents for section '%s'.\n"), 2065218822Sdim section->name); 2066218822Sdim } 2067218822Sdim 2068218822Sdim return ret; 2069218822Sdim} 2070218822Sdim 2071218822Sdimvoid 2072218822Sdimfree_debug_section (enum dwarf_section_display_enum debug) 2073218822Sdim{ 2074218822Sdim struct dwarf_section *section = &debug_displays [debug].section; 2075218822Sdim 2076218822Sdim if (section->start == NULL) 2077218822Sdim return; 2078218822Sdim 2079218822Sdim free ((char *) section->start); 2080218822Sdim section->start = NULL; 2081218822Sdim section->address = 0; 2082218822Sdim section->size = 0; 2083218822Sdim} 2084218822Sdim 2085218822Sdimstatic void 2086218822Sdimdump_dwarf_section (bfd *abfd, asection *section, 2087218822Sdim void *arg ATTRIBUTE_UNUSED) 2088218822Sdim{ 2089218822Sdim const char *name = bfd_get_section_name (abfd, section); 2090218822Sdim const char *match; 2091218822Sdim enum dwarf_section_display_enum i; 2092218822Sdim 2093218822Sdim if (CONST_STRNEQ (name, ".gnu.linkonce.wi.")) 2094218822Sdim match = ".debug_info"; 2095218822Sdim else 2096218822Sdim match = name; 2097218822Sdim 2098218822Sdim for (i = 0; i < max; i++) 2099218822Sdim if (strcmp (debug_displays[i].section.name, match) == 0) 2100218822Sdim { 2101218822Sdim if (!debug_displays[i].eh_frame) 2102218822Sdim { 2103218822Sdim struct dwarf_section *sec = &debug_displays [i].section; 2104218822Sdim 2105218822Sdim if (load_debug_section (i, abfd)) 2106218822Sdim { 2107218822Sdim debug_displays[i].display (sec, abfd); 2108218822Sdim 2109218822Sdim if (i != info && i != abbrev) 2110218822Sdim free_debug_section (i); 2111218822Sdim } 2112218822Sdim } 2113218822Sdim break; 2114218822Sdim } 2115218822Sdim} 2116218822Sdim 2117218822Sdimstatic const char *mach_o_dwarf_sections [] = { 2118218822Sdim "LC_SEGMENT.__DWARFA.__debug_abbrev", /* .debug_abbrev */ 2119218822Sdim "LC_SEGMENT.__DWARFA.__debug_aranges", /* .debug_aranges */ 2120218822Sdim "LC_SEGMENT.__DWARFA.__debug_frame", /* .debug_frame */ 2121218822Sdim "LC_SEGMENT.__DWARFA.__debug_info", /* .debug_info */ 2122218822Sdim "LC_SEGMENT.__DWARFA.__debug_line", /* .debug_line */ 2123218822Sdim "LC_SEGMENT.__DWARFA.__debug_pubnames", /* .debug_pubnames */ 2124218822Sdim ".eh_frame", /* .eh_frame */ 2125218822Sdim "LC_SEGMENT.__DWARFA.__debug_macinfo", /* .debug_macinfo */ 2126218822Sdim "LC_SEGMENT.__DWARFA.__debug_str", /* .debug_str */ 2127218822Sdim "LC_SEGMENT.__DWARFA.__debug_loc", /* .debug_loc */ 2128218822Sdim "LC_SEGMENT.__DWARFA.__debug_pubtypes", /* .debug_pubtypes */ 2129218822Sdim "LC_SEGMENT.__DWARFA.__debug_ranges", /* .debug_ranges */ 2130218822Sdim "LC_SEGMENT.__DWARFA.__debug_static_func", /* .debug_static_func */ 2131218822Sdim "LC_SEGMENT.__DWARFA.__debug_static_vars", /* .debug_static_vars */ 2132218822Sdim "LC_SEGMENT.__DWARFA.__debug_types", /* .debug_types */ 2133218822Sdim "LC_SEGMENT.__DWARFA.__debug_weaknames" /* .debug_weaknames */ 2134218822Sdim}; 2135218822Sdim 2136218822Sdimstatic const char *generic_dwarf_sections [max]; 2137218822Sdim 2138218822Sdimstatic void 2139218822Sdimcheck_mach_o_dwarf (bfd *abfd) 2140218822Sdim{ 2141218822Sdim static enum bfd_flavour old_flavour = bfd_target_unknown_flavour; 2142218822Sdim enum bfd_flavour current_flavour = bfd_get_flavour (abfd); 2143218822Sdim enum dwarf_section_display_enum i; 2144218822Sdim 2145218822Sdim if (generic_dwarf_sections [0] == NULL) 2146218822Sdim for (i = 0; i < max; i++) 2147218822Sdim generic_dwarf_sections [i] = debug_displays[i].section.name; 2148218822Sdim 2149218822Sdim if (old_flavour != current_flavour) 2150218822Sdim { 2151218822Sdim if (current_flavour == bfd_target_mach_o_flavour) 2152218822Sdim for (i = 0; i < max; i++) 2153218822Sdim debug_displays[i].section.name = mach_o_dwarf_sections [i]; 2154218822Sdim else if (old_flavour == bfd_target_mach_o_flavour) 2155218822Sdim for (i = 0; i < max; i++) 2156218822Sdim debug_displays[i].section.name = generic_dwarf_sections [i]; 2157218822Sdim 2158218822Sdim old_flavour = current_flavour; 2159218822Sdim } 2160218822Sdim} 2161218822Sdim 2162218822Sdim/* Dump the dwarf debugging information. */ 2163218822Sdim 2164218822Sdimstatic void 2165218822Sdimdump_dwarf (bfd *abfd) 2166218822Sdim{ 2167218822Sdim is_relocatable = ((abfd->flags & (HAS_RELOC | EXEC_P | DYNAMIC)) 2168218822Sdim == HAS_RELOC); 2169218822Sdim 2170218822Sdim /* FIXME: bfd_get_arch_size may return -1. We assume that 64bit 2171218822Sdim targets will return 64. */ 2172218822Sdim eh_addr_size = bfd_get_arch_size (abfd) == 64 ? 8 : 4; 2173218822Sdim 2174218822Sdim if (bfd_big_endian (abfd)) 2175218822Sdim byte_get = byte_get_big_endian; 2176218822Sdim else if (bfd_little_endian (abfd)) 2177218822Sdim byte_get = byte_get_little_endian; 2178218822Sdim else 2179218822Sdim abort (); 2180218822Sdim 2181218822Sdim check_mach_o_dwarf (abfd); 2182218822Sdim 2183218822Sdim bfd_map_over_sections (abfd, dump_dwarf_section, NULL); 2184218822Sdim 2185218822Sdim free_debug_memory (); 2186218822Sdim} 2187218822Sdim 2188130561Sobrien/* Read ABFD's stabs section STABSECT_NAME, and return a pointer to 2189130561Sobrien it. Return NULL on failure. */ 219033965Sjdp 2191130561Sobrienstatic char * 2192130561Sobrienread_section_stabs (bfd *abfd, const char *sect_name, bfd_size_type *size_ptr) 219333965Sjdp{ 2194130561Sobrien asection *stabsect; 2195130561Sobrien bfd_size_type size; 2196130561Sobrien char *contents; 219733965Sjdp 2198130561Sobrien stabsect = bfd_get_section_by_name (abfd, sect_name); 2199130561Sobrien if (stabsect == NULL) 220033965Sjdp { 2201130561Sobrien printf (_("No %s section present\n\n"), sect_name); 2202130561Sobrien return FALSE; 220333965Sjdp } 220433965Sjdp 2205130561Sobrien size = bfd_section_size (abfd, stabsect); 2206130561Sobrien contents = xmalloc (size); 2207104834Sobrien 2208130561Sobrien if (! bfd_get_section_contents (abfd, stabsect, contents, 0, size)) 220933965Sjdp { 221060484Sobrien non_fatal (_("Reading %s section of %s failed: %s"), 2211130561Sobrien sect_name, bfd_get_filename (abfd), 221260484Sobrien bfd_errmsg (bfd_get_error ())); 2213130561Sobrien free (contents); 221460484Sobrien exit_status = 1; 2215130561Sobrien return NULL; 221633965Sjdp } 221733965Sjdp 2218130561Sobrien *size_ptr = size; 221933965Sjdp 2220130561Sobrien return contents; 222133965Sjdp} 222233965Sjdp 222333965Sjdp/* Stabs entries use a 12 byte format: 222433965Sjdp 4 byte string table index 222533965Sjdp 1 byte stab type 222633965Sjdp 1 byte stab other field 222733965Sjdp 2 byte stab desc field 222833965Sjdp 4 byte stab value 222933965Sjdp FIXME: This will have to change for a 64 bit object format. */ 223033965Sjdp 2231130561Sobrien#define STRDXOFF (0) 2232130561Sobrien#define TYPEOFF (4) 2233130561Sobrien#define OTHEROFF (5) 2234130561Sobrien#define DESCOFF (6) 2235130561Sobrien#define VALOFF (8) 223633965Sjdp#define STABSIZE (12) 223733965Sjdp 223833965Sjdp/* Print ABFD's stabs section STABSECT_NAME (in `stabs'), 223933965Sjdp using string table section STRSECT_NAME (in `strtab'). */ 224033965Sjdp 224133965Sjdpstatic void 2242130561Sobrienprint_section_stabs (bfd *abfd, 2243130561Sobrien const char *stabsect_name, 2244130561Sobrien unsigned *string_offset_ptr) 224533965Sjdp{ 224633965Sjdp int i; 2247130561Sobrien unsigned file_string_table_offset = 0; 2248130561Sobrien unsigned next_file_string_table_offset = *string_offset_ptr; 224933965Sjdp bfd_byte *stabp, *stabs_end; 225033965Sjdp 225133965Sjdp stabp = stabs; 225233965Sjdp stabs_end = stabp + stab_size; 225333965Sjdp 225460484Sobrien printf (_("Contents of %s section:\n\n"), stabsect_name); 225533965Sjdp printf ("Symnum n_type n_othr n_desc n_value n_strx String\n"); 225633965Sjdp 225733965Sjdp /* Loop through all symbols and print them. 225833965Sjdp 225933965Sjdp We start the index at -1 because there is a dummy symbol on 226033965Sjdp the front of stabs-in-{coff,elf} sections that supplies sizes. */ 226133965Sjdp for (i = -1; stabp < stabs_end; stabp += STABSIZE, i++) 226233965Sjdp { 226333965Sjdp const char *name; 226433965Sjdp unsigned long strx; 226533965Sjdp unsigned char type, other; 226633965Sjdp unsigned short desc; 226733965Sjdp bfd_vma value; 226833965Sjdp 226933965Sjdp strx = bfd_h_get_32 (abfd, stabp + STRDXOFF); 227033965Sjdp type = bfd_h_get_8 (abfd, stabp + TYPEOFF); 227133965Sjdp other = bfd_h_get_8 (abfd, stabp + OTHEROFF); 227233965Sjdp desc = bfd_h_get_16 (abfd, stabp + DESCOFF); 227333965Sjdp value = bfd_h_get_32 (abfd, stabp + VALOFF); 227433965Sjdp 227533965Sjdp printf ("\n%-6d ", i); 227633965Sjdp /* Either print the stab name, or, if unnamed, print its number 2277104834Sobrien again (makes consistent formatting for tools like awk). */ 227833965Sjdp name = bfd_get_stab_name (type); 227933965Sjdp if (name != NULL) 228033965Sjdp printf ("%-6s", name); 228133965Sjdp else if (type == N_UNDF) 228233965Sjdp printf ("HdrSym"); 228333965Sjdp else 228433965Sjdp printf ("%-6d", type); 228533965Sjdp printf (" %-6d %-6d ", other, desc); 228689857Sobrien bfd_printf_vma (abfd, value); 228733965Sjdp printf (" %-6lu", strx); 228833965Sjdp 228933965Sjdp /* Symbols with type == 0 (N_UNDF) specify the length of the 229033965Sjdp string table associated with this file. We use that info 229133965Sjdp to know how to relocate the *next* file's string table indices. */ 229233965Sjdp if (type == N_UNDF) 229333965Sjdp { 229433965Sjdp file_string_table_offset = next_file_string_table_offset; 229533965Sjdp next_file_string_table_offset += value; 229633965Sjdp } 229733965Sjdp else 229833965Sjdp { 229933965Sjdp /* Using the (possibly updated) string table offset, print the 230033965Sjdp string (if any) associated with this symbol. */ 230133965Sjdp if ((strx + file_string_table_offset) < stabstr_size) 230233965Sjdp printf (" %s", &strtab[strx + file_string_table_offset]); 230333965Sjdp else 230433965Sjdp printf (" *"); 230533965Sjdp } 230633965Sjdp } 230733965Sjdp printf ("\n\n"); 2308130561Sobrien *string_offset_ptr = next_file_string_table_offset; 230933965Sjdp} 231033965Sjdp 2311130561Sobrientypedef struct 2312130561Sobrien{ 2313130561Sobrien const char * section_name; 2314130561Sobrien const char * string_section_name; 2315130561Sobrien unsigned string_offset; 2316130561Sobrien} 2317130561Sobrienstab_section_names; 2318130561Sobrien 231933965Sjdpstatic void 2320130561Sobrienfind_stabs_section (bfd *abfd, asection *section, void *names) 232133965Sjdp{ 2322130561Sobrien int len; 2323130561Sobrien stab_section_names * sought = (stab_section_names *) names; 232433965Sjdp 232533965Sjdp /* Check for section names for which stabsect_name is a prefix, to 2326130561Sobrien handle .stab.N, etc. */ 2327130561Sobrien len = strlen (sought->section_name); 2328130561Sobrien 2329130561Sobrien /* If the prefix matches, and the files section name ends with a 2330130561Sobrien nul or a digit, then we match. I.e., we want either an exact 2331130561Sobrien match or a section followed by a number. */ 2332130561Sobrien if (strncmp (sought->section_name, section->name, len) == 0 2333130561Sobrien && (section->name[len] == 0 2334130561Sobrien || (section->name[len] == '.' && ISDIGIT (section->name[len + 1])))) 233533965Sjdp { 2336130561Sobrien if (strtab == NULL) 2337130561Sobrien strtab = read_section_stabs (abfd, sought->string_section_name, 2338130561Sobrien &stabstr_size); 2339130561Sobrien 2340130561Sobrien if (strtab) 234133965Sjdp { 2342218822Sdim stabs = (bfd_byte *) read_section_stabs (abfd, section->name, 2343218822Sdim &stab_size); 2344130561Sobrien if (stabs) 2345130561Sobrien print_section_stabs (abfd, section->name, &sought->string_offset); 234633965Sjdp } 234733965Sjdp } 234833965Sjdp} 2349130561Sobrien 2350130561Sobrienstatic void 2351130561Sobriendump_stabs_section (bfd *abfd, char *stabsect_name, char *strsect_name) 2352130561Sobrien{ 2353130561Sobrien stab_section_names s; 2354130561Sobrien 2355130561Sobrien s.section_name = stabsect_name; 2356130561Sobrien s.string_section_name = strsect_name; 2357130561Sobrien s.string_offset = 0; 2358130561Sobrien 2359130561Sobrien bfd_map_over_sections (abfd, find_stabs_section, & s); 2360130561Sobrien 2361130561Sobrien free (strtab); 2362130561Sobrien strtab = NULL; 2363130561Sobrien} 2364130561Sobrien 2365130561Sobrien/* Dump the any sections containing stabs debugging information. */ 2366130561Sobrien 2367130561Sobrienstatic void 2368130561Sobriendump_stabs (bfd *abfd) 2369130561Sobrien{ 2370130561Sobrien dump_stabs_section (abfd, ".stab", ".stabstr"); 2371130561Sobrien dump_stabs_section (abfd, ".stab.excl", ".stab.exclstr"); 2372130561Sobrien dump_stabs_section (abfd, ".stab.index", ".stab.indexstr"); 2373130561Sobrien dump_stabs_section (abfd, "$GDB_SYMBOLS$", "$GDB_STRINGS$"); 2374130561Sobrien} 237533965Sjdp 237633965Sjdpstatic void 2377130561Sobriendump_bfd_header (bfd *abfd) 237833965Sjdp{ 237933965Sjdp char *comma = ""; 238033965Sjdp 238160484Sobrien printf (_("architecture: %s, "), 238233965Sjdp bfd_printable_arch_mach (bfd_get_arch (abfd), 238333965Sjdp bfd_get_mach (abfd))); 238460484Sobrien printf (_("flags 0x%08x:\n"), abfd->flags); 238533965Sjdp 238633965Sjdp#define PF(x, y) if (abfd->flags & x) {printf("%s%s", comma, y); comma=", ";} 238733965Sjdp PF (HAS_RELOC, "HAS_RELOC"); 238833965Sjdp PF (EXEC_P, "EXEC_P"); 238933965Sjdp PF (HAS_LINENO, "HAS_LINENO"); 239033965Sjdp PF (HAS_DEBUG, "HAS_DEBUG"); 239133965Sjdp PF (HAS_SYMS, "HAS_SYMS"); 239233965Sjdp PF (HAS_LOCALS, "HAS_LOCALS"); 239333965Sjdp PF (DYNAMIC, "DYNAMIC"); 239433965Sjdp PF (WP_TEXT, "WP_TEXT"); 239533965Sjdp PF (D_PAGED, "D_PAGED"); 239633965Sjdp PF (BFD_IS_RELAXABLE, "BFD_IS_RELAXABLE"); 2397130561Sobrien PF (HAS_LOAD_PAGE, "HAS_LOAD_PAGE"); 239860484Sobrien printf (_("\nstart address 0x")); 239989857Sobrien bfd_printf_vma (abfd, abfd->start_address); 240033965Sjdp printf ("\n"); 240133965Sjdp} 2402130561Sobrien 240333965Sjdp 240433965Sjdpstatic void 2405130561Sobriendump_bfd_private_header (bfd *abfd) 240633965Sjdp{ 240733965Sjdp bfd_print_private_bfd_data (abfd, stdout); 240833965Sjdp} 240933965Sjdp 2410130561Sobrien 2411130561Sobrien/* Display a section in hexadecimal format with associated characters. 2412130561Sobrien Each line prefixed by the zero padded address. */ 241360484Sobrien 241433965Sjdpstatic void 2415130561Sobriendump_section (bfd *abfd, asection *section, void *dummy ATTRIBUTE_UNUSED) 241633965Sjdp{ 2417130561Sobrien bfd_byte *data = 0; 2418130561Sobrien bfd_size_type datasize; 2419130561Sobrien bfd_size_type addr_offset; 2420130561Sobrien bfd_size_type start_offset; 2421130561Sobrien bfd_size_type stop_offset; 2422130561Sobrien unsigned int opb = bfd_octets_per_byte (abfd); 2423130561Sobrien /* Bytes per line. */ 2424130561Sobrien const int onaline = 16; 2425130561Sobrien char buf[64]; 2426130561Sobrien int count; 2427130561Sobrien int width; 242833965Sjdp 2429130561Sobrien if ((section->flags & SEC_HAS_CONTENTS) == 0) 2430130561Sobrien return; 243133965Sjdp 2432130561Sobrien if (! process_section_p (section)) 2433130561Sobrien return; 2434130561Sobrien 2435130561Sobrien if ((datasize = bfd_section_size (abfd, section)) == 0) 2436130561Sobrien return; 243733965Sjdp 2438130561Sobrien printf (_("Contents of section %s:\n"), section->name); 243933965Sjdp 2440130561Sobrien data = xmalloc (datasize); 244160484Sobrien 2442130561Sobrien bfd_get_section_contents (abfd, section, data, 0, datasize); 244360484Sobrien 2444130561Sobrien /* Compute the address range to display. */ 2445130561Sobrien if (start_address == (bfd_vma) -1 2446130561Sobrien || start_address < section->vma) 2447130561Sobrien start_offset = 0; 2448130561Sobrien else 2449130561Sobrien start_offset = start_address - section->vma; 245060484Sobrien 2451130561Sobrien if (stop_address == (bfd_vma) -1) 2452130561Sobrien stop_offset = datasize / opb; 2453130561Sobrien else 245460484Sobrien { 2455130561Sobrien if (stop_address < section->vma) 2456130561Sobrien stop_offset = 0; 2457130561Sobrien else 2458130561Sobrien stop_offset = stop_address - section->vma; 245960484Sobrien 2460130561Sobrien if (stop_offset > datasize / opb) 2461130561Sobrien stop_offset = datasize / opb; 246260484Sobrien } 246360484Sobrien 2464130561Sobrien width = 4; 246560484Sobrien 2466130561Sobrien bfd_sprintf_vma (abfd, buf, start_offset + section->vma); 2467130561Sobrien if (strlen (buf) >= sizeof (buf)) 2468130561Sobrien abort (); 246960484Sobrien 2470130561Sobrien count = 0; 2471130561Sobrien while (buf[count] == '0' && buf[count+1] != '\0') 2472130561Sobrien count++; 2473130561Sobrien count = strlen (buf) - count; 2474130561Sobrien if (count > width) 2475130561Sobrien width = count; 247633965Sjdp 2477130561Sobrien bfd_sprintf_vma (abfd, buf, stop_offset + section->vma - 1); 2478130561Sobrien if (strlen (buf) >= sizeof (buf)) 2479130561Sobrien abort (); 248033965Sjdp 2481130561Sobrien count = 0; 2482130561Sobrien while (buf[count] == '0' && buf[count+1] != '\0') 2483130561Sobrien count++; 2484130561Sobrien count = strlen (buf) - count; 2485130561Sobrien if (count > width) 2486130561Sobrien width = count; 2487130561Sobrien 2488130561Sobrien for (addr_offset = start_offset; 2489130561Sobrien addr_offset < stop_offset; addr_offset += onaline / opb) 249033965Sjdp { 2491130561Sobrien bfd_size_type j; 249233965Sjdp 2493130561Sobrien bfd_sprintf_vma (abfd, buf, (addr_offset + section->vma)); 2494130561Sobrien count = strlen (buf); 2495130561Sobrien if ((size_t) count >= sizeof (buf)) 2496130561Sobrien abort (); 2497130561Sobrien 2498130561Sobrien putchar (' '); 2499130561Sobrien while (count < width) 250033965Sjdp { 2501130561Sobrien putchar ('0'); 2502130561Sobrien count++; 2503130561Sobrien } 2504130561Sobrien fputs (buf + count - width, stdout); 2505130561Sobrien putchar (' '); 250633965Sjdp 2507130561Sobrien for (j = addr_offset * opb; 2508130561Sobrien j < addr_offset * opb + onaline; j++) 2509130561Sobrien { 2510130561Sobrien if (j < stop_offset * opb) 2511130561Sobrien printf ("%02x", (unsigned) (data[j])); 2512130561Sobrien else 2513130561Sobrien printf (" "); 2514130561Sobrien if ((j & 3) == 3) 2515130561Sobrien printf (" "); 2516130561Sobrien } 251733965Sjdp 2518130561Sobrien printf (" "); 2519130561Sobrien for (j = addr_offset * opb; 2520130561Sobrien j < addr_offset * opb + onaline; j++) 2521130561Sobrien { 2522130561Sobrien if (j >= stop_offset * opb) 2523130561Sobrien printf (" "); 2524130561Sobrien else 2525130561Sobrien printf ("%c", ISPRINT (data[j]) ? data[j] : '.'); 252633965Sjdp } 2527130561Sobrien putchar ('\n'); 252833965Sjdp } 2529130561Sobrien free (data); 253033965Sjdp} 253133965Sjdp 2532130561Sobrien/* Actually display the various requested regions. */ 2533130561Sobrien 253433965Sjdpstatic void 2535130561Sobriendump_data (bfd *abfd) 253633965Sjdp{ 2537130561Sobrien bfd_map_over_sections (abfd, dump_section, NULL); 2538130561Sobrien} 253933965Sjdp 2540130561Sobrien/* Should perhaps share code and display with nm? */ 254133965Sjdp 254233965Sjdpstatic void 2543130561Sobriendump_symbols (bfd *abfd ATTRIBUTE_UNUSED, bfd_boolean dynamic) 254433965Sjdp{ 254533965Sjdp asymbol **current; 254633965Sjdp long max; 254733965Sjdp long count; 254833965Sjdp 254933965Sjdp if (dynamic) 255033965Sjdp { 255133965Sjdp current = dynsyms; 255233965Sjdp max = dynsymcount; 255333965Sjdp printf ("DYNAMIC SYMBOL TABLE:\n"); 255433965Sjdp } 255533965Sjdp else 255633965Sjdp { 255733965Sjdp current = syms; 255833965Sjdp max = symcount; 255933965Sjdp printf ("SYMBOL TABLE:\n"); 256033965Sjdp } 256133965Sjdp 2562130561Sobrien if (max == 0) 2563130561Sobrien printf (_("no symbols\n")); 2564130561Sobrien 256533965Sjdp for (count = 0; count < max; count++) 256633965Sjdp { 2567130561Sobrien bfd *cur_bfd; 2568130561Sobrien 2569130561Sobrien if (*current == NULL) 2570218822Sdim printf (_("no information for symbol number %ld\n"), count); 2571130561Sobrien 2572130561Sobrien else if ((cur_bfd = bfd_asymbol_bfd (*current)) == NULL) 2573218822Sdim printf (_("could not determine the type of symbol number %ld\n"), 2574130561Sobrien count); 2575130561Sobrien 2576218822Sdim else if (process_section_p ((* current)->section) 2577218822Sdim && (dump_special_syms 2578218822Sdim || !bfd_is_target_special_symbol (cur_bfd, *current))) 257933965Sjdp { 2580130561Sobrien const char *name = (*current)->name; 258133965Sjdp 2582130561Sobrien if (do_demangle && name != NULL && *name != '\0') 258333965Sjdp { 258433965Sjdp char *alloc; 258533965Sjdp 2586130561Sobrien /* If we want to demangle the name, we demangle it 2587130561Sobrien here, and temporarily clobber it while calling 2588130561Sobrien bfd_print_symbol. FIXME: This is a gross hack. */ 2589218822Sdim alloc = bfd_demangle (cur_bfd, name, DMGL_ANSI | DMGL_PARAMS); 2590218822Sdim if (alloc != NULL) 2591218822Sdim (*current)->name = alloc; 259233965Sjdp bfd_print_symbol (cur_bfd, stdout, *current, 259333965Sjdp bfd_print_symbol_all); 2594218822Sdim if (alloc != NULL) 2595218822Sdim { 2596218822Sdim (*current)->name = name; 2597218822Sdim free (alloc); 2598218822Sdim } 259933965Sjdp } 260033965Sjdp else 2601130561Sobrien bfd_print_symbol (cur_bfd, stdout, *current, 2602130561Sobrien bfd_print_symbol_all); 2603218822Sdim printf ("\n"); 260433965Sjdp } 260533965Sjdp 2606130561Sobrien current++; 260733965Sjdp } 2608130561Sobrien printf ("\n\n"); 260933965Sjdp} 2610130561Sobrien 261133965Sjdpstatic void 2612130561Sobriendump_reloc_set (bfd *abfd, asection *sec, arelent **relpp, long relcount) 261333965Sjdp{ 261433965Sjdp arelent **p; 261533965Sjdp char *last_filename, *last_functionname; 261633965Sjdp unsigned int last_line; 261733965Sjdp 261833965Sjdp /* Get column headers lined up reasonably. */ 261933965Sjdp { 262033965Sjdp static int width; 2621130561Sobrien 262233965Sjdp if (width == 0) 262333965Sjdp { 262433965Sjdp char buf[30]; 2625130561Sobrien 262689857Sobrien bfd_sprintf_vma (abfd, buf, (bfd_vma) -1); 262733965Sjdp width = strlen (buf) - 7; 262833965Sjdp } 262933965Sjdp printf ("OFFSET %*s TYPE %*s VALUE \n", width, "", 12, ""); 263033965Sjdp } 263133965Sjdp 263233965Sjdp last_filename = NULL; 263333965Sjdp last_functionname = NULL; 263433965Sjdp last_line = 0; 263533965Sjdp 2636130561Sobrien for (p = relpp; relcount && *p != NULL; p++, relcount--) 263733965Sjdp { 263833965Sjdp arelent *q = *p; 263933965Sjdp const char *filename, *functionname; 264033965Sjdp unsigned int line; 264133965Sjdp const char *sym_name; 264233965Sjdp const char *section_name; 264333965Sjdp 264433965Sjdp if (start_address != (bfd_vma) -1 264533965Sjdp && q->address < start_address) 264633965Sjdp continue; 264733965Sjdp if (stop_address != (bfd_vma) -1 264833965Sjdp && q->address > stop_address) 264933965Sjdp continue; 265033965Sjdp 265133965Sjdp if (with_line_numbers 265233965Sjdp && sec != NULL 265333965Sjdp && bfd_find_nearest_line (abfd, sec, syms, q->address, 265433965Sjdp &filename, &functionname, &line)) 265533965Sjdp { 265633965Sjdp if (functionname != NULL 265733965Sjdp && (last_functionname == NULL 265833965Sjdp || strcmp (functionname, last_functionname) != 0)) 265933965Sjdp { 266033965Sjdp printf ("%s():\n", functionname); 266133965Sjdp if (last_functionname != NULL) 266233965Sjdp free (last_functionname); 266333965Sjdp last_functionname = xstrdup (functionname); 266433965Sjdp } 2665130561Sobrien 266633965Sjdp if (line > 0 266733965Sjdp && (line != last_line 266833965Sjdp || (filename != NULL 266933965Sjdp && last_filename != NULL 267033965Sjdp && strcmp (filename, last_filename) != 0))) 267133965Sjdp { 267233965Sjdp printf ("%s:%u\n", filename == NULL ? "???" : filename, line); 267333965Sjdp last_line = line; 267433965Sjdp if (last_filename != NULL) 267533965Sjdp free (last_filename); 267633965Sjdp if (filename == NULL) 267733965Sjdp last_filename = NULL; 267833965Sjdp else 267933965Sjdp last_filename = xstrdup (filename); 268033965Sjdp } 268133965Sjdp } 268233965Sjdp 268333965Sjdp if (q->sym_ptr_ptr && *q->sym_ptr_ptr) 268433965Sjdp { 268533965Sjdp sym_name = (*(q->sym_ptr_ptr))->name; 268633965Sjdp section_name = (*(q->sym_ptr_ptr))->section->name; 268733965Sjdp } 268833965Sjdp else 268933965Sjdp { 269033965Sjdp sym_name = NULL; 269133965Sjdp section_name = NULL; 269233965Sjdp } 2693130561Sobrien 2694218822Sdim bfd_printf_vma (abfd, q->address); 2695218822Sdim if (q->howto == NULL) 2696218822Sdim printf (" *unknown* "); 2697218822Sdim else if (q->howto->name) 2698218822Sdim printf (" %-16s ", q->howto->name); 2699218822Sdim else 2700218822Sdim printf (" %-16d ", q->howto->type); 270133965Sjdp if (sym_name) 2702218822Sdim objdump_print_symname (abfd, NULL, *q->sym_ptr_ptr); 270333965Sjdp else 270433965Sjdp { 2705130561Sobrien if (section_name == NULL) 270633965Sjdp section_name = "*unknown*"; 2707218822Sdim printf ("[%s]", section_name); 270833965Sjdp } 2709130561Sobrien 271033965Sjdp if (q->addend) 271133965Sjdp { 271233965Sjdp printf ("+0x"); 271389857Sobrien bfd_printf_vma (abfd, q->addend); 271433965Sjdp } 2715130561Sobrien 271633965Sjdp printf ("\n"); 271733965Sjdp } 271833965Sjdp} 271933965Sjdp 2720130561Sobrienstatic void 2721130561Sobriendump_relocs_in_section (bfd *abfd, 2722130561Sobrien asection *section, 2723130561Sobrien void *dummy ATTRIBUTE_UNUSED) 272433965Sjdp{ 2725130561Sobrien arelent **relpp; 2726130561Sobrien long relcount; 2727130561Sobrien long relsize; 2728130561Sobrien 2729130561Sobrien if ( bfd_is_abs_section (section) 2730130561Sobrien || bfd_is_und_section (section) 2731130561Sobrien || bfd_is_com_section (section) 2732130561Sobrien || (! process_section_p (section)) 2733130561Sobrien || ((section->flags & SEC_RELOC) == 0)) 2734130561Sobrien return; 2735130561Sobrien 2736130561Sobrien relsize = bfd_get_reloc_upper_bound (abfd, section); 2737130561Sobrien if (relsize < 0) 2738130561Sobrien bfd_fatal (bfd_get_filename (abfd)); 2739130561Sobrien 2740130561Sobrien printf ("RELOCATION RECORDS FOR [%s]:", section->name); 2741130561Sobrien 2742130561Sobrien if (relsize == 0) 2743130561Sobrien { 2744130561Sobrien printf (" (none)\n\n"); 2745130561Sobrien return; 2746130561Sobrien } 2747130561Sobrien 2748130561Sobrien relpp = xmalloc (relsize); 2749130561Sobrien relcount = bfd_canonicalize_reloc (abfd, section, relpp, syms); 2750130561Sobrien 2751130561Sobrien if (relcount < 0) 2752130561Sobrien bfd_fatal (bfd_get_filename (abfd)); 2753130561Sobrien else if (relcount == 0) 2754130561Sobrien printf (" (none)\n\n"); 275533965Sjdp else 2756130561Sobrien { 2757130561Sobrien printf ("\n"); 2758130561Sobrien dump_reloc_set (abfd, section, relpp, relcount); 2759130561Sobrien printf ("\n\n"); 2760130561Sobrien } 2761130561Sobrien free (relpp); 276233965Sjdp} 276333965Sjdp 2764130561Sobrienstatic void 2765130561Sobriendump_relocs (bfd *abfd) 2766130561Sobrien{ 2767130561Sobrien bfd_map_over_sections (abfd, dump_relocs_in_section, NULL); 2768130561Sobrien} 276933965Sjdp 277033965Sjdpstatic void 2771130561Sobriendump_dynamic_relocs (bfd *abfd) 277233965Sjdp{ 2773130561Sobrien long relsize; 2774130561Sobrien arelent **relpp; 2775130561Sobrien long relcount; 277633965Sjdp 2777130561Sobrien relsize = bfd_get_dynamic_reloc_upper_bound (abfd); 2778130561Sobrien if (relsize < 0) 2779130561Sobrien bfd_fatal (bfd_get_filename (abfd)); 2780130561Sobrien 2781130561Sobrien printf ("DYNAMIC RELOCATION RECORDS"); 2782130561Sobrien 2783130561Sobrien if (relsize == 0) 2784130561Sobrien printf (" (none)\n\n"); 2785130561Sobrien else 278633965Sjdp { 2787130561Sobrien relpp = xmalloc (relsize); 2788130561Sobrien relcount = bfd_canonicalize_dynamic_reloc (abfd, relpp, dynsyms); 278933965Sjdp 2790130561Sobrien if (relcount < 0) 2791130561Sobrien bfd_fatal (bfd_get_filename (abfd)); 2792130561Sobrien else if (relcount == 0) 2793130561Sobrien printf (" (none)\n\n"); 2794130561Sobrien else 279533965Sjdp { 2796130561Sobrien printf ("\n"); 2797130561Sobrien dump_reloc_set (abfd, NULL, relpp, relcount); 2798130561Sobrien printf ("\n\n"); 279933965Sjdp } 2800130561Sobrien free (relpp); 2801130561Sobrien } 2802130561Sobrien} 280333965Sjdp 2804130561Sobrien/* Creates a table of paths, to search for source files. */ 2805130561Sobrien 2806130561Sobrienstatic void 2807130561Sobrienadd_include_path (const char *path) 2808130561Sobrien{ 2809130561Sobrien if (path[0] == 0) 2810130561Sobrien return; 2811130561Sobrien include_path_count++; 2812130561Sobrien include_paths = xrealloc (include_paths, 2813130561Sobrien include_path_count * sizeof (*include_paths)); 2814130561Sobrien#ifdef HAVE_DOS_BASED_FILE_SYSTEM 2815130561Sobrien if (path[1] == ':' && path[2] == 0) 2816130561Sobrien path = concat (path, ".", (const char *) 0); 2817130561Sobrien#endif 2818130561Sobrien include_paths[include_path_count - 1] = path; 2819130561Sobrien} 2820130561Sobrien 2821130561Sobrienstatic void 2822130561Sobrienadjust_addresses (bfd *abfd ATTRIBUTE_UNUSED, 2823130561Sobrien asection *section, 2824218822Sdim void *arg) 2825130561Sobrien{ 2826218822Sdim if ((section->flags & SEC_DEBUGGING) == 0) 2827218822Sdim { 2828218822Sdim bfd_boolean *has_reloc_p = (bfd_boolean *) arg; 2829218822Sdim section->vma += adjust_section_vma; 2830218822Sdim if (*has_reloc_p) 2831218822Sdim section->lma += adjust_section_vma; 2832218822Sdim } 2833130561Sobrien} 2834130561Sobrien 2835130561Sobrien/* Dump selected contents of ABFD. */ 2836130561Sobrien 2837130561Sobrienstatic void 2838130561Sobriendump_bfd (bfd *abfd) 2839130561Sobrien{ 2840130561Sobrien /* If we are adjusting section VMA's, change them all now. Changing 2841130561Sobrien the BFD information is a hack. However, we must do it, or 2842130561Sobrien bfd_find_nearest_line will not do the right thing. */ 2843130561Sobrien if (adjust_section_vma != 0) 2844218822Sdim { 2845218822Sdim bfd_boolean has_reloc = (abfd->flags & HAS_RELOC); 2846218822Sdim bfd_map_over_sections (abfd, adjust_addresses, &has_reloc); 2847218822Sdim } 2848130561Sobrien 2849130561Sobrien if (! dump_debugging_tags) 2850130561Sobrien printf (_("\n%s: file format %s\n"), bfd_get_filename (abfd), 2851130561Sobrien abfd->xvec->name); 2852130561Sobrien if (dump_ar_hdrs) 2853130561Sobrien print_arelt_descr (stdout, abfd, TRUE); 2854130561Sobrien if (dump_file_header) 2855130561Sobrien dump_bfd_header (abfd); 2856130561Sobrien if (dump_private_headers) 2857130561Sobrien dump_bfd_private_header (abfd); 2858130561Sobrien if (! dump_debugging_tags) 2859130561Sobrien putchar ('\n'); 2860130561Sobrien if (dump_section_headers) 2861130561Sobrien dump_headers (abfd); 2862130561Sobrien 2863218822Sdim if (dump_symtab 2864218822Sdim || dump_reloc_info 2865218822Sdim || disassemble 2866218822Sdim || dump_debugging 2867218822Sdim || dump_dwarf_section_info) 2868130561Sobrien syms = slurp_symtab (abfd); 2869218822Sdim if (dump_dynamic_symtab || dump_dynamic_reloc_info 2870218822Sdim || (disassemble && bfd_get_dynamic_symtab_upper_bound (abfd) > 0)) 2871130561Sobrien dynsyms = slurp_dynamic_symtab (abfd); 2872218822Sdim if (disassemble) 2873218822Sdim { 2874218822Sdim synthcount = bfd_get_synthetic_symtab (abfd, symcount, syms, 2875218822Sdim dynsymcount, dynsyms, &synthsyms); 2876218822Sdim if (synthcount < 0) 2877218822Sdim synthcount = 0; 2878218822Sdim } 2879130561Sobrien 2880130561Sobrien if (dump_symtab) 2881130561Sobrien dump_symbols (abfd, FALSE); 2882130561Sobrien if (dump_dynamic_symtab) 2883130561Sobrien dump_symbols (abfd, TRUE); 2884218822Sdim if (dump_dwarf_section_info) 2885218822Sdim dump_dwarf (abfd); 2886130561Sobrien if (dump_stab_section_info) 2887130561Sobrien dump_stabs (abfd); 2888130561Sobrien if (dump_reloc_info && ! disassemble) 2889130561Sobrien dump_relocs (abfd); 2890130561Sobrien if (dump_dynamic_reloc_info && ! disassemble) 2891130561Sobrien dump_dynamic_relocs (abfd); 2892130561Sobrien if (dump_section_contents) 2893130561Sobrien dump_data (abfd); 2894130561Sobrien if (disassemble) 2895130561Sobrien disassemble_data (abfd); 2896130561Sobrien 2897130561Sobrien if (dump_debugging) 2898130561Sobrien { 2899130561Sobrien void *dhandle; 2900130561Sobrien 2901130561Sobrien dhandle = read_debugging_info (abfd, syms, symcount); 2902130561Sobrien if (dhandle != NULL) 290333965Sjdp { 2904218822Sdim if (!print_debugging_info (stdout, dhandle, abfd, syms, 2905218822Sdim bfd_demangle, 2906218822Sdim dump_debugging_tags ? TRUE : FALSE)) 2907130561Sobrien { 2908130561Sobrien non_fatal (_("%s: printing debugging information failed"), 2909130561Sobrien bfd_get_filename (abfd)); 2910130561Sobrien exit_status = 1; 2911130561Sobrien } 291233965Sjdp } 2913130561Sobrien } 291433965Sjdp 2915130561Sobrien if (syms) 2916130561Sobrien { 2917130561Sobrien free (syms); 2918130561Sobrien syms = NULL; 291933965Sjdp } 2920130561Sobrien 2921130561Sobrien if (dynsyms) 2922130561Sobrien { 2923130561Sobrien free (dynsyms); 2924130561Sobrien dynsyms = NULL; 2925130561Sobrien } 2926218822Sdim 2927218822Sdim if (synthsyms) 2928218822Sdim { 2929218822Sdim free (synthsyms); 2930218822Sdim synthsyms = NULL; 2931218822Sdim } 2932218822Sdim 2933218822Sdim symcount = 0; 2934218822Sdim dynsymcount = 0; 2935218822Sdim synthcount = 0; 293633965Sjdp} 293733965Sjdp 293833965Sjdpstatic void 2939130561Sobriendisplay_bfd (bfd *abfd) 294033965Sjdp{ 2941130561Sobrien char **matching; 294233965Sjdp 2943130561Sobrien if (bfd_check_format_matches (abfd, bfd_object, &matching)) 2944130561Sobrien { 2945130561Sobrien dump_bfd (abfd); 2946130561Sobrien return; 2947130561Sobrien } 294833965Sjdp 2949130561Sobrien if (bfd_get_error () == bfd_error_file_ambiguously_recognized) 2950130561Sobrien { 2951130561Sobrien nonfatal (bfd_get_filename (abfd)); 2952130561Sobrien list_matching_formats (matching); 2953130561Sobrien free (matching); 2954130561Sobrien return; 2955130561Sobrien } 295633965Sjdp 2957130561Sobrien if (bfd_get_error () != bfd_error_file_not_recognized) 2958130561Sobrien { 2959130561Sobrien nonfatal (bfd_get_filename (abfd)); 2960130561Sobrien return; 2961130561Sobrien } 296233965Sjdp 2963130561Sobrien if (bfd_check_format_matches (abfd, bfd_core, &matching)) 2964130561Sobrien { 2965130561Sobrien dump_bfd (abfd); 2966130561Sobrien return; 2967130561Sobrien } 296833965Sjdp 2969130561Sobrien nonfatal (bfd_get_filename (abfd)); 297033965Sjdp 2971130561Sobrien if (bfd_get_error () == bfd_error_file_ambiguously_recognized) 2972130561Sobrien { 2973130561Sobrien list_matching_formats (matching); 2974130561Sobrien free (matching); 2975130561Sobrien } 297633965Sjdp} 297733965Sjdp 297833965Sjdpstatic void 2979130561Sobriendisplay_file (char *filename, char *target) 298033965Sjdp{ 2981130561Sobrien bfd *file; 2982130561Sobrien bfd *arfile = NULL; 298333965Sjdp 2984130561Sobrien if (get_file_size (filename) < 1) 2985218822Sdim { 2986218822Sdim exit_status = 1; 2987218822Sdim return; 2988218822Sdim } 298933965Sjdp 2990130561Sobrien file = bfd_openr (filename, target); 2991130561Sobrien if (file == NULL) 299233965Sjdp { 2993130561Sobrien nonfatal (filename); 2994130561Sobrien return; 2995130561Sobrien } 299633965Sjdp 2997130561Sobrien /* If the file is an archive, process all of its elements. */ 2998130561Sobrien if (bfd_check_format (file, bfd_archive)) 2999130561Sobrien { 3000130561Sobrien bfd *last_arfile = NULL; 3001130561Sobrien 3002130561Sobrien printf (_("In archive %s:\n"), bfd_get_filename (file)); 3003130561Sobrien for (;;) 300433965Sjdp { 3005130561Sobrien bfd_set_error (bfd_error_no_error); 300633965Sjdp 3007130561Sobrien arfile = bfd_openr_next_archived_file (file, arfile); 3008130561Sobrien if (arfile == NULL) 3009130561Sobrien { 3010130561Sobrien if (bfd_get_error () != bfd_error_no_more_archived_files) 3011130561Sobrien nonfatal (bfd_get_filename (file)); 3012130561Sobrien break; 3013130561Sobrien } 3014130561Sobrien 3015130561Sobrien display_bfd (arfile); 3016130561Sobrien 3017130561Sobrien if (last_arfile != NULL) 3018130561Sobrien bfd_close (last_arfile); 3019130561Sobrien last_arfile = arfile; 302033965Sjdp } 3021130561Sobrien 3022130561Sobrien if (last_arfile != NULL) 3023130561Sobrien bfd_close (last_arfile); 302433965Sjdp } 3025130561Sobrien else 3026130561Sobrien display_bfd (file); 302733965Sjdp 3028130561Sobrien bfd_close (file); 302933965Sjdp} 3030130561Sobrien 303133965Sjdpint 3032130561Sobrienmain (int argc, char **argv) 303333965Sjdp{ 303433965Sjdp int c; 303533965Sjdp char *target = default_target; 3036130561Sobrien bfd_boolean seenflag = FALSE; 303733965Sjdp 3038130561Sobrien#if defined (HAVE_SETLOCALE) 3039130561Sobrien#if defined (HAVE_LC_MESSAGES) 304060484Sobrien setlocale (LC_MESSAGES, ""); 304160484Sobrien#endif 304289857Sobrien setlocale (LC_CTYPE, ""); 304389857Sobrien#endif 3044130561Sobrien 304560484Sobrien bindtextdomain (PACKAGE, LOCALEDIR); 304660484Sobrien textdomain (PACKAGE); 304760484Sobrien 304833965Sjdp program_name = *argv; 304933965Sjdp xmalloc_set_program_name (program_name); 305033965Sjdp 305133965Sjdp START_PROGRESS (program_name, 0); 305233965Sjdp 3053218822Sdim expandargv (&argc, &argv); 3054218822Sdim 305533965Sjdp bfd_init (); 305633965Sjdp set_default_bfd_target (); 305733965Sjdp 3058218822Sdim while ((c = getopt_long (argc, argv, "pib:m:M:VvCdDlfaHhrRtTxsSI:j:wE:zgeGW", 305933965Sjdp long_options, (int *) 0)) 306033965Sjdp != EOF) 306133965Sjdp { 306233965Sjdp switch (c) 306333965Sjdp { 306433965Sjdp case 0: 306589857Sobrien break; /* We've been given a long option. */ 306633965Sjdp case 'm': 306733965Sjdp machine = optarg; 306833965Sjdp break; 306960484Sobrien case 'M': 3070130561Sobrien if (disassembler_options) 3071130561Sobrien /* Ignore potential memory leak for now. */ 3072130561Sobrien disassembler_options = concat (disassembler_options, ",", 3073130561Sobrien optarg, NULL); 3074130561Sobrien else 3075130561Sobrien disassembler_options = optarg; 307660484Sobrien break; 307733965Sjdp case 'j': 3078130561Sobrien if (only_used == only_size) 3079130561Sobrien { 3080130561Sobrien only_size += 8; 3081130561Sobrien only = xrealloc (only, only_size * sizeof (char *)); 3082130561Sobrien } 3083130561Sobrien only [only_used++] = optarg; 308433965Sjdp break; 308533965Sjdp case 'l': 3086130561Sobrien with_line_numbers = TRUE; 308733965Sjdp break; 308833965Sjdp case 'b': 308933965Sjdp target = optarg; 309033965Sjdp break; 309160484Sobrien case 'C': 3092130561Sobrien do_demangle = TRUE; 309377298Sobrien if (optarg != NULL) 309477298Sobrien { 309577298Sobrien enum demangling_styles style; 309689857Sobrien 309777298Sobrien style = cplus_demangle_name_to_style (optarg); 3098104834Sobrien if (style == unknown_demangling) 309977298Sobrien fatal (_("unknown demangling style `%s'"), 310077298Sobrien optarg); 310189857Sobrien 310277298Sobrien cplus_demangle_set_style (style); 3103104834Sobrien } 310460484Sobrien break; 310560484Sobrien case 'w': 3106130561Sobrien wide_output = TRUE; 310760484Sobrien break; 310860484Sobrien case OPTION_ADJUST_VMA: 310960484Sobrien adjust_section_vma = parse_vma (optarg, "--adjust-vma"); 311060484Sobrien break; 311160484Sobrien case OPTION_START_ADDRESS: 311260484Sobrien start_address = parse_vma (optarg, "--start-address"); 311360484Sobrien break; 311460484Sobrien case OPTION_STOP_ADDRESS: 311560484Sobrien stop_address = parse_vma (optarg, "--stop-address"); 311660484Sobrien break; 311760484Sobrien case 'E': 311860484Sobrien if (strcmp (optarg, "B") == 0) 311960484Sobrien endian = BFD_ENDIAN_BIG; 312060484Sobrien else if (strcmp (optarg, "L") == 0) 312160484Sobrien endian = BFD_ENDIAN_LITTLE; 312260484Sobrien else 312360484Sobrien { 312460484Sobrien non_fatal (_("unrecognized -E option")); 312560484Sobrien usage (stderr, 1); 312660484Sobrien } 312760484Sobrien break; 312860484Sobrien case OPTION_ENDIAN: 312960484Sobrien if (strncmp (optarg, "big", strlen (optarg)) == 0) 313060484Sobrien endian = BFD_ENDIAN_BIG; 313160484Sobrien else if (strncmp (optarg, "little", strlen (optarg)) == 0) 313260484Sobrien endian = BFD_ENDIAN_LITTLE; 313360484Sobrien else 313460484Sobrien { 313560484Sobrien non_fatal (_("unrecognized --endian type `%s'"), optarg); 313660484Sobrien usage (stderr, 1); 313760484Sobrien } 313860484Sobrien break; 313989857Sobrien 314033965Sjdp case 'f': 3141130561Sobrien dump_file_header = TRUE; 3142130561Sobrien seenflag = TRUE; 314333965Sjdp break; 314433965Sjdp case 'i': 3145130561Sobrien formats_info = TRUE; 3146130561Sobrien seenflag = TRUE; 314733965Sjdp break; 3148130561Sobrien case 'I': 3149130561Sobrien add_include_path (optarg); 3150130561Sobrien break; 315133965Sjdp case 'p': 3152130561Sobrien dump_private_headers = TRUE; 3153130561Sobrien seenflag = TRUE; 315433965Sjdp break; 315533965Sjdp case 'x': 3156130561Sobrien dump_private_headers = TRUE; 3157130561Sobrien dump_symtab = TRUE; 3158130561Sobrien dump_reloc_info = TRUE; 3159130561Sobrien dump_file_header = TRUE; 3160130561Sobrien dump_ar_hdrs = TRUE; 3161130561Sobrien dump_section_headers = TRUE; 3162130561Sobrien seenflag = TRUE; 316333965Sjdp break; 316433965Sjdp case 't': 3165130561Sobrien dump_symtab = TRUE; 3166130561Sobrien seenflag = TRUE; 316733965Sjdp break; 316833965Sjdp case 'T': 3169130561Sobrien dump_dynamic_symtab = TRUE; 3170130561Sobrien seenflag = TRUE; 317133965Sjdp break; 317233965Sjdp case 'd': 3173130561Sobrien disassemble = TRUE; 3174130561Sobrien seenflag = TRUE; 317533965Sjdp break; 317660484Sobrien case 'z': 3177130561Sobrien disassemble_zeroes = TRUE; 317860484Sobrien break; 317933965Sjdp case 'D': 3180130561Sobrien disassemble = TRUE; 3181130561Sobrien disassemble_all = TRUE; 3182130561Sobrien seenflag = TRUE; 318333965Sjdp break; 318433965Sjdp case 'S': 3185130561Sobrien disassemble = TRUE; 3186130561Sobrien with_source_code = TRUE; 3187130561Sobrien seenflag = TRUE; 318833965Sjdp break; 318960484Sobrien case 'g': 319060484Sobrien dump_debugging = 1; 3191130561Sobrien seenflag = TRUE; 319260484Sobrien break; 3193130561Sobrien case 'e': 3194130561Sobrien dump_debugging = 1; 3195130561Sobrien dump_debugging_tags = 1; 3196130561Sobrien do_demangle = TRUE; 3197130561Sobrien seenflag = TRUE; 3198130561Sobrien break; 3199218822Sdim case 'W': 3200218822Sdim dump_dwarf_section_info = TRUE; 3201218822Sdim seenflag = TRUE; 3202218822Sdim do_debug_info = 1; 3203218822Sdim do_debug_abbrevs = 1; 3204218822Sdim do_debug_lines = 1; 3205218822Sdim do_debug_pubnames = 1; 3206218822Sdim do_debug_aranges = 1; 3207218822Sdim do_debug_ranges = 1; 3208218822Sdim do_debug_frames = 1; 3209218822Sdim do_debug_macinfo = 1; 3210218822Sdim do_debug_str = 1; 3211218822Sdim do_debug_loc = 1; 3212218822Sdim break; 321360484Sobrien case 'G': 3214130561Sobrien dump_stab_section_info = TRUE; 3215130561Sobrien seenflag = TRUE; 321660484Sobrien break; 321733965Sjdp case 's': 3218130561Sobrien dump_section_contents = TRUE; 3219130561Sobrien seenflag = TRUE; 322033965Sjdp break; 322133965Sjdp case 'r': 3222130561Sobrien dump_reloc_info = TRUE; 3223130561Sobrien seenflag = TRUE; 322433965Sjdp break; 322533965Sjdp case 'R': 3226130561Sobrien dump_dynamic_reloc_info = TRUE; 3227130561Sobrien seenflag = TRUE; 322833965Sjdp break; 322933965Sjdp case 'a': 3230130561Sobrien dump_ar_hdrs = TRUE; 3231130561Sobrien seenflag = TRUE; 323233965Sjdp break; 323333965Sjdp case 'h': 3234130561Sobrien dump_section_headers = TRUE; 3235130561Sobrien seenflag = TRUE; 323633965Sjdp break; 323733965Sjdp case 'H': 323833965Sjdp usage (stdout, 0); 3239130561Sobrien seenflag = TRUE; 324089857Sobrien case 'v': 324133965Sjdp case 'V': 3242130561Sobrien show_version = TRUE; 3243130561Sobrien seenflag = TRUE; 324433965Sjdp break; 3245104834Sobrien 324633965Sjdp default: 324733965Sjdp usage (stderr, 1); 324833965Sjdp } 324933965Sjdp } 325033965Sjdp 325133965Sjdp if (show_version) 325233965Sjdp print_version ("objdump"); 325333965Sjdp 3254130561Sobrien if (!seenflag) 325560484Sobrien usage (stderr, 2); 325633965Sjdp 325733965Sjdp if (formats_info) 3258130561Sobrien exit_status = display_info (); 325933965Sjdp else 326033965Sjdp { 326133965Sjdp if (optind == argc) 326233965Sjdp display_file ("a.out", target); 326333965Sjdp else 326433965Sjdp for (; optind < argc;) 326533965Sjdp display_file (argv[optind++], target); 326633965Sjdp } 326733965Sjdp 326833965Sjdp END_PROGRESS (program_name); 326933965Sjdp 327060484Sobrien return exit_status; 327133965Sjdp} 3272