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 | |
| parent | d92fb224eb7439e3170d4d37b3d8bffab6f7f2c1 (diff) | |
| parent | 725aad5d2f8b78ed21a5e253fb38f9722c2c8b2d (diff) | |
Merge branch 'master' into mjw/dwarf_output
Conflicts:
libdw/ChangeLog
src/readelf.c
| -rw-r--r-- | NEWS | 4 | ||||
| -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 | ||||
| -rw-r--r-- | src/ChangeLog | 18 | ||||
| -rw-r--r-- | src/dwarfstrings.c | 28 | ||||
| -rw-r--r-- | src/readelf.c | 86 |
8 files changed, 228 insertions, 39 deletions
@@ -1,3 +1,7 @@ +Version 0.153 + +libdw: Support reading .zdebug_* DWARF sections compressed via zlib. + Version 0.152 Various build and warning nits fixed for newest GCC and Autoconf. 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; diff --git a/src/ChangeLog b/src/ChangeLog index 096c4e7a..938e7a29 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,21 @@ +2011-02-23 Roland McGrath <[email protected]> + + * readelf.c (section_name): New function. + (print_debug_abbrev_section): Use it instead of constant. + (print_debug_aranges_section): Likewise. + (print_debug_ranges_section): Likewise. + (print_debug_units): Likewise. + (print_debug_line_section): Likewise. + (print_debug_loc_section): Likewise. + (print_debug_macinfo_section): Likewise. + (print_debug_pubnames_section): Likewise. + (print_debug_str_section): Likewise. + (print_debug) [USE_ZLIB]: Match .zdebug_* sections too. + (print_debug_abbrev_section): Use decoded d_size, not sh_size. + (print_debug_str_section): Likewise. + + * readelf.c (dwarf_attr_string): Grok DW_AT_GNU_odr_signature. + 2011-02-11 Roland McGrath <[email protected]> * elfcmp.c (verbose): New variable. diff --git a/src/dwarfstrings.c b/src/dwarfstrings.c index b340f026..3909e131 100644 --- a/src/dwarfstrings.c +++ b/src/dwarfstrings.c @@ -97,6 +97,9 @@ dwarf_tag_string (unsigned int tag) [DW_TAG_mutable_type] = "mutable_type", [DW_TAG_condition] = "condition", [DW_TAG_shared_type] = "shared_type", + [DW_TAG_type_unit] = "type_unit", + [DW_TAG_rvalue_reference_type] = "rvalue_reference_type", + [DW_TAG_template_alias] = "template_alias", }; const unsigned int nknown_tags = (sizeof (known_tags) / sizeof (known_tags[0])); @@ -126,6 +129,26 @@ dwarf_tag_string (unsigned int tag) result = "class_template"; break; + case DW_TAG_GNU_BINCL: + result = "GNU_BINCL"; + break; + + case DW_TAG_GNU_EINCL: + result = "GNU_EINCL"; + break; + + case DW_TAG_GNU_template_template_param: + result = "GNU_template_template_param"; + break; + + case DW_TAG_GNU_template_parameter_pack: + result = "GNU_template_parameter_pack"; + break; + + case DW_TAG_GNU_formal_parameter_pack: + result = "GNU_formal_parameter_pack"; + break; + default: if (tag < DW_TAG_lo_user) snprintf (buf, sizeof buf, gettext ("unknown tag %hx"), tag); @@ -233,6 +256,11 @@ dwarf_attr_string (unsigned int attrnum) [DW_AT_elemental] = "elemental", [DW_AT_pure] = "pure", [DW_AT_recursive] = "recursive", + [DW_AT_signature] = "signature", + [DW_AT_main_subprogram] = "main_subprogram", + [DW_AT_data_bit_offset] = "data_bit_offset", + [DW_AT_const_expr] = "const_expr", + [DW_AT_enum_class] = "enum_class", [DW_AT_linkage_name] = "linkage_name", }; const unsigned int nknown_attrs = (sizeof (known_attrs) diff --git a/src/readelf.c b/src/readelf.c index 30c2be09..808511ef 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -1,5 +1,5 @@ /* Print information from ELF file in human-readable form. - Copyright (C) 1999-2010 Red Hat, Inc. + Copyright (C) 1999-2011 Red Hat, Inc. This file is part of Red Hat elfutils. Written by Ulrich Drepper <[email protected]>, 1999. @@ -1155,6 +1155,13 @@ print_phdr (Ebl *ebl, GElf_Ehdr *ehdr) } +static const char * +section_name (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr) +{ + return elf_strptr (ebl->elf, ehdr->e_shstrndx, shdr->sh_name) ?: "???"; +} + + static void handle_scngrp (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) { @@ -3777,16 +3784,16 @@ skip_listptr_hole (struct listptr_table *table, size_t *idxp, static void print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)), - Ebl *ebl __attribute__ ((unused)), - GElf_Ehdr *ehdr __attribute__ ((unused)), + Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg) { printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n" " [ Code]\n"), - elf_ndxscn (scn), ".debug_abbrev", (uint64_t) shdr->sh_offset); + elf_ndxscn (scn), section_name (ebl, ehdr, shdr), + (uint64_t) shdr->sh_offset); Dwarf_Off offset = 0; - while (offset < shdr->sh_size) + while (offset < dbg->sectiondata[IDX_debug_abbrev]->d_size) { printf (gettext ("\nAbbreviation section at offset %" PRIu64 ":\n"), offset); @@ -3848,8 +3855,7 @@ print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)), takes care of it. */ static void print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)), - Ebl *ebl __attribute__ ((unused)), - GElf_Ehdr *ehdr, Elf_Scn *scn, + Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg) { Dwarf_Aranges *aranges; @@ -3866,7 +3872,8 @@ print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)), "\ \nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entries:\n", cnt), - elf_ndxscn (scn), ".debug_aranges", (uint64_t) shdr->sh_offset, cnt); + elf_ndxscn (scn), section_name (ebl, ehdr, shdr), + (uint64_t) shdr->sh_offset, cnt); /* Compute floor(log16(cnt)). */ size_t tmp = cnt; @@ -3904,8 +3911,8 @@ print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)), /* Print content of DWARF .debug_ranges section. */ static void print_debug_ranges_section (Dwfl_Module *dwflmod, - Ebl *ebl __attribute__ ((unused)), - GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr, + Ebl *ebl, GElf_Ehdr *ehdr, + Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg) { Elf_Data *data = elf_rawdata (scn, NULL); @@ -3919,7 +3926,8 @@ print_debug_ranges_section (Dwfl_Module *dwflmod, printf (gettext ("\ \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"), - elf_ndxscn (scn), ".debug_ranges", (uint64_t) shdr->sh_offset); + elf_ndxscn (scn), section_name (ebl, ehdr, shdr), + (uint64_t) shdr->sh_offset); sort_listptr (&known_rangelistptr, "rangelistptr"); size_t listptr_idx = 0; @@ -5015,14 +5023,12 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) static void print_debug_units (Dwfl_Module *dwflmod, - Ebl *ebl __attribute__ ((unused)), - GElf_Ehdr *ehdr __attribute__ ((unused)), - Elf_Scn *scn, - GElf_Shdr *shdr, Dwarf *dbg, - bool debug_types) + Ebl *ebl, GElf_Ehdr *ehdr, + Elf_Scn *scn, GElf_Shdr *shdr, + Dwarf *dbg, bool debug_types) { const bool silent = !(print_debug_sections & section_info); - const char *secname = debug_types ? ".debug_types" : ".debug_info"; + const char *secname = section_name (ebl, ehdr, shdr); if (!silent) printf (gettext ("\ @@ -5185,13 +5191,13 @@ print_debug_types_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, static void -print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, - GElf_Ehdr *ehdr __attribute__ ((unused)), +print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg) { printf (gettext ("\ \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"), - elf_ndxscn (scn), ".debug_line", (uint64_t) shdr->sh_offset); + elf_ndxscn (scn), section_name (ebl, ehdr, shdr), + (uint64_t) shdr->sh_offset); if (shdr->sh_size == 0) return; @@ -5224,7 +5230,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, { invalid_data: error (0, 0, gettext ("invalid data in section [%zu] '%s'"), - elf_ndxscn (scn), ".debug_line"); + elf_ndxscn (scn), section_name (ebl, ehdr, shdr)); return; } unit_length = read_8ubyte_unaligned_inc (dbg, linep); @@ -5292,7 +5298,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, error (0, 0, gettext ("invalid data at offset %tu in section [%zu] '%s'"), linep - (const unsigned char *) data->d_buf, - elf_ndxscn (scn), ".debug_line"); + elf_ndxscn (scn), section_name (ebl, ehdr, shdr)); linep = lineendp; continue; } @@ -5675,7 +5681,7 @@ advance address by fixed value %u to %s\n"), static void print_debug_loc_section (Dwfl_Module *dwflmod, - Ebl *ebl __attribute__ ((unused)), GElf_Ehdr *ehdr, + Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg) { Elf_Data *data = elf_rawdata (scn, NULL); @@ -5689,7 +5695,8 @@ print_debug_loc_section (Dwfl_Module *dwflmod, printf (gettext ("\ \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"), - elf_ndxscn (scn), ".debug_loc", (uint64_t) shdr->sh_offset); + elf_ndxscn (scn), section_name (ebl, ehdr, shdr), + (uint64_t) shdr->sh_offset); sort_listptr (&known_loclistptr, "loclistptr"); size_t listptr_idx = 0; @@ -5798,13 +5805,13 @@ mac_compare (const void *p1, const void *p2) static void print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)), - Ebl *ebl __attribute__ ((unused)), - GElf_Ehdr *ehdr __attribute__ ((unused)), + Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg) { printf (gettext ("\ \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"), - elf_ndxscn (scn), ".debug_macinfo", (uint64_t) shdr->sh_offset); + elf_ndxscn (scn), section_name (ebl, ehdr, shdr), + (uint64_t) shdr->sh_offset); putc_unlocked ('\n', stdout); /* There is no function in libdw to iterate over the raw content of @@ -5970,12 +5977,12 @@ print_pubnames (Dwarf *dbg __attribute__ ((unused)), Dwarf_Global *global, /* Print the known exported symbols in the DWARF section '.debug_pubnames'. */ static void print_debug_pubnames_section (Dwfl_Module *dwflmod __attribute__ ((unused)), - Ebl *ebl __attribute__ ((unused)), - GElf_Ehdr *ehdr __attribute__ ((unused)), + Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg) { printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"), - elf_ndxscn (scn), ".debug_pubnames", (uint64_t) shdr->sh_offset); + elf_ndxscn (scn), section_name (ebl, ehdr, shdr), + (uint64_t) shdr->sh_offset); int n = 0; (void) dwarf_getpubnames (dbg, print_pubnames, &n, 0); @@ -5984,12 +5991,13 @@ print_debug_pubnames_section (Dwfl_Module *dwflmod __attribute__ ((unused)), /* Print the content of the DWARF string section '.debug_str'. */ static void print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)), - Ebl *ebl __attribute__ ((unused)), - GElf_Ehdr *ehdr __attribute__ ((unused)), + Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg) { + const size_t sh_size = dbg->sectiondata[IDX_debug_str]->d_size; + /* Compute floor(log16(shdr->sh_size)). */ - GElf_Addr tmp = shdr->sh_size; + GElf_Addr tmp = sh_size; int digits = 1; while (tmp >= 16) { @@ -6001,12 +6009,12 @@ print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)), printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n" " %*s String\n"), elf_ndxscn (scn), - ".debug_str", (uint64_t) shdr->sh_offset, + section_name (ebl, ehdr, shdr), (uint64_t) shdr->sh_offset, /* TRANS: the debugstr| prefix makes the string unique. */ digits + 2, sgettext ("debugstr|Offset")); Dwarf_Off offset = 0; - while (offset < shdr->sh_size) + while (offset < sh_size) { size_t len; const char *str = dwarf_getstring (dbg, offset, &len); @@ -6352,7 +6360,13 @@ print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr) int n; for (n = 0; n < ndebug_sections; ++n) - if (strcmp (name, debug_sections[n].name) == 0) + if (strcmp (name, debug_sections[n].name) == 0 +#if USE_ZLIB + || (name[0] == '.' && name[1] == 'z' + && debug_sections[n].name[1] == 'd' + && strcmp (&name[2], &debug_sections[n].name[1]) == 0) +#endif + ) { if ((print_debug_sections | implicit_debug_sections) & debug_sections[n].bitmask) |
