diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 6d0a0c64910..16daed77ff1 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,10 @@ +2020-11-16 Pedro Alves + + * frame.c (get_prev_frame): Move get_frame_id call from here ... + (get_prev_frame_always_1): ... to here. + * inline-frame.c (inline_frame_this_id): Mention + get_prev_frame_always_1 in comment. + 2020-11-15 Joel Brobecker * valarith.c (fixed_point_binop): Add BINOP_EQUAL and BINOP_LESS diff --git a/gdb/frame.c b/gdb/frame.c index e783638e0d1..4618da6c81e 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -2200,6 +2200,23 @@ get_prev_frame_always_1 (struct frame_info *this_frame) if (get_frame_type (this_frame) == INLINE_FRAME) return get_prev_frame_if_no_cycle (this_frame); + /* If this_frame is the current frame, then compute and stash its + frame id prior to fetching and computing the frame id of the + previous frame. Otherwise, the cycle detection code in + get_prev_frame_if_no_cycle() will not work correctly. When + get_frame_id() is called later on, an assertion error will be + triggered in the event of a cycle between the current frame and + its previous frame. + + Note we do this after the INLINE_FRAME check above. That is + because the inline frame's frame id computation needs to fetch + the frame id of its previous real stack frame. I.e., we need to + avoid recursion in that case. This is OK since we're sure the + inline frame won't create a cycle with the real stack frame. See + inline_frame_this_id. */ + if (this_frame->level == 0) + get_frame_id (this_frame); + /* Check that this frame is unwindable. If it isn't, don't try to unwind to the prev frame. */ this_frame->stop_reason @@ -2492,16 +2509,6 @@ get_prev_frame (struct frame_info *this_frame) something should be calling get_selected_frame() or get_current_frame(). */ gdb_assert (this_frame != NULL); - - /* If this_frame is the current frame, then compute and stash - its frame id prior to fetching and computing the frame id of the - previous frame. Otherwise, the cycle detection code in - get_prev_frame_if_no_cycle() will not work correctly. When - get_frame_id() is called later on, an assertion error will - be triggered in the event of a cycle between the current - frame and its previous frame. */ - if (this_frame->level == 0) - get_frame_id (this_frame); frame_pc_p = get_frame_pc_if_available (this_frame, &frame_pc); diff --git a/gdb/inline-frame.c b/gdb/inline-frame.c index 300b1224db0..92a7d562eaf 100644 --- a/gdb/inline-frame.c +++ b/gdb/inline-frame.c @@ -161,7 +161,8 @@ inline_frame_this_id (struct frame_info *this_frame, real frame's this_id method. So we must call get_prev_frame_always. Because we are inlined into some function, there must be previous frames, so this is safe - as - long as we're careful not to create any cycles. */ + long as we're careful not to create any cycles. See related + comments in get_prev_frame_always_1. */ *this_id = get_frame_id (get_prev_frame_always (this_frame)); /* We need a valid frame ID, so we need to be based on a valid