From: Jielun Wu <firmiana402@gmail.com>
To: gdb-patches@sourceware.org
Cc: simark@simark.ca
Subject: [PATCH v2] gdb: Check DW_OP_deref_type size against type
Date: Sat, 22 Aug 2026 11:56:21 +0800 [thread overview]
Message-ID: <20260822035621.694548-1-firmiana402@gmail.com> (raw)
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
reply other threads:[~2026-08-22 3:56 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260822035621.694548-1-firmiana402@gmail.com \
--to=firmiana402@gmail.com \
--cc=gdb-patches@sourceware.org \
--cc=simark@simark.ca \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox