diff options
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | libdw/ChangeLog | 11 | ||||
-rw-r--r-- | libdw/dwarf_end.c | 1 | ||||
-rw-r--r-- | libdw/dwarf_nextcu.c | 2 | ||||
-rw-r--r-- | libdw/dwarf_offdie.c | 36 | ||||
-rw-r--r-- | libdw/libdw.h | 9 | ||||
-rw-r--r-- | libdw/libdw.map | 1 | ||||
-rw-r--r-- | libdw/libdwP.h | 7 | ||||
-rw-r--r-- | libdw/libdw_findcu.c | 21 | ||||
-rw-r--r-- | src/ChangeLog | 6 | ||||
-rw-r--r-- | src/readelf.c | 69 |
11 files changed, 124 insertions, 43 deletions
@@ -1,13 +1,13 @@ Version 0.148: -libdw: Accept DWARF 4 formats. +libdw: Accept DWARF 4 format: new functions dwarf_next_unit, dwarf_offdie_types. New functions dwarf_lineisa, dwarf_linediscriminator, dwarf_lineop_index. New function dwarf_cfi_validate_fde. libdwfl: Fixes in core-file handling, support cores from PIEs. When working from build IDs, don't open a named file that mismatches. -readelf: Handle some DWARF 4 format bits. +readelf: Handle DWARF 4 formats. Version 0.147: diff --git a/libdw/ChangeLog b/libdw/ChangeLog index e446b507..34c7ba31 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,5 +1,16 @@ 2010-06-20 Roland McGrath <roland@redhat.com> + * libdw_findcu.c (__libdw_findcu): Take new flag argument, + to search TUs instead of CUs. + * libdwP.h: Update decl. + (struct Dwarf): New member tu_tree. + * dwarf_end.c (dwarf_end): Clean up tu_tree. + * dwarf_offdie.c (do_offdie): New function, broken out of ... + (dwarf_offdie): ... here. + (dwarf_offdie_types): New function. + * libdw.h: Declare it. + * libdw.map (ELFUTILS_0.148): Add it. + * libdwP.h (CUDIE): Use cu_data. * dwarf_formblock.c: Likewise. * dwarf_formref_die.c: Likewise. diff --git a/libdw/dwarf_end.c b/libdw/dwarf_end.c index 80dac7b7..ec10542e 100644 --- a/libdw/dwarf_end.c +++ b/libdw/dwarf_end.c @@ -92,6 +92,7 @@ dwarf_end (dwarf) allocated separately, but the abbreviation hash tables need to be handled. */ tdestroy (dwarf->cu_tree, cu_free); + tdestroy (dwarf->tu_tree, cu_free); struct libdw_memblock *memp = dwarf->mem_tail; /* The first block is allocated together with the Dwarf object. */ diff --git a/libdw/dwarf_nextcu.c b/libdw/dwarf_nextcu.c index 288ee95e..2e8f4d79 100644 --- a/libdw/dwarf_nextcu.c +++ b/libdw/dwarf_nextcu.c @@ -63,7 +63,7 @@ dwarf_next_unit (dwarf, off, next_off, header_sizep, versionp, abbrev_offsetp, Dwarf_Off off; Dwarf_Off *next_off; size_t *header_sizep; - uint16_t *versionp; + Dwarf_Half *versionp; Dwarf_Off *abbrev_offsetp; uint8_t *address_sizep; uint8_t *offset_sizep; diff --git a/libdw/dwarf_offdie.c b/libdw/dwarf_offdie.c index a9886f2c..925fe512 100644 --- a/libdw/dwarf_offdie.c +++ b/libdw/dwarf_offdie.c @@ -1,5 +1,5 @@ /* Return DIE at given offset. - Copyright (C) 2002, 2003, 2005 Red Hat, Inc. + Copyright (C) 2002-2010 Red Hat, Inc. This file is part of Red Hat elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -56,16 +56,15 @@ #include "libdwP.h" -Dwarf_Die * -dwarf_offdie (dbg, offset, result) - Dwarf *dbg; - Dwarf_Off offset; - Dwarf_Die *result; +static Dwarf_Die * +do_offdie (Dwarf *dbg, Dwarf_Off offset, Dwarf_Die *result, bool debug_types) { if (dbg == NULL) return NULL; - if (offset >= dbg->sectiondata[IDX_debug_info]->d_size) + Elf_Data *const data = dbg->sectiondata[debug_types ? IDX_debug_types + : IDX_debug_info]; + if (offset >= data->d_size) { __libdw_seterrno (DWARF_E_INVALID_DWARF); return NULL; @@ -75,10 +74,10 @@ dwarf_offdie (dbg, offset, result) determined any of the information. */ memset (result, '\0', sizeof (Dwarf_Die)); - result->addr = (char *) dbg->sectiondata[IDX_debug_info]->d_buf + offset; + result->addr = (char *) data->d_buf + offset; /* Get the CU. */ - result->cu = __libdw_findcu (dbg, offset); + result->cu = __libdw_findcu (dbg, offset, debug_types); if (result->cu == NULL) { /* This should never happen. The input file is malformed. */ @@ -88,4 +87,23 @@ dwarf_offdie (dbg, offset, result) return result; } + + +Dwarf_Die * +dwarf_offdie (dbg, offset, result) + Dwarf *dbg; + Dwarf_Off offset; + Dwarf_Die *result; +{ + return do_offdie (dbg, offset, result, false); +} INTDEF(dwarf_offdie) + +Dwarf_Die * +dwarf_offdie_types (dbg, offset, result) + Dwarf *dbg; + Dwarf_Off offset; + Dwarf_Die *result; +{ + return do_offdie (dbg, offset, result, true); +} diff --git a/libdw/libdw.h b/libdw/libdw.h index d244d919..d3e7a5ab 100644 --- a/libdw/libdw.h +++ b/libdw/libdw.h @@ -298,7 +298,7 @@ extern int dwarf_nextcu (Dwarf *dwarf, Dwarf_Off off, Dwarf_Off *next_off, null, this reads a type unit from the .debug_types section; otherwise this reads a CU from the .debug_info section. */ extern int dwarf_next_unit (Dwarf *dwarf, Dwarf_Off off, Dwarf_Off *next_off, - size_t *header_sizep, uint16_t *versionp, + size_t *header_sizep, Dwarf_Half *versionp, Dwarf_Off *abbrev_offsetp, uint8_t *address_sizep, uint8_t *offset_sizep, uint64_t *type_signaturep, Dwarf_Off *type_offsetp) @@ -346,10 +346,15 @@ extern Dwarf_CFI *dwarf_getcfi_elf (Elf *elf); extern int dwarf_cfi_end (Dwarf_CFI *cache); -/* Return DIE at given offset. */ +/* Return DIE at given offset in .debug_types section. */ extern Dwarf_Die *dwarf_offdie (Dwarf *dbg, Dwarf_Off offset, Dwarf_Die *result) __nonnull_attribute__ (3); +/* Return DIE at given offset in .debug_types section. */ +extern Dwarf_Die *dwarf_offdie_types (Dwarf *dbg, Dwarf_Off offset, + Dwarf_Die *result) + __nonnull_attribute__ (3); + /* Return offset of DIE. */ extern Dwarf_Off dwarf_dieoffset (Dwarf_Die *die); diff --git a/libdw/libdw.map b/libdw/libdw.map index 9cf8cd38..954fff67 100644 --- a/libdw/libdw.map +++ b/libdw/libdw.map @@ -247,4 +247,5 @@ ELFUTILS_0.148 { dwarf_lineop_index; dwarf_next_unit; + dwarf_offdie_types; } ELFUTILS_0.146; diff --git a/libdw/libdwP.h b/libdw/libdwP.h index 558f961c..bb0ae1d1 100644 --- a/libdw/libdwP.h +++ b/libdw/libdwP.h @@ -171,9 +171,10 @@ struct Dwarf void *cu_tree; Dwarf_Off next_cu_offset; - /* Hash table for .debug_types type units. */ - Dwarf_Sig8_Hash sig8_hash; + /* Search tree and sig8 hash table for .debug_types type units. */ + void *tu_tree; Dwarf_Off next_tu_offset; + Dwarf_Sig8_Hash sig8_hash; /* Address ranges. */ Dwarf_Aranges *aranges; @@ -389,7 +390,7 @@ extern struct Dwarf_CU *__libdw_intern_next_unit (Dwarf *dbg, bool debug_types) __nonnull_attribute__ (1) internal_function; /* Find CU for given offset. */ -extern struct Dwarf_CU *__libdw_findcu (Dwarf *dbg, Dwarf_Off offset) +extern struct Dwarf_CU *__libdw_findcu (Dwarf *dbg, Dwarf_Off offset, bool tu) __nonnull_attribute__ (1) internal_function; /* Return tag of given DIE. */ diff --git a/libdw/libdw_findcu.c b/libdw/libdw_findcu.c index 7e0b3568..8e5f9e9b 100644 --- a/libdw/libdw_findcu.c +++ b/libdw/libdw_findcu.c @@ -136,17 +136,22 @@ findcu_cb (const void *arg1, const void *arg2) } struct Dwarf_CU * -__libdw_findcu (dbg, start) +__libdw_findcu (dbg, start, debug_types) Dwarf *dbg; Dwarf_Off start; + bool debug_types; { + void **tree = debug_types ? &dbg->tu_tree : &dbg->cu_tree; + Dwarf_Off *next_offset + = debug_types ? &dbg->next_tu_offset : &dbg->next_cu_offset; + /* Maybe we already know that CU. */ struct Dwarf_CU fake = { .start = start, .end = 0 }; - struct Dwarf_CU **found = tfind (&fake, &dbg->cu_tree, findcu_cb); + struct Dwarf_CU **found = tfind (&fake, tree, findcu_cb); if (found != NULL) return *found; - if (start < dbg->next_cu_offset) + if (start < *next_offset) { __libdw_seterrno (DWARF_E_INVALID_DWARF); return NULL; @@ -155,22 +160,22 @@ __libdw_findcu (dbg, start) /* No. Then read more CUs. */ while (1) { - Dwarf_Off oldoff = dbg->next_cu_offset; - struct Dwarf_CU *newp = __libdw_intern_next_unit (dbg, false); + Dwarf_Off oldoff = *next_offset; + struct Dwarf_CU *newp = __libdw_intern_next_unit (dbg, debug_types); if (newp == NULL) return NULL; /* Add the new entry to the search tree. */ - if (tsearch (newp, &dbg->cu_tree, findcu_cb) == NULL) + if (tsearch (newp, tree, findcu_cb) == NULL) { /* Something went wrong. Undo the operation. */ - dbg->next_cu_offset = oldoff; + *next_offset = oldoff; __libdw_seterrno (DWARF_E_NOMEM); return NULL; } /* Is this the one we are looking for? */ - if (start < dbg->next_cu_offset) + if (start < *next_offset) // XXX Match exact offset. return newp; } diff --git a/src/ChangeLog b/src/ChangeLog index 72d34a8f..59e8b8bc 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,5 +1,11 @@ 2010-06-20 Roland McGrath <roland@redhat.com> + * readelf.c (print_debug_units): New function, broken out of ... + (print_debug_info_section): ... here. Call it. + (print_debug_types_section): New function. + (enum section_e): Add section_types alias for section_info. + (print_debug): Add types to the sections table. + * readelf.c (print_debug_frame_section): Handle version 4 format. * readelf.c (print_debug_line_section): Handle version 4 format. diff --git a/src/readelf.c b/src/readelf.c index 2215e861..f5be7f14 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -180,7 +180,8 @@ static enum section_e section_abbrev = 1, /* .debug_abbrev */ section_aranges = 2, /* .debug_aranges */ section_frame = 4, /* .debug_frame or .eh_frame & al. */ - section_info = 8, /* .debug_info */ + section_info = 8, /* .debug_info, .debug_types */ + section_types = section_info, section_line = 16, /* .debug_line */ section_loc = 32, /* .debug_loc */ section_pubnames = 64, /* .debug_pubnames */ @@ -5385,17 +5386,19 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) return DWARF_CB_OK; } - static void -print_debug_info_section (Dwfl_Module *dwflmod, - Ebl *ebl __attribute__ ((unused)), - GElf_Ehdr *ehdr __attribute__ ((unused)), - Elf_Scn *scn, - GElf_Shdr *shdr, Dwarf *dbg) +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) { + const char *secname = debug_types ? ".debug_types" : ".debug_info"; + printf (gettext ("\ \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n [Offset]\n"), - elf_ndxscn (scn), ".debug_info", (uint64_t) shdr->sh_offset); + elf_ndxscn (scn), secname, (uint64_t) shdr->sh_offset); /* If the section is empty we don't have to do anything. */ if (shdr->sh_size == 0) @@ -5408,20 +5411,34 @@ print_debug_info_section (Dwfl_Module *dwflmod, /* New compilation unit. */ size_t cuhl; - //Dwarf_Half version; + Dwarf_Half version; Dwarf_Off abbroffset; uint8_t addrsize; uint8_t offsize; Dwarf_Off nextcu; + uint64_t typesig; + Dwarf_Off typeoff; next_cu: - if (dwarf_nextcu (dbg, offset, &nextcu, &cuhl, &abbroffset, &addrsize, - &offsize) != 0) + if (dwarf_next_unit (dbg, offset, &nextcu, &cuhl, &version, + &abbroffset, &addrsize, &offsize, + debug_types ? &typesig : NULL, + debug_types ? &typeoff : NULL) != 0) goto do_return; - printf (gettext (" Compilation unit at offset %" PRIu64 ":\n" - " Version: %" PRIu16 ", Abbreviation section offset: %" - PRIu64 ", Address size: %" PRIu8 ", Offset size: %" PRIu8 "\n"), - (uint64_t) offset, /*version*/2, abbroffset, addrsize, offsize); + if (debug_types) + printf (gettext (" Type unit at offset %" PRIu64 ":\n" + " Version: %" PRIu16 ", Abbreviation section offset: %" + PRIu64 ", Address size: %" PRIu8 ", Offset size: %" PRIu8 + "\n Type signature: %#" PRIx64 + ", Type offset: %" PRIu64 "\n"), + (uint64_t) offset, version, abbroffset, addrsize, offsize, + typesig, (uint64_t) typeoff); + else + printf (gettext (" Compilation unit at offset %" PRIu64 ":\n" + " Version: %" PRIu16 ", Abbreviation section offset: %" + PRIu64 ", Address size: %" PRIu8 ", Offset size: %" PRIu8 + "\n"), + (uint64_t) offset, version, abbroffset, addrsize, offsize); struct attrcb_args args = @@ -5437,11 +5454,12 @@ print_debug_info_section (Dwfl_Module *dwflmod, int level = 0; - if (unlikely (dwarf_offdie (dbg, offset, &dies[level]) == NULL)) + if (unlikely ((debug_types ? dwarf_offdie_types : dwarf_offdie) + (dbg, offset, &dies[level]) == NULL)) { error (0, 0, gettext ("cannot get DIE at offset %" PRIu64 " in section '%s': %s"), - (uint64_t) offset, ".debug_info", dwarf_errmsg (-1)); + (uint64_t) offset, secname, dwarf_errmsg (-1)); goto do_return; } @@ -5460,7 +5478,7 @@ print_debug_info_section (Dwfl_Module *dwflmod, { error (0, 0, gettext ("cannot get tag of DIE at offset %" PRIu64 " in section '%s': %s"), - (uint64_t) offset, ".debug_info", dwarf_errmsg (-1)); + (uint64_t) offset, secname, dwarf_errmsg (-1)); goto do_return; } @@ -5511,6 +5529,20 @@ print_debug_info_section (Dwfl_Module *dwflmod, free (dies); } +static void +print_debug_info_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, + Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg) +{ + print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, false); +} + +static void +print_debug_types_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, + Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg) +{ + print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, true); +} + static void print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, @@ -6642,6 +6674,7 @@ print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr) NEW_SECTION (aranges), NEW_SECTION (frame), NEW_SECTION (info), + NEW_SECTION (types), NEW_SECTION (line), NEW_SECTION (loc), NEW_SECTION (pubnames), |