Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Andrew Burgess <aburgess@redhat.com>
To: Tom de Vries <tdevries@suse.de>, gdb-patches@sourceware.org
Subject: Re: [PATCH v2] [gdb/testsuite] Fix gdb.base/inline-frame-cycle-unwind.exp for s390x (alternative)
Date: Wed, 21 Jan 2026 17:10:54 +0000	[thread overview]
Message-ID: <87y0lqhowx.fsf@redhat.com> (raw)
In-Reply-To: <20260121122543.4129049-1-tdevries@suse.de>

Tom de Vries <tdevries@suse.de> writes:

> From: Andrew Burgess <aburgess@redhat.com>
>
> With test-case gdb.base/inline-frame-cycle-unwind.exp on s390x-linux, I run
> into:
> ...
> (gdb) bt
>  #0  inline_func () at inline-frame-cycle-unwind.c:49
>  #1  normal_func () at inline-frame-cycle-unwind.c:32
>  #2  0x000000000100065c in inline_func () at inline-frame-cycle-unwind.c:45
>  #3  normal_func () at inline-frame-cycle-unwind.c:32
>  Backtrace stopped: previous frame identical to this frame (corrupt stack?)
> (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
>  #0  inline_func () at inline-frame-cycle-unwind.c:49
>  #1  normal_func () at inline-frame-cycle-unwind.c:32
>  #2  0x0000000000401157 in inline_func () at inline-frame-cycle-unwind.c:45
>  #3  normal_func () at inline-frame-cycle-unwind.c:32
>  #4  0x0000000000401157 in inline_func () at inline-frame-cycle-unwind.c:45
>  #5  normal_func () at inline-frame-cycle-unwind.c:32
>  Backtrace stopped: previous frame identical to this frame (corrupt stack?)
> (gdb) PASS: $exp: bt: cycle at level 5: backtrace when the unwind is broken \
>   at frame 5
> ...
>
> Let's first see what happens on x86_64-linux.
>
> The test-case installs a custom unwinder, which gets triggered with
> pending_frame.level() == 5.
>
> The responsibility of the unwinder at that point is to:
> - calculate a frame ID for the pending frame, and
> - provided the register values for the previous frame (with level
>   pending_frame.level() + 1), as saved in the pending frame.
>
> However, the custom unwinder does some else.  While it does calculate the
> frame ID for the pending frame, instead it provides the register values for
> the pending frame, which causes the unwinder to stop.

Sort of.  Passing a value from #n to #(n+1) unmodified isn't itself
wrong, or bad, it's just saying that a register hasn't changed between
frames.

In this case, by passing $sp and $pc up the stack unmodified, frame
#(n+1) is going to appear to be an exact duplicate of frame #n, but the
custom unwinder isn't going to trigger from #(n+1), so the standard
DWARF unwinder will kick in instead.

The DWARF unwinder should then compute the exact same frame-id that our
custom unwinder installed for frame #n, which will trigger the frame
cycle which is at the core of this test.

>
> After adding some debugging prints, we can see that the frame ID calculated by
> the custom unwinder:
> ...
> LEVEL: 5
> FrameID: sp: 7fffffffcd50, pc: 401116
> ...
> matches the frame ID as calculated by GDB:
> ...
> (gdb) maint print frame-id 5
> frame-id for frame #5: {stack=0x7fffffffcd50,code=0x0000000000401116,!special}
> ...
>
> Now back to s390x-linux.
>
> This time, the frame ID calculated by the custom unwinder:
> ...
> LEVEL: 5
> FrameID: sp: 3ffffffe8d0, pc: 1000608
> ...
> does not match the frame ID as calculated by GDB:
> ...
> (gdb) maint print frame-id 5
> frame-id for frame #5: {stack=0x3ffffffe970,code=0x0000000001000608,!special}
> ...
>
> Instead, it matches the frame ID for frame #3:
> ...
> (gdb) maint print frame-id 3
> frame-id for frame #3: {stack=0x3ffffffe8d0,code=0x0000000001000608,!special}
> ...

So the problem for s390 is the difference in relationship between the
Call Frame Address (CFA), as used in the frame-id, and $sp value for a
function.

On x86-64, for this specific test, the difference between $sp and the
CFA for frames 1, 3, and 5 is the same as the difference between $sp
values between these frames.  There's no reason why this has to be the
case, it just is, and the original form of this test depended on this
fact.

Remember, our custom unwinder, when triggered for frame #n, wants to
generate the actual, real, correct, frame-id for frame #n.  But when the
test was written 'maint print frame-id' wasn't a thing, so the hack that
I used to calculate the frame-id noticed that the $sp to CFA for a frame
was the same as $sp to $sp between frames.  So I calculate the
difference between $sp values (called STACK_ADJUST), and then add this
to the $sp value in frame #n to try and recreate the frame-id.

On s390 however, my hack doesn't work.  The CFA for a frame is 2x the
frame size (on this test, on the machine and compiler I tested with).
And so, when we try to create the frame-id for #n in the custom
unwinder, instead of calculating the correct CFA, we calculate a
different frame-id that happens to be the same as an earlier frame, and
that is why the frame is truncated where it is.

>
> Fix this by using "maint print frame-id" to get all frame-ids, and using those
> instead.

I did make an attempt at fixing this, but having read your commit
message, and having written the above reply, I think your approach here
is probably the right one.  It might be worth folding some of the above
text into the commit message though, what do you think?

I'm happy to do this if you'd like me too.

Thanks,
Andrew


  reply	other threads:[~2026-01-21 17:11 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-01-21 12:25 Tom de Vries
2026-01-21 17:10 ` Andrew Burgess [this message]
2026-01-21 17:21   ` Tom de Vries
2026-01-26 13:47     ` Andrew Burgess
2026-01-24 23:52 ` Kevin Buettner
2026-01-28 19:52 ` [PATCHv3] gdb: fix gdb.base/inline-frame-cycle-unwind.exp for s390x Andrew Burgess
2026-01-29  8:11   ` Tom de Vries

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=87y0lqhowx.fsf@redhat.com \
    --to=aburgess@redhat.com \
    --cc=gdb-patches@sourceware.org \
    --cc=tdevries@suse.de \
    /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