|
|
28857cc |
2005-02-11 Jeff Johnston <jjohnstn@redhat.com>
|
|
|
28857cc |
|
|
|
28857cc |
* target.h (target_waitstatus): Add new step_thread_exit flag.
|
|
|
28857cc |
* infrun.c (init_execution_control_state): Initialize step_thread_exit.
|
|
|
28857cc |
(handle_inferior_event): If step_thread_exit flag is set, print
|
|
|
28857cc |
out special message and reset flag.
|
|
|
28857cc |
(currently_stepping): Do not return true if step_thread_exit flag
|
|
|
28857cc |
is set.
|
|
|
28857cc |
* linux-nat.c (resume_callback): Use second parameter to notify
|
|
|
28857cc |
if the resume should be a PTRACE_SINGLESTEP or PTRACE_CONT.
|
|
|
28857cc |
(stop_and_resume_callback): Pass on data parameter to resume_callback.
|
|
|
28857cc |
(linux_nat_resume): Don't attempt to resume if lp is NULL.
|
|
|
28857cc |
(linux_nat_wait): Do not wait on step_lp as first wait. After
|
|
|
28857cc |
wait, check if step_lp has an event or not. If the step lwp has
|
|
|
28857cc |
exited, issue a stop on the first non-step_lp lwp in the lwp list.
|
|
|
28857cc |
Change the delayed stop code to not ignore an intentional stop.
|
|
|
28857cc |
If we see an event on an lwp which isn't the step_lp, verify if
|
|
|
28857cc |
the step_lp has exited or not. Set the step_thread_exit flag if
|
|
|
28857cc |
we have verified that the step_lp is gone.
|
|
|
28857cc |
* testsuite/gdb.threads/step-thread-exit.c: New testcase.
|
|
|
28857cc |
* testsuite/gdb.threads/step-thread-exit.exp: Ditto.
|
|
|
28857cc |
|
|
|
9231e41 |
Index: gdb-6.5/gdb/testsuite/gdb.threads/step-thread-exit.c
|
|
|
9231e41 |
===================================================================
|
|
|
9231e41 |
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
|
|
fef19e0 |
+++ gdb-6.5/gdb/testsuite/gdb.threads/step-thread-exit.c 2006-07-12 03:18:47.000000000 -0300
|
|
|
fef19e0 |
@@ -0,0 +1,50 @@
|
|
|
28857cc |
+/* This testcase is part of GDB, the GNU debugger.
|
|
|
28857cc |
+
|
|
|
28857cc |
+ Copyright 2005 Free Software Foundation, Inc.
|
|
|
28857cc |
+
|
|
|
28857cc |
+ This program is free software; you can redistribute it and/or modify
|
|
|
28857cc |
+ it under the terms of the GNU General Public License as published by
|
|
|
28857cc |
+ the Free Software Foundation; either version 2 of the License, or
|
|
|
28857cc |
+ (at your option) any later version.
|
|
|
28857cc |
+
|
|
|
28857cc |
+ This program is distributed in the hope that it will be useful,
|
|
|
28857cc |
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
28857cc |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
28857cc |
+ GNU General Public License for more details.
|
|
|
28857cc |
+
|
|
|
28857cc |
+ You should have received a copy of the GNU General Public License
|
|
|
28857cc |
+ along with this program; if not, write to the Free Software
|
|
|
28857cc |
+ Foundation, Inc., 59 Temple Place - Suite 330,
|
|
|
28857cc |
+ Boston, MA 02111-1307, USA. */
|
|
|
28857cc |
+
|
|
|
28857cc |
+#include <pthread.h>
|
|
|
28857cc |
+#include <stdio.h>
|
|
|
28857cc |
+#include <stdlib.h>
|
|
|
28857cc |
+#include <unistd.h>
|
|
|
28857cc |
+
|
|
|
28857cc |
+void *thread_function (void *ptr)
|
|
|
28857cc |
+{
|
|
|
28857cc |
+ int *x = (int *)ptr;
|
|
|
28857cc |
+ printf("In thread_function, *x is %d\n", *x);
|
|
|
28857cc |
+} /* thread_function_end */
|
|
|
28857cc |
+
|
|
|
fef19e0 |
+volatile int repeat = 0;
|
|
|
fef19e0 |
+
|
|
|
28857cc |
+main()
|
|
|
28857cc |
+{
|
|
|
28857cc |
+ int ret;
|
|
|
28857cc |
+ pthread_t th;
|
|
|
28857cc |
+ int i = 3;
|
|
|
28857cc |
+
|
|
|
28857cc |
+ ret = pthread_create (&th, NULL, thread_function, &i);
|
|
|
fef19e0 |
+ do
|
|
|
fef19e0 |
+ {
|
|
|
fef19e0 |
+ repeat = 0;
|
|
|
fef19e0 |
+ sleep (3); /* sleep */
|
|
|
fef19e0 |
+ }
|
|
|
fef19e0 |
+ while (repeat);
|
|
|
28857cc |
+ pthread_join (th, NULL);
|
|
|
28857cc |
+ return 0;
|
|
|
28857cc |
+}
|
|
|
28857cc |
+
|
|
|
28857cc |
+
|
|
|
9231e41 |
Index: gdb-6.5/gdb/testsuite/gdb.threads/step-thread-exit.exp
|
|
|
9231e41 |
===================================================================
|
|
|
9231e41 |
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
|
|
fef19e0 |
+++ gdb-6.5/gdb/testsuite/gdb.threads/step-thread-exit.exp 2006-07-12 03:22:30.000000000 -0300
|
|
|
fef19e0 |
@@ -0,0 +1,113 @@
|
|
|
28857cc |
+# This testcase is part of GDB, the GNU debugger.
|
|
|
28857cc |
+
|
|
|
28857cc |
+# Copyright 2005 Free Software Foundation, Inc.
|
|
|
28857cc |
+
|
|
|
28857cc |
+# This program is free software; you can redistribute it and/or modify
|
|
|
28857cc |
+# it under the terms of the GNU General Public License as published by
|
|
|
28857cc |
+# the Free Software Foundation; either version 2 of the License, or
|
|
|
28857cc |
+# (at your option) any later version.
|
|
|
28857cc |
+#
|
|
|
28857cc |
+# This program is distributed in the hope that it will be useful,
|
|
|
28857cc |
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
28857cc |
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
28857cc |
+# GNU General Public License for more details.
|
|
|
28857cc |
+#
|
|
|
28857cc |
+# You should have received a copy of the GNU General Public License
|
|
|
28857cc |
+# along with this program; if not, write to the Free Software
|
|
|
28857cc |
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
28857cc |
+
|
|
|
28857cc |
+# Check that GDB can step over a thread exit.
|
|
|
28857cc |
+
|
|
|
28857cc |
+if $tracelevel {
|
|
|
28857cc |
+ strace $tracelevel
|
|
|
28857cc |
+}
|
|
|
28857cc |
+
|
|
|
28857cc |
+set prms_id 0
|
|
|
28857cc |
+set bug_id 0
|
|
|
28857cc |
+
|
|
|
28857cc |
+set testfile "step-thread-exit"
|
|
|
28857cc |
+set srcfile ${testfile}.c
|
|
|
28857cc |
+set binfile ${objdir}/${subdir}/${testfile}
|
|
|
28857cc |
+if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "incdir=${objdir}"]] != "" } {
|
|
|
28857cc |
+ return -1
|
|
|
28857cc |
+}
|
|
|
28857cc |
+
|
|
|
28857cc |
+gdb_exit
|
|
|
28857cc |
+gdb_start
|
|
|
28857cc |
+gdb_reinitialize_dir $srcdir/$subdir
|
|
|
28857cc |
+gdb_load ${binfile}
|
|
|
28857cc |
+
|
|
|
28857cc |
+# Reset the debug file directory so we can't debug within the C library
|
|
|
28857cc |
+gdb_test "set debug-file-directory ." "" ""
|
|
|
28857cc |
+
|
|
|
28857cc |
+#
|
|
|
28857cc |
+# Run to `main' where we begin our tests.
|
|
|
28857cc |
+#
|
|
|
28857cc |
+
|
|
|
28857cc |
+if ![runto_main] then {
|
|
|
28857cc |
+ gdb_suppress_tests
|
|
|
28857cc |
+}
|
|
|
28857cc |
+
|
|
|
28857cc |
+set sleep_line [expr [gdb_get_line_number "sleep"]]
|
|
|
28857cc |
+set end_line [expr [gdb_get_line_number "thread_function_end"]]
|
|
|
28857cc |
+
|
|
|
28857cc |
+gdb_breakpoint "$end_line"
|
|
|
28857cc |
+gdb_test "continue" "Break.*thread_function.*" "continue to thread_function 1"
|
|
|
28857cc |
+
|
|
|
28857cc |
+# Keep nexting until we cause the thread to exit. We expect the main
|
|
|
28857cc |
+# thread to be stopped and a message printed to tell us we have stepped
|
|
|
28857cc |
+# over the thread exit.
|
|
|
28857cc |
+set test "step over thread exit 1"
|
|
|
28857cc |
+gdb_test_multiple "next" "$test" {
|
|
|
28857cc |
+ -re "\}.*$gdb_prompt $" {
|
|
|
28857cc |
+ send_gdb "next\n"
|
|
|
28857cc |
+ exp_continue
|
|
|
28857cc |
+ }
|
|
|
fef19e0 |
+ -re "Stepped over thread exit.*Program received signal SIGSTOP.*$gdb_prompt $" {
|
|
|
fef19e0 |
+ pass "$test"
|
|
|
28857cc |
+ }
|
|
|
28857cc |
+ -re "start_thread.*$gdb_prompt $" {
|
|
|
28857cc |
+ send_gdb "next\n"
|
|
|
28857cc |
+ exp_continue
|
|
|
28857cc |
+ }
|
|
|
28857cc |
+}
|
|
|
28857cc |
+
|
|
|
28857cc |
+gdb_test "bt" ".*sleep.*main.*$sleep_line.*" "backtrace after step 1"
|
|
|
28857cc |
+
|
|
|
28857cc |
+runto_main
|
|
|
28857cc |
+gdb_breakpoint "$sleep_line"
|
|
|
28857cc |
+gdb_breakpoint "$end_line"
|
|
|
fef19e0 |
+set test "continue to thread_function 2"
|
|
|
fef19e0 |
+gdb_test_multiple "continue" "$test" {
|
|
|
fef19e0 |
+ -re "Break.*thread_function.*$gdb_prompt $" {
|
|
|
fef19e0 |
+ pass $test
|
|
|
fef19e0 |
+ }
|
|
|
fef19e0 |
+ -re "Break.*$sleep_line.*$gdb_prompt $" {
|
|
|
fef19e0 |
+ gdb_test "set repeat=1" "" ""
|
|
|
fef19e0 |
+ send_gdb "continue\n"
|
|
|
fef19e0 |
+ exp_continue
|
|
|
fef19e0 |
+ }
|
|
|
fef19e0 |
+}
|
|
|
28857cc |
+
|
|
|
28857cc |
+# Keep nexting until we cause the thread to exit. In this case, we
|
|
|
28857cc |
+# expect the breakpoint in the main thread to have already triggered
|
|
|
28857cc |
+# and so we should stop there with a message that we stepped over
|
|
|
28857cc |
+# the thread exit.
|
|
|
28857cc |
+set test "step over thread exit 2"
|
|
|
28857cc |
+gdb_test_multiple "next" "$test" {
|
|
|
28857cc |
+ -re "\}.*$gdb_prompt $" {
|
|
|
28857cc |
+ send_gdb "next\n"
|
|
|
28857cc |
+ exp_continue
|
|
|
28857cc |
+ }
|
|
|
fef19e0 |
+ -re "Stepped over thread exit.*Break.*$sleep_line.*$gdb_prompt $" {
|
|
|
fef19e0 |
+ pass "$test (breakpoint hit)"
|
|
|
fef19e0 |
+ }
|
|
|
fef19e0 |
+ -re "Stepped over thread exit.*$gdb_prompt $" {
|
|
|
fef19e0 |
+ pass "$test (breakpoint not hit)"
|
|
|
28857cc |
+ }
|
|
|
28857cc |
+ -re "start_thread.*$gdb_prompt $" {
|
|
|
28857cc |
+ send_gdb "next\n"
|
|
|
28857cc |
+ exp_continue
|
|
|
28857cc |
+ }
|
|
|
28857cc |
+}
|
|
|
28857cc |
+
|
|
|
9231e41 |
Index: gdb-6.5/gdb/infrun.c
|
|
|
9231e41 |
===================================================================
|
|
|
fef19e0 |
--- gdb-6.5.orig/gdb/infrun.c 2006-07-12 01:54:29.000000000 -0300
|
|
|
fef19e0 |
+++ gdb-6.5/gdb/infrun.c 2006-07-12 03:22:41.000000000 -0300
|
|
|
9231e41 |
@@ -1088,6 +1088,7 @@ init_execution_control_state (struct exe
|
|
|
28857cc |
ecs->current_symtab = ecs->sal.symtab;
|
|
|
28857cc |
ecs->infwait_state = infwait_normal_state;
|
|
|
28857cc |
ecs->waiton_ptid = pid_to_ptid (-1);
|
|
|
28857cc |
+ ecs->ws.step_thread_exit = 0;
|
|
|
28857cc |
ecs->wp = &(ecs->ws);
|
|
|
28857cc |
}
|
|
|
28857cc |
|
|
|
9231e41 |
@@ -1307,6 +1308,16 @@ handle_inferior_event (struct execution_
|
|
|
28857cc |
ui_out_text (uiout, "]\n");
|
|
|
28857cc |
}
|
|
|
28857cc |
|
|
|
28857cc |
+ /* Check if were stepping a thread and we stepped over the exit.
|
|
|
28857cc |
+ In such a case, we will have found another event to process.
|
|
|
28857cc |
+ Clear any stepping state and process that event. */
|
|
|
28857cc |
+ if (ecs->ws.step_thread_exit)
|
|
|
28857cc |
+ {
|
|
|
28857cc |
+ printf_unfiltered ("[Stepped over thread exit]\n");
|
|
|
28857cc |
+ clear_proceed_status ();
|
|
|
28857cc |
+ ecs->ws.step_thread_exit = 0;
|
|
|
28857cc |
+ }
|
|
|
28857cc |
+
|
|
|
28857cc |
switch (ecs->ws.kind)
|
|
|
28857cc |
{
|
|
|
28857cc |
case TARGET_WAITKIND_LOADED:
|
|
|
fef19e0 |
@@ -2697,11 +2708,12 @@ process_event_stop_test:
|
|
|
28857cc |
static int
|
|
|
28857cc |
currently_stepping (struct execution_control_state *ecs)
|
|
|
28857cc |
{
|
|
|
28857cc |
- return ((!ecs->handling_longjmp
|
|
|
28857cc |
- && ((step_range_end && step_resume_breakpoint == NULL)
|
|
|
28857cc |
- || trap_expected))
|
|
|
28857cc |
- || ecs->stepping_through_solib_after_catch
|
|
|
28857cc |
- || bpstat_should_step ());
|
|
|
28857cc |
+ return (!ecs->ws.step_thread_exit
|
|
|
28857cc |
+ && ((!ecs->handling_longjmp
|
|
|
28857cc |
+ && ((step_range_end && step_resume_breakpoint == NULL)
|
|
|
28857cc |
+ || trap_expected))
|
|
|
28857cc |
+ || ecs->stepping_through_solib_after_catch
|
|
|
28857cc |
+ || bpstat_should_step ()));
|
|
|
28857cc |
}
|
|
|
28857cc |
|
|
|
28857cc |
/* Subroutine call with source code we should not step over. Do step
|
|
|
9231e41 |
Index: gdb-6.5/gdb/linux-nat.c
|
|
|
9231e41 |
===================================================================
|
|
|
fef19e0 |
--- gdb-6.5.orig/gdb/linux-nat.c 2006-07-12 01:54:29.000000000 -0300
|
|
|
fef19e0 |
+++ gdb-6.5/gdb/linux-nat.c 2006-07-12 03:22:42.000000000 -0300
|
|
|
fef19e0 |
@@ -1137,18 +1137,21 @@ linux_nat_detach (char *args, int from_t
|
|
|
28857cc |
static int
|
|
|
28857cc |
resume_callback (struct lwp_info *lp, void *data)
|
|
|
28857cc |
{
|
|
|
28857cc |
+ int step = (data != NULL);
|
|
|
28857cc |
+
|
|
|
28857cc |
if (lp->stopped && lp->status == 0)
|
|
|
28857cc |
{
|
|
|
28857cc |
struct thread_info *tp;
|
|
|
28857cc |
|
|
|
9231e41 |
linux_ops->to_resume (pid_to_ptid (GET_LWP (lp->ptid)),
|
|
|
9231e41 |
- 0, TARGET_SIGNAL_0);
|
|
|
9231e41 |
+ step, TARGET_SIGNAL_0);
|
|
|
28857cc |
if (debug_linux_nat)
|
|
|
28857cc |
fprintf_unfiltered (gdb_stdlog,
|
|
|
28857cc |
- "RC: PTRACE_CONT %s, 0, 0 (resume sibling)\n",
|
|
|
28857cc |
+ "RC: %s %s, 0, 0 (resume sibling)\n",
|
|
|
28857cc |
+ step ? "PTRACE_SINGLESTEP" : "PTRACE_CONT",
|
|
|
28857cc |
target_pid_to_str (lp->ptid));
|
|
|
28857cc |
lp->stopped = 0;
|
|
|
28857cc |
- lp->step = 0;
|
|
|
28857cc |
+ lp->step = step;
|
|
|
28857cc |
}
|
|
|
28857cc |
|
|
|
28857cc |
return 0;
|
|
|
fef19e0 |
@@ -1259,13 +1262,17 @@ linux_nat_resume (ptid_t ptid, int step,
|
|
|
28857cc |
if (resume_all)
|
|
|
28857cc |
iterate_over_lwps (resume_callback, NULL);
|
|
|
28857cc |
|
|
|
9231e41 |
- linux_ops->to_resume (ptid, step, signo);
|
|
|
28857cc |
- if (debug_linux_nat)
|
|
|
28857cc |
- fprintf_unfiltered (gdb_stdlog,
|
|
|
28857cc |
- "LLR: %s %s, %s (resume event thread)\n",
|
|
|
28857cc |
- step ? "PTRACE_SINGLESTEP" : "PTRACE_CONT",
|
|
|
28857cc |
- target_pid_to_str (ptid),
|
|
|
28857cc |
- signo ? strsignal (signo) : "0");
|
|
|
28857cc |
+ if (lp)
|
|
|
28857cc |
+ {
|
|
|
9231e41 |
+ linux_ops->to_resume (ptid, step, signo);
|
|
|
28857cc |
+
|
|
|
28857cc |
+ if (debug_linux_nat)
|
|
|
9231e41 |
+ fprintf_unfiltered (gdb_stdlog,
|
|
|
28857cc |
+ "LLR: %s %s, %s (resume event thread)\n",
|
|
|
28857cc |
+ step ? "PTRACE_SINGLESTEP" : "PTRACE_CONT",
|
|
|
28857cc |
+ target_pid_to_str (ptid),
|
|
|
28857cc |
+ signo ? strsignal (signo) : "0");
|
|
|
28857cc |
+ }
|
|
|
28857cc |
}
|
|
|
28857cc |
|
|
|
28857cc |
/* Issue kill to specified lwp. */
|
|
|
fef19e0 |
@@ -1863,7 +1870,7 @@ stop_and_resume_callback (struct lwp_inf
|
|
|
28857cc |
for (ptr = lwp_list; ptr; ptr = ptr->next)
|
|
|
28857cc |
if (lp == ptr)
|
|
|
28857cc |
{
|
|
|
28857cc |
- resume_callback (lp, NULL);
|
|
|
28857cc |
+ resume_callback (lp, data);
|
|
|
28857cc |
resume_set_callback (lp, NULL);
|
|
|
28857cc |
}
|
|
|
28857cc |
}
|
|
|
fef19e0 |
@@ -1874,8 +1881,10 @@ static ptid_t
|
|
|
28857cc |
linux_nat_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
|
|
|
28857cc |
{
|
|
|
28857cc |
struct lwp_info *lp = NULL;
|
|
|
28857cc |
+ struct lwp_info *step_lp = NULL;
|
|
|
28857cc |
int options = 0;
|
|
|
28857cc |
int status = 0;
|
|
|
28857cc |
+ int intentional_stop = 0;
|
|
|
28857cc |
pid_t pid = PIDGET (ptid);
|
|
|
28857cc |
sigset_t flush_mask;
|
|
|
28857cc |
|
|
|
fef19e0 |
@@ -1913,14 +1922,12 @@ retry:
|
|
|
28857cc |
gets the expected trap so we don't want to wait on any LWP.
|
|
|
28857cc |
This has ramifications when adjustment of the PC is required which can be
|
|
|
28857cc |
different after a breakpoint vs a step (e.g. x86). */
|
|
|
28857cc |
- lp = iterate_over_lwps (find_singlestep_lwp_callback, NULL);
|
|
|
28857cc |
- if (lp) {
|
|
|
28857cc |
+ step_lp = iterate_over_lwps (find_singlestep_lwp_callback, NULL);
|
|
|
28857cc |
+ if (step_lp) {
|
|
|
28857cc |
if (debug_linux_nat)
|
|
|
28857cc |
fprintf_unfiltered (gdb_stdlog,
|
|
|
28857cc |
"LLW: Found step lwp %s.\n",
|
|
|
28857cc |
- target_pid_to_str (lp->ptid));
|
|
|
28857cc |
- ptid = lp->ptid;
|
|
|
28857cc |
- pid = PIDGET (ptid);
|
|
|
28857cc |
+ target_pid_to_str (step_lp->ptid));
|
|
|
28857cc |
}
|
|
|
28857cc |
|
|
|
28857cc |
/* If any pid, check if there is a LWP with a wait status pending. */
|
|
|
fef19e0 |
@@ -2161,8 +2168,9 @@ retry:
|
|
|
28857cc |
}
|
|
|
28857cc |
|
|
|
28857cc |
/* Make sure we don't report a SIGSTOP that we sent
|
|
|
28857cc |
- ourselves in an attempt to stop an LWP. */
|
|
|
28857cc |
- if (lp->signalled
|
|
|
28857cc |
+ ourselves in an attempt to stop an LWP, unless we
|
|
|
28857cc |
+ intentionally want to see the SIGSTOP. */
|
|
|
28857cc |
+ if (lp->signalled && !intentional_stop
|
|
|
28857cc |
&& WIFSTOPPED (status) && WSTOPSIG (status) == SIGSTOP)
|
|
|
28857cc |
{
|
|
|
28857cc |
if (debug_linux_nat)
|
|
|
fef19e0 |
@@ -2196,6 +2204,20 @@ retry:
|
|
|
28857cc |
|
|
|
28857cc |
if (pid == -1)
|
|
|
28857cc |
{
|
|
|
28857cc |
+ lp = NULL;
|
|
|
28857cc |
+ if (step_lp && errno == ECHILD)
|
|
|
28857cc |
+ {
|
|
|
28857cc |
+ /* We have stepped over a thread exit. We want to stop
|
|
|
28857cc |
+ the first existing lwp we find and report a stop event. */
|
|
|
28857cc |
+ for (lp = lwp_list; lp && lp == step_lp; lp = lp->next)
|
|
|
28857cc |
+ ; /* empty */
|
|
|
28857cc |
+ }
|
|
|
28857cc |
+ if (lp != NULL)
|
|
|
28857cc |
+ {
|
|
|
28857cc |
+ stop_callback (lp, NULL);
|
|
|
28857cc |
+ intentional_stop = 1;
|
|
|
28857cc |
+ }
|
|
|
28857cc |
+
|
|
|
28857cc |
/* Alternate between checking cloned and uncloned processes. */
|
|
|
28857cc |
options ^= __WCLONE;
|
|
|
28857cc |
|
|
|
fef19e0 |
@@ -2268,6 +2290,42 @@ retry:
|
|
|
28857cc |
fprintf_unfiltered (gdb_stdlog, "LLW: Candidate event %s in %s.\n",
|
|
|
28857cc |
status_to_str (status), target_pid_to_str (lp->ptid));
|
|
|
28857cc |
|
|
|
28857cc |
+ /* Check if there is any LWP that is being single-stepped. We need to
|
|
|
28857cc |
+ wait specifically on such an LWP because the higher-level code is
|
|
|
28857cc |
+ expecting a step operation to find an event on the stepped LWP.
|
|
|
28857cc |
+ It is possible for other events to occur before the step operation
|
|
|
28857cc |
+ gets the expected trap so we don't want to wait on any LWP.
|
|
|
28857cc |
+ This has ramifications when adjustment of the PC is required which can be
|
|
|
28857cc |
+ different after a breakpoint vs a step (e.g. x86). */
|
|
|
28857cc |
+ if (step_lp && step_lp != lp)
|
|
|
28857cc |
+ {
|
|
|
28857cc |
+ struct lwp_info *ptr;
|
|
|
28857cc |
+ int arg = 1;
|
|
|
28857cc |
+ if (debug_linux_nat)
|
|
|
28857cc |
+ fprintf_unfiltered (gdb_stdlog,
|
|
|
28857cc |
+ "LLW: Found step lwp %s.\n",
|
|
|
28857cc |
+ target_pid_to_str (step_lp->ptid));
|
|
|
28857cc |
+ stop_and_resume_callback (step_lp, &arg;;
|
|
|
28857cc |
+ for (ptr = lwp_list; ptr; ptr = ptr->next)
|
|
|
28857cc |
+ if (step_lp == ptr)
|
|
|
28857cc |
+ break;
|
|
|
28857cc |
+
|
|
|
28857cc |
+ if (ptr)
|
|
|
28857cc |
+ {
|
|
|
28857cc |
+ if (debug_linux_nat)
|
|
|
28857cc |
+ fprintf_unfiltered (gdb_stdlog,
|
|
|
28857cc |
+ "LLW: Continuing step lwp %s.\n",
|
|
|
28857cc |
+ target_pid_to_str (step_lp->ptid));
|
|
|
28857cc |
+ ptid = step_lp->ptid;
|
|
|
28857cc |
+ pid = PIDGET (ptid);
|
|
|
28857cc |
+ lp->status = status;
|
|
|
28857cc |
+ status = 0;
|
|
|
28857cc |
+ options = WNOHANG | (step_lp->cloned ? __WCLONE : 0);
|
|
|
28857cc |
+ pid = GET_LWP (ptid);
|
|
|
28857cc |
+ goto retry;
|
|
|
28857cc |
+ }
|
|
|
28857cc |
+ }
|
|
|
28857cc |
+
|
|
|
28857cc |
/* Now stop all other LWP's ... */
|
|
|
28857cc |
iterate_over_lwps (stop_callback, NULL);
|
|
|
28857cc |
|
|
|
fef19e0 |
@@ -2306,6 +2364,10 @@ retry:
|
|
|
28857cc |
else
|
|
|
28857cc |
store_waitstatus (ourstatus, status);
|
|
|
28857cc |
|
|
|
28857cc |
+ /* If we were stepping a thread and it exited, mark this. */
|
|
|
28857cc |
+ if (step_lp && step_lp != lp)
|
|
|
28857cc |
+ ourstatus->step_thread_exit = 1;
|
|
|
28857cc |
+
|
|
|
9231e41 |
return lp->ptid;
|
|
|
28857cc |
}
|
|
|
28857cc |
|
|
|
9231e41 |
Index: gdb-6.5/gdb/target.h
|
|
|
9231e41 |
===================================================================
|
|
|
fef19e0 |
--- gdb-6.5.orig/gdb/target.h 2006-07-12 01:54:29.000000000 -0300
|
|
|
fef19e0 |
+++ gdb-6.5/gdb/target.h 2006-07-12 03:22:40.000000000 -0300
|
|
|
9231e41 |
@@ -136,6 +136,7 @@ enum target_waitkind
|
|
|
28857cc |
struct target_waitstatus
|
|
|
28857cc |
{
|
|
|
28857cc |
enum target_waitkind kind;
|
|
|
28857cc |
+ int step_thread_exit; /* non-zero if we step over a thread exit. */
|
|
|
28857cc |
|
|
|
28857cc |
/* Forked child pid, execd pathname, exit status or signal number. */
|
|
|
28857cc |
union
|