Fix bug in DW_OP_GNU_variable_value evaluation
authorTom Tromey <tromey@adacore.com>
Tue, 28 Jul 2020 16:55:43 +0000 (10:55 -0600)
committerTom Tromey <tromey@adacore.com>
Tue, 28 Jul 2020 16:55:43 +0000 (10:55 -0600)
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-28  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-28  Tom Tromey  <tromey@adacore.com>

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

gdb/ChangeLog
gdb/dwarf2/expr.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.dwarf2/varval.exp

index bc05eeaea30d435a5eedc8e7ea6bdf0721f6c68c..e10f89fc2d622d697c3621e50782d86a07799244 100644 (file)
@@ -1,3 +1,8 @@
+2020-07-28  Tom Tromey  <tromey@adacore.com>
+
+       * dwarf2/expr.c (dwarf_expr_context::execute_stack_op)
+       <DW_OP_GNU_variable_value>: Cast to address type.
+
 2020-07-28  Kamil Rytarowski  <n54@gmx.com>
 
        * nbsd-nat.h (nbsd_nat_target::xfer_partial): New declaration.
index 91ac4c0d9d2def605c89efbed226a9b3cc0e777d..9bf74139d2da2b30aeb190031046d243abb9ac73 100644 (file)
@@ -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;
        
index 5ae258820e64f745eb3750f9f293cf2798384777..40283fa532643e45b97996445bbc3e09fe950a8e 100644 (file)
@@ -1,3 +1,8 @@
+2020-07-28  Tom Tromey  <tromey@adacore.com>
+
+       * gdb.dwarf2/varval.exp (setup_exec): Add 'or' instruction to
+       'varval' location.
+
 2020-07-28  Andrew Burgess  <andrew.burgess@embecosm.com>
 
        * gdb.python/py-unwind.py: Update to make use of a register
index 69790e7370e443961ff9df2776809fa21a2c4a08..cb8836e2b24f468784e6202689cedb34042f6ca4 100644 (file)
@@ -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}
                    }