Fix bug in DW_OP_GNU_variable_value evaluation

Message ID 20200727204644.2410247-1-tromey@adacore.com
State New
Headers show
Series
  • Fix bug in DW_OP_GNU_variable_value evaluation
Related show

Commit Message

Tom Tromey July 27, 2020, 8:46 p.m.
A modified version of the gnat compiler (TBH I don't know if the
modifications are relevant to this bug or not, but I figured I'd
mention it) can generate a DWARF location expression like:

 <1><1201>: Abbrev Number: 3 (DW_TAG_dwarf_procedure)
    <1202>   DW_AT_location    : 32 byte block: 12 31 29 28 4 0 30 2f 12 0 14 30 2d 28 4 0 14 2f 1 0 30 34 1e 23 3 9 fc 1a 16 13 16 13 	(DW_OP_dup; DW_OP_lit1; DW_OP_eq; DW_OP_bra: 4; DW_OP_lit0; DW_OP_skip: 18; DW_OP_over; DW_OP_lit0; DW_OP_lt; DW_OP_bra: 4; DW_OP_over; DW_OP_skip: 1; DW_OP_lit0; DW_OP_lit4; DW_OP_mul; DW_OP_plus_uconst: 3; DW_OP_const1s: -4; DW_OP_and; DW_OP_swap; DW_OP_drop; DW_OP_swap; DW_OP_drop)

 <2><1279>: Abbrev Number: 9 (DW_TAG_structure_type)
    <127a>   DW_AT_name        : (indirect string, offset: 0x1a5a): p__logical_channel_t
    <127e>   DW_AT_byte_size   : 18 byte block: fd 43 12 0 0 97 94 1 99 34 0 0 0 23 7 9 fc 1a 	(DW_OP_GNU_variable_value: <0x1243>; DW_OP_push_object_address; DW_OP_deref_size: 1; DW_OP_call4: <0x1201>; DW_OP_plus_uconst: 7; DW_OP_const1s: -4; DW_OP_and)

When evaluated, this gives:

    Incompatible types on DWARF stack

In Jakub's original message about DW_OP_GNU_variable_value:

    https://gcc.gnu.org/legacy-ml/gcc-patches/2017-02/msg01499.html

.. it says:

    The intended behavior is that the debug info consumer computes the
    value of that referenced variable at the current PC, and if it can
    compute it and pushes the value as a generic type integer into the
    DWARF stack

Instead, gdb is using the variable's type -- but this fails with some
operations, like DW_OP_and, which expect the types to match.

I believe what was intended was for the value to be cast to the DWARF
"untyped" type, which is what this patch implements.  This patch also
updates varval.exp to exhibit the bug.

gdb/ChangeLog
2020-07-27  Tom Tromey  <tromey@adacore.com>

	* dwarf2/expr.c (dwarf_expr_context::execute_stack_op)
	<DW_OP_GNU_variable_value>: Cast to address type.

gdb/testsuite/ChangeLog
2020-07-27  Tom Tromey  <tromey@adacore.com>

	* gdb.dwarf2/varval.exp (setup_exec): Add 'or' instruction to
	'varval' location.
---
 gdb/ChangeLog                       | 5 +++++
 gdb/dwarf2/expr.c                   | 3 ++-
 gdb/testsuite/ChangeLog             | 5 +++++
 gdb/testsuite/gdb.dwarf2/varval.exp | 2 ++
 4 files changed, 14 insertions(+), 1 deletion(-)

-- 
2.26.2

Comments

Eli Zaretskii via Gdb-patches July 28, 2020, 1:23 a.m. | #1
On Mon, 27 Jul 2020 14:46:44 -0600
Tom Tromey <tromey@adacore.com> wrote:

> A modified version of the gnat compiler (TBH I don't know if the

> modifications are relevant to this bug or not, but I figured I'd

> mention it) can generate a DWARF location expression like:

> 

>  <1><1201>: Abbrev Number: 3 (DW_TAG_dwarf_procedure)

>     <1202>   DW_AT_location    : 32 byte block: 12 31 29 28 4 0 30 2f 12 0 14 30 2d 28 4 0 14 2f 1 0 30 34 1e 23 3 9 fc 1a 16 13 16 13 	(DW_OP_dup; DW_OP_lit1; DW_OP_eq; DW_OP_bra: 4; DW_OP_lit0; DW_OP_skip: 18; DW_OP_over; DW_OP_lit0; DW_OP_lt; DW_OP_bra: 4; DW_OP_over; DW_OP_skip: 1; DW_OP_lit0; DW_OP_lit4; DW_OP_mul; DW_OP_plus_uconst: 3; DW_OP_const1s: -4; DW_OP_and; DW_OP_swap; DW_OP_drop; DW_OP_swap; DW_OP_drop)

