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