* sysdep.h: Include sys/stat.h here.
[deliverable/binutils-gdb.git] / binutils / objdump.c
index c672f15c660f0fef3b63d81333fa4a133931a3f0..76ca2db726e0beadd82c36e18a0ddfca0ae7cc26 100644 (file)
@@ -1,7 +1,7 @@
 /* objdump.c -- dump information about an object file.
    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
-   Free Software Foundation, Inc.
+   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,
+   2012 Free Software Foundation, Inc.
 
    This file is part of GNU Binutils.
 
@@ -55,6 +55,7 @@
 #include "elf-bfd.h"
 #include "progress.h"
 #include "bucomm.h"
+#include "elfcomm.h"
 #include "dwarf.h"
 #include "getopt.h"
 #include "safe-ctype.h"
 #include "filenames.h"
 #include "debug.h"
 #include "budbg.h"
+#include "objdump.h"
 
 #ifdef HAVE_MMAP
 #include <sys/mman.h>
 #endif
 
-#include <sys/stat.h>
-
 /* Internal headers for the ELF .stab-dump code - sorry.  */
 #define        BYTES_IN_WORD   32
 #include "aout/aout64.h"
@@ -92,6 +92,7 @@ static int dump_reloc_info;           /* -r */
 static int dump_dynamic_reloc_info;    /* -R */
 static int dump_ar_hdrs;               /* -a */
 static int dump_private_headers;       /* -p */
+static char *dump_private_options;     /* -P */
 static int prefix_addresses;           /* --prefix-addresses */
 static int with_line_numbers;          /* -l */
 static bfd_boolean with_source_code;   /* -S */
@@ -109,6 +110,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 suppress_bfd_header;
 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 */
@@ -183,6 +185,13 @@ static char *strtab;
 static bfd_size_type stabstr_size;
 
 static bfd_boolean is_relocatable = FALSE;
+
+/* Handlers for -P/--private.  */
+static const struct objdump_private_desc * const objdump_private_vectors[] =
+  {
+    OBJDUMP_PRIVATE_VECTORS
+    NULL
+  };
 \f
 static void
 usage (FILE *stream, int status)
@@ -194,6 +203,7 @@ usage (FILE *stream, int status)
   -a, --archive-headers    Display archive header information\n\
   -f, --file-headers       Display the contents of the overall file header\n\
   -p, --private-headers    Display object format specific file header contents\n\
+  -P, --private=OPT,OPT... Display object format specific contents\n\
   -h, --[section-]headers  Display the contents of the section headers\n\
   -x, --all-headers        Display the contents of all headers\n\
   -d, --disassemble        Display assembler contents of executable sections\n\
@@ -206,7 +216,7 @@ usage (FILE *stream, int status)
   -W[lLiaprmfFsoRt] or\n\
   --dwarf[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,\n\
           =frames-interp,=str,=loc,=Ranges,=pubtypes,\n\
-          =trace_info,=trace_abbrev,=trace_aranges]\n\
+          =gdb_index,=trace_info,=trace_abbrev,=trace_aranges]\n\
                            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\
