aboutsummaryrefslogtreecommitdiff
path: root/gdb/gdbserver/linux-low.c
diff options
context:
space:
mode:
authorDaniel Jacobowitz <drow@false.org>2007-07-02 15:35:36 +0000
committerDaniel Jacobowitz <drow@false.org>2007-07-02 15:35:36 +0000
commitae13219ef81570640d856de602d606752f1b562a (patch)
tree253787951832584267f55b893cb5e8a00180e7f5 /gdb/gdbserver/linux-low.c
parent741d6ea85b096ca043859a71ae022ad160a64eec (diff)
downloadgdb-ae13219ef81570640d856de602d606752f1b562a.zip
gdb-ae13219ef81570640d856de602d606752f1b562a.tar.gz
gdb-ae13219ef81570640d856de602d606752f1b562a.tar.bz2
* inferiors.c (change_inferior_id): Add comment.
* linux-low.c (check_removed_breakpoint): Add an early prototype. Improve debug output. (linux_attach): Doc update. (linux_detach_one_process, linux_detach): Clean up before releasing each process. (send_sigstop, wait_for_sigstop): Improve comments and debug output. * linux-low.h (struct process_info): Doc improvement. * mem-break.c (delete_all_breakpoints): New. * mem-break.h (delete_all_breakpoints): New prototype. * thread-db.c (find_first_thread): New. (thread_db_create_event): Call it instead of thread_db_find_new_threads. Clean up unused variables. (maybe_attach_thread): Remove first thread handling. (thread_db_find_new_threads): Use find_first_thread. (thread_db_get_tls_address): Likewise.
Diffstat (limited to 'gdb/gdbserver/linux-low.c')
-rw-r--r--gdb/gdbserver/linux-low.c44
1 files changed, 40 insertions, 4 deletions
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index 067a632..f37e407 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -68,6 +68,7 @@ static void linux_resume_one_process (struct inferior_list_entry *entry,
static void linux_resume (struct thread_resume *resume_info);
static void stop_all_processes (void);
static int linux_wait_for_event (struct thread_info *child);
+static int check_removed_breakpoint (struct process_info *event_child);
struct pending_signals
{
@@ -224,7 +225,8 @@ linux_attach (unsigned long pid)
linux_attach_lwp (pid, pid);
- /* Don't ignore the initial SIGSTOP if we just attached to this process. */
+ /* Don't ignore the initial SIGSTOP if we just attached to this process.
+ It will be collected by wait shortly. */
process = (struct process_info *) find_inferior_id (&all_processes, pid);
process->stop_expected = 0;
@@ -286,13 +288,36 @@ linux_detach_one_process (struct inferior_list_entry *entry)
struct thread_info *thread = (struct thread_info *) entry;
struct process_info *process = get_thread_process (thread);
+ /* Make sure the process isn't stopped at a breakpoint that's
+ no longer there. */
+ check_removed_breakpoint (process);
+
+ /* If this process is stopped but is expecting a SIGSTOP, then make
+ sure we take care of that now. This isn't absolutely guaranteed
+ to collect the SIGSTOP, but is fairly likely to. */
+ if (process->stop_expected)
+ {
+ /* Clear stop_expected, so that the SIGSTOP will be reported. */
+ process->stop_expected = 0;
+ if (process->stopped)
+ linux_resume_one_process (&process->head, 0, 0, NULL);
+ linux_wait_for_event (thread);
+ }
+
+ /* Flush any pending changes to the process's registers. */
+ regcache_invalidate_one ((struct inferior_list_entry *)
+ get_process_thread (process));
+
+ /* Finally, let it resume. */
ptrace (PTRACE_DETACH, pid_of (process), 0, 0);
}
static int
linux_detach (void)
{
+ delete_all_breakpoints ();
for_each_inferior (&all_threads, linux_detach_one_process);
+ clear_inferiors ();
return 0;
}
@@ -332,7 +357,8 @@ check_removed_breakpoint (struct process_info *event_child)
return 0;
if (debug_threads)
- fprintf (stderr, "Checking for breakpoint.\n");
+ fprintf (stderr, "Checking for breakpoint in process %ld.\n",
+ event_child->lwpid);
saved_inferior = current_inferior;
current_inferior = get_process_thread (event_child);
@@ -345,7 +371,8 @@ check_removed_breakpoint (struct process_info *event_child)
if (stop_pc != event_child->pending_stop_pc)
{
if (debug_threads)
- fprintf (stderr, "Ignoring, PC was changed.\n");
+ fprintf (stderr, "Ignoring, PC was changed. Old PC was 0x%08llx\n",
+ event_child->pending_stop_pc);
event_child->pending_is_breakpoint = 0;
current_inferior = saved_inferior;
@@ -817,6 +844,13 @@ send_sigstop (struct inferior_list_entry *entry)
send another. */
if (process->stop_expected)
{
+ if (debug_threads)
+ fprintf (stderr, "Have pending sigstop for process %ld\n",
+ process->lwpid);
+
+ /* We clear the stop_expected flag so that wait_for_sigstop
+ will receive the SIGSTOP event (instead of silently resuming and
+ waiting again). It'll be reset below. */
process->stop_expected = 0;
return;
}
@@ -852,7 +886,9 @@ wait_for_sigstop (struct inferior_list_entry *entry)
&& WSTOPSIG (wstat) != SIGSTOP)
{
if (debug_threads)
- fprintf (stderr, "Stopped with non-sigstop signal\n");
+ fprintf (stderr, "Process %ld (thread %ld) "
+ "stopped with non-sigstop status %06x\n",
+ process->lwpid, process->tid, wstat);
process->status_pending_p = 1;
process->status_pending = wstat;
process->stop_expected = 1;