summaryrefslogtreecommitdiff
path: root/gdb/gdbserver/win32-low.c
diff options
context:
space:
mode:
authorPedro Alves <pedro@codesourcery.com>2009-04-01 22:50:24 +0000
committerPedro Alves <pedro@codesourcery.com>2009-04-01 22:50:24 +0000
commit04687403162fc6cd98679d98abfc7b34a2d44c83 (patch)
tree9ae485b713c21cbe224d34539c8980ad0db750e1 /gdb/gdbserver/win32-low.c
parentc7d9ddfbfc71bdb63152defdc3cd38217bd2c84f (diff)
downloadgdb-04687403162fc6cd98679d98abfc7b34a2d44c83.tar.gz
2009-04-01 Pedro Alves <pedro@codesourcery.com>
Implement the multiprocess extensions, and add linux multiprocess support. * server.h (ULONGEST): Declare. (struct ptid, ptid_t): New. (minus_one_ptid, null_ptid): Declare. (ptid_build, pid_to_ptid, ptid_get_pid, ptid_get_lwp) (ptid_get_tid, ptid_equal, ptid_is_pid): Declare. (struct inferior_list_entry): Change `id' type from unsigned from to ptid_t. (struct sym_cache, struct breakpoint, struct process_info_private): Forward declare. (struct process_info): Declare. (current_process): Declare. (all_processes): Declare. (initialize_inferiors): Declare. (add_thread): Adjust to use ptid_t. (thread_id_to_gdb_id, thread_to_gdb_id, gdb_id_to_thread_id): Ditto. (add_process, remove_process, find_thread_pid): Declare. (find_inferior_id): Adjust to use ptid_t. (cont_thread, general_thread, step_thread): Change type to ptid_t. (multi_process): Declare. (push_event): Adjust to use ptid_t. (read_ptid, write_ptid): Declare. (prepare_resume_reply): Adjust to use ptid_t. (clear_symbol_cache): Declare. * inferiors.c (all_processes): New. (null_ptid, minus_one_ptid): New. (ptid_build, pid_to_ptid, ptid_get_pid, ptid_get_lwp) (ptid_get_tid, ptid_equal, ptid_is_pid): New. (add_thread): Change unsigned long to ptid. Remove gdb_id parameter. Adjust. (thread_id_to_gdb_id, thread_to_gdb_id): Change unsigned long to ptid. (gdb_id_to_thread): Rename to ... (find_thread_pid): ... this. Change unsigned long to ptid. (gdb_id_to_thread_id, find_inferior_id): Change unsigned long to ptid. (loaded_dll, pull_pid_from_list): Adjust. (add_process, remove_process, find_process_pid) (get_thread_process, current_process, initialize_inferiors): New. * target.h (struct thread_resume) <thread>: Change type to ptid_t. (struct target_waitstatus) <related_pid>: Ditto. (struct target_ops) <kill, detach>: Add `pid' argument. Change return type to int. (struct target_ops) <join>: Add `pid' argument. (struct target_ops) <thread_alive>: Change pid's type to ptid_t. (struct target_ops) <wait>: Add `ptid' field. Change return type to ptid. (kill_inferior, detach_inferior, join_inferior): Add `pid' argument. (mywait): Add `ptid' argument. Change return type to ptid_t. (target_pid_to_str): Declare. * target.c (set_desired_inferior): Adjust to use ptids. (mywait): Add new `ptid' argument. Adjust. (target_pid_to_str): New. * mem-break.h (free_all_breakpoints): Declare. * mem-break.c (breakpoints): Delelete. (set_breakpoint_at, delete_breakpoint, find_breakpoint_at) (check_mem_read, check_mem_write, delete_all_breakpoints): Adjust to use per-process breakpoint list. (free_all_breakpoints): New. * remote-utils.c (struct sym_cache) <name>: Drop `const'. (symbol_cache, all_symbols_looked_up): Delete. (hexchars): New. (ishex, unpack_varlen_hex, write_ptid, hex_or_minus_one, read_ptid): New. (prepare_resume_reply): Change ptid argument's type from unsigned long to ptid_t. Adjust. Implement W;process and X;process. (free_sym_cache, clear_symbol_cache): New. (look_up_one_symbol): Adjust to per-process symbol cache. * * server.c (cont_thread, general_thread, step_thread): Change type to ptid_t. (attached): Delete. (multi_process): New. (last_ptid): Change type to ptid_t. (struct vstop_notif) <ptid>: Change type to ptid_t. (queue_stop_reply, push_event): Change `ptid' argument's type to ptid_t. (discard_queued_stop_replies): Add `pid' argument. (start_inferior): Adjust to use ptids. Adjust to mywait interface changes. Don't reference the `attached' global. (attach_inferior): Adjust to mywait interface changes. (handle_query): Adjust to use ptids. Parse GDB's qSupported features. Handle and report "multiprocess+". Handle "qAttached:PID". (handle_v_cont): Adjust to use ptids. Adjust to mywait interface changes. (handle_v_kill): New. (handle_v_stopped): Adjust to use target_pid_to_str. (handle_v_requests): Allow multiple attaches and runs when multiprocess extensions are in effect. Handle "vKill". (myresume): Adjust to use ptids. (queue_stop_reply_callback): Add `arg' parameter. Handle it. (handle_status): Adjust to discard_queued_stop_replies interface change. (first_thread_of, kill_inferior_callback) (detach_or_kill_inferior_callback, join_inferiors_callback): New. (main): Call initialize_inferiors. Adjust to use ptids, killing and detaching from all inferiors. Handle multiprocess packet variants. * linux-low.h: Include gdb_proc_service.h. (struct process_info_private): New. (struct linux_target_ops) <pid_of>: Use ptid_get_pid. <lwpid_of>: Use ptid_get_lwp. (get_lwp_thread): Adjust. (struct lwp_info): Add `dead' member. (find_lwp_pid): Declare. * linux-low.c (thread_db_active): Delete. (new_inferior): Adjust comment. (inferior_pid): Delete. (linux_add_process): New. (handle_extended_wait): Adjust. (add_lwp): Change unsigned long to ptid. (linux_create_inferior): Add process to processes table. Adjust to use ptids. Don't set new_inferior here. (linux_attach_lwp): Rename to ... (linux_attach_lwp_1): ... this. Add `initial' argument. Handle it. Adjust to use ptids. (linux_attach_lwp): New. (linux_attach): Add process to processes table. Don't set new_inferior here. (struct counter): New. (second_thread_of_pid_p, last_thread_of_process_p): New. (linux_kill_one_lwp): Add `args' parameter. Handle it. Adjust to multiple processes. (linux_kill): Add `pid' argument. Handle it. Adjust to multiple processes. Remove process from process table. (linux_detach_one_lwp): Add `args' parameter. Handle it. Adjust to multiple processes. (any_thread_of): New. (linux_detach): Add `pid' argument, and handle it. Remove process from processes table. (linux_join): Add `pid' argument. Handle it. (linux_thread_alive): Change unsighed long argument to ptid_t. Consider dead lwps as not being alive. (status_pending_p): Rename `dummy' argument to `arg'. Filter out threads we're not interested in. (same_lwp, find_lwp_pid): New. (linux_wait_for_lwp): Change `pid' argument's type from int to ptid_t. Adjust. (linux_wait_for_event): Rename to ... (linux_wait_for_event_1): ... this. Change `pid' argument's type from int to ptid_t. Adjust. (linux_wait_for_event): New. (linux_wait_1): Add `ptid' argument. Change return type to ptid_t. Adjust. Use last_thread_of_process_p. Remove processes that exit from the process table. (linux_wait): Add `ptid' argument. Change return type to ptid_t. Adjust. (mark_lwp_dead): New. (wait_for_sigstop): Adjust to use ptids. If a process exits while stopping all threads, mark its main lwp as dead. (linux_set_resume_request, linux_resume_one_thread): Adjust to use ptids. (fetch_register, usr_store_inferior_registers) (regsets_fetch_inferior_registers) (regsets_store_inferior_registers, linux_read_memory) (linux_write_memory): Inline `inferior_pid'. (linux_look_up_symbols): Adjust to use per-process `thread_db_active'. (linux_request_interrupt): Adjust to use ptids. (linux_read_auxv): Inline `inferior_pid'. (initialize_low): Don't reference thread_db_active. * gdb_proc_service.h (struct ps_prochandle) <pid>: Remove. * proc-service.c (ps_lgetregs): Use find_lwp_pid. (ps_getpid): Return the pid of the current inferior. * thread-db.c (proc_handle, thread_agent): Delete. (thread_db_create_event, thread_db_enable_reporting): Adjust to per-process data. (find_one_thread): Change argument type to ptid_t. Adjust to per-process data. (maybe_attach_thread): Adjust to per-process data and ptids. (thread_db_find_new_threads): Ditto. (thread_db_init): Ditto. * spu-low.c (spu_create_inferior, spu_attach): Add process to processes table. Adjust to use ptids. (spu_kill, spu_detach): Adjust interface. Remove process from processes table. (spu_join, spu_thread_alive): Adjust interface. (spu_wait): Adjust interface. Remove process from processes table. Adjust to use ptids. * win32-low.c (current_inferior_tid): Delete. (current_inferior_ptid): New. (debug_event_ptid): New. (thread_rec): Take a ptid. Adjust. (child_add_thread): Add `pid' argument. Adjust to use ptids. (child_delete_thread): Ditto. (do_initial_child_stuff): Add `attached' argument. Add process to processes table. (child_fetch_inferior_registers, child_store_inferior_registers): Adjust. (win32_create_inferior): Pass 0 to do_initial_child_stuff. (win32_attach): Pass 1 to do_initial_child_stuff. (win32_kill): Adjust interface. Remove process from processes table. (win32_detach): Ditto. (win32_join): Adjust interface. (win32_thread_alive): Take a ptid. (win32_resume): Adjust to use ptids. (get_child_debug_event): Ditto. (win32_wait): Adjust interface. Remove exiting process from processes table.
Diffstat (limited to 'gdb/gdbserver/win32-low.c')
-rw-r--r--gdb/gdbserver/win32-low.c117
1 files changed, 72 insertions, 45 deletions
diff --git a/gdb/gdbserver/win32-low.c b/gdb/gdbserver/win32-low.c
index 1d7c2034683..f3943abfd90 100644
--- a/gdb/gdbserver/win32-low.c
+++ b/gdb/gdbserver/win32-low.c
@@ -94,11 +94,17 @@ static void win32_resume (struct thread_resume *resume_info, size_t n);
/* Get the thread ID from the current selected inferior (the current
thread). */
-static DWORD
-current_inferior_tid (void)
+static ptid_t
+current_inferior_ptid (void)
{
- win32_thread_info *th = inferior_target_data (current_inferior);
- return th->tid;
+ return ((struct inferior_list_entry*) current_inferior)->id;
+}
+
+/* The current debug event from WaitForDebugEvent. */
+static ptid_t
+debug_event_ptid (DEBUG_EVENT *event)
+{
+ return ptid_build (event->dwProcessId, event->dwThreadId, 0);
}
/* Get the thread context of the thread associated with TH. */
@@ -137,12 +143,12 @@ win32_set_thread_context (win32_thread_info *th)
/* Find a thread record given a thread id. If GET_CONTEXT is set then
also retrieve the context for this thread. */
static win32_thread_info *
-thread_rec (DWORD id, int get_context)
+thread_rec (ptid_t ptid, int get_context)
{
struct thread_info *thread;
win32_thread_info *th;
- thread = (struct thread_info *) find_inferior_id (&all_threads, id);
+ thread = (struct thread_info *) find_inferior_id (&all_threads, ptid);
if (thread == NULL)
return NULL;
@@ -169,20 +175,21 @@ thread_rec (DWORD id, int get_context)
/* Add a thread to the thread list. */
static win32_thread_info *
-child_add_thread (DWORD tid, HANDLE h)
+child_add_thread (DWORD pid, DWORD tid, HANDLE h)
{
win32_thread_info *th;
+ ptid_t ptid = ptid_build (pid, tid, 0);
- if ((th = thread_rec (tid, FALSE)))
+ if ((th = thread_rec (ptid, FALSE)))
return th;
th = xcalloc (1, sizeof (*th));
th->tid = tid;
th->h = h;
- add_thread (tid, th, (unsigned int) tid);
+ add_thread (ptid, th);
set_inferior_regcache_data ((struct thread_info *)
- find_inferior_id (&all_threads, tid),
+ find_inferior_id (&all_threads, ptid),
new_register_cache ());
if (the_low_target.thread_added != NULL)
@@ -204,15 +211,17 @@ delete_thread_info (struct inferior_list_entry *thread)
/* Delete a thread from the list of threads. */
static void
-child_delete_thread (DWORD id)
+child_delete_thread (DWORD pid, DWORD tid)
{
struct inferior_list_entry *thread;
+ ptid_t ptid;
/* If the last thread is exiting, just return. */
if (all_threads.head == all_threads.tail)
return;
- thread = find_inferior_id (&all_threads, id);
+ ptid = ptid_build (pid, tid, 0);
+ thread = find_inferior_id (&all_threads, ptid);
if (thread == NULL)
return;
@@ -250,7 +259,7 @@ child_init_thread_list (void)
}
static void
-do_initial_child_stuff (HANDLE proch, DWORD pid)
+do_initial_child_stuff (HANDLE proch, DWORD pid, int attached)
{
last_sig = TARGET_SIGNAL_0;
@@ -263,6 +272,7 @@ do_initial_child_stuff (HANDLE proch, DWORD pid)
memset (&current_event, 0, sizeof (current_event));
+ add_process (pid, attached);
child_init_thread_list ();
if (the_low_target.initial_stuff != NULL)
@@ -320,7 +330,7 @@ static void
child_fetch_inferior_registers (int r)
{
int regno;
- win32_thread_info *th = thread_rec (current_inferior_tid (), TRUE);
+ win32_thread_info *th = thread_rec (current_inferior_ptid (), TRUE);
if (r == -1 || r == 0 || r > NUM_REGS)
child_fetch_inferior_registers (NUM_REGS);
else
@@ -334,7 +344,7 @@ static void
child_store_inferior_registers (int r)
{
int regno;
- win32_thread_info *th = thread_rec (current_inferior_tid (), TRUE);
+ win32_thread_info *th = thread_rec (current_inferior_ptid (), TRUE);
if (r == -1 || r == 0 || r > NUM_REGS)
child_store_inferior_registers (NUM_REGS);
else
@@ -540,7 +550,7 @@ win32_create_inferior (char *program, char **program_args)
CloseHandle (pi.hThread);
#endif
- do_initial_child_stuff (pi.hProcess, pi.dwProcessId);
+ do_initial_child_stuff (pi.hProcess, pi.dwProcessId, 0);
return current_process_id;
}
@@ -571,7 +581,7 @@ win32_attach (unsigned long pid)
/* win32_wait needs to know we're attaching. */
attaching = 1;
- do_initial_child_stuff (h, pid);
+ do_initial_child_stuff (h, pid, 1);
return 0;
}
@@ -639,11 +649,13 @@ win32_clear_inferiors (void)
}
/* Kill all inferiors. */
-static void
-win32_kill (void)
+static int
+win32_kill (int pid)
{
+ struct process_info *process;
+
if (current_process_handle == NULL)
- return;
+ return -1;
TerminateProcess (current_process_handle, 0);
for (;;)
@@ -662,12 +674,17 @@ win32_kill (void)
}
win32_clear_inferiors ();
+
+ process = find_process_pid (pid);
+ remove_process (process);
+ return 0;
}
-/* Detach from all inferiors. */
+/* Detach from inferior PID. */
static int
-win32_detach (void)
+win32_detach (int pid)
{
+ struct process_info *process;
winapi_DebugActiveProcessStop DebugActiveProcessStop = NULL;
winapi_DebugSetProcessKillOnExit DebugSetProcessKillOnExit = NULL;
#ifdef _WIN32_WCE
@@ -684,7 +701,7 @@ win32_detach (void)
{
struct thread_resume resume;
- resume.thread = -1;
+ resume.thread = minus_one_ptid;
resume.kind = resume_continue;
resume.sig = 0;
win32_resume (&resume, 1);
@@ -694,6 +711,8 @@ win32_detach (void)
return -1;
DebugSetProcessKillOnExit (FALSE);
+ process = find_process_pid (pid);
+ remove_process (process);
win32_clear_inferiors ();
return 0;
@@ -701,11 +720,9 @@ win32_detach (void)
/* Wait for inferiors to end. */
static void
-win32_join (void)
+win32_join (int pid)
{
- extern unsigned long signal_pid;
-
- HANDLE h = OpenProcess (PROCESS_ALL_ACCESS, FALSE, signal_pid);
+ HANDLE h = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid);
if (h != NULL)
{
WaitForSingleObject (h, INFINITE);
@@ -715,13 +732,13 @@ win32_join (void)
/* Return 1 iff the thread with thread ID TID is alive. */
static int
-win32_thread_alive (unsigned long tid)
+win32_thread_alive (ptid_t ptid)
{
int res;
/* Our thread list is reliable; don't bother to poll target
threads. */
- if (find_inferior_id (&all_threads, tid) != NULL)
+ if (find_inferior_id (&all_threads, ptid) != NULL)
res = 1;
else
res = 0;
@@ -738,11 +755,12 @@ win32_resume (struct thread_resume *resume_info, size_t n)
int step;
win32_thread_info *th;
DWORD continue_status = DBG_CONTINUE;
+ ptid_t ptid;
/* This handles the very limited set of resume packets that GDB can
currently produce. */
- if (n == 1 && resume_info[0].thread == -1)
+ if (n == 1 && ptid_equal (resume_info[0].thread, minus_one_ptid))
tid = -1;
else if (n > 1)
tid = -1;
@@ -751,7 +769,7 @@ win32_resume (struct thread_resume *resume_info, size_t n)
the Windows resume code do the right thing for thread switching. */
tid = current_event.dwThreadId;
- if (resume_info[0].thread != -1)
+ if (!ptid_equal (resume_info[0].thread, minus_one_ptid))
{
sig = resume_info[0].sig;
step = resume_info[0].kind == resume_step;
@@ -777,7 +795,8 @@ win32_resume (struct thread_resume *resume_info, size_t n)
last_sig = TARGET_SIGNAL_0;
/* Get context for the currently selected thread. */
- th = thread_rec (current_event.dwThreadId, FALSE);
+ ptid = debug_event_ptid (&current_event);
+ th = thread_rec (ptid, FALSE);
if (th)
{
if (th->context.ContextFlags)
@@ -1295,6 +1314,8 @@ auto_delete_breakpoint (CORE_ADDR stop_pc)
static int
get_child_debug_event (struct target_waitstatus *ourstatus)
{
+ ptid_t ptid;
+
last_sig = TARGET_SIGNAL_0;
ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
@@ -1349,9 +1370,9 @@ get_child_debug_event (struct target_waitstatus *ourstatus)
gotevent:
+ ptid = debug_event_ptid (&current_event);
current_inferior =
- (struct thread_info *) find_inferior_id (&all_threads,
- current_event.dwThreadId);
+ (struct thread_info *) find_inferior_id (&all_threads, ptid);
switch (current_event.dwDebugEventCode)
{
@@ -1362,8 +1383,9 @@ get_child_debug_event (struct target_waitstatus *ourstatus)
(unsigned) current_event.dwThreadId));
/* Record the existence of this thread. */
- child_add_thread (current_event.dwThreadId,
- current_event.u.CreateThread.hThread);
+ child_add_thread (current_event.dwProcessId,
+ current_event.dwThreadId,
+ current_event.u.CreateThread.hThread);
break;
case EXIT_THREAD_DEBUG_EVENT:
@@ -1371,7 +1393,8 @@ get_child_debug_event (struct target_waitstatus *ourstatus)
"for pid=%d tid=%x\n",
(unsigned) current_event.dwProcessId,
(unsigned) current_event.dwThreadId));
- child_delete_thread (current_event.dwThreadId);
+ child_delete_thread (current_event.dwProcessId,
+ current_event.dwThreadId);
break;
case CREATE_PROCESS_DEBUG_EVENT:
@@ -1388,10 +1411,11 @@ get_child_debug_event (struct target_waitstatus *ourstatus)
ourstatus->value.execd_pathname = "Main executable";
/* Add the main thread. */
- child_add_thread (main_thread_id,
+ child_add_thread (current_event.dwProcessId,
+ main_thread_id,
current_event.u.CreateProcessInfo.hThread);
- ourstatus->value.related_pid = current_event.dwThreadId;
+ ourstatus->value.related_pid = debug_event_ptid (&current_event);
#ifdef _WIN32_WCE
if (!attaching)
{
@@ -1467,17 +1491,18 @@ get_child_debug_event (struct target_waitstatus *ourstatus)
}
current_inferior =
- (struct thread_info *) find_inferior_id (&all_threads,
- current_event.dwThreadId);
+ (struct thread_info *) find_inferior_id (&all_threads, ptid);
return 1;
}
/* Wait for the inferior process to change state.
STATUS will be filled in with a response code to send to GDB.
Returns the signal which caused the process to stop. */
-static unsigned long
-win32_wait (struct target_waitstatus *ourstatus, int options)
+static ptid_t
+win32_wait (ptid_t ptid, struct target_waitstatus *ourstatus, int options)
{
+ struct process_info *process;
+
while (1)
{
if (!get_child_debug_event (ourstatus))
@@ -1489,8 +1514,10 @@ win32_wait (struct target_waitstatus *ourstatus, int options)
OUTMSG2 (("Child exited with retcode = %x\n",
ourstatus->value.integer));
+ process = find_process_pid (current_process_id);
+ remove_process (process);
win32_clear_inferiors ();
- return current_event.dwProcessId;
+ return pid_to_ptid (current_event.dwProcessId);
case TARGET_WAITKIND_STOPPED:
case TARGET_WAITKIND_LOADED:
OUTMSG2 (("Child Stopped with signal = %d \n",
@@ -1512,7 +1539,7 @@ win32_wait (struct target_waitstatus *ourstatus, int options)
if (ourstatus->kind == TARGET_WAITKIND_LOADED)
ourstatus->kind = TARGET_WAITKIND_STOPPED;
- return current_event.dwThreadId;
+ return debug_event_ptid (&current_event);
default:
OUTMSG (("Ignoring unknown internal event, %d\n", ourstatus->kind));
/* fall-through */