aboutsummaryrefslogtreecommitdiff
path: root/gdb/gdbserver
diff options
context:
space:
mode:
authorYao Qi <yao.qi@linaro.org>2016-06-17 10:25:12 +0100
committerYao Qi <yao.qi@linaro.org>2016-06-17 10:38:55 +0100
commitf50bf8e5153e3cdddd1ad5d3f7d16f2b4e5adb3c (patch)
treeac0815d07b13c8d80b7ee797b0a7d32333743abe /gdb/gdbserver
parent8376a3cbf73ca8b623db1daa8f9c49fb83ac54bd (diff)
downloadgdb-f50bf8e5153e3cdddd1ad5d3f7d16f2b4e5adb3c.zip
gdb-f50bf8e5153e3cdddd1ad5d3f7d16f2b4e5adb3c.tar.gz
gdb-f50bf8e5153e3cdddd1ad5d3f7d16f2b4e5adb3c.tar.bz2
Step over exit with reinsert breakpoints
This patch fixes a GDBserver crash when one thread is stepping over a syscall instruction which is exit. Step-over isn't finished due to the exit, but GDBserver doesn't clean up the state of step-over, so in the wait next time, GDBserver will wait on step_over_bkpt, which is already exited, and GDBserver crashes because 'requested_child' is NULL. See gdbserver logs below, Need step over [LWP 14858]? yes, found breakpoint at 0x2aaaaad91307^M proceed_all_lwps: found thread 14858 needing a step-over^M Starting step-over on LWP 14858. Stopping all threads^M >>>> entering void stop_all_lwps(int, lwp_info*) .... <<<< exiting void stop_all_lwps(int, lwp_info*)^M Done stopping all threads for step-over.^M pc is 0x2aaaaad91307^M Writing 0f to 0x2aaaaad91307 in process 14858^M Could not find fast tracepoint jump at 0x2aaaaad91307 in list (uninserting).^M pending reinsert at 0x2aaaaad91307^M step from pc 0x2aaaaad91307^M Resuming lwp 14858 (step, signal 0, stop not expected)^M # Start step-over for LWP 14858 >>>> entering ptid_t linux_wait_1(ptid_t, target_waitstatus*, int) .... LLFE: 14858 exited. ... <<<< exiting ptid_t linux_wait_1(ptid_t, target_waitstatus*, int) # LWP 14858 exited ..... >>>> entering ptid_t linux_wait_1(ptid_t, target_waitstatus*, int)^M linux_wait_1: [<all threads>]^M step_over_bkpt set [LWP 14858.14858], doing a blocking wait # but step_over_bkpt is still LWP 14858, which is wrong The fix is to finish step-over if it is ongoing, and unsuspend other threads. Without the fix in linux-low.c, GDBserver will crash in with running gdb.base/step-over-exit.exp. gdb/gdbserver: 2016-06-17 Yao Qi <yao.qi@linaro.org> * linux-low.c (unsuspend_all_lwps): Declare. (linux_low_filter_event): If thread exited, call finish_step_over. If step-over is finished, unsuspend other threads. gdb/testsuite: 2016-06-17 Yao Qi <yao.qi@linaro.org> * gdb.base/step-over-exit.c: New. * gdb.base/step-over-exit.exp: New.
Diffstat (limited to 'gdb/gdbserver')
-rw-r--r--gdb/gdbserver/ChangeLog6
-rw-r--r--gdb/gdbserver/linux-low.c8
2 files changed, 14 insertions, 0 deletions
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index c7a9595..fd70f59 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,5 +1,11 @@
2016-06-17 Yao Qi <yao.qi@linaro.org>
+ * linux-low.c (unsuspend_all_lwps): Declare.
+ (linux_low_filter_event): If thread exited, call finish_step_over.
+ If step-over is finished, unsuspend other threads.
+
+2016-06-17 Yao Qi <yao.qi@linaro.org>
+
* linux-low.c (linux_resume_one_lwp_throw): Assert
has_reinsert_breakpoints returns false.
* mem-break.c (delete_disabled_breakpoints): Assert
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index 5f025b5..95104d2 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -252,6 +252,7 @@ static void linux_resume_one_lwp (struct lwp_info *lwp,
static void linux_resume (struct thread_resume *resume_info, size_t n);
static void stop_all_lwps (int suspend, struct lwp_info *except);
static void unstop_all_lwps (int unsuspend, struct lwp_info *except);
+static void unsuspend_all_lwps (struct lwp_info *except);
static int linux_wait_for_event_filtered (ptid_t wait_ptid, ptid_t filter_ptid,
int *wstat, int options);
static int linux_wait_for_event (ptid_t ptid, int *wstat, int options);
@@ -2357,6 +2358,13 @@ linux_low_filter_event (int lwpid, int wstat)
{
if (debug_threads)
debug_printf ("LLFE: %d exited.\n", lwpid);
+
+ if (finish_step_over (child))
+ {
+ /* Unsuspend all other LWPs, and set them back running again. */
+ unsuspend_all_lwps (child);
+ }
+
/* If there is at least one more LWP, then the exit signal was
not the end of the debugged application and should be
ignored, unless GDB wants to hear about thread exits. */