summaryrefslogtreecommitdiff
path: root/libdw
diff options
context:
space:
mode:
authorJonathan Lebon <jlebon@redhat.com>2015-05-11 15:38:14 -0400
committerMark Wielaard <mjw@redhat.com>2015-05-13 17:43:25 +0200
commit987e3d722d1d3879c51f4ed7ab1da03a75f5f38c (patch)
treea4199e9b8135570eaeb18e25f224e8d1f903aabb /libdw
parent90659075adc29213ec0f86fd08f39c7e571fb061 (diff)
downloadelfutils-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/ChangeLog9
-rw-r--r--libdw/dwarf_begin_elf.c147
-rw-r--r--libdw/dwarf_error.c1
-rw-r--r--libdw/libdwP.h1
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,