From e3b5daf9f735999259c5a8f68b422850c59897e5 Mon Sep 17 00:00:00 2001 From: Markus Metzger Date: Tue, 31 May 2016 09:03:15 +0200 Subject: [PATCH] infcmd, btrace: fix crash in 'finish' for tailcall-only frames Patch 7eb895307f53 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. --- gdb/ChangeLog | 5 +++++ gdb/infcmd.c | 30 +++++++++++++++++++++++++----- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index f9dc6f9c61f..134f0f45064 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,8 @@ +2016-06-01 Markus Metzger + + * infcmd.c (skip_finish_frames): New. + (finish_command): Call skip_finish_frames. + 2016-06-01 Yao Qi PR remote/19998 diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 14d51fd4710..1defb13806d 100644 --- a/gdb/infcmd.c +++ b/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.")); -- 2.30.2