From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 62897 invoked by alias); 9 Feb 2018 17:25:50 -0000 Mailing-List: contact elfutils-devel-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Post: List-Help: List-Subscribe: Sender: elfutils-devel-owner@sourceware.org Received: (qmail 62883 invoked by uid 89); 9 Feb 2018 17:25:49 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Checked: by ClamAV 0.99.2 on sourceware.org X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.9 required=5.0 tests=BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,KAM_LAZY_DOMAIN_SECURITY autolearn=ham version=3.3.2 spammy=6011, 8611, formp X-Spam-Status: No, score=-25.9 required=5.0 tests=BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,KAM_LAZY_DOMAIN_SECURITY autolearn=ham version=3.3.2 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on sourceware.org X-Spam-Level: X-HELO: gnu.wildebeest.org Received: from wildebeest.demon.nl (HELO gnu.wildebeest.org) (212.238.236.112) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 09 Feb 2018 17:25:46 +0000 Received: from tarox.wildebeest.org (tarox.wildebeest.org [172.31.17.39]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by gnu.wildebeest.org (Postfix) with ESMTPSA id 8A10C302BB05; Fri, 9 Feb 2018 18:25:43 +0100 (CET) Received: by tarox.wildebeest.org (Postfix, from userid 1000) id E6147413CD0D; Fri, 9 Feb 2018 18:25:42 +0100 (CET) From: Mark Wielaard To: elfutils-devel@sourceware.org Cc: Mark Wielaard Subject: [PATCH] libdw: Handle DWARF5 DW_FORM_implicit_const. Add dwarf_getabbrevattr_data. Date: Fri, 09 Feb 2018 17:25:00 -0000 Message-Id: <1518197139-13387-1-git-send-email-mark@klomp.org> X-Mailer: git-send-email 1.8.3.1 X-Spam-Flag: NO X-IsSubscribed: yes X-SW-Source: 2018-q1/txt/msg00028.txt.bz2 Handle the new DW_FORM_implicit_const. The value of this form is embedded in the abbrev data (as sleb128) and not in the info DIE data. This also adds a new function dwarf_getabbrevattr_data which allows getting any data/value associated with a form. eu-readelf will use this new function to show the DW_FORM_implicit_const value. Signed-off-by: Mark Wielaard --- libdw/ChangeLog | 19 +++++++++++++++++++ libdw/dwarf_child.c | 14 +++++++++++++- libdw/dwarf_formsdata.c | 7 ++++++- libdw/dwarf_formudata.c | 7 ++++++- libdw/dwarf_getabbrev.c | 7 +++++++ libdw/dwarf_getabbrevattr.c | 22 ++++++++++++++++++++-- libdw/dwarf_getattrs.c | 11 ++++++++++- libdw/dwarf_hasattr.c | 6 ++++++ libdw/libdw.h | 6 ++++++ libdw/libdw.map | 1 + libdw/libdwP.h | 1 + libdw/memory-access.h | 19 +++++++++++++++++++ src/ChangeLog | 6 ++++++ src/readelf.c | 15 +++++++++------ 14 files changed, 129 insertions(+), 12 deletions(-) diff --git a/libdw/ChangeLog b/libdw/ChangeLog index 65e4ddc..f52ce58 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,3 +1,22 @@ +2018-02-09 Mark Wielaard + + * 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 * dwarf.h: Add DWARF5 DW_FORMs. diff --git a/libdw/dwarf_child.c b/libdw/dwarf_child.c index 248338e..9446b88 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 bc2b508..def32c9 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 , 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 e41981a..9c1644e 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 , 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 a3a68b3..1e113db 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 57fe363..54ff604 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 7f55faf..50faf98 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 90b333e..90053b1 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 acc3891..ac43ad9 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 8d12e89..4577d05 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 b31497d..ad55558 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 ed68bdb..5f96a14 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 c724c6a..ebd6f55 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,9 @@ +2018-02-09 Mark Wielaard + + * 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 * readelf.c (dwarf_unit_string): New function. diff --git a/src/readelf.c b/src/readelf.c index 4449584..c57d7fe 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: -- 1.8.3.1