* dwarf.c (display_debug_lines_raw): Include the name of the
authorNick Clifton <nickc@redhat.com>
Wed, 24 Jun 2009 10:37:35 +0000 (10:37 +0000)
committerNick Clifton <nickc@redhat.com>
Wed, 24 Jun 2009 10:37:35 +0000 (10:37 +0000)
        section in warning message.
        (struct debug_display): Enable reloc processing for .debug_line
        and .debug_ranges sections.

        * readelf.c: Add --relocated-dump command line option to dump the
        relocated contents of a specified section.
        (request_dump): New function.
        (parse_args): Use it.
        (dump_section_as_bytes): Add parameter to indicate whether the
        contents should be relocated.
        (target_specific_reloc_handling): Add code for a R_MN10300_16
        reloc found after a R_MN10300_SYM_DIFF reloc.
        (debug_apply_relocations): Rename to apply_relocations.
        (get_section_contents): New function.  Replaces common code found
        in dump_section_as_strings and dump_section_as_bytes.
        * doc/binutils.texi: Document new command line option.
        * NEWS: Mention the new feature.

binutils/ChangeLog
binutils/NEWS
binutils/doc/binutils.texi
binutils/dwarf.c
binutils/readelf.c

index acce3a8d1764e5720584774f1228e2a770abc627..c748a6a77ee6502738fb640df0fb88dbd91d9f36 100644 (file)
@@ -1,3 +1,24 @@
+2009-06-23  Nick Clifton  <nickc@redhat.com>
+
+       * dwarf.c (display_debug_lines_raw): Include the name of the
+       section in warning message.
+       (struct debug_display): Enable reloc processing for .debug_line
+       and .debug_ranges sections.
+
+       * readelf.c: Add --relocated-dump command line option to dump the
+       relocated contents of a specified section.
+       (request_dump): New function.
+       (parse_args): Use it.
+       (dump_section_as_bytes): Add parameter to indicate whether the
+       contents should be relocated.
+       (target_specific_reloc_handling): Add code for a R_MN10300_16
+       reloc found after a R_MN10300_SYM_DIFF reloc.
+       (debug_apply_relocations): Rename to apply_relocations.
+       (get_section_contents): New function.  Replaces common code found
+       in dump_section_as_strings and dump_section_as_bytes.
+       * doc/binutils.texi: Document new command line option.
+       * NEWS: Mention the new feature.
+
 2009-06-22  Nick Clifton  <nickc@redhat.com>
 
        * readelf.c (target_specific_reloc_handling): New function:
index 9a33f266ce5dec0f754dd933d42a5d255e863c19..2edef3c25c51f7aa6cfb9f7380002f53a0eacea0 100644 (file)
@@ -1,4 +1,7 @@
 -*- text -*-
+* Readelf can now display the relocated contents of a section as a sequence
+  of bytes via the --relocated-dump=<name|number> command line option.
+
 * The gprof program has been given a new command line option:
   --external-symbols-table=<filename> which reads in symbols from a specified
   file.
index d74b12b86b2a06ad0a796ad47501fac494ef81ea..2364f9c594994621822f3dec1ca04874a5edc419 100644 (file)
@@ -3844,6 +3844,7 @@ readelf [@option{-a}|@option{--all}]
         [@option{-D}|@option{--use-dynamic}]
         [@option{-x} <number or name>|@option{--hex-dump=}<number or name>]
         [@option{-p} <number or name>|@option{--string-dump=}<number or name>]
+        [@option{-R} <number or name>|@option{--relocated-dump=}<number or name>]
         [@option{-c}|@option{--archive-index}]
         [@option{-w[lLiaprmfFsoR]}|
          @option{--debug-dump}[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=frames-interp,=str,=loc,=Ranges]]
@@ -3966,10 +3967,18 @@ symbols section.
 
 @item -x <number or name>
 @itemx --hex-dump=<number or name>
-Displays the contents of the indicated section as a hexadecimal dump.
+Displays the contents of the indicated section as a hexadecimal bytes.
 A number identifies a particular section by index in the section table;
 any other string identifies all sections with that name in the object file.
 