@@ -219,6 +229,8 @@ usage (FILE *stream, int status)
 "));
   if (status != 2)
     {
+      const struct objdump_private_desc * const *desc;
+
       fprintf (stream, _("\n The following switches are optional:\n"));
       fprintf (stream, _("\
   -b, --target=BFDNAME           Specify the target object format as BFDNAME\n\
@@ -241,16 +253,27 @@ usage (FILE *stream, int status)
       --stop-address=ADDR        Only process data whose address is <= ADDR\n\
       --prefix-addresses         Print complete address alongside disassembly\n\
       --[no-]show-raw-insn       Display hex alongside symbolic disassembly\n\
-      --insn-width=WIDTH         Display WIDTH bytes on a signle line for -d\n\
+      --insn-width=WIDTH         Display WIDTH bytes on a single line for -d\n\
       --adjust-vma=OFFSET        Add OFFSET to all displayed section addresses\n\
       --special-syms             Include special symbols in symbol dumps\n\
       --prefix=PREFIX            Add PREFIX to absolute paths for -S\n\
-      --prefix-strip=LEVEL       Strip initial directory names for -S\n\
-\n"));
+      --prefix-strip=LEVEL       Strip initial directory names for -S\n"));
+      fprintf (stream, _("\
+      --dwarf-depth=N        Do not display DIEs at depth N or greater\n\
+      --dwarf-start=N        Display DIEs starting with N, at the same depth\n\
+                             or deeper\n\n"));
       list_supported_targets (program_name, stream);
       list_supported_architectures (program_name, stream);
 
       disassembler_usage (stream);
+
+      if (objdump_private_vectors[0] != NULL)
+        {
+          fprintf (stream,
+                   _("\nOptions supported for -P/--private switch:\n"));
+          for (desc = objdump_private_vectors; *desc != NULL; desc++)
+            (*desc)->help (stream);
+        }
     }
   if (REPORT_BUGS_TO[0] && status == 0)
     fprintf (stream, _("Report bugs to %s.\n"), REPORT_BUGS_TO);
@@ -267,7 +290,9 @@ enum option_values
     OPTION_PREFIX,
     OPTION_PREFIX_STRIP,
     OPTION_INSN_WIDTH,
-    OPTION_ADJUST_VMA
+    OPTION_ADJUST_VMA,
+    OPTION_DWARF_DEPTH,
+    OPTION_DWARF_START
   };
 
 static struct option long_options[]=
@@ -275,6 +300,7 @@ static struct option long_options[]=
   {"adjust-vma", required_argument, NULL, OPTION_ADJUST_VMA},
   {"all-headers", no_argument, NULL, 'x'},
   {"private-headers", no_argument, NULL, 'p'},
+  {"private", required_argument, NULL, 'P'},
   {"architecture", required_argument, NULL, 'm'},
   {"archive-headers", no_argument, NULL, 'a'},
   {"debugging", no_argument, NULL, 'g'},
@@ -315,6 +341,8 @@ static struct option long_options[]=
   {"prefix", required_argument, NULL, OPTION_PREFIX},
   {"prefix-strip", required_argument, NULL, OPTION_PREFIX_STRIP},
   {"insn-width", required_argument, NULL, OPTION_INSN_WIDTH},
+  {"dwarf-depth",      required_argument, 0, OPTION_DWARF_DEPTH},
+  {"dwarf-start",      required_argument, 0, OPTION_DWARF_START},
   {0, no_argument, 0, 0}
 };
 \f
@@ -511,8 +539,6 @@ dump_headers (bfd *abfd)
 
   if (wide_output)
     printf (_("  Flags"));
-  if (abfd->flags & HAS_LOAD_PAGE)
-    printf (_("  Pg"));
   printf ("\n");
 
   bfd_map_over_sections (abfd, dump_section_header, NULL);
@@ -1349,7 +1375,7 @@ show_line (bfd *abfd, asection *section, bfd_vma addr_offset)
       unsigned l;
 
       for (pp = &print_files; *pp != NULL; pp = &(*pp)->next)
-       if (strcmp ((*pp)->filename, filename) == 0)
+       if (filename_cmp ((*pp)->filename, filename) == 0)
          break;
       p = *pp;
 
@@ -2588,6 +2614,57 @@ dump_bfd_private_header (bfd *abfd)
   bfd_print_private_bfd_data (abfd, stdout);
 }
 
+static void
+dump_target_specific (bfd *abfd)
+{
+  const struct objdump_private_desc * const *desc;
+  struct objdump_private_option *opt;
+  char *e, *b;
+
+  /* Find the desc.  */
+  for (desc = objdump_private_vectors; *desc != NULL; desc++)
+    if ((*desc)->filter (abfd))
+      break;
+
+  if (desc == NULL)
+    {
+      non_fatal (_("option -P/--private not supported by this file"));
+      return;
+    }
+
+  /* Clear all options.  */
+  for (opt = (*desc)->options; opt->name; opt++)
+    opt->selected = FALSE;
+
+  /* Decode options.  */
+  b = dump_private_options;
+  do
+    {
+      e = strchr (b, ',');
+
+      if (e)
+        *e = 0;
+
+      for (opt = (*desc)->options; opt->name; opt++)
+        if (strcmp (opt->name, b) == 0)
+          {
+            opt->selected = TRUE;
+            break;
+          }
+      if (opt->name == NULL)
+        non_fatal (_("target specific dump '%s' not supported"), b);
+
+      if (e)
+        {
+          *e = ',';
+          b = e + 1;
+        }
+    }
+  while (e != NULL);
+
+  /* Dump.  */
+  (*desc)->dump (abfd);
+}
 \f
 /* Display a section in hexadecimal format with associated characters.
    Each line prefixed by the zero padded address.  */
