mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-26 09:08:59 +00:00
infcmd, btrace: fix crash in 'finish' for tailcall-only frames
Patch 7eb895307f Skip unwritable frames in command "finish"
skips non-writable frames in addition to tailcall frames.
If skip_tailcall_frames already returns NULL, skip_unwritable_frames
will be called with a NULL frame and crash in get_frame_arch. This is
caught by gdb.btrace/tailcall-only.exp.
Further, if we ever end up with a mixture of tailcall and non-writable
frames, we may not skip all of them, as intended.
Loop over skip_tailcall_frames and skip_unwritable_frames as long as at least
one of them makes progress.
gdb/
* infcmd.c (skip_finish_frames): New.
(finish_command): Call skip_finish_frames.
This commit is contained in:
@@ -1,3 +1,8 @@
|
||||
2016-06-01 Markus Metzger <markus.t.metzger@intel.com>
|
||||
|
||||
* infcmd.c (skip_finish_frames): New.
|
||||
(finish_command): Call skip_finish_frames.
|
||||
|
||||
2016-06-01 Yao Qi <yao.qi@linaro.org>
|
||||
|
||||
PR remote/19998
|
||||
|
||||
30
gdb/infcmd.c
30
gdb/infcmd.c
@@ -1927,6 +1927,30 @@ finish_forward (struct finish_command_fsm *sm, struct frame_info *frame)
|
||||
proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
|
||||
}
|
||||
|
||||
/* Skip frames for "finish". */
|
||||
|
||||
static struct frame_info *
|
||||
skip_finish_frames (struct frame_info *frame)
|
||||
{
|
||||
struct frame_info *start;
|
||||
|
||||
do
|
||||
{
|
||||
start = frame;
|
||||
|
||||
frame = skip_tailcall_frames (frame);
|
||||
if (frame == NULL)
|
||||
break;
|
||||
|
||||
frame = skip_unwritable_frames (frame);
|
||||
if (frame == NULL)
|
||||
break;
|
||||
}
|
||||
while (start != frame);
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
/* "finish": Set a temporary breakpoint at the place the selected
|
||||
frame will return to, then continue. */
|
||||
|
||||
@@ -2025,11 +2049,7 @@ finish_command (char *arg, int from_tty)
|
||||
finish_backward (sm);
|
||||
else
|
||||
{
|
||||
/* Ignore TAILCALL_FRAME type frames, they were executed already before
|
||||
entering THISFRAME. */
|
||||
frame = skip_tailcall_frames (frame);
|
||||
|
||||
frame = skip_unwritable_frames (frame);
|
||||
frame = skip_finish_frames (frame);
|
||||
|
||||
if (frame == NULL)
|
||||
error (_("Cannot find the caller frame."));
|
||||
|
||||
Reference in New Issue
Block a user