diff options
-rw-r--r-- | libdw/ChangeLog | 19 | ||||
-rw-r--r-- | libdw/dwarf_child.c | 14 | ||||
-rw-r--r-- | libdw/dwarf_formsdata.c | 7 | ||||
-rw-r--r-- | libdw/dwarf_formudata.c | 7 | ||||
-rw-r--r-- | libdw/dwarf_getabbrev.c | 7 | ||||
-rw-r--r-- | libdw/dwarf_getabbrevattr.c | 22 | ||||
-rw-r--r-- | libdw/dwarf_getattrs.c | 11 | ||||
-rw-r--r-- | libdw/dwarf_hasattr.c | 6 | ||||
-rw-r--r-- | libdw/libdw.h | 6 | ||||
-rw-r--r-- | libdw/libdw.map | 1 | ||||
-rw-r--r-- | libdw/libdwP.h | 1 | ||||
-rw-r--r-- | libdw/memory-access.h | 19 | ||||
-rw-r--r-- | src/ChangeLog | 6 | ||||
-rw-r--r-- | src/readelf.c | 15 |
14 files changed, 129 insertions, 12 deletions
diff --git a/libdw/ChangeLog b/libdw/ChangeLog index 35ce554e..888e5096 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,3 +1,22 @@ +2018-02-09 Mark Wielaard <mark@klomp.org> + + * dwarf_child.c (__libdw_find_attr): Handle DW_FORM_implicit_const. + * dwarf_formsdata.c (dwarf_formsdata): Likewise. + * dwarf_formudata.c (dwarf_formudata): Likewise. + * dwarf_getabbrev.c (__libdw_getabbrev): Likewise. + * dwarf_getattrs.c (dwarf_getattrs): Likewise. + * dwarf_hasattr.c (dwarf_hasattr): Likewise. + * dwarf_getabbrevattr.c (dwarf_getabbrevattr_data): New function + that will also return any data associated with the abbrev. Which + currently is only for DW_FORM_implicit_const. Based on... + (dwarf_getabbrevattr): ... this function. Which now just calls + dwarf_getabbrevattr_data. + * libdw.h (dwarf_getabbrevattr_data): Declare new function. + * libdw.map (ELFUTILS_0.170): Add dwarf_getabbrevattr_data. + * libdwP.h (dwarf_getabbrevattr_data): INTDECL. + * memory-access.h (__libdw_get_sleb128_unchecked): New inlined + function based on __libdw_get_uleb128_unchecked. + 2018-02-08 Mark Wielaard <mark@klomp.org> * dwarf.h: Add DWARF5 DW_FORMs. diff --git a/libdw/dwarf_child.c b/libdw/dwarf_child.c index 248338eb..9446b880 100644 --- a/libdw/dwarf_child.c +++ b/libdw/dwarf_child.c @@ -77,7 +77,12 @@ __libdw_find_attr (Dwarf_Die *die, unsigned int search_name, if (formp != NULL) *formp = attr_form; - return (unsigned char *) readp; + /* Normally the attribute data comes from the DIE/info, + except for implicit_form, where it comes from the abbrev. */ + if (attr_form == DW_FORM_implicit_const) + return (unsigned char *) attrp; + else + return (unsigned char *) readp; } /* Skip over the rest of this attribute (if there is any). */ @@ -92,6 +97,13 @@ __libdw_find_attr (Dwarf_Die *die, unsigned int search_name, // __libdw_form_val_len will have done a bounds check. readp += len; + + // If the value is in the abbrev data, skip it. + if (attr_form == DW_FORM_implicit_const) + { + int64_t attr_value __attribute__((__unused__)); + get_sleb128_unchecked (attr_value, attrp); + } } } diff --git a/libdw/dwarf_formsdata.c b/libdw/dwarf_formsdata.c index bc2b508d..def32c9d 100644 --- a/libdw/dwarf_formsdata.c +++ b/libdw/dwarf_formsdata.c @@ -1,5 +1,5 @@ /* Return signed constant represented by attribute. - Copyright (C) 2003, 2005, 2014 Red Hat, Inc. + Copyright (C) 2003, 2005, 2014, 2017 Red Hat, Inc. This file is part of elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2003. @@ -86,6 +86,11 @@ dwarf_formsdata (Dwarf_Attribute *attr, Dwarf_Sword *return_sval) get_uleb128 (*return_sval, datap, endp); break; + case DW_FORM_implicit_const: + // The data comes from the abbrev, which has been bounds checked. + get_sleb128_unchecked (*return_sval, datap); + break; + default: __libdw_seterrno (DWARF_E_NO_CONSTANT); return -1; diff --git a/libdw/dwarf_formudata.c b/libdw/dwarf_formudata.c index e41981a4..9c1644ef 100644 --- a/libdw/dwarf_formudata.c +++ b/libdw/dwarf_formudata.c @@ -1,5 +1,5 @@ /* Return unsigned constant represented by attribute. - Copyright (C) 2003-2012, 2014 Red Hat, Inc. + Copyright (C) 2003-2012, 2014, 2017 Red Hat, Inc. This file is part of elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2003. @@ -221,6 +221,11 @@ dwarf_formudata (Dwarf_Attribute *attr, Dwarf_Word *return_uval) get_uleb128 (*return_uval, datap, endp); break; + case DW_FORM_implicit_const: + // The data comes from the abbrev, which has been bounds checked. + get_sleb128_unchecked (*return_uval, datap); + break; + default: __libdw_seterrno (DWARF_E_NO_CONSTANT); return -1; diff --git a/libdw/dwarf_getabbrev.c b/libdw/dwarf_getabbrev.c index a3a68b37..1e113dbe 100644 --- a/libdw/dwarf_getabbrev.c +++ b/libdw/dwarf_getabbrev.c @@ -132,6 +132,13 @@ __libdw_getabbrev (Dwarf *dbg, struct Dwarf_CU *cu, Dwarf_Off offset, if (abbrevp >= end) goto invalid; get_uleb128 (attrform, abbrevp, end); + if (attrform == DW_FORM_implicit_const) + { + int64_t formval __attribute__((__unused__)); + if (abbrevp >= end) + goto invalid; + get_sleb128 (formval, abbrevp, end); + } } while (attrname != 0 && attrform != 0); diff --git a/libdw/dwarf_getabbrevattr.c b/libdw/dwarf_getabbrevattr.c index 57fe3637..54ff604f 100644 --- a/libdw/dwarf_getabbrevattr.c +++ b/libdw/dwarf_getabbrevattr.c @@ -37,8 +37,9 @@ int -dwarf_getabbrevattr (Dwarf_Abbrev *abbrev, size_t idx, unsigned int *namep, - unsigned int *formp, Dwarf_Off *offsetp) +dwarf_getabbrevattr_data (Dwarf_Abbrev *abbrev, size_t idx, + unsigned int *namep, unsigned int *formp, + Dwarf_Sword *datap, Dwarf_Off *offsetp) { if (abbrev == NULL) return -1; @@ -48,6 +49,7 @@ dwarf_getabbrevattr (Dwarf_Abbrev *abbrev, size_t idx, unsigned int *namep, const unsigned char *start_attrp; unsigned int name; unsigned int form; + Dwarf_Word data; do { @@ -58,6 +60,11 @@ dwarf_getabbrevattr (Dwarf_Abbrev *abbrev, size_t idx, unsigned int *namep, get_uleb128_unchecked (name, attrp); get_uleb128_unchecked (form, attrp); + if (form == DW_FORM_implicit_const) + get_sleb128_unchecked (data, attrp); + else + data = 0; + /* If both values are zero the index is out of range. */ if (name == 0 && form == 0) return -1; @@ -69,8 +76,19 @@ dwarf_getabbrevattr (Dwarf_Abbrev *abbrev, size_t idx, unsigned int *namep, *namep = name; if (formp != NULL) *formp = form; + if (datap != NULL) + *datap = data; if (offsetp != NULL) *offsetp = (start_attrp - abbrev->attrp) + abbrev->offset; return 0; } +INTDEF(dwarf_getabbrevattr_data) + +int +dwarf_getabbrevattr (Dwarf_Abbrev *abbrev, size_t idx, unsigned int *namep, + unsigned int *formp, Dwarf_Off *offsetp) +{ + return INTUSE(dwarf_getabbrevattr_data) (abbrev, idx, namep, formp, + NULL, offsetp); +} diff --git a/libdw/dwarf_getattrs.c b/libdw/dwarf_getattrs.c index 7f55fafc..50faf988 100644 --- a/libdw/dwarf_getattrs.c +++ b/libdw/dwarf_getattrs.c @@ -83,7 +83,10 @@ dwarf_getattrs (Dwarf_Die *die, int (*callback) (Dwarf_Attribute *, void *), if (remembered_attrp >= offset_attrp) { /* Fill in the rest. */ - attr.valp = (unsigned char *) die_addr; + if (attr.form == DW_FORM_implicit_const) + attr.valp = (unsigned char *) attrp; + else + attr.valp = (unsigned char *) die_addr; attr.cu = die->cu; /* Now call the callback function. */ @@ -104,6 +107,12 @@ dwarf_getattrs (Dwarf_Die *die, int (*callback) (Dwarf_Attribute *, void *), // __libdw_form_val_len will have done a bounds check. die_addr += len; + + if (attr.form == DW_FORM_implicit_const) + { + int64_t attr_value __attribute__((__unused__)); + get_sleb128_unchecked (attr_value, attrp); + } } } /* NOTREACHED */ diff --git a/libdw/dwarf_hasattr.c b/libdw/dwarf_hasattr.c index 90b333e6..90053b13 100644 --- a/libdw/dwarf_hasattr.c +++ b/libdw/dwarf_hasattr.c @@ -66,6 +66,12 @@ dwarf_hasattr (Dwarf_Die *die, unsigned int search_name) if (attr_name == search_name) return 1; + + if (attr_form == DW_FORM_implicit_const) + { + int64_t attr_value __attribute__ ((unused)); + get_sleb128_unchecked (attr_value, attrp); + } } } INTDEF (dwarf_hasattr) diff --git a/libdw/libdw.h b/libdw/libdw.h index acc38916..ac43ad97 100644 --- a/libdw/libdw.h +++ b/libdw/libdw.h @@ -594,6 +594,12 @@ extern int dwarf_getabbrevattr (Dwarf_Abbrev *abbrev, size_t idx, unsigned int *namep, unsigned int *formp, Dwarf_Off *offset); +/* Get specific attribute of abbreviation and any data encoded with it. + Specifically for DW_FORM_implicit_const data will be set to the + constant value associated. */ +extern int dwarf_getabbrevattr_data (Dwarf_Abbrev *abbrev, size_t idx, + unsigned int *namep, unsigned int *formp, + Dwarf_Sword *datap, Dwarf_Off *offset); /* Get string from-debug_str section. */ extern const char *dwarf_getstring (Dwarf *dbg, Dwarf_Off offset, diff --git a/libdw/libdw.map b/libdw/libdw.map index 8d12e892..4577d058 100644 --- a/libdw/libdw.map +++ b/libdw/libdw.map @@ -349,4 +349,5 @@ ELFUTILS_0.171 { global: dwarf_die_addr_die; dwarf_get_units; + dwarf_getabbrevattr_data; } ELFUTILS_0.170; diff --git a/libdw/libdwP.h b/libdw/libdwP.h index b31497d9..ad555588 100644 --- a/libdw/libdwP.h +++ b/libdw/libdwP.h @@ -901,6 +901,7 @@ INTDECL (dwarf_formref_die) INTDECL (dwarf_formsdata) INTDECL (dwarf_formstring) INTDECL (dwarf_formudata) +INTDECL (dwarf_getabbrevattr_data) INTDECL (dwarf_getalt) INTDECL (dwarf_getarange_addr) INTDECL (dwarf_getarangeinfo) diff --git a/libdw/memory-access.h b/libdw/memory-access.h index ed68bdb9..5f96a14a 100644 --- a/libdw/memory-access.h +++ b/libdw/memory-access.h @@ -139,7 +139,26 @@ __libdw_get_sleb128 (const unsigned char **addrp, const unsigned char *end) return INT64_MAX; } +static inline int64_t +__libdw_get_sleb128_unchecked (const unsigned char **addrp) +{ + int64_t acc = 0; + + /* Unroll the first step to help the compiler optimize + for the common single-byte case. */ + get_sleb128_step (acc, *addrp, 0); + + /* Subtract one step, so we don't shift into sign bit. */ + const size_t max = len_leb128 (int64_t) - 1; + for (size_t i = 1; i < max; ++i) + get_sleb128_step (acc, *addrp, i); + /* Other implementations set VALUE to INT_MAX in this + case. So we better do this as well. */ + return INT64_MAX; +} + #define get_sleb128(var, addr, end) ((var) = __libdw_get_sleb128 (&(addr), end)) +#define get_sleb128_unchecked(var, addr) ((var) = __libdw_get_sleb128_unchecked (&(addr))) /* We use simple memory access functions in case the hardware allows it. diff --git a/src/ChangeLog b/src/ChangeLog index a828966f..28273663 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,9 @@ +2018-02-09 Mark Wielaard <mark@klomp.org> + + * readelf.c (print_debug_abbrev_section): Print the value of a + DW_FORM_implicit_const using dwarf_getabbrevattr_data. + (attr_callback): Handle DW_FORM_implicit_const. + 2018-01-30 Mark Wielaard <mark@klomp.org> * readelf.c (dwarf_unit_string): New function. diff --git a/src/readelf.c b/src/readelf.c index 93bc45db..bdeba4b6 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -4758,14 +4758,16 @@ print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)), size_t cnt = 0; unsigned int name; unsigned int form; + Dwarf_Sword data; Dwarf_Off enoffset; - while (dwarf_getabbrevattr (&abbrev, cnt, - &name, &form, &enoffset) == 0) + while (dwarf_getabbrevattr_data (&abbrev, cnt, &name, &form, + &data, &enoffset) == 0) { - printf (" attr: %s, form: %s, offset: %#" PRIx64 "\n", - dwarf_attr_name (name), dwarf_form_name (form), - (uint64_t) enoffset); - + printf (" attr: %s, form: %s", + dwarf_attr_name (name), dwarf_form_name (form)); + if (form == DW_FORM_implicit_const) + printf (" (%" PRId64 ")", data); + printf (", offset: %#" PRIx64 "\n", (uint64_t) enoffset); ++cnt; } @@ -6078,6 +6080,7 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) break; case DW_FORM_sec_offset: + case DW_FORM_implicit_const: case DW_FORM_udata: case DW_FORM_sdata: case DW_FORM_data8: |