For DWARF version 4 or higher a block form really encodes a block, not an expression location. Also constant offsets can be expressed as DW_FORM_implicit_const in DWARF version 5.
Signed-off-by: Mark Wielaard <m...@klomp.org> --- libdw/ChangeLog | 6 ++++++ libdw/dwarf_getlocation.c | 17 +++++++++++++++++ src/ChangeLog | 5 +++++ src/readelf.c | 4 +++- 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/libdw/ChangeLog b/libdw/ChangeLog index b8038f00..f01bee39 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,3 +1,9 @@ +2021-02-12 Mark Wielaard <m...@klomp.org> + + * dwarf_getlocation.c (attr_ok): For DWARF version 4 or higher + block forms are not expression locations. + (is_constant_offset): DW_FORM_implicit_const is also a constant. + 2020-12-20 Dmitry V. Levin <l...@altlinux.org> * .gitignore: New file. diff --git a/libdw/dwarf_getlocation.c b/libdw/dwarf_getlocation.c index 4e582db2..5db3cf97 100644 --- a/libdw/dwarf_getlocation.c +++ b/libdw/dwarf_getlocation.c @@ -48,6 +48,22 @@ attr_ok (Dwarf_Attribute *attr) if (dwarf_whatform (attr) == DW_FORM_exprloc) return true; + if (attr->cu->version >= 4) + { + /* Must be an exprloc (or constant), just not any block form. */ + switch (dwarf_whatform (attr)) + { + case DW_FORM_block: + case DW_FORM_block1: + case DW_FORM_block2: + case DW_FORM_block4: + __libdw_seterrno (DWARF_E_NO_LOC_VALUE); + return false; + default: + break; + } + } + /* Otherwise must be one of the attributes listed below. Older DWARF versions might have encoded the exprloc as block, and we cannot easily distinguish attributes in the loclist class because @@ -186,6 +202,7 @@ is_constant_offset (Dwarf_Attribute *attr, case DW_FORM_data8: case DW_FORM_sdata: case DW_FORM_udata: + case DW_FORM_implicit_const: break; } diff --git a/src/ChangeLog b/src/ChangeLog index e65620fd..61cd98f4 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,8 @@ +2021-02-12 Mark Wielaard <m...@klomp.org> + + * readelf.c (attr_callback): Don't handle blocks as expression + blocks for DWARF version 4 or higher. + 2021-02-03 Timm Bäder <tbae...@redhat.com> * ar.c (do_oper_extract): Extract should_truncate_fname function diff --git a/src/readelf.c b/src/readelf.c index 11692bb5..9d2a25a4 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -7599,7 +7599,9 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) case DW_AT_GNU_call_site_data_value: case DW_AT_GNU_call_site_target: case DW_AT_GNU_call_site_target_clobbered: - if (form != DW_FORM_data16) + if (form == DW_FORM_exprloc + || (form != DW_FORM_data16 + && attrp->cu->version < 4)) /* blocks were expressions. */ { putchar ('\n'); print_ops (cbargs->dwflmod, cbargs->dbg, -- 2.18.4