diff options
| author | Mark Wielaard <[email protected]> | 2011-02-24 16:00:17 +0100 |
|---|---|---|
| committer | Mark Wielaard <[email protected]> | 2011-02-24 16:36:31 +0100 |
| commit | 9ee5559ff57d5566f533d3d77e58988aad2da71d (patch) | |
| tree | 174cad0d7c51799130f96f482f9a0051255a0704 /libdw | |
| parent | d92fb224eb7439e3170d4d37b3d8bffab6f7f2c1 (diff) | |
| parent | 725aad5d2f8b78ed21a5e253fb38f9722c2c8b2d (diff) | |
Merge branch 'master' into mjw/dwarf_output
Conflicts:
libdw/ChangeLog
src/readelf.c
Diffstat (limited to 'libdw')
| -rw-r--r-- | libdw/ChangeLog | 11 | ||||
| -rw-r--r-- | libdw/dwarf_begin_elf.c | 83 | ||||
| -rw-r--r-- | libdw/dwarf_end.c | 24 | ||||
| -rw-r--r-- | libdw/libdwP.h | 13 |
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; |
