summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS4
-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
-rw-r--r--src/ChangeLog6
-rw-r--r--src/readelf.c69
11 files changed, 124 insertions, 43 deletions
diff --git a/NEWS b/NEWS
index 01a33db9..6237f5cb 100644
--- a/NEWS
+++ b/NEWS
@@ -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),