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