diff options
author | Mark Wielaard <mjw@redhat.com> | 2015-12-30 14:18:40 +0100 |
---|---|---|
committer | Mark Wielaard <mjw@redhat.com> | 2016-01-06 14:27:10 +0100 |
commit | c495d754f33bd2ce3eeaaed936d8f045fbf53f30 (patch) | |
tree | a64b525f34ef7084911caafa4fabade4d60897ed | |
parent | 272018bba1f253bae00b5ba280ad0e0f18c04006 (diff) | |
download | android_external_elfutils-c495d754f33bd2ce3eeaaed936d8f045fbf53f30.tar.gz android_external_elfutils-c495d754f33bd2ce3eeaaed936d8f045fbf53f30.tar.bz2 android_external_elfutils-c495d754f33bd2ce3eeaaed936d8f045fbf53f30.zip |
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/ChangeLog | 13 | ||||
-rw-r--r-- | libdw/dwarf_begin_elf.c | 156 | ||||
-rw-r--r-- | libdw/dwarf_end.c | 20 | ||||
-rw-r--r-- | libdw/libdwP.h | 11 |
4 files changed, 63 insertions, 137 deletions
diff --git a/libdw/ChangeLog b/libdw/ChangeLog index 89d03269..fc80e8d2 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 63532fd8..6f25e429 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 2108063d..6c6d985a 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 2d233f63..5d095a7e 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; |