[PATCH] gdb: Preserve the operand type in DW_OP_plus_uconst
Jielun Wu <[email protected]>
| Newsgroups | gmane.comp.gdb.patches |
|---|---|
| Message-ID | <[email protected]> |
DWARF v5 requires DW_OP_plus_uconst to interpret its unsigned LEB128 constant as the type of the popped stack entry and push a result of that same type. GDB instead reconstructs the result using address_type, discarding an explicit base type. Construct the result using the popped value's type. Add a DWARF assembler test that uses a typed value after DW_OP_plus_uconst in another typed arithmetic operation. Without the fix, the expression fails with incompatible DWARF stack types. Tested on x86_64-linux. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=34315 Signed-off-by: Jielun Wu <[email protected]> --- gdb/dwarf2/expr.c | 2 +- .../gdb.dwarf2/dw2-plus-uconst-type.exp | 75 +++++++++++++++++++ 2 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-plus-uconst-type.exp diff --git a/gdb/dwarf2/expr.c b/gdb/dwarf2/expr.c index 3a6b8f58199..2d9408a3a27 100644 --- a/gdb/dwarf2/expr.c +++ b/gdb/dwarf2/expr.c @@ -2063,7 +2063,7 @@ dwarf_expr_context::execute_stack_op (gdb::array_view<const gdb_byte> expr) result = value_as_long (result_val); op_ptr = safe_read_uleb128 (op_ptr, op_end, ®); result += reg; - result_val = value_from_ulongest (address_type, result); + result_val = value_from_ulongest (result_val->type (), result); break; } } diff --git a/gdb/testsuite/gdb.dwarf2/dw2-plus-uconst-type.exp b/gdb/testsuite/gdb.dwarf2/dw2-plus-uconst-type.exp new file mode 100644 index 00000000000..224324798c6 --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/dw2-plus-uconst-type.exp @@ -0,0 +1,75 @@ +# Copyright 2026 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Test that DW_OP_plus_uconst preserves the type of the popped stack value. +# A following DW_OP_plus checks this: it reports an error if the intermediate +# result and the second explicitly typed value have incompatible types. + +load_lib dwarf.exp + +require dwarf2_support + +standard_testfile main.c -dw.S + +set asm_file [standard_output_file $srcfile2] + +Dwarf::assemble $asm_file { + cu {version 5} { + compile_unit {} { + declare_labels uint32_label + + uint32_label: base_type { + DW_AT_name "uint32_t" + DW_AT_encoding @DW_ATE_unsigned + DW_AT_byte_size 4 DW_FORM_sdata + } + + DW_TAG_variable { + DW_AT_name "plus_uconst_preserves_type" + DW_AT_type :$uint32_label + DW_AT_external 1 DW_FORM_flag + DW_AT_location { + variable _constants + variable _cu_label + + _op .byte $_constants(DW_OP_const_type) + _op .uleb128 "$uint32_label - $_cu_label" \ + "base type DIE offset" + _op .byte 4 "constant size" + _op .4byte 40 "constant data" + DW_OP_plus_uconst 1 + _op .byte $_constants(DW_OP_const_type) + _op .uleb128 "$uint32_label - $_cu_label" \ + "base type DIE offset" + _op .byte 4 "constant size" + _op .4byte 1 "constant data" + DW_OP_plus + DW_OP_stack_value + } SPECIAL_expr + } + } + } +} + +if {[prepare_for_testing "failed to prepare" ${testfile} \ + [list $srcfile $asm_file] nodebug]} { + return +} + +if {![runto_main]} { + return +} + +gdb_test "print plus_uconst_preserves_type" " = 42" -- 2.34.1