summaryrefslogtreecommitdiffstats
path: root/libdw/dwarf_nextcu.c
diff options
context:
space:
mode:
Diffstat (limited to 'libdw/dwarf_nextcu.c')
-rw-r--r--libdw/dwarf_nextcu.c80
1 files changed, 63 insertions, 17 deletions
diff --git a/libdw/dwarf_nextcu.c b/libdw/dwarf_nextcu.c
index e436e115..288ee95e 100644
--- a/libdw/dwarf_nextcu.c
+++ b/libdw/dwarf_nextcu.c
@@ -1,5 +1,5 @@
/* Advance to next CU header.
- Copyright (C) 2002-2009 Red Hat, Inc.
+ Copyright (C) 2002-2010 Red Hat, Inc.
This file is part of Red Hat elfutils.
Written by Ulrich Drepper <[email protected]>, 2002.
@@ -57,26 +57,33 @@
int
-dwarf_nextcu (dwarf, off, next_off, header_sizep, abbrev_offsetp,
- address_sizep, offset_sizep)
+dwarf_next_unit (dwarf, off, next_off, header_sizep, versionp, abbrev_offsetp,
+ address_sizep, offset_sizep, type_signaturep, type_offsetp)
Dwarf *dwarf;
Dwarf_Off off;
Dwarf_Off *next_off;
size_t *header_sizep;
+ uint16_t *versionp;
Dwarf_Off *abbrev_offsetp;
uint8_t *address_sizep;
uint8_t *offset_sizep;
+ uint64_t *type_signaturep;
+ Dwarf_Off *type_offsetp;
{
+ const bool debug_types = type_signaturep != NULL;
+ const size_t sec_idx = debug_types ? IDX_debug_types : IDX_debug_info;
+
/* Maybe there has been an error before. */
if (dwarf == NULL)
return -1;
/* If we reached the end before don't do anything. */
if (off == (Dwarf_Off) -1l
+ || unlikely (dwarf->sectiondata[sec_idx] == NULL)
/* Make sure there is enough space in the .debug_info section
for at least the initial word. We cannot test the rest since
we don't know yet whether this is a 64-bit object or not. */
- || unlikely (off + 4 >= dwarf->sectiondata[IDX_debug_info]->d_size))
+ || unlikely (off + 4 >= dwarf->sectiondata[sec_idx]->d_size))
{
*next_off = (Dwarf_Off) -1l;
return 1;
@@ -84,7 +91,7 @@ dwarf_nextcu (dwarf, off, next_off, header_sizep, abbrev_offsetp,
/* This points into the .debug_info section to the beginning of the
CU entry. */
- const unsigned char *data = dwarf->sectiondata[IDX_debug_info]->d_buf;
+ const unsigned char *data = dwarf->sectiondata[sec_idx]->d_buf;
const unsigned char *bytes = data + off;
/* The format of the CU header is described in dwarf2p1 7.5.1:
@@ -122,13 +129,14 @@ dwarf_nextcu (dwarf, off, next_off, header_sizep, abbrev_offsetp,
else if (unlikely (length >= DWARF3_LENGTH_MIN_ESCAPE_CODE
&& length <= DWARF3_LENGTH_MAX_ESCAPE_CODE))
{
+ invalid:
__libdw_seterrno (DWARF_E_INVALID_DWARF);
return -1;
}
/* 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))
+ if (unlikely (DIE_OFFSET_FROM_CU_OFFSET (off, offset_size, debug_types)
+ >= dwarf->sectiondata[sec_idx]->d_size))
{
*next_off = -1;
return 1;
@@ -138,22 +146,47 @@ dwarf_nextcu (dwarf, off, next_off, header_sizep, abbrev_offsetp,
/* This is a 64-bit DWARF format. */
length = read_8ubyte_unaligned_inc (dwarf, bytes);
- /* Read the version stamp. Always a 16-bit value.
- XXX Do we need the value? */
- read_2ubyte_unaligned_inc (dwarf, bytes);
+ /* Read the version stamp. Always a 16-bit value. */
+ uint_fast16_t version = read_2ubyte_unaligned_inc (dwarf, bytes);
/* Get offset in .debug_abbrev. Note that the size of the entry
depends on whether this is a 32-bit or 64-bit DWARF definition. */
uint64_t abbrev_offset;
- if (__libdw_read_offset_inc (dwarf, IDX_debug_info, &bytes, offset_size,
+ if (__libdw_read_offset_inc (dwarf, sec_idx, &bytes, offset_size,
&abbrev_offset, IDX_debug_abbrev, 0))
return -1;
+ /* The address size. Always an 8-bit value. */
+ uint8_t address_size = *bytes++;
+
+ if (debug_types)
+ {
+ uint64_t type_sig8 = read_8ubyte_unaligned_inc (dwarf, bytes);
+
+ Dwarf_Off type_offset;
+ if (__libdw_read_offset_inc (dwarf, sec_idx, &bytes, offset_size,
+ &type_offset, sec_idx, 0))
+ return -1;
+
+ /* Validate that the TYPE_OFFSET points past the header. */
+ if (unlikely (type_offset < (size_t) (bytes - (data + off))))
+ goto invalid;
+
+ *type_signaturep = type_sig8;
+ if (type_offsetp != NULL)
+ *type_offsetp = type_offset;
+ }
+
+ /* Store the header length. */
+ if (header_sizep != NULL)
+ *header_sizep = bytes - (data + off);
+
+ if (versionp != NULL)
+ *versionp = version;
+
if (abbrev_offsetp != NULL)
*abbrev_offsetp = abbrev_offset;
- /* The address size. Always an 8-bit value. */
- uint8_t address_size = *bytes++;
if (address_sizep != NULL)
*address_sizep = address_size;
@@ -161,14 +194,27 @@ dwarf_nextcu (dwarf, off, next_off, header_sizep, abbrev_offsetp,
if (offset_sizep != NULL)
*offset_sizep = offset_size;
- /* Store the header length. */
- if (header_sizep != NULL)
- *header_sizep = bytes - (data + off);
-
/* 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;
}
+INTDEF(dwarf_next_unit)
+
+int
+dwarf_nextcu (dwarf, off, next_off, header_sizep, abbrev_offsetp,
+ address_sizep, offset_sizep)
+ Dwarf *dwarf;
+ Dwarf_Off off;
+ Dwarf_Off *next_off;
+ size_t *header_sizep;
+ Dwarf_Off *abbrev_offsetp;
+ uint8_t *address_sizep;
+ uint8_t *offset_sizep;
+{
+ return INTUSE(dwarf_next_unit) (dwarf, off, next_off, header_sizep, NULL,
+ abbrev_offsetp, address_sizep, offset_sizep,
+ NULL, NULL);
+}
INTDEF(dwarf_nextcu)