+@item -R <number or name>
+@itemx --relocated-dump=<number or name>
+Displays the contents of the indicated section as a hexadecimal
+bytes.  A number identifies a particular section by index in the
+section table; any other string identifies all sections with that name
+in the object file.  The contents of the section will be relocated
+before they are displayed.
+
 @item -p <number or name>
 @itemx --string-dump=<number or name>
 Displays the contents of the indicated section as printable strings.
index b524d17930178493ab256dc0964fb70b415a2a39..1a01e009a5ea7fc73d69c2b6e8c24ce54723fcd6 100644 (file)
@@ -2145,7 +2145,8 @@ display_debug_lines_raw (struct dwarf_section *section,
       if (info.li_length + initial_length_size > section->size)
        {
          warn
-           (_("The line info appears to be corrupt - the section is too small\n"));
+           (_("The information in section %s appears to be corrupt - the section is too small\n"),
+            section->name);
          return 0;
        }
 
@@ -4872,7 +4873,7 @@ struct dwarf_section_display debug_displays[] =
   { { ".debug_info",           ".zdebug_info",         NULL,   NULL,   0,      0 },
     display_debug_info,                        &do_debug_info,         1,      0 },
   { { ".debug_line",           ".zdebug_line",         NULL,   NULL,   0,      0 },
-    display_debug_lines,               &do_debug_lines,        0,      0 },
+    display_debug_lines,               &do_debug_lines,        1,      0 },
   { { ".debug_pubnames",       ".zdebug_pubnames",     NULL,   NULL,   0,      0 },
     display_debug_pubnames,            &do_debug_pubnames,     0,      0 },
   { { ".eh_frame",             "",                     NULL,   NULL,   0,      0 },
@@ -4886,7 +4887,7 @@ struct dwarf_section_display debug_displays[] =
   { { ".debug_pubtypes",       ".zdebug_pubtypes",     NULL,   NULL,   0,      0 },
     display_debug_pubnames,            &do_debug_pubnames,     0,      0 },
   { { ".debug_ranges",         ".zdebug_ranges",       NULL,   NULL,   0,      0 },
-    display_debug_ranges,              &do_debug_ranges,       0,      0 },
+    display_debug_ranges,              &do_debug_ranges,       1,      0 },
   { { ".debug_static_func",    ".zdebug_static_func",  NULL,   NULL,   0,      0 },
     display_debug_not_supported,       NULL,                   0,      0 },
   { { ".debug_static_vars",    ".zdebug_static_vars",  NULL,   NULL,   0,      0 },
index 87c8119902020c8500c9ebd2519ed13f32fc0a09..ce739e684490debd126ce86aec3fb723848b96e4 100644 (file)
@@ -214,6 +214,7 @@ static struct group ** section_headers_groups;
 #define DISASS_DUMP    (1 << 1)        /* The -i command line switch.  */
 #define DEBUG_DUMP     (1 << 2)        /* The -w command line switch.  */
 #define STRING_DUMP     (1 << 3)       /* The -p command line switch.  */
+#define RELOC_DUMP      (1 << 4)       /* The -R command line switch.  */
 
 typedef unsigned char dump_type;
 
@@ -2844,11 +2845,12 @@ static struct option options[] =
   {"unwind",          no_argument, 0, 'u'},
   {"archive-index",    no_argument, 0, 'c'},
   {"hex-dump",        required_argument, 0, 'x'},
-  {"debug-dump",       optional_argument, 0, OPTION_DEBUG_DUMP},
+  {"relocated-dump",   required_argument, 0, 'R'},
   {"string-dump",      required_argument, 0, 'p'},
 #ifdef SUPPORT_DISASSEMBLY
   {"instruction-dump", required_argument, 0, 'i'},
 #endif
+  {"debug-dump",       optional_argument, 0, OPTION_DEBUG_DUMP},
 
   {"version",         no_argument, 0, 'v'},
   {"wide",            no_argument, 0, 'W'},
@@ -2885,6 +2887,8 @@ usage (FILE * stream)
                          Dump the contents of section <number|name> as bytes\n\
   -p --string-dump=<number|name>\n\
                          Dump the contents of section <number|name> as strings\n\
+  -R --relocated-dump=<number|name>\n\
+                         Dump the contents of section <number|name> as relocated bytes\n\
   -w[lLiaprmfFsoR] or\n\
   --debug-dump[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=str,=loc,=Ranges]\n\
                          Display the contents of DWARF2 debug sections\n"));
@@ -2961,6 +2965,22 @@ request_dump_byname (const char * section, dump_type type)
   dump_sects_byname = new_request;
 }
 
