From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id GayVKrmRb2l9rwwAWB0awg (envelope-from ) for ; Tue, 20 Jan 2026 09:31:21 -0500 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=G5vqeAgM; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id A00D81E08D; Tue, 20 Jan 2026 09:31:21 -0500 (EST) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-3.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,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 AE33E1E08D for ; Tue, 20 Jan 2026 09:31:20 -0500 (EST) Received: from vm01.sourceware.org (localhost [127.0.0.1]) by sourceware.org (Postfix) with ESMTP id 263684BA2E2E for ; Tue, 20 Jan 2026 14:31:20 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 263684BA2E2E 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=G5vqeAgM Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTP id 2CF684BA9003 for ; Tue, 20 Jan 2026 14:30:53 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 2CF684BA9003 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 2CF684BA9003 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1768919453; cv=none; b=pV3GyWKV7s5yreOcMWCIQGqTj5NuZL4bP11IS5XO6nqO4Kv8t9qE0ekQZXFZX7aVs8STwqvONnKKUFU9r1hi9dOktRre2q/6iqYrW7GylA2rz74DXXOQH+Qc2nulXQGGvqzLNK1k9AbSRJvCiQADoSsyPDzqQVI59lGt33CgZwg= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1768919453; c=relaxed/simple; bh=9cVj//l/AUmG//Pp4zZKsKf2jgL6pn3SThbnS7o2G1k=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=HbhQXcfl9WFP/FBD+UX3xx7r9atya89DDL33W2ZZ7a9E60+KhVBBlTn2BxfcSGjpUzn9+rGIYPUIVAfU01Ilxd0MvHUJY2bL2Ex4Mi2P1ZKzqzHTrkufcDAPbvvX9zg5e7Nd0S69BSuiiBcecAACYQBFhlwS5Bdmxg40Ga4Skxo= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 2CF684BA9003 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1768919452; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=ugU7luDuOQYqe+0D+q7VIMTnpTzHyBmf86r9x4IJ/cA=; b=G5vqeAgMuNJo8Ji2Lph+jxzZYh0nTA+JSElNf9/PKPD89+Lit84fEoLAoRA5COQmkKTo1G b64qzORrrBRO6oRKVD9MHsJ62IIicj3FcTUA994LDJzFHcJsVliFQvcUYQHinXeCI5KALV RgLVH0pB/Tk7S4pDwDALToDS4vOf/lg= Received: from mail-wm1-f71.google.com (mail-wm1-f71.google.com [209.85.128.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-127-qdMuZbF8M76eW3Mtk4fajA-1; Tue, 20 Jan 2026 09:30:51 -0500 X-MC-Unique: qdMuZbF8M76eW3Mtk4fajA-1 X-Mimecast-MFC-AGG-ID: qdMuZbF8M76eW3Mtk4fajA_1768919450 Received: by mail-wm1-f71.google.com with SMTP id 5b1f17b1804b1-47fff4fd76dso37449305e9.3 for ; Tue, 20 Jan 2026 06:30:51 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768919450; x=1769524250; h=mime-version:message-id:date:references:in-reply-to:subject:to:from :x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=ugU7luDuOQYqe+0D+q7VIMTnpTzHyBmf86r9x4IJ/cA=; b=wE8Pu3q5dpIvUxNHDAGknDgQBFnfJcAuykFg4xccm3okGDs3c1ApAUhFJuMnDZTnNn RQKZHTWSsJ2TmTMQbd4p7AHY3+SqR92mX5dX1XRqStPm7vuY7FEdjrlhVg9NKxECDMb7 m0nKEN3c1dq104FwFIJU1RU/5OmlhheVV7WZay0UZx45wsSsVNkH5ywdIidu7zQvVG3E kyjkUQ28mvp0IShBg15GD4vkmO41SlSPzETheG6u+7xlaaOOnVSnolwWVXYyDjYngwP7 009ZVWUI/bKPPuitpEE/tXAhiRKuaRwx6MMhXWNabbbUuboDAEpWVMFvtP91qQx+MykF c0DQ== X-Forwarded-Encrypted: i=1; AJvYcCVDfZpvNJchK+t1gajDrD2c8VgjkyKdkxgtPj4bszcgXKx13PHnfwg4Al8wbDvwIpunmxM4kDEeCMosow==@sourceware.org X-Gm-Message-State: AOJu0YwYrzO38y7KoRqBWoXA5YSTfxNVlR0pegCqmjnhWrSwc4HyZ/8n cYduXGyssJXwnI++seXj3UqyIgEwDHsMNfGph/hnY3Qo0k8g9LXPb/vJvrKszgZYzHAuI7CkTFr 6lO/frwL6zi+8YUB1vTbHGm1MRnTG4oRGeqtSp2lX2As7ku2QZuKwJtKkzwy97+0= X-Gm-Gg: AY/fxX7SDfC+R+O3fXBXJCt4WuxSVFQ4uWRe6C53Pf7dn5vVyYQuQAlKZAE0YO8t5Wo KvLpuapuA9P8TNmM/j7mY5UlAJxs/rtFC/ehJJ7DBvmXcKPMNaxKryyMVo8gUq5hWFQF1I3nE6J pu/hRY5/DH4v70o+VD2gzDO1qIGeVduEn7q1KbnekQN2TeWngFIrpkN0108uuR3rw2G4Bhyp1Rh UhQAcrGTyzLEYHe8IZvkkvlF+1O4nMy0mTLtooOLxZsUuNn0T+3+Itq9uucFsILvz4o0MTbsXTo yP6n5nJnHaK1UcHCH0vgCQgMV2gVLfXgZX7l5xtYiyB6/KAF6YiZ5ecP69V3fiBvWww6iDxb/Lq ux5tBKjPgoKyj/LqObgfVzuj20523 X-Received: by 2002:a05:600c:8b56:b0:477:79f8:daa8 with SMTP id 5b1f17b1804b1-4801e34307emr214687565e9.17.1768919450015; Tue, 20 Jan 2026 06:30:50 -0800 (PST) X-Received: by 2002:a05:600c:8b56:b0:477:79f8:daa8 with SMTP id 5b1f17b1804b1-4801e34307emr214687035e9.17.1768919449438; Tue, 20 Jan 2026 06:30:49 -0800 (PST) Received: from localhost (13.81.93.209.dyn.plus.net. [209.93.81.13]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4801e9ee5c3sm112257285e9.2.2026.01.20.06.30.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 Jan 2026 06:30:49 -0800 (PST) From: Andrew Burgess To: Tom de Vries , gdb-patches@sourceware.org Subject: Re: [PATCH] [gdb/testsuite] Fix gdb.base/inline-frame-cycle-unwind.exp for s390x (alternative) In-Reply-To: <20251211133946.962934-1-tdevries@suse.de> References: <20251211133946.962934-1-tdevries@suse.de> Date: Tue, 20 Jan 2026 14:30:47 +0000 Message-ID: <87a4y8qru0.fsf@redhat.com> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: pbJDWEwBFns5-1FAOsfnD8AxNE0lXplwHRs94k-d5Ug_1768919450 X-Mimecast-Originator: redhat.com Content-Type: text/plain 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 Tom de Vries writes: > With test-case gdb.base/inline-frame-cycle-unwind.exp on s390x-linux, I run > into: > ... > (gdb) bt^M > #0 inline_func () at inline-frame-cycle-unwind.c:49^M > #1 normal_func () at inline-frame-cycle-unwind.c:32^M > #2 0x000000000100065c in inline_func () at inline-frame-cycle-unwind.c:45^M > #3 normal_func () at inline-frame-cycle-unwind.c:32^M > Backtrace stopped: previous frame identical to this frame (corrupt stack?)^M > (gdb) FAIL: $exp: bt: cycle at level 5: backtrace when the unwind is broken \ > at frame 5 > ... > > In contrast, on x86_64-linux, I get: > ... > (gdb) bt^M > #0 inline_func () at inline-frame-cycle-unwind.c:49^M > #1 normal_func () at inline-frame-cycle-unwind.c:32^M > #2 0x0000000000401157 in inline_func () at inline-frame-cycle-unwind.c:45^M > #3 normal_func () at inline-frame-cycle-unwind.c:32^M > #4 0x0000000000401157 in inline_func () at inline-frame-cycle-unwind.c:45^M > #5 normal_func () at inline-frame-cycle-unwind.c:32^M > Backtrace stopped: previous frame identical to this frame (corrupt stack?)^M > (gdb) PASS: $exp: bt: cycle at level 5: backtrace when the unwind is broken \ > at frame 5 > ... > > AFAIU, the mechanism of the test is as follows: the custom unwinder produces the > frame-id for frame #5 at frame #4. Consequently, when arriving at frame #5, a > cycle is detected. I don't believe this is how it works. See below for what I think happens. > > [ It took me a while to understand this because of the following off-by-one > confusion: for frame #0, we get pending_frame.level() == 1. So when > stop_at_level == 5, the custom unwinder calculates a frame-id for frame #4, > not frame #5. But the frame-id it calculates is the one for frame #5, so > unwinding will stop at frame #5 because the frame-ids for frame #4 and > frame #5 are identical. ] I went back and looked at the unpatched test again, and I don't believe this "off-by-one" issue is a thing, at least, I don't see one based on your description. It does appear that for frame #0 we get pending_frame.level() == 1, but this isn't what's really happening. Frame #0 is inline, so the Python frame unwinder is never run for this frame. The first frame for which the Python frame unwinder is run is frame #1, hence pending_frame.level() == 1. The frame-id calculated within TestUnwinder.__call__ is the frame-id for the previous (outer, older) frame. So, when pending_frame.level() == 5 we are calculating the frame-id for frame #6. As frame #6 then appears to be identical to frame #5, a cycle is detected and the backtrace ends. > This relies on the test-case to calculate the offending frame-id, and the > problem on s390x is that that calculation is incorrect. Agreed. > > Fix this by using "maint print frame-id" to get all frame-ids, and using those > instead. I suspect this is the better approach. I'm not sure 'maint print frame-id' existed when I wrote this test (but I could be wrong). Still, it would be nice if we could understand exactly why this is going wrong in this case. My main question here is that we're only calculating a "fake" frame-id for frame #6, so this should be the first frame that GDB doesn't display. That GDB is cutting off after #3 would seem to indicate that #4, or maybe #5 (as the non-inline frame) is a duplicate of an earlier frame, but I don't understand how that can be the case. > > Tested on x86_64-linux and s390x-linux. > --- > .../gdb.base/inline-frame-cycle-unwind.exp | 13 +++++++++++++ > gdb/testsuite/gdb.base/inline-frame-cycle-unwind.py | 8 +++++--- > 2 files changed, 18 insertions(+), 3 deletions(-) > > diff --git a/gdb/testsuite/gdb.base/inline-frame-cycle-unwind.exp b/gdb/testsuite/gdb.base/inline-frame-cycle-unwind.exp > index 7fc47af624f..5c6504323ee 100644 > --- a/gdb/testsuite/gdb.base/inline-frame-cycle-unwind.exp > +++ b/gdb/testsuite/gdb.base/inline-frame-cycle-unwind.exp > @@ -72,6 +72,19 @@ gdb_continue_to_breakpoint "stop at test breakpoint" > gdb_test_no_output "source ${pyfile}"\ > "import python scripts" > > +foreach_with_prefix n { 0 1 2 3 4 5 6 } { > + set sp 0x0 > + set pc 0x0 > + gdb_test_multiple "maint print frame-id $n" "" { > + -re -wrap "frame-id for frame #$n: {stack=($hex),code=($hex),.*}" { > + set sp $expect_out(1,string) > + set pc $expect_out(2,string) > + gdb_test_no_output "python frame_id_sp.append($sp)" > + gdb_test_no_output "python frame_id_pc.append($pc)" > + } > + } > +} > + > # Test with and without filters. > foreach bt_cmd { "bt" "bt -no-filters" } { > with_test_prefix "$bt_cmd" { > diff --git a/gdb/testsuite/gdb.base/inline-frame-cycle-unwind.py b/gdb/testsuite/gdb.base/inline-frame-cycle-unwind.py > index 55dea989512..25a67b1a7c9 100644 > --- a/gdb/testsuite/gdb.base/inline-frame-cycle-unwind.py > +++ b/gdb/testsuite/gdb.base/inline-frame-cycle-unwind.py > @@ -26,6 +26,9 @@ stop_at_level = None > # function called recursively. > stack_adjust = None > > +frame_id_sp = [] > +frame_id_pc = [] > + > > class FrameId(object): > def __init__(self, sp, pc): > @@ -55,9 +58,8 @@ class TestUnwinder(Unwinder): > if stop_at_level not in [1, 3, 5]: > raise gdb.GdbError("invalid stop_at_level") > > - sp_desc = pending_frame.architecture().registers().find("sp") > - sp = pending_frame.read_register(sp_desc) + stack_adjust > - pc = (gdb.lookup_symbol("normal_func"))[0].value().address > + sp = frame_id_sp[stop_at_level] > + pc = frame_id_pc[stop_at_level] > unwinder = pending_frame.create_unwind_info(FrameId(sp, pc)) I wonder if here you could: print(f"DEBUG: frame level: {pending_frame.level()}") sp_desc = pending_frame.architecture().registers().find("sp") prev_sp = int(pending_frame.read_register(sp_desc)) print(f"DEBUG: previous-sp: {prev_sp:x}, adjustment: {int(stack_adjust):x}") adjusted_sp = int(prev_sp + stack_adjust) print(f"DEBUG: adjusted-sp: {adjusted_sp:x}") print(f"DEBUG: new-sp: {frame_id_sp[stop_at_level]:x}") addr = int((gdb.lookup_symbol("normal_func"))[0].value().address) print(f"DEBUG: previous-pc: {addr:x}") print(f"DEBUG: new-pc: {frame_id_pc[stop_at_level]:x}") then we'd be able to see which part of the frame-id was being generated incorrectly. Thanks, Andrew > > for reg in pending_frame.architecture().registers("general"): > > base-commit: 2271dee682787051c0628c869d7cdb220bdd0e67 > -- > 2.51.0