From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id CXonKRoLu2nyRy8AWB0awg (envelope-from ) for ; Wed, 18 Mar 2026 16:29:14 -0400 Authentication-Results: simark.ca; dkim=pass (2048-bit key; unprotected) header.d=polymtl.ca header.i=@polymtl.ca header.a=rsa-sha256 header.s=oct2025 header.b=mg+hkfsd; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id A45061E0BC; Wed, 18 Mar 2026 16:29:14 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-2.4 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED,RCVD_IN_VALIDITY_CERTIFIED_BLOCKED, RCVD_IN_VALIDITY_RPBL_BLOCKED,RCVD_IN_VALIDITY_SAFE_BLOCKED autolearn=ham autolearn_force=no version=4.0.1 Received: from vm01.sourceware.org (vm01.sourceware.org [38.145.34.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 EC8481E08C for ; Wed, 18 Mar 2026 16:29:13 -0400 (EDT) Received: from vm01.sourceware.org (localhost [127.0.0.1]) by sourceware.org (Postfix) with ESMTP id 743AC4BCA43D for ; Wed, 18 Mar 2026 20:29:13 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 743AC4BCA43D Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=polymtl.ca header.i=@polymtl.ca header.a=rsa-sha256 header.s=oct2025 header.b=mg+hkfsd Received: from smtp.polymtl.ca (smtp.polymtl.ca [132.207.4.11]) by sourceware.org (Postfix) with ESMTPS id 8AEAA4BC7EE4 for ; Wed, 18 Mar 2026 20:28:10 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 8AEAA4BC7EE4 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=polymtl.ca Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=polymtl.ca ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 8AEAA4BC7EE4 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=132.207.4.11 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1773865696; cv=none; b=dmPAeInYbxDMbAvhnio5lXZYQTdtUAnYHwkRCuVh3wg6FvhwBavcQDp1mEZgwjSOofwom9BOR6xjfIQHHBU6BeCcmZbZAZDokaQhOWg9R0BH7jfS5RvORrfvgyOaqs1QGgSwPnueLbDNsm9s/78KaonMc+//HvCTVEM6837hsO8= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1773865696; c=relaxed/simple; bh=0C6tIXs34KfHvU/DCrF3qPN7hkvS7vVEY8H98Qf4byU=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=CfKbq/zJqfVl3OT4+UYzDYgoJ4GPqMiy5NmxACvNEmX/0olJ+Wm4WS2+j9lhmJluhjN70r9CQXymJ3jprGVrBf8XDk/p2TmPU9a+T6ylv9j1BbQLSvHjWwNhWmjnFeqDfT3jLPuRB05TsRxfWqEV6tk4Q7L8SNuPE5RnW1il7cQ= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 8AEAA4BC7EE4 Received: from simark.ca (simark.ca [158.69.221.121]) (authenticated bits=0) by smtp.polymtl.ca (8.14.7/8.14.7) with ESMTP id 62IKS4fJ134545 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 18 Mar 2026 16:28:09 -0400 DKIM-Filter: OpenDKIM Filter v2.11.0 smtp.polymtl.ca 62IKS4fJ134545 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=polymtl.ca; s=oct2025; t=1773865689; bh=0+XPdiCnFVBOQF4fRUoUdhRGHzF0JF7KGG01SJxbcVA=; h=From:To:Cc:Subject:Date:In-Reply-To:From; b=mg+hkfsd6uEoepUt8bCl6O6rTIbQGAznd4rxdQqPtyxdSzqS5TWXq9+uOwB2TsnA6 ANxCVRw2EVcsTwjbgIBuab0htqv7XESWwWRbp+w8cAge49myyQ3HAHJxplAer9+gZ6 PFX4aR51VX7FdVtjZerCRuRYE2TlhoKZM7kPkksaKdvyLkcJATwsAT9TH/PwFa7LHT 8YsiXhoSBqALQvTqHlfu1/mD9U+GIJr6JjgWR49gPhAVV3CoekQgLVHEyLtWYYit6W fwOtArQvyEtcJvb3EYW4SEcpcjvRBh9iWASCC+lcfHYVFdTXZ2HuMZYz+1Op/EaSgz NLdY1zDKlKP4g== Received: by simark.ca (Postfix) id AA02F1E0AD; Wed, 18 Mar 2026 16:28:03 -0400 (EDT) From: simon.marchi@polymtl.ca To: gdb-patches@sourceware.org Cc: Simon Marchi Subject: [PATCH v2 2/2] gdb/dwarf: fix internal error when FDEs do not describe the CFA Date: Wed, 18 Mar 2026 16:27:23 -0400 Message-ID: <20260318202801.2030268-2-simon.marchi@polymtl.ca> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260318202801.2030268-1-simon.marchi@polymtl.ca> References: <20260316172239.349677-2-simon.marchi@efficios.com> <20260318202801.2030268-1-simon.marchi@polymtl.ca> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Poly-FromMTA: (simark.ca [158.69.221.121]) at Wed, 18 Mar 2026 20:28:04 +0000 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 From: Simon Marchi New in v2: change how undefined_retaddr is set, to avoid regressions on AArch64 (among possibly others). This patch fixes an internal error problem that happens when a frame description entry does not define the Canonical Frame Address (CFA). This problem was initially reported downstream as a ROCgdb issue (see Bug trailer below), but I wrote a reproducer that uses the .debug_frame functionality added to the DWARF assembler in the previous patch. The error is: /home/smarchi/src/binutils-gdb/gdb/dwarf2/frame.c:1046: internal-error: Unknown CFA rule. The original bug was encountered while debugging a GPU kernel written with Triton [1]. From what I understand, the generated kernel does not really use a stack, so the .debug_frame contents generated is quite bare: $ readelf --debug-dump=frames k Contents of the .debug_frame section: 00000000 000000000000000c ffffffff CIE Version: 4 Augmentation: "" Pointer Size: 8 Segment Size: 0 Code alignment factor: 4 Data alignment factor: 4 Return address column: 16 DW_CFA_nop 00000010 0000000000000014 00000000 FDE cie=00000000 pc=0000000000001600..0000000000001704 For those who don't speak fluent .debug_frame, what we see here is a Frame Description Entry (FDE) that doesn't define any register rule, referring to a Common Information Entry (CIE) that also doesn't define any initial register rule. This is equivalent to having no unwind information at all. One question is: why generate these at all? I suppose that this is an edge case, that the compiler is written in a way that that presumes there will always be some unwind info. That there is no "if unwind info is empty, skip emitting the FDE" check. Anyway, the important thing for us is that these can be found in the wild, so GDB shouldn't crash. The fix consists of handling CFA_UNSET in the dwarf2_frame_cache switch. CFA_UNSET is the initial state when we start interpreting a CFA program, meaning that we don't know yet how the CFA is defined. In our case, it remains unset after interpreting the CFA program. With just the fix above, we get: (gdb) bt #0 0x000055555555511d in main () Backtrace stopped: previous frame identical to this frame (corrupt stack?) Which is good (better than crashing), but it would be good to avoid the error. To do so, set the undefined_retaddr flag to true. This has two effects: - dwarf2_frame_this_id won't try to build a frame id from the CFA (which is good, we don't have a CFA) - dwarf2_frame_unwind_stop_reason will return UNWIND_OUTERMOST, which is the most accurate thing we can return here (there is no outer frame) The result is the expected: (gdb) bt #0 0x000055555555511d in main () My initial implementation changed this condition: if (fs.retaddr_column < fs.regs.reg.size () && fs.regs.reg[fs.retaddr_column].how == DWARF2_FRAME_REG_UNDEFINED) cache->undefined_retaddr = true; such that we would enter it if fs.retaddr_column <+ fs.regs.reg.size () However, this broke the unwinding on AArch64 (and possibly others). Add a test case written using the DWARF assembler that reproduces the issue. [1] https://triton-lang.org/ Change-Id: I67c717ff03a41c0630a73ce9549d88ff363e8cea Bug: https://github.com/ROCm/ROCgdb/issues/47 --- gdb/dwarf2/frame.c | 4 ++ .../gdb.dwarf2/debug-frame-no-cfa.exp | 54 +++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 gdb/testsuite/gdb.dwarf2/debug-frame-no-cfa.exp diff --git a/gdb/dwarf2/frame.c b/gdb/dwarf2/frame.c index 152bebef0e30..2301d9146373 100644 --- a/gdb/dwarf2/frame.c +++ b/gdb/dwarf2/frame.c @@ -962,6 +962,10 @@ dwarf2_frame_cache (const frame_info_ptr &this_frame, void **this_cache) /* Calculate the CFA. */ switch (fs.regs.cfa_how) { + case CFA_UNSET: + cache->undefined_retaddr = true; + return cache; + case CFA_REG_OFFSET: cache->cfa = read_addr_from_reg (this_frame, fs.regs.cfa_reg); if (fs.armcc_cfa_offsets_reversed) diff --git a/gdb/testsuite/gdb.dwarf2/debug-frame-no-cfa.exp b/gdb/testsuite/gdb.dwarf2/debug-frame-no-cfa.exp new file mode 100644 index 000000000000..8442b5c3ddbb --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/debug-frame-no-cfa.exp @@ -0,0 +1,54 @@ +# 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 . + +# Test GDB against an FDE in the .debug_frame section that doesn't set a rule +# for the CFA. + +load_lib dwarf.exp + +require dwarf2_support is_x86_64_m64_target + +standard_testfile main.c -dw.S + +set asm_file [standard_output_file $srcfile2] +Dwarf::assemble $asm_file { + get_func_info main + + frame { + declare_labels cie_label + + cie_label: CIE { + return_address_register 16 + } {} + + FDE $cie_label $main_start $main_len {} { + } + } +} + +if { [prepare_for_testing "failed to prepare" ${testfile} \ + [list $srcfile $asm_file] {nodebug}] } { + return +} + +if { ![runto_main] } { + return +} + +# This would cause an internal error in dwarf2_frame_cache. +# +# Make sure to match a single line, so that the test fails if an error +# about stack unwind is printed after frame 0. +gdb_test "backtrace" "^#0 \[^\r\n\]* main \[^\r\n\]*" -- 2.53.0