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:
Markus Metzger
2016-05-31 09:03:15 +02:00
parent 03d73f1fd9
commit e3b5daf9f7
2 changed files with 30 additions and 5 deletions

View File

@@ -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

View File

@@ -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."));