aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2015-04-05 09:20:02 -0700
committerH.J. Lu <hjl.tools@gmail.com>2015-04-05 09:29:57 -0700
commit77115a4a156052eb1542d16041115cc347da4a07 (patch)
tree4eed88480e46422071a1d39651e4d27d92fc82a7
parent317974f6831d8c7af613257e190e0dc3125bc4cf (diff)
downloadgdb-77115a4a156052eb1542d16041115cc347da4a07.zip
gdb-77115a4a156052eb1542d16041115cc347da4a07.tar.gz
gdb-77115a4a156052eb1542d16041115cc347da4a07.tar.bz2
Add SHF_COMPRESSED support to readelf
This patch updates readelf to dump compression header with readelf -S -W: [ 4] .debug_info PROGBITS 00000000 000038 00007d 00 C 0 0 1 readelf -t -W: [ 4] .debug_info PROGBITS 00000000 000038 00007d 00 0 0 1 [00000800]: COMPRESSED ZLIB, 0000009d, 1 It also checks the compression header when decompressing the compressed section. * readelf.c (get_elf_section_flags): Support SHF_COMPRESSED. (get_compression_header): New. (process_section_headers): Dump compression header if needed. (uncompress_section_contents): Don't free compressed_buffer here. (load_specific_debug_section): Free the compressed buffer, update the section buffer and the section size if uncompress is successful.
-rw-r--r--binutils/ChangeLog10
-rw-r--r--binutils/readelf.c78
2 files changed, 82 insertions, 6 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 023bd98..230a58d 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,3 +1,13 @@
+2015-04-05 H.J. Lu <hongjiu.lu@intel.com>
+
+ * readelf.c (get_elf_section_flags): Support SHF_COMPRESSED.
+ (get_compression_header): New.
+ (process_section_headers): Dump compression header if needed.
+ (uncompress_section_contents): Don't free compressed_buffer here.
+ (load_specific_debug_section): Free the compressed buffer, update
+ the section buffer and the section size if uncompress is
+ successful.
+
2015-04-02 H.J. Lu <hongjiu.lu@intel.com>
* configure: Regenerated.
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 17d4fd4..fea372f 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -5155,7 +5155,8 @@ get_elf_section_flags (bfd_vma sh_flags)
/* Generic. */
/* 18 */ { STRING_COMMA_LEN ("EXCLUDE") },
/* SPARC specific. */
- /* 19 */ { STRING_COMMA_LEN ("ORDERED") }
+ /* 19 */ { STRING_COMMA_LEN ("ORDERED") },
+ /* 20 */ { STRING_COMMA_LEN ("COMPRESSED") }
};
if (do_section_details)
@@ -5187,6 +5188,7 @@ get_elf_section_flags (bfd_vma sh_flags)
case SHF_GROUP: sindex = 8; break;
case SHF_TLS: sindex = 9; break;
case SHF_EXCLUDE: sindex = 18; break;
+ case SHF_COMPRESSED: sindex = 20; break;
default:
sindex = -1;
@@ -5268,6 +5270,7 @@ get_elf_section_flags (bfd_vma sh_flags)
case SHF_GROUP: *p = 'G'; break;
case SHF_TLS: *p = 'T'; break;
case SHF_EXCLUDE: *p = 'E'; break;
+ case SHF_COMPRESSED: *p = 'C'; break;
default:
if ((elf_header.e_machine == EM_X86_64
@@ -5355,6 +5358,27 @@ get_elf_section_flags (bfd_vma sh_flags)
return buff;
}
+static unsigned int
+get_compression_header (Elf_Internal_Chdr *chdr, unsigned char *buf)
+{
+ if (is_32bit_elf)
+ {
+ Elf32_External_Chdr *echdr = (Elf32_External_Chdr *) buf;
+ chdr->ch_type = BYTE_GET (echdr->ch_type);
+ chdr->ch_size = BYTE_GET (echdr->ch_size);
+ chdr->ch_addralign = BYTE_GET (echdr->ch_addralign);
+ return sizeof (*echdr);
+ }
+ else
+ {
+ Elf64_External_Chdr *echdr = (Elf64_External_Chdr *) buf;
+ chdr->ch_type = BYTE_GET (echdr->ch_type);
+ chdr->ch_size = BYTE_GET (echdr->ch_size);
+ chdr->ch_addralign = BYTE_GET (echdr->ch_addralign);
+ return sizeof (*echdr);
+ }
+}
+
static int
process_section_headers (FILE * file)
{
@@ -5799,7 +5823,29 @@ process_section_headers (FILE * file)
}
if (do_section_details)
- printf (" %s\n", get_elf_section_flags (section->sh_flags));
+ {
+ printf (" %s\n", get_elf_section_flags (section->sh_flags));
+ if ((section->sh_flags & SHF_COMPRESSED) != 0)
+ {
+ /* Minimum section size is 12 bytes for 32-bit compression
+ header + 12 bytes for compressed data header. */
+ unsigned char buf[24];
+ assert (sizeof (buf) >= sizeof (Elf64_External_Chdr));
+ if (get_data (&buf, (FILE *) file, section->sh_offset, 1,
+ sizeof (buf), _("compression header")))
+ {
+ Elf_Internal_Chdr chdr;
+ get_compression_header (&chdr, buf);
+ if (chdr.ch_type == ELFCOMPRESS_ZLIB)
+ printf (" ZLIB, ");
+ else
+ printf (_(" [<unknown>: 0x%x], "),
+ chdr.ch_type);
+ print_vma (chdr.ch_size, LONG_HEX);
+ printf (", %lu\n", (unsigned long) chdr.ch_addralign);
+ }
+ }
+ }
}
if (!do_section_details)
@@ -12007,7 +12053,6 @@ uncompress_section_contents (unsigned char **buffer,
|| strm.avail_out != 0)
goto fail;
- free (compressed_buffer);
*buffer = uncompressed_buffer;
*size = uncompressed_size;
return 1;
@@ -12040,9 +12085,30 @@ load_specific_debug_section (enum dwarf_section_display_enum debug,
section->size = 0;
else
{
- section->size = sec->sh_size;
- if (uncompress_section_contents (&section->start, &section->size))
- sec->sh_size = section->size;
+ unsigned char *start = section->start;
+ dwarf_size_type size = sec->sh_size;
+
+ if ((sec->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 != sec->sh_addralign)
+ return 0;
+ start += compression_header_size;
+ size -= compression_header_size;
+ }
+
+ if (uncompress_section_contents (&start, &size))
+ {
+ /* Free the compressed buffer, update the section buffer
+ and the section size if uncompress is successful. */
+ free (section->start);
+ section->start = start;
+ sec->sh_size = size;
+ }
+ section->size = size;
}
if (section->start == NULL)