+static inline void
+request_dump (dump_type type)
+{
+  int section;
+  char * cp;
+
+  do_dump++;
+  section = strtoul (optarg, & cp, 0);
+
+  if (! *cp && section >= 0)
+    request_dump_bynumber (section, type);
+  else
+    request_dump_byname (optarg, type);
+}
+
+
 static void
 parse_args (int argc, char ** argv)
 {
@@ -2970,11 +2990,8 @@ parse_args (int argc, char ** argv)
     usage (stderr);
 
   while ((c = getopt_long
-         (argc, argv, "ADHINSVWacdeghi:lnp:rstuvw::x:", options, NULL)) != EOF)
+         (argc, argv, "ADHINR:SVWacdeghi:lnp:rstuvw::x:", options, NULL)) != EOF)
     {
-      char * cp;
-      int section;
-
       switch (c)
        {
        case 0:
@@ -3048,20 +3065,13 @@ parse_args (int argc, char ** argv)
          do_archive_index++;
          break;
        case 'x':
-         do_dump++;
-         section = strtoul (optarg, & cp, 0);
-         if (! *cp && section >= 0)
-           request_dump_bynumber (section, HEX_DUMP);
-         else
-           request_dump_byname (optarg, HEX_DUMP);
+         request_dump (HEX_DUMP);
          break;
        case 'p':
-         do_dump++;
-         section = strtoul (optarg, & cp, 0);
-         if (! *cp && section >= 0)
-           request_dump_bynumber (section, STRING_DUMP);
-         else
-           request_dump_byname (optarg, STRING_DUMP);
+         request_dump (STRING_DUMP);
+         break;
+       case 'R':
+         request_dump (RELOC_DUMP);
          break;
        case 'w':
          do_dump++;
@@ -3088,12 +3098,8 @@ parse_args (int argc, char ** argv)
          break;
 #ifdef SUPPORT_DISASSEMBLY
        case 'i':
-         do_dump++;
-         section = strtoul (optarg, & cp, 0);
-         if (! *cp && section >= 0)
-           request_dump_bynumber (section, DISASS_DUMP);
-         else
-           request_dump_byname (optarg, DISASS_DUMP);
+         request_dump (DISASS_DUMP);
+         break;
 #endif
        case 'v':
          print_version (program_name);
@@ -7759,190 +7765,57 @@ process_syminfo (FILE * file ATTRIBUTE_UNUSED)
   return 1;
 }
 
-#ifdef SUPPORT_DISASSEMBLY
-static int
-disassemble_section (Elf_Internal_Shdr * section, FILE * file)
-{
-  printf (_("\nAssembly dump of section %s\n"),
-         SECTION_NAME (section));
-
-  /* XXX -- to be done --- XXX */
-
-  return 1;
-}
-#endif
-
-static int
-dump_section_as_strings (Elf_Internal_Shdr * section, FILE * file)
-{
-  Elf_Internal_Shdr * relsec;
-  bfd_size_type num_bytes;
-  bfd_vma addr;
-  char * data;
-  char * end;
-  char * start;
-  char * name = SECTION_NAME (section);
-  bfd_boolean some_strings_shown;
-
-  num_bytes = section->sh_size;
-
-  if (num_bytes == 0 || section->sh_type == SHT_NOBITS)
-    {
-      printf (_("\nSection '%s' has no data to dump.\n"), name);
-      return 0;
-    }
-
-  addr = section->sh_addr;
-
-  start = get_data (NULL, file, section->sh_offset, 1, num_bytes,
-                   _("section data"));
-  if (!start)
-    return 0;
-
-  printf (_("\nString dump of section '%s':\n"), name);
-
-  /* If the section being dumped has relocations against it the user might
-     be expecting these relocations to have been applied.  Check for this
-     case and issue a warning message in order to avoid confusion.
-     FIXME: Maybe we ought to have an option that dumps a section with
-     relocs applied ?  */
-  for (relsec = section_headers;
-       relsec < section_headers + elf_header.e_shnum;
-       ++relsec)
-    {
-      if ((relsec->sh_type != SHT_RELA && relsec->sh_type != SHT_REL)
-         || relsec->sh_info >= elf_header.e_shnum
-         || section_headers + relsec->sh_info != section
-         || relsec->sh_size == 0
-         || relsec->sh_link >= elf_header.e_shnum)
-       continue;
-
-      printf (_("  Note: This section has relocations against it, but these have NOT been applied to this dump.\n"));
-      break;
-    }
-
-  data = start;
-  end  = start + num_bytes;
-  some_strings_shown = FALSE;
-
-  while (data < end)
-    {
-      while (!ISPRINT (* data))
-       if (++ data >= end)
-         break;
-
-      if (data < end)
-       {
-#ifndef __MSVCRT__
-         printf ("  [%6tx]  %s\n", data - start, data);
-#else
-         printf ("  [%6Ix]  %s\n", (size_t) (data - start), data);
-#endif
-         data += strlen (data);
-         some_strings_shown = TRUE;
-       }
-    }
-
-  if (! some_strings_shown)
-    printf (_("  No strings found in this section."));
-
-  free (start);
-
-  putchar ('\n');
-  return 1;
-}
-
+/* Check to see if the given reloc needs to be handled in a target specific
+   manner.  If so then process the reloc and return TRUE otherwise return
+   FALSE.  */
 
-static int
-dump_section_as_bytes (Elf_Internal_Shdr * section, FILE * file)
+static bfd_boolean
+target_specific_reloc_handling (Elf_Internal_Rela * reloc,
+                               unsigned char *     start,
+                               Elf_Internal_Sym *  symtab)
 {
-  Elf_Internal_Shdr * relsec;
-  bfd_size_type bytes;
-  bfd_vma addr;
-  unsigned char * data;
-  unsigned char * start;
-
-  bytes = section->sh_size;
-
-  if (bytes == 0 || section->sh_type == SHT_NOBITS)
-    {
-      printf (_("\nSection '%s' has no data to dump.\n"),
-             SECTION_NAME (section));
-      return 0;
-    }
-  else
-    printf (_("\nHex dump of section '%s':\n"), SECTION_NAME (section));
-
-  addr = section->sh_addr;
-
-  start = get_data (NULL, file, section->sh_offset, 1, bytes,
-                   _("section data"));
-  if (!start)
-    return 0;
-
-  /* If the section being dumped has relocations against it the user might
-     be expecting these relocations to have been applied.  Check for this
-     case and issue a warning message in order to avoid confusion.
-     FIXME: Maybe we ought to have an option that dumps a section with
-     relocs applied ?  */
-  for (relsec = section_headers;
-       relsec < section_headers + elf_header.e_shnum;
-       ++relsec)
-    {
-      if ((relsec->sh_type != SHT_RELA && relsec->sh_type != SHT_REL)
-         || relsec->sh_info >= elf_header.e_shnum
-         || section_headers + relsec->sh_info != section
-         || relsec->sh_size == 0
-         || relsec->sh_link >= elf_header.e_shnum)
-       continue;
-
-      printf (_(" NOTE: This section has relocations against it, but these have NOT been applied to this dump.\n"));
-      break;
-    }
-
-  data = start;
+  unsigned int reloc_type = get_reloc_type (reloc->r_info);
 
-  while (bytes)
+  switch (elf_header.e_machine)
     {
-      int j;
-      int k;
-      int lbytes;
-
-      lbytes = (bytes > 16 ? 16 : bytes);
-
-      printf ("  0x%8.8lx ", (unsigned long) addr);
-
-      for (j = 0; j < 16; j++)
-       {
-         if (j < lbytes)
-           printf ("%2.2x", data[j]);
-         else
-           printf ("  ");
+    case EM_MN10300:
+    case EM_CYGNUS_MN10300:
+      {
+       static Elf_Internal_Sym * saved_sym = NULL;
 
-         if ((j & 3) == 3)
-           printf (" ");
-       }
+       switch (reloc_type)
+         {
+         case 34: /* R_MN10300_ALIGN */
+           return TRUE;
+         case 33: /* R_MN10300_SYM_DIFF */
+           saved_sym = symtab + get_reloc_symindex (reloc->r_info);
+           return TRUE;
+         case 1: /* R_MN10300_32 */
+         case 2: /* R_MN10300_16 */
+           if (saved_sym != NULL)
+             {
+               bfd_vma value;
 
-      for (j = 0; j < lbytes; j++)
-       {
-         k = data[j];
-         if (k >= ' ' && k < 0x7f)
-           printf ("%c", k);
-         else
-           printf (".");
-       }
+               value = reloc->r_addend
+                 + (symtab[get_reloc_symindex (reloc->r_info)].st_value
+                    - saved_sym->st_value);
 
-      putchar ('\n');
+               byte_put (start + reloc->r_offset, value, reloc_type == 1 ? 4 : 2);
 
-      data  += lbytes;
-      addr  += lbytes;
-      bytes -= lbytes;
+               saved_sym = NULL;
+               return TRUE;
+             }
+           break;
+         default:
+           if (saved_sym != NULL)
+             error (_("Unhandled MN10300 reloc type found after SYM_DIFF reloc"));
+           break;
+         }
+       break;
+      }
     }
 
-  free (start);
-
-  putchar ('\n');
-  return 1;
+  return FALSE;
 }
 
 /* Returns TRUE iff RELOC_TYPE is a 32-bit absolute RELA relocation used in
@@ -8130,8 +8003,8 @@ is_32bit_pcrel_reloc (unsigned int reloc_type)
       /* Do not abort or issue an error message here.  Not all targets use
         pc-relative 32-bit relocs in their DWARF debug information and we
         have already tested for target coverage in is_32bit_abs_reloc.  A
-        more helpful warning message will be generated by
-        debug_apply_relocations anyway, so just return.  */
+        more helpful warning message will be generated by apply_relocations
+        anyway, so just return.  */
       return FALSE;
     }
 }
