+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.
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). */
// __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);
+ }
}
}
/* 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.
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;
/* 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.
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;
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);
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;
const unsigned char *start_attrp;
unsigned int name;
unsigned int form;
+ Dwarf_Word data;
do
{
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;
*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);
+}
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. */
// __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 */
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)
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,
global:
dwarf_die_addr_die;
dwarf_get_units;
+ dwarf_getabbrevattr_data;
} ELFUTILS_0.170;
INTDECL (dwarf_formsdata)
INTDECL (dwarf_formstring)
INTDECL (dwarf_formudata)
+INTDECL (dwarf_getabbrevattr_data)
INTDECL (dwarf_getalt)
INTDECL (dwarf_getarange_addr)
INTDECL (dwarf_getarangeinfo)
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.
+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.
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;
}
break;
case DW_FORM_sec_offset:
+ case DW_FORM_implicit_const:
case DW_FORM_udata:
case DW_FORM_sdata:
case DW_FORM_data8: