summaryrefslogtreecommitdiff
path: root/libdw
diff options
context:
space:
mode:
authorRoland McGrath <roland@redhat.com>2010-06-20 17:55:50 -0700
committerRoland McGrath <roland@redhat.com>2010-06-20 17:55:50 -0700
commit2b1f09548b66c2c75d5be6f13cd9374adc95f8d8 (patch)
tree35782d2db2a9f3bb01d8703da55b9a20cf3581c4 /libdw
parent5cc030d6169713ff4711c28a6ce1250b142cd5b3 (diff)
downloadelfutils-2b1f09548b66c2c75d5be6f13cd9374adc95f8d8.tar.gz
Finish .debug_types support in libdw and readelf.
Diffstat (limited to 'libdw')
-rw-r--r--libdw/ChangeLog11
-rw-r--r--libdw/dwarf_end.c1
-rw-r--r--libdw/dwarf_nextcu.c2
-rw-r--r--libdw/dwarf_offdie.c36
-rw-r--r--libdw/libdw.h9
-rw-r--r--libdw/libdw.map1
-rw-r--r--libdw/libdwP.h7
-rw-r--r--libdw/libdw_findcu.c21
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;
}