diff options
author | Kevin Buettner <kevinb@redhat.com> | 2018-07-30 15:41:56 -0700 |
---|---|---|
committer | Kevin Buettner <kevinb@redhat.com> | 2018-08-18 12:57:59 -0700 |
commit | a6b786da4e3353bf634ec7d9c7bffbd7569e73c6 (patch) | |
tree | 10386bffdca5e61d5d05ff6379b5880319275dd4 /gdb/dwarf2expr.c | |
parent | f41078422a4381d4943f36aa1ef95b1d7c85ee7e (diff) | |
download | gdb-a6b786da4e3353bf634ec7d9c7bffbd7569e73c6.zip gdb-a6b786da4e3353bf634ec7d9c7bffbd7569e73c6.tar.gz gdb-a6b786da4e3353bf634ec7d9c7bffbd7569e73c6.tar.bz2 |
Add support for DW_OP_GNU_variable_value
This patch adds support for DW_OP_GNU_variable_value to GDB.
Jakub Jelinek provides a fairly expansive discussion of this DWARF
expression opcode in his GCC patch...
https://gcc.gnu.org/ml/gcc-patches/2017-02/msg01499.html
It has also been proposed for addition to the DWARF Standard:
http://www.dwarfstd.org/ShowIssue.php?issue=161109.2
If compiled with a suitable version of GCC, the test case associated
with GCC Bug 77589 uses DW_OP_GNU_variable_value in a DW_AT_byte_stride
expression. Here's a link to the bug:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77589
This is what the DWARF looks like. Look at the last line, which has
the DW_AT_byte_stride expression:
<2><e1>: Abbrev Number: 12 (DW_TAG_variable)
<e2> DW_AT_name : (indirect string, offset: 0x115): span.0
<e6> DW_AT_type : <0x2e>
<ea> DW_AT_artificial : 1
<ea> DW_AT_location : 3 byte block: 91 b0 7f (DW_OP_fbreg: -80)
...
<2><178>: Abbrev Number: 18 (DW_TAG_subrange_type)
<179> DW_AT_lower_bound : 4 byte block: 97 23 20 6 (DW_OP_push_object_address; DW_OP_plus_uconst: 32; DW_OP_deref)
<17e> DW_AT_upper_bound : 4 byte block: 97 23 28 6 (DW_OP_push_object_address; DW_OP_plus_uconst: 40; DW_OP_deref)
<183> DW_AT_byte_stride : 10 byte block: 97 23 18 6 fd e1 0 0 0 1e (DW_OP_push_object_address; DW_OP_plus_uconst: 24; DW_OP_deref; DW_OP_GNU_variable_value: <0xe1>; DW_OP_mul)
A patch to readelf, which I'm also submitting, is required to do this
decoding.
I found that GDB gave me the correct answer for "p c40pt(2)" once I
(correctly) implemented DW_OP_GNU_variable_value.
I also have test case (later in this series) which uses the DWARF
assembler and, therefore, do not rely on having a compiler with this
support.
gdb/ChangeLog:
* dwarf2expr.h (struct dwarf_expr_context): Add virtual method
dwarf_variable_value.
* dwarf2-frame.c (class dwarf_expr_executor):
Add override for dwarf_variable_value.
* dwarf2loc.c (class dwarf_evaluate_loc_desc): Likewise.
(class symbol_needs_eval_context): Likewise.
(indirect_synthetic_pointer): Add forward declaration.
(sect_variable_value): New function.
(dwarf2_compile_expr_to_ax): Add case for DW_OP_GNU_variable_value.
* dwarf2expr.c (dwarf_expr_context::execute_stack_op): Add case
for DW_OP_GNU_variable_value.
Diffstat (limited to 'gdb/dwarf2expr.c')
-rw-r--r-- | gdb/dwarf2expr.c | 11 |
1 files changed, 11 insertions, 0 deletions
diff --git a/gdb/dwarf2expr.c b/gdb/dwarf2expr.c index 445f857..f1ca033 100644 --- a/gdb/dwarf2expr.c +++ b/gdb/dwarf2expr.c @@ -1259,6 +1259,17 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr, this->dwarf_call (cu_off); } goto no_push; + + case DW_OP_GNU_variable_value: + { + sect_offset sect_off + = (sect_offset) extract_unsigned_integer (op_ptr, + this->ref_addr_size, + byte_order); + op_ptr += this->ref_addr_size; + result_val = this->dwarf_variable_value (sect_off); + } + break; case DW_OP_entry_value: case DW_OP_GNU_entry_value: |