From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id lrk+LJumkGq/DggAWB0awg (envelope-from ) for ; Thu, 27 Aug 2026 17:05:31 -0400 Authentication-Results: simark.ca; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=Z/l2P8vJ; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id 82A721E166; Thu, 27 Aug 2026 17:05:31 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-6.4 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham autolearn_force=no version=4.0.1 Received: from vm01.sourceware.org (vm01.sourceware.org [IPv6:2620:52:6:3111::32]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id 80BB31E033 for ; Thu, 27 Aug 2026 17:05:29 -0400 (EDT) Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 37D6F4BA79AF for ; Thu, 27 Aug 2026 21:05:28 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 37D6F4BA79AF Authentication-Results: sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=Z/l2P8vJ Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTP id 8B2C94BA2E37 for ; Thu, 27 Aug 2026 21:05:01 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 8B2C94BA2E37 Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 8B2C94BA2E37 Authentication-Results: sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1787864701; cv=none; b=ETPXyg71HHBB6cZBpFS9yfv4/y2CHir+rTzV/mlWmwnCutQ/qVwu+eoTW6Mx7nRI+0y4WXeY7Ta2uuNfIRa9D5ScTMi6+iOluOrQarNdJR8WgBK7bozVzeYZtkHupksRrn7Ej+steuvta7//2iS6+rb4lnGGtvg4uY8/E8e0qJA= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1787864701; c=relaxed/simple; bh=bItDlSBI4Tm663hM1W2YUvcwLHZvv7/RR3C2EWs8lm0=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=JNuo9wKx0bdiFbyB8Rlb5YaRwcKJ5IVOW+uzlzklr1L8RbGkNPNJoUDQUoamU8dQbP0ebgEzbELGKKlmUvaUI8d3Kb5jc3HwCqLH8IqALMBAilv0YI9pQD6jzh99kvsxz+sWYYiWo8RJWFApOAMvkLgrgpDiqf3lmG4NA0sFPyg= ARC-Authentication-Results: i=1; sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=Z/l2P8vJ DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 8B2C94BA2E37 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1787864701; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=AMggAUOPvJeLPWeZ4MDnbQvKtS2zeZg6S/R2Ss6ZI90=; b=Z/l2P8vJK5sNA2/diklKUr8DnZ3gM3wYxuU1KKjZQZ2EHvzfLyZSYFLxUpxMrboPbR9Lfw AQ3MNljaip6nl6WNuTlvxzblyzHL677HrPVyGvojbmQ59YLzsyFGG9+jOtLA9U1j4DYaD0 foV6EUZIpdP3pr10CgVaZTAbEmgSyg0= Received: from mail-wm1-f72.google.com (mail-wm1-f72.google.com [209.85.128.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-606-lkxPn0GNONSUTeCRX3Pq5A-1; Thu, 27 Aug 2026 17:04:59 -0400 X-MC-Unique: lkxPn0GNONSUTeCRX3Pq5A-1 X-Mimecast-MFC-AGG-ID: lkxPn0GNONSUTeCRX3Pq5A_1787864698 Received: by mail-wm1-f72.google.com with SMTP id 5b1f17b1804b1-49808ea1b64so1638315e9.1 for ; Thu, 27 Aug 2026 14:04:59 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787864698; x=1788469498; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=AMggAUOPvJeLPWeZ4MDnbQvKtS2zeZg6S/R2Ss6ZI90=; b=mPHHfn6q2k5M2adbSiyWDV8vSHV9rXwsFfy3RfoHIx04C7IQIW4V7W1oQmLDm7mJeD ljjvZgHdyVW/zOaCxDmxrAdZto45ABjFy7xV2hEY8w82IReyKSd720Y9pKp1/fE4tHxx lUPvaUKV/7f/8khTKjxxybEdjGRn6Y/OLt2xBQDkPQM9/HxO3nYEGbT7yOj8Ow82RPjq A45emYTxq1BNHhKC1rC0sGyptYBjEweDnWaq1Kt94QEdP1QDHcBoGay7fB36agcooweZ LpZlyICONikk4t1u2YLdwP89Tzg0xY1txqyLaDmWurHns2pZ7Uywyd3FInBYJDs4tBKd Bldw== X-Gm-Message-State: AFuF++krqK8iHSt3RTyi42SGEIBfxYuJFj8+By8Rcj4x9UJBbAmnt2n3 JSN6PbBzaaBFEFVTcscs+VWoKLBUGEeCoQT5vb9QW41Pd1W990TlrU7pkLOHb+75UT59tIVN7YD XDKnpKkJ5ZzG4A7nOxlEd7T0T6Gei4WLk6ZQmvOYAjVAdEAgXXbrnmOChdi8NLVqLQhJk1GLmmy Gwf5EmOStzXX8LFr1pq+HWfa6ithm6ofHmaKolV3P0glq6b1c= X-Gm-Gg: AR+sD116IWXLcj2EBO7pQ8MBpfGRdTDwaIL6dfWZBM3ntIDfG2u2pBa5s81JNUVvHTV AU68SOUTRXeEtB8d3J6TEY1MRFDvB2TGQ/9d46BXoliHUrqa3/Zy8LYM9XNljEluk4AITU865ox yxc8yXPizhpd5AvC9tl/kY6yCNPpDqv7vljm6K8CYU/qdc9SZddZn2Xd0V+THk6mw9s8lUmWXrB 7Yln832YtqxnZeklkih2mouzYIqz3BMQcnWZzwPeWAzXhkJQ/c5qr8/YgLuyJIPKgBW7+lfdVVU OIpHvPSOqgw43eXYXnFKuJqOk5VZUdS6XelZaFhviFFju5+vgRd8SsrNZQh/4uorEe6F3R/Lyns qBVtb5xnCPIynBAXClkzrjZHLeYM= X-Received: by 2002:a05:600c:474f:b0:49b:e22:4ee4 with SMTP id 5b1f17b1804b1-49b91a58979mr23562795e9.4.1787864697917; Thu, 27 Aug 2026 14:04:57 -0700 (PDT) X-Received: by 2002:a05:600c:474f:b0:49b:e22:4ee4 with SMTP id 5b1f17b1804b1-49b91a58979mr23562245e9.4.1787864697333; Thu, 27 Aug 2026 14:04:57 -0700 (PDT) Received: from localhost (128.223.159.143.dyn.plus.net. [143.159.223.128]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-49b91c9a550sm13135435e9.1.2026.08.27.14.04.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 27 Aug 2026 14:04:57 -0700 (PDT) From: Andrew Burgess To: gdb-patches@sourceware.org Cc: Tom de Vries , Andrew Burgess Subject: [PATCH] gdb: fixes for DW_OP_entry_value when inferior is at entry point Date: Thu, 27 Aug 2026 22:04:55 +0100 Message-Id: X-Mailer: git-send-email 2.25.4 MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: 35uqPiCZhGe9l_Ya05c6ce-hrfxGC4txQKxGh2MbMik_1787864698 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit content-type: text/plain; charset="US-ASCII"; x-default=true X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces~public-inbox=simark.ca@sourceware.org This fixes some issues with DW_OP_entry_value which are discussed in PR gdb/34571. The bug identifies a case where a variable has a DW_AT_location value of (on s390): DW_OP_entry_value: (DW_OP_reg2 (r2)); DW_OP_stack_value But GDB is not able to correctly figure out the variable's value. To understand the fix for this bug we need to first revisit the earlier commit that introduced the bug: commit 1bafda2c4595f0f936a5845caf9667b70b198091 Date: Wed Apr 9 12:02:18 2025 +0200 [gdb/symtab] Handle DW_OP_entry_value at function entry I believe there is a misunderstanding in this commit about how different DWARF attributes are handled, and GDB was updated inline with this misunderstanding. The commit message for 1bafda2c4595f0f9 includes this example DWARF: DW_AT_upper_bound : 13 byte block: a3 1 5a 23 1 8 20 24 8 20 26 31 1c (DW_OP_entry_value: (DW_OP_reg10 (a0)); DW_OP_plus_uconst: 1; DW_OP_const1u: 32; DW_OP_shl; DW_OP_const1u: 32; DW_OP_shra; DW_OP_lit1; DW_OP_minus) We need to notice two things here: 1. This does indeed use DW_OP_entry_value, and 2. It does not end with DW_OP_stack_value, the final value calculated by this expression is the value of the DW_AT_upper_bound attribute. The test then adds a test that uses the DWARF assembler to assemble this: DW_TAG_variable { { DW_AT_name argc } { DW_AT_type :$integer } { DW_AT_location { DW_OP_entry_value { DW_OP_regx $::dwarf_regnum } } SPECIAL_expr } } On my x86-64 machine this results in the following DWARF: <2><4d>: Abbrev Number: 4 (DW_TAG_variable) <4e> DW_AT_name : argc <53> DW_AT_type : <0x2c> <57> DW_AT_location : 4 byte block: a3 2 90 5 (DW_OP_entry_value: (DW_OP_regx: 5 (rdi))) Notice here that: 1. This also uses DW_OP_entry_value, and 2. As with the DW_AT_upper_bound case, this does not end with DW_OP_stack_value. However, I believe this is a misunderstanding of the DWARF. DW_AT_upper_bound and DW_AT_location handle their DWARF expressions in two different ways. Here's part of what DWARF-5 says about DW_OP_entry_value: The DW_OP_entry_value operation pushes the value that the described location held upon entering the current subprogram. So when the DW_AT_location expression is evaluated the DWARF stack will contain the entry value for register %rdi. However, that is the value of the register, it is not a register name, given the above DWARF, GDB should be treating the value on the stack (the contents of %rdi) as the address at which the variable can be found, which is not what the test expects. But, we can clearly see why the test was written this way. It was trying to represent the original problematic DWARF, which used DW_OP_entry_value without a trailing DW_OP_stack_value. However, the original case was for DW_AT_upper_bound, which I think is covered by 2.19 "Static and Dynamic Values of Attributes" in the DWARF-5 spec. In this section we see: "Some attributes that apply to types specify a property (such as the lower bound of an array) that is an integer value, where the value may be known during compilation or may be computed dynamically during execution." and later in the same section: "For an exprloc, the value is interpreted as a DWARF expression; evaluation of the expression yields the value of the attribute." So I believe this is telling us that the DWARF expression for DW_AT_upper_bound should be handled differently than the expression for DW_AT_location. For DW_AT_location the result on the DWARF stack is going to be one of the location descriptions listed in section 2.6.1.1 "Simple Location Descriptions", but for DW_AT_upper_bound the result will be the value itself. If we go back to the original PR gdb/34571 bug we see that it's DW_AT_location expression was: DW_OP_entry_value: (DW_OP_reg2 (r2)); DW_OP_stack_value with a trailing DW_OP_stack_value. The test case didn't have that trailing DW_OP_stack_value. The problem is that currently, when GDB sees: DW_OP_entry_value: (DW_OP_reg2 (r2)); It pushes the register name $r2 to the DWARF stack, and then marks the stack as being a register location description. This works for the test where there is no DW_OP_stack_value. But when we add the trailing DW_OP_stack_value GDB marks the stack as being an "Implicit Location Description" (meaning the value on the stack is the result). This causes us to then interpret the register number as the result, rather than fetching the register value. I worried that I was going to somehow have to try and support both cases, but the more I looked into it, the more I convinced myself that commit 1bafda2c4595f0f9 wasn't fully correct, and that we should just update the test that was added in that commit. So that's what this commit does. When we see DW_OP_entry_value for a plain register name, and we're at the very start of the function, instead of pushing the register name to the stack and marking the stack as being a "Register Location Description", we instead read the register value, push that to the stack, and leave the m_location variable unchanged. Then in the test I've added a DW_OP_stack_value to the DW_AT_location attribute. I've also added some additional variables with more complex DW_AT_location expressions. These all make use of DW_OP_entry_value, but manipulate the value in some way to compute the final result. These reflect examples that I saw when compiling the example code from PR gdb/34571 at different optimisation levels. One thing that did puzzle me is that commit 1bafda2c4595f0f9 talks about the problem having been discovered when looking at the text gdb.base/vla-optimized-out.exp on risc-v, and the claim is that the issues in that test were fixed by 1bafda2c4595f0f9. I didn't understand how that could be possible given the bug I claim exists. But if we look at the original DW_AT_upper_bound DWARF we see what happened: DW_OP_entry_value: (DW_OP_reg10 (a0)); <- Reg value on stack. DW_OP_plus_uconst: 1; <- Add 1. DW_OP_const1u: 32; \ DW_OP_shl; | Sign extend via DW_OP_const1u: 32; | left/right shift. DW_OP_shra; / DW_OP_lit1; \ Subtract 1. DW_OP_minus / I don't understand why there's the +1/-1 logic in there, I wonder if this is a compiler artefact, but clearly this is supposed to take the value from register $a10 and sign extend it from 32 to 64 bits. However, what it actually does is take the register NUMBER, and sign extend that. Luckily though, for small register numbers, the whole expression leaves the register number unchanged on the DWARF expression stack. Because DW_OP_entry_value also incorrectly marks the DWARF expression stack as being a "Register Location Description", then after all this is complete GDB reads the value from the register. So long at the value it reads didn't actually need sign extending then we're fine. In this test the value in the register is '5', which doesn't require the sign extension, so despite the bug in GDB, the test does the right thing. That at least explains why the original commit appeared to fix the problem with gdb.base/vla-optimized-out.exp. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=34571 --- gdb/dwarf2/expr.c | 11 +++-- gdb/testsuite/gdb.dwarf2/dw2-entry-value-2.c | 1 + .../gdb.dwarf2/dw2-entry-value-2.exp | 46 +++++++++++++++++++ 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/gdb/dwarf2/expr.c b/gdb/dwarf2/expr.c index 3a6b8f58199..934fda67ca6 100644 --- a/gdb/dwarf2/expr.c +++ b/gdb/dwarf2/expr.c @@ -2365,10 +2365,15 @@ dwarf_expr_context::execute_stack_op (gdb::array_view expr) if (trivial_entry_value (this->m_frame)) { /* We can assume that DW_OP_entry_value (expr) == expr. - Handle as DW_OP_regx. */ + Handle DW_OP_regx, place register value on the + stack. */ + gdbarch *f_arch = get_frame_arch (this->m_frame); + int dwarf_regnum = kind_u.dwarf_reg; + int gdb_regnum + = dwarf_reg_to_regnum_or_error (f_arch, dwarf_regnum); result_val - = value_from_ulongest (address_type, kind_u.dwarf_reg); - this->m_location = DWARF_VALUE_REGISTER; + = value_from_register (address_type, gdb_regnum, + this->m_frame); break; } diff --git a/gdb/testsuite/gdb.dwarf2/dw2-entry-value-2.c b/gdb/testsuite/gdb.dwarf2/dw2-entry-value-2.c index 45fa86bdf2f..af3199abcee 100644 --- a/gdb/testsuite/gdb.dwarf2/dw2-entry-value-2.c +++ b/gdb/testsuite/gdb.dwarf2/dw2-entry-value-2.c @@ -16,6 +16,7 @@ along with this program. If not, see . */ int var = 2; +unsigned long long fake_data[3] = { 1, 2, 3 }; static void bar (int *p) diff --git a/gdb/testsuite/gdb.dwarf2/dw2-entry-value-2.exp b/gdb/testsuite/gdb.dwarf2/dw2-entry-value-2.exp index 3b48846fb71..6d441dc53f8 100644 --- a/gdb/testsuite/gdb.dwarf2/dw2-entry-value-2.exp +++ b/gdb/testsuite/gdb.dwarf2/dw2-entry-value-2.exp @@ -67,6 +67,33 @@ Dwarf::assemble $asm_file { DW_OP_entry_value { DW_OP_regx $::dwarf_regnum } + DW_OP_stack_value + } SPECIAL_expr + } + + DW_TAG_variable { + DW_AT_name argc2 + DW_AT_type :$integer + DW_AT_location { + DW_OP_entry_value { + DW_OP_regx $::dwarf_regnum + } + DW_OP_plus_uconst 3 + DW_OP_stack_value + } SPECIAL_expr + } + + DW_TAG_variable { + DW_AT_name argc3 + DW_AT_type :$integer + DW_AT_location { + DW_OP_addr [gdb_target_symbol fake_data] + DW_OP_entry_value { + DW_OP_regx $::dwarf_regnum + } + DW_OP_const1u 3 + DW_OP_shl + DW_OP_plus } SPECIAL_expr } } @@ -87,6 +114,19 @@ Dwarf::assemble $asm_file { DW_OP_stack_value } SPECIAL_expr } + + DW_TAG_variable { + DW_AT_name foo2 + DW_AT_type :$integer + DW_AT_location { + DW_OP_entry_value { + DW_OP_bregx $::dwarf_regnum 0 + DW_OP_deref_size 4 + } + DW_OP_plus_uconst 1 + DW_OP_stack_value + } SPECIAL_expr + } } } } @@ -103,12 +143,16 @@ if { ![runto *main] } { with_test_prefix "at main+0" { gdb_test "p argc" " = 1" + gdb_test "p argc2" " = 4" + gdb_test "p argc3" " = 2" gdb_test "stepi" } with_test_prefix "at main+1" { gdb_test "p argc" " = " + gdb_test "p argc2" " = " + gdb_test "p argc3" " = " } gdb_breakpoint "*bar" @@ -116,10 +160,12 @@ gdb_continue_to_breakpoint "bar" with_test_prefix "at bar+0" { gdb_test "p foo" " = 2" + gdb_test "p foo2" " = 3" gdb_test "stepi" } with_test_prefix "at bar+1" { gdb_test "p foo" " = " + gdb_test "p foo2" " = " } base-commit: 6e3ecea0e3ca191e81e82ee0194c49eea1ffb101 -- 2.25.4