diff options
Diffstat (limited to 'libdw/dwarf_nextcu.c')
| -rw-r--r-- | libdw/dwarf_nextcu.c | 80 |
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) |
