[PATCH 2/3] libdw: Update acceptable forms and attributes for dwarf_getlocation.
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 --- 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 + * dwarf_getlocation.c (attr_ok): Always accept DW_FORM_exprloc. + Update list of acceptable attribute codes based on DWARF5. + +2017-11-03 Mark Wielaard + * dwarf.h: Add DW_OP_GNU_variable_value. 2017-10-03 Mark Wielaard 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
[PATCH 3/3] libdw: Handle DW_OP_GNU_variable_value.
Handle DW_OP_GNU_variable_value in dwarf_getlocation[_attr,_die]. DW_OP_GNU_variable_value takes one argument a DIE reference that describes a value given by a location of const_value attribute. To test handling of the new operand the varlocs test is adapted to print out all DIEs and attributes with expressions or location lists (the original varlocs test only prints out variables and arguments of function DIEs). Signed-off-by: Mark Wielaard --- libdw/ChangeLog| 7 ++ libdw/dwarf_getlocation.c | 1 + libdw/dwarf_getlocation_attr.c | 1 + libdw/dwarf_getlocation_die.c | 1 + tests/ChangeLog| 16 +++ tests/Makefile.am | 4 +- tests/run-exprlocs.sh | 180 tests/testfile-stridex.bz2 | Bin 0 -> 4009 bytes tests/varlocs.c| 228 - 9 files changed, 431 insertions(+), 7 deletions(-) create mode 100755 tests/run-exprlocs.sh create mode 100755 tests/testfile-stridex.bz2 diff --git a/libdw/ChangeLog b/libdw/ChangeLog index bb9e849..4375244 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,5 +1,12 @@ 2017-11-03 Mark Wielaard + * dwarf_getlocation.c (__libdw_intern_expression): Handle + DW_OP_GNU_variable_value. + * dwarf_getlocation_attr.c (dwarf_getlocation_attr): Likewise. + * dwarf_getlocation_die.c (dwarf_getlocation_die): Likewise. + +2017-11-03 Mark Wielaard + * dwarf_getlocation.c (attr_ok): Always accept DW_FORM_exprloc. Update list of acceptable attribute codes based on DWARF5. diff --git a/libdw/dwarf_getlocation.c b/libdw/dwarf_getlocation.c index c59546e..86a9ae7 100644 --- a/libdw/dwarf_getlocation.c +++ b/libdw/dwarf_getlocation.c @@ -323,6 +323,7 @@ __libdw_intern_expression (Dwarf *dbg, bool other_byte_order, break; case DW_OP_call_ref: + case DW_OP_GNU_variable_value: /* DW_FORM_ref_addr, depends on offset size of CU. */ if (dbg == NULL || __libdw_read_offset_inc (dbg, sec_index, &data, ref_size, diff --git a/libdw/dwarf_getlocation_attr.c b/libdw/dwarf_getlocation_attr.c index 8b6a4af..e4dd708 100644 --- a/libdw/dwarf_getlocation_attr.c +++ b/libdw/dwarf_getlocation_attr.c @@ -97,6 +97,7 @@ dwarf_getlocation_attr (Dwarf_Attribute *attr, const Dwarf_Op *op, Dwarf_Attribu break; case DW_OP_GNU_implicit_pointer: + case DW_OP_GNU_variable_value: { Dwarf_Die die; if (INTUSE(dwarf_getlocation_die) (attr, op, &die) != 0) diff --git a/libdw/dwarf_getlocation_die.c b/libdw/dwarf_getlocation_die.c index b4908d2..21b4365 100644 --- a/libdw/dwarf_getlocation_die.c +++ b/libdw/dwarf_getlocation_die.c @@ -45,6 +45,7 @@ dwarf_getlocation_die (Dwarf_Attribute *attr, const Dwarf_Op *op, { case DW_OP_GNU_implicit_pointer: case DW_OP_call_ref: +case DW_OP_GNU_variable_value: dieoff = op->number; break; diff --git a/tests/ChangeLog b/tests/ChangeLog index beac0e2..f39a027 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,19 @@ +2017-11-03 Mark Wielaard + + * run-exprlocs.sh: New test. + * testfile-stridex.bz2: New testfile. + * Makefile.am (TESTS): Add run-exprlocs.sh. + (EXTRA_DIST): Add run-exprlocs.sh and testfile-stridex.bz2. + * varlocs.c (dwarf_tag_string): New function. + (dwarf_attr_string): Likewise. + (dwarf_form_string): Likewise. + (print_expr): Fix typo in error message.r + Handle DW_OP_GNU_variable_value. + (attr_arg): New struct. + (handle_attr): New function. + (handle_die): Likewise. + (main): Handle --exprlocs argument. Call handle_die. + 2017-10-16 Mark Wielaard * md5-sha1-test.c: Removed. diff --git a/tests/Makefile.am b/tests/Makefile.am index ec42b80..f992b12 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -112,7 +112,7 @@ TESTS = run-arextract.sh run-arsymtest.sh run-ar.sh newfile test-nlist \ run-dwfl-report-elf-align.sh run-addr2line-test.sh \ run-addr2line-i-test.sh run-addr2line-i-lex-test.sh \ run-addr2line-i-demangle-test.sh run-addr2line-alt-debugpath.sh \ - run-varlocs.sh run-funcretval.sh \ + run-varlocs.sh run-exprlocs.sh run-funcretval.sh \ run-backtrace-native.sh run-backtrace-data.sh run-backtrace-dwarf.sh \ run-backtrace-native-biarch.sh run-backtrace-native-core.sh \ run-backtrace-native-core-biarch.sh run-backtrace-core-x86_64.sh \ @@ -284,7 +284,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \ testfileppc32.bz2 testfileppc64.bz2 \ testfiles390.bz2 testfiles390x.bz2 \ testfilearm.bz2 testfileaarch64.bz2 \ -run-varlocs.sh \ +run-varlocs.sh run-exprlocs.sh testfile-stridex.bz2 \ testfile_const_type.c testfile_
[PATCH 1/3] readelf: Handle DW_OP_GNU_variable_value.
Also format both DW_OP_call_ref and DW_OP_GNU_variable_value argument as a normal DIE reference. Signed-off-by: Mark Wielaard --- libdw/ChangeLog | 4 libdw/dwarf.h | 1 + src/ChangeLog | 5 + src/readelf.c | 5 +++-- 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/libdw/ChangeLog b/libdw/ChangeLog index e6e7f3b..7085649 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,3 +1,7 @@ +2017-11-03 Mark Wielaard + + * dwarf.h: Add DW_OP_GNU_variable_value. + 2017-10-03 Mark Wielaard * libdw.h: Define LIBDW_CIE_ID and use it in dwarf_cfi_cie_p. diff --git a/libdw/dwarf.h b/libdw/dwarf.h index 902d261..8edf719 100644 --- a/libdw/dwarf.h +++ b/libdw/dwarf.h @@ -545,6 +545,7 @@ enum DW_OP_GNU_convert = 0xf7, DW_OP_GNU_reinterpret = 0xf9, DW_OP_GNU_parameter_ref = 0xfa, +DW_OP_GNU_variable_value = 0xfd, DW_OP_lo_user = 0xe0, /* Implementation-defined range start. */ DW_OP_hi_user = 0xff /* Implementation-defined range end. */ diff --git a/src/ChangeLog b/src/ChangeLog index 0d3bfc1..3b886a7 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,8 @@ +2017-11-03 Mark Wielaard + + * readelf.c (print_ops): Handle DW_OP_GNU_variable_value. Print + referenced DIE as offset. + 2017-09-10 Mark Wielaard * ar.c (do_oper_delete): Remove DEBUG conditional check. diff --git a/src/readelf.c b/src/readelf.c index 5e2f3fc..833884b 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -4160,6 +4160,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, break; case DW_OP_call_ref: + case DW_OP_GNU_variable_value: /* Offset operand. */ if (ref_size != 4 && ref_size != 8) goto invalid; /* Cannot be used in CFA. */ @@ -4170,8 +4171,8 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, addr = read_8ubyte_unaligned (dbg, data); data += ref_size; CONSUME (ref_size); - - printf ("%*s[%4" PRIuMAX "] %s %#" PRIxMAX "\n", + /* addr is a DIE offset, so format it as one. */ + printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "]\n", indent, "", (uintmax_t) offset, op_name, (uintmax_t) addr); offset += 1 + ref_size; -- 1.8.3.1
[PATCH] DwarfExtensions: Document DW_OP_GNU_variable_value.
Signed-off-by: Mark Wielaard --- DwarfExtensions | 1 + 1 file changed, 1 insertion(+) diff --git a/DwarfExtensions b/DwarfExtensions index ba5ab41..9a2b844 100644 --- a/DwarfExtensions +++ b/DwarfExtensions @@ -106,6 +106,7 @@ DW_OP_GNU_parameter_ref 0xfa http://gcc.gnu.org/ml/gcc-patches/2011-06/msg00649.html";>References optimized out parameter GCC readelf DW_OP_GNU_addr_index 0xfb http://gcc.gnu.org/wiki/DebugFission";>GNU Fission http://www.dwarfstd.org/ShowIssue.php?issue=120514.1&type=closed";>DWARF5 proposal Unknown No support DW_OP_GNU_const_index 0xfc http://gcc.gnu.org/wiki/DebugFission";>GNU Fission http://www.dwarfstd.org/ShowIssue.php?issue=120514.1&type=closed";>DWARF5 proposal Unknown No support + DW_OP_GNU_variable_value 0xfd Provides value (not address) of referenced DIE https://gcc.gnu.org/ml/gcc-patches/2017-02/msg01499.html";>GCC patch http://www.dwarfstd.org/ShowIssue.php?issue=161109.2";>DWARF6 proposal GCC readelf, libdw Language codes -- 1.8.3.1