> 

>  <2><1279>: Abbrev Number: 9 (DW_TAG_structure_type)

>     <127a>   DW_AT_name        : (indirect string, offset: 0x1a5a): p__logical_channel_t

>     <127e>   DW_AT_byte_size   : 18 byte block: fd 43 12 0 0 97 94 1 99 34 0 0 0 23 7 9 fc 1a 	(DW_OP_GNU_variable_value: <0x1243>; DW_OP_push_object_address; DW_OP_deref_size: 1; DW_OP_call4: <0x1201>; DW_OP_plus_uconst: 7; DW_OP_const1s: -4; DW_OP_and)

> 

> When evaluated, this gives:

> 

>     Incompatible types on DWARF stack

> 

> In Jakub's original message about DW_OP_GNU_variable_value:

> 

>     https://gcc.gnu.org/legacy-ml/gcc-patches/2017-02/msg01499.html

> 

> .. it says:

> 

>     The intended behavior is that the debug info consumer computes the

>     value of that referenced variable at the current PC, and if it can

>     compute it and pushes the value as a generic type integer into the

>     DWARF stack

> 

> Instead, gdb is using the variable's type -- but this fails with some

> operations, like DW_OP_and, which expect the types to match.

> 

> I believe what was intended was for the value to be cast to the DWARF

> "untyped" type, which is what this patch implements.  This patch also

> updates varval.exp to exhibit the bug.

> 

> gdb/ChangeLog

> 2020-07-27  Tom Tromey  <tromey@adacore.com>

> 

> 	* dwarf2/expr.c (dwarf_expr_context::execute_stack_op)

> 	<DW_OP_GNU_variable_value>: Cast to address type.

> 

> gdb/testsuite/ChangeLog

> 2020-07-27  Tom Tromey  <tromey@adacore.com>

> 

> 	* gdb.dwarf2/varval.exp (setup_exec): Add 'or' instruction to

> 	'varval' location.


LGTM.

Kevin
Tom Tromey July 28, 2020, 5:01 p.m. | #2
>>>>> "Kevin" == Kevin Buettner <kevinb@redhat.com> writes:


>> gdb/ChangeLog

>> 2020-07-27  Tom Tromey  <tromey@adacore.com>

>> 

>> * dwarf2/expr.c (dwarf_expr_context::execute_stack_op)

>> <DW_OP_GNU_variable_value>: Cast to address type.

>> 

>> gdb/testsuite/ChangeLog

>> 2020-07-27  Tom Tromey  <tromey@adacore.com>

>> 

>> * gdb.dwarf2/varval.exp (setup_exec): Add 'or' instruction to

>> 'varval' location.


Kevin> LGTM.

Thanks.  I am going to check this one in.

Tom

Patch

diff --git a/gdb/dwarf2/expr.c b/gdb/dwarf2/expr.c
index 91ac4c0d9d2..9bf74139d2d 100644
--- a/gdb/dwarf2/expr.c
+++ b/gdb/dwarf2/expr.c
@@ -1270,7 +1270,8 @@  dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
 	                                                this->ref_addr_size,
 							byte_order);
 	    op_ptr += this->ref_addr_size;
-	    result_val = this->dwarf_variable_value (sect_off);
+	    result_val = value_cast (address_type,
+				     this->dwarf_variable_value (sect_off));
 	  }
 	  break;
 	
diff --git a/gdb/testsuite/gdb.dwarf2/varval.exp b/gdb/testsuite/gdb.dwarf2/varval.exp
index 69790e7370e..cb8836e2b24 100644
--- a/gdb/testsuite/gdb.dwarf2/varval.exp
+++ b/gdb/testsuite/gdb.dwarf2/varval.exp
@@ -207,6 +207,8 @@  proc setup_exec { arg_bad } {
 			{DW_AT_type :${int_label}}
 			{DW_AT_location {
 			    DW_OP_GNU_variable_value ${var_a_label}
+			    DW_OP_const1s 0
+			    DW_OP_or
 			    DW_OP_stack_value
 			} SPECIAL_expr}
 		    }