aboutsummaryrefslogtreecommitdiff
path: root/gdb/frame.c
diff options
context:
space:
mode:
authorCraig Blackmore <craig.blackmore@embecosm.com>2025-02-13 15:53:34 +0000
committerAndrew Burgess <aburgess@redhat.com>2025-03-27 18:40:36 +0000
commitfbd747b6a406beff96cc1d3767165aa3f5514a60 (patch)
treeca7fdd1b9dd38548a5ee76433182bc6dd1eae652 /gdb/frame.c
parenta7a38dba7f4fbd9e9c8dd4e739d42ef8a36fb49a (diff)
downloadbinutils-fbd747b6a406beff96cc1d3767165aa3f5514a60.zip
binutils-fbd747b6a406beff96cc1d3767165aa3f5514a60.tar.gz
binutils-fbd747b6a406beff96cc1d3767165aa3f5514a60.tar.bz2
gdb: Fix assertion failure when inline frame #0 is duplicated
Modifying inline-frame-cycle-unwind.exp to use `bt -no-filters` produces the following incorrect backtrace: #0 inline_func () at .../gdb/gdb/testsuite/gdb.base/inline-frame-cycle-unwind.c:49 #1 normal_func () at .../gdb/gdb/testsuite/gdb.base/inline-frame-cycle-unwind.c:32 #2 0x000055555555517f in inline_func () at .../gdb/gdb/testsuite/gdb.base/inline-frame-cycle-unwind.c:50 #3 normal_func () at .../gdb/gdb/testsuite/gdb.base/inline-frame-cycle-unwind.c:32 Backtrace stopped: previous frame identical to this frame (corrupt stack?) (gdb) FAIL: gdb.base/inline-frame-cycle-unwind.exp: cycle at level 1: backtrace when the unwind is broken at frame 1 The expected output, which we get with `bt`, is: #0 inline_func () at .../gdb/gdb/testsuite/gdb.base/inline-frame-cycle-unwind.c:49 #1 normal_func () at .../gdb/gdb/testsuite/gdb.base/inline-frame-cycle-unwind.c:32 Backtrace stopped: previous frame identical to this frame (corrupt stack?) (gdb) PASS: gdb.base/inline-frame-cycle-unwind.exp: cycle at level 1: backtrace when the unwind is broken at frame 1 The cycle checking in `get_prev_frame_maybe_check_cycle` relies on newer frame ids having already been computed and stashed. Unlike other frames, frame #0's id does not get computed immediately. The test passes with `bt` because when applying python frame filters, the call to `bootstrap_python_frame_filters` happens to compute the id of frame #0. When `get_prev_frame_maybe_check_cycle` later tries to stash frame #2's id, the cycle is detected. The test fails with `bt -no-filters` because frame #0's id has not been stashed by the time `get_prev_frame_maybe_check_cycle` tries to stash frame #2's id which succeeds and the cycle is only detected later when trying to stash frame #4's id. Doing `stepi` after the incorrect backtrace would then trigger an assertion failure when trying to stash frame #0's id because it is a duplicate of #2's already stashed id. In `get_prev_frame_always_1`, if this_frame is inline frame 0, then compute and stash its frame id before returning the previous frame. This ensures that the id of inline frame 0 has been stashed before `get_prev_frame_maybe_check_cycle` is called on older frames. The test case has been updated to run both `bt` and `bt -no-filters`. Co-authored-by: Andrew Burgess <aburgess@redhat.com>
Diffstat (limited to 'gdb/frame.c')
-rw-r--r--gdb/frame.c17
1 files changed, 16 insertions, 1 deletions
diff --git a/gdb/frame.c b/gdb/frame.c
index 2fb06a0..88560b8 100644
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -2325,7 +2325,22 @@ get_prev_frame_always_1 (const frame_info_ptr &this_frame)
until we have unwound all the way down to the previous non-inline
frame. */
if (get_frame_type (this_frame) == INLINE_FRAME)
- return get_prev_frame_maybe_check_cycle (this_frame);
+ {
+ frame_info_ptr fi = get_prev_frame_maybe_check_cycle (this_frame);
+
+ /* If this_frame is the current frame, then compute and stash its frame
+ id so that the cycle check in get_prev_frame_maybe_check_cycle works
+ correctly in the case where inline frame 0 has been duplicated.
+
+ The this_id.p check is required to avoid recursion as computing the
+ frame id results in a call to inline_frame_this_id which calls back
+ into get_prev_frame_always. */
+ if (this_frame->level == 0
+ && this_frame->this_id.p != frame_id_status::COMPUTING)
+ get_frame_id (this_frame);
+
+ return fi;
+ }
/* If this_frame is the current frame, then compute and stash its
frame id prior to fetching and computing the frame id of the