@@ -8265,141 +8138,23 @@ is_none_reloc (unsigned int reloc_type)
   return FALSE;
 }
 
-/* Uncompresses a section that was compressed using zlib, in place.
-   This is a copy of bfd_uncompress_section_contents, in bfd/compress.c  */
+/* Apply relocations to a section.
+   Note: So far support has been added only for those relocations
+   which can be found in debug sections.
+   FIXME: Add support for more relocations ?  */
 
-static int
-uncompress_section_contents (unsigned char ** buffer, dwarf_size_type * size)
+static void
+apply_relocations (void * file,
+                  Elf_Internal_Shdr * section,
+                  unsigned char * start)
 {
-#ifndef HAVE_ZLIB_H
-  /* These are just to quiet gcc.  */
-  buffer = 0;
-  size = 0;
-  return FALSE;
-#else
-  dwarf_size_type compressed_size = *size;
-  unsigned char * compressed_buffer = *buffer;
-  dwarf_size_type uncompressed_size;
-  unsigned char * uncompressed_buffer;
-  z_stream strm;
-  int rc;
-  dwarf_size_type header_size = 12;
-
-  /* Read the zlib header.  In this case, it should be "ZLIB" followed
-     by the uncompressed section size, 8 bytes in big-endian order.  */
-  if (compressed_size < header_size
-      || ! streq ((char *) compressed_buffer, "ZLIB"))
-    return 0;
+  Elf_Internal_Shdr * relsec;
+  unsigned char * end = start + section->sh_size;
 
-  uncompressed_size = compressed_buffer[4]; uncompressed_size <<= 8;
-  uncompressed_size += compressed_buffer[5]; uncompressed_size <<= 8;
-  uncompressed_size += compressed_buffer[6]; uncompressed_size <<= 8;
-  uncompressed_size += compressed_buffer[7]; uncompressed_size <<= 8;
-  uncompressed_size += compressed_buffer[8]; uncompressed_size <<= 8;
-  uncompressed_size += compressed_buffer[9]; uncompressed_size <<= 8;
-  uncompressed_size += compressed_buffer[10]; uncompressed_size <<= 8;
-  uncompressed_size += compressed_buffer[11];
+  if (elf_header.e_type != ET_REL)
+    return;
 
-  /* It is possible the section consists of several compressed
-     buffers concatenated together, so we uncompress in a loop.  */
-  strm.zalloc = NULL;
-  strm.zfree = NULL;
-  strm.opaque = NULL;
-  strm.avail_in = compressed_size - header_size;
-  strm.next_in = (Bytef *) compressed_buffer + header_size;
-  strm.avail_out = uncompressed_size;
-  uncompressed_buffer = xmalloc (uncompressed_size);
-
-  rc = inflateInit (& strm);
-  while (strm.avail_in > 0)
-    {
-      if (rc != Z_OK)
-        goto fail;
-      strm.next_out = ((Bytef *) uncompressed_buffer
-                       + (uncompressed_size - strm.avail_out));
-      rc = inflate (&strm, Z_FINISH);
-      if (rc != Z_STREAM_END)
-        goto fail;
-      rc = inflateReset (& strm);
-    }
-  rc = inflateEnd (& strm);
-  if (rc != Z_OK
-      || strm.avail_out != 0)
-    goto fail;
-
-  free (compressed_buffer);
-  *buffer = uncompressed_buffer;
-  *size = uncompressed_size;
-  return 1;
-
- fail:
-  free (uncompressed_buffer);
-  return 0;
-#endif  /* HAVE_ZLIB_H */
-}
-
-/* Check to see if the given reloc needs to be handled in a target specific
-   manner.  If so then process the reloc and return TRUE otherwise return
-   FALSE.  */
-
-static bfd_boolean
-target_specific_reloc_handling (Elf_Internal_Rela * reloc,
-                               unsigned char *     start,
-                               Elf_Internal_Sym *  symtab)
-{
-  unsigned int reloc_type = get_reloc_type (reloc->r_info);
-
-  switch (elf_header.e_machine)
-    {
-    case EM_MN10300:
-    case EM_CYGNUS_MN10300:
-      {
-       static Elf_Internal_Sym * saved_sym = NULL;
-
-       switch (reloc_type)
-         {
-         case 34: /* R_MN10300_ALIGN */
-           return TRUE;
-         case 33: /* R_MN10300_SYM_DIFF */
-           saved_sym = symtab + get_reloc_symindex (reloc->r_info);
-           return TRUE;
-         case 1: /* R_MN10300_32 */
-           if (saved_sym != NULL)
-             {
-               bfd_vma value;
-
-               value = reloc->r_addend
-                 + (symtab[get_reloc_symindex (reloc->r_info)].st_value
-                    - saved_sym->st_value);
-
-               byte_put (start + reloc->r_offset, value, 4);
-
-               saved_sym = NULL;
-               return TRUE;
-             }
-           break;
-         }
-       break;
-      }
-    }
-
-  return FALSE;
-}
-
-/* Apply relocations to a debug section.  */
-
-static void
-debug_apply_relocations (void * file,
-                        Elf_Internal_Shdr * section,
-                        unsigned char * start)
-{
-  Elf_Internal_Shdr * relsec;
-  unsigned char * end = start + section->sh_size;
-
-  if (elf_header.e_type != ET_REL)
-    return;
-
-  /* Find the reloc section associated with the debug section.  */
+  /* Find the reloc section associated with the section.  */
   for (relsec = section_headers;
        relsec < section_headers + elf_header.e_shnum;
        ++relsec)
@@ -8524,6 +8279,274 @@ debug_apply_relocations (void * file,
     }
 }
 
