summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2015-05-15 17:16:31 +0100
committerNick Clifton <nickc@redhat.com>2015-05-15 17:16:31 +0100
commit0e602686df5677fee06cbd1718b4a7aa5379cd2a (patch)
tree728d4833b4bb267e64d627bd7982fcddee260ab5
parent4e63d0ac896b6036edd8e2c09a4dac7aa16a46d1 (diff)
downloadbinutils-gdb-0e602686df5677fee06cbd1718b4a7aa5379cd2a.tar.gz
Add --decompress option to readelf to decompress sections before they are dumped.
bin * readelf.c (options): Add "decompress". (usage): Mention -z/--decompress. (parse_args): Handle -z. (uncompress_section_contents): Move to earlier in the file. (dump_section_as_strings): If requested, decompress the section before dumping. (dump_section_as_bytes): Likewise. * doc/binutils.texi: Document the new option. tests * binutils-all/z.s: New test. Checks the --decompress option to readelf. * binutils-all/readelf.exp: Run the test. * binutils-all/readelf.z: Expected output from readelf.
-rw-r--r--binutils/ChangeLog11
-rw-r--r--binutils/doc/binutils.texi7
-rw-r--r--binutils/readelf.c241
-rw-r--r--binutils/testsuite/ChangeLog7
-rw-r--r--binutils/testsuite/binutils-all/readelf.exp46
-rw-r--r--binutils/testsuite/binutils-all/readelf.z8
-rw-r--r--binutils/testsuite/binutils-all/z.s70
7 files changed, 303 insertions, 87 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 5d017a1f1ec..ee2ddf0f54d 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,3 +1,14 @@
+2015-05-15 Nick Clifton <nickc@redhat.com>
+
+ * readelf.c (options): Add "decompress".
+ (usage): Mention -z/--decompress.
+ (parse_args): Handle -z.
+ (uncompress_section_contents): Move to earlier in the file.
+ (dump_section_as_strings): If requested, decompress the section
+ before dumping.
+ (dump_section_as_bytes): Likewise.
+ * doc/binutils.texi: Document the new option.
+
2015-05-14 Peter Bergner <bergner@vnet.ibm.com>
* MAINTAINERS: Add myself as PPC maintainer.
diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi
index 601de480bbc..619c28ec10e 100644
--- a/binutils/doc/binutils.texi
+++ b/binutils/doc/binutils.texi
@@ -4344,6 +4344,7 @@ readelf [@option{-a}|@option{--all}]
[@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{-z}|@option{--decompress}]
[@option{-c}|@option{--archive-index}]
[@option{-w[lLiaprmfFsoRt]}|
@option{--debug-dump}[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=frames-interp,=str,=loc,=Ranges,=pubtypes,=trace_info,=trace_abbrev,=trace_aranges,=gdb_index]]
@@ -4492,6 +4493,12 @@ Displays the contents of the indicated section as printable strings.
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 -z
+@itemx --decompress
+Requests that the section(s) being dumped by @option{x}, @option{R} or
+@option{p} options are decompressed before being displayed. If the
+section(s) are not compressed then they are displayed as is.
+
@item -c
@itemx --archive-index
@cindex Archive file symbol index information
diff --git a/binutils/readelf.c b/binutils/readelf.c
index e299e1b78b9..4bb31ebdaac 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -209,6 +209,7 @@ static int do_arch;
static int do_notes;
static int do_archive_index;
static int is_32bit_elf;
+static int decompress_dumps;
struct group_list
{
@@ -3960,6 +3961,7 @@ static struct option options[] =
{"hex-dump", required_argument, 0, 'x'},
{"relocated-dump", required_argument, 0, 'R'},
{"string-dump", required_argument, 0, 'p'},
+ {"decompress", no_argument, 0, 'z'},
#ifdef SUPPORT_DISASSEMBLY
{"instruction-dump", required_argument, 0, 'i'},
#endif
@@ -4007,6 +4009,7 @@ usage (FILE * stream)
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\
+ -z --decompress Decompress section before dumping it\n\
-w[lLiaprmfFsoRt] or\n\
--debug-dump[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,\n\
=frames-interp,=str,=loc,=Ranges,=pubtypes,\n\
@@ -4117,7 +4120,7 @@ parse_args (int argc, char ** argv)
usage (stderr);
while ((c = getopt_long
- (argc, argv, "ADHINR:SVWacdeghi:lnp:rstuvw::x:", options, NULL)) != EOF)
+ (argc, argv, "ADHINR:SVWacdeghi:lnp:rstuvw::x:z", options, NULL)) != EOF)
{
switch (c)
{
@@ -4200,6 +4203,9 @@ parse_args (int argc, char ** argv)
case 'R':
request_dump (RELOC_DUMP);
break;
+ case 'z':
+ decompress_dumps++;
+ break;
case 'w':
do_dump++;
if (optarg == 0)
@@ -11939,23 +11945,120 @@ get_section_contents (Elf_Internal_Shdr * section, FILE * file)
_("section contents"));
}
+/* Uncompresses a section that was compressed using zlib, in place. */
+
+static bfd_boolean
+uncompress_section_contents (unsigned char **buffer,
+ dwarf_size_type uncompressed_size,
+ dwarf_size_type *size)
+{
+ dwarf_size_type compressed_size = *size;
+ unsigned char * compressed_buffer = *buffer;
+ unsigned char * uncompressed_buffer;
+ z_stream strm;
+ int rc;
+
+ /* It is possible the section consists of several compressed
+ buffers concatenated together, so we uncompress in a loop. */
+ /* PR 18313: The state field in the z_stream structure is supposed
+ to be invisible to the user (ie us), but some compilers will
+ still complain about it being used without initialisation. So
+ we first zero the entire z_stream structure and then set the fields
+ that we need. */
+ memset (& strm, 0, sizeof strm);
+ strm.avail_in = compressed_size;
+ strm.next_in = (Bytef *) compressed_buffer;
+ strm.avail_out = uncompressed_size;
+ uncompressed_buffer = (unsigned char *) 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;
+
+ *buffer = uncompressed_buffer;
+ *size = uncompressed_size;
+ return TRUE;
+
+ fail:
+ free (uncompressed_buffer);
+ /* Indicate decompression failure. */
+ *buffer = NULL;
+ return FALSE;
+}
static void
dump_section_as_strings (Elf_Internal_Shdr * section, FILE * file)
{
- Elf_Internal_Shdr * relsec;
- bfd_size_type num_bytes;
- char * data;
- char * end;
- char * start;
- bfd_boolean some_strings_shown;
-
- start = get_section_contents (section, file);
+ Elf_Internal_Shdr * relsec;
+ bfd_size_type num_bytes;
+ char * data;
+ char * end;
+ char * real_start;
+ char * start;
+ bfd_boolean some_strings_shown;
+
+ real_start = start = get_section_contents (section, file);
if (start == NULL)
return;
+ num_bytes = section->sh_size;
printf (_("\nString dump of section '%s':\n"), printable_section_name (section));
+ if (decompress_dumps)
+ {
+ dwarf_size_type new_size = num_bytes;
+ dwarf_size_type uncompressed_size = 0;
+
+ if ((section->sh_flags & SHF_COMPRESSED) != 0)
+ {
+ Elf_Internal_Chdr chdr;
+ unsigned int compression_header_size
+ = get_compression_header (& chdr, (unsigned char *) start);
+
+ if (chdr.ch_type == ELFCOMPRESS_ZLIB
+ && chdr.ch_addralign == section->sh_addralign)
+ {
+ uncompressed_size = chdr.ch_size;
+ start += compression_header_size;
+ new_size -= compression_header_size;
+ }
+ }
+ else if (new_size > 12 && streq ((char *) start, "ZLIB"))
+ {
+ /* Read the zlib header. In this case, it should be "ZLIB"
+ followed by the uncompressed section size, 8 bytes in
+ big-endian order. */
+ uncompressed_size = start[4]; uncompressed_size <<= 8;
+ uncompressed_size += start[5]; uncompressed_size <<= 8;
+ uncompressed_size += start[6]; uncompressed_size <<= 8;
+ uncompressed_size += start[7]; uncompressed_size <<= 8;
+ uncompressed_size += start[8]; uncompressed_size <<= 8;
+ uncompressed_size += start[9]; uncompressed_size <<= 8;
+ uncompressed_size += start[10]; uncompressed_size <<= 8;
+ uncompressed_size += start[11];
+ start += 12;
+ new_size -= 12;
+ }
+
+ if (uncompressed_size
+ && uncompress_section_contents ((unsigned char **) & start,
+ uncompressed_size, & new_size))
+ num_bytes = new_size;
+ }
+
/* 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.
@@ -11976,7 +12079,6 @@ dump_section_as_strings (Elf_Internal_Shdr * section, FILE * file)
break;
}
- num_bytes = section->sh_size;
data = start;
end = start + num_bytes;
some_strings_shown = FALSE;
@@ -12016,7 +12118,7 @@ dump_section_as_strings (Elf_Internal_Shdr * section, FILE * file)
if (! some_strings_shown)
printf (_(" No strings found in this section."));
- free (start);
+ free (real_start);
putchar ('\n');
}
@@ -12027,20 +12129,65 @@ dump_section_as_bytes (Elf_Internal_Shdr * section,
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);
+ bfd_size_type bytes;
+ bfd_size_type section_size;
+ bfd_vma addr;
+ unsigned char * data;
+ unsigned char * real_start;
+ unsigned char * start;
+
+ real_start = start = (unsigned char *) get_section_contents (section, file);
if (start == NULL)
return;
+ section_size = section->sh_size;
printf (_("\nHex dump of section '%s':\n"), printable_section_name (section));
+ if (decompress_dumps)
+ {
+ dwarf_size_type new_size = section_size;
+ dwarf_size_type uncompressed_size = 0;
+
+ if ((section->sh_flags & SHF_COMPRESSED) != 0)
+ {
+ Elf_Internal_Chdr chdr;
+ unsigned int compression_header_size
+ = get_compression_header (& chdr, start);
+
+ if (chdr.ch_type == ELFCOMPRESS_ZLIB
+ && chdr.ch_addralign == section->sh_addralign)
+ {
+ uncompressed_size = chdr.ch_size;
+ start += compression_header_size;
+ new_size -= compression_header_size;
+ }
+ }
+ else if (new_size > 12 && streq ((char *) start, "ZLIB"))
+ {
+ /* Read the zlib header. In this case, it should be "ZLIB"
+ followed by the uncompressed section size, 8 bytes in
+ big-endian order. */
+ uncompressed_size = start[4]; uncompressed_size <<= 8;
+ uncompressed_size += start[5]; uncompressed_size <<= 8;
+ uncompressed_size += start[6]; uncompressed_size <<= 8;
+ uncompressed_size += start[7]; uncompressed_size <<= 8;
+ uncompressed_size += start[8]; uncompressed_size <<= 8;
+ uncompressed_size += start[9]; uncompressed_size <<= 8;
+ uncompressed_size += start[10]; uncompressed_size <<= 8;
+ uncompressed_size += start[11];
+ start += 12;
+ new_size -= 12;
+ }
+
+ if (uncompressed_size
+ && uncompress_section_contents (& start, uncompressed_size,
+ & new_size))
+ section_size = new_size;
+ }
+
if (relocate)
{
- apply_relocations (file, section, start, section->sh_size, NULL, NULL);
+ apply_relocations (file, section, start, section_size, NULL, NULL);
}
else
{
@@ -12066,7 +12213,7 @@ dump_section_as_bytes (Elf_Internal_Shdr * section,
}
addr = section->sh_addr;
- bytes = section->sh_size;
+ bytes = section_size;
data = start;
while (bytes)
@@ -12106,65 +12253,11 @@ dump_section_as_bytes (Elf_Internal_Shdr * section,
bytes -= lbytes;
}
- free (start);
+ free (real_start);
putchar ('\n');
}
-/* Uncompresses a section that was compressed using zlib, in place. */
-
-static int
-uncompress_section_contents (unsigned char **buffer,
- dwarf_size_type uncompressed_size,
- dwarf_size_type *size)
-{
- dwarf_size_type compressed_size = *size;
- unsigned char * compressed_buffer = *buffer;
- unsigned char * uncompressed_buffer;
- z_stream strm;
- int rc;
-
- /* It is possible the section consists of several compressed
- buffers concatenated together, so we uncompress in a loop. */
- /* PR 18313: The state field in the z_stream structure is supposed
- to be invisible to the user (ie us), but some compilers will
- still complain about it being used without initialisation. So
- we first zero the entire z_stream structure and then set the fields
- that we need. */
- memset (& strm, 0, sizeof strm);
- strm.avail_in = compressed_size;
- strm.next_in = (Bytef *) compressed_buffer;
- strm.avail_out = uncompressed_size;
- uncompressed_buffer = (unsigned char *) 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;
-
- *buffer = uncompressed_buffer;
- *size = uncompressed_size;
- return 1;
-
- fail:
- free (uncompressed_buffer);
- /* Indicate decompression failure. */
- *buffer = NULL;
- return 0;
-}
-
static int
load_specific_debug_section (enum dwarf_section_display_enum debug,
const Elf_Internal_Shdr * sec, void * file)
diff --git a/binutils/testsuite/ChangeLog b/binutils/testsuite/ChangeLog
index ad8d8ad3630..99801e216a1 100644
--- a/binutils/testsuite/ChangeLog
+++ b/binutils/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2015-05-15 Nick Clifton <nickc@redhat.com>
+
+ * binutils-all/z.s: New test. Checks the --decompress option to
+ readelf.
+ * binutils-all/readelf.exp: Run the test.
+ * binutils-all/readelf.z: Expected output from readelf.
+
2015-05-14 H.J. Lu <hongjiu.lu@intel.com>
* binutils-all/compress.exp: Replace "$OBJDUMP -s -j .debug_info"
diff --git a/binutils/testsuite/binutils-all/readelf.exp b/binutils/testsuite/binutils-all/readelf.exp
index 58e140cc964..59fd556deb4 100644
--- a/binutils/testsuite/binutils-all/readelf.exp
+++ b/binutils/testsuite/binutils-all/readelf.exp
@@ -346,29 +346,49 @@ readelf_dump_test
if {![binutils_assemble $srcdir/$subdir/version.s tmpdir/version.o]} then {
perror "could not assemble version note test file"
unresolved "readelf - failed to assemble"
- return
-}
-
-if ![is_remote host] {
- set tempfile tmpdir/version.o
+ fail "readelf -n"
} else {
- set tempfile [remote_download host tmpdir/version.o]
+
+ if ![is_remote host] {
+ set tempfile tmpdir/version.o
+ } else {
+ set tempfile [remote_download host tmpdir/version.o]
+ }
+
+ readelf_test -n $tempfile readelf.n {}
}
-readelf_test -n $tempfile readelf.n {}
# PR 18374 - Check that relocations against the .debug_loc section
# do not prevent readelf from displaying all the location lists.
if {![binutils_assemble $srcdir/$subdir/pr18374.s tmpdir/pr18374.o]} then {
perror "could not assemble PR18374 test file"
unresolved "readelf - failed to assemble"
- return
+ fail "readelf --debug-loc"
+} else {
+
+ if ![is_remote host] {
+ set tempfile tmpdir/pr18374.o
+ } else {
+ set tempfile [remote_download host tmpdir/pr18374.o]
+ }
+
+ readelf_test --debug-dump=loc $tempfile readelf.pr18374 {}
}
-if ![is_remote host] {
- set tempfile tmpdir/pr18374.o
+
+# Check that decompressed dumps work.
+if {![binutils_assemble $srcdir/$subdir/z.s tmpdir/z.o]} then {
+ perror "could not assemble decompress dump test file"
+ unresolved "readelf - failed to assemble"
+ fail "readelf -z"
} else {
- set tempfile [remote_download host tmpdir/pr18374.o]
-}
-readelf_test --debug-dump=loc $tempfile readelf.pr18374 {}
+ if ![is_remote host] {
+ set tempfile tmpdir/z.o
+ } else {
+ set tempfile [remote_download host tmpdir/z.o]
+ }
+
+ readelf_test {--decompress --hex-dump .debug_loc} $tempfile readelf.z {}
+}
diff --git a/binutils/testsuite/binutils-all/readelf.z b/binutils/testsuite/binutils-all/readelf.z
new file mode 100644
index 00000000000..08434447625
--- /dev/null
+++ b/binutils/testsuite/binutils-all/readelf.z
@@ -0,0 +1,8 @@
+Hex dump of section '.debug_loc':
+ 0x00000000 00000000 00000000 01005000 00000000 ..........P.....
+ 0x00000010 00000004 00f30150 9f000000 00000000 .......P........
+ 0x00000020 00000000 00000000 00010051 00000000 ...........Q....
+ 0x00000030 00000000 0300717f 9f000000 00000000 ......q.........
+ 0x00000040 000b0070 0020f301 51227000 229f0000 ...p. ..Q"p."...
+ 0x00000050 00000000 00000b00 70002070 0022f301 ........p. p."..
+ 0x00000060 51229f00 00000000 000000 Q".........
diff --git a/binutils/testsuite/binutils-all/z.s b/binutils/testsuite/binutils-all/z.s
new file mode 100644
index 00000000000..2d24f3334ea
--- /dev/null
+++ b/binutils/testsuite/binutils-all/z.s
@@ -0,0 +1,70 @@
+ .section .debug_loc,"",%progbits
+
+ .byte 0x5a
+ .byte 0x4c
+ .byte 0x49
+ .byte 0x42
+ .byte 0x00
+ .byte 0x00
+ .byte 0x00
+ .byte 0x00
+ .byte 0x00
+ .byte 0x00
+ .byte 0x00
+ .byte 0x6b
+ .byte 0x78
+ .byte 0x9c
+ .byte 0x63
+ .byte 0x60
+ .byte 0x80
+ .byte 0x00
+ .byte 0x46
+ .byte 0x86
+ .byte 0x00
+ .byte 0x28
+ .byte 0x8b
+ .byte 0x81
+ .byte 0x85
+ .byte 0xe1
+ .byte 0x33
+ .byte 0x63
+ .byte 0xc0
+ .byte 0x7c
+ .byte 0x06
+ .byte 0x34
+ .byte 0xc0
+ .byte 0xc8
+ .byte 0x10
+ .byte 0x08
+ .byte 0x63
+ .byte 0x32
+ .byte 0x33
+ .byte 0x14
+ .byte 0xd6
+ .byte 0xc3
+ .byte 0xe5
+ .byte 0xb9
+ .byte 0x19
+ .byte 0x0a
+ .byte 0x18
+ .byte 0x14
+ .byte 0x3e
+ .byte 0x33
+ .byte 0x06
+ .byte 0x2a
+ .byte 0x15
+ .byte 0x30
+ .byte 0x28
+ .byte 0xa1
+ .byte 0x0a
+ .byte 0x02
+ .byte 0x05
+ .byte 0x40
+ .byte 0xe2
+ .byte 0x70
+ .byte 0x41
+ .byte 0x00
+ .byte 0xc1
+ .byte 0x6a
+ .byte 0x0a
+ .byte 0x83