summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libdw/ChangeLog19
-rw-r--r--libdw/dwarf_child.c14
-rw-r--r--libdw/dwarf_formsdata.c7
-rw-r--r--libdw/dwarf_formudata.c7
-rw-r--r--libdw/dwarf_getabbrev.c7
-rw-r--r--libdw/dwarf_getabbrevattr.c22
-rw-r--r--libdw/dwarf_getattrs.c11
-rw-r--r--libdw/dwarf_hasattr.c6
-rw-r--r--libdw/libdw.h6
-rw-r--r--libdw/libdw.map1
-rw-r--r--libdw/libdwP.h1
-rw-r--r--libdw/memory-access.h19
-rw-r--r--src/ChangeLog6
-rw-r--r--src/readelf.c15
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: