This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Committed: Add --relocated-dump option to readelf
- From: Nick Clifton <nickc at redhat dot com>
- To: binutils at sourceware dot org
- Date: Wed, 24 Jun 2009 11:37:09 +0100
- Subject: Committed: Add --relocated-dump option to readelf
Hi Guys,
I am checking in the patch below to further enhance readelf's
ability to display debug information found in object files created
by the MN10300 toolchain.
In addition this patch adds a new switch to readelf:
--relocated-dump (or -R). This switch acts just like the --hex-dump
switch except that relocations are applied to the content of the
section before it is displayed.
Tested with all the usual suspects.
Cheers
Nick
binutils/ChangeLog
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.
Index: binutils/NEWS
===================================================================
RCS file: /cvs/src/src/binutils/NEWS,v
retrieving revision 1.83
diff -c -3 -p -r1.83 NEWS
*** binutils/NEWS 12 Jun 2009 15:33:30 -0000 1.83
--- binutils/NEWS 24 Jun 2009 10:36:21 -0000
***************
*** 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: binutils/dwarf.c
===================================================================
RCS file: /cvs/src/src/binutils/dwarf.c,v
retrieving revision 1.46
diff -c -3 -p -r1.46 dwarf.c
*** binutils/dwarf.c 22 Jun 2009 08:46:13 -0000 1.46
--- binutils/dwarf.c 24 Jun 2009 10:36:22 -0000
*************** display_debug_lines_raw (struct dwarf_se
*** 2145,2151 ****
if (info.li_length + initial_length_size > section->size)
{
warn
! (_("The line info appears to be corrupt - the section is too small\n"));
return 0;
}
--- 2145,2152 ----
if (info.li_length + initial_length_size > section->size)
{
warn
! (_("The information in section %s appears to be corrupt - the section is too small\n"),
! section->name);
return 0;
}
*************** struct dwarf_section_display debug_displ
*** 4872,4878 ****
{ { ".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 },
{ { ".debug_pubnames", ".zdebug_pubnames", NULL, NULL, 0, 0 },
display_debug_pubnames, &do_debug_pubnames, 0, 0 },
{ { ".eh_frame", "", NULL, NULL, 0, 0 },
--- 4873,4879 ----
{ { ".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, 1, 0 },
{ { ".debug_pubnames", ".zdebug_pubnames", NULL, NULL, 0, 0 },
display_debug_pubnames, &do_debug_pubnames, 0, 0 },
{ { ".eh_frame", "", NULL, NULL, 0, 0 },
*************** struct dwarf_section_display debug_displ
*** 4886,4892 ****
{ { ".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 },
{ { ".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 },
--- 4887,4893 ----
{ { ".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, 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: binutils/readelf.c
===================================================================
RCS file: /cvs/src/src/binutils/readelf.c,v
retrieving revision 1.448
diff -c -3 -p -r1.448 readelf.c
*** binutils/readelf.c 22 Jun 2009 08:46:13 -0000 1.448
--- binutils/readelf.c 24 Jun 2009 10:36:25 -0000
*************** static struct group ** section_headers_g
*** 214,219 ****
--- 214,220 ----
#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;
*************** static struct option options[] =
*** 2844,2854 ****
{"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},
{"string-dump", required_argument, 0, 'p'},
#ifdef SUPPORT_DISASSEMBLY
{"instruction-dump", required_argument, 0, 'i'},
#endif
{"version", no_argument, 0, 'v'},
{"wide", no_argument, 0, 'W'},
--- 2845,2856 ----
{"unwind", no_argument, 0, 'u'},
{"archive-index", no_argument, 0, 'c'},
{"hex-dump", required_argument, 0, 'x'},
! {"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'},
*************** usage (FILE * stream)
*** 2885,2890 ****
--- 2887,2894 ----
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"));
*************** request_dump_byname (const char * sectio
*** 2961,2966 ****
--- 2965,2986 ----
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)
{
*************** parse_args (int argc, char ** argv)
*** 2970,2980 ****
usage (stderr);
while ((c = getopt_long
! (argc, argv, "ADHINSVWacdeghi:lnp:rstuvw::x:", options, NULL)) != EOF)
{
- char * cp;
- int section;
-
switch (c)
{
case 0:
--- 2990,2997 ----
usage (stderr);
while ((c = getopt_long
! (argc, argv, "ADHINR:SVWacdeghi:lnp:rstuvw::x:", options, NULL)) != EOF)
{
switch (c)
{
case 0:
*************** parse_args (int argc, char ** argv)
*** 3048,3067 ****
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);
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);
break;
case 'w':
do_dump++;
--- 3065,3077 ----
do_archive_index++;
break;
case 'x':
! request_dump (HEX_DUMP);
break;
case 'p':
! request_dump (STRING_DUMP);
! break;
! case 'R':
! request_dump (RELOC_DUMP);
break;
case 'w':
do_dump++;
*************** parse_args (int argc, char ** argv)
*** 3088,3099 ****
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);
#endif
case 'v':
print_version (program_name);
--- 3098,3105 ----
break;
#ifdef SUPPORT_DISASSEMBLY
case 'i':
! request_dump (DISASS_DUMP);
! break;
#endif
case 'v':
print_version (program_name);
*************** process_syminfo (FILE * file ATTRIBUTE_U
*** 7759,7948 ****
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;
! }
!
! static int
! dump_section_as_bytes (Elf_Internal_Shdr * section, FILE * file)
{
! 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;
! 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');
! return 1;
}
/* Returns TRUE iff RELOC_TYPE is a 32-bit absolute RELA relocation used in
--- 7765,7821 ----
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 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 */
! case 2: /* R_MN10300_16 */
! 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, reloc_type == 1 ? 4 : 2);
! saved_sym = NULL;
! return TRUE;
! }
! break;
! default:
! if (saved_sym != NULL)
! error (_("Unhandled MN10300 reloc type found after SYM_DIFF reloc"));
! break;
! }
! break;
! }
}
! return FALSE;
}
/* Returns TRUE iff RELOC_TYPE is a 32-bit absolute RELA relocation used in
*************** is_32bit_pcrel_reloc (unsigned int reloc
*** 8130,8137 ****
/* 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. */
return FALSE;
}
}
--- 8003,8010 ----
/* 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 apply_relocations
! anyway, so just return. */
return FALSE;
}
}
*************** is_none_reloc (unsigned int reloc_type)
*** 8265,8405 ****
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 */
! 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 */
! }
!
! /* 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. */
for (relsec = section_headers;
relsec < section_headers + elf_header.e_shnum;
++relsec)
--- 8138,8160 ----
return FALSE;
}
! /* 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 void
! 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 section. */
for (relsec = section_headers;
relsec < section_headers + elf_header.e_shnum;
++relsec)
*************** debug_apply_relocations (void * file,
*** 8524,8529 ****
--- 8279,8552 ----
}
}
+ #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)
*************** load_specific_debug_section (enum dwarf_
*** 8551,8557 ****
return 0;
if (debug_displays [debug].relocate)
! debug_apply_relocations (file, sec, section->start);
return 1;
}
--- 8574,8580 ----
return 0;
if (debug_displays [debug].relocate)
! apply_relocations (file, sec, section->start);
return 1;
}
*************** process_section_contents (FILE * file)
*** 8700,8712 ****
disassemble_section (section, file);
#endif
if (dump_sects[i] & HEX_DUMP)
! dump_section_as_bytes (section, file);
! if (dump_sects[i] & DEBUG_DUMP)
! display_debug_section (section, file);
if (dump_sects[i] & STRING_DUMP)
dump_section_as_strings (section, file);
}
/* Check to see if the user requested a
--- 8723,8738 ----
disassemble_section (section, file);
#endif
if (dump_sects[i] & HEX_DUMP)
! dump_section_as_bytes (section, file, FALSE);
! 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
Index: binutils/doc/binutils.texi
===================================================================
RCS file: /cvs/src/src/binutils/doc/binutils.texi,v
retrieving revision 1.148
diff -c -3 -p -r1.148 binutils.texi
*** binutils/doc/binutils.texi 18 Jun 2009 10:31:21 -0000 1.148
--- binutils/doc/binutils.texi 24 Jun 2009 10:36:27 -0000
*************** readelf [@option{-a}|@option{--all}]
*** 3844,3849 ****
--- 3844,3850 ----
[@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]]
*************** symbols section.
*** 3966,3975 ****
@item -x <number or name>
@itemx --hex-dump=<number or name>
! Displays the contents of the indicated section as a hexadecimal dump.
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 -p <number or name>
@itemx --string-dump=<number or name>
Displays the contents of the indicated section as printable strings.
--- 3967,3984 ----
@item -x <number or name>
@itemx --hex-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.
+ @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.