summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2008-01-18 19:59:08 +0000
committerUlrich Drepper <drepper@redhat.com>2008-01-18 19:59:08 +0000
commit35f08c4d52d0ffd9f8aa50f47b84de5603842b1f (patch)
tree7def9d6d4ef3ffea169252d44325cb039294129d
parent4173bd8d5dd43413ba0635e2a74bc57a9478fb13 (diff)
propagate from branch 'com.redhat.elfutils.nickc.pending' (head 28d6423325f0cc14a133eb6b92a8c3604e437ba6)
to branch 'com.redhat.elfutils' (head 6ef48518ed8497626058574c787852bd939d46ee)
-rw-r--r--config/elfutils.spec.in2
-rw-r--r--libdw/ChangeLog46
-rw-r--r--libdw/dwarf.h15
-rw-r--r--libdw/dwarf_child.c8
-rw-r--r--libdw/dwarf_diecu.c2
-rw-r--r--libdw/dwarf_entry_breakpoints.c7
-rw-r--r--libdw/dwarf_formref.c6
-rw-r--r--libdw/dwarf_getaranges.c11
-rw-r--r--libdw/dwarf_getattrs.c15
-rw-r--r--libdw/dwarf_getpubnames.c22
-rw-r--r--libdw/dwarf_getsrclines.c2
-rw-r--r--libdw/dwarf_haschildren.c6
-rw-r--r--libdw/dwarf_nextcu.c29
-rw-r--r--libdw/dwarf_siblingof.c18
-rw-r--r--libdw/dwarf_tag.c5
-rw-r--r--libdw/libdw.h14
-rw-r--r--libdw/libdwP.h15
-rw-r--r--libdwarf/ChangeLog4
-rw-r--r--libdwarf/libdwarf.h2
-rw-r--r--src/readelf.c11
20 files changed, 184 insertions, 56 deletions
diff --git a/config/elfutils.spec.in b/config/elfutils.spec.in
index 5c5fc540..380e5c5a 100644
--- a/config/elfutils.spec.in
+++ b/config/elfutils.spec.in
@@ -8,7 +8,7 @@ Group: Development/Tools
Source: elfutils-%{version}.tar.gz
Obsoletes: libelf libelf-devel
Requires: elfutils-libelf = %{version}-%{release}
-Requires: glibc >= 2.7
+Requires: glibc >= 2.3.1-2
# ExcludeArch: xxx
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 3b416242..004e0fa1 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,49 @@
+2008-01-17 Nick Clifton <nickc@redhat.com>
+
+ * dwarf.h (DWARF3_LENGTH_MIN_ESCAPE_CODE): New define.
+ (DWARF3_LENGTH_MAX_ESCAPE_CODE): New define.
+ (DWARF3_LENGTH_64_BIT): New define.
+ * dwarf_getaranges (dwarf_getaranges): Use the new definitions.
+ * dwarf_getpubnames: Include dwarf.h.
+ (get_offsets): Use the new definitions.
+ * dwarf_getsrclines.c (dwarf_getsrclines): Use the new defintions.
+ * dwarf_nextcu.c: Include dwarf.h. Correct comment.
+ (dwarf_nextcu): Use the new definitions.
+
+ * libdwP.h (DIE_OFFSET_FROM_CU_OFFSET): New macro.
+ * dwarf_die.c (dwarf_diecu): Use the new macro.
+ * dwarf_getaranges (dwarf_getaranges): Use the new macro.
+ * dwarf_nextcu.c (dwarf_nextcu): Use the new macro.
+
+ * dwarf_getpubnames (get_offsets): Replace assertion with test and
+ error return.
+
+ * dwarf_entry_breakpoints.c (dwarf_entry_breakpoints): Use CUDIE.
+
+ * dwarf_siblingof (dwarf_siblingof): Detect a NULL return pointer.
+ Set the address in the return structure to the address of the next
+ non-sibling die, if there is no sibling and the return pointer is
+ not the same as the die pointer.
+ * libdw.h: Expand the description of the dwarf_siblingof prototype.
+
+ * dwarf_child.c: Fix typo in comment.
+
+ * libdwP.h (DWARF_VERSION): Change to 3.
+
+ * dwarf_formref.c (__libdw_formref.c): Handle attributes which do
+ not have a initialised valp pointer.
+
+ * dwarf_getattrs.c (dwarf_getattrs): Return 1 rather than 0 when
+ the end of the attributes is reached. When the callback fails,
+ return the address of the failing attribute, not the address of
+ its successor.
+ * libdw.h: Expand the description of the dwarf_getattrs prototype.
+
+ * dwarf_child.c (__libdw_find_attr): Use the new definition.
+ (dwarf_child): Likewise.
+ * dwarf_tag.c (__libdw_findabbrev): Likewise.
+ (dwarf_tag): Likewise.
+
2008-01-08 Roland McGrath <roland@redhat.com>
* Makefile.am (euinclude): Variable removed.
diff --git a/libdw/dwarf.h b/libdw/dwarf.h
index 4b763ffa..f760b9d5 100644
--- a/libdw/dwarf.h
+++ b/libdw/dwarf.h
@@ -672,4 +672,19 @@ enum
/* DWARF XXX. */
#define DW_ADDR_none 0
+/* Section 7.2.2 of the DWARF3 specification defines a range of escape
+ codes that can appear in the length field of certain DWARF structures.
+
+ These defines enumerate the minium and maximum values of this range.
+ Currently only the maximum value is used (to indicate that 64-bit
+ values are going to be used in the dwarf data that accompanies the
+ structure). The other values are reserved.
+
+ Note: There is a typo in DWARF3 spec (published Dec 20, 2005). In
+ sections 7.4, 7.5.1, 7.19, 7.20 the minimum escape code is referred to
+ as 0xffffff00 whereas in fact it should be 0xfffffff0. */
+#define DWARF3_LENGTH_MIN_ESCAPE_CODE 0xfffffff0u
+#define DWARF3_LENGTH_MAX_ESCAPE_CODE 0xffffffffu
+#define DWARF3_LENGTH_64_BIT DWARF3_LENGTH_MAX_ESCAPE_CODE
+
#endif /* dwarf.h */
diff --git a/libdw/dwarf_child.c b/libdw/dwarf_child.c
index b22b010e..bbc75075 100644
--- a/libdw/dwarf_child.c
+++ b/libdw/dwarf_child.c
@@ -1,4 +1,4 @@
-/* Return vhild of current DIE.
+/* Return child of current DIE.
Copyright (C) 2003, 2004, 2005, 2006, 2007 Red Hat, Inc.
This file is part of Red Hat elfutils.
Written by Ulrich Drepper <drepper@redhat.com>, 2003.
@@ -77,9 +77,9 @@ __libdw_find_attr (Dwarf_Die *die, unsigned int search_name,
if (abbrevp == NULL)
{
abbrevp = __libdw_findabbrev (die->cu, abbrev_code);
- die->abbrev = abbrevp ?: (Dwarf_Abbrev *) -1l;
+ die->abbrev = abbrevp ?: DWARF_END_ABBREV;
}
- if (unlikely (die->abbrev == (Dwarf_Abbrev *) -1l))
+ if (unlikely (die->abbrev == DWARF_END_ABBREV))
{
__libdw_seterrno (DWARF_E_INVALID_DWARF);
return NULL;
@@ -163,7 +163,7 @@ dwarf_child (die, result)
void *addr = NULL;
/* If we already know there are no children do not search. */
- if (die->abbrev != (Dwarf_Abbrev *) -1
+ if (die->abbrev != DWARF_END_ABBREV
&& (die->abbrev == NULL || die->abbrev->has_children))
addr = __libdw_find_attr (die, INVALID, NULL, NULL);
if (die->abbrev == (Dwarf_Abbrev *) -1l)
diff --git a/libdw/dwarf_diecu.c b/libdw/dwarf_diecu.c
index 0724ee06..963c7d06 100644
--- a/libdw/dwarf_diecu.c
+++ b/libdw/dwarf_diecu.c
@@ -70,7 +70,7 @@ dwarf_diecu (die, result, address_sizep, offset_sizep)
memset (result, '\0', sizeof (Dwarf_Die));
result->addr = ((char *) die->cu->dbg->sectiondata[IDX_debug_info]->d_buf
- + die->cu->start + 3 * die->cu->offset_size - 4 + 3);
+ + DIE_OFFSET_FROM_CU_OFFSET (die->cu->start, die->cu->offset_size));
result->cu = die->cu;
if (address_sizep != NULL)
diff --git a/libdw/dwarf_entry_breakpoints.c b/libdw/dwarf_entry_breakpoints.c
index e568bc99..d4966e95 100644
--- a/libdw/dwarf_entry_breakpoints.c
+++ b/libdw/dwarf_entry_breakpoints.c
@@ -87,12 +87,7 @@ dwarf_entry_breakpoints (die, bkpts)
}
/* Fetch the CU's line records to look for this DIE's addresses. */
- Dwarf_Die cudie =
- {
- .cu = die->cu,
- .addr = ((char *) die->cu->dbg->sectiondata[IDX_debug_info]->d_buf
- + die->cu->start + 3 * die->cu->offset_size - 4 + 3),
- };
+ Dwarf_Die cudie = CUDIE (die->cu);
Dwarf_Lines *lines;
size_t nlines;
if (INTUSE(dwarf_getsrclines) (&cudie, &lines, &nlines) < 0)
diff --git a/libdw/dwarf_formref.c b/libdw/dwarf_formref.c
index 7c4fb71a..9d472df8 100644
--- a/libdw/dwarf_formref.c
+++ b/libdw/dwarf_formref.c
@@ -62,6 +62,12 @@ __libdw_formref (attr, return_offset)
{
const unsigned char *datap;
+ if (attr->valp == NULL)
+ {
+ __libdw_seterrno (DWARF_E_INVALID_REFERENCE);
+ return -1;
+ }
+
switch (attr->form)
{
case DW_FORM_ref1:
diff --git a/libdw/dwarf_getaranges.c b/libdw/dwarf_getaranges.c
index d2294ea3..b6c19425 100644
--- a/libdw/dwarf_getaranges.c
+++ b/libdw/dwarf_getaranges.c
@@ -55,7 +55,7 @@
#include <stdlib.h>
#include <assert.h>
#include "libdwP.h"
-
+#include <dwarf.h>
struct arangelist
{
@@ -131,11 +131,14 @@ dwarf_getaranges (dbg, aranges, naranges)
a segment descriptor on the target system. */
Dwarf_Word length = read_4ubyte_unaligned_inc (dbg, readp);
unsigned int length_bytes = 4;
- if (length == 0xffffffff)
+ if (length == DWARF3_LENGTH_64_BIT)
{
length = read_8ubyte_unaligned_inc (dbg, readp);
length_bytes = 8;
}
+ else if (unlikely (length >= DWARF3_LENGTH_MIN_ESCAPE_CODE
+ && length <= DWARF3_LENGTH_MAX_ESCAPE_CODE))
+ goto invalid;
unsigned int version = read_2ubyte_unaligned_inc (dbg, readp);
if (version != 2)
@@ -197,11 +200,11 @@ dwarf_getaranges (dbg, aranges, naranges)
const char *cu_header = (dbg->sectiondata[IDX_debug_info]->d_buf
+ offset);
unsigned int offset_size;
- if (read_4ubyte_unaligned_noncvt (cu_header) == 0xffffffff)
+ if (read_4ubyte_unaligned_noncvt (cu_header) == DWARF3_LENGTH_64_BIT)
offset_size = 8;
else
offset_size = 4;
- new_arange->arange.offset = offset + 3 * offset_size - 4 + 3;
+ new_arange->arange.offset = DIE_OFFSET_FROM_CU_OFFSET (offset, offset_size);
/* Sanity-check the data. */
if (new_arange->arange.offset
diff --git a/libdw/dwarf_getattrs.c b/libdw/dwarf_getattrs.c
index ebf0869c..876475e6 100644
--- a/libdw/dwarf_getattrs.c
+++ b/libdw/dwarf_getattrs.c
@@ -72,7 +72,7 @@ dwarf_getattrs (Dwarf_Die *die, int (*callback) (Dwarf_Attribute *, void *),
/* Find the abbreviation. */
die->abbrev = __libdw_findabbrev (die->cu, u128);
- if (die->abbrev == (Dwarf_Abbrev *) -1l)
+ if (die->abbrev == DWARF_END_ABBREV)
{
__libdw_seterrno (DWARF_E_INVALID_DWARF);
return -1l;
@@ -96,13 +96,19 @@ dwarf_getattrs (Dwarf_Die *die, int (*callback) (Dwarf_Attribute *, void *),
/* Get attribute name and form. */
Dwarf_Attribute attr;
+ const unsigned char * remembered_attrp = attrp;
+
// XXX Fix bound checks
get_uleb128 (attr.code, attrp);
get_uleb128 (attr.form, attrp);
/* We can stop if we found the attribute with value zero. */
if (attr.code == 0 && attr.form == 0)
- return 0;
+ /* Do not return 0 here - there would be no way to
+ distinguish this value from the attribute at offset 0.
+ Instead we return +1 which would never be a valid
+ offset of an attribute. */
+ return 1l;
/* Fill in the rest. */
attr.valp = (unsigned char *) die_addr;
@@ -110,7 +116,10 @@ dwarf_getattrs (Dwarf_Die *die, int (*callback) (Dwarf_Attribute *, void *),
/* Now call the callback function. */
if (callback (&attr, arg) != DWARF_CB_OK)
- return attrp - die->abbrev->attrp;
+ /* Return the offset of the start of the attribute, so that
+ dwarf_getattrs() can be restarted from this point if the
+ caller so desires. */
+ return remembered_attrp - die->abbrev->attrp;
/* Skip over the rest of this attribute (if there is any). */
if (attr.form != 0)
diff --git a/libdw/dwarf_getpubnames.c b/libdw/dwarf_getpubnames.c
index 6d07a3b7..91dad311 100644
--- a/libdw/dwarf_getpubnames.c
+++ b/libdw/dwarf_getpubnames.c
@@ -58,6 +58,7 @@
#include <sys/param.h>
#include <libdwP.h>
+#include <dwarf.h>
static int
@@ -93,11 +94,17 @@ get_offsets (Dwarf *dbg)
/* Read the set header. */
int len_bytes = 4;
Dwarf_Off len = read_4ubyte_unaligned_inc (dbg, readp);
- if (len == 0xffffffff)
+ if (len == DWARF3_LENGTH_64_BIT)
{
len = read_8ubyte_unaligned_inc (dbg, readp);
len_bytes = 8;
}
+ else if (unlikely (len >= DWARF3_LENGTH_MIN_ESCAPE_CODE
+ && len <= DWARF3_LENGTH_MAX_ESCAPE_CODE))
+ {
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ goto err_return;
+ }
/* Now we know the offset of the first offset/name pair. */
mem[cnt].set_start = readp + 2 + 2 * len_bytes - startp;
@@ -122,14 +129,17 @@ get_offsets (Dwarf *dbg)
mem[cnt].cu_offset = read_8ubyte_unaligned (dbg, readp + 2);
/* Determine the size of the CU header. */
- assert (dbg->sectiondata[IDX_debug_info] != NULL);
- assert (dbg->sectiondata[IDX_debug_info]->d_buf != NULL);
- assert (mem[cnt].cu_offset + 3
- < dbg->sectiondata[IDX_debug_info]->d_size);
+ if (dbg->sectiondata[IDX_debug_info] == NULL
+ || dbg->sectiondata[IDX_debug_info]->d_buf == NULL
+ || mem[cnt].cu_offset + 3 >= dbg->sectiondata[IDX_debug_info]->d_size)
+ {
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ goto err_return;
+ }
unsigned char *infop
= ((unsigned char *) dbg->sectiondata[IDX_debug_info]->d_buf
+ mem[cnt].cu_offset);
- if (read_4ubyte_unaligned_noncvt (infop) == 0xffffffff)
+ if (read_4ubyte_unaligned_noncvt (infop) == DWARF3_LENGTH_64_BIT)
mem[cnt].cu_header_size = 23;
else
mem[cnt].cu_header_size = 11;
diff --git a/libdw/dwarf_getsrclines.c b/libdw/dwarf_getsrclines.c
index 666cca22..e4ec267f 100644
--- a/libdw/dwarf_getsrclines.c
+++ b/libdw/dwarf_getsrclines.c
@@ -164,7 +164,7 @@ dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines, size_t *nlines)
}
Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
unsigned int length = 4;
- if (unlikely (unit_length == 0xffffffff))
+ if (unlikely (unit_length == DWARF3_LENGTH_64_BIT))
{
if (unlikely (linep + 8 > lineendp))
goto invalid_data;
diff --git a/libdw/dwarf_haschildren.c b/libdw/dwarf_haschildren.c
index 7b21f690..fe431955 100644
--- a/libdw/dwarf_haschildren.c
+++ b/libdw/dwarf_haschildren.c
@@ -62,7 +62,7 @@ dwarf_haschildren (die)
{
/* Find the abbreviation entry. */
Dwarf_Abbrev *abbrevp = die->abbrev;
- if (abbrevp != (Dwarf_Abbrev *) -1l)
+ if (abbrevp != DWARF_END_ABBREV)
{
const unsigned char *readp = (unsigned char *) die->addr;
@@ -72,9 +72,9 @@ dwarf_haschildren (die)
get_uleb128 (abbrev_code, readp);
abbrevp = __libdw_findabbrev (die->cu, abbrev_code);
- die->abbrev = abbrevp ?: (Dwarf_Abbrev *) -1l;
+ die->abbrev = abbrevp ?: DWARF_END_ABBREV;
}
- if (unlikely (die->abbrev == (Dwarf_Abbrev *) -1l))
+ if (unlikely (die->abbrev == DWARF_END_ABBREV))
{
__libdw_seterrno (DWARF_E_INVALID_DWARF);
return 0;
diff --git a/libdw/dwarf_nextcu.c b/libdw/dwarf_nextcu.c
index 30743022..3927c41e 100644
--- a/libdw/dwarf_nextcu.c
+++ b/libdw/dwarf_nextcu.c
@@ -53,6 +53,7 @@
#endif
#include <libdwP.h>
+#include <dwarf.h>
int
@@ -91,9 +92,9 @@ dwarf_nextcu (dwarf, off, next_off, header_sizep, abbrev_offsetp,
of the .debug_info contribution for that compilation unit, not
including the length field itself. In the 32-bit DWARF format,
this is a 4-byte unsigned integer (which must be less than
- 0xffffff00); in the 64-bit DWARF format, this consists of the
+ 0xfffffff0); in the 64-bit DWARF format, this consists of the
4-byte value 0xffffffff followed by an 8-byte unsigned integer
- that gives the actual length (see Section 7.4).
+ that gives the actual length (see Section 7.2.2).
2. A 2-byte unsigned integer representing the version of the
DWARF information for that compilation unit. For DWARF Version
@@ -112,22 +113,27 @@ dwarf_nextcu (dwarf, off, next_off, header_sizep, abbrev_offsetp,
offset portion of an address. */
uint64_t length = read_4ubyte_unaligned_inc (dwarf, bytes);
size_t offset_size = 4;
- if (length == 0xffffffffu)
+ /* Lengths of 0xfffffff0 - 0xffffffff are escape codes. Oxffffffff is
+ used to indicate that 64-bit dwarf information is being used, the
+ other values are currently reserved. */
+ if (length == DWARF3_LENGTH_64_BIT)
offset_size = 8;
+ else if (unlikely (length >= DWARF3_LENGTH_MIN_ESCAPE_CODE
+ && length <= DWARF3_LENGTH_MAX_ESCAPE_CODE))
+ {
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ return -1;
+ }
- /* Now we know how large the header is. Note the trick in the
- computation. If the offset_size is 4 the '- 4' term undoes the
- '2 *'. If offset_size is 8 this term computes the size of the
- escape value plus the 8 byte offset. */
- if (unlikely (off + 2 * offset_size - 4 + sizeof (uint16_t)
- + offset_size + sizeof (uint8_t)
+ /* Now we know how large the header is. */
+ if (unlikely (DIE_OFFSET_FROM_CU_OFFSET (off, offset_size)
>= dwarf->sectiondata[IDX_debug_info]->d_size))
{
*next_off = -1;
return 1;
}
- if (length == 0xffffffffu)
+ if (length == DWARF3_LENGTH_64_BIT)
/* This is a 64-bit DWARF format. */
length = read_8ubyte_unaligned_inc (dwarf, bytes);
@@ -160,7 +166,8 @@ dwarf_nextcu (dwarf, off, next_off, header_sizep, abbrev_offsetp,
- ((char *) dwarf->sectiondata[IDX_debug_info]->d_buf
+ off));
- /* See above for an explanation of the trick in this formula. */
+ /* See definition of DIE_OFFSET_FROM_CU_OFFSET macro
+ for an explanation of the trick in this expression. */
*next_off = off + 2 * offset_size - 4 + length;
return 0;
diff --git a/libdw/dwarf_siblingof.c b/libdw/dwarf_siblingof.c
index a6cca394..ac9d2877 100644
--- a/libdw/dwarf_siblingof.c
+++ b/libdw/dwarf_siblingof.c
@@ -56,7 +56,6 @@
#include <dwarf.h>
#include <string.h>
-
int
dwarf_siblingof (die, result)
Dwarf_Die *die;
@@ -66,6 +65,12 @@ dwarf_siblingof (die, result)
if (die == NULL)
return -1;
+ if (result == NULL)
+ return -1;
+
+ if (result != die)
+ result->addr = NULL;
+
unsigned int level = 0;
/* Copy of the current DIE. */
@@ -102,13 +107,12 @@ dwarf_siblingof (die, result)
+ sibattr.cu->start + offset);
}
else if (unlikely (addr == NULL)
- || unlikely (this_die.abbrev == (Dwarf_Abbrev *) -1l))
+ || unlikely (this_die.abbrev == DWARF_END_ABBREV))
return -1;
else if (this_die.abbrev->has_children)
/* This abbreviation has children. */
++level;
-
while (1)
{
/* Make sure we are still in range. Some producers might skip
@@ -120,8 +124,12 @@ dwarf_siblingof (die, result)
break;
if (level-- == 0)
- /* No more sibling at all. */
- return 1;
+ {
+ if (result != die)
+ result->addr = addr;
+ /* No more sibling at all. */
+ return 1;
+ }
++addr;
}
diff --git a/libdw/dwarf_tag.c b/libdw/dwarf_tag.c
index 05222821..7fcd89ca 100644
--- a/libdw/dwarf_tag.c
+++ b/libdw/dwarf_tag.c
@@ -76,8 +76,7 @@ __libdw_findabbrev (struct Dwarf_CU *cu, unsigned int code)
{
/* Make sure we do not try to search for it again. */
cu->last_abbrev_offset = (size_t) -1l;
- abb = (void *) -1l;
- break;
+ return DWARF_END_ABBREV;
}
cu->last_abbrev_offset += length;
@@ -107,7 +106,7 @@ dwarf_tag (die)
die->abbrev = __libdw_findabbrev (die->cu, u128);
}
- if (die->abbrev == (Dwarf_Abbrev *) -1l)
+ if (die->abbrev == DWARF_END_ABBREV)
{
__libdw_seterrno (DWARF_E_INVALID_DWARF);
return DW_TAG_invalid;
diff --git a/libdw/libdw.h b/libdw/libdw.h
index 6242d04f..4720739a 100644
--- a/libdw/libdw.h
+++ b/libdw/libdw.h
@@ -252,14 +252,24 @@ extern Dwarf_Die *dwarf_addrdie (Dwarf *dbg, Dwarf_Addr addr,
extern int dwarf_child (Dwarf_Die *die, Dwarf_Die *result)
__nonnull_attribute__ (2);
-/* Return sibling of given DIE. */
+/* Locates the first sibling of DIE and places it in RESULT.
+ Returns 0 if a sibling was found, -1 if something went wrong.
+ Returns 1 if no sibling could be found and, if RESULT is not
+ the same as DIE, it sets RESULT->addr to the address of the
+ (non-sibling) DIE that follows this one, or NULL if this DIE
+ was the last one in the cokmpilation unit. */
extern int dwarf_siblingof (Dwarf_Die *die, Dwarf_Die *result)
__nonnull_attribute__ (2);
/* Check whether the DIE has children. */
extern int dwarf_haschildren (Dwarf_Die *die) __nonnull_attribute__ (1);
-/* Get attributes of the DIE. */
+/* Walks the attributes of DIE, starting at the one OFFSET bytes in,
+ calling the CALLBACK function for each one. Stops if the callback
+ function ever returns a value other than DWARF_CB_OK and returns the
+ offset of the offending attribute. If the end of the attributes
+ is reached 1 is returned. If something goes wrong -1 is returned and
+ the dwarf error number is set. */
extern ptrdiff_t dwarf_getattrs (Dwarf_Die *die,
int (*callback) (Dwarf_Attribute *, void *),
void *arg, ptrdiff_t offset)
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
index 78fd5ce7..2277f39c 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -62,7 +62,7 @@
/* Version of the DWARF specification we support. */
-#define DWARF_VERSION 2
+#define DWARF_VERSION 3
/* Version of the CIE format. */
#define CIE_VERSION 1
@@ -286,6 +286,19 @@ struct Dwarf_CU
void *locs;
};
+/* Compute the offset of a CU's first DIE from its offset. This
+ is either:
+ LEN VER OFFSET ADDR
+ 4-bytes + 2-bytes + 4-bytes + 1-byte for 32-bit dwarf
+ 12-bytes + 2-bytes + 8-bytes + 1-byte for 64-bit dwarf
+
+ Note the trick in the computation. If the offset_size is 4
+ the '- 4' term changes the '3 *' into a '2 *'. If the
+ offset_size is 8 it accounts for the 4-byte escape value
+ used at the start of the length. */
+#define DIE_OFFSET_FROM_CU_OFFSET(cu_offset, offset_size) \
+ ((cu_offset) + 3 * (offset_size) - 4 + 3)
+
#define CUDIE(fromcu) \
((Dwarf_Die) \
{ \
diff --git a/libdwarf/ChangeLog b/libdwarf/ChangeLog
index c46ffcb6..4c63735e 100644
--- a/libdwarf/ChangeLog
+++ b/libdwarf/ChangeLog
@@ -1,3 +1,7 @@
+2008-01-17 Nick Clifton <nickc@redhat.com>
+
+ * libdwarf.h: Fix typo in comment.
+
2003-08-11 Ulrich Drepper <drepper@redhat.com>
* Moved to CVS archive.
diff --git a/libdwarf/libdwarf.h b/libdwarf/libdwarf.h
index 284b8a38..2a2b9e3e 100644
--- a/libdwarf/libdwarf.h
+++ b/libdwarf/libdwarf.h
@@ -134,7 +134,7 @@ extern int dwarf_init (int fd, Dwarf_Unsigned access,
Dwarf_Handler errhand, Dwarf_Ptr errarg,
Dwarf_Debug *dbg, Dwarf_Error *errdesc);
-/* Similar to `dwarf_init' but instead of a file descriptor of ELF
+/* Similar to `dwarf_init' but instead of a file descriptor an ELF
descriptor is passed. */
extern int dwarf_elf_init (Elf *elf, Dwarf_Unsigned access,
Dwarf_Handler errhand, Dwarf_Ptr errarg,
diff --git a/src/readelf.c b/src/readelf.c
index d65f8103..f243f626 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -4041,7 +4041,8 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
if (unlikely (dwarf_formaddr (attrp, &addr) != 0))
{
attrval_out:
- error (0, 0, gettext ("cannot get attribute value: %s"),
+ error (0, 0, gettext ("offset: %" PRIx64 " cannot get attribute value: %s"),
+ attrp->valp - (unsigned char *) attrp->cu->dbg->sectiondata[IDX_debug_info]->d_buf,
dwarf_errmsg (-1));
return DWARF_CB_ABORT;
}
@@ -4285,7 +4286,7 @@ print_debug_info_section (Dwfl_Module *dwflmod,
int tag = dwarf_tag (&dies[level]);
if (unlikely (tag == DW_TAG_invalid))
{
- error (0, 0, gettext ("cannot get tag of DIE at offset %" PRIu64
+ error (0, 0, gettext ("cannot get tag of DIE at offset %" PRIx64
" in section '%s': %s"),
(uint64_t) offset, ".debug_info", dwarf_errmsg (-1));
goto do_return;
@@ -4309,8 +4310,10 @@ print_debug_info_section (Dwfl_Module *dwflmod,
if (res > 0)
{
while ((res = dwarf_siblingof (&dies[level], &dies[level])) == 1)
- if (level-- == 0)
- break;
+ {
+ if (level-- == 0)
+ break;
+ }
if (unlikely (res == -1))
{