diff options
author | Jonathan Lebon <jlebon@redhat.com> | 2015-05-11 15:38:14 -0400 |
---|---|---|
committer | Mark Wielaard <mjw@redhat.com> | 2015-05-13 17:43:25 +0200 |
commit | 987e3d722d1d3879c51f4ed7ab1da03a75f5f38c (patch) | |
tree | a4199e9b8135570eaeb18e25f224e8d1f903aabb /libdw | |
parent | 90659075adc29213ec0f86fd08f39c7e571fb061 (diff) | |
download | elfutils-987e3d722d1d3879c51f4ed7ab1da03a75f5f38c.tar.gz |
dwarf_begin_elf: new error for compression failure
In order to provide better feedback to users, a distinction is made
between finding no dwarf info (E_NO_DWARF) and finding dwarf info but
which is compressed and failed to decompress (E_COMPRESSED_ERROR). This
can occur for example if elfutils was built without zlib support, or if
the compressed section is invalid.
Signed-off-by: Jonathan Lebon <jlebon@redhat.com>
Signed-off-by: Mark Wielaard <mjw@redhat.com>
Diffstat (limited to 'libdw')
-rw-r--r-- | libdw/ChangeLog | 9 | ||||
-rw-r--r-- | libdw/dwarf_begin_elf.c | 147 | ||||
-rw-r--r-- | libdw/dwarf_error.c | 1 | ||||
-rw-r--r-- | libdw/libdwP.h | 1 |
4 files changed, 97 insertions, 61 deletions
diff --git a/libdw/ChangeLog b/libdw/ChangeLog index 604a9abb..f8eca492 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,5 +1,14 @@ 2015-05-11 Jonathan Lebon <jlebon@redhat.com> + * libdwP.h (DWARF_E_COMPRESSED_ERROR): New enumerator. + * dwarf_error.c (errmsgs): Add DWARF_E_COMPRESSED_ERROR message. + * dwarf_begin_elf.c (inflate_section): New static function, lifted + from... + (check_section): ... here. Call inflate_section, set libdw errno to + DWARF_E_COMPRESSED_ERROR if .debug_info section couldn't be inflated. + +2015-05-11 Jonathan Lebon <jlebon@redhat.com> + * dwarf_begin_elf.c (check_section): Add compressed flag. Always check for .zdebug sections. Only wrap decompression in #if USE_ZLIB. diff --git a/libdw/dwarf_begin_elf.c b/libdw/dwarf_begin_elf.c index 09ea5b11..4e0d590d 100644 --- a/libdw/dwarf_begin_elf.c +++ b/libdw/dwarf_begin_elf.c @@ -71,6 +71,70 @@ 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) { @@ -146,71 +210,32 @@ check_section (Dwarf *result, GElf_Ehdr *ehdr, Elf_Scn *scn, bool inscngrp) /* We can now read the section data into results. */ if (!compressed) result->sectiondata[cnt] = data; -#if USE_ZLIB else { - /* A compressed section. */ - - /* 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 result; - - 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 result; - - Elf_Data *zdata = malloc (sizeof (Elf_Data) + size); - if (unlikely (zdata == NULL)) - return result; - - 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); - else - { - result->sectiondata[cnt] = zdata; - result->sectiondata_gzip_mask |= 1U << cnt; - } - } + /* 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; + } + } + return result; } diff --git a/libdw/dwarf_error.c b/libdw/dwarf_error.c index aa97a68e..fe389995 100644 --- a/libdw/dwarf_error.c +++ b/libdw/dwarf_error.c @@ -62,6 +62,7 @@ static const char *errmsgs[] = [DWARF_E_IO_ERROR] = N_("I/O error"), [DWARF_E_INVALID_ELF] = N_("invalid ELF file"), [DWARF_E_NO_DWARF] = N_("no DWARF information"), + [DWARF_E_COMPRESSED_ERROR] = N_("cannot decompress DWARF"), [DWARF_E_NOELF] = N_("no ELF file"), [DWARF_E_GETEHDR_ERROR] = N_("cannot get ELF header"), [DWARF_E_NOMEM] = N_("out of memory"), diff --git a/libdw/libdwP.h b/libdw/libdwP.h index fc779601..2d233f63 100644 --- a/libdw/libdwP.h +++ b/libdw/libdwP.h @@ -97,6 +97,7 @@ enum DWARF_E_IO_ERROR, DWARF_E_INVALID_ELF, DWARF_E_NO_DWARF, + DWARF_E_COMPRESSED_ERROR, DWARF_E_NOELF, DWARF_E_GETEHDR_ERROR, DWARF_E_NOMEM, |