This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[comitted, PATCH] Add SHF_COMPRESSED support to readelf


I checked in this patch to update 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.
---
 binutils/ChangeLog | 10 +++++++
 binutils/readelf.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++-----
 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)
-- 
2.1.0


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]