objdump.c revision 60484
133965Sjdp/* objdump.c -- dump information about an object file. 260484Sobrien Copyright 1990, 91, 92, 93, 94, 95, 96, 97, 98, 99, 2000 338889Sjdp Free Software Foundation, Inc. 433965Sjdp 533965SjdpThis file is part of GNU Binutils. 633965Sjdp 733965SjdpThis program is free software; you can redistribute it and/or modify 833965Sjdpit under the terms of the GNU General Public License as published by 933965Sjdpthe Free Software Foundation; either version 2, or (at your option) 1033965Sjdpany later version. 1133965Sjdp 1233965SjdpThis program is distributed in the hope that it will be useful, 1333965Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of 1433965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1533965SjdpGNU General Public License for more details. 1633965Sjdp 1733965SjdpYou should have received a copy of the GNU General Public License 1833965Sjdpalong with this program; if not, write to the Free Software 1933965SjdpFoundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 2033965Sjdp 2133965Sjdp#include "bfd.h" 2233965Sjdp#include "getopt.h" 2333965Sjdp#include "progress.h" 2433965Sjdp#include "bucomm.h" 2533965Sjdp#include <ctype.h> 2633965Sjdp#include "dis-asm.h" 2733965Sjdp#include "libiberty.h" 2833965Sjdp#include "demangle.h" 2933965Sjdp#include "debug.h" 3033965Sjdp#include "budbg.h" 3133965Sjdp 3233965Sjdp#ifdef ANSI_PROTOTYPES 3333965Sjdp#include <stdarg.h> 3433965Sjdp#else 3533965Sjdp#include <varargs.h> 3633965Sjdp#endif 3733965Sjdp 3833965Sjdp/* Internal headers for the ELF .stab-dump code - sorry. */ 3933965Sjdp#define BYTES_IN_WORD 32 4033965Sjdp#include "aout/aout64.h" 4133965Sjdp 4233965Sjdp#ifdef NEED_DECLARATION_FPRINTF 4333965Sjdp/* This is needed by INIT_DISASSEMBLE_INFO. */ 4433965Sjdpextern int fprintf PARAMS ((FILE *, const char *, ...)); 4533965Sjdp#endif 4633965Sjdp 4760484Sobrien/* Exit status. */ 4860484Sobrienstatic int exit_status = 0; 4960484Sobrien 5033965Sjdpstatic char *default_target = NULL; /* default at runtime */ 5133965Sjdp 5233965Sjdpstatic int show_version = 0; /* show the version number */ 5333965Sjdpstatic int dump_section_contents; /* -s */ 5433965Sjdpstatic int dump_section_headers; /* -h */ 5533965Sjdpstatic boolean dump_file_header; /* -f */ 5633965Sjdpstatic int dump_symtab; /* -t */ 5733965Sjdpstatic int dump_dynamic_symtab; /* -T */ 5833965Sjdpstatic int dump_reloc_info; /* -r */ 5933965Sjdpstatic int dump_dynamic_reloc_info; /* -R */ 6033965Sjdpstatic int dump_ar_hdrs; /* -a */ 6133965Sjdpstatic int dump_private_headers; /* -p */ 6233965Sjdpstatic int prefix_addresses; /* --prefix-addresses */ 6333965Sjdpstatic int with_line_numbers; /* -l */ 6433965Sjdpstatic boolean with_source_code; /* -S */ 6533965Sjdpstatic int show_raw_insn; /* --show-raw-insn */ 6633965Sjdpstatic int dump_stab_section_info; /* --stabs */ 6733965Sjdpstatic int do_demangle; /* -C, --demangle */ 6833965Sjdpstatic boolean disassemble; /* -d */ 6933965Sjdpstatic boolean disassemble_all; /* -D */ 7033965Sjdpstatic int disassemble_zeroes; /* --disassemble-zeroes */ 7133965Sjdpstatic boolean formats_info; /* -i */ 7233965Sjdpstatic char *only; /* -j secname */ 7333965Sjdpstatic int wide_output; /* -w */ 7433965Sjdpstatic bfd_vma start_address = (bfd_vma) -1; /* --start-address */ 7533965Sjdpstatic bfd_vma stop_address = (bfd_vma) -1; /* --stop-address */ 7633965Sjdpstatic int dump_debugging; /* --debugging */ 7733965Sjdpstatic bfd_vma adjust_section_vma = 0; /* --adjust-vma */ 7860484Sobrienstatic int file_start_context = 0; /* --file-start-context */ 7933965Sjdp 8033965Sjdp/* Extra info to pass to the disassembler address printing function. */ 8133965Sjdpstruct objdump_disasm_info { 8233965Sjdp bfd *abfd; 8333965Sjdp asection *sec; 8433965Sjdp boolean require_sec; 8533965Sjdp}; 8633965Sjdp 8733965Sjdp/* Architecture to disassemble for, or default if NULL. */ 8833965Sjdpstatic char *machine = (char *) NULL; 8933965Sjdp 9060484Sobrien/* Target specific options to the disassembler. */ 9160484Sobrienstatic char *disassembler_options = (char *) NULL; 9260484Sobrien 9333965Sjdp/* Endianness to disassemble for, or default if BFD_ENDIAN_UNKNOWN. */ 9433965Sjdpstatic enum bfd_endian endian = BFD_ENDIAN_UNKNOWN; 9533965Sjdp 9633965Sjdp/* The symbol table. */ 9733965Sjdpstatic asymbol **syms; 9833965Sjdp 9933965Sjdp/* Number of symbols in `syms'. */ 10033965Sjdpstatic long symcount = 0; 10133965Sjdp 10233965Sjdp/* The sorted symbol table. */ 10333965Sjdpstatic asymbol **sorted_syms; 10433965Sjdp 10533965Sjdp/* Number of symbols in `sorted_syms'. */ 10633965Sjdpstatic long sorted_symcount = 0; 10733965Sjdp 10833965Sjdp/* The dynamic symbol table. */ 10933965Sjdpstatic asymbol **dynsyms; 11033965Sjdp 11133965Sjdp/* Number of symbols in `dynsyms'. */ 11233965Sjdpstatic long dynsymcount = 0; 11333965Sjdp 11433965Sjdp/* Static declarations. */ 11533965Sjdp 11633965Sjdpstatic void 11733965Sjdpusage PARAMS ((FILE *, int)); 11833965Sjdp 11933965Sjdpstatic void 12060484Sobriennonfatal PARAMS ((const char *)); 12160484Sobrien 12260484Sobrienstatic void 12333965Sjdpdisplay_file PARAMS ((char *filename, char *target)); 12433965Sjdp 12533965Sjdpstatic void 12633965Sjdpdump_section_header PARAMS ((bfd *, asection *, PTR)); 12733965Sjdp 12833965Sjdpstatic void 12933965Sjdpdump_headers PARAMS ((bfd *)); 13033965Sjdp 13133965Sjdpstatic void 13233965Sjdpdump_data PARAMS ((bfd *abfd)); 13333965Sjdp 13433965Sjdpstatic void 13533965Sjdpdump_relocs PARAMS ((bfd *abfd)); 13633965Sjdp 13733965Sjdpstatic void 13833965Sjdpdump_dynamic_relocs PARAMS ((bfd * abfd)); 13933965Sjdp 14033965Sjdpstatic void 14133965Sjdpdump_reloc_set PARAMS ((bfd *, asection *, arelent **, long)); 14233965Sjdp 14333965Sjdpstatic void 14433965Sjdpdump_symbols PARAMS ((bfd *abfd, boolean dynamic)); 14533965Sjdp 14633965Sjdpstatic void 14733965Sjdpdump_bfd_header PARAMS ((bfd *)); 14833965Sjdp 14933965Sjdpstatic void 15033965Sjdpdump_bfd_private_header PARAMS ((bfd *)); 15133965Sjdp 15233965Sjdpstatic void 15333965Sjdpdisplay_bfd PARAMS ((bfd *abfd)); 15433965Sjdp 15533965Sjdpstatic void 15633965Sjdpdisplay_target_list PARAMS ((void)); 15733965Sjdp 15833965Sjdpstatic void 15933965Sjdpdisplay_info_table PARAMS ((int, int)); 16033965Sjdp 16133965Sjdpstatic void 16233965Sjdpdisplay_target_tables PARAMS ((void)); 16333965Sjdp 16433965Sjdpstatic void 16533965Sjdpdisplay_info PARAMS ((void)); 16633965Sjdp 16733965Sjdpstatic void 16833965Sjdpobjdump_print_value PARAMS ((bfd_vma, struct disassemble_info *, boolean)); 16933965Sjdp 17033965Sjdpstatic void 17133965Sjdpobjdump_print_symname PARAMS ((bfd *, struct disassemble_info *, asymbol *)); 17233965Sjdp 17333965Sjdpstatic asymbol * 17433965Sjdpfind_symbol_for_address PARAMS ((bfd *, asection *, bfd_vma, boolean, long *)); 17533965Sjdp 17633965Sjdpstatic void 17733965Sjdpobjdump_print_addr_with_sym PARAMS ((bfd *, asection *, asymbol *, bfd_vma, 17833965Sjdp struct disassemble_info *, boolean)); 17933965Sjdp 18033965Sjdpstatic void 18133965Sjdpobjdump_print_addr PARAMS ((bfd_vma, struct disassemble_info *, boolean)); 18233965Sjdp 18333965Sjdpstatic void 18433965Sjdpobjdump_print_address PARAMS ((bfd_vma, struct disassemble_info *)); 18533965Sjdp 18633965Sjdpstatic void 18733965Sjdpshow_line PARAMS ((bfd *, asection *, bfd_vma)); 18833965Sjdp 18933965Sjdpstatic void 19033965Sjdpdisassemble_bytes PARAMS ((struct disassemble_info *, disassembler_ftype, 19160484Sobrien boolean, bfd_byte *, bfd_vma, bfd_vma, 19260484Sobrien arelent ***, arelent **)); 19333965Sjdp 19433965Sjdpstatic void 19533965Sjdpdisassemble_data PARAMS ((bfd *)); 19633965Sjdp 19733965Sjdpstatic const char * 19833965Sjdpendian_string PARAMS ((enum bfd_endian)); 19933965Sjdp 20033965Sjdpstatic asymbol ** 20133965Sjdpslurp_symtab PARAMS ((bfd *)); 20233965Sjdp 20333965Sjdpstatic asymbol ** 20433965Sjdpslurp_dynamic_symtab PARAMS ((bfd *)); 20533965Sjdp 20633965Sjdpstatic long 20733965Sjdpremove_useless_symbols PARAMS ((asymbol **, long)); 20833965Sjdp 20933965Sjdpstatic int 21033965Sjdpcompare_symbols PARAMS ((const PTR, const PTR)); 21133965Sjdp 21233965Sjdpstatic int 21333965Sjdpcompare_relocs PARAMS ((const PTR, const PTR)); 21433965Sjdp 21533965Sjdpstatic void 21633965Sjdpdump_stabs PARAMS ((bfd *)); 21733965Sjdp 21833965Sjdpstatic boolean 21933965Sjdpread_section_stabs PARAMS ((bfd *, const char *, const char *)); 22033965Sjdp 22133965Sjdpstatic void 22233965Sjdpprint_section_stabs PARAMS ((bfd *, const char *, const char *)); 22333965Sjdp 22433965Sjdpstatic void 22533965Sjdpusage (stream, status) 22633965Sjdp FILE *stream; 22733965Sjdp int status; 22833965Sjdp{ 22960484Sobrien fprintf (stream, _("Usage: %s <switches> file(s)\n"), program_name); 23060484Sobrien fprintf (stream, _(" At least one of the following switches must be given:\n")); 23160484Sobrien fprintf (stream, _("\ 23260484Sobrien -a --archive-headers Display archive header information\n\ 23360484Sobrien -f --file-headers Display the contents of the overall file header\n\ 23460484Sobrien -p --private-headers Display object format specific file header contents\n\ 23560484Sobrien -h --[section-]headers Display the contents of the section headers\n\ 23660484Sobrien -x --all-headers Display the contents of all headers\n\ 23760484Sobrien -d --disassemble Display assembler contents of executable sections\n\ 23860484Sobrien -D --disassemble-all Display assembler contents of all sections\n\ 23960484Sobrien -S --source Intermix source code with disassembly\n\ 24060484Sobrien -s --full-contents Display the full contents of all sections requested\n\ 24160484Sobrien -g --debugging Display debug information in object file\n\ 24260484Sobrien -G --stabs Display the STABS contents of an ELF format file\n\ 24360484Sobrien -t --syms Display the contents of the symbol table(s)\n\ 24460484Sobrien -T --dynamic-syms Display the contents of the dynamic symbol table\n\ 24560484Sobrien -r --reloc Display the relocation entries in the file\n\ 24660484Sobrien -R --dynamic-reloc Display the dynamic relocation entries in the file\n\ 24760484Sobrien -V --version Display this program's version number\n\ 24860484Sobrien -i --info List object formats and architectures supported\n\ 24960484Sobrien -H --help Display this information\n\ 25060484Sobrien")); 25160484Sobrien if (status != 2) 25260484Sobrien { 25360484Sobrien fprintf (stream, _("\n The following switches are optional:\n")); 25460484Sobrien fprintf (stream, _("\ 25560484Sobrien -b --target <bfdname> Specify the target object format as <bfdname>\n\ 25660484Sobrien -m --architecture <machine> Specify the target architecture as <machine>\n\ 25760484Sobrien -j --section <name> Only display information for section <name>\n\ 25860484Sobrien -M --disassembler-options <o> Pass text <o> on to the disassembler\n\ 25960484Sobrien -EB --endian=big Assume big endian format when disassembling\n\ 26060484Sobrien -EL --endian=little Assume little endian format when disassembling\n\ 26160484Sobrien --file-start-context Include context from start of file (with -S)\n\ 26260484Sobrien -l --line-numbers Include line numbers and filenames in output\n\ 26360484Sobrien -C --demangle Decode mangled/processed symbol names\n\ 26460484Sobrien -w --wide Format output for more than 80 columns\n\ 26560484Sobrien -z --disassemble-zeroes Do not skip blocks of zeroes when disassembling\n\ 26660484Sobrien --start-address <addr> Only process data whoes address is >= <addr>\n\ 26760484Sobrien --stop-address <addr> Only process data whoes address is <= <addr>\n\ 26860484Sobrien --prefix-addresses Print complete address alongside disassembly\n\ 26960484Sobrien --[no-]show-raw-insn Display hex alongside symbolic disassembly\n\ 27060484Sobrien --adjust-vma <offset> Add <offset> to all displayed section addresses\n\ 27160484Sobrien\n")); 27260484Sobrien list_supported_targets (program_name, stream); 27360484Sobrien 27460484Sobrien disassembler_usage (stream); 27560484Sobrien } 27633965Sjdp if (status == 0) 27760484Sobrien fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO); 27833965Sjdp exit (status); 27933965Sjdp} 28033965Sjdp 28133965Sjdp/* 150 isn't special; it's just an arbitrary non-ASCII char value. */ 28233965Sjdp 28333965Sjdp#define OPTION_ENDIAN (150) 28433965Sjdp#define OPTION_START_ADDRESS (OPTION_ENDIAN + 1) 28533965Sjdp#define OPTION_STOP_ADDRESS (OPTION_START_ADDRESS + 1) 28633965Sjdp#define OPTION_ADJUST_VMA (OPTION_STOP_ADDRESS + 1) 28733965Sjdp 28833965Sjdpstatic struct option long_options[]= 28933965Sjdp{ 29033965Sjdp {"adjust-vma", required_argument, NULL, OPTION_ADJUST_VMA}, 29133965Sjdp {"all-headers", no_argument, NULL, 'x'}, 29233965Sjdp {"private-headers", no_argument, NULL, 'p'}, 29333965Sjdp {"architecture", required_argument, NULL, 'm'}, 29433965Sjdp {"archive-headers", no_argument, NULL, 'a'}, 29560484Sobrien {"debugging", no_argument, NULL, 'g'}, 29660484Sobrien {"demangle", no_argument, NULL, 'C'}, 29733965Sjdp {"disassemble", no_argument, NULL, 'd'}, 29833965Sjdp {"disassemble-all", no_argument, NULL, 'D'}, 29960484Sobrien {"disassembler-options", required_argument, NULL, 'M'}, 30060484Sobrien {"disassemble-zeroes", no_argument, NULL, 'z'}, 30133965Sjdp {"dynamic-reloc", no_argument, NULL, 'R'}, 30233965Sjdp {"dynamic-syms", no_argument, NULL, 'T'}, 30333965Sjdp {"endian", required_argument, NULL, OPTION_ENDIAN}, 30433965Sjdp {"file-headers", no_argument, NULL, 'f'}, 30560484Sobrien {"file-start-context", no_argument, &file_start_context, 1}, 30633965Sjdp {"full-contents", no_argument, NULL, 's'}, 30733965Sjdp {"headers", no_argument, NULL, 'h'}, 30833965Sjdp {"help", no_argument, NULL, 'H'}, 30933965Sjdp {"info", no_argument, NULL, 'i'}, 31033965Sjdp {"line-numbers", no_argument, NULL, 'l'}, 31133965Sjdp {"no-show-raw-insn", no_argument, &show_raw_insn, -1}, 31233965Sjdp {"prefix-addresses", no_argument, &prefix_addresses, 1}, 31333965Sjdp {"reloc", no_argument, NULL, 'r'}, 31433965Sjdp {"section", required_argument, NULL, 'j'}, 31533965Sjdp {"section-headers", no_argument, NULL, 'h'}, 31633965Sjdp {"show-raw-insn", no_argument, &show_raw_insn, 1}, 31733965Sjdp {"source", no_argument, NULL, 'S'}, 31860484Sobrien {"stabs", no_argument, NULL, 'G'}, 31933965Sjdp {"start-address", required_argument, NULL, OPTION_START_ADDRESS}, 32033965Sjdp {"stop-address", required_argument, NULL, OPTION_STOP_ADDRESS}, 32133965Sjdp {"syms", no_argument, NULL, 't'}, 32233965Sjdp {"target", required_argument, NULL, 'b'}, 32360484Sobrien {"version", no_argument, NULL, 'V'}, 32460484Sobrien {"wide", no_argument, NULL, 'w'}, 32533965Sjdp {0, no_argument, 0, 0} 32633965Sjdp}; 32733965Sjdp 32833965Sjdpstatic void 32960484Sobriennonfatal (msg) 33060484Sobrien const char *msg; 33160484Sobrien{ 33260484Sobrien bfd_nonfatal (msg); 33360484Sobrien exit_status = 1; 33460484Sobrien} 33560484Sobrien 33660484Sobrienstatic void 33733965Sjdpdump_section_header (abfd, section, ignored) 33860484Sobrien bfd *abfd ATTRIBUTE_UNUSED; 33933965Sjdp asection *section; 34060484Sobrien PTR ignored ATTRIBUTE_UNUSED; 34133965Sjdp{ 34233965Sjdp char *comma = ""; 34360484Sobrien unsigned int opb = bfd_octets_per_byte (abfd); 34433965Sjdp 34533965Sjdp printf ("%3d %-13s %08lx ", section->index, 34633965Sjdp bfd_get_section_name (abfd, section), 34760484Sobrien (unsigned long) bfd_section_size (abfd, section) / opb); 34833965Sjdp printf_vma (bfd_get_section_vma (abfd, section)); 34933965Sjdp printf (" "); 35033965Sjdp printf_vma (section->lma); 35133965Sjdp printf (" %08lx 2**%u", section->filepos, 35233965Sjdp bfd_get_section_alignment (abfd, section)); 35333965Sjdp if (! wide_output) 35433965Sjdp printf ("\n "); 35533965Sjdp printf (" "); 35633965Sjdp 35733965Sjdp#define PF(x, y) \ 35833965Sjdp if (section->flags & x) { printf ("%s%s", comma, y); comma = ", "; } 35933965Sjdp 36033965Sjdp PF (SEC_HAS_CONTENTS, "CONTENTS"); 36133965Sjdp PF (SEC_ALLOC, "ALLOC"); 36233965Sjdp PF (SEC_CONSTRUCTOR, "CONSTRUCTOR"); 36333965Sjdp PF (SEC_CONSTRUCTOR_TEXT, "CONSTRUCTOR TEXT"); 36433965Sjdp PF (SEC_CONSTRUCTOR_DATA, "CONSTRUCTOR DATA"); 36533965Sjdp PF (SEC_CONSTRUCTOR_BSS, "CONSTRUCTOR BSS"); 36633965Sjdp PF (SEC_LOAD, "LOAD"); 36733965Sjdp PF (SEC_RELOC, "RELOC"); 36833965Sjdp#ifdef SEC_BALIGN 36933965Sjdp PF (SEC_BALIGN, "BALIGN"); 37033965Sjdp#endif 37133965Sjdp PF (SEC_READONLY, "READONLY"); 37233965Sjdp PF (SEC_CODE, "CODE"); 37333965Sjdp PF (SEC_DATA, "DATA"); 37433965Sjdp PF (SEC_ROM, "ROM"); 37533965Sjdp PF (SEC_DEBUGGING, "DEBUGGING"); 37633965Sjdp PF (SEC_NEVER_LOAD, "NEVER_LOAD"); 37733965Sjdp PF (SEC_EXCLUDE, "EXCLUDE"); 37833965Sjdp PF (SEC_SORT_ENTRIES, "SORT_ENTRIES"); 37960484Sobrien PF (SEC_SMALL_DATA, "SMALL_DATA"); 38060484Sobrien PF (SEC_SHARED, "SHARED"); 38133965Sjdp 38233965Sjdp if ((section->flags & SEC_LINK_ONCE) != 0) 38333965Sjdp { 38433965Sjdp const char *ls; 38533965Sjdp 38633965Sjdp switch (section->flags & SEC_LINK_DUPLICATES) 38733965Sjdp { 38833965Sjdp default: 38933965Sjdp abort (); 39033965Sjdp case SEC_LINK_DUPLICATES_DISCARD: 39133965Sjdp ls = "LINK_ONCE_DISCARD"; 39233965Sjdp break; 39333965Sjdp case SEC_LINK_DUPLICATES_ONE_ONLY: 39433965Sjdp ls = "LINK_ONCE_ONE_ONLY"; 39533965Sjdp break; 39633965Sjdp case SEC_LINK_DUPLICATES_SAME_SIZE: 39733965Sjdp ls = "LINK_ONCE_SAME_SIZE"; 39833965Sjdp break; 39933965Sjdp case SEC_LINK_DUPLICATES_SAME_CONTENTS: 40033965Sjdp ls = "LINK_ONCE_SAME_CONTENTS"; 40133965Sjdp break; 40233965Sjdp } 40333965Sjdp printf ("%s%s", comma, ls); 40460484Sobrien 40560484Sobrien if (section->comdat != NULL) 40660484Sobrien printf (" (COMDAT %s %ld)", section->comdat->name, 40760484Sobrien section->comdat->symbol); 40860484Sobrien 40933965Sjdp comma = ", "; 41033965Sjdp } 41133965Sjdp 41233965Sjdp printf ("\n"); 41333965Sjdp#undef PF 41433965Sjdp} 41533965Sjdp 41633965Sjdpstatic void 41733965Sjdpdump_headers (abfd) 41833965Sjdp bfd *abfd; 41933965Sjdp{ 42060484Sobrien printf (_("Sections:\n")); 42160484Sobrien 42233965Sjdp#ifndef BFD64 42360484Sobrien printf (_("Idx Name Size VMA LMA File off Algn")); 42433965Sjdp#else 42560484Sobrien printf (_("Idx Name Size VMA LMA File off Algn")); 42633965Sjdp#endif 42760484Sobrien 42860484Sobrien if (wide_output) 42960484Sobrien printf (_(" Flags")); 43060484Sobrien printf ("\n"); 43160484Sobrien 43233965Sjdp bfd_map_over_sections (abfd, dump_section_header, (PTR) NULL); 43333965Sjdp} 43433965Sjdp 43533965Sjdpstatic asymbol ** 43633965Sjdpslurp_symtab (abfd) 43733965Sjdp bfd *abfd; 43833965Sjdp{ 43933965Sjdp asymbol **sy = (asymbol **) NULL; 44033965Sjdp long storage; 44133965Sjdp 44233965Sjdp if (!(bfd_get_file_flags (abfd) & HAS_SYMS)) 44333965Sjdp { 44460484Sobrien non_fatal (_("%s: no symbols"), bfd_get_filename (abfd)); 44533965Sjdp symcount = 0; 44633965Sjdp return NULL; 44733965Sjdp } 44833965Sjdp 44933965Sjdp storage = bfd_get_symtab_upper_bound (abfd); 45033965Sjdp if (storage < 0) 45133965Sjdp bfd_fatal (bfd_get_filename (abfd)); 45233965Sjdp 45333965Sjdp if (storage) 45433965Sjdp { 45533965Sjdp sy = (asymbol **) xmalloc (storage); 45633965Sjdp } 45733965Sjdp symcount = bfd_canonicalize_symtab (abfd, sy); 45833965Sjdp if (symcount < 0) 45933965Sjdp bfd_fatal (bfd_get_filename (abfd)); 46033965Sjdp if (symcount == 0) 46160484Sobrien non_fatal (_("%s: no symbols"), bfd_get_filename (abfd)); 46233965Sjdp return sy; 46333965Sjdp} 46433965Sjdp 46533965Sjdp/* Read in the dynamic symbols. */ 46633965Sjdp 46733965Sjdpstatic asymbol ** 46833965Sjdpslurp_dynamic_symtab (abfd) 46933965Sjdp bfd *abfd; 47033965Sjdp{ 47133965Sjdp asymbol **sy = (asymbol **) NULL; 47233965Sjdp long storage; 47333965Sjdp 47433965Sjdp storage = bfd_get_dynamic_symtab_upper_bound (abfd); 47533965Sjdp if (storage < 0) 47633965Sjdp { 47733965Sjdp if (!(bfd_get_file_flags (abfd) & DYNAMIC)) 47833965Sjdp { 47960484Sobrien non_fatal (_("%s: not a dynamic object"), bfd_get_filename (abfd)); 48033965Sjdp dynsymcount = 0; 48133965Sjdp return NULL; 48233965Sjdp } 48333965Sjdp 48433965Sjdp bfd_fatal (bfd_get_filename (abfd)); 48533965Sjdp } 48633965Sjdp 48733965Sjdp if (storage) 48833965Sjdp { 48933965Sjdp sy = (asymbol **) xmalloc (storage); 49033965Sjdp } 49133965Sjdp dynsymcount = bfd_canonicalize_dynamic_symtab (abfd, sy); 49233965Sjdp if (dynsymcount < 0) 49333965Sjdp bfd_fatal (bfd_get_filename (abfd)); 49433965Sjdp if (dynsymcount == 0) 49560484Sobrien non_fatal (_("%s: No dynamic symbols"), bfd_get_filename (abfd)); 49633965Sjdp return sy; 49733965Sjdp} 49833965Sjdp 49933965Sjdp/* Filter out (in place) symbols that are useless for disassembly. 50033965Sjdp COUNT is the number of elements in SYMBOLS. 50133965Sjdp Return the number of useful symbols. */ 50233965Sjdp 50333965Sjdpstatic long 50433965Sjdpremove_useless_symbols (symbols, count) 50533965Sjdp asymbol **symbols; 50633965Sjdp long count; 50733965Sjdp{ 50833965Sjdp register asymbol **in_ptr = symbols, **out_ptr = symbols; 50933965Sjdp 51033965Sjdp while (--count >= 0) 51133965Sjdp { 51233965Sjdp asymbol *sym = *in_ptr++; 51333965Sjdp 51433965Sjdp if (sym->name == NULL || sym->name[0] == '\0') 51533965Sjdp continue; 51633965Sjdp if (sym->flags & (BSF_DEBUGGING)) 51733965Sjdp continue; 51833965Sjdp if (bfd_is_und_section (sym->section) 51933965Sjdp || bfd_is_com_section (sym->section)) 52033965Sjdp continue; 52133965Sjdp 52233965Sjdp *out_ptr++ = sym; 52333965Sjdp } 52433965Sjdp return out_ptr - symbols; 52533965Sjdp} 52633965Sjdp 52733965Sjdp/* Sort symbols into value order. */ 52833965Sjdp 52933965Sjdpstatic int 53033965Sjdpcompare_symbols (ap, bp) 53133965Sjdp const PTR ap; 53233965Sjdp const PTR bp; 53333965Sjdp{ 53433965Sjdp const asymbol *a = *(const asymbol **)ap; 53533965Sjdp const asymbol *b = *(const asymbol **)bp; 53633965Sjdp const char *an, *bn; 53733965Sjdp size_t anl, bnl; 53833965Sjdp boolean af, bf; 53933965Sjdp flagword aflags, bflags; 54033965Sjdp 54133965Sjdp if (bfd_asymbol_value (a) > bfd_asymbol_value (b)) 54233965Sjdp return 1; 54333965Sjdp else if (bfd_asymbol_value (a) < bfd_asymbol_value (b)) 54433965Sjdp return -1; 54533965Sjdp 54633965Sjdp if (a->section > b->section) 54733965Sjdp return 1; 54833965Sjdp else if (a->section < b->section) 54933965Sjdp return -1; 55033965Sjdp 55133965Sjdp an = bfd_asymbol_name (a); 55233965Sjdp bn = bfd_asymbol_name (b); 55333965Sjdp anl = strlen (an); 55433965Sjdp bnl = strlen (bn); 55533965Sjdp 55633965Sjdp /* The symbols gnu_compiled and gcc2_compiled convey no real 55733965Sjdp information, so put them after other symbols with the same value. */ 55833965Sjdp 55933965Sjdp af = (strstr (an, "gnu_compiled") != NULL 56033965Sjdp || strstr (an, "gcc2_compiled") != NULL); 56133965Sjdp bf = (strstr (bn, "gnu_compiled") != NULL 56233965Sjdp || strstr (bn, "gcc2_compiled") != NULL); 56333965Sjdp 56433965Sjdp if (af && ! bf) 56533965Sjdp return 1; 56633965Sjdp if (! af && bf) 56733965Sjdp return -1; 56833965Sjdp 56933965Sjdp /* We use a heuristic for the file name, to try to sort it after 57033965Sjdp more useful symbols. It may not work on non Unix systems, but it 57133965Sjdp doesn't really matter; the only difference is precisely which 57233965Sjdp symbol names get printed. */ 57333965Sjdp 57433965Sjdp#define file_symbol(s, sn, snl) \ 57533965Sjdp (((s)->flags & BSF_FILE) != 0 \ 57633965Sjdp || ((sn)[(snl) - 2] == '.' \ 57733965Sjdp && ((sn)[(snl) - 1] == 'o' \ 57833965Sjdp || (sn)[(snl) - 1] == 'a'))) 57933965Sjdp 58033965Sjdp af = file_symbol (a, an, anl); 58133965Sjdp bf = file_symbol (b, bn, bnl); 58233965Sjdp 58333965Sjdp if (af && ! bf) 58433965Sjdp return 1; 58533965Sjdp if (! af && bf) 58633965Sjdp return -1; 58733965Sjdp 58833965Sjdp /* Try to sort global symbols before local symbols before function 58933965Sjdp symbols before debugging symbols. */ 59033965Sjdp 59133965Sjdp aflags = a->flags; 59233965Sjdp bflags = b->flags; 59333965Sjdp 59433965Sjdp if ((aflags & BSF_DEBUGGING) != (bflags & BSF_DEBUGGING)) 59533965Sjdp { 59633965Sjdp if ((aflags & BSF_DEBUGGING) != 0) 59733965Sjdp return 1; 59833965Sjdp else 59933965Sjdp return -1; 60033965Sjdp } 60133965Sjdp if ((aflags & BSF_FUNCTION) != (bflags & BSF_FUNCTION)) 60233965Sjdp { 60333965Sjdp if ((aflags & BSF_FUNCTION) != 0) 60433965Sjdp return -1; 60533965Sjdp else 60633965Sjdp return 1; 60733965Sjdp } 60833965Sjdp if ((aflags & BSF_LOCAL) != (bflags & BSF_LOCAL)) 60933965Sjdp { 61033965Sjdp if ((aflags & BSF_LOCAL) != 0) 61133965Sjdp return 1; 61233965Sjdp else 61333965Sjdp return -1; 61433965Sjdp } 61533965Sjdp if ((aflags & BSF_GLOBAL) != (bflags & BSF_GLOBAL)) 61633965Sjdp { 61733965Sjdp if ((aflags & BSF_GLOBAL) != 0) 61833965Sjdp return -1; 61933965Sjdp else 62033965Sjdp return 1; 62133965Sjdp } 62233965Sjdp 62333965Sjdp /* Symbols that start with '.' might be section names, so sort them 62433965Sjdp after symbols that don't start with '.'. */ 62533965Sjdp if (an[0] == '.' && bn[0] != '.') 62633965Sjdp return 1; 62733965Sjdp if (an[0] != '.' && bn[0] == '.') 62833965Sjdp return -1; 62933965Sjdp 63033965Sjdp /* Finally, if we can't distinguish them in any other way, try to 63133965Sjdp get consistent results by sorting the symbols by name. */ 63233965Sjdp return strcmp (an, bn); 63333965Sjdp} 63433965Sjdp 63533965Sjdp/* Sort relocs into address order. */ 63633965Sjdp 63733965Sjdpstatic int 63833965Sjdpcompare_relocs (ap, bp) 63933965Sjdp const PTR ap; 64033965Sjdp const PTR bp; 64133965Sjdp{ 64233965Sjdp const arelent *a = *(const arelent **)ap; 64333965Sjdp const arelent *b = *(const arelent **)bp; 64433965Sjdp 64533965Sjdp if (a->address > b->address) 64633965Sjdp return 1; 64733965Sjdp else if (a->address < b->address) 64833965Sjdp return -1; 64933965Sjdp 65033965Sjdp /* So that associated relocations tied to the same address show up 65133965Sjdp in the correct order, we don't do any further sorting. */ 65233965Sjdp if (a > b) 65333965Sjdp return 1; 65433965Sjdp else if (a < b) 65533965Sjdp return -1; 65633965Sjdp else 65733965Sjdp return 0; 65833965Sjdp} 65933965Sjdp 66033965Sjdp/* Print VMA to STREAM. If SKIP_ZEROES is true, omit leading zeroes. */ 66133965Sjdp 66233965Sjdpstatic void 66333965Sjdpobjdump_print_value (vma, info, skip_zeroes) 66433965Sjdp bfd_vma vma; 66533965Sjdp struct disassemble_info *info; 66633965Sjdp boolean skip_zeroes; 66733965Sjdp{ 66833965Sjdp char buf[30]; 66933965Sjdp char *p; 67033965Sjdp 67133965Sjdp sprintf_vma (buf, vma); 67233965Sjdp if (! skip_zeroes) 67333965Sjdp p = buf; 67433965Sjdp else 67533965Sjdp { 67633965Sjdp for (p = buf; *p == '0'; ++p) 67733965Sjdp ; 67833965Sjdp if (*p == '\0') 67933965Sjdp --p; 68033965Sjdp } 68133965Sjdp (*info->fprintf_func) (info->stream, "%s", p); 68233965Sjdp} 68333965Sjdp 68433965Sjdp/* Print the name of a symbol. */ 68533965Sjdp 68633965Sjdpstatic void 68733965Sjdpobjdump_print_symname (abfd, info, sym) 68833965Sjdp bfd *abfd; 68933965Sjdp struct disassemble_info *info; 69033965Sjdp asymbol *sym; 69133965Sjdp{ 69233965Sjdp char *alloc; 69333965Sjdp const char *name; 69433965Sjdp const char *print; 69533965Sjdp 69633965Sjdp alloc = NULL; 69733965Sjdp name = bfd_asymbol_name (sym); 69833965Sjdp if (! do_demangle || name[0] == '\0') 69933965Sjdp print = name; 70033965Sjdp else 70133965Sjdp { 70233965Sjdp /* Demangle the name. */ 70333965Sjdp if (bfd_get_symbol_leading_char (abfd) == name[0]) 70433965Sjdp ++name; 70533965Sjdp 70633965Sjdp alloc = cplus_demangle (name, DMGL_ANSI | DMGL_PARAMS); 70733965Sjdp if (alloc == NULL) 70833965Sjdp print = name; 70933965Sjdp else 71033965Sjdp print = alloc; 71133965Sjdp } 71233965Sjdp 71333965Sjdp if (info != NULL) 71433965Sjdp (*info->fprintf_func) (info->stream, "%s", print); 71533965Sjdp else 71633965Sjdp printf ("%s", print); 71733965Sjdp 71833965Sjdp if (alloc != NULL) 71933965Sjdp free (alloc); 72033965Sjdp} 72133965Sjdp 72233965Sjdp/* Locate a symbol given a bfd, a section, and a VMA. If REQUIRE_SEC 72333965Sjdp is true, then always require the symbol to be in the section. This 72433965Sjdp returns NULL if there is no suitable symbol. If PLACE is not NULL, 72533965Sjdp then *PLACE is set to the index of the symbol in sorted_syms. */ 72633965Sjdp 72733965Sjdpstatic asymbol * 72833965Sjdpfind_symbol_for_address (abfd, sec, vma, require_sec, place) 72933965Sjdp bfd *abfd; 73033965Sjdp asection *sec; 73133965Sjdp bfd_vma vma; 73233965Sjdp boolean require_sec; 73333965Sjdp long *place; 73433965Sjdp{ 73533965Sjdp /* @@ Would it speed things up to cache the last two symbols returned, 73633965Sjdp and maybe their address ranges? For many processors, only one memory 73733965Sjdp operand can be present at a time, so the 2-entry cache wouldn't be 73833965Sjdp constantly churned by code doing heavy memory accesses. */ 73933965Sjdp 74033965Sjdp /* Indices in `sorted_syms'. */ 74133965Sjdp long min = 0; 74233965Sjdp long max = sorted_symcount; 74333965Sjdp long thisplace; 74460484Sobrien unsigned int opb = bfd_octets_per_byte (abfd); 74533965Sjdp 74633965Sjdp if (sorted_symcount < 1) 74733965Sjdp return NULL; 74833965Sjdp 74933965Sjdp /* Perform a binary search looking for the closest symbol to the 75033965Sjdp required value. We are searching the range (min, max]. */ 75133965Sjdp while (min + 1 < max) 75233965Sjdp { 75333965Sjdp asymbol *sym; 75433965Sjdp 75533965Sjdp thisplace = (max + min) / 2; 75633965Sjdp sym = sorted_syms[thisplace]; 75733965Sjdp 75833965Sjdp if (bfd_asymbol_value (sym) > vma) 75933965Sjdp max = thisplace; 76033965Sjdp else if (bfd_asymbol_value (sym) < vma) 76133965Sjdp min = thisplace; 76233965Sjdp else 76333965Sjdp { 76433965Sjdp min = thisplace; 76533965Sjdp break; 76633965Sjdp } 76733965Sjdp } 76833965Sjdp 76933965Sjdp /* The symbol we want is now in min, the low end of the range we 77033965Sjdp were searching. If there are several symbols with the same 77133965Sjdp value, we want the first one. */ 77233965Sjdp thisplace = min; 77333965Sjdp while (thisplace > 0 77433965Sjdp && (bfd_asymbol_value (sorted_syms[thisplace]) 77533965Sjdp == bfd_asymbol_value (sorted_syms[thisplace - 1]))) 77633965Sjdp --thisplace; 77733965Sjdp 77833965Sjdp /* If the file is relocateable, and the symbol could be from this 77933965Sjdp section, prefer a symbol from this section over symbols from 78033965Sjdp others, even if the other symbol's value might be closer. 78133965Sjdp 78233965Sjdp Note that this may be wrong for some symbol references if the 78333965Sjdp sections have overlapping memory ranges, but in that case there's 78433965Sjdp no way to tell what's desired without looking at the relocation 78533965Sjdp table. */ 78633965Sjdp 78733965Sjdp if (sorted_syms[thisplace]->section != sec 78833965Sjdp && (require_sec 78933965Sjdp || ((abfd->flags & HAS_RELOC) != 0 79033965Sjdp && vma >= bfd_get_section_vma (abfd, sec) 79133965Sjdp && vma < (bfd_get_section_vma (abfd, sec) 79260484Sobrien + bfd_section_size (abfd, sec) / opb)))) 79333965Sjdp { 79433965Sjdp long i; 79533965Sjdp 79633965Sjdp for (i = thisplace + 1; i < sorted_symcount; i++) 79733965Sjdp { 79833965Sjdp if (bfd_asymbol_value (sorted_syms[i]) 79933965Sjdp != bfd_asymbol_value (sorted_syms[thisplace])) 80033965Sjdp break; 80133965Sjdp } 80233965Sjdp --i; 80333965Sjdp for (; i >= 0; i--) 80433965Sjdp { 80533965Sjdp if (sorted_syms[i]->section == sec 80633965Sjdp && (i == 0 80733965Sjdp || sorted_syms[i - 1]->section != sec 80833965Sjdp || (bfd_asymbol_value (sorted_syms[i]) 80933965Sjdp != bfd_asymbol_value (sorted_syms[i - 1])))) 81033965Sjdp { 81133965Sjdp thisplace = i; 81233965Sjdp break; 81333965Sjdp } 81433965Sjdp } 81533965Sjdp 81633965Sjdp if (sorted_syms[thisplace]->section != sec) 81733965Sjdp { 81833965Sjdp /* We didn't find a good symbol with a smaller value. 81933965Sjdp Look for one with a larger value. */ 82033965Sjdp for (i = thisplace + 1; i < sorted_symcount; i++) 82133965Sjdp { 82233965Sjdp if (sorted_syms[i]->section == sec) 82333965Sjdp { 82433965Sjdp thisplace = i; 82533965Sjdp break; 82633965Sjdp } 82733965Sjdp } 82833965Sjdp } 82933965Sjdp 83033965Sjdp if (sorted_syms[thisplace]->section != sec 83133965Sjdp && (require_sec 83233965Sjdp || ((abfd->flags & HAS_RELOC) != 0 83333965Sjdp && vma >= bfd_get_section_vma (abfd, sec) 83433965Sjdp && vma < (bfd_get_section_vma (abfd, sec) 83533965Sjdp + bfd_section_size (abfd, sec))))) 83633965Sjdp { 83733965Sjdp /* There is no suitable symbol. */ 83833965Sjdp return NULL; 83933965Sjdp } 84033965Sjdp } 84133965Sjdp 84233965Sjdp if (place != NULL) 84333965Sjdp *place = thisplace; 84433965Sjdp 84533965Sjdp return sorted_syms[thisplace]; 84633965Sjdp} 84733965Sjdp 84833965Sjdp/* Print an address to INFO symbolically. */ 84933965Sjdp 85033965Sjdpstatic void 85133965Sjdpobjdump_print_addr_with_sym (abfd, sec, sym, vma, info, skip_zeroes) 85233965Sjdp bfd *abfd; 85333965Sjdp asection *sec; 85433965Sjdp asymbol *sym; 85533965Sjdp bfd_vma vma; 85633965Sjdp struct disassemble_info *info; 85733965Sjdp boolean skip_zeroes; 85833965Sjdp{ 85933965Sjdp objdump_print_value (vma, info, skip_zeroes); 86033965Sjdp 86133965Sjdp if (sym == NULL) 86233965Sjdp { 86333965Sjdp bfd_vma secaddr; 86433965Sjdp 86533965Sjdp (*info->fprintf_func) (info->stream, " <%s", 86633965Sjdp bfd_get_section_name (abfd, sec)); 86733965Sjdp secaddr = bfd_get_section_vma (abfd, sec); 86833965Sjdp if (vma < secaddr) 86933965Sjdp { 87038889Sjdp (*info->fprintf_func) (info->stream, "-0x"); 87133965Sjdp objdump_print_value (secaddr - vma, info, true); 87233965Sjdp } 87333965Sjdp else if (vma > secaddr) 87433965Sjdp { 87538889Sjdp (*info->fprintf_func) (info->stream, "+0x"); 87633965Sjdp objdump_print_value (vma - secaddr, info, true); 87733965Sjdp } 87833965Sjdp (*info->fprintf_func) (info->stream, ">"); 87933965Sjdp } 88033965Sjdp else 88133965Sjdp { 88233965Sjdp (*info->fprintf_func) (info->stream, " <"); 88333965Sjdp objdump_print_symname (abfd, info, sym); 88433965Sjdp if (bfd_asymbol_value (sym) > vma) 88533965Sjdp { 88638889Sjdp (*info->fprintf_func) (info->stream, "-0x"); 88733965Sjdp objdump_print_value (bfd_asymbol_value (sym) - vma, info, true); 88833965Sjdp } 88933965Sjdp else if (vma > bfd_asymbol_value (sym)) 89033965Sjdp { 89138889Sjdp (*info->fprintf_func) (info->stream, "+0x"); 89233965Sjdp objdump_print_value (vma - bfd_asymbol_value (sym), info, true); 89333965Sjdp } 89433965Sjdp (*info->fprintf_func) (info->stream, ">"); 89533965Sjdp } 89633965Sjdp} 89733965Sjdp 89833965Sjdp/* Print VMA to INFO, symbolically if possible. If SKIP_ZEROES is 89933965Sjdp true, don't output leading zeroes. */ 90033965Sjdp 90133965Sjdpstatic void 90233965Sjdpobjdump_print_addr (vma, info, skip_zeroes) 90333965Sjdp bfd_vma vma; 90433965Sjdp struct disassemble_info *info; 90533965Sjdp boolean skip_zeroes; 90633965Sjdp{ 90733965Sjdp struct objdump_disasm_info *aux; 90833965Sjdp asymbol *sym; 90933965Sjdp 91033965Sjdp if (sorted_symcount < 1) 91133965Sjdp { 91238889Sjdp (*info->fprintf_func) (info->stream, "0x"); 91333965Sjdp objdump_print_value (vma, info, skip_zeroes); 91433965Sjdp return; 91533965Sjdp } 91633965Sjdp 91733965Sjdp aux = (struct objdump_disasm_info *) info->application_data; 91833965Sjdp sym = find_symbol_for_address (aux->abfd, aux->sec, vma, aux->require_sec, 91933965Sjdp (long *) NULL); 92033965Sjdp objdump_print_addr_with_sym (aux->abfd, aux->sec, sym, vma, info, 92133965Sjdp skip_zeroes); 92233965Sjdp} 92333965Sjdp 92433965Sjdp/* Print VMA to INFO. This function is passed to the disassembler 92533965Sjdp routine. */ 92633965Sjdp 92733965Sjdpstatic void 92833965Sjdpobjdump_print_address (vma, info) 92933965Sjdp bfd_vma vma; 93033965Sjdp struct disassemble_info *info; 93133965Sjdp{ 93233965Sjdp objdump_print_addr (vma, info, ! prefix_addresses); 93333965Sjdp} 93433965Sjdp 93538889Sjdp/* Determine of the given address has a symbol associated with it. */ 93638889Sjdp 93738889Sjdpstatic int 93838889Sjdpobjdump_symbol_at_address (vma, info) 93938889Sjdp bfd_vma vma; 94038889Sjdp struct disassemble_info * info; 94138889Sjdp{ 94238889Sjdp struct objdump_disasm_info * aux; 94338889Sjdp asymbol * sym; 94438889Sjdp 94538889Sjdp /* No symbols - do not bother checking. */ 94638889Sjdp if (sorted_symcount < 1) 94738889Sjdp return 0; 94838889Sjdp 94938889Sjdp aux = (struct objdump_disasm_info *) info->application_data; 95038889Sjdp sym = find_symbol_for_address (aux->abfd, aux->sec, vma, aux->require_sec, 95138889Sjdp (long *) NULL); 95238889Sjdp 95338889Sjdp return (sym != NULL && (bfd_asymbol_value (sym) == vma)); 95438889Sjdp} 95538889Sjdp 95633965Sjdp/* Hold the last function name and the last line number we displayed 95733965Sjdp in a disassembly. */ 95833965Sjdp 95933965Sjdpstatic char *prev_functionname; 96033965Sjdpstatic unsigned int prev_line; 96133965Sjdp 96233965Sjdp/* We keep a list of all files that we have seen when doing a 96333965Sjdp dissassembly with source, so that we know how much of the file to 96433965Sjdp display. This can be important for inlined functions. */ 96533965Sjdp 96633965Sjdpstruct print_file_list 96733965Sjdp{ 96833965Sjdp struct print_file_list *next; 96933965Sjdp char *filename; 97033965Sjdp unsigned int line; 97133965Sjdp FILE *f; 97233965Sjdp}; 97333965Sjdp 97433965Sjdpstatic struct print_file_list *print_files; 97533965Sjdp 97633965Sjdp/* The number of preceding context lines to show when we start 97733965Sjdp displaying a file for the first time. */ 97833965Sjdp 97933965Sjdp#define SHOW_PRECEDING_CONTEXT_LINES (5) 98033965Sjdp 98133965Sjdp/* Skip ahead to a given line in a file, optionally printing each 98233965Sjdp line. */ 98333965Sjdp 98433965Sjdpstatic void 98533965Sjdpskip_to_line PARAMS ((struct print_file_list *, unsigned int, boolean)); 98633965Sjdp 98733965Sjdpstatic void 98833965Sjdpskip_to_line (p, line, show) 98933965Sjdp struct print_file_list *p; 99033965Sjdp unsigned int line; 99133965Sjdp boolean show; 99233965Sjdp{ 99333965Sjdp while (p->line < line) 99433965Sjdp { 99533965Sjdp char buf[100]; 99633965Sjdp 99733965Sjdp if (fgets (buf, sizeof buf, p->f) == NULL) 99833965Sjdp { 99933965Sjdp fclose (p->f); 100033965Sjdp p->f = NULL; 100133965Sjdp break; 100233965Sjdp } 100333965Sjdp 100433965Sjdp if (show) 100533965Sjdp printf ("%s", buf); 100633965Sjdp 100733965Sjdp if (strchr (buf, '\n') != NULL) 100833965Sjdp ++p->line; 100933965Sjdp } 101033965Sjdp} 101133965Sjdp 101233965Sjdp/* Show the line number, or the source line, in a dissassembly 101333965Sjdp listing. */ 101433965Sjdp 101533965Sjdpstatic void 101660484Sobrienshow_line (abfd, section, addr_offset) 101733965Sjdp bfd *abfd; 101833965Sjdp asection *section; 101960484Sobrien bfd_vma addr_offset; 102033965Sjdp{ 102133965Sjdp CONST char *filename; 102233965Sjdp CONST char *functionname; 102333965Sjdp unsigned int line; 102433965Sjdp 102533965Sjdp if (! with_line_numbers && ! with_source_code) 102633965Sjdp return; 102733965Sjdp 102860484Sobrien if (! bfd_find_nearest_line (abfd, section, syms, addr_offset, &filename, 102933965Sjdp &functionname, &line)) 103033965Sjdp return; 103133965Sjdp 103233965Sjdp if (filename != NULL && *filename == '\0') 103333965Sjdp filename = NULL; 103433965Sjdp if (functionname != NULL && *functionname == '\0') 103533965Sjdp functionname = NULL; 103633965Sjdp 103733965Sjdp if (with_line_numbers) 103833965Sjdp { 103933965Sjdp if (functionname != NULL 104033965Sjdp && (prev_functionname == NULL 104133965Sjdp || strcmp (functionname, prev_functionname) != 0)) 104233965Sjdp printf ("%s():\n", functionname); 104333965Sjdp if (line > 0 && line != prev_line) 104433965Sjdp printf ("%s:%u\n", filename == NULL ? "???" : filename, line); 104533965Sjdp } 104633965Sjdp 104733965Sjdp if (with_source_code 104833965Sjdp && filename != NULL 104933965Sjdp && line > 0) 105033965Sjdp { 105133965Sjdp struct print_file_list **pp, *p; 105233965Sjdp 105333965Sjdp for (pp = &print_files; *pp != NULL; pp = &(*pp)->next) 105433965Sjdp if (strcmp ((*pp)->filename, filename) == 0) 105533965Sjdp break; 105633965Sjdp p = *pp; 105733965Sjdp 105833965Sjdp if (p != NULL) 105933965Sjdp { 106033965Sjdp if (p != print_files) 106133965Sjdp { 106233965Sjdp int l; 106333965Sjdp 106433965Sjdp /* We have reencountered a file name which we saw 106533965Sjdp earlier. This implies that either we are dumping out 106633965Sjdp code from an included file, or the same file was 106733965Sjdp linked in more than once. There are two common cases 106833965Sjdp of an included file: inline functions in a header 106933965Sjdp file, and a bison or flex skeleton file. In the 107033965Sjdp former case we want to just start printing (but we 107133965Sjdp back up a few lines to give context); in the latter 107233965Sjdp case we want to continue from where we left off. I 107333965Sjdp can't think of a good way to distinguish the cases, 107433965Sjdp so I used a heuristic based on the file name. */ 107533965Sjdp if (strcmp (p->filename + strlen (p->filename) - 2, ".h") != 0) 107633965Sjdp l = p->line; 107733965Sjdp else 107833965Sjdp { 107933965Sjdp l = line - SHOW_PRECEDING_CONTEXT_LINES; 108060484Sobrien if (l < 0) 108160484Sobrien l = 0; 108233965Sjdp } 108333965Sjdp 108433965Sjdp if (p->f == NULL) 108533965Sjdp { 108633965Sjdp p->f = fopen (p->filename, "r"); 108733965Sjdp p->line = 0; 108833965Sjdp } 108933965Sjdp if (p->f != NULL) 109033965Sjdp skip_to_line (p, l, false); 109133965Sjdp 109233965Sjdp if (print_files->f != NULL) 109333965Sjdp { 109433965Sjdp fclose (print_files->f); 109533965Sjdp print_files->f = NULL; 109633965Sjdp } 109733965Sjdp } 109833965Sjdp 109933965Sjdp if (p->f != NULL) 110033965Sjdp { 110133965Sjdp skip_to_line (p, line, true); 110233965Sjdp *pp = p->next; 110333965Sjdp p->next = print_files; 110433965Sjdp print_files = p; 110533965Sjdp } 110633965Sjdp } 110733965Sjdp else 110833965Sjdp { 110933965Sjdp FILE *f; 111033965Sjdp 111133965Sjdp f = fopen (filename, "r"); 111233965Sjdp if (f != NULL) 111333965Sjdp { 111433965Sjdp int l; 111533965Sjdp 111633965Sjdp p = ((struct print_file_list *) 111733965Sjdp xmalloc (sizeof (struct print_file_list))); 111833965Sjdp p->filename = xmalloc (strlen (filename) + 1); 111933965Sjdp strcpy (p->filename, filename); 112033965Sjdp p->line = 0; 112133965Sjdp p->f = f; 112233965Sjdp 112333965Sjdp if (print_files != NULL && print_files->f != NULL) 112433965Sjdp { 112533965Sjdp fclose (print_files->f); 112633965Sjdp print_files->f = NULL; 112733965Sjdp } 112833965Sjdp p->next = print_files; 112933965Sjdp print_files = p; 113033965Sjdp 113160484Sobrien if (file_start_context) 113260484Sobrien l = 0; 113360484Sobrien else 113460484Sobrien l = line - SHOW_PRECEDING_CONTEXT_LINES; 113560484Sobrien if (l < 0) 113660484Sobrien l = 0; 113733965Sjdp skip_to_line (p, l, false); 113833965Sjdp if (p->f != NULL) 113933965Sjdp skip_to_line (p, line, true); 114033965Sjdp } 114133965Sjdp } 114233965Sjdp } 114333965Sjdp 114433965Sjdp if (functionname != NULL 114533965Sjdp && (prev_functionname == NULL 114633965Sjdp || strcmp (functionname, prev_functionname) != 0)) 114733965Sjdp { 114833965Sjdp if (prev_functionname != NULL) 114933965Sjdp free (prev_functionname); 115033965Sjdp prev_functionname = xmalloc (strlen (functionname) + 1); 115133965Sjdp strcpy (prev_functionname, functionname); 115233965Sjdp } 115333965Sjdp 115433965Sjdp if (line > 0 && line != prev_line) 115533965Sjdp prev_line = line; 115633965Sjdp} 115733965Sjdp 115833965Sjdp/* Pseudo FILE object for strings. */ 115960484Sobrientypedef struct 116060484Sobrien{ 116133965Sjdp char *buffer; 116260484Sobrien size_t size; 116333965Sjdp char *current; 116433965Sjdp} SFILE; 116533965Sjdp 116633965Sjdp/* sprintf to a "stream" */ 116733965Sjdp 116860484Sobrienstatic int 116933965Sjdp#ifdef ANSI_PROTOTYPES 117033965Sjdpobjdump_sprintf (SFILE *f, const char *format, ...) 117133965Sjdp#else 117233965Sjdpobjdump_sprintf (va_alist) 117333965Sjdp va_dcl 117460484Sobrien#endif 117533965Sjdp{ 117660484Sobrien#ifndef ANSI_PROTOTYPES 117733965Sjdp SFILE *f; 117833965Sjdp const char *format; 117960484Sobrien#endif 118060484Sobrien char *buf; 118133965Sjdp va_list args; 118260484Sobrien size_t n; 118333965Sjdp 118460484Sobrien#ifdef ANSI_PROTOTYPES 118560484Sobrien va_start (args, format); 118660484Sobrien#else 118733965Sjdp va_start (args); 118833965Sjdp f = va_arg (args, SFILE *); 118933965Sjdp format = va_arg (args, const char *); 119060484Sobrien#endif 119160484Sobrien 119260484Sobrien vasprintf (&buf, format, args); 119360484Sobrien 119433965Sjdp va_end (args); 119560484Sobrien 119660484Sobrien if (buf == NULL) 119760484Sobrien { 119860484Sobrien fatal (_("Out of virtual memory")); 119960484Sobrien } 120060484Sobrien 120160484Sobrien n = strlen (buf); 120260484Sobrien 120360484Sobrien while ((size_t) ((f->buffer + f->size) - f->current) < n + 1) 120460484Sobrien { 120560484Sobrien size_t curroff; 120660484Sobrien 120760484Sobrien curroff = f->current - f->buffer; 120860484Sobrien f->size *= 2; 120960484Sobrien f->buffer = xrealloc (f->buffer, f->size); 121060484Sobrien f->current = f->buffer + curroff; 121160484Sobrien } 121260484Sobrien 121360484Sobrien memcpy (f->current, buf, n); 121460484Sobrien f->current += n; 121560484Sobrien f->current[0] = '\0'; 121660484Sobrien 121760484Sobrien free (buf); 121860484Sobrien 121933965Sjdp return n; 122033965Sjdp} 122133965Sjdp 122233965Sjdp/* The number of zeroes we want to see before we start skipping them. 122333965Sjdp The number is arbitrarily chosen. */ 122433965Sjdp 122533965Sjdp#define SKIP_ZEROES (8) 122633965Sjdp 122733965Sjdp/* The number of zeroes to skip at the end of a section. If the 122833965Sjdp number of zeroes at the end is between SKIP_ZEROES_AT_END and 122933965Sjdp SKIP_ZEROES, they will be disassembled. If there are fewer than 123033965Sjdp SKIP_ZEROES_AT_END, they will be skipped. This is a heuristic 123133965Sjdp attempt to avoid disassembling zeroes inserted by section 123233965Sjdp alignment. */ 123333965Sjdp 123433965Sjdp#define SKIP_ZEROES_AT_END (3) 123533965Sjdp 123633965Sjdp/* Disassemble some data in memory between given values. */ 123733965Sjdp 123833965Sjdpstatic void 123960484Sobriendisassemble_bytes (info, disassemble_fn, insns, data, 124060484Sobrien start_offset, stop_offset, relppp, 124133965Sjdp relppend) 124233965Sjdp struct disassemble_info *info; 124333965Sjdp disassembler_ftype disassemble_fn; 124433965Sjdp boolean insns; 124533965Sjdp bfd_byte *data; 124660484Sobrien bfd_vma start_offset; 124760484Sobrien bfd_vma stop_offset; 124833965Sjdp arelent ***relppp; 124933965Sjdp arelent **relppend; 125033965Sjdp{ 125133965Sjdp struct objdump_disasm_info *aux; 125233965Sjdp asection *section; 125360484Sobrien int octets_per_line; 125433965Sjdp boolean done_dot; 125533965Sjdp int skip_addr_chars; 125660484Sobrien bfd_vma addr_offset; 125760484Sobrien int opb = info->octets_per_byte; 125833965Sjdp 125933965Sjdp aux = (struct objdump_disasm_info *) info->application_data; 126033965Sjdp section = aux->sec; 126133965Sjdp 126233965Sjdp if (insns) 126360484Sobrien octets_per_line = 4; 126433965Sjdp else 126560484Sobrien octets_per_line = 16; 126633965Sjdp 126733965Sjdp /* Figure out how many characters to skip at the start of an 126833965Sjdp address, to make the disassembly look nicer. We discard leading 126933965Sjdp zeroes in chunks of 4, ensuring that there is always a leading 127033965Sjdp zero remaining. */ 127133965Sjdp skip_addr_chars = 0; 127233965Sjdp if (! prefix_addresses) 127333965Sjdp { 127433965Sjdp char buf[30]; 127533965Sjdp char *s; 127633965Sjdp 127760484Sobrien sprintf_vma (buf, section->vma + 127860484Sobrien bfd_section_size (section->owner, section) / opb); 127933965Sjdp s = buf; 128033965Sjdp while (s[0] == '0' && s[1] == '0' && s[2] == '0' && s[3] == '0' 128133965Sjdp && s[4] == '0') 128233965Sjdp { 128333965Sjdp skip_addr_chars += 4; 128433965Sjdp s += 4; 128533965Sjdp } 128633965Sjdp } 128733965Sjdp 128833965Sjdp info->insn_info_valid = 0; 128933965Sjdp 129033965Sjdp done_dot = false; 129160484Sobrien addr_offset = start_offset; 129260484Sobrien while (addr_offset < stop_offset) 129333965Sjdp { 129460484Sobrien bfd_vma z; 129560484Sobrien int octets = 0; 129633965Sjdp boolean need_nl = false; 129733965Sjdp 129860484Sobrien /* If we see more than SKIP_ZEROES octets of zeroes, we just 129933965Sjdp print `...'. */ 130060484Sobrien for (z = addr_offset * opb; z < stop_offset * opb; z++) 130133965Sjdp if (data[z] != 0) 130233965Sjdp break; 130333965Sjdp if (! disassemble_zeroes 130433965Sjdp && (info->insn_info_valid == 0 130533965Sjdp || info->branch_delay_insns == 0) 130660484Sobrien && (z - addr_offset * opb >= SKIP_ZEROES 130760484Sobrien || (z == stop_offset * opb && 130860484Sobrien z - addr_offset * opb < SKIP_ZEROES_AT_END))) 130933965Sjdp { 131033965Sjdp printf ("\t...\n"); 131133965Sjdp 131260484Sobrien /* If there are more nonzero octets to follow, we only skip 131333965Sjdp zeroes in multiples of 4, to try to avoid running over 131433965Sjdp the start of an instruction which happens to start with 131533965Sjdp zero. */ 131660484Sobrien if (z != stop_offset * opb) 131760484Sobrien z = addr_offset * opb + ((z - addr_offset * opb) &~ 3); 131833965Sjdp 131960484Sobrien octets = z - addr_offset * opb; 132033965Sjdp } 132133965Sjdp else 132233965Sjdp { 132360484Sobrien char buf[50]; 132433965Sjdp SFILE sfile; 132538889Sjdp int bpc = 0; 132638889Sjdp int pb = 0; 132733965Sjdp 132833965Sjdp done_dot = false; 132933965Sjdp 133033965Sjdp if (with_line_numbers || with_source_code) 133160484Sobrien show_line (aux->abfd, section, addr_offset); 133233965Sjdp 133333965Sjdp if (! prefix_addresses) 133433965Sjdp { 133533965Sjdp char *s; 133633965Sjdp 133760484Sobrien sprintf_vma (buf, section->vma + addr_offset); 133833965Sjdp for (s = buf + skip_addr_chars; *s == '0'; s++) 133933965Sjdp *s = ' '; 134033965Sjdp if (*s == '\0') 134133965Sjdp *--s = '0'; 134233965Sjdp printf ("%s:\t", buf + skip_addr_chars); 134333965Sjdp } 134433965Sjdp else 134533965Sjdp { 134633965Sjdp aux->require_sec = true; 134760484Sobrien objdump_print_address (section->vma + addr_offset, info); 134833965Sjdp aux->require_sec = false; 134933965Sjdp putchar (' '); 135033965Sjdp } 135133965Sjdp 135233965Sjdp if (insns) 135333965Sjdp { 135460484Sobrien sfile.size = 120; 135560484Sobrien sfile.buffer = xmalloc (sfile.size); 135660484Sobrien sfile.current = sfile.buffer; 135733965Sjdp info->fprintf_func = (fprintf_ftype) objdump_sprintf; 135833965Sjdp info->stream = (FILE *) &sfile; 135933965Sjdp info->bytes_per_line = 0; 136033965Sjdp info->bytes_per_chunk = 0; 136160484Sobrien 136260484Sobrien /* FIXME: This is wrong. It tests the number of octets 136360484Sobrien in the last instruction, not the current one. */ 136460484Sobrien if (*relppp < relppend 136560484Sobrien && (**relppp)->address >= addr_offset 136660484Sobrien && (**relppp)->address < addr_offset + octets / opb) 136738889Sjdp info->flags = INSN_HAS_RELOC; 136838889Sjdp else 136938889Sjdp info->flags = 0; 137060484Sobrien 137160484Sobrien octets = (*disassemble_fn) (section->vma + addr_offset, info); 137233965Sjdp info->fprintf_func = (fprintf_ftype) fprintf; 137333965Sjdp info->stream = stdout; 137433965Sjdp if (info->bytes_per_line != 0) 137560484Sobrien octets_per_line = info->bytes_per_line; 137660484Sobrien if (octets < 0) 137760484Sobrien { 137860484Sobrien if (sfile.current != sfile.buffer) 137960484Sobrien printf ("%s\n", sfile.buffer); 138060484Sobrien free (sfile.buffer); 138160484Sobrien break; 138260484Sobrien } 138333965Sjdp } 138433965Sjdp else 138533965Sjdp { 138660484Sobrien bfd_vma j; 138733965Sjdp 138860484Sobrien octets = octets_per_line; 138960484Sobrien if (addr_offset + octets / opb > stop_offset) 139060484Sobrien octets = (stop_offset - addr_offset) * opb; 139133965Sjdp 139260484Sobrien for (j = addr_offset * opb; j < addr_offset * opb + octets; ++j) 139333965Sjdp { 139433965Sjdp if (isprint (data[j])) 139560484Sobrien buf[j - addr_offset * opb] = data[j]; 139633965Sjdp else 139760484Sobrien buf[j - addr_offset * opb] = '.'; 139833965Sjdp } 139960484Sobrien buf[j - addr_offset * opb] = '\0'; 140033965Sjdp } 140133965Sjdp 140233965Sjdp if (prefix_addresses 140333965Sjdp ? show_raw_insn > 0 140433965Sjdp : show_raw_insn >= 0) 140533965Sjdp { 140660484Sobrien bfd_vma j; 140733965Sjdp 140833965Sjdp /* If ! prefix_addresses and ! wide_output, we print 140960484Sobrien octets_per_line octets per line. */ 141060484Sobrien pb = octets; 141160484Sobrien if (pb > octets_per_line && ! prefix_addresses && ! wide_output) 141260484Sobrien pb = octets_per_line; 141333965Sjdp 141433965Sjdp if (info->bytes_per_chunk) 141533965Sjdp bpc = info->bytes_per_chunk; 141633965Sjdp else 141733965Sjdp bpc = 1; 141833965Sjdp 141960484Sobrien for (j = addr_offset * opb; j < addr_offset * opb + pb; j += bpc) 142033965Sjdp { 142133965Sjdp int k; 142233965Sjdp if (bpc > 1 && info->display_endian == BFD_ENDIAN_LITTLE) 142333965Sjdp { 142433965Sjdp for (k = bpc - 1; k >= 0; k--) 142533965Sjdp printf ("%02x", (unsigned) data[j + k]); 142633965Sjdp putchar (' '); 142733965Sjdp } 142833965Sjdp else 142933965Sjdp { 143033965Sjdp for (k = 0; k < bpc; k++) 143133965Sjdp printf ("%02x", (unsigned) data[j + k]); 143233965Sjdp putchar (' '); 143333965Sjdp } 143433965Sjdp } 143533965Sjdp 143660484Sobrien for (; pb < octets_per_line; pb += bpc) 143733965Sjdp { 143833965Sjdp int k; 143933965Sjdp 144033965Sjdp for (k = 0; k < bpc; k++) 144133965Sjdp printf (" "); 144233965Sjdp putchar (' '); 144333965Sjdp } 144433965Sjdp 144533965Sjdp /* Separate raw data from instruction by extra space. */ 144633965Sjdp if (insns) 144733965Sjdp putchar ('\t'); 144833965Sjdp else 144933965Sjdp printf (" "); 145033965Sjdp } 145133965Sjdp 145260484Sobrien if (! insns) 145360484Sobrien printf ("%s", buf); 145460484Sobrien else 145560484Sobrien { 145660484Sobrien printf ("%s", sfile.buffer); 145760484Sobrien free (sfile.buffer); 145860484Sobrien } 145933965Sjdp 146033965Sjdp if (prefix_addresses 146133965Sjdp ? show_raw_insn > 0 146233965Sjdp : show_raw_insn >= 0) 146333965Sjdp { 146460484Sobrien while (pb < octets) 146533965Sjdp { 146660484Sobrien bfd_vma j; 146733965Sjdp char *s; 146833965Sjdp 146933965Sjdp putchar ('\n'); 147060484Sobrien j = addr_offset * opb + pb; 147133965Sjdp 147260484Sobrien sprintf_vma (buf, section->vma + j / opb); 147333965Sjdp for (s = buf + skip_addr_chars; *s == '0'; s++) 147433965Sjdp *s = ' '; 147533965Sjdp if (*s == '\0') 147633965Sjdp *--s = '0'; 147733965Sjdp printf ("%s:\t", buf + skip_addr_chars); 147833965Sjdp 147960484Sobrien pb += octets_per_line; 148060484Sobrien if (pb > octets) 148160484Sobrien pb = octets; 148260484Sobrien for (; j < addr_offset * opb + pb; j += bpc) 148333965Sjdp { 148433965Sjdp int k; 148533965Sjdp 148633965Sjdp if (bpc > 1 && info->display_endian == BFD_ENDIAN_LITTLE) 148733965Sjdp { 148833965Sjdp for (k = bpc - 1; k >= 0; k--) 148933965Sjdp printf ("%02x", (unsigned) data[j + k]); 149033965Sjdp putchar (' '); 149133965Sjdp } 149233965Sjdp else 149333965Sjdp { 149433965Sjdp for (k = 0; k < bpc; k++) 149533965Sjdp printf ("%02x", (unsigned) data[j + k]); 149633965Sjdp putchar (' '); 149733965Sjdp } 149833965Sjdp } 149933965Sjdp } 150033965Sjdp } 150133965Sjdp 150233965Sjdp if (!wide_output) 150333965Sjdp putchar ('\n'); 150433965Sjdp else 150533965Sjdp need_nl = true; 150633965Sjdp } 150733965Sjdp 150833965Sjdp if (dump_reloc_info 150933965Sjdp && (section->flags & SEC_RELOC) != 0) 151033965Sjdp { 151133965Sjdp while ((*relppp) < relppend 151260484Sobrien && ((**relppp)->address >= (bfd_vma) addr_offset 151360484Sobrien && (**relppp)->address < (bfd_vma) addr_offset + octets / opb)) 151433965Sjdp { 151533965Sjdp arelent *q; 151633965Sjdp 151733965Sjdp q = **relppp; 151833965Sjdp 151933965Sjdp if (wide_output) 152033965Sjdp putchar ('\t'); 152133965Sjdp else 152233965Sjdp printf ("\t\t\t"); 152333965Sjdp 152433965Sjdp objdump_print_value (section->vma + q->address, info, true); 152533965Sjdp 152633965Sjdp printf (": %s\t", q->howto->name); 152733965Sjdp 152833965Sjdp if (q->sym_ptr_ptr == NULL || *q->sym_ptr_ptr == NULL) 152933965Sjdp printf ("*unknown*"); 153033965Sjdp else 153133965Sjdp { 153233965Sjdp const char *sym_name; 153333965Sjdp 153433965Sjdp sym_name = bfd_asymbol_name (*q->sym_ptr_ptr); 153533965Sjdp if (sym_name != NULL && *sym_name != '\0') 153633965Sjdp objdump_print_symname (aux->abfd, info, *q->sym_ptr_ptr); 153733965Sjdp else 153833965Sjdp { 153933965Sjdp asection *sym_sec; 154033965Sjdp 154133965Sjdp sym_sec = bfd_get_section (*q->sym_ptr_ptr); 154233965Sjdp sym_name = bfd_get_section_name (aux->abfd, sym_sec); 154333965Sjdp if (sym_name == NULL || *sym_name == '\0') 154433965Sjdp sym_name = "*unknown*"; 154533965Sjdp printf ("%s", sym_name); 154633965Sjdp } 154733965Sjdp } 154833965Sjdp 154933965Sjdp if (q->addend) 155033965Sjdp { 155133965Sjdp printf ("+0x"); 155233965Sjdp objdump_print_value (q->addend, info, true); 155333965Sjdp } 155433965Sjdp 155533965Sjdp printf ("\n"); 155633965Sjdp need_nl = false; 155733965Sjdp ++(*relppp); 155833965Sjdp } 155933965Sjdp } 156033965Sjdp 156133965Sjdp if (need_nl) 156233965Sjdp printf ("\n"); 156333965Sjdp 156460484Sobrien addr_offset += octets / opb; 156533965Sjdp } 156633965Sjdp} 156733965Sjdp 156833965Sjdp/* Disassemble the contents of an object file. */ 156933965Sjdp 157033965Sjdpstatic void 157133965Sjdpdisassemble_data (abfd) 157233965Sjdp bfd *abfd; 157333965Sjdp{ 157460484Sobrien unsigned long addr_offset; 157533965Sjdp disassembler_ftype disassemble_fn; 157633965Sjdp struct disassemble_info disasm_info; 157733965Sjdp struct objdump_disasm_info aux; 157833965Sjdp asection *section; 157960484Sobrien unsigned int opb; 158033965Sjdp 158133965Sjdp print_files = NULL; 158233965Sjdp prev_functionname = NULL; 158333965Sjdp prev_line = -1; 158433965Sjdp 158533965Sjdp /* We make a copy of syms to sort. We don't want to sort syms 158633965Sjdp because that will screw up the relocs. */ 158733965Sjdp sorted_syms = (asymbol **) xmalloc (symcount * sizeof (asymbol *)); 158833965Sjdp memcpy (sorted_syms, syms, symcount * sizeof (asymbol *)); 158933965Sjdp 159033965Sjdp sorted_symcount = remove_useless_symbols (sorted_syms, symcount); 159133965Sjdp 159233965Sjdp /* Sort the symbols into section and symbol order */ 159333965Sjdp qsort (sorted_syms, sorted_symcount, sizeof (asymbol *), compare_symbols); 159433965Sjdp 159533965Sjdp INIT_DISASSEMBLE_INFO(disasm_info, stdout, fprintf); 159633965Sjdp disasm_info.application_data = (PTR) &aux; 159733965Sjdp aux.abfd = abfd; 159833965Sjdp aux.require_sec = false; 159933965Sjdp disasm_info.print_address_func = objdump_print_address; 160038889Sjdp disasm_info.symbol_at_address_func = objdump_symbol_at_address; 160133965Sjdp 160233965Sjdp if (machine != (char *) NULL) 160333965Sjdp { 160433965Sjdp const bfd_arch_info_type *info = bfd_scan_arch (machine); 160533965Sjdp if (info == NULL) 160633965Sjdp { 160760484Sobrien fatal (_("Can't use supplied machine %s"), machine); 160833965Sjdp } 160933965Sjdp abfd->arch_info = info; 161033965Sjdp } 161133965Sjdp 161233965Sjdp if (endian != BFD_ENDIAN_UNKNOWN) 161333965Sjdp { 161433965Sjdp struct bfd_target *xvec; 161533965Sjdp 161633965Sjdp xvec = (struct bfd_target *) xmalloc (sizeof (struct bfd_target)); 161733965Sjdp memcpy (xvec, abfd->xvec, sizeof (struct bfd_target)); 161833965Sjdp xvec->byteorder = endian; 161933965Sjdp abfd->xvec = xvec; 162033965Sjdp } 162133965Sjdp 162233965Sjdp disassemble_fn = disassembler (abfd); 162333965Sjdp if (!disassemble_fn) 162433965Sjdp { 162560484Sobrien non_fatal (_("Can't disassemble for architecture %s\n"), 162660484Sobrien bfd_printable_arch_mach (bfd_get_arch (abfd), 0)); 162760484Sobrien exit_status = 1; 162833965Sjdp return; 162933965Sjdp } 163033965Sjdp 163160484Sobrien opb = bfd_octets_per_byte (abfd); 163260484Sobrien 163333965Sjdp disasm_info.flavour = bfd_get_flavour (abfd); 163433965Sjdp disasm_info.arch = bfd_get_arch (abfd); 163533965Sjdp disasm_info.mach = bfd_get_mach (abfd); 163660484Sobrien disasm_info.disassembler_options = disassembler_options; 163760484Sobrien disasm_info.octets_per_byte = opb; 163860484Sobrien 163933965Sjdp if (bfd_big_endian (abfd)) 164060484Sobrien disasm_info.display_endian = disasm_info.endian = BFD_ENDIAN_BIG; 164133965Sjdp else if (bfd_little_endian (abfd)) 164260484Sobrien disasm_info.display_endian = disasm_info.endian = BFD_ENDIAN_LITTLE; 164333965Sjdp else 164433965Sjdp /* ??? Aborting here seems too drastic. We could default to big or little 164533965Sjdp instead. */ 164633965Sjdp disasm_info.endian = BFD_ENDIAN_UNKNOWN; 164733965Sjdp 164833965Sjdp for (section = abfd->sections; 164933965Sjdp section != (asection *) NULL; 165033965Sjdp section = section->next) 165133965Sjdp { 165233965Sjdp bfd_byte *data = NULL; 165333965Sjdp bfd_size_type datasize = 0; 165433965Sjdp arelent **relbuf = NULL; 165533965Sjdp arelent **relpp = NULL; 165633965Sjdp arelent **relppend = NULL; 165760484Sobrien unsigned long stop_offset; 165838889Sjdp asymbol *sym = NULL; 165938889Sjdp long place = 0; 166033965Sjdp 166133965Sjdp if ((section->flags & SEC_LOAD) == 0 166233965Sjdp || (! disassemble_all 166333965Sjdp && only == NULL 166433965Sjdp && (section->flags & SEC_CODE) == 0)) 166533965Sjdp continue; 166633965Sjdp if (only != (char *) NULL && strcmp (only, section->name) != 0) 166733965Sjdp continue; 166833965Sjdp 166933965Sjdp if (dump_reloc_info 167033965Sjdp && (section->flags & SEC_RELOC) != 0) 167133965Sjdp { 167233965Sjdp long relsize; 167333965Sjdp 167433965Sjdp relsize = bfd_get_reloc_upper_bound (abfd, section); 167533965Sjdp if (relsize < 0) 167633965Sjdp bfd_fatal (bfd_get_filename (abfd)); 167733965Sjdp 167833965Sjdp if (relsize > 0) 167933965Sjdp { 168033965Sjdp long relcount; 168133965Sjdp 168233965Sjdp relbuf = (arelent **) xmalloc (relsize); 168333965Sjdp relcount = bfd_canonicalize_reloc (abfd, section, relbuf, syms); 168433965Sjdp if (relcount < 0) 168533965Sjdp bfd_fatal (bfd_get_filename (abfd)); 168633965Sjdp 168733965Sjdp /* Sort the relocs by address. */ 168833965Sjdp qsort (relbuf, relcount, sizeof (arelent *), compare_relocs); 168933965Sjdp 169033965Sjdp relpp = relbuf; 169133965Sjdp relppend = relpp + relcount; 169260484Sobrien 169360484Sobrien /* Skip over the relocs belonging to addresses below the 169460484Sobrien start address. */ 169560484Sobrien if (start_address != (bfd_vma) -1) 169660484Sobrien { 169760484Sobrien while (relpp < relppend 169860484Sobrien && (*relpp)->address < start_address) 169960484Sobrien ++relpp; 170060484Sobrien } 170133965Sjdp } 170233965Sjdp } 170333965Sjdp 170460484Sobrien printf (_("Disassembly of section %s:\n"), section->name); 170533965Sjdp 170633965Sjdp datasize = bfd_get_section_size_before_reloc (section); 170733965Sjdp if (datasize == 0) 170833965Sjdp continue; 170933965Sjdp 171033965Sjdp data = (bfd_byte *) xmalloc ((size_t) datasize); 171133965Sjdp 171233965Sjdp bfd_get_section_contents (abfd, section, data, 0, datasize); 171333965Sjdp 171433965Sjdp aux.sec = section; 171533965Sjdp disasm_info.buffer = data; 171633965Sjdp disasm_info.buffer_vma = section->vma; 171733965Sjdp disasm_info.buffer_length = datasize; 171833965Sjdp if (start_address == (bfd_vma) -1 171933965Sjdp || start_address < disasm_info.buffer_vma) 172060484Sobrien addr_offset = 0; 172133965Sjdp else 172260484Sobrien addr_offset = start_address - disasm_info.buffer_vma; 172333965Sjdp if (stop_address == (bfd_vma) -1) 172460484Sobrien stop_offset = datasize / opb; 172533965Sjdp else 172633965Sjdp { 172733965Sjdp if (stop_address < disasm_info.buffer_vma) 172860484Sobrien stop_offset = 0; 172933965Sjdp else 173060484Sobrien stop_offset = stop_address - disasm_info.buffer_vma; 173160484Sobrien if (stop_offset > disasm_info.buffer_length / opb) 173260484Sobrien stop_offset = disasm_info.buffer_length / opb; 173333965Sjdp } 173433965Sjdp 173560484Sobrien sym = find_symbol_for_address (abfd, section, section->vma + addr_offset, 173638889Sjdp true, &place); 173738889Sjdp 173860484Sobrien while (addr_offset < stop_offset) 173933965Sjdp { 174038889Sjdp asymbol *nextsym; 174160484Sobrien unsigned long nextstop_offset; 174238889Sjdp boolean insns; 174338889Sjdp 174460484Sobrien if (sym != NULL && bfd_asymbol_value (sym) <= section->vma + addr_offset) 174533965Sjdp { 174638889Sjdp int x; 174733965Sjdp 174838889Sjdp for (x = place; 174938889Sjdp (x < sorted_symcount 175060484Sobrien && bfd_asymbol_value (sorted_syms[x]) <= section->vma + addr_offset); 175138889Sjdp ++x) 175238889Sjdp continue; 175338889Sjdp disasm_info.symbols = & sorted_syms[place]; 175438889Sjdp disasm_info.num_symbols = x - place; 175538889Sjdp } 175638889Sjdp else 175738889Sjdp disasm_info.symbols = NULL; 175833965Sjdp 175938889Sjdp if (! prefix_addresses) 176038889Sjdp { 176133965Sjdp printf ("\n"); 176233965Sjdp objdump_print_addr_with_sym (abfd, section, sym, 176360484Sobrien section->vma + addr_offset, 176433965Sjdp &disasm_info, 176533965Sjdp false); 176633965Sjdp printf (":\n"); 176738889Sjdp } 176838889Sjdp 176960484Sobrien if (sym != NULL && bfd_asymbol_value (sym) > section->vma + addr_offset) 177038889Sjdp nextsym = sym; 177138889Sjdp else if (sym == NULL) 177238889Sjdp nextsym = NULL; 177338889Sjdp else 177438889Sjdp { 177560484Sobrien /* Search forward for the next appropriate symbol in 177660484Sobrien SECTION. Note that all the symbols are sorted 177760484Sobrien together into one big array, and that some sections 177860484Sobrien may have overlapping addresses. */ 177938889Sjdp while (place < sorted_symcount 178038889Sjdp && (sorted_syms[place]->section != section 178138889Sjdp || (bfd_asymbol_value (sorted_syms[place]) 178238889Sjdp <= bfd_asymbol_value (sym)))) 178338889Sjdp ++place; 178438889Sjdp if (place >= sorted_symcount) 178533965Sjdp nextsym = NULL; 178633965Sjdp else 178738889Sjdp nextsym = sorted_syms[place]; 178838889Sjdp } 178938889Sjdp 179060484Sobrien if (sym != NULL && bfd_asymbol_value (sym) > section->vma + addr_offset) 179138889Sjdp { 179260484Sobrien nextstop_offset = bfd_asymbol_value (sym) - section->vma; 179360484Sobrien if (nextstop_offset > stop_offset) 179460484Sobrien nextstop_offset = stop_offset; 179533965Sjdp } 179638889Sjdp else if (nextsym == NULL) 179760484Sobrien nextstop_offset = stop_offset; 179838889Sjdp else 179938889Sjdp { 180060484Sobrien nextstop_offset = bfd_asymbol_value (nextsym) - section->vma; 180160484Sobrien if (nextstop_offset > stop_offset) 180260484Sobrien nextstop_offset = stop_offset; 180338889Sjdp } 180438889Sjdp 180538889Sjdp /* If a symbol is explicitly marked as being an object 180638889Sjdp rather than a function, just dump the bytes without 180738889Sjdp disassembling them. */ 180838889Sjdp if (disassemble_all 180938889Sjdp || sym == NULL 181060484Sobrien || bfd_asymbol_value (sym) > section->vma + addr_offset 181138889Sjdp || ((sym->flags & BSF_OBJECT) == 0 181238889Sjdp && (strstr (bfd_asymbol_name (sym), "gnu_compiled") 181338889Sjdp == NULL) 181438889Sjdp && (strstr (bfd_asymbol_name (sym), "gcc2_compiled") 181538889Sjdp == NULL)) 181638889Sjdp || (sym->flags & BSF_FUNCTION) != 0) 181738889Sjdp insns = true; 181838889Sjdp else 181938889Sjdp insns = false; 182038889Sjdp 182160484Sobrien disassemble_bytes (&disasm_info, disassemble_fn, insns, data, 182260484Sobrien addr_offset, nextstop_offset, &relpp, relppend); 182338889Sjdp 182460484Sobrien addr_offset = nextstop_offset; 182538889Sjdp sym = nextsym; 182633965Sjdp } 182738889Sjdp 182833965Sjdp free (data); 182933965Sjdp if (relbuf != NULL) 183033965Sjdp free (relbuf); 183133965Sjdp } 183233965Sjdp free (sorted_syms); 183333965Sjdp} 183433965Sjdp 183533965Sjdp 183633965Sjdp/* Define a table of stab values and print-strings. We wish the initializer 183733965Sjdp could be a direct-mapped table, but instead we build one the first 183833965Sjdp time we need it. */ 183933965Sjdp 184033965Sjdpstatic void dump_section_stabs PARAMS ((bfd *abfd, char *stabsect_name, 184133965Sjdp char *strsect_name)); 184233965Sjdp 184333965Sjdp/* Dump the stabs sections from an object file that has a section that 184433965Sjdp uses Sun stabs encoding. */ 184533965Sjdp 184633965Sjdpstatic void 184733965Sjdpdump_stabs (abfd) 184833965Sjdp bfd *abfd; 184933965Sjdp{ 185033965Sjdp dump_section_stabs (abfd, ".stab", ".stabstr"); 185133965Sjdp dump_section_stabs (abfd, ".stab.excl", ".stab.exclstr"); 185233965Sjdp dump_section_stabs (abfd, ".stab.index", ".stab.indexstr"); 185333965Sjdp dump_section_stabs (abfd, "$GDB_SYMBOLS$", "$GDB_STRINGS$"); 185433965Sjdp} 185533965Sjdp 185633965Sjdpstatic bfd_byte *stabs; 185733965Sjdpstatic bfd_size_type stab_size; 185833965Sjdp 185933965Sjdpstatic char *strtab; 186033965Sjdpstatic bfd_size_type stabstr_size; 186133965Sjdp 186233965Sjdp/* Read ABFD's stabs section STABSECT_NAME into `stabs' 186333965Sjdp and string table section STRSECT_NAME into `strtab'. 186433965Sjdp If the section exists and was read, allocate the space and return true. 186533965Sjdp Otherwise return false. */ 186633965Sjdp 186733965Sjdpstatic boolean 186833965Sjdpread_section_stabs (abfd, stabsect_name, strsect_name) 186933965Sjdp bfd *abfd; 187033965Sjdp const char *stabsect_name; 187133965Sjdp const char *strsect_name; 187233965Sjdp{ 187333965Sjdp asection *stabsect, *stabstrsect; 187433965Sjdp 187533965Sjdp stabsect = bfd_get_section_by_name (abfd, stabsect_name); 187633965Sjdp if (0 == stabsect) 187733965Sjdp { 187860484Sobrien printf (_("No %s section present\n\n"), stabsect_name); 187933965Sjdp return false; 188033965Sjdp } 188133965Sjdp 188233965Sjdp stabstrsect = bfd_get_section_by_name (abfd, strsect_name); 188333965Sjdp if (0 == stabstrsect) 188433965Sjdp { 188560484Sobrien non_fatal (_("%s has no %s section"), 188660484Sobrien bfd_get_filename (abfd), strsect_name); 188760484Sobrien exit_status = 1; 188833965Sjdp return false; 188933965Sjdp } 189033965Sjdp 189133965Sjdp stab_size = bfd_section_size (abfd, stabsect); 189233965Sjdp stabstr_size = bfd_section_size (abfd, stabstrsect); 189333965Sjdp 189433965Sjdp stabs = (bfd_byte *) xmalloc (stab_size); 189533965Sjdp strtab = (char *) xmalloc (stabstr_size); 189633965Sjdp 189733965Sjdp if (! bfd_get_section_contents (abfd, stabsect, (PTR) stabs, 0, stab_size)) 189833965Sjdp { 189960484Sobrien non_fatal (_("Reading %s section of %s failed: %s"), 190060484Sobrien stabsect_name, bfd_get_filename (abfd), 190160484Sobrien bfd_errmsg (bfd_get_error ())); 190233965Sjdp free (stabs); 190333965Sjdp free (strtab); 190460484Sobrien exit_status = 1; 190533965Sjdp return false; 190633965Sjdp } 190733965Sjdp 190833965Sjdp if (! bfd_get_section_contents (abfd, stabstrsect, (PTR) strtab, 0, 190933965Sjdp stabstr_size)) 191033965Sjdp { 191160484Sobrien non_fatal (_("Reading %s section of %s failed: %s\n"), 191260484Sobrien strsect_name, bfd_get_filename (abfd), 191360484Sobrien bfd_errmsg (bfd_get_error ())); 191433965Sjdp free (stabs); 191533965Sjdp free (strtab); 191660484Sobrien exit_status = 1; 191733965Sjdp return false; 191833965Sjdp } 191933965Sjdp 192033965Sjdp return true; 192133965Sjdp} 192233965Sjdp 192333965Sjdp/* Stabs entries use a 12 byte format: 192433965Sjdp 4 byte string table index 192533965Sjdp 1 byte stab type 192633965Sjdp 1 byte stab other field 192733965Sjdp 2 byte stab desc field 192833965Sjdp 4 byte stab value 192933965Sjdp FIXME: This will have to change for a 64 bit object format. */ 193033965Sjdp 193133965Sjdp#define STRDXOFF (0) 193233965Sjdp#define TYPEOFF (4) 193333965Sjdp#define OTHEROFF (5) 193433965Sjdp#define DESCOFF (6) 193533965Sjdp#define VALOFF (8) 193633965Sjdp#define STABSIZE (12) 193733965Sjdp 193833965Sjdp/* Print ABFD's stabs section STABSECT_NAME (in `stabs'), 193933965Sjdp using string table section STRSECT_NAME (in `strtab'). */ 194033965Sjdp 194133965Sjdpstatic void 194233965Sjdpprint_section_stabs (abfd, stabsect_name, strsect_name) 194333965Sjdp bfd *abfd; 194433965Sjdp const char *stabsect_name; 194560484Sobrien const char *strsect_name ATTRIBUTE_UNUSED; 194633965Sjdp{ 194733965Sjdp int i; 194833965Sjdp unsigned file_string_table_offset = 0, next_file_string_table_offset = 0; 194933965Sjdp bfd_byte *stabp, *stabs_end; 195033965Sjdp 195133965Sjdp stabp = stabs; 195233965Sjdp stabs_end = stabp + stab_size; 195333965Sjdp 195460484Sobrien printf (_("Contents of %s section:\n\n"), stabsect_name); 195533965Sjdp printf ("Symnum n_type n_othr n_desc n_value n_strx String\n"); 195633965Sjdp 195733965Sjdp /* Loop through all symbols and print them. 195833965Sjdp 195933965Sjdp We start the index at -1 because there is a dummy symbol on 196033965Sjdp the front of stabs-in-{coff,elf} sections that supplies sizes. */ 196133965Sjdp 196233965Sjdp for (i = -1; stabp < stabs_end; stabp += STABSIZE, i++) 196333965Sjdp { 196433965Sjdp const char *name; 196533965Sjdp unsigned long strx; 196633965Sjdp unsigned char type, other; 196733965Sjdp unsigned short desc; 196833965Sjdp bfd_vma value; 196933965Sjdp 197033965Sjdp strx = bfd_h_get_32 (abfd, stabp + STRDXOFF); 197133965Sjdp type = bfd_h_get_8 (abfd, stabp + TYPEOFF); 197233965Sjdp other = bfd_h_get_8 (abfd, stabp + OTHEROFF); 197333965Sjdp desc = bfd_h_get_16 (abfd, stabp + DESCOFF); 197433965Sjdp value = bfd_h_get_32 (abfd, stabp + VALOFF); 197533965Sjdp 197633965Sjdp printf ("\n%-6d ", i); 197733965Sjdp /* Either print the stab name, or, if unnamed, print its number 197833965Sjdp again (makes consistent formatting for tools like awk). */ 197933965Sjdp name = bfd_get_stab_name (type); 198033965Sjdp if (name != NULL) 198133965Sjdp printf ("%-6s", name); 198233965Sjdp else if (type == N_UNDF) 198333965Sjdp printf ("HdrSym"); 198433965Sjdp else 198533965Sjdp printf ("%-6d", type); 198633965Sjdp printf (" %-6d %-6d ", other, desc); 198733965Sjdp printf_vma (value); 198833965Sjdp printf (" %-6lu", strx); 198933965Sjdp 199033965Sjdp /* Symbols with type == 0 (N_UNDF) specify the length of the 199133965Sjdp string table associated with this file. We use that info 199233965Sjdp to know how to relocate the *next* file's string table indices. */ 199333965Sjdp 199433965Sjdp if (type == N_UNDF) 199533965Sjdp { 199633965Sjdp file_string_table_offset = next_file_string_table_offset; 199733965Sjdp next_file_string_table_offset += value; 199833965Sjdp } 199933965Sjdp else 200033965Sjdp { 200133965Sjdp /* Using the (possibly updated) string table offset, print the 200233965Sjdp string (if any) associated with this symbol. */ 200333965Sjdp 200433965Sjdp if ((strx + file_string_table_offset) < stabstr_size) 200533965Sjdp printf (" %s", &strtab[strx + file_string_table_offset]); 200633965Sjdp else 200733965Sjdp printf (" *"); 200833965Sjdp } 200933965Sjdp } 201033965Sjdp printf ("\n\n"); 201133965Sjdp} 201233965Sjdp 201333965Sjdpstatic void 201433965Sjdpdump_section_stabs (abfd, stabsect_name, strsect_name) 201533965Sjdp bfd *abfd; 201633965Sjdp char *stabsect_name; 201733965Sjdp char *strsect_name; 201833965Sjdp{ 201933965Sjdp asection *s; 202033965Sjdp 202133965Sjdp /* Check for section names for which stabsect_name is a prefix, to 202233965Sjdp handle .stab0, etc. */ 202333965Sjdp for (s = abfd->sections; 202433965Sjdp s != NULL; 202533965Sjdp s = s->next) 202633965Sjdp { 202733965Sjdp int len; 202833965Sjdp 202933965Sjdp len = strlen (stabsect_name); 203033965Sjdp 203138889Sjdp /* If the prefix matches, and the files section name ends with a 203238889Sjdp nul or a digit, then we match. I.e., we want either an exact 203338889Sjdp match or a section followed by a number. */ 203433965Sjdp if (strncmp (stabsect_name, s->name, len) == 0 203538889Sjdp && (s->name[len] == '\000' 203638889Sjdp || isdigit ((unsigned char) s->name[len]))) 203733965Sjdp { 203833965Sjdp if (read_section_stabs (abfd, s->name, strsect_name)) 203933965Sjdp { 204033965Sjdp print_section_stabs (abfd, s->name, strsect_name); 204133965Sjdp free (stabs); 204233965Sjdp free (strtab); 204333965Sjdp } 204433965Sjdp } 204533965Sjdp } 204633965Sjdp} 204733965Sjdp 204833965Sjdpstatic void 204933965Sjdpdump_bfd_header (abfd) 205033965Sjdp bfd *abfd; 205133965Sjdp{ 205233965Sjdp char *comma = ""; 205333965Sjdp 205460484Sobrien printf (_("architecture: %s, "), 205533965Sjdp bfd_printable_arch_mach (bfd_get_arch (abfd), 205633965Sjdp bfd_get_mach (abfd))); 205760484Sobrien printf (_("flags 0x%08x:\n"), abfd->flags); 205833965Sjdp 205933965Sjdp#define PF(x, y) if (abfd->flags & x) {printf("%s%s", comma, y); comma=", ";} 206033965Sjdp PF (HAS_RELOC, "HAS_RELOC"); 206133965Sjdp PF (EXEC_P, "EXEC_P"); 206233965Sjdp PF (HAS_LINENO, "HAS_LINENO"); 206333965Sjdp PF (HAS_DEBUG, "HAS_DEBUG"); 206433965Sjdp PF (HAS_SYMS, "HAS_SYMS"); 206533965Sjdp PF (HAS_LOCALS, "HAS_LOCALS"); 206633965Sjdp PF (DYNAMIC, "DYNAMIC"); 206733965Sjdp PF (WP_TEXT, "WP_TEXT"); 206833965Sjdp PF (D_PAGED, "D_PAGED"); 206933965Sjdp PF (BFD_IS_RELAXABLE, "BFD_IS_RELAXABLE"); 207060484Sobrien printf (_("\nstart address 0x")); 207133965Sjdp printf_vma (abfd->start_address); 207233965Sjdp printf ("\n"); 207333965Sjdp} 207433965Sjdp 207533965Sjdpstatic void 207633965Sjdpdump_bfd_private_header (abfd) 207733965Sjdpbfd *abfd; 207833965Sjdp{ 207933965Sjdp bfd_print_private_bfd_data (abfd, stdout); 208033965Sjdp} 208133965Sjdp 208260484Sobrien/* Dump selected contents of ABFD */ 208360484Sobrien 208433965Sjdpstatic void 208560484Sobriendump_bfd (abfd) 208633965Sjdp bfd *abfd; 208733965Sjdp{ 208833965Sjdp /* If we are adjusting section VMA's, change them all now. Changing 208933965Sjdp the BFD information is a hack. However, we must do it, or 209033965Sjdp bfd_find_nearest_line will not do the right thing. */ 209133965Sjdp if (adjust_section_vma != 0) 209233965Sjdp { 209333965Sjdp asection *s; 209433965Sjdp 209533965Sjdp for (s = abfd->sections; s != NULL; s = s->next) 209633965Sjdp { 209733965Sjdp s->vma += adjust_section_vma; 209833965Sjdp s->lma += adjust_section_vma; 209933965Sjdp } 210033965Sjdp } 210133965Sjdp 210260484Sobrien printf (_("\n%s: file format %s\n"), bfd_get_filename (abfd), 210333965Sjdp abfd->xvec->name); 210433965Sjdp if (dump_ar_hdrs) 210533965Sjdp print_arelt_descr (stdout, abfd, true); 210633965Sjdp if (dump_file_header) 210733965Sjdp dump_bfd_header (abfd); 210833965Sjdp if (dump_private_headers) 210933965Sjdp dump_bfd_private_header (abfd); 211033965Sjdp putchar ('\n'); 211133965Sjdp if (dump_section_headers) 211233965Sjdp dump_headers (abfd); 211333965Sjdp if (dump_symtab || dump_reloc_info || disassemble || dump_debugging) 211433965Sjdp { 211533965Sjdp syms = slurp_symtab (abfd); 211633965Sjdp } 211733965Sjdp if (dump_dynamic_symtab || dump_dynamic_reloc_info) 211833965Sjdp { 211933965Sjdp dynsyms = slurp_dynamic_symtab (abfd); 212033965Sjdp } 212133965Sjdp if (dump_symtab) 212233965Sjdp dump_symbols (abfd, false); 212333965Sjdp if (dump_dynamic_symtab) 212433965Sjdp dump_symbols (abfd, true); 212533965Sjdp if (dump_stab_section_info) 212633965Sjdp dump_stabs (abfd); 212733965Sjdp if (dump_reloc_info && ! disassemble) 212833965Sjdp dump_relocs (abfd); 212933965Sjdp if (dump_dynamic_reloc_info) 213033965Sjdp dump_dynamic_relocs (abfd); 213133965Sjdp if (dump_section_contents) 213233965Sjdp dump_data (abfd); 213333965Sjdp if (disassemble) 213433965Sjdp disassemble_data (abfd); 213533965Sjdp if (dump_debugging) 213633965Sjdp { 213733965Sjdp PTR dhandle; 213833965Sjdp 213933965Sjdp dhandle = read_debugging_info (abfd, syms, symcount); 214033965Sjdp if (dhandle != NULL) 214133965Sjdp { 214233965Sjdp if (! print_debugging_info (stdout, dhandle)) 214360484Sobrien { 214460484Sobrien non_fatal (_("%s: printing debugging information failed"), 214560484Sobrien bfd_get_filename (abfd)); 214660484Sobrien exit_status = 1; 214760484Sobrien } 214833965Sjdp } 214933965Sjdp } 215033965Sjdp if (syms) 215133965Sjdp { 215233965Sjdp free (syms); 215333965Sjdp syms = NULL; 215433965Sjdp } 215533965Sjdp if (dynsyms) 215633965Sjdp { 215733965Sjdp free (dynsyms); 215833965Sjdp dynsyms = NULL; 215933965Sjdp } 216033965Sjdp} 216133965Sjdp 216233965Sjdpstatic void 216360484Sobriendisplay_bfd (abfd) 216460484Sobrien bfd *abfd; 216560484Sobrien{ 216660484Sobrien char **matching; 216760484Sobrien 216860484Sobrien if (bfd_check_format_matches (abfd, bfd_object, &matching)) 216960484Sobrien { 217060484Sobrien dump_bfd (abfd); 217160484Sobrien return; 217260484Sobrien } 217360484Sobrien 217460484Sobrien if (bfd_get_error () == bfd_error_file_ambiguously_recognized) 217560484Sobrien { 217660484Sobrien nonfatal (bfd_get_filename (abfd)); 217760484Sobrien list_matching_formats (matching); 217860484Sobrien free (matching); 217960484Sobrien return; 218060484Sobrien } 218160484Sobrien 218260484Sobrien if (bfd_get_error () != bfd_error_file_not_recognized) 218360484Sobrien { 218460484Sobrien nonfatal (bfd_get_filename (abfd)); 218560484Sobrien return; 218660484Sobrien } 218760484Sobrien 218860484Sobrien if (bfd_check_format_matches (abfd, bfd_core, &matching)) 218960484Sobrien { 219060484Sobrien dump_bfd (abfd); 219160484Sobrien return; 219260484Sobrien } 219360484Sobrien 219460484Sobrien nonfatal (bfd_get_filename (abfd)); 219560484Sobrien 219660484Sobrien if (bfd_get_error () == bfd_error_file_ambiguously_recognized) 219760484Sobrien { 219860484Sobrien list_matching_formats (matching); 219960484Sobrien free (matching); 220060484Sobrien } 220160484Sobrien} 220260484Sobrien 220360484Sobrienstatic void 220433965Sjdpdisplay_file (filename, target) 220533965Sjdp char *filename; 220633965Sjdp char *target; 220733965Sjdp{ 220833965Sjdp bfd *file, *arfile = (bfd *) NULL; 220933965Sjdp 221033965Sjdp file = bfd_openr (filename, target); 221133965Sjdp if (file == NULL) 221233965Sjdp { 221360484Sobrien nonfatal (filename); 221433965Sjdp return; 221533965Sjdp } 221633965Sjdp 221733965Sjdp if (bfd_check_format (file, bfd_archive) == true) 221833965Sjdp { 221933965Sjdp bfd *last_arfile = NULL; 222033965Sjdp 222160484Sobrien printf (_("In archive %s:\n"), bfd_get_filename (file)); 222233965Sjdp for (;;) 222333965Sjdp { 222433965Sjdp bfd_set_error (bfd_error_no_error); 222533965Sjdp 222633965Sjdp arfile = bfd_openr_next_archived_file (file, arfile); 222733965Sjdp if (arfile == NULL) 222833965Sjdp { 222933965Sjdp if (bfd_get_error () != bfd_error_no_more_archived_files) 223060484Sobrien nonfatal (bfd_get_filename (file)); 223133965Sjdp break; 223233965Sjdp } 223333965Sjdp 223433965Sjdp display_bfd (arfile); 223533965Sjdp 223633965Sjdp if (last_arfile != NULL) 223733965Sjdp bfd_close (last_arfile); 223833965Sjdp last_arfile = arfile; 223933965Sjdp } 224033965Sjdp 224133965Sjdp if (last_arfile != NULL) 224233965Sjdp bfd_close (last_arfile); 224333965Sjdp } 224433965Sjdp else 224533965Sjdp display_bfd (file); 224633965Sjdp 224733965Sjdp bfd_close (file); 224833965Sjdp} 224933965Sjdp 225033965Sjdp/* Actually display the various requested regions */ 225133965Sjdp 225233965Sjdpstatic void 225333965Sjdpdump_data (abfd) 225433965Sjdp bfd *abfd; 225533965Sjdp{ 225633965Sjdp asection *section; 225733965Sjdp bfd_byte *data = 0; 225833965Sjdp bfd_size_type datasize = 0; 225960484Sobrien bfd_size_type addr_offset; 226060484Sobrien bfd_size_type start_offset, stop_offset; 226160484Sobrien unsigned int opb = bfd_octets_per_byte (abfd); 226233965Sjdp 226333965Sjdp for (section = abfd->sections; section != NULL; section = 226433965Sjdp section->next) 226533965Sjdp { 226633965Sjdp int onaline = 16; 226733965Sjdp 226833965Sjdp if (only == (char *) NULL || 226933965Sjdp strcmp (only, section->name) == 0) 227033965Sjdp { 227133965Sjdp if (section->flags & SEC_HAS_CONTENTS) 227233965Sjdp { 227360484Sobrien printf (_("Contents of section %s:\n"), section->name); 227433965Sjdp 227533965Sjdp if (bfd_section_size (abfd, section) == 0) 227633965Sjdp continue; 227733965Sjdp data = (bfd_byte *) xmalloc ((size_t) bfd_section_size (abfd, section)); 227833965Sjdp datasize = bfd_section_size (abfd, section); 227933965Sjdp 228033965Sjdp 228133965Sjdp bfd_get_section_contents (abfd, section, (PTR) data, 0, bfd_section_size (abfd, section)); 228233965Sjdp 228333965Sjdp if (start_address == (bfd_vma) -1 228433965Sjdp || start_address < section->vma) 228560484Sobrien start_offset = 0; 228633965Sjdp else 228760484Sobrien start_offset = start_address - section->vma; 228833965Sjdp if (stop_address == (bfd_vma) -1) 228960484Sobrien stop_offset = bfd_section_size (abfd, section) / opb; 229033965Sjdp else 229133965Sjdp { 229233965Sjdp if (stop_address < section->vma) 229360484Sobrien stop_offset = 0; 229433965Sjdp else 229560484Sobrien stop_offset = stop_address - section->vma; 229660484Sobrien if (stop_offset > bfd_section_size (abfd, section) / opb) 229760484Sobrien stop_offset = bfd_section_size (abfd, section) / opb; 229833965Sjdp } 229960484Sobrien for (addr_offset = start_offset; 230060484Sobrien addr_offset < stop_offset; addr_offset += onaline) 230133965Sjdp { 230233965Sjdp bfd_size_type j; 230333965Sjdp 230460484Sobrien printf (" %04lx ", (unsigned long int) 230560484Sobrien (addr_offset + section->vma)); 230660484Sobrien for (j = addr_offset * opb; 230760484Sobrien j < addr_offset * opb + onaline; j++) 230833965Sjdp { 230960484Sobrien if (j < stop_offset * opb) 231033965Sjdp printf ("%02x", (unsigned) (data[j])); 231133965Sjdp else 231233965Sjdp printf (" "); 231333965Sjdp if ((j & 3) == 3) 231433965Sjdp printf (" "); 231533965Sjdp } 231633965Sjdp 231733965Sjdp printf (" "); 231860484Sobrien for (j = addr_offset; j < addr_offset * opb + onaline; j++) 231933965Sjdp { 232060484Sobrien if (j >= stop_offset * opb) 232133965Sjdp printf (" "); 232233965Sjdp else 232333965Sjdp printf ("%c", isprint (data[j]) ? data[j] : '.'); 232433965Sjdp } 232533965Sjdp putchar ('\n'); 232633965Sjdp } 232733965Sjdp free (data); 232833965Sjdp } 232933965Sjdp } 233033965Sjdp } 233133965Sjdp} 233233965Sjdp 233333965Sjdp/* Should perhaps share code and display with nm? */ 233433965Sjdpstatic void 233533965Sjdpdump_symbols (abfd, dynamic) 233660484Sobrien bfd *abfd ATTRIBUTE_UNUSED; 233733965Sjdp boolean dynamic; 233833965Sjdp{ 233933965Sjdp asymbol **current; 234033965Sjdp long max; 234133965Sjdp long count; 234233965Sjdp 234333965Sjdp if (dynamic) 234433965Sjdp { 234533965Sjdp current = dynsyms; 234633965Sjdp max = dynsymcount; 234733965Sjdp if (max == 0) 234833965Sjdp return; 234933965Sjdp printf ("DYNAMIC SYMBOL TABLE:\n"); 235033965Sjdp } 235133965Sjdp else 235233965Sjdp { 235333965Sjdp current = syms; 235433965Sjdp max = symcount; 235533965Sjdp if (max == 0) 235633965Sjdp return; 235733965Sjdp printf ("SYMBOL TABLE:\n"); 235833965Sjdp } 235933965Sjdp 236033965Sjdp for (count = 0; count < max; count++) 236133965Sjdp { 236233965Sjdp if (*current) 236333965Sjdp { 236433965Sjdp bfd *cur_bfd = bfd_asymbol_bfd (*current); 236533965Sjdp 236633965Sjdp if (cur_bfd != NULL) 236733965Sjdp { 236833965Sjdp const char *name; 236933965Sjdp char *alloc; 237033965Sjdp 237133965Sjdp name = bfd_asymbol_name (*current); 237233965Sjdp alloc = NULL; 237333965Sjdp if (do_demangle && name != NULL && *name != '\0') 237433965Sjdp { 237533965Sjdp const char *n; 237633965Sjdp 237733965Sjdp /* If we want to demangle the name, we demangle it 237833965Sjdp here, and temporarily clobber it while calling 237933965Sjdp bfd_print_symbol. FIXME: This is a gross hack. */ 238033965Sjdp 238133965Sjdp n = name; 238233965Sjdp if (bfd_get_symbol_leading_char (cur_bfd) == *n) 238333965Sjdp ++n; 238433965Sjdp alloc = cplus_demangle (n, DMGL_ANSI | DMGL_PARAMS); 238533965Sjdp if (alloc != NULL) 238633965Sjdp (*current)->name = alloc; 238733965Sjdp else 238833965Sjdp (*current)->name = n; 238933965Sjdp } 239033965Sjdp 239133965Sjdp bfd_print_symbol (cur_bfd, stdout, *current, 239233965Sjdp bfd_print_symbol_all); 239333965Sjdp 239433965Sjdp (*current)->name = name; 239533965Sjdp if (alloc != NULL) 239633965Sjdp free (alloc); 239733965Sjdp 239833965Sjdp printf ("\n"); 239933965Sjdp } 240033965Sjdp } 240133965Sjdp current++; 240233965Sjdp } 240333965Sjdp printf ("\n"); 240433965Sjdp printf ("\n"); 240533965Sjdp} 240633965Sjdp 240733965Sjdpstatic void 240833965Sjdpdump_relocs (abfd) 240933965Sjdp bfd *abfd; 241033965Sjdp{ 241133965Sjdp arelent **relpp; 241233965Sjdp long relcount; 241333965Sjdp asection *a; 241433965Sjdp 241533965Sjdp for (a = abfd->sections; a != (asection *) NULL; a = a->next) 241633965Sjdp { 241733965Sjdp long relsize; 241833965Sjdp 241933965Sjdp if (bfd_is_abs_section (a)) 242033965Sjdp continue; 242133965Sjdp if (bfd_is_und_section (a)) 242233965Sjdp continue; 242333965Sjdp if (bfd_is_com_section (a)) 242433965Sjdp continue; 242533965Sjdp 242633965Sjdp if (only) 242733965Sjdp { 242833965Sjdp if (strcmp (only, a->name)) 242933965Sjdp continue; 243033965Sjdp } 243133965Sjdp else if ((a->flags & SEC_RELOC) == 0) 243233965Sjdp continue; 243333965Sjdp 243433965Sjdp relsize = bfd_get_reloc_upper_bound (abfd, a); 243533965Sjdp if (relsize < 0) 243633965Sjdp bfd_fatal (bfd_get_filename (abfd)); 243733965Sjdp 243833965Sjdp printf ("RELOCATION RECORDS FOR [%s]:", a->name); 243933965Sjdp 244033965Sjdp if (relsize == 0) 244133965Sjdp { 244233965Sjdp printf (" (none)\n\n"); 244333965Sjdp } 244433965Sjdp else 244533965Sjdp { 244633965Sjdp relpp = (arelent **) xmalloc (relsize); 244733965Sjdp relcount = bfd_canonicalize_reloc (abfd, a, relpp, syms); 244833965Sjdp if (relcount < 0) 244933965Sjdp bfd_fatal (bfd_get_filename (abfd)); 245033965Sjdp else if (relcount == 0) 245133965Sjdp { 245233965Sjdp printf (" (none)\n\n"); 245333965Sjdp } 245433965Sjdp else 245533965Sjdp { 245633965Sjdp printf ("\n"); 245733965Sjdp dump_reloc_set (abfd, a, relpp, relcount); 245833965Sjdp printf ("\n\n"); 245933965Sjdp } 246033965Sjdp free (relpp); 246133965Sjdp } 246233965Sjdp } 246333965Sjdp} 246433965Sjdp 246533965Sjdpstatic void 246633965Sjdpdump_dynamic_relocs (abfd) 246733965Sjdp bfd *abfd; 246833965Sjdp{ 246933965Sjdp long relsize; 247033965Sjdp arelent **relpp; 247133965Sjdp long relcount; 247233965Sjdp 247333965Sjdp relsize = bfd_get_dynamic_reloc_upper_bound (abfd); 247433965Sjdp if (relsize < 0) 247533965Sjdp bfd_fatal (bfd_get_filename (abfd)); 247633965Sjdp 247733965Sjdp printf ("DYNAMIC RELOCATION RECORDS"); 247833965Sjdp 247933965Sjdp if (relsize == 0) 248033965Sjdp { 248133965Sjdp printf (" (none)\n\n"); 248233965Sjdp } 248333965Sjdp else 248433965Sjdp { 248533965Sjdp relpp = (arelent **) xmalloc (relsize); 248633965Sjdp relcount = bfd_canonicalize_dynamic_reloc (abfd, relpp, dynsyms); 248733965Sjdp if (relcount < 0) 248833965Sjdp bfd_fatal (bfd_get_filename (abfd)); 248933965Sjdp else if (relcount == 0) 249033965Sjdp { 249133965Sjdp printf (" (none)\n\n"); 249233965Sjdp } 249333965Sjdp else 249433965Sjdp { 249533965Sjdp printf ("\n"); 249633965Sjdp dump_reloc_set (abfd, (asection *) NULL, relpp, relcount); 249733965Sjdp printf ("\n\n"); 249833965Sjdp } 249933965Sjdp free (relpp); 250033965Sjdp } 250133965Sjdp} 250233965Sjdp 250333965Sjdpstatic void 250433965Sjdpdump_reloc_set (abfd, sec, relpp, relcount) 250533965Sjdp bfd *abfd; 250633965Sjdp asection *sec; 250733965Sjdp arelent **relpp; 250833965Sjdp long relcount; 250933965Sjdp{ 251033965Sjdp arelent **p; 251133965Sjdp char *last_filename, *last_functionname; 251233965Sjdp unsigned int last_line; 251333965Sjdp 251433965Sjdp /* Get column headers lined up reasonably. */ 251533965Sjdp { 251633965Sjdp static int width; 251733965Sjdp if (width == 0) 251833965Sjdp { 251933965Sjdp char buf[30]; 252033965Sjdp sprintf_vma (buf, (bfd_vma) -1); 252133965Sjdp width = strlen (buf) - 7; 252233965Sjdp } 252333965Sjdp printf ("OFFSET %*s TYPE %*s VALUE \n", width, "", 12, ""); 252433965Sjdp } 252533965Sjdp 252633965Sjdp last_filename = NULL; 252733965Sjdp last_functionname = NULL; 252833965Sjdp last_line = 0; 252933965Sjdp 253033965Sjdp for (p = relpp; relcount && *p != (arelent *) NULL; p++, relcount--) 253133965Sjdp { 253233965Sjdp arelent *q = *p; 253333965Sjdp const char *filename, *functionname; 253433965Sjdp unsigned int line; 253533965Sjdp const char *sym_name; 253633965Sjdp const char *section_name; 253733965Sjdp 253833965Sjdp if (start_address != (bfd_vma) -1 253933965Sjdp && q->address < start_address) 254033965Sjdp continue; 254133965Sjdp if (stop_address != (bfd_vma) -1 254233965Sjdp && q->address > stop_address) 254333965Sjdp continue; 254433965Sjdp 254533965Sjdp if (with_line_numbers 254633965Sjdp && sec != NULL 254733965Sjdp && bfd_find_nearest_line (abfd, sec, syms, q->address, 254833965Sjdp &filename, &functionname, &line)) 254933965Sjdp { 255033965Sjdp if (functionname != NULL 255133965Sjdp && (last_functionname == NULL 255233965Sjdp || strcmp (functionname, last_functionname) != 0)) 255333965Sjdp { 255433965Sjdp printf ("%s():\n", functionname); 255533965Sjdp if (last_functionname != NULL) 255633965Sjdp free (last_functionname); 255733965Sjdp last_functionname = xstrdup (functionname); 255833965Sjdp } 255933965Sjdp if (line > 0 256033965Sjdp && (line != last_line 256133965Sjdp || (filename != NULL 256233965Sjdp && last_filename != NULL 256333965Sjdp && strcmp (filename, last_filename) != 0))) 256433965Sjdp { 256533965Sjdp printf ("%s:%u\n", filename == NULL ? "???" : filename, line); 256633965Sjdp last_line = line; 256733965Sjdp if (last_filename != NULL) 256833965Sjdp free (last_filename); 256933965Sjdp if (filename == NULL) 257033965Sjdp last_filename = NULL; 257133965Sjdp else 257233965Sjdp last_filename = xstrdup (filename); 257333965Sjdp } 257433965Sjdp } 257533965Sjdp 257633965Sjdp if (q->sym_ptr_ptr && *q->sym_ptr_ptr) 257733965Sjdp { 257833965Sjdp sym_name = (*(q->sym_ptr_ptr))->name; 257933965Sjdp section_name = (*(q->sym_ptr_ptr))->section->name; 258033965Sjdp } 258133965Sjdp else 258233965Sjdp { 258333965Sjdp sym_name = NULL; 258433965Sjdp section_name = NULL; 258533965Sjdp } 258633965Sjdp if (sym_name) 258733965Sjdp { 258833965Sjdp printf_vma (q->address); 258960484Sobrien if (q->howto->name) 259060484Sobrien printf (" %-16s ", q->howto->name); 259160484Sobrien else 259260484Sobrien printf (" %-16d ", q->howto->type); 259333965Sjdp objdump_print_symname (abfd, (struct disassemble_info *) NULL, 259433965Sjdp *q->sym_ptr_ptr); 259533965Sjdp } 259633965Sjdp else 259733965Sjdp { 259833965Sjdp if (section_name == (CONST char *) NULL) 259933965Sjdp section_name = "*unknown*"; 260033965Sjdp printf_vma (q->address); 260133965Sjdp printf (" %-16s [%s]", 260233965Sjdp q->howto->name, 260333965Sjdp section_name); 260433965Sjdp } 260533965Sjdp if (q->addend) 260633965Sjdp { 260733965Sjdp printf ("+0x"); 260833965Sjdp printf_vma (q->addend); 260933965Sjdp } 261033965Sjdp printf ("\n"); 261133965Sjdp } 261233965Sjdp} 261333965Sjdp 261433965Sjdp/* The length of the longest architecture name + 1. */ 261533965Sjdp#define LONGEST_ARCH sizeof("rs6000:6000") 261633965Sjdp 261733965Sjdpstatic const char * 261833965Sjdpendian_string (endian) 261933965Sjdp enum bfd_endian endian; 262033965Sjdp{ 262133965Sjdp if (endian == BFD_ENDIAN_BIG) 262233965Sjdp return "big endian"; 262333965Sjdp else if (endian == BFD_ENDIAN_LITTLE) 262433965Sjdp return "little endian"; 262533965Sjdp else 262633965Sjdp return "endianness unknown"; 262733965Sjdp} 262833965Sjdp 262933965Sjdp/* List the targets that BFD is configured to support, each followed 263033965Sjdp by its endianness and the architectures it supports. */ 263133965Sjdp 263233965Sjdpstatic void 263333965Sjdpdisplay_target_list () 263433965Sjdp{ 263533965Sjdp extern bfd_target *bfd_target_vector[]; 263633965Sjdp char *dummy_name; 263733965Sjdp int t; 263833965Sjdp 263933965Sjdp dummy_name = choose_temp_base (); 264033965Sjdp for (t = 0; bfd_target_vector[t]; t++) 264133965Sjdp { 264233965Sjdp bfd_target *p = bfd_target_vector[t]; 264333965Sjdp bfd *abfd = bfd_openw (dummy_name, p->name); 264433965Sjdp int a; 264533965Sjdp 264633965Sjdp printf ("%s\n (header %s, data %s)\n", p->name, 264733965Sjdp endian_string (p->header_byteorder), 264833965Sjdp endian_string (p->byteorder)); 264933965Sjdp 265033965Sjdp if (abfd == NULL) 265133965Sjdp { 265260484Sobrien nonfatal (dummy_name); 265333965Sjdp continue; 265433965Sjdp } 265533965Sjdp 265633965Sjdp if (! bfd_set_format (abfd, bfd_object)) 265733965Sjdp { 265833965Sjdp if (bfd_get_error () != bfd_error_invalid_operation) 265960484Sobrien nonfatal (p->name); 266033965Sjdp continue; 266133965Sjdp } 266233965Sjdp 266333965Sjdp for (a = (int) bfd_arch_obscure + 1; a < (int) bfd_arch_last; a++) 266433965Sjdp if (bfd_set_arch_mach (abfd, (enum bfd_architecture) a, 0)) 266533965Sjdp printf (" %s\n", 266633965Sjdp bfd_printable_arch_mach ((enum bfd_architecture) a, 0)); 266733965Sjdp } 266833965Sjdp unlink (dummy_name); 266933965Sjdp free (dummy_name); 267033965Sjdp} 267133965Sjdp 267233965Sjdp/* Print a table showing which architectures are supported for entries 267333965Sjdp FIRST through LAST-1 of bfd_target_vector (targets across, 267433965Sjdp architectures down). */ 267533965Sjdp 267633965Sjdpstatic void 267733965Sjdpdisplay_info_table (first, last) 267833965Sjdp int first; 267933965Sjdp int last; 268033965Sjdp{ 268133965Sjdp extern bfd_target *bfd_target_vector[]; 268233965Sjdp int t, a; 268333965Sjdp char *dummy_name; 268433965Sjdp 268533965Sjdp /* Print heading of target names. */ 268633965Sjdp printf ("\n%*s", (int) LONGEST_ARCH, " "); 268733965Sjdp for (t = first; t < last && bfd_target_vector[t]; t++) 268833965Sjdp printf ("%s ", bfd_target_vector[t]->name); 268933965Sjdp putchar ('\n'); 269033965Sjdp 269133965Sjdp dummy_name = choose_temp_base (); 269233965Sjdp for (a = (int) bfd_arch_obscure + 1; a < (int) bfd_arch_last; a++) 269333965Sjdp if (strcmp (bfd_printable_arch_mach (a, 0), "UNKNOWN!") != 0) 269433965Sjdp { 269533965Sjdp printf ("%*s ", (int) LONGEST_ARCH - 1, 269633965Sjdp bfd_printable_arch_mach (a, 0)); 269733965Sjdp for (t = first; t < last && bfd_target_vector[t]; t++) 269833965Sjdp { 269933965Sjdp bfd_target *p = bfd_target_vector[t]; 270033965Sjdp boolean ok = true; 270133965Sjdp bfd *abfd = bfd_openw (dummy_name, p->name); 270233965Sjdp 270333965Sjdp if (abfd == NULL) 270433965Sjdp { 270560484Sobrien nonfatal (p->name); 270633965Sjdp ok = false; 270733965Sjdp } 270833965Sjdp 270933965Sjdp if (ok) 271033965Sjdp { 271133965Sjdp if (! bfd_set_format (abfd, bfd_object)) 271233965Sjdp { 271333965Sjdp if (bfd_get_error () != bfd_error_invalid_operation) 271460484Sobrien nonfatal (p->name); 271533965Sjdp ok = false; 271633965Sjdp } 271733965Sjdp } 271833965Sjdp 271933965Sjdp if (ok) 272033965Sjdp { 272133965Sjdp if (! bfd_set_arch_mach (abfd, a, 0)) 272233965Sjdp ok = false; 272333965Sjdp } 272433965Sjdp 272533965Sjdp if (ok) 272633965Sjdp printf ("%s ", p->name); 272733965Sjdp else 272833965Sjdp { 272933965Sjdp int l = strlen (p->name); 273033965Sjdp while (l--) 273133965Sjdp putchar ('-'); 273233965Sjdp putchar (' '); 273333965Sjdp } 273433965Sjdp } 273533965Sjdp putchar ('\n'); 273633965Sjdp } 273733965Sjdp unlink (dummy_name); 273833965Sjdp free (dummy_name); 273933965Sjdp} 274033965Sjdp 274133965Sjdp/* Print tables of all the target-architecture combinations that 274233965Sjdp BFD has been configured to support. */ 274333965Sjdp 274433965Sjdpstatic void 274533965Sjdpdisplay_target_tables () 274633965Sjdp{ 274733965Sjdp int t, columns; 274833965Sjdp extern bfd_target *bfd_target_vector[]; 274933965Sjdp char *colum; 275033965Sjdp 275133965Sjdp columns = 0; 275233965Sjdp colum = getenv ("COLUMNS"); 275333965Sjdp if (colum != NULL) 275433965Sjdp columns = atoi (colum); 275533965Sjdp if (columns == 0) 275633965Sjdp columns = 80; 275733965Sjdp 275833965Sjdp t = 0; 275933965Sjdp while (bfd_target_vector[t] != NULL) 276033965Sjdp { 276133965Sjdp int oldt = t, wid; 276233965Sjdp 276333965Sjdp wid = LONGEST_ARCH + strlen (bfd_target_vector[t]->name) + 1; 276433965Sjdp ++t; 276533965Sjdp while (wid < columns && bfd_target_vector[t] != NULL) 276633965Sjdp { 276733965Sjdp int newwid; 276833965Sjdp 276933965Sjdp newwid = wid + strlen (bfd_target_vector[t]->name) + 1; 277033965Sjdp if (newwid >= columns) 277133965Sjdp break; 277233965Sjdp wid = newwid; 277333965Sjdp ++t; 277433965Sjdp } 277533965Sjdp display_info_table (oldt, t); 277633965Sjdp } 277733965Sjdp} 277833965Sjdp 277933965Sjdpstatic void 278033965Sjdpdisplay_info () 278133965Sjdp{ 278260484Sobrien printf (_("BFD header file version %s\n"), BFD_VERSION); 278333965Sjdp display_target_list (); 278433965Sjdp display_target_tables (); 278533965Sjdp} 278633965Sjdp 278733965Sjdpint 278833965Sjdpmain (argc, argv) 278933965Sjdp int argc; 279033965Sjdp char **argv; 279133965Sjdp{ 279233965Sjdp int c; 279333965Sjdp char *target = default_target; 279433965Sjdp boolean seenflag = false; 279533965Sjdp 279660484Sobrien#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES) 279760484Sobrien setlocale (LC_MESSAGES, ""); 279860484Sobrien#endif 279960484Sobrien bindtextdomain (PACKAGE, LOCALEDIR); 280060484Sobrien textdomain (PACKAGE); 280160484Sobrien 280233965Sjdp program_name = *argv; 280333965Sjdp xmalloc_set_program_name (program_name); 280433965Sjdp 280533965Sjdp START_PROGRESS (program_name, 0); 280633965Sjdp 280733965Sjdp bfd_init (); 280833965Sjdp set_default_bfd_target (); 280933965Sjdp 281060484Sobrien while ((c = getopt_long (argc, argv, "pib:m:M:VCdDlfahHrRtTxsSj:wE:zgG", 281133965Sjdp long_options, (int *) 0)) 281233965Sjdp != EOF) 281333965Sjdp { 281433965Sjdp switch (c) 281533965Sjdp { 281633965Sjdp case 0: 281733965Sjdp break; /* we've been given a long option */ 281833965Sjdp case 'm': 281933965Sjdp machine = optarg; 282033965Sjdp break; 282160484Sobrien case 'M': 282260484Sobrien disassembler_options = optarg; 282360484Sobrien break; 282433965Sjdp case 'j': 282533965Sjdp only = optarg; 282633965Sjdp break; 282733965Sjdp case 'l': 282860484Sobrien with_line_numbers = true; 282933965Sjdp break; 283033965Sjdp case 'b': 283133965Sjdp target = optarg; 283233965Sjdp break; 283360484Sobrien case 'C': 283460484Sobrien do_demangle = true; 283560484Sobrien break; 283660484Sobrien case 'w': 283760484Sobrien wide_output = true; 283860484Sobrien break; 283960484Sobrien case OPTION_ADJUST_VMA: 284060484Sobrien adjust_section_vma = parse_vma (optarg, "--adjust-vma"); 284160484Sobrien break; 284260484Sobrien case OPTION_START_ADDRESS: 284360484Sobrien start_address = parse_vma (optarg, "--start-address"); 284460484Sobrien break; 284560484Sobrien case OPTION_STOP_ADDRESS: 284660484Sobrien stop_address = parse_vma (optarg, "--stop-address"); 284760484Sobrien break; 284860484Sobrien case 'E': 284960484Sobrien if (strcmp (optarg, "B") == 0) 285060484Sobrien endian = BFD_ENDIAN_BIG; 285160484Sobrien else if (strcmp (optarg, "L") == 0) 285260484Sobrien endian = BFD_ENDIAN_LITTLE; 285360484Sobrien else 285460484Sobrien { 285560484Sobrien non_fatal (_("unrecognized -E option")); 285660484Sobrien usage (stderr, 1); 285760484Sobrien } 285860484Sobrien break; 285960484Sobrien case OPTION_ENDIAN: 286060484Sobrien if (strncmp (optarg, "big", strlen (optarg)) == 0) 286160484Sobrien endian = BFD_ENDIAN_BIG; 286260484Sobrien else if (strncmp (optarg, "little", strlen (optarg)) == 0) 286360484Sobrien endian = BFD_ENDIAN_LITTLE; 286460484Sobrien else 286560484Sobrien { 286660484Sobrien non_fatal (_("unrecognized --endian type `%s'"), optarg); 286760484Sobrien usage (stderr, 1); 286860484Sobrien } 286960484Sobrien break; 287060484Sobrien 287133965Sjdp case 'f': 287233965Sjdp dump_file_header = true; 287360484Sobrien seenflag = true; 287433965Sjdp break; 287533965Sjdp case 'i': 287633965Sjdp formats_info = true; 287760484Sobrien seenflag = true; 287833965Sjdp break; 287933965Sjdp case 'p': 288060484Sobrien dump_private_headers = true; 288160484Sobrien seenflag = true; 288233965Sjdp break; 288333965Sjdp case 'x': 288460484Sobrien dump_private_headers = true; 288560484Sobrien dump_symtab = true; 288660484Sobrien dump_reloc_info = true; 288733965Sjdp dump_file_header = true; 288860484Sobrien dump_ar_hdrs = true; 288960484Sobrien dump_section_headers = true; 289060484Sobrien seenflag = true; 289133965Sjdp break; 289233965Sjdp case 't': 289360484Sobrien dump_symtab = true; 289460484Sobrien seenflag = true; 289533965Sjdp break; 289633965Sjdp case 'T': 289760484Sobrien dump_dynamic_symtab = true; 289860484Sobrien seenflag = true; 289933965Sjdp break; 290033965Sjdp case 'd': 290133965Sjdp disassemble = true; 290260484Sobrien seenflag = true; 290333965Sjdp break; 290460484Sobrien case 'z': 290560484Sobrien disassemble_zeroes = true; 290660484Sobrien break; 290733965Sjdp case 'D': 290860484Sobrien disassemble = true; 290960484Sobrien disassemble_all = true; 291060484Sobrien seenflag = true; 291133965Sjdp break; 291233965Sjdp case 'S': 291333965Sjdp disassemble = true; 291433965Sjdp with_source_code = true; 291560484Sobrien seenflag = true; 291633965Sjdp break; 291760484Sobrien case 'g': 291860484Sobrien dump_debugging = 1; 291960484Sobrien seenflag = true; 292060484Sobrien break; 292160484Sobrien case 'G': 292260484Sobrien dump_stab_section_info = true; 292360484Sobrien seenflag = true; 292460484Sobrien break; 292533965Sjdp case 's': 292660484Sobrien dump_section_contents = true; 292760484Sobrien seenflag = true; 292833965Sjdp break; 292933965Sjdp case 'r': 293060484Sobrien dump_reloc_info = true; 293160484Sobrien seenflag = true; 293233965Sjdp break; 293333965Sjdp case 'R': 293460484Sobrien dump_dynamic_reloc_info = true; 293560484Sobrien seenflag = true; 293633965Sjdp break; 293733965Sjdp case 'a': 293860484Sobrien dump_ar_hdrs = true; 293960484Sobrien seenflag = true; 294033965Sjdp break; 294133965Sjdp case 'h': 294260484Sobrien dump_section_headers = true; 294360484Sobrien seenflag = true; 294433965Sjdp break; 294533965Sjdp case 'H': 294633965Sjdp usage (stdout, 0); 294760484Sobrien seenflag = true; 294833965Sjdp case 'V': 294960484Sobrien show_version = true; 295060484Sobrien seenflag = true; 295133965Sjdp break; 295260484Sobrien 295333965Sjdp default: 295433965Sjdp usage (stderr, 1); 295533965Sjdp } 295633965Sjdp } 295733965Sjdp 295833965Sjdp if (show_version) 295933965Sjdp print_version ("objdump"); 296033965Sjdp 296133965Sjdp if (seenflag == false) 296260484Sobrien usage (stderr, 2); 296333965Sjdp 296433965Sjdp if (formats_info) 296560484Sobrien display_info (); 296633965Sjdp else 296733965Sjdp { 296833965Sjdp if (optind == argc) 296933965Sjdp display_file ("a.out", target); 297033965Sjdp else 297133965Sjdp for (; optind < argc;) 297233965Sjdp display_file (argv[optind++], target); 297333965Sjdp } 297433965Sjdp 297533965Sjdp END_PROGRESS (program_name); 297633965Sjdp 297760484Sobrien return exit_status; 297833965Sjdp} 2979