summaryrefslogtreecommitdiffstats
path: root/libdw
diff options
context:
space:
mode:
authorMark Wielaard <[email protected]>2011-02-24 16:00:17 +0100
committerMark Wielaard <[email protected]>2011-02-24 16:36:31 +0100
commit9ee5559ff57d5566f533d3d77e58988aad2da71d (patch)
tree174cad0d7c51799130f96f482f9a0051255a0704 /libdw
parentd92fb224eb7439e3170d4d37b3d8bffab6f7f2c1 (diff)
parent725aad5d2f8b78ed21a5e253fb38f9722c2c8b2d (diff)
Merge branch 'master' into mjw/dwarf_output
Conflicts: libdw/ChangeLog src/readelf.c
Diffstat (limited to 'libdw')
-rw-r--r--libdw/ChangeLog11
-rw-r--r--libdw/dwarf_begin_elf.c83
-rw-r--r--libdw/dwarf_end.c24
-rw-r--r--libdw/libdwP.h13
4 files changed, 128 insertions, 3 deletions
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 1b85aebf..d9f743e0 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -3,6 +3,17 @@
* c++/dwarf-knowledge.cc (expected_value_space):
Grok DW_AT_GNU_odr_signature.
+2011-02-23 Roland McGrath <[email protected]>
+
+ * libdwP.h (struct Dwarf) [USE_ZLIB]: New member sectiondata_gzip_mask.
+ Declare __libdw_free_zdata.
+ * dwarf_end.c [USE_ZLIB] (__libdw_free_zdata): New function.
+ (dwarf_end): Call it.
+
+ * dwarf_begin_elf.c (valid_p): Likewise.
+ (check_section, scngrp_read): Likewise.
+ (check_section) [USE_ZLIB]: Grok .z* flavors of sections.
+
2010-12-07 Petr Machata <[email protected]>
* c++/subr.hh (sharing_stack::element::pop): Remove. Move the
diff --git a/libdw/dwarf_begin_elf.c b/libdw/dwarf_begin_elf.c
index b5fb7c91..9ec7d51f 100644
--- a/libdw/dwarf_begin_elf.c
+++ b/libdw/dwarf_begin_elf.c
@@ -1,5 +1,5 @@
/* Create descriptor from ELF descriptor for processing file.
- Copyright (C) 2002-2010 Red Hat, Inc.
+ Copyright (C) 2002-2011 Red Hat, Inc.
This file is part of Red Hat elfutils.
Written by Ulrich Drepper <[email protected]>, 2002.
@@ -61,6 +61,13 @@
#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][17] =
@@ -117,6 +124,7 @@ check_section (Dwarf *result, GElf_Ehdr *ehdr, Elf_Scn *scn, bool inscngrp)
{
/* The section name must be valid. Otherwise is the ELF file
invalid. */
+ __libdw_free_zdata (result);
__libdw_seterrno (DWARF_E_INVALID_ELF);
free (result);
return NULL;
@@ -141,6 +149,76 @@ check_section (Dwarf *result, GElf_Ehdr *ehdr, Elf_Scn *scn, bool inscngrp)
break;
}
+#if USE_ZLIB
+ else if (scnname[0] == '.' && scnname[1] == 'z'
+ && strcmp (&scnname[2], &dwarf_scnnames[cnt][1]) == 0)
+ {
+ /* A compressed section. */
+
+ if (unlikely (result->sectiondata[cnt] != NULL))
+ /* A section appears twice. That's bad. We ignore the section. */
+ break;
+
+ /* Get the section data. */
+ Elf_Data *data = elf_getdata (scn, NULL);
+ if (data != NULL && data->d_size != 0)
+ {
+ /* 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))
+ break;
+
+ uint64_t size;
+ memcpy (&size, data->d_buf + 4, sizeof size);
+ size = be64toh (size);
+
+ Elf_Data *zdata = malloc (sizeof (Elf_Data) + size);
+ if (unlikely (zdata == NULL))
+ break;
+
+ 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;
+ }
+ }
+
+ break;
+ }
+#endif
return result;
}
@@ -159,6 +237,7 @@ valid_p (Dwarf *result)
if (likely (result != NULL)
&& unlikely (result->sectiondata[IDX_debug_info] == NULL))
{
+ __libdw_free_zdata (result);
__libdw_seterrno (DWARF_E_NO_DWARF);
free (result);
result = NULL;
@@ -189,6 +268,7 @@ scngrp_read (Dwarf *result, Elf *elf, GElf_Ehdr *ehdr, Elf_Scn *scngrp)
if (data == NULL)
{
/* We cannot read the section content. Fail! */
+ __libdw_free_zdata (result);
free (result);
return NULL;
}
@@ -204,6 +284,7 @@ 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);
__libdw_seterrno (DWARF_E_INVALID_ELF);
free (result);
return NULL;
diff --git a/libdw/dwarf_end.c b/libdw/dwarf_end.c
index ec10542e..1e733cae 100644
--- a/libdw/dwarf_end.c
+++ b/libdw/dwarf_end.c
@@ -1,5 +1,5 @@
/* Release debugging handling context.
- Copyright (C) 2002-2010 Red Hat, Inc.
+ Copyright (C) 2002-2011 Red Hat, Inc.
This file is part of Red Hat elfutils.
Written by Ulrich Drepper <[email protected]>, 2002.
@@ -54,6 +54,8 @@
#include <search.h>
#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
#include "libdwP.h"
#include "cfi.h"
@@ -76,6 +78,24 @@ 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 *dwarf;
@@ -106,6 +126,8 @@ dwarf_end (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 8d49f501..a58d0665 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -1,5 +1,5 @@
/* Internal definitions for libdwarf.
- Copyright (C) 2002-2010 Red Hat, Inc.
+ Copyright (C) 2002-2011 Red Hat, Inc.
This file is part of Red Hat elfutils.
Written by Ulrich Drepper <[email protected]>, 2002.
@@ -150,6 +150,11 @@ 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;
@@ -390,6 +395,12 @@ 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;