@@ -2830,6 +2907,7 @@ dump_reloc_set (bfd *abfd, asection *sec, arelent **relpp, long relcount)
       unsigned int linenumber;
       const char *sym_name;
       const char *section_name;
+      bfd_vma addend2 = 0;
 
       if (start_address != (bfd_vma) -1
          && q->address < start_address)
@@ -2857,7 +2935,7 @@ dump_reloc_set (bfd *abfd, asection *sec, arelent **relpp, long relcount)
              && (linenumber != last_line
                  || (filename != NULL
                      && last_filename != NULL
-                     && strcmp (filename, last_filename) != 0)))
+                     && filename_cmp (filename, last_filename) != 0)))
            {
              printf ("%s:%u\n", filename == NULL ? "???" : filename, linenumber);
              last_line = linenumber;
@@ -2885,7 +2963,37 @@ dump_reloc_set (bfd *abfd, asection *sec, arelent **relpp, long relcount)
       if (q->howto == NULL)
        printf (" *unknown*         ");
       else if (q->howto->name)
-       printf (" %-16s  ", q->howto->name);
+       {
+         const char *name = q->howto->name;
+
+         /* R_SPARC_OLO10 relocations contain two addends.
+            But because 'arelent' lacks enough storage to
+            store them both, the 64-bit ELF Sparc backend
+            records this as two relocations.  One R_SPARC_LO10
+            and one R_SPARC_13, both pointing to the same
+            address.  This is merely so that we have some
+            place to store both addend fields.
+
+            Undo this transformation, otherwise the output
+            will be confusing.  */
+         if (abfd->xvec->flavour == bfd_target_elf_flavour
+             && elf_tdata(abfd)->elf_header->e_machine == EM_SPARCV9
+             && relcount > 1
+             && !strcmp (q->howto->name, "R_SPARC_LO10"))
+           {
+             arelent *q2 = *(p + 1);
+             if (q2 != NULL
+                 && q2->howto
+                 && q->address == q2->address
+                 && !strcmp (q2->howto->name, "R_SPARC_13"))
+               {
+                 name = "R_SPARC_OLO10";
+                 addend2 = q2->addend;
+                 p++;
+               }
+           }
+         printf (" %-16s  ", name);
+       }
       else
        printf (" %-16d  ", q->howto->type);
 
@@ -2905,9 +3013,19 @@ dump_reloc_set (bfd *abfd, asection *sec, arelent **relpp, long relcount)
          printf ("+0x");
          bfd_printf_vma (abfd, q->addend);
        }
+      if (addend2)
+       {
+         printf ("+0x");
+         bfd_printf_vma (abfd, addend2);
+       }
 
       printf ("\n");
     }
+
+  if (last_filename != NULL)
+    free (last_filename);
+  if (last_functionname != NULL)
+    free (last_functionname);
 }
 
 static void
@@ -3039,7 +3157,7 @@ dump_bfd (bfd *abfd)
       bfd_map_over_sections (abfd, adjust_addresses, &has_reloc);
     }
 
-  if (! dump_debugging_tags)
+  if (! dump_debugging_tags && ! suppress_bfd_header)
     printf (_("\n%s:     file format %s\n"), bfd_get_filename (abfd),
            abfd->xvec->name);
   if (dump_ar_hdrs)
@@ -3048,7 +3166,9 @@ dump_bfd (bfd *abfd)
     dump_bfd_header (abfd);
   if (dump_private_headers)
     dump_bfd_private_header (abfd);
-  if (! dump_debugging_tags)
+  if (dump_private_options != NULL)
+    dump_target_specific (abfd);
+  if (! dump_debugging_tags && ! suppress_bfd_header)
     putchar ('\n');
   if (dump_section_headers)
     dump_headers (abfd);
@@ -3135,7 +3255,7 @@ dump_bfd (bfd *abfd)
 }
 
 static void
-display_bfd (bfd *abfd)
+display_object_bfd (bfd *abfd)
 {
   char **matching;
 
@@ -3175,24 +3295,8 @@ display_bfd (bfd *abfd)
 }
 
 static void
-display_file (char *filename, char *target)
+display_any_bfd (bfd *file, int level)
 {
-  bfd *file;
-  bfd *arfile = NULL;
-
-  if (get_file_size (filename) < 1)
-    {
-      exit_status = 1;
-      return;
-    }
-
-  file = bfd_openr (filename, target);
-  if (file == NULL)
-    {
-      nonfatal (filename);
-      return;
-    }
-
   /* Decompress sections unless dumping the section contents.  */
   if (!dump_section_contents)
     file->flags |= BFD_DECOMPRESS;
@@ -3200,9 +3304,14 @@ display_file (char *filename, char *target)
   /* If the file is an archive, process all of its elements.  */
   if (bfd_check_format (file, bfd_archive))
     {
+      bfd *arfile = NULL;
       bfd *last_arfile = NULL;
 
-      printf (_("In archive %s:\n"), bfd_get_filename (file));
+      if (level == 0)
+        printf (_("In archive %s:\n"), bfd_get_filename (file));
+      else
+        printf (_("In nested archive %s:\n"), bfd_get_filename (file));
+
       for (;;)
        {
          bfd_set_error (bfd_error_no_error);
@@ -3215,7 +3324,7 @@ display_file (char *filename, char *target)
              break;
            }
 
-         display_bfd (arfile);
+         display_any_bfd (arfile, level + 1);
 
          if (last_arfile != NULL)
            bfd_close (last_arfile);
@@ -3226,7 +3335,28 @@ display_file (char *filename, char *target)
        bfd_close (last_arfile);
     }
   else
-    display_bfd (file);
+    display_object_bfd (file);
+}
+
+static void
+display_file (char *filename, char *target)
+{
+  bfd *file;
+
+  if (get_file_size (filename) < 1)
+    {
+      exit_status = 1;
+      return;
+    }
+
+  file = bfd_openr (filename, target);
+  if (file == NULL)
+    {
+      nonfatal (filename);
+      return;
+    }
+
+  display_any_bfd (file, 0);
 
   bfd_close (file);
 }
@@ -3259,7 +3389,7 @@ main (int argc, char **argv)
   set_default_bfd_target ();
 
   while ((c = getopt_long (argc, argv,
-                          "pib:m:M:VvCdDlfFaHhrRtTxsSI:j:wE:zgeGW::",
+                          "pP:ib:m:M:VvCdDlfFaHhrRtTxsSI:j:wE:zgeGW::",
                           long_options, (int *) 0))
         != EOF)
     {
@@ -3376,6 +3506,10 @@ main (int argc, char **argv)
          dump_private_headers = TRUE;
          seenflag = TRUE;
          break;
+       case 'P':
+         dump_private_options = optarg;
+         seenflag = TRUE;
+         break;
        case 'x':
          dump_private_headers = TRUE;
          dump_symtab = TRUE;
@@ -3436,6 +3570,19 @@ main (int argc, char **argv)
          else
            dwarf_select_sections_all ();
          break;
+       case OPTION_DWARF_DEPTH:
+         {
+           char *cp;
+           dwarf_cutoff_level = strtoul (optarg, & cp, 0);
+         }
+         break;
+       case OPTION_DWARF_START:
+         {
+           char *cp;
+           dwarf_start_die = strtoul (optarg, & cp, 0);
+           suppress_bfd_header = 1;
+         }
+         break;
        case 'G':
          dump_stab_section_info = TRUE;
          seenflag = TRUE;
This page took 0.034986 seconds and 4 git commands to generate.