Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [PATCH v2] gdb: Check DW_OP_deref_type size against type
@ 2026-08-22  3:56 Jielun Wu
  0 siblings, 0 replies; only message in thread
From: Jielun Wu @ 2026-08-22  3:56 UTC (permalink / raw)
  To: gdb-patches; +Cc: simark

DWARF v5 requires the explicit size operand of DW_OP_deref_type to
match the size of the referenced base type.  The evaluator currently
passes both sizes to dwarf_expr_context::deref without validating the
encoding, and the generic dereference helper accepts the mismatch by
zero-extending the bytes read from memory.

Reject a mismatch after resolving the base type.  Name the actual opcode
and report both sizes in the diagnostic.

Teach the testsuite's DWARF assembler to emit DW_OP_deref_type and
DW_OP_GNU_deref_type operands.  Add tests covering matching and
mismatched sizes for both opcodes.

Tested on x86_64-linux.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=34277
Signed-off-by: Jielun Wu <firmiana402@gmail.com>
---
Changes in v2:
- Name the actual opcode and report both sizes in the diagnostic.
- Rename addr_size to deref_size.
- Add DWARF assembler handlers for the standard and GNU opcodes.
- Add matching-size coverage for both opcodes.

 gdb/dwarf2/expr.c                             | 10 ++-
 .../gdb.dwarf2/dw2-deref-type-size.c          | 22 +++++
 .../gdb.dwarf2/dw2-deref-type-size.exp        | 88 +++++++++++++++++++
 gdb/testsuite/lib/dwarf.exp                   | 11 +++
 4 files changed, 129 insertions(+), 2 deletions(-)
 create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-deref-type-size.c
 create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-deref-type-size.exp

diff --git a/gdb/dwarf2/expr.c b/gdb/dwarf2/expr.c
index 3a6b8f58199..7160a73d80b 100644
--- a/gdb/dwarf2/expr.c
+++ b/gdb/dwarf2/expr.c
@@ -2016,7 +2016,8 @@ dwarf_expr_context::execute_stack_op (gdb::array_view<const gdb_byte> expr)
 	case DW_OP_deref_type:
 	case DW_OP_GNU_deref_type:
 	  {
-	    int addr_size = (op == DW_OP_deref ? this->m_addr_size : *op_ptr++);
+	    int deref_size
+	      = (op == DW_OP_deref ? this->m_addr_size : *op_ptr++);
 	    CORE_ADDR addr = fetch_address (0);
 	    struct type *type;
 
@@ -2027,11 +2028,16 @@ dwarf_expr_context::execute_stack_op (gdb::array_view<const gdb_byte> expr)
 		op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset);
 		cu_offset type_die_cu_off = (cu_offset) uoffset;
 		type = get_base_type (type_die_cu_off);
+		if (type->length () != deref_size)
+		  error (_("%s has dereference size %d, but its "
+			   "type has size %s"),
+			 get_DW_OP_name (op), deref_size,
+			 pulongest (type->length ()));
 	      }
 	    else
 	      type = address_type;
 
-	    result_val = this->deref (addr, addr_size, type);
+	    result_val = this->deref (addr, deref_size, type);
 	    break;
 	  }
 
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-deref-type-size.c b/gdb/testsuite/gdb.dwarf2/dw2-deref-type-size.c
new file mode 100644
index 00000000000..af01073cd74
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-deref-type-size.c
@@ -0,0 +1,22 @@
+/* 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/>.  */
+
+unsigned char deref_data = 0x5a;
+
+int
+main (void)
+{
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-deref-type-size.exp b/gdb/testsuite/gdb.dwarf2/dw2-deref-type-size.exp
new file mode 100644
index 00000000000..82d369f5220
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-deref-type-size.exp
@@ -0,0 +1,88 @@
+# 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 DW_OP_deref_type with explicit dereference sizes that both match
+# and differ from the size of the referenced base type.
+
+load_lib dwarf.exp
+
+require dwarf2_support
+
+standard_testfile .c -dw.S
+
+set asm_file [standard_output_file $srcfile2]
+
+Dwarf::assemble $asm_file {
+    cu {version 5} {
+	compile_unit {} {
+	    declare_labels uint8_label uint64_label
+
+	    uint8_label: base_type {
+		DW_AT_name "uint8_t"
+		DW_AT_encoding @DW_ATE_unsigned_char
+		DW_AT_byte_size 1 DW_FORM_sdata
+	    }
+
+	    uint64_label: base_type {
+		DW_AT_name "uint64_t"
+		DW_AT_encoding @DW_ATE_unsigned
+		DW_AT_byte_size 8 DW_FORM_sdata
+	    }
+
+	    foreach {var op size type_label} [list \
+		valid_deref_type DW_OP_deref_type 1 $uint8_label \
+		valid_gnu_deref_type DW_OP_GNU_deref_type 1 $uint8_label \
+		invalid_deref_type DW_OP_deref_type 4 $uint64_label \
+		invalid_gnu_deref_type DW_OP_GNU_deref_type 4 $uint64_label] {
+		DW_TAG_variable {
+		    DW_AT_name $var
+		    DW_AT_type :$type_label
+		    DW_AT_external 1 DW_FORM_flag
+		    DW_AT_location {
+			DW_OP_addr [gdb_target_symbol "deref_data"]
+			$op $size $type_label
+			DW_OP_stack_value
+		    } SPECIAL_expr
+		}
+	    }
+	}
+    }
+}
+
+if {[prepare_for_testing "failed to prepare" ${testfile} \
+	 [list $srcfile $asm_file] nodebug]} {
+    return
+}
+
+if {![runto_main]} {
+    return
+}
+
+foreach_with_prefix var {
+    valid_deref_type
+    valid_gnu_deref_type
+} {
+    gdb_test "print/x $var" " = 0x5a"
+}
+
+foreach {var op} {
+    invalid_deref_type DW_OP_deref_type
+    invalid_gnu_deref_type DW_OP_GNU_deref_type
+} {
+    with_test_prefix $var {
+	gdb_test "print $var" \
+	    "$op has dereference size 4, but its type has size 8"
+    }
+}
diff --git a/gdb/testsuite/lib/dwarf.exp b/gdb/testsuite/lib/dwarf.exp
index 839c5174265..54102b1981d 100644
--- a/gdb/testsuite/lib/dwarf.exp
+++ b/gdb/testsuite/lib/dwarf.exp
@@ -1460,6 +1460,17 @@ namespace eval Dwarf {
 	_op .byte $size
     }
 
+    proc _handle_DW_OP_deref_type {size label} {
+	variable _cu_label
+
+	_op .byte $size
+	_op .uleb128 "$label - $_cu_label"
+    }
+
+    proc _handle_DW_OP_GNU_deref_type {size label} {
+	_handle_DW_OP_deref_type $size $label
+    }
+
     proc _handle_DW_OP_bregx {register offset} {
 	_op .uleb128 $register
 	_op .sleb128 $offset
-- 
2.34.1

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2026-08-22  3:56 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-08-22  3:56 [PATCH v2] gdb: Check DW_OP_deref_type size against type Jielun Wu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox