diff options
author | Roland McGrath <roland@redhat.com> | 2010-06-20 17:55:50 -0700 |
---|---|---|
committer | Roland McGrath <roland@redhat.com> | 2010-06-20 17:55:50 -0700 |
commit | 2b1f09548b66c2c75d5be6f13cd9374adc95f8d8 (patch) | |
tree | 35782d2db2a9f3bb01d8703da55b9a20cf3581c4 /libdw | |
parent | 5cc030d6169713ff4711c28a6ce1250b142cd5b3 (diff) | |
download | elfutils-2b1f09548b66c2c75d5be6f13cd9374adc95f8d8.tar.gz |
Finish .debug_types support in libdw and readelf.
Diffstat (limited to 'libdw')
-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 |
8 files changed, 65 insertions, 23 deletions
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; } |