top level:
[deliverable/binutils-gdb.git] / binutils / objdump.c
index 7f1e2ea099772e88bcbd36bc97f63b3a7e507eaa..a273f511f15b1c9e9ad6ab05d57229fbe2342154 100644 (file)
@@ -1,6 +1,6 @@
 /* objdump.c -- dump information about an object file.
    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002, 2003
+   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
    Free Software Foundation, Inc.
 
    This file is part of GNU Binutils.
@@ -17,7 +17,7 @@
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
 
 /* Objdump overview.
 
@@ -41,7 +41,7 @@
 
    4. dump_bfd() in turn calls separate functions to display the requested
       item(s) of information(s).  For example disassemble_data() is called if
-      a disassmebly has been requested.
+      a disassembly has been requested.
 
    When disassembling the code loops through blocks of instructions bounded
    by symbols, calling disassemble_bytes() on each block.  The actual
@@ -52,6 +52,7 @@
 #include "bfdver.h"
 #include "progress.h"
 #include "bucomm.h"
+#include "dwarf.h"
 #include "budemang.h"
 #include "getopt.h"
 #include "safe-ctype.h"
 #define        BYTES_IN_WORD   32
 #include "aout/aout64.h"
 
-#ifdef NEED_DECLARATION_FPRINTF
-/* This is needed by init_disassemble_info().  */
-extern int fprintf (FILE *, const char *, ...);
-#endif
-
 /* Exit status.  */
 static int exit_status = 0;
 
@@ -91,6 +87,7 @@ static int prefix_addresses;          /* --prefix-addresses */
 static int with_line_numbers;          /* -l */
 static bfd_boolean with_source_code;   /* -S */
 static int show_raw_insn;              /* --show-raw-insn */
+static int dump_dwarf_section_info;    /* --dwarf */
 static int dump_stab_section_info;     /* --stabs */
 static int do_demangle;                        /* -C, --demangle */
 static bfd_boolean disassemble;                /* -d */
@@ -102,6 +99,7 @@ static bfd_vma start_address = (bfd_vma) -1; /* --start-address */
 static bfd_vma stop_address = (bfd_vma) -1;  /* --stop-address */
 static int dump_debugging;             /* --debugging */
 static int dump_debugging_tags;                /* --debugging-tags */
+static int dump_special_syms = 0;      /* --special-syms */
 static bfd_vma adjust_section_vma = 0; /* --adjust-vma */
 static int file_start_context = 0;      /* --file-start-context */
 
@@ -127,6 +125,7 @@ struct objdump_disasm_info
   arelent **         dynrelbuf;
   long               dynrelcount;
   disassembler_ftype disassemble_fn;
+  arelent *          reloc;
 };
 
 /* Architecture to disassemble for, or default if NULL.  */
@@ -153,6 +152,10 @@ static long sorted_symcount = 0;
 /* The dynamic symbol table.  */
 static asymbol **dynsyms;
 
+/* The synthetic symbol table.  */
+static asymbol *synthsyms;
+static long synthcount = 0;
+
 /* Number of symbols in `dynsyms'.  */
 static long dynsymcount = 0;
 
@@ -181,10 +184,12 @@ usage (FILE *stream, int status)
   -g, --debugging          Display debug information in object file\n\
   -e, --debugging-tags     Display debug information using ctags style\n\
   -G, --stabs              Display (in raw form) any STABS info in the file\n\
+  -W, --dwarf              Display DWARF info in the file\n\
   -t, --syms               Display the contents of the symbol table(s)\n\
   -T, --dynamic-syms       Display the contents of the dynamic symbol table\n\
   -r, --reloc              Display the relocation entries in the file\n\
   -R, --dynamic-reloc      Display the dynamic relocation entries in the file\n\
+  @<file>                  Read options from <file>\n\
   -v, --version            Display this program's version number\n\
   -i, --info               List object formats and architectures supported\n\
   -H, --help               Display this information\n\
@@ -213,13 +218,14 @@ usage (FILE *stream, int status)
       --prefix-addresses         Print complete address alongside disassembly\n\
       --[no-]show-raw-insn       Display hex alongside symbolic disassembly\n\
       --adjust-vma=OFFSET        Add OFFSET to all displayed section addresses\n\
+      --special-syms             Include special symbols in symbol dumps\n\
 \n"));
       list_supported_targets (program_name, stream);
       list_supported_architectures (program_name, stream);
 
       disassembler_usage (stream);
     }
-  if (status == 0)
+  if (REPORT_BUGS_TO[0] && status == 0)
     fprintf (stream, _("Report bugs to %s.\n"), REPORT_BUGS_TO);
   exit (status);
 }
