]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
dwarf_begin_elf: new error for compression failure
authorJonathan Lebon <jlebon@redhat.com>
Mon, 11 May 2015 19:38:14 +0000 (15:38 -0400)
committerMark Wielaard <mjw@redhat.com>
Wed, 13 May 2015 15:43:25 +0000 (17:43 +0200)
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>
libdw/ChangeLog
libdw/dwarf_begin_elf.c
libdw/dwarf_error.c
libdw/libdwP.h

index 604a9abbba9963baf16cbdcdd2ea10b9d82a2f62..f8eca492c6fad1a6894fa0ed3be82a7f570d57ae 100644 (file)
@@ -1,3 +1,12 @@
+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
index 09ea5b11cfe8c9c12546fcb93b0b2869c33f1c40..4e0d590d7ab46bdb12d62f47f4ef5ca0c4457aa0 100644 (file)
@@ -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;
 }
 
index aa97a68eb9d1ac7557ae8f09a1f3ab0f5a4882b0..fe389995c961846e105f01312dbfaeafc269d18d 100644 (file)
@@ -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"),
index fc7796016112d44c93117b6d68c031c41cdf5121..2d233f63746c3c18b03449eaf8ec90fde21cca7b 100644 (file)
@@ -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,