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