@@ -264,7 +270,9 @@ static struct option long_options[]=
   {"section-headers", no_argument, NULL, 'h'},
   {"show-raw-insn", no_argument, &show_raw_insn, 1},
   {"source", no_argument, NULL, 'S'},
+  {"special-syms", no_argument, &dump_special_syms, 1},
   {"include", required_argument, NULL, 'I'},
+  {"dwarf", no_argument, NULL, 'W'},
   {"stabs", no_argument, NULL, 'G'},
   {"start-address", required_argument, NULL, OPTION_START_ADDRESS},
   {"stop-address", required_argument, NULL, OPTION_STOP_ADDRESS},
@@ -283,12 +291,17 @@ nonfatal (const char *msg)
 }
 \f
 static void
-dump_section_header (bfd *abfd ATTRIBUTE_UNUSED, asection *section,
+dump_section_header (bfd *abfd, asection *section,
                     void *ignored ATTRIBUTE_UNUSED)
 {
   char *comma = "";
   unsigned int opb = bfd_octets_per_byte (abfd);
 
+  /* Ignore linker created section.  See elfNN_ia64_object_p in
+     bfd/elfxx-ia64.c.  */
+  if (section->flags & SEC_LINKER_CREATED)
+    return;
+
   printf ("%3d %-13s %08lx  ", section->index,
          bfd_get_section_name (abfd, section),
          (unsigned long) bfd_section_size (abfd, section) / opb);
@@ -317,16 +330,21 @@ dump_section_header (bfd *abfd ATTRIBUTE_UNUSED, asection *section,
   PF (SEC_NEVER_LOAD, "NEVER_LOAD");
   PF (SEC_EXCLUDE, "EXCLUDE");
   PF (SEC_SORT_ENTRIES, "SORT_ENTRIES");
-  PF (SEC_BLOCK, "BLOCK");
-  PF (SEC_CLINK, "CLINK");
+  if (bfd_get_arch (abfd) == bfd_arch_tic54x)
+    {
+      PF (SEC_TIC54X_BLOCK, "BLOCK");
+      PF (SEC_TIC54X_CLINK, "CLINK");
+    }
   PF (SEC_SMALL_DATA, "SMALL_DATA");
-  PF (SEC_SHARED, "SHARED");
-  PF (SEC_ARCH_BIT_0, "ARCH_BIT_0");
+  if (bfd_get_flavour (abfd) == bfd_target_coff_flavour)
+    PF (SEC_COFF_SHARED, "SHARED");
   PF (SEC_THREAD_LOCAL, "THREAD_LOCAL");
+  PF (SEC_GROUP, "GROUP");
 
   if ((section->flags & SEC_LINK_ONCE) != 0)
     {
       const char *ls;
+      struct coff_comdat_info *comdat;
 
       switch (section->flags & SEC_LINK_DUPLICATES)
        {
@@ -347,9 +365,9 @@ dump_section_header (bfd *abfd ATTRIBUTE_UNUSED, asection *section,
        }
       printf ("%s%s", comma, ls);
 
-      if (section->comdat != NULL)
-       printf (" (COMDAT %s %ld)", section->comdat->name,
-               section->comdat->symbol);
+      comdat = bfd_coff_get_comdat_section (abfd, section);
+      if (comdat != NULL)
+       printf (" (COMDAT %s %ld)", comdat->name, comdat->symbol);
 
       comma = ", ";
     }
@@ -450,7 +468,7 @@ remove_useless_symbols (asymbol **symbols, long count)
 
       if (sym->name == NULL || sym->name[0] == '\0')
        continue;
-      if (sym->flags & (BSF_DEBUGGING))
+      if (sym->flags & (BSF_DEBUGGING | BSF_SECTION_SYM))
        continue;
       if (bfd_is_und_section (sym->section)
          || bfd_is_com_section (sym->section))
@@ -840,7 +858,8 @@ objdump_print_addr (bfd_vma vma,
                    bfd_boolean skip_zeroes)
 {
   struct objdump_disasm_info *aux;
-  asymbol *sym;
+  asymbol *sym = NULL; /* Initialize to avoid compiler warning.  */
+  bfd_boolean skip_find = FALSE;
 
   if (sorted_symcount < 1)
     {
@@ -850,7 +869,23 @@ objdump_print_addr (bfd_vma vma,
     }
 
   aux = (struct objdump_disasm_info *) info->application_data;
-  sym = find_symbol_for_address (vma, info, NULL);
+
+  if (aux->reloc != NULL
+      && aux->reloc->sym_ptr_ptr != NULL
+      && * aux->reloc->sym_ptr_ptr != NULL)
+    {
+      sym = * aux->reloc->sym_ptr_ptr;
+
+      /* Adjust the vma to the reloc.  */
+      vma += bfd_asymbol_value (sym);
+
+      if (bfd_is_und_section (bfd_get_section (sym)))
+       skip_find = TRUE;
+    }
+
+  if (!skip_find)
+    sym = find_symbol_for_address (vma, info, NULL);
+
   objdump_print_addr_with_sym (aux->abfd, aux->sec, sym, vma, info,
                               skip_zeroes);
 }
@@ -864,7 +899,7 @@ objdump_print_address (bfd_vma vma, struct disassemble_info *info)
   objdump_print_addr (vma, info, ! prefix_addresses);
 }
 
-/* Determine of the given address has a symbol associated with it.  */
+/* Determine if the given address has a symbol associated with it.  */
 
 static int
 objdump_symbol_at_address (bfd_vma vma, struct disassemble_info * info)
@@ -1142,48 +1177,34 @@ show_line (bfd *abfd, asection *section, bfd_vma addr_offset)
 typedef struct
 {
   char *buffer;
-  size_t size;
-  char *current;
+  size_t pos;
+  size_t alloc;
 } SFILE;
 
 /* sprintf to a "stream".  */
 
-static int
+static int ATTRIBUTE_PRINTF_2
 objdump_sprintf (SFILE *f, const char *format, ...)
 {
-  char *buf;
   size_t n;
   va_list args;
 
-  va_start (args, format);
-
-  vasprintf (&buf, format, args);
-
-  if (buf == NULL)
+  while (1)
     {
+      size_t space = f->alloc - f->pos;
+  
+      va_start (args, format);
+      n = vsnprintf (f->buffer + f->pos, space, format, args);
       va_end (args);
-      fatal (_("Out of virtual memory"));
-    }
-
-  n = strlen (buf);
 
-  while ((size_t) ((f->buffer + f->size) - f->current) < n + 1)
-    {
-      size_t curroff;
-
-      curroff = f->current - f->buffer;
-      f->size *= 2;
-      f->buffer = xrealloc (f->buffer, f->size);
-      f->current = f->buffer + curroff;
+      if (space > n)
+       break;
+      
+      f->alloc = (f->alloc + n) * 2;
+      f->buffer = xrealloc (f->buffer, f->alloc);
     }
-
-  memcpy (f->current, buf, n);
-  f->current += n;
-  f->current[0] = '\0';
-
-  free (buf);
-
-  va_end (args);
+  f->pos += n;
+  
   return n;
 }
 
@@ -1208,9 +1229,7 @@ process_section_p (asection * section)
 /* The number of zeroes we want to see before we start skipping them.
    The number is arbitrarily chosen.  */
 
-#ifndef SKIP_ZEROES
-#define SKIP_ZEROES (8)
-#endif
+#define DEFAULT_SKIP_ZEROES 8
 
 /* The number of zeroes to skip at the end of a section.  If the
    number of zeroes at the end is between SKIP_ZEROES_AT_END and
@@ -1219,9 +1238,7 @@ process_section_p (asection * section)
    attempt to avoid disassembling zeroes inserted by section
    alignment.  */
 
-#ifndef SKIP_ZEROES_AT_END
-#define SKIP_ZEROES_AT_END (3)
-#endif
+#define DEFAULT_SKIP_ZEROES_AT_END 3
 
 /* Disassemble some data in memory between given values.  */
 
@@ -1242,11 +1259,19 @@ disassemble_bytes (struct disassemble_info * info,
   bfd_boolean done_dot;
   int skip_addr_chars;
   bfd_vma addr_offset;
-  int opb = info->octets_per_byte;
+  unsigned int opb = info->octets_per_byte;
+  unsigned int skip_zeroes = info->skip_zeroes;
+  unsigned int skip_zeroes_at_end = info->skip_zeroes_at_end;
+  int octets = opb;
+  SFILE sfile;
 
   aux = (struct objdump_disasm_info *) info->application_data;
   section = aux->sec;
 
+  sfile.alloc = 120;
+  sfile.buffer = xmalloc (sfile.alloc);
+  sfile.pos = 0;
+  
   if (insns)
     octets_per_line = 4;
   else
@@ -1282,8 +1307,12 @@ disassemble_bytes (struct disassemble_info * info,
   while (addr_offset < stop_offset)
     {
       bfd_vma z;
-      int octets = 0;
       bfd_boolean need_nl = FALSE;
+      int previous_octets;
+
+      /* Remember the length of the previous instruction.  */
+      previous_octets = octets;
+      octets = 0;
 
       /* If we see more than SKIP_ZEROES octets of zeroes, we just
         print `...'.  */
@@ -1293,9 +1322,9 @@ disassemble_bytes (struct disassemble_info * info,
       if (! disassemble_zeroes
          && (info->insn_info_valid == 0
              || info->branch_delay_insns == 0)
-         && (z - addr_offset * opb >= SKIP_ZEROES
+         && (z - addr_offset * opb >= skip_zeroes
              || (z == stop_offset * opb &&
-                 z - addr_offset * opb < SKIP_ZEROES_AT_END)))
+                 z - addr_offset * opb < skip_zeroes_at_end)))
        {
          printf ("\t...\n");
 
@@ -1311,17 +1340,13 @@ disassemble_bytes (struct disassemble_info * info,
       else
        {
          char buf[50];
-         SFILE sfile;
          int bpc = 0;
          int pb = 0;
 
          done_dot = FALSE;
 
          if (with_line_numbers || with_source_code)
-           /* The line number tables will refer to unadjusted
-              section VMAs, so we must undo any VMA modifications
-              when calling show_line.  */
-           show_line (aux->abfd, section, addr_offset - adjust_section_vma);
+           show_line (aux->abfd, section, addr_offset);
 
          if (! prefix_addresses)
            {
@@ -1344,25 +1369,44 @@ disassemble_bytes (struct disassemble_info * info,
 
          if (insns)
            {
-             sfile.size = 120;
-             sfile.buffer = xmalloc (sfile.size);
-             sfile.current = sfile.buffer;
+             sfile.pos = 0;
              info->fprintf_func = (fprintf_ftype) objdump_sprintf;
-             info->stream = (FILE *) &sfile;
+             info->stream = &sfile;
              info->bytes_per_line = 0;
              info->bytes_per_chunk = 0;
+             info->flags = 0;
 
-#ifdef DISASSEMBLER_NEEDS_RELOCS
-             /* FIXME: This is wrong.  It tests the number of octets
-                in the last instruction, not the current one.  */
-             if (*relppp < relppend
-                 && (**relppp)->address >= rel_offset + addr_offset
-                 && ((**relppp)->address
-                     < rel_offset + addr_offset + octets / opb))
-               info->flags = INSN_HAS_RELOC;
-             else
-#endif
-               info->flags = 0;
+             if (info->disassembler_needs_relocs
+                 && *relppp < relppend)
+               {
+                 bfd_signed_vma distance_to_rel;
+
+                 distance_to_rel = (**relppp)->address
+                   - (rel_offset + addr_offset);
+
+                 /* Check to see if the current reloc is associated with
+                    the instruction that we are about to disassemble.  */
+                 if (distance_to_rel == 0
+                     /* FIXME: This is wrong.  We are trying to catch
+                        relocs that are addressed part way through the
+                        current instruction, as might happen with a packed
+                        VLIW instruction.  Unfortunately we do not know the
+                        length of the current instruction since we have not
+                        disassembled it yet.  Instead we take a guess based
+                        upon the length of the previous instruction.  The
+                        proper solution is to have a new target-specific
+                        disassembler function which just returns the length
+                        of an instruction at a given address without trying
+                        to display its disassembly. */
+                     || (distance_to_rel > 0
+                         && distance_to_rel < (bfd_signed_vma) (previous_octets/ opb)))
+                   {
+                     info->flags = INSN_HAS_RELOC;
+                     aux->reloc = **relppp;
+                   }
+                 else
+                   aux->reloc = NULL;
+               }
 
              octets = (*disassemble_fn) (section->vma + addr_offset, info);
              info->fprintf_func = (fprintf_ftype) fprintf;
@@ -1371,9 +1415,8 @@ disassemble_bytes (struct disassemble_info * info,
                octets_per_line = info->bytes_per_line;
              if (octets < 0)
                {
-                 if (sfile.current != sfile.buffer)
+                 if (sfile.pos)
                    printf ("%s\n", sfile.buffer);
-                 free (sfile.buffer);
                  break;
                }
            }
@@ -1415,6 +1458,7 @@ disassemble_bytes (struct disassemble_info * info,
              for (j = addr_offset * opb; j < addr_offset * opb + pb; j += bpc)
                {
                  int k;
+
                  if (bpc > 1 && info->display_endian == BFD_ENDIAN_LITTLE)
                    {
                      for (k = bpc - 1; k >= 0; k--)
@@ -1447,11 +1491,8 @@ disassemble_bytes (struct disassemble_info * info,
 
          if (! insns)
            printf ("%s", buf);
-         else
-           {
-             printf ("%s", sfile.buffer);
-             free (sfile.buffer);
-           }
+         else if (sfile.pos)
+           printf ("%s", sfile.buffer);
 
          if (prefix_addresses
              ? show_raw_insn > 0
@@ -1515,9 +1556,15 @@ disassemble_bytes (struct disassemble_info * info,
              else
                printf ("\t\t\t");
 
-             objdump_print_value (section->vma + q->address, info, TRUE);
+             objdump_print_value (section->vma - rel_offset + q->address,
+                                  info, TRUE);
 
-             printf (": %s\t", q->howto->name);
+             if (q->howto == NULL)
+               printf (": *unknown*\t");
+             else if (q->howto->name)
+               printf (": %s\t", q->howto->name);
+             else
+               printf (": %d\t", q->howto->type);
 
              if (q->sym_ptr_ptr == NULL || *q->sym_ptr_ptr == NULL)
                printf ("*unknown*");
@@ -1557,6 +1604,8 @@ disassemble_bytes (struct disassemble_info * info,
 
       addr_offset += octets / opb;
     }
+
+  free (sfile.buffer);
 }
 
 static void
@@ -1581,13 +1630,14 @@ disassemble_section (bfd *abfd, asection *section, void *info)
      code are not normally disassembled.  */
   if (! disassemble_all
       && only == NULL
-      && (section->flags & SEC_CODE) == 0)
+      && ((section->flags & (SEC_CODE | SEC_HAS_CONTENTS))
+         != (SEC_CODE | SEC_HAS_CONTENTS)))
     return;
 
   if (! process_section_p (section))
     return;
 
-  datasize = bfd_get_section_size_before_reloc (section);
+  datasize = bfd_get_section_size (section);
   if (datasize == 0)
     return;
 
@@ -1600,7 +1650,7 @@ disassemble_section (bfd *abfd, asection *section, void *info)
       /* Dynamic reloc addresses are absolute, non-dynamic are section
         relative.  REL_OFFSET specifies the reloc address corresponding
         to the start of this section.  */
-      rel_offset = pinfo->buffer_vma;
+      rel_offset = section->vma;
     }
   else
     {
@@ -1609,10 +1659,7 @@ disassemble_section (bfd *abfd, asection *section, void *info)
       rel_offset = 0;
 
       if ((section->flags & SEC_RELOC) != 0
-#ifndef DISASSEMBLER_NEEDS_RELOCS
-         && dump_reloc_info
-#endif
-         )
+         && (dump_reloc_info || pinfo->disassembler_needs_relocs))
        {
          long relsize;
 
@@ -1701,11 +1748,13 @@ disassemble_section (bfd *abfd, asection *section, void *info)
 
          pinfo->symbols = sorted_syms + place;
          pinfo->num_symbols = x - place;
+         pinfo->symtab_pos = place;
        }
       else
        {
          pinfo->symbols = NULL;
          pinfo->num_symbols = 0;
+         pinfo->symtab_pos = -1;
        }
 
       if (! prefix_addresses)
@@ -1788,6 +1837,7 @@ disassemble_data (bfd *abfd)
 {
   struct disassemble_info disasm_info;
   struct objdump_disasm_info aux;
+  long i;
 
   print_files = NULL;
   prev_functionname = NULL;
@@ -1795,10 +1845,18 @@ disassemble_data (bfd *abfd)
 
   /* We make a copy of syms to sort.  We don't want to sort syms
      because that will screw up the relocs.  */
-  sorted_syms = xmalloc (symcount * sizeof (asymbol *));
-  memcpy (sorted_syms, syms, symcount * sizeof (asymbol *));
+  sorted_symcount = symcount ? symcount : dynsymcount;
+  sorted_syms = xmalloc ((sorted_symcount + synthcount) * sizeof (asymbol *));
+  memcpy (sorted_syms, symcount ? syms : dynsyms,
+         sorted_symcount * sizeof (asymbol *));
 
-  sorted_symcount = remove_useless_symbols (sorted_syms, symcount);
+  sorted_symcount = remove_useless_symbols (sorted_syms, sorted_symcount);
+
+  for (i = 0; i < synthcount; ++i)
+    {
+      sorted_syms[sorted_symcount] = synthsyms + i;
+      ++sorted_symcount;
+    }
 
   /* Sort the symbols into section and symbol order.  */
   qsort (sorted_syms, sorted_symcount, sizeof (asymbol *), compare_symbols);
@@ -1810,6 +1868,7 @@ disassemble_data (bfd *abfd)
   aux.require_sec = FALSE;
   aux.dynrelbuf = NULL;
   aux.dynrelcount = 0;
+  aux.reloc = NULL;
 
   disasm_info.print_address_func = objdump_print_address;
   disasm_info.symbol_at_address_func = objdump_symbol_at_address;
@@ -1849,6 +1908,9 @@ disassemble_data (bfd *abfd)
   disasm_info.mach = bfd_get_mach (abfd);
   disasm_info.disassembler_options = disassembler_options;
   disasm_info.octets_per_byte = bfd_octets_per_byte (abfd);
+  disasm_info.skip_zeroes = DEFAULT_SKIP_ZEROES;
+  disasm_info.skip_zeroes_at_end = DEFAULT_SKIP_ZEROES_AT_END;
+  disasm_info.disassembler_needs_relocs = FALSE;
 
   if (bfd_big_endian (abfd))
     disasm_info.display_endian = disasm_info.endian = BFD_ENDIAN_BIG;
@@ -1885,6 +1947,8 @@ disassemble_data (bfd *abfd)
                 compare_relocs);
        }
     }
+  disasm_info.symtab = sorted_syms;
+  disasm_info.symtab_size = sorted_symcount;
 
   bfd_map_over_sections (abfd, disassemble_section, & disasm_info);
 
@@ -1893,6 +1957,163 @@ disassemble_data (bfd *abfd)
   free (sorted_syms);
 }
 \f
+int
+load_debug_section (enum dwarf_section_display_enum debug, void *file)
+{
+  struct dwarf_section *section = &debug_displays [debug].section;
+  bfd *abfd = file;
+  asection *sec;
+  bfd_boolean ret;
+
+  /* If it is already loaded, do nothing.  */
+  if (section->start != NULL)
+    return 1;
+
+  /* Locate the debug section.  */
+  sec = bfd_get_section_by_name (abfd, section->name);
+  if (sec == NULL)
+    return 0;
+
+  section->address = bfd_get_section_vma (abfd, sec);
+  section->size = bfd_get_section_size (sec);
+  section->start = xmalloc (section->size);
+
+  if (is_relocatable && debug_displays [debug].relocate)
+    ret = bfd_simple_get_relocated_section_contents (abfd,
+                                                    sec,
+                                                    section->start,
+                                                    syms) != NULL;
+  else
+    ret = bfd_get_section_contents (abfd, sec, section->start, 0,
+                                   section->size);
+
+  if (!ret)
+    {
+      free_debug_section (debug);
+      printf (_("\nCan't get contents for section '%s'.\n"),
+             section->name);
+    }
+
+  return ret;
+}
+
+void
+free_debug_section (enum dwarf_section_display_enum debug)
+{
+  struct dwarf_section *section = &debug_displays [debug].section;
+
+  if (section->start == NULL)
+    return;
+
+  free ((char *) section->start);
+  section->start = NULL;
+  section->address = 0;
+  section->size = 0;
+}
+
+static void
+dump_dwarf_section (bfd *abfd, asection *section,
+                   void *arg ATTRIBUTE_UNUSED)
+{
+  const char *name = bfd_get_section_name (abfd, section);
+  const char *match;
+  enum dwarf_section_display_enum i;
+
+  if (CONST_STRNEQ (name, ".gnu.linkonce.wi."))
+    match = ".debug_info";
+  else
+    match = name;
+
+  for (i = 0; i < max; i++)
+    if (strcmp (debug_displays[i].section.name, match) == 0)
+      {
+       if (!debug_displays[i].eh_frame)
+         {
+           struct dwarf_section *sec = &debug_displays [i].section;
+
+           if (load_debug_section (i, abfd))
+             {
+               debug_displays[i].display (sec, abfd);
+
+               if (i != info && i != abbrev)
+                 free_debug_section (i);
+             }
+         }
+       break;
+      }
+}
+
+static const char *mach_o_dwarf_sections [] = {
+  "LC_SEGMENT.__DWARFA.__debug_abbrev",                /* .debug_abbrev */
+  "LC_SEGMENT.__DWARFA.__debug_aranges",       /* .debug_aranges */
+  "LC_SEGMENT.__DWARFA.__debug_frame",         /* .debug_frame */
+  "LC_SEGMENT.__DWARFA.__debug_info",          /* .debug_info */
+  "LC_SEGMENT.__DWARFA.__debug_line",          /* .debug_line */
+  "LC_SEGMENT.__DWARFA.__debug_pubnames",      /* .debug_pubnames */
+  ".eh_frame",                                 /* .eh_frame */
+  "LC_SEGMENT.__DWARFA.__debug_macinfo",       /* .debug_macinfo */
+  "LC_SEGMENT.__DWARFA.__debug_str",           /* .debug_str */
+  "LC_SEGMENT.__DWARFA.__debug_loc",           /* .debug_loc */
+  "LC_SEGMENT.__DWARFA.__debug_pubtypes",      /* .debug_pubtypes */
+  "LC_SEGMENT.__DWARFA.__debug_ranges",                /* .debug_ranges */
+  "LC_SEGMENT.__DWARFA.__debug_static_func",   /* .debug_static_func */
+  "LC_SEGMENT.__DWARFA.__debug_static_vars",   /* .debug_static_vars */
+  "LC_SEGMENT.__DWARFA.__debug_types",         /* .debug_types */
+  "LC_SEGMENT.__DWARFA.__debug_weaknames"      /* .debug_weaknames */
+};
+
+static const char *generic_dwarf_sections [max];
+
+static void
+check_mach_o_dwarf (bfd *abfd)
+{
+  static enum bfd_flavour old_flavour = bfd_target_unknown_flavour;
+  enum bfd_flavour current_flavour = bfd_get_flavour (abfd);
+  enum dwarf_section_display_enum i;
+
+  if (generic_dwarf_sections [0] == NULL)
+    for (i = 0; i < max; i++)
+      generic_dwarf_sections [i] = debug_displays[i].section.name;
+
+  if (old_flavour != current_flavour)
+    {
+      if (current_flavour == bfd_target_mach_o_flavour)
+       for (i = 0; i < max; i++)
+         debug_displays[i].section.name = mach_o_dwarf_sections [i];
+      else if (old_flavour == bfd_target_mach_o_flavour)
+       for (i = 0; i < max; i++)
+         debug_displays[i].section.name = generic_dwarf_sections [i];
+
+      old_flavour = current_flavour;
+    }
+}
+
+/* Dump the dwarf debugging information.  */
+
+static void
+dump_dwarf (bfd *abfd)
+{
+  is_relocatable = ((abfd->flags & (HAS_RELOC | EXEC_P | DYNAMIC))
+                   == HAS_RELOC);
+
+  /* FIXME: bfd_get_arch_size may return -1.  We assume that 64bit
+     targets will return 64.  */
+  eh_addr_size = bfd_get_arch_size (abfd) == 64 ? 8 : 4;
+
+  if (bfd_big_endian (abfd))
+    byte_get = byte_get_big_endian;
+  else if (bfd_little_endian (abfd))
+    byte_get = byte_get_little_endian;
+  else
+    abort ();
+
+  check_mach_o_dwarf (abfd);
+
+  bfd_map_over_sections (abfd, dump_dwarf_section, NULL);
+
+  free_debug_memory ();
+}
+\f
 /* Read ABFD's stabs section STABSECT_NAME, and return a pointer to
    it.  Return NULL on failure.   */
 
@@ -2047,7 +2268,8 @@ find_stabs_section (bfd *abfd, asection *section, void *names)
       
       if (strtab)
        {
-         stabs = read_section_stabs (abfd, section->name, &stab_size);
+         stabs = (bfd_byte *) read_section_stabs (abfd, section->name,
+                                                  &stab_size);
          if (stabs)
            print_section_stabs (abfd, section->name, &sought->string_offset);
        }
@@ -2274,13 +2496,15 @@ dump_symbols (bfd *abfd ATTRIBUTE_UNUSED, bfd_boolean dynamic)
       bfd *cur_bfd;
 
       if (*current == NULL)
-       printf (_("no information for the %ld'th symbol"), count);
+       printf (_("no information for symbol number %ld\n"), count);
 
       else if ((cur_bfd = bfd_asymbol_bfd (*current)) == NULL)
-       printf (_("could not determine the type of the %ld'th symbol"),
+       printf (_("could not determine the type of symbol number %ld\n"),
                count);
 
-      else
+      else if (process_section_p ((* current)->section)
+              && (dump_special_syms
+                  || !bfd_is_target_special_symbol (cur_bfd, *current)))
        {
          const char *name = (*current)->name;
 
@@ -2301,9 +2525,9 @@ dump_symbols (bfd *abfd ATTRIBUTE_UNUSED, bfd_boolean dynamic)
          else
            bfd_print_symbol (cur_bfd, stdout, *current,
                              bfd_print_symbol_all);
+         printf ("\n");
        }
 
-      printf ("\n");
       current++;
     }
   printf ("\n\n");
@@ -2392,23 +2616,20 @@ dump_reloc_set (bfd *abfd, asection *sec, arelent **relpp, long relcount)
          section_name = NULL;
        }
 
+      bfd_printf_vma (abfd, q->address);
+      if (q->howto == NULL)
+       printf (" *unknown*         ");
+      else if (q->howto->name)
+       printf (" %-16s  ", q->howto->name);
+      else
+       printf (" %-16d  ", q->howto->type);
       if (sym_name)
-       {
-         bfd_printf_vma (abfd, q->address);
-         if (q->howto->name)
-           printf (" %-16s  ", q->howto->name);
-         else
-           printf (" %-16d  ", q->howto->type);
-         objdump_print_symname (abfd, NULL, *q->sym_ptr_ptr);
-       }
+       objdump_print_symname (abfd, NULL, *q->sym_ptr_ptr);
       else
        {
          if (section_name == NULL)
            section_name = "*unknown*";
-         bfd_printf_vma (abfd, q->address);
-         printf (" %-16s  [%s]",
-                 q->howto->name,
-                 section_name);
+         printf ("[%s]", section_name);
        }
 
       if (q->addend)
@@ -2525,10 +2746,15 @@ add_include_path (const char *path)
 static void
 adjust_addresses (bfd *abfd ATTRIBUTE_UNUSED,
                  asection *section,
-                 void *dummy ATTRIBUTE_UNUSED)
+                 void *arg)
 {
-  section->vma += adjust_section_vma;
-  section->lma += adjust_section_vma;
+  if ((section->flags & SEC_DEBUGGING) == 0)
+    {
+      bfd_boolean *has_reloc_p = (bfd_boolean *) arg;
+      section->vma += adjust_section_vma;
+      if (*has_reloc_p)
+       section->lma += adjust_section_vma;
+    }
 }
 
 /* Dump selected contents of ABFD.  */
@@ -2540,7 +2766,10 @@ dump_bfd (bfd *abfd)
      the BFD information is a hack.  However, we must do it, or
      bfd_find_nearest_line will not do the right thing.  */
   if (adjust_section_vma != 0)
-    bfd_map_over_sections (abfd, adjust_addresses, NULL);
+    {
+      bfd_boolean has_reloc = (abfd->flags & HAS_RELOC);
+      bfd_map_over_sections (abfd, adjust_addresses, &has_reloc);
+    }
 
   if (! dump_debugging_tags)
     printf (_("\n%s:     file format %s\n"), bfd_get_filename (abfd),
@@ -2556,15 +2785,29 @@ dump_bfd (bfd *abfd)
   if (dump_section_headers)
     dump_headers (abfd);
 
-  if (dump_symtab || dump_reloc_info || disassemble || dump_debugging)
+  if (dump_symtab
+      || dump_reloc_info
+      || disassemble
+      || dump_debugging
+      || dump_dwarf_section_info)
     syms = slurp_symtab (abfd);
-  if (dump_dynamic_symtab || dump_dynamic_reloc_info)
+  if (dump_dynamic_symtab || dump_dynamic_reloc_info
+      || (disassemble && bfd_get_dynamic_symtab_upper_bound (abfd) > 0))
     dynsyms = slurp_dynamic_symtab (abfd);
+  if (disassemble)
+    {
+      synthcount = bfd_get_synthetic_symtab (abfd, symcount, syms,
+                                            dynsymcount, dynsyms, &synthsyms);
+      if (synthcount < 0)
+       synthcount = 0;
+    }
 
   if (dump_symtab)
     dump_symbols (abfd, FALSE);
   if (dump_dynamic_symtab)
     dump_symbols (abfd, TRUE);
+  if (dump_dwarf_section_info)
+    dump_dwarf (abfd);
   if (dump_stab_section_info)
     dump_stabs (abfd);
   if (dump_reloc_info && ! disassemble)
@@ -2604,6 +2847,16 @@ dump_bfd (bfd *abfd)
       free (dynsyms);
       dynsyms = NULL;
     }
+
+  if (synthsyms)
+    {
+      free (synthsyms);
+      synthsyms = NULL;
+    }
+
+  symcount = 0;
+  dynsymcount = 0;
+  synthcount = 0;
 }
 
 static void
@@ -2653,7 +2906,10 @@ display_file (char *filename, char *target)
   bfd *arfile = NULL;
 
   if (get_file_size (filename) < 1)
-    return;
+    {
+      exit_status = 1;
+      return;
+    }
 
   file = bfd_openr (filename, target);
   if (file == NULL)
@@ -2718,10 +2974,12 @@ main (int argc, char **argv)
 
   START_PROGRESS (program_name, 0);
 
+  expandargv (&argc, &argv);
+
   bfd_init ();
   set_default_bfd_target ();
 
-  while ((c = getopt_long (argc, argv, "pib:m:M:VvCdDlfaHhrRtTxsSI:j:wE:zgeG",
+  while ((c = getopt_long (argc, argv, "pib:m:M:VvCdDlfaHhrRtTxsSI:j:wE:zgeGW",
                           long_options, (int *) 0))
         != EOF)
     {
@@ -2862,6 +3120,20 @@ main (int argc, char **argv)
          do_demangle = TRUE;
          seenflag = TRUE;
          break;
+       case 'W':
+         dump_dwarf_section_info = TRUE;
+         seenflag = TRUE;
+         do_debug_info = 1;
+         do_debug_abbrevs = 1;
+         do_debug_lines = 1;
+         do_debug_pubnames = 1;
+         do_debug_aranges = 1;
+         do_debug_ranges = 1;
+         do_debug_frames = 1;
+         do_debug_macinfo = 1;
+         do_debug_str = 1;
+         do_debug_loc = 1;
+         break;
        case 'G':
          dump_stab_section_info = TRUE;
          seenflag = TRUE;
This page took 0.041937 seconds and 4 git commands to generate.