dwarf_getlocation has to know which attributes can contain a DWARF expression or location list because the form alone might be ambiguous.
Since DWARF4 there is DW_FORM_exprloc so always accept that. But for older DWARF or location lists we cannot just check for DW_FORM_sec_offset since that could be a reference to diffent kinds of sections (based on attribute). Update the attribute list based on the latest DWARF5 encodings table. Note that DW_AT_call_origin wasn't added because that seems to be a typo in the DWARF5 spec. http://dwarfstd.org/ShowIssue.php?issue=171103.1 Signed-off-by: Mark Wielaard <m...@klomp.org> --- libdw/ChangeLog | 5 +++++ libdw/dwarf_getlocation.c | 26 +++++++++++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/libdw/ChangeLog b/libdw/ChangeLog index 7085649..bb9e849 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,5 +1,10 @@ 2017-11-03 Mark Wielaard <m...@klomp.org> + * dwarf_getlocation.c (attr_ok): Always accept DW_FORM_exprloc. + Update list of acceptable attribute codes based on DWARF5. + +2017-11-03 Mark Wielaard <m...@klomp.org> + * dwarf.h: Add DW_OP_GNU_variable_value. 2017-10-03 Mark Wielaard <m...@klomp.org> diff --git a/libdw/dwarf_getlocation.c b/libdw/dwarf_getlocation.c index a4a2761..c59546e 100644 --- a/libdw/dwarf_getlocation.c +++ b/libdw/dwarf_getlocation.c @@ -45,10 +45,34 @@ attr_ok (Dwarf_Attribute *attr) if (attr == NULL) return false; - /* Must be one of the attributes listed below. */ + /* If it is an exprloc, it is obviously OK. */ + if (dwarf_whatform (attr) == DW_FORM_exprloc) + return true; + + /* Otherwise must be one of the attributes listed below. Older + DWARF versions might have encoded the exprloc as block, and we + cannot easily distinquish attributes in the loclist class because + the same forms are used for different classes. */ switch (attr->code) { case DW_AT_location: + case DW_AT_byte_size: + case DW_AT_bit_offset: + case DW_AT_bit_size: + case DW_AT_lower_bound: + case DW_AT_bit_stride: + case DW_AT_upper_bound: + case DW_AT_count: + case DW_AT_allocated: + case DW_AT_associated: + case DW_AT_data_location: + case DW_AT_byte_stride: + case DW_AT_rank: + case DW_AT_call_value: + case DW_AT_call_target: + case DW_AT_call_target_clobbered: + case DW_AT_call_data_location: + case DW_AT_call_data_value: case DW_AT_data_member_location: case DW_AT_vtable_elem_location: case DW_AT_string_length: -- 1.8.3.1