+#ifdef SUPPORT_DISASSEMBLY
+static int
+disassemble_section (Elf_Internal_Shdr * section, FILE * file)
+{
+  printf (_("\nAssembly dump of section %s\n"),
+         SECTION_NAME (section));
+
+  /* XXX -- to be done --- XXX */
+
+  return 1;
+}
+#endif
+
+/* Reads in the contents of SECTION from FILE, returning a pointer
+   to a malloc'ed buffer or NULL if something went wrong.  */
+
+static char *
+get_section_contents (Elf_Internal_Shdr * section, FILE * file)
+{
+  bfd_size_type num_bytes;
+
+  num_bytes = section->sh_size;
+
+  if (num_bytes == 0 || section->sh_type == SHT_NOBITS)
+    {
+      printf (_("\nSection '%s' has no data to dump.\n"),
+             SECTION_NAME (section));
+      return NULL;
+    }
+
+  return get_data (NULL, file, section->sh_offset, 1, num_bytes,
+                  _("section contents"));
+}
+
+                     
+static void
+dump_section_as_strings (Elf_Internal_Shdr * section, FILE * file)
+{
+  Elf_Internal_Shdr * relsec;
+  bfd_size_type num_bytes;
+  bfd_vma addr;
+  char * data;
+  char * end;
+  char * start;
+  char * name = SECTION_NAME (section);
+  bfd_boolean some_strings_shown;
+
+  start = get_section_contents (section, file);
+  if (start == NULL)
+    return;
+
+  printf (_("\nString dump of section '%s':\n"), name);
+
+  /* If the section being dumped has relocations against it the user might
+     be expecting these relocations to have been applied.  Check for this
+     case and issue a warning message in order to avoid confusion.
+     FIXME: Maybe we ought to have an option that dumps a section with
+     relocs applied ?  */
+  for (relsec = section_headers;
+       relsec < section_headers + elf_header.e_shnum;
+       ++relsec)
+    {
+      if ((relsec->sh_type != SHT_RELA && relsec->sh_type != SHT_REL)
+         || relsec->sh_info >= elf_header.e_shnum
+         || section_headers + relsec->sh_info != section
+         || relsec->sh_size == 0
+         || relsec->sh_link >= elf_header.e_shnum)
+       continue;
+
+      printf (_("  Note: This section has relocations against it, but these have NOT been applied to this dump.\n"));
+      break;
+    }
+
+  num_bytes = section->sh_size;
+  addr = section->sh_addr;
+  data = start;
+  end  = start + num_bytes;
+  some_strings_shown = FALSE;
+
+  while (data < end)
+    {
+      while (!ISPRINT (* data))
+       if (++ data >= end)
+         break;
+
+      if (data < end)
+       {
+#ifndef __MSVCRT__
+         printf ("  [%6tx]  %s\n", data - start, data);
+#else
+         printf ("  [%6Ix]  %s\n", (size_t) (data - start), data);
+#endif
+         data += strlen (data);
+         some_strings_shown = TRUE;
+       }
+    }
+
+  if (! some_strings_shown)
+    printf (_("  No strings found in this section."));
+
+  free (start);
+
+  putchar ('\n');
+}
+
+static void
+dump_section_as_bytes (Elf_Internal_Shdr * section,
+                      FILE * file,
+                      bfd_boolean relocate)
+{
+  Elf_Internal_Shdr * relsec;
+  bfd_size_type bytes;
+  bfd_vma addr;
+  unsigned char * data;
+  unsigned char * start;
+
+  start = (unsigned char *) get_section_contents (section, file);
+  if (start == NULL)
+    return;
+
+  printf (_("\nHex dump of section '%s':\n"), SECTION_NAME (section));
+
+  if (relocate)
+    {
+      apply_relocations (file, section, start);
+    }
+  else
+    {
+      /* If the section being dumped has relocations against it the user might
+        be expecting these relocations to have been applied.  Check for this
+        case and issue a warning message in order to avoid confusion.
+        FIXME: Maybe we ought to have an option that dumps a section with
+        relocs applied ?  */
+      for (relsec = section_headers;
+          relsec < section_headers + elf_header.e_shnum;
+          ++relsec)
+       {
+         if ((relsec->sh_type != SHT_RELA && relsec->sh_type != SHT_REL)
+             || relsec->sh_info >= elf_header.e_shnum
+             || section_headers + relsec->sh_info != section
+             || relsec->sh_size == 0
+             || relsec->sh_link >= elf_header.e_shnum)
+           continue;
+
+         printf (_(" NOTE: This section has relocations against it, but these have NOT been applied to this dump.\n"));
+         break;
+       }
+    }
+
+  addr = section->sh_addr;
+  bytes = section->sh_size;
+  data = start;
+
+  while (bytes)
+    {
+      int j;
+      int k;
+      int lbytes;
+
+      lbytes = (bytes > 16 ? 16 : bytes);
+
+      printf ("  0x%8.8lx ", (unsigned long) addr);
+
+      for (j = 0; j < 16; j++)
+       {
+         if (j < lbytes)
+           printf ("%2.2x", data[j]);
+         else
+           printf ("  ");
+
+         if ((j & 3) == 3)
+           printf (" ");
+       }
+
+      for (j = 0; j < lbytes; j++)
+       {
+         k = data[j];
+         if (k >= ' ' && k < 0x7f)
+           printf ("%c", k);
+         else
+           printf (".");
+       }
+
+      putchar ('\n');
+
+      data  += lbytes;
+      addr  += lbytes;
+      bytes -= lbytes;
+    }
+
+  free (start);
+
+  putchar ('\n');
+}
+
+/* Uncompresses a section that was compressed using zlib, in place.
+   This is a copy of bfd_uncompress_section_contents, in bfd/compress.c  */
+
+static int
+uncompress_section_contents (unsigned char ** buffer, dwarf_size_type * size)
+{
+#ifndef HAVE_ZLIB_H
+  /* These are just to quiet gcc.  */
+  buffer = 0;
+  size = 0;
+  return FALSE;
+#else
+  dwarf_size_type compressed_size = *size;
+  unsigned char * compressed_buffer = *buffer;
+  dwarf_size_type uncompressed_size;
+  unsigned char * uncompressed_buffer;
+  z_stream strm;
+  int rc;
+  dwarf_size_type header_size = 12;
+
+  /* Read the zlib header.  In this case, it should be "ZLIB" followed
+     by the uncompressed section size, 8 bytes in big-endian order.  */
+  if (compressed_size < header_size
+      || ! streq ((char *) compressed_buffer, "ZLIB"))
+    return 0;
+
+  uncompressed_size = compressed_buffer[4]; uncompressed_size <<= 8;
+  uncompressed_size += compressed_buffer[5]; uncompressed_size <<= 8;
+  uncompressed_size += compressed_buffer[6]; uncompressed_size <<= 8;
+  uncompressed_size += compressed_buffer[7]; uncompressed_size <<= 8;
+  uncompressed_size += compressed_buffer[8]; uncompressed_size <<= 8;
+  uncompressed_size += compressed_buffer[9]; uncompressed_size <<= 8;
+  uncompressed_size += compressed_buffer[10]; uncompressed_size <<= 8;
+  uncompressed_size += compressed_buffer[11];
+
+  /* It is possible the section consists of several compressed
+     buffers concatenated together, so we uncompress in a loop.  */
+  strm.zalloc = NULL;
+  strm.zfree = NULL;
+  strm.opaque = NULL;
+  strm.avail_in = compressed_size - header_size;
+  strm.next_in = (Bytef *) compressed_buffer + header_size;
+  strm.avail_out = uncompressed_size;
+  uncompressed_buffer = xmalloc (uncompressed_size);
+
+  rc = inflateInit (& strm);
+  while (strm.avail_in > 0)
+    {
+      if (rc != Z_OK)
+        goto fail;
+      strm.next_out = ((Bytef *) uncompressed_buffer
+                       + (uncompressed_size - strm.avail_out));
+      rc = inflate (&strm, Z_FINISH);
+      if (rc != Z_STREAM_END)
+        goto fail;
+      rc = inflateReset (& strm);
+    }
+  rc = inflateEnd (& strm);
+  if (rc != Z_OK
+      || strm.avail_out != 0)
+    goto fail;
+
+  free (compressed_buffer);
+  *buffer = uncompressed_buffer;
+  *size = uncompressed_size;
+  return 1;
+
+ fail:
+  free (uncompressed_buffer);
+  return 0;
+#endif  /* HAVE_ZLIB_H */
+}
+
 static int
 load_specific_debug_section (enum dwarf_section_display_enum debug,
                             Elf_Internal_Shdr * sec, void * file)
@@ -8551,7 +8574,7 @@ load_specific_debug_section (enum dwarf_section_display_enum debug,
       return 0;
 
   if (debug_displays [debug].relocate)
-    debug_apply_relocations (file, sec, section->start);
+    apply_relocations (file, sec, section->start);
 
   return 1;
 }
@@ -8700,13 +8723,16 @@ process_section_contents (FILE * file)
        disassemble_section (section, file);
 #endif
       if (dump_sects[i] & HEX_DUMP)
-       dump_section_as_bytes (section, file);
+       dump_section_as_bytes (section, file, FALSE);
 
-      if (dump_sects[i] & DEBUG_DUMP)
-       display_debug_section (section, file);
+      if (dump_sects[i] & RELOC_DUMP)
+       dump_section_as_bytes (section, file, TRUE);
 
       if (dump_sects[i] & STRING_DUMP)
        dump_section_as_strings (section, file);
+
+      if (dump_sects[i] & DEBUG_DUMP)
+       display_debug_section (section, file);
     }
 
   /* Check to see if the user requested a