diff options
author | Markus Metzger <markus.t.metzger@intel.com> | 2016-05-31 09:03:15 +0200 |
---|---|---|
committer | Markus Metzger <markus.t.metzger@intel.com> | 2016-06-01 11:14:02 +0200 |
commit | e3b5daf9f735999259c5a8f68b422850c59897e5 (patch) | |
tree | 240a55afba83e89b38678d33373d27d9c8920be0 /gdb | |
parent | 03d73f1fd9d89d89bdd021cad26693e4f6abc07a (diff) | |
download | gdb-e3b5daf9f735999259c5a8f68b422850c59897e5.zip gdb-e3b5daf9f735999259c5a8f68b422850c59897e5.tar.gz gdb-e3b5daf9f735999259c5a8f68b422850c59897e5.tar.bz2 |
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.
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/ChangeLog | 5 | ||||
-rw-r--r-- | gdb/infcmd.c | 30 |
2 files changed, 30 insertions, 5 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index f9dc6f9..134f0f4 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -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 diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 14d51fd..1defb13 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.")); |