summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Wielaard <mjw@redhat.com>2015-12-30 14:18:40 +0100
committerMark Wielaard <mjw@redhat.com>2016-01-06 14:27:10 +0100
commitc495d754f33bd2ce3eeaaed936d8f045fbf53f30 (patch)
treea64b525f34ef7084911caafa4fabade4d60897ed
parent272018bba1f253bae00b5ba280ad0e0f18c04006 (diff)
downloadelfutils-c495d754f33bd2ce3eeaaed936d8f045fbf53f30.tar.gz
elfutils-c495d754f33bd2ce3eeaaed936d8f045fbf53f30.tar.xz
libdw: Use elf_compress[_gnu] to uncompress debug section data.
libdw used its own code for decompressing GNU style .zdebug sections. Using elf_compress and elf_compress_gnu instead makes it possible to transparently use either GNU style or ELF style compressed data. Signed-off-by: Mark Wielaard <mjw@redhat.com>
-rw-r--r--libdw/ChangeLog13
-rw-r--r--libdw/dwarf_begin_elf.c156
-rw-r--r--libdw/dwarf_end.c20
-rw-r--r--libdw/libdwP.h11
4 files changed, 63 insertions, 137 deletions
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 89d0326..fc80e8d 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,16 @@
+2015-12-18 Mark Wielaard <mjw@redhat.com>
+
+ * libdwP.h (struct Dwarf): Remove sectiondata_gzip_mask.
+ (__libdw_free_zdata): Remove.
+ * dwarf_begin_elf.c (inflate_section): Remove.
+ (check_section): Remove __libdw_free_zdata calls. Use elf_compress
+ and elf_compress_gnu to decompress if necessary.
+ (valid_p): Remove __libdw_free_zdata calls.
+ (scngrp_read): Use elf_compress if section is compressed. Remove
+ __libdw_free_zdata calls.
+ * dwarf_end.c (__libdw_free_zdata): Remove.
+ (dwarf_end): Don't call __libdw_free_zdata.
+
2015-10-28 Mark Wielaard <mjw@redhat.com>
* libdw.map (ELFUTILS_0.165): New. Add dwelf_scn_gnu_compressed_size.
diff --git a/libdw/dwarf_begin_elf.c b/libdw/dwarf_begin_elf.c
index 63532fd..6f25e42 100644
--- a/libdw/dwarf_begin_elf.c
+++ b/libdw/dwarf_begin_elf.c
@@ -44,13 +44,6 @@
#include "libdwP.h"
-#if USE_ZLIB
-# include <endian.h>
-# define crc32 loser_crc32
-# include <zlib.h>
-# undef crc32
-#endif
-
/* Section names. */
static const char dwarf_scnnames[IDX_last][18] =
@@ -71,70 +64,6 @@ static const char dwarf_scnnames[IDX_last][18] =
};
#define ndwarf_scnnames (sizeof (dwarf_scnnames) / sizeof (dwarf_scnnames[0]))
-#if USE_ZLIB
-static Elf_Data *
-inflate_section (Elf_Data * data)
-{
- /* There is a 12-byte header of "ZLIB" followed by
- an 8-byte big-endian size. */
-
- if (unlikely (data->d_size < 4 + 8)
- || unlikely (memcmp (data->d_buf, "ZLIB", 4) != 0))
- return NULL;
-
- uint64_t size;
- memcpy (&size, data->d_buf + 4, sizeof size);
- size = be64toh (size);
-
- /* Check for unsigned overflow so malloc always allocated
- enough memory for both the Elf_Data header and the
- uncompressed section data. */
- if (unlikely (sizeof (Elf_Data) + size < size))
- return NULL;
-
- Elf_Data *zdata = malloc (sizeof (Elf_Data) + size);
- if (unlikely (zdata == NULL))
- return NULL;
-
- zdata->d_buf = &zdata[1];
- zdata->d_type = ELF_T_BYTE;
- zdata->d_version = EV_CURRENT;
- zdata->d_size = size;
- zdata->d_off = 0;
- zdata->d_align = 1;
-
- z_stream z =
- {
- .next_in = data->d_buf + 4 + 8,
- .avail_in = data->d_size - 4 - 8,
- .next_out = zdata->d_buf,
- .avail_out = zdata->d_size
- };
- int zrc = inflateInit (&z);
- while (z.avail_in > 0 && likely (zrc == Z_OK))
- {
- z.next_out = zdata->d_buf + (zdata->d_size - z.avail_out);
- zrc = inflate (&z, Z_FINISH);
- if (unlikely (zrc != Z_STREAM_END))
- {
- zrc = Z_DATA_ERROR;
- break;
- }
- zrc = inflateReset (&z);
- }
- if (likely (zrc == Z_OK))
- zrc = inflateEnd (&z);
-
- if (unlikely (zrc != Z_OK) || unlikely (z.avail_out != 0))
- {
- free (zdata);
- return NULL;
- }
-
- return zdata;
-}
-#endif
-
static Dwarf *
check_section (Dwarf *result, GElf_Ehdr *ehdr, Elf_Scn *scn, bool inscngrp)
{
@@ -173,7 +102,6 @@ check_section (Dwarf *result, GElf_Ehdr *ehdr, Elf_Scn *scn, bool inscngrp)
/* The section name must be valid. Otherwise is the ELF file
invalid. */
err:
- __libdw_free_zdata (result);
Dwarf_Sig8_Hash_free (&result->sig8_hash);
__libdw_seterrno (DWARF_E_INVALID_ELF);
free (result);
@@ -182,14 +110,14 @@ check_section (Dwarf *result, GElf_Ehdr *ehdr, Elf_Scn *scn, bool inscngrp)
/* Recognize the various sections. Most names start with .debug_. */
size_t cnt;
- bool compressed = false;
+ bool gnu_compressed = false;
for (cnt = 0; cnt < ndwarf_scnnames; ++cnt)
if (strcmp (scnname, dwarf_scnnames[cnt]) == 0)
break;
else if (scnname[0] == '.' && scnname[1] == 'z'
&& strcmp (&scnname[2], &dwarf_scnnames[cnt][1]) == 0)
{
- compressed = true;
+ gnu_compressed = true;
break;
}
@@ -201,40 +129,41 @@ check_section (Dwarf *result, GElf_Ehdr *ehdr, Elf_Scn *scn, bool inscngrp)
/* A section appears twice. That's bad. We ignore the section. */
return result;
+ /* We cannot know whether or not a GNU compressed section has already
+ been uncompressed or not, so ignore any errors. */
+ if (gnu_compressed)
+ elf_compress_gnu (scn, 0, 0);
+
+ if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
+ {
+ if (elf_compress (scn, 0, 0) < 0)
+ {
+ /* If we failed to decompress the section and it's the
+ debug_info section, then fail with specific error rather
+ than the generic NO_DWARF. Without debug_info we can't do
+ anything (see also valid_p()). */
+ if (cnt == IDX_debug_info)
+ {
+ Dwarf_Sig8_Hash_free (&result->sig8_hash);
+ __libdw_seterrno (DWARF_E_COMPRESSED_ERROR);
+ free (result);
+ return NULL;
+ }
+ return result;
+ }
+ }
+
/* Get the section data. */
Elf_Data *data = elf_getdata (scn, NULL);
- if (data == NULL || data->d_size == 0)
+ if (data == NULL)
+ goto err;
+
+ if (data->d_buf == NULL || data->d_size == 0)
/* No data actually available, ignore it. */
return result;
/* We can now read the section data into results. */
- if (!compressed)
- result->sectiondata[cnt] = data;
- else
- {
- /* A compressed section. */
-
-#if USE_ZLIB
- Elf_Data *inflated = inflate_section(data);
- if (inflated != NULL)
- {
- result->sectiondata[cnt] = inflated;
- result->sectiondata_gzip_mask |= 1U << cnt;
- }
-#endif
-
- /* If we failed to decompress the section and it's the debug_info section,
- * then fail with specific error rather than the generic NO_DWARF. Without
- * debug_info we can't do anything (see also valid_p()). */
- if (result->sectiondata[cnt] == NULL && cnt == IDX_debug_info)
- {
- __libdw_free_zdata (result);
- Dwarf_Sig8_Hash_free (&result->sig8_hash);
- __libdw_seterrno (DWARF_E_COMPRESSED_ERROR);
- free (result);
- return NULL;
- }
- }
+ result->sectiondata[cnt] = data;
return result;
}
@@ -253,7 +182,6 @@ valid_p (Dwarf *result)
if (likely (result != NULL)
&& unlikely (result->sectiondata[IDX_debug_info] == NULL))
{
- __libdw_free_zdata (result);
Dwarf_Sig8_Hash_free (&result->sig8_hash);
__libdw_seterrno (DWARF_E_NO_DWARF);
free (result);
@@ -265,7 +193,6 @@ valid_p (Dwarf *result)
result->fake_loc_cu = (Dwarf_CU *) calloc (1, sizeof (Dwarf_CU));
if (unlikely (result->fake_loc_cu == NULL))
{
- __libdw_free_zdata (result);
Dwarf_Sig8_Hash_free (&result->sig8_hash);
__libdw_seterrno (DWARF_E_NOMEM);
free (result);
@@ -301,13 +228,31 @@ global_read (Dwarf *result, Elf *elf, GElf_Ehdr *ehdr)
static Dwarf *
scngrp_read (Dwarf *result, Elf *elf, GElf_Ehdr *ehdr, Elf_Scn *scngrp)
{
+ GElf_Shdr shdr_mem;
+ GElf_Shdr *shdr = gelf_getshdr (scngrp, &shdr_mem);
+ if (shdr == NULL)
+ {
+ Dwarf_Sig8_Hash_free (&result->sig8_hash);
+ __libdw_seterrno (DWARF_E_INVALID_ELF);
+ free (result);
+ return NULL;
+ }
+
+ if ((shdr->sh_flags & SHF_COMPRESSED) != 0
+ && elf_compress (scngrp, 0, 0) < 0)
+ {
+ Dwarf_Sig8_Hash_free (&result->sig8_hash);
+ __libdw_seterrno (DWARF_E_COMPRESSED_ERROR);
+ free (result);
+ return NULL;
+ }
+
/* SCNGRP is the section descriptor for a section group which might
contain debug sections. */
Elf_Data *data = elf_getdata (scngrp, NULL);
if (data == NULL)
{
/* We cannot read the section content. Fail! */
- __libdw_free_zdata (result);
Dwarf_Sig8_Hash_free (&result->sig8_hash);
free (result);
return NULL;
@@ -324,7 +269,6 @@ scngrp_read (Dwarf *result, Elf *elf, GElf_Ehdr *ehdr, Elf_Scn *scngrp)
{
/* A section group refers to a non-existing section. Should
never happen. */
- __libdw_free_zdata (result);
Dwarf_Sig8_Hash_free (&result->sig8_hash);
__libdw_seterrno (DWARF_E_INVALID_ELF);
free (result);
diff --git a/libdw/dwarf_end.c b/libdw/dwarf_end.c
index 2108063..6c6d985 100644
--- a/libdw/dwarf_end.c
+++ b/libdw/dwarf_end.c
@@ -57,24 +57,6 @@ cu_free (void *arg)
}
-#if USE_ZLIB
-void
-internal_function
-__libdw_free_zdata (Dwarf *dwarf)
-{
- unsigned int gzip_mask = dwarf->sectiondata_gzip_mask;
- while (gzip_mask != 0)
- {
- int i = ffs (gzip_mask);
- assert (i > 0);
- --i;
- assert (i < IDX_last);
- free (dwarf->sectiondata[i]);
- gzip_mask &= ~(1U << i);
- }
-}
-#endif
-
int
dwarf_end (Dwarf *dwarf)
{
@@ -110,8 +92,6 @@ dwarf_end (Dwarf *dwarf)
/* Free the pubnames helper structure. */
free (dwarf->pubnames_sets);
- __libdw_free_zdata (dwarf);
-
/* Free the ELF descriptor if necessary. */
if (dwarf->free_elf)
elf_end (dwarf->elf);
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
index 2d233f6..5d095a7 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -147,11 +147,6 @@ struct Dwarf
/* The section data. */
Elf_Data *sectiondata[IDX_last];
-#if USE_ZLIB
- /* The 1 << N bit is set if sectiondata[N] is malloc'd decompressed data. */
- unsigned int sectiondata_gzip_mask:IDX_last;
-#endif
-
/* True if the file has a byte order different from the host. */
bool other_byte_order;
@@ -440,12 +435,6 @@ extern void *__libdw_allocate (Dwarf *dbg, size_t minsize, size_t align)
/* Default OOM handler. */
extern void __libdw_oom (void) __attribute ((noreturn, visibility ("hidden")));
-#if USE_ZLIB
-extern void __libdw_free_zdata (Dwarf *dwarf) internal_function;
-#else
-# define __libdw_free_zdata(dwarf) ((void) (dwarf))
-#endif
-
/* Allocate the internal data for a unit not seen before. */
extern struct Dwarf_CU *__libdw_intern_next_unit (Dwarf *dbg, bool debug_types)
__nonnull_attribute__ (1) internal_function;