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.
This commit is contained in:
Pedro Alves 2009-04-01 22:50:24 +00:00
parent bd99dc8583
commit 95954743cb
16 changed files with 1586 additions and 458 deletions

View File

@ -1,3 +1,206 @@
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.
2009-04-01 Pedro Alves <pedro@codesourcery.com> 2009-04-01 Pedro Alves <pedro@codesourcery.com>
Non-stop mode support. Non-stop mode support.

View File

@ -66,8 +66,8 @@ typedef elf_gregset_t prgregset_t;
/* Structure that identifies the target process. */ /* Structure that identifies the target process. */
struct ps_prochandle struct ps_prochandle
{ {
/* The process id is all we need. */ /* We don't need to track anything. All context is served from the
pid_t pid; current inferior. */
}; };
#endif /* gdb_proc_service.h */ #endif /* gdb_proc_service.h */

View File

@ -30,12 +30,88 @@ struct thread_info
unsigned int gdb_id; unsigned int gdb_id;
}; };
struct inferior_list all_processes;
struct inferior_list all_threads; struct inferior_list all_threads;
struct inferior_list all_dlls; struct inferior_list all_dlls;
int dlls_changed; int dlls_changed;
struct thread_info *current_inferior; struct thread_info *current_inferior;
/* Oft used ptids */
ptid_t null_ptid;
ptid_t minus_one_ptid;
/* Create a ptid given the necessary PID, LWP, and TID components. */
ptid_t
ptid_build (int pid, long lwp, long tid)
{
ptid_t ptid;
ptid.pid = pid;
ptid.lwp = lwp;
ptid.tid = tid;
return ptid;
}
/* Create a ptid from just a pid. */
ptid_t
pid_to_ptid (int pid)
{
return ptid_build (pid, 0, 0);
}
/* Fetch the pid (process id) component from a ptid. */
int
ptid_get_pid (ptid_t ptid)
{
return ptid.pid;
}
/* Fetch the lwp (lightweight process) component from a ptid. */
long
ptid_get_lwp (ptid_t ptid)
{
return ptid.lwp;
}
/* Fetch the tid (thread id) component from a ptid. */
long
ptid_get_tid (ptid_t ptid)
{
return ptid.tid;
}
/* ptid_equal() is used to test equality of two ptids. */
int
ptid_equal (ptid_t ptid1, ptid_t ptid2)
{
return (ptid1.pid == ptid2.pid
&& ptid1.lwp == ptid2.lwp
&& ptid1.tid == ptid2.tid);
}
/* Return true if this ptid represents a process. */
int
ptid_is_pid (ptid_t ptid)
{
if (ptid_equal (minus_one_ptid, ptid))
return 0;
if (ptid_equal (null_ptid, ptid))
return 0;
return (ptid_get_pid (ptid) != 0
&& ptid_get_lwp (ptid) == 0
&& ptid_get_tid (ptid) == 0);
}
#define get_thread(inf) ((struct thread_info *)(inf)) #define get_thread(inf) ((struct thread_info *)(inf))
#define get_dll(inf) ((struct dll_info *)(inf)) #define get_dll(inf) ((struct dll_info *)(inf))
@ -93,7 +169,7 @@ remove_inferior (struct inferior_list *list,
} }
void void
add_thread (unsigned long thread_id, void *target_data, unsigned int gdb_id) add_thread (ptid_t thread_id, void *target_data)
{ {
struct thread_info *new_thread = xmalloc (sizeof (*new_thread)); struct thread_info *new_thread = xmalloc (sizeof (*new_thread));
@ -108,40 +184,38 @@ add_thread (unsigned long thread_id, void *target_data, unsigned int gdb_id)
new_thread->target_data = target_data; new_thread->target_data = target_data;
set_inferior_regcache_data (new_thread, new_register_cache ()); set_inferior_regcache_data (new_thread, new_register_cache ());
new_thread->gdb_id = gdb_id;
} }
unsigned int ptid_t
thread_id_to_gdb_id (unsigned long thread_id) thread_id_to_gdb_id (ptid_t thread_id)
{ {
struct inferior_list_entry *inf = all_threads.head; struct inferior_list_entry *inf = all_threads.head;
while (inf != NULL) while (inf != NULL)
{ {
struct thread_info *thread = get_thread (inf); if (ptid_equal (inf->id, thread_id))
if (inf->id == thread_id) return thread_id;
return thread->gdb_id;
inf = inf->next; inf = inf->next;
} }
return 0; return null_ptid;
} }
unsigned int ptid_t
thread_to_gdb_id (struct thread_info *thread) thread_to_gdb_id (struct thread_info *thread)
{ {
return thread->gdb_id; return thread->entry.id;
} }
struct thread_info * struct thread_info *
gdb_id_to_thread (unsigned int gdb_id) find_thread_pid (ptid_t ptid)
{ {
struct inferior_list_entry *inf = all_threads.head; struct inferior_list_entry *inf = all_threads.head;
while (inf != NULL) while (inf != NULL)
{ {
struct thread_info *thread = get_thread (inf); struct thread_info *thread = get_thread (inf);
if (thread->gdb_id == gdb_id) if (ptid_equal (thread->entry.id, ptid))
return thread; return thread;
inf = inf->next; inf = inf->next;
} }
@ -149,12 +223,12 @@ gdb_id_to_thread (unsigned int gdb_id)
return NULL; return NULL;
} }
unsigned long ptid_t
gdb_id_to_thread_id (unsigned int gdb_id) gdb_id_to_thread_id (ptid_t gdb_id)
{ {
struct thread_info *thread = gdb_id_to_thread (gdb_id); struct thread_info *thread = find_thread_pid (gdb_id);
return thread ? thread->entry.id : 0; return thread ? thread->entry.id : null_ptid;
} }
static void static void
@ -192,13 +266,13 @@ find_inferior (struct inferior_list *list,
} }
struct inferior_list_entry * struct inferior_list_entry *
find_inferior_id (struct inferior_list *list, unsigned long id) find_inferior_id (struct inferior_list *list, ptid_t id)
{ {
struct inferior_list_entry *inf = list->head; struct inferior_list_entry *inf = list->head;
while (inf != NULL) while (inf != NULL)
{ {
if (inf->id == id) if (ptid_equal (inf->id, id))
return inf; return inf;
inf = inf->next; inf = inf->next;
} }
@ -267,7 +341,7 @@ loaded_dll (const char *name, CORE_ADDR base_addr)
struct dll_info *new_dll = xmalloc (sizeof (*new_dll)); struct dll_info *new_dll = xmalloc (sizeof (*new_dll));
memset (new_dll, 0, sizeof (*new_dll)); memset (new_dll, 0, sizeof (*new_dll));
new_dll->entry.id = -1; new_dll->entry.id = minus_one_ptid;
new_dll->name = xstrdup (name); new_dll->name = xstrdup (name);
new_dll->base_addr = base_addr; new_dll->base_addr = base_addr;
@ -318,7 +392,7 @@ add_pid_to_list (struct inferior_list *list, unsigned long pid)
struct inferior_list_entry *new_entry; struct inferior_list_entry *new_entry;
new_entry = xmalloc (sizeof (struct inferior_list_entry)); new_entry = xmalloc (sizeof (struct inferior_list_entry));
new_entry->id = pid; new_entry->id = pid_to_ptid (pid);
add_inferior_to_list (list, new_entry); add_inferior_to_list (list, new_entry);
} }
@ -327,7 +401,7 @@ pull_pid_from_list (struct inferior_list *list, unsigned long pid)
{ {
struct inferior_list_entry *new_entry; struct inferior_list_entry *new_entry;
new_entry = find_inferior_id (list, pid); new_entry = find_inferior_id (list, pid_to_ptid (pid));
if (new_entry == NULL) if (new_entry == NULL)
return 0; return 0;
else else
@ -337,3 +411,56 @@ pull_pid_from_list (struct inferior_list *list, unsigned long pid)
return 1; return 1;
} }
} }
struct process_info *
add_process (int pid, int attached)
{
struct process_info *process;
process = xcalloc (1, sizeof (*process));
process->head.id = pid_to_ptid (pid);
process->attached = attached;
add_inferior_to_list (&all_processes, &process->head);
return process;
}
void
remove_process (struct process_info *process)
{
clear_symbol_cache (&process->symbol_cache);
free_all_breakpoints (process);
remove_inferior (&all_processes, &process->head);
}
struct process_info *
find_process_pid (int pid)
{
return (struct process_info *)
find_inferior_id (&all_processes, pid_to_ptid (pid));
}
static struct process_info *
get_thread_process (struct thread_info *thread)
{
int pid = ptid_get_pid (thread->entry.id);
return find_process_pid (pid);
}
struct process_info *
current_process (void)
{
if (current_inferior == NULL)
fatal ("Current inferior requested, but current_inferior is NULL\n");
return get_thread_process (current_inferior);
}
void
initialize_inferiors (void)
{
null_ptid = ptid_build (0, 0, 0);
minus_one_ptid = ptid_build (-1, 0, 0);
}

File diff suppressed because it is too large Load Diff

View File

@ -21,6 +21,8 @@
#include <thread_db.h> #include <thread_db.h>
#endif #endif
#include "gdb_proc_service.h"
#ifdef HAVE_LINUX_REGSETS #ifdef HAVE_LINUX_REGSETS
typedef void (*regset_fill_func) (void *); typedef void (*regset_fill_func) (void *);
typedef void (*regset_store_func) (const void *); typedef void (*regset_store_func) (const void *);
@ -41,6 +43,19 @@ struct regset_info
extern struct regset_info target_regsets[]; extern struct regset_info target_regsets[];
#endif #endif
struct process_info_private
{
/* True if this process has loaded thread_db, and it is active. */
int thread_db_active;
/* Structure that identifies the child process for the
<proc_service.h> interface. */
struct ps_prochandle proc_handle;
/* Connection to the libthread_db library. */
td_thragent_t *thread_agent;
};
struct linux_target_ops struct linux_target_ops
{ {
/* Architecture-specific setup. */ /* Architecture-specific setup. */
@ -78,14 +93,14 @@ struct linux_target_ops
extern struct linux_target_ops the_low_target; extern struct linux_target_ops the_low_target;
#define pid_of(proc) ((proc)->head.id) #define pid_of(proc) ptid_get_pid ((proc)->head.id)
#define lwpid_of(proc) ((proc)->head.id) #define lwpid_of(proc) ptid_get_lwp ((proc)->head.id)
#define get_lwp(inf) ((struct lwp_info *)(inf)) #define get_lwp(inf) ((struct lwp_info *)(inf))
#define get_thread_lwp(thr) (get_lwp (inferior_target_data (thr))) #define get_thread_lwp(thr) (get_lwp (inferior_target_data (thr)))
#define get_lwp_thread(proc) ((struct thread_info *) \ #define get_lwp_thread(proc) ((struct thread_info *) \
find_inferior_id (&all_threads, \ find_inferior_id (&all_threads, \
lwpid_of (get_lwp (proc)))) get_lwp (proc)->head.id))
struct lwp_info struct lwp_info
{ {
@ -106,6 +121,11 @@ struct lwp_info
event already received in a wait()). */ event already received in a wait()). */
int stopped; int stopped;
/* If this flag is set, the lwp is known to be dead already (exit
event already received in a wait(), and is cached in
status_pending). */
int dead;
/* When stopped is set, the last wait status recorded for this lwp. */ /* When stopped is set, the last wait status recorded for this lwp. */
int last_status; int last_status;
@ -150,3 +170,5 @@ void linux_attach_lwp (unsigned long pid);
int thread_db_init (int use_events); int thread_db_init (int use_events);
int thread_db_get_tls_address (struct thread_info *thread, CORE_ADDR offset, int thread_db_get_tls_address (struct thread_info *thread, CORE_ADDR offset,
CORE_ADDR load_module, CORE_ADDR *address); CORE_ADDR load_module, CORE_ADDR *address);
struct lwp_info *find_lwp_pid (ptid_t ptid);

View File

@ -46,11 +46,10 @@ struct breakpoint
int (*handler) (CORE_ADDR); int (*handler) (CORE_ADDR);
}; };
struct breakpoint *breakpoints;
void void
set_breakpoint_at (CORE_ADDR where, int (*handler) (CORE_ADDR)) set_breakpoint_at (CORE_ADDR where, int (*handler) (CORE_ADDR))
{ {
struct process_info *proc = current_process ();
struct breakpoint *bp; struct breakpoint *bp;
if (breakpoint_data == NULL) if (breakpoint_data == NULL)
@ -67,24 +66,25 @@ set_breakpoint_at (CORE_ADDR where, int (*handler) (CORE_ADDR))
bp->pc = where; bp->pc = where;
bp->handler = handler; bp->handler = handler;
bp->next = breakpoints; bp->next = proc->breakpoints;
breakpoints = bp; proc->breakpoints = bp;
} }
static void static void
delete_breakpoint (struct breakpoint *bp) delete_breakpoint (struct breakpoint *bp)
{ {
struct process_info *proc = current_process ();
struct breakpoint *cur; struct breakpoint *cur;
if (breakpoints == bp) if (proc->breakpoints == bp)
{ {
breakpoints = bp->next; proc->breakpoints = bp->next;
(*the_target->write_memory) (bp->pc, bp->old_data, (*the_target->write_memory) (bp->pc, bp->old_data,
breakpoint_len); breakpoint_len);
free (bp); free (bp);
return; return;
} }
cur = breakpoints; cur = proc->breakpoints;
while (cur->next) while (cur->next)
{ {
if (cur->next == bp) if (cur->next == bp)
@ -102,7 +102,8 @@ delete_breakpoint (struct breakpoint *bp)
static struct breakpoint * static struct breakpoint *
find_breakpoint_at (CORE_ADDR where) find_breakpoint_at (CORE_ADDR where)
{ {
struct breakpoint *bp = breakpoints; struct process_info *proc = current_process ();
struct breakpoint *bp = proc->breakpoints;
while (bp != NULL) while (bp != NULL)
{ {
@ -225,7 +226,8 @@ set_breakpoint_data (const unsigned char *bp_data, int bp_len)
void void
check_mem_read (CORE_ADDR mem_addr, unsigned char *buf, int mem_len) check_mem_read (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
{ {
struct breakpoint *bp = breakpoints; struct process_info *proc = current_process ();
struct breakpoint *bp = proc->breakpoints;
CORE_ADDR mem_end = mem_addr + mem_len; CORE_ADDR mem_end = mem_addr + mem_len;
for (; bp != NULL; bp = bp->next) for (; bp != NULL; bp = bp->next)
@ -258,7 +260,8 @@ check_mem_read (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
void void
check_mem_write (CORE_ADDR mem_addr, unsigned char *buf, int mem_len) check_mem_write (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
{ {
struct breakpoint *bp = breakpoints; struct process_info *proc = current_process ();
struct breakpoint *bp = proc->breakpoints;
CORE_ADDR mem_end = mem_addr + mem_len; CORE_ADDR mem_end = mem_addr + mem_len;
for (; bp != NULL; bp = bp->next) for (; bp != NULL; bp = bp->next)
@ -290,11 +293,29 @@ check_mem_write (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
} }
} }
/* Delete all breakpoints. */ /* Delete all breakpoints, and un-insert them from the inferior. */
void void
delete_all_breakpoints (void) delete_all_breakpoints (void)
{ {
while (breakpoints) struct process_info *proc = current_process ();
delete_breakpoint (breakpoints);
while (proc->breakpoints)
delete_breakpoint (proc->breakpoints);
}
/* Release all breakpoints, but do not try to un-insert them from the
inferior. */
void
free_all_breakpoints (struct process_info *proc)
{
struct breakpoint *bp;
while (proc->breakpoints)
{
bp = proc->breakpoints;
proc->breakpoints = bp->next;
free (bp);
}
} }

View File

@ -75,4 +75,9 @@ void set_breakpoint_data (const unsigned char *bp_data, int bp_len);
void delete_all_breakpoints (void); void delete_all_breakpoints (void);
/* Delete all breakpoints, but do not try to un-insert them from the
inferior. */
void free_all_breakpoints (struct process_info *proc);
#endif /* MEM_BREAK_H */ #endif /* MEM_BREAK_H */

View File

@ -102,8 +102,7 @@ ps_lgetregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, prgregset_t gregset)
struct lwp_info *lwp; struct lwp_info *lwp;
struct thread_info *reg_inferior, *save_inferior; struct thread_info *reg_inferior, *save_inferior;
lwp = (struct lwp_info *) find_inferior_id (&all_lwps, lwp = find_lwp_pid (pid_to_ptid (lwpid));
lwpid);
if (lwp == NULL) if (lwp == NULL)
return PS_ERR; return PS_ERR;
@ -157,5 +156,5 @@ ps_lsetfpregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, void *fpregset)
pid_t pid_t
ps_getpid (gdb_ps_prochandle_t ph) ps_getpid (gdb_ps_prochandle_t ph)
{ {
return ph->pid; return pid_of (get_thread_lwp (current_inferior));
} }

View File

@ -79,18 +79,11 @@ typedef int socklen_t;
/* A cache entry for a successfully looked-up symbol. */ /* A cache entry for a successfully looked-up symbol. */
struct sym_cache struct sym_cache
{ {
const char *name; char *name;
CORE_ADDR addr; CORE_ADDR addr;
struct sym_cache *next; struct sym_cache *next;
}; };
/* The symbol cache. */
static struct sym_cache *symbol_cache;
/* If this flag has been set, assume cache misses are
failures. */
int all_symbols_looked_up;
int remote_debug = 0; int remote_debug = 0;
struct ui_file *gdb_stdlog; struct ui_file *gdb_stdlog;
@ -317,6 +310,29 @@ fromhex (int a)
return 0; return 0;
} }
static const char hexchars[] = "0123456789abcdef";
static int
ishex (int ch, int *val)
{
if ((ch >= 'a') && (ch <= 'f'))
{
*val = ch - 'a' + 10;
return 1;
}
if ((ch >= 'A') && (ch <= 'F'))
{
*val = ch - 'A' + 10;
return 1;
}
if ((ch >= '0') && (ch <= '9'))
{
*val = ch - '0';
return 1;
}
return 0;
}
int int
unhexify (char *bin, const char *hex, int count) unhexify (char *bin, const char *hex, int count)
{ {
@ -523,6 +539,103 @@ try_rle (char *buf, int remaining, unsigned char *csum, char **p)
return n + 1; return n + 1;
} }
char *
unpack_varlen_hex (char *buff, /* packet to parse */
ULONGEST *result)
{
int nibble;
ULONGEST retval = 0;
while (ishex (*buff, &nibble))
{
buff++;
retval = retval << 4;
retval |= nibble & 0x0f;
}
*result = retval;
return buff;
}
/* Write a PTID to BUF. Returns BUF+CHARACTERS_WRITTEN. */
char *
write_ptid (char *buf, ptid_t ptid)
{
int pid, tid;
if (multi_process)
{
pid = ptid_get_pid (ptid);
if (pid < 0)
buf += sprintf (buf, "p-%x.", -pid);
else
buf += sprintf (buf, "p%x.", pid);
}
tid = ptid_get_lwp (ptid);
if (tid < 0)
buf += sprintf (buf, "-%x", -tid);
else
buf += sprintf (buf, "%x", tid);
return buf;
}
ULONGEST
hex_or_minus_one (char *buf, char **obuf)
{
ULONGEST ret;
if (strncmp (buf, "-1", 2) == 0)
{
ret = (ULONGEST) -1;
buf += 2;
}
else
buf = unpack_varlen_hex (buf, &ret);
if (obuf)
*obuf = buf;
return ret;
}
/* Extract a PTID from BUF. If non-null, OBUF is set to the to one
passed the last parsed char. Returns null_ptid on error. */
ptid_t
read_ptid (char *buf, char **obuf)
{
char *p = buf;
char *pp;
ULONGEST pid = 0, tid = 0;
if (*p == 'p')
{
/* Multi-process ptid. */
pp = unpack_varlen_hex (p + 1, &pid);
if (*pp != '.')
error ("invalid remote ptid: %s\n", p);
p = pp + 1;
tid = hex_or_minus_one (p, &pp);
if (obuf)
*obuf = pp;
return ptid_build (pid, tid, 0);
}
/* No multi-process. Just a tid. */
tid = hex_or_minus_one (p, &pp);
/* Since the stub is not sending a process id, then default to
what's in the current inferior. */
pid = ptid_get_pid (((struct inferior_list_entry *) current_inferior)->id);
if (obuf)
*obuf = pp;
return ptid_build (pid, tid, 0);
}
/* Send a packet to the remote machine, with error checking. /* Send a packet to the remote machine, with error checking.
The data of the packet is in BUF, and the length of the The data of the packet is in BUF, and the length of the
packet is in CNT. Returns >= 0 on success, -1 otherwise. */ packet is in CNT. Returns >= 0 on success, -1 otherwise. */
@ -957,12 +1070,12 @@ dead_thread_notify (int id)
} }
void void
prepare_resume_reply (char *buf, unsigned long ptid, prepare_resume_reply (char *buf, ptid_t ptid,
struct target_waitstatus *status) struct target_waitstatus *status)
{ {
if (debug_threads) if (debug_threads)
fprintf (stderr, "Writing resume reply for %lu:%d\n\n", fprintf (stderr, "Writing resume reply for %s:%d\n\n",
ptid, status->kind); target_pid_to_str (ptid), status->kind);
switch (status->kind) switch (status->kind)
{ {
@ -978,7 +1091,7 @@ prepare_resume_reply (char *buf, unsigned long ptid,
saved_inferior = current_inferior; saved_inferior = current_inferior;
current_inferior = gdb_id_to_thread (ptid); current_inferior = find_thread_pid (ptid);
if (the_target->stopped_by_watchpoint != NULL if (the_target->stopped_by_watchpoint != NULL
&& (*the_target->stopped_by_watchpoint) ()) && (*the_target->stopped_by_watchpoint) ())
@ -1021,13 +1134,16 @@ prepare_resume_reply (char *buf, unsigned long ptid,
in GDB will claim this event belongs to inferior_ptid in GDB will claim this event belongs to inferior_ptid
if we do not specify a thread, and there's no way for if we do not specify a thread, and there's no way for
gdbserver to know what inferior_ptid is. */ gdbserver to know what inferior_ptid is. */
if (1 || general_thread != ptid) if (1 || !ptid_equal (general_thread, ptid))
{ {
/* In non-stop, don't change the general thread behind /* In non-stop, don't change the general thread behind
GDB's back. */ GDB's back. */
if (!non_stop) if (!non_stop)
general_thread = ptid; general_thread = ptid;
sprintf (buf, "thread:%lx;", ptid); sprintf (buf, "thread:");
buf += strlen (buf);
buf = write_ptid (buf, ptid);
strcat (buf, ";");
buf += strlen (buf); buf += strlen (buf);
} }
} }
@ -1043,10 +1159,18 @@ prepare_resume_reply (char *buf, unsigned long ptid,
} }
break; break;
case TARGET_WAITKIND_EXITED: case TARGET_WAITKIND_EXITED:
sprintf (buf, "W%02x", status->value.integer); if (multi_process)
sprintf (buf, "W%x;process:%x",
status->value.integer, ptid_get_pid (ptid));
else
sprintf (buf, "W%02x", status->value.integer);
break; break;
case TARGET_WAITKIND_SIGNALLED: case TARGET_WAITKIND_SIGNALLED:
sprintf (buf, "X%02x", status->value.sig); if (multi_process)
sprintf (buf, "X%x;process:%x",
status->value.sig, ptid_get_pid (ptid));
else
sprintf (buf, "X%02x", status->value.sig);
break; break;
default: default:
error ("unhandled waitkind"); error ("unhandled waitkind");
@ -1174,6 +1298,31 @@ decode_search_memory_packet (const char *buf, int packet_len,
return 0; return 0;
} }
static void
free_sym_cache (struct sym_cache *sym)
{
if (sym != NULL)
{
free (sym->name);
free (sym);
}
}
void
clear_symbol_cache (struct sym_cache **symcache_p)
{
struct sym_cache *sym, *next;
/* Check the cache first. */
for (sym = *symcache_p; sym; sym = next)
{
next = sym->next;
free_sym_cache (sym);
}
*symcache_p = NULL;
}
/* Ask GDB for the address of NAME, and return it in ADDRP if found. /* Ask GDB for the address of NAME, and return it in ADDRP if found.
Returns 1 if the symbol is found, 0 if it is not, -1 on error. */ Returns 1 if the symbol is found, 0 if it is not, -1 on error. */
@ -1183,9 +1332,12 @@ look_up_one_symbol (const char *name, CORE_ADDR *addrp)
char own_buf[266], *p, *q; char own_buf[266], *p, *q;
int len; int len;
struct sym_cache *sym; struct sym_cache *sym;
struct process_info *proc;
proc = current_process ();
/* Check the cache first. */ /* Check the cache first. */
for (sym = symbol_cache; sym; sym = sym->next) for (sym = proc->symbol_cache; sym; sym = sym->next)
if (strcmp (name, sym->name) == 0) if (strcmp (name, sym->name) == 0)
{ {
*addrp = sym->addr; *addrp = sym->addr;
@ -1197,7 +1349,7 @@ look_up_one_symbol (const char *name, CORE_ADDR *addrp)
in any libraries loaded after that point, only in symbols in in any libraries loaded after that point, only in symbols in
libpthread.so. It might not be an appropriate time to look libpthread.so. It might not be an appropriate time to look
up a symbol, e.g. while we're trying to fetch registers. */ up a symbol, e.g. while we're trying to fetch registers. */
if (all_symbols_looked_up) if (proc->all_symbols_looked_up)
return 0; return 0;
/* Send the request. */ /* Send the request. */
@ -1257,8 +1409,8 @@ look_up_one_symbol (const char *name, CORE_ADDR *addrp)
sym = xmalloc (sizeof (*sym)); sym = xmalloc (sizeof (*sym));
sym->name = xstrdup (name); sym->name = xstrdup (name);
sym->addr = *addrp; sym->addr = *addrp;
sym->next = symbol_cache; sym->next = proc->symbol_cache;
symbol_cache = sym; proc->symbol_cache = sym;
return 1; return 1;
} }

View File

@ -32,17 +32,17 @@
#include <malloc.h> #include <malloc.h>
#endif #endif
unsigned long cont_thread; ptid_t cont_thread;
unsigned long general_thread; ptid_t general_thread;
unsigned long step_thread; ptid_t step_thread;
int server_waiting; int server_waiting;
static int extended_protocol; static int extended_protocol;
static int attached;
static int response_needed; static int response_needed;
static int exit_requested; static int exit_requested;
int multi_process;
int non_stop; int non_stop;
static char **program_argv, **wrapper_argv; static char **program_argv, **wrapper_argv;
@ -90,7 +90,7 @@ int disable_packet_qfThreadInfo;
/* Last status reported to GDB. */ /* Last status reported to GDB. */
static struct target_waitstatus last_status; static struct target_waitstatus last_status;
static unsigned long last_ptid; static ptid_t last_ptid;
static char *own_buf; static char *own_buf;
static unsigned char *mem_buf; static unsigned char *mem_buf;
@ -104,7 +104,7 @@ struct vstop_notif
struct vstop_notif *next; struct vstop_notif *next;
/* Thread or process that got the event. */ /* Thread or process that got the event. */
unsigned long ptid; ptid_t ptid;
/* Event info. */ /* Event info. */
struct target_waitstatus status; struct target_waitstatus status;
@ -116,7 +116,7 @@ static struct vstop_notif *notif_queue = NULL;
/* Put a stop reply to the stop reply queue. */ /* Put a stop reply to the stop reply queue. */
static void static void
queue_stop_reply (unsigned long ptid, struct target_waitstatus *status) queue_stop_reply (ptid_t ptid, struct target_waitstatus *status)
{ {
struct vstop_notif *new_notif; struct vstop_notif *new_notif;
@ -153,7 +153,7 @@ queue_stop_reply (unsigned long ptid, struct target_waitstatus *status)
we aren't sending one yet. */ we aren't sending one yet. */
void void
push_event (unsigned long ptid, struct target_waitstatus *status) push_event (ptid_t ptid, struct target_waitstatus *status)
{ {
queue_stop_reply (ptid, status); queue_stop_reply (ptid, status);
@ -170,19 +170,30 @@ push_event (unsigned long ptid, struct target_waitstatus *status)
} }
} }
/* Get rid of the currently pending stop replies. */ /* Get rid of the currently pending stop replies for PID. If PID is
-1, then apply to all processes. */
static void static void
discard_queued_stop_replies (void) discard_queued_stop_replies (int pid)
{ {
struct vstop_notif *next; struct vstop_notif *prev = NULL, *reply, *next;
while (notif_queue) for (reply = notif_queue; reply; reply = next)
{ {
next = notif_queue->next; next = reply->next;
notif_queue = next;
free (next); if (pid == -1
|| ptid_get_pid (reply->ptid) == pid)
{
if (reply == notif_queue)
notif_queue = next;
else
prev->next = reply->next;
free (reply);
}
else
prev = reply;
} }
} }
@ -209,7 +220,6 @@ static int
start_inferior (char **argv) start_inferior (char **argv)
{ {
char **new_argv = argv; char **new_argv = argv;
attached = 0;
if (wrapper_argv != NULL) if (wrapper_argv != NULL)
{ {
@ -253,13 +263,13 @@ start_inferior (char **argv)
if (wrapper_argv != NULL) if (wrapper_argv != NULL)
{ {
struct thread_resume resume_info; struct thread_resume resume_info;
unsigned long ptid; ptid_t ptid;
resume_info.thread = -1; resume_info.thread = pid_to_ptid (signal_pid);
resume_info.kind = resume_continue; resume_info.kind = resume_continue;
resume_info.sig = 0; resume_info.sig = 0;
ptid = mywait (&last_status, 0, 0); ptid = mywait (pid_to_ptid (signal_pid), &last_status, 0, 0);
if (last_status.kind != TARGET_WAITKIND_STOPPED) if (last_status.kind != TARGET_WAITKIND_STOPPED)
return signal_pid; return signal_pid;
@ -268,7 +278,7 @@ start_inferior (char **argv)
{ {
(*the_target->resume) (&resume_info, 1); (*the_target->resume) (&resume_info, 1);
mywait (&last_status, 0, 0); mywait (pid_to_ptid (signal_pid), &last_status, 0, 0);
if (last_status.kind != TARGET_WAITKIND_STOPPED) if (last_status.kind != TARGET_WAITKIND_STOPPED)
return signal_pid; return signal_pid;
} }
@ -279,7 +289,7 @@ start_inferior (char **argv)
/* Wait till we are at 1st instruction in program, return new pid /* Wait till we are at 1st instruction in program, return new pid
(assuming success). */ (assuming success). */
last_ptid = mywait (&last_status, 0, 0); last_ptid = mywait (pid_to_ptid (signal_pid), &last_status, 0, 0);
return signal_pid; return signal_pid;
} }
@ -293,8 +303,6 @@ attach_inferior (int pid)
if (myattach (pid) != 0) if (myattach (pid) != 0)
return -1; return -1;
attached = 1;
fprintf (stderr, "Attached; pid = %d\n", pid); fprintf (stderr, "Attached; pid = %d\n", pid);
fflush (stderr); fflush (stderr);
@ -305,7 +313,7 @@ attach_inferior (int pid)
if (!non_stop) if (!non_stop)
{ {
last_ptid = mywait (&last_status, 0, 0); last_ptid = mywait (pid_to_ptid (pid), &last_status, 0, 0);
/* GDB knows to ignore the first SIGSTOP after attaching to a running /* GDB knows to ignore the first SIGSTOP after attaching to a running
process using the "attach" command, but this is different; it's process using the "attach" command, but this is different; it's
@ -656,10 +664,11 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
/* Reply the current thread id. */ /* Reply the current thread id. */
if (strcmp ("qC", own_buf) == 0 && !disable_packet_qC) if (strcmp ("qC", own_buf) == 0 && !disable_packet_qC)
{ {
unsigned long gdb_id; ptid_t gdb_id;
require_running (own_buf); require_running (own_buf);
if (general_thread != 0 && general_thread != -1) if (!ptid_equal (general_thread, null_ptid)
&& !ptid_equal (general_thread, minus_one_ptid))
gdb_id = general_thread; gdb_id = general_thread;
else else
{ {
@ -667,7 +676,9 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
gdb_id = thread_to_gdb_id ((struct thread_info *)thread_ptr); gdb_id = thread_to_gdb_id ((struct thread_info *)thread_ptr);
} }
sprintf (own_buf, "QC%lx", gdb_id); sprintf (own_buf, "QC");
own_buf += 2;
own_buf = write_ptid (own_buf, gdb_id);
return; return;
} }
@ -684,21 +695,28 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
{ {
if (strcmp ("qfThreadInfo", own_buf) == 0) if (strcmp ("qfThreadInfo", own_buf) == 0)
{ {
ptid_t gdb_id;
require_running (own_buf); require_running (own_buf);
thread_ptr = all_threads.head; thread_ptr = all_threads.head;
sprintf (own_buf, "m%x",
thread_to_gdb_id ((struct thread_info *)thread_ptr)); *own_buf++ = 'm';
gdb_id = thread_to_gdb_id ((struct thread_info *)thread_ptr);
write_ptid (own_buf, gdb_id);
thread_ptr = thread_ptr->next; thread_ptr = thread_ptr->next;
return; return;
} }
if (strcmp ("qsThreadInfo", own_buf) == 0) if (strcmp ("qsThreadInfo", own_buf) == 0)
{ {
ptid_t gdb_id;
require_running (own_buf); require_running (own_buf);
if (thread_ptr != NULL) if (thread_ptr != NULL)
{ {
sprintf (own_buf, "m%x", *own_buf++ = 'm';
thread_to_gdb_id ((struct thread_info *)thread_ptr)); gdb_id = thread_to_gdb_id ((struct thread_info *)thread_ptr);
write_ptid (own_buf, gdb_id);
thread_ptr = thread_ptr->next; thread_ptr = thread_ptr->next;
return; return;
} }
@ -1046,6 +1064,21 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
if (strncmp ("qSupported", own_buf, 10) == 0 if (strncmp ("qSupported", own_buf, 10) == 0
&& (own_buf[10] == ':' || own_buf[10] == '\0')) && (own_buf[10] == ':' || own_buf[10] == '\0'))
{ {
char *p = &own_buf[10];
/* Process each feature being provided by GDB. The first
feature will follow a ':', and latter features will follow
';'. */
if (*p == ':')
for (p = strtok (p + 1, ";");
p != NULL;
p = strtok (NULL, ";"))
{
/* Record if GDB knows about multiprocess support. */
if (strcmp (p, "multiprocess+") == 0)
multi_process = 1;
}
sprintf (own_buf, "PacketSize=%x;QPassSignals+", PBUFSIZ - 1); sprintf (own_buf, "PacketSize=%x;QPassSignals+", PBUFSIZ - 1);
/* We do not have any hook to indicate whether the target backend /* We do not have any hook to indicate whether the target backend
@ -1073,6 +1106,8 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
if (the_target->qxfer_osdata != NULL) if (the_target->qxfer_osdata != NULL)
strcat (own_buf, ";qXfer:osdata:read+"); strcat (own_buf, ";qXfer:osdata:read+");
strcat (own_buf, ";multiprocess+");
if (target_supports_non_stop ()) if (target_supports_non_stop ())
strcat (own_buf, ";QNonStop+"); strcat (own_buf, ";QNonStop+");
@ -1086,7 +1121,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
char *p = own_buf + 12; char *p = own_buf + 12;
CORE_ADDR parts[2], address = 0; CORE_ADDR parts[2], address = 0;
int i, err; int i, err;
unsigned long ptid = 0; ptid_t ptid = null_ptid;
require_running (own_buf); require_running (own_buf);
@ -1111,7 +1146,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
} }
if (i == 0) if (i == 0)
ptid = strtoul (p, NULL, 16); ptid = read_ptid (p, NULL);
else else
decode_address (&parts[i - 1], p, len); decode_address (&parts[i - 1], p, len);
p = p2; p = p2;
@ -1121,7 +1156,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
err = 1; err = 1;
else else
{ {
struct thread_info *thread = gdb_id_to_thread (ptid); struct thread_info *thread = find_thread_pid (ptid);
if (thread == NULL) if (thread == NULL)
err = 2; err = 2;
@ -1208,10 +1243,30 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
return; return;
} }
if (strcmp (own_buf, "qAttached") == 0) if (strcmp (own_buf, "qAttached") == 0
|| strncmp (own_buf, "qAttached:", sizeof ("qAttached:") - 1) == 0)
{ {
require_running (own_buf); struct process_info *process;
strcpy (own_buf, attached ? "1" : "0");
if (own_buf[sizeof ("qAttached") - 1])
{
int pid = strtoul (own_buf + sizeof ("qAttached:") - 1, NULL, 16);
process = (struct process_info *)
find_inferior_id (&all_processes, pid_to_ptid (pid));
}
else
{
require_running (own_buf);
process = current_process ();
}
if (process == NULL)
{
write_enn (own_buf);
return;
}
strcpy (own_buf, process->attached ? "1" : "0");
return; return;
} }
@ -1227,7 +1282,7 @@ handle_v_cont (char *own_buf)
char *p, *q; char *p, *q;
int n = 0, i = 0; int n = 0, i = 0;
struct thread_resume *resume_info; struct thread_resume *resume_info;
struct thread_resume default_action = {0}; struct thread_resume default_action = {{0}};
/* Count the number of semicolons in the packet. There should be one /* Count the number of semicolons in the packet. There should be one
for every action. */ for every action. */
@ -1277,7 +1332,7 @@ handle_v_cont (char *own_buf)
if (p[0] == 0) if (p[0] == 0)
{ {
resume_info[i].thread = -1; resume_info[i].thread = minus_one_ptid;
default_action = resume_info[i]; default_action = resume_info[i];
/* Note: we don't increment i here, we'll overwrite this entry /* Note: we don't increment i here, we'll overwrite this entry
@ -1285,8 +1340,7 @@ handle_v_cont (char *own_buf)
} }
else if (p[0] == ':') else if (p[0] == ':')
{ {
unsigned int gdb_id = strtoul (p + 1, &q, 16); ptid_t ptid = read_ptid (p + 1, &q);
unsigned long thread_id;
if (p == q) if (p == q)
goto err; goto err;
@ -1294,11 +1348,7 @@ handle_v_cont (char *own_buf)
if (p[0] != ';' && p[0] != 0) if (p[0] != ';' && p[0] != 0)
goto err; goto err;
thread_id = gdb_id_to_thread_id (gdb_id); resume_info[i].thread = ptid;
if (thread_id)
resume_info[i].thread = thread_id;
else
goto err;
i++; i++;
} }
@ -1309,11 +1359,11 @@ handle_v_cont (char *own_buf)
/* Still used in occasional places in the backend. */ /* Still used in occasional places in the backend. */
if (n == 1 if (n == 1
&& resume_info[0].thread != -1 && !ptid_equal (resume_info[0].thread, minus_one_ptid)
&& resume_info[0].kind != resume_stop) && resume_info[0].kind != resume_stop)
cont_thread = resume_info[0].thread; cont_thread = resume_info[0].thread;
else else
cont_thread = -1; cont_thread = minus_one_ptid;
set_desired_inferior (0); set_desired_inferior (0);
if (!non_stop) if (!non_stop)
@ -1327,7 +1377,7 @@ handle_v_cont (char *own_buf)
write_ok (own_buf); write_ok (own_buf);
else else
{ {
last_ptid = mywait (&last_status, 0, 1); last_ptid = mywait (minus_one_ptid, &last_status, 0, 1);
prepare_resume_reply (own_buf, last_ptid, &last_status); prepare_resume_reply (own_buf, last_ptid, &last_status);
disable_async_io (); disable_async_io ();
} }
@ -1462,6 +1512,30 @@ handle_v_run (char *own_buf)
} }
} }
/* Kill process. Return 1 if successful, 0 if failure. */
int
handle_v_kill (char *own_buf)
{
int pid;
char *p = &own_buf[6];
pid = strtol (p, NULL, 16);
if (pid != 0 && kill_inferior (pid) == 0)
{
last_status.kind = TARGET_WAITKIND_SIGNALLED;
last_status.value.sig = TARGET_SIGNAL_KILL;
last_ptid = pid_to_ptid (pid);
discard_queued_stop_replies (pid);
write_ok (own_buf);
return 1;
}
else
{
write_enn (own_buf);
return 0;
}
}
/* Handle a 'vStopped' packet. */ /* Handle a 'vStopped' packet. */
static void static void
handle_v_stopped (char *own_buf) handle_v_stopped (char *own_buf)
@ -1473,7 +1547,8 @@ handle_v_stopped (char *own_buf)
struct vstop_notif *head; struct vstop_notif *head;
if (remote_debug) if (remote_debug)
fprintf (stderr, "vStopped: acking %ld\n", notif_queue->ptid); fprintf (stderr, "vStopped: acking %s\n",
target_pid_to_str (notif_queue->ptid));
head = notif_queue; head = notif_queue;
notif_queue = notif_queue->next; notif_queue = notif_queue->next;
@ -1510,7 +1585,7 @@ handle_v_requests (char *own_buf, int packet_len, int *new_packet_len)
if (strncmp (own_buf, "vAttach;", 8) == 0) if (strncmp (own_buf, "vAttach;", 8) == 0)
{ {
if (target_running ()) if (!multi_process && target_running ())
{ {
fprintf (stderr, "Already debugging a process\n"); fprintf (stderr, "Already debugging a process\n");
write_enn (own_buf); write_enn (own_buf);
@ -1522,7 +1597,7 @@ handle_v_requests (char *own_buf, int packet_len, int *new_packet_len)
if (strncmp (own_buf, "vRun;", 5) == 0) if (strncmp (own_buf, "vRun;", 5) == 0)
{ {
if (target_running ()) if (!multi_process && target_running ())
{ {
fprintf (stderr, "Already debugging a process\n"); fprintf (stderr, "Already debugging a process\n");
write_enn (own_buf); write_enn (own_buf);
@ -1532,6 +1607,18 @@ handle_v_requests (char *own_buf, int packet_len, int *new_packet_len)
return; return;
} }
if (strncmp (own_buf, "vKill;", 6) == 0)
{
if (!target_running ())
{
fprintf (stderr, "No process to kill\n");
write_enn (own_buf);
return;
}
handle_v_kill (own_buf);
return;
}
if (strncmp (own_buf, "vStopped", 8) == 0) if (strncmp (own_buf, "vStopped", 8) == 0)
{ {
handle_v_stopped (own_buf); handle_v_stopped (own_buf);
@ -1556,7 +1643,8 @@ myresume (char *own_buf, int step, int sig)
set_desired_inferior (0); set_desired_inferior (0);
valid_cont_thread = (cont_thread != 0 && cont_thread != -1); valid_cont_thread = (!ptid_equal (cont_thread, null_ptid)
&& !ptid_equal (cont_thread, minus_one_ptid));
if (step || sig || valid_cont_thread) if (step || sig || valid_cont_thread)
{ {
@ -1572,7 +1660,7 @@ myresume (char *own_buf, int step, int sig)
if (!valid_cont_thread) if (!valid_cont_thread)
{ {
resume_info[n].thread = -1; resume_info[n].thread = minus_one_ptid;
resume_info[n].kind = resume_continue; resume_info[n].kind = resume_continue;
resume_info[n].sig = 0; resume_info[n].sig = 0;
n++; n++;
@ -1587,7 +1675,7 @@ myresume (char *own_buf, int step, int sig)
write_ok (own_buf); write_ok (own_buf);
else else
{ {
last_ptid = mywait (&last_status, 0, 1); last_ptid = mywait (minus_one_ptid, &last_status, 0, 1);
prepare_resume_reply (own_buf, last_ptid, &last_status); prepare_resume_reply (own_buf, last_ptid, &last_status);
disable_async_io (); disable_async_io ();
} }
@ -1596,16 +1684,24 @@ myresume (char *own_buf, int step, int sig)
/* Callback for for_each_inferior. Make a new stop reply for each /* Callback for for_each_inferior. Make a new stop reply for each
stopped thread. */ stopped thread. */
static void static int
queue_stop_reply_callback (struct inferior_list_entry *entry) queue_stop_reply_callback (struct inferior_list_entry *entry, void *arg)
{ {
struct target_waitstatus status; int pid = * (int *) arg;
status.kind = TARGET_WAITKIND_STOPPED; if (pid == -1
status.value.sig = TARGET_SIGNAL_TRAP; || ptid_get_pid (entry->id) == pid)
{
struct target_waitstatus status;
/* Pass the last stop reply back to GDB, but don't notify. */ status.kind = TARGET_WAITKIND_STOPPED;
queue_stop_reply (entry->id, &status); status.value.sig = TARGET_SIGNAL_TRAP;
/* Pass the last stop reply back to GDB, but don't notify. */
queue_stop_reply (entry->id, &status);
}
return 0;
} }
/* Status handler for the '?' packet. */ /* Status handler for the '?' packet. */
@ -1623,8 +1719,9 @@ handle_status (char *own_buf)
if (non_stop) if (non_stop)
{ {
discard_queued_stop_replies (); int pid = -1;
for_each_inferior (&all_threads, queue_stop_reply_callback); discard_queued_stop_replies (pid);
find_inferior (&all_threads, queue_stop_reply_callback, &pid);
/* The first is sent immediatly. OK is sent if there is no /* The first is sent immediatly. OK is sent if there is no
stopped thread, which is the same handling of the vStopped stopped thread, which is the same handling of the vStopped
@ -1690,6 +1787,52 @@ gdbserver_show_disableable (FILE *stream)
break; \ break; \
} }
static int
first_thread_of (struct inferior_list_entry *entry, void *args)
{
int pid = * (int *) args;
if (ptid_get_pid (entry->id) == pid)
return 1;
return 0;
}
static void
kill_inferior_callback (struct inferior_list_entry *entry)
{
struct process_info *process = (struct process_info *) entry;
int pid = ptid_get_pid (process->head.id);
kill_inferior (pid);
discard_queued_stop_replies (pid);
}
static void
detach_or_kill_inferior_callback (struct inferior_list_entry *entry)
{
struct process_info *process = (struct process_info *) entry;
int pid = ptid_get_pid (process->head.id);
if (process->attached)
detach_inferior (pid);
else
kill_inferior (pid);
discard_queued_stop_replies (pid);
}
static void
join_inferiors_callback (struct inferior_list_entry *entry)
{
struct process_info *process = (struct process_info *) entry;
/* If we are attached, then we can exit. Otherwise, we need to hang
around doing nothing, until the child is gone. */
if (!process->attached)
join_inferior (ptid_get_pid (process->head.id));
}
int int
main (int argc, char *argv[]) main (int argc, char *argv[])
{ {
@ -1827,6 +1970,7 @@ main (int argc, char *argv[])
exit (1); exit (1);
} }
initialize_inferiors ();
initialize_async_io (); initialize_async_io ();
initialize_low (); initialize_low ();
@ -1861,7 +2005,7 @@ main (int argc, char *argv[])
{ {
last_status.kind = TARGET_WAITKIND_EXITED; last_status.kind = TARGET_WAITKIND_EXITED;
last_status.value.integer = 0; last_status.value.integer = 0;
last_ptid = -1; last_ptid = minus_one_ptid;
} }
/* Don't report shared library events on the initial connection, /* Don't report shared library events on the initial connection,
@ -1871,8 +2015,9 @@ main (int argc, char *argv[])
if (setjmp (toplevel)) if (setjmp (toplevel))
{ {
fprintf (stderr, "Killing inferior\n"); fprintf (stderr, "Killing all inferiors\n");
kill_inferior (); for_each_inferior (&all_processes,
kill_inferior_callback);
exit (1); exit (1);
} }
@ -1891,6 +2036,7 @@ main (int argc, char *argv[])
while (1) while (1)
{ {
noack_mode = 0; noack_mode = 0;
multi_process = 0;
non_stop = 0; non_stop = 0;
remote_open (port); remote_open (port);
@ -1916,10 +2062,8 @@ main (int argc, char *argv[])
if (exit_requested) if (exit_requested)
{ {
if (attached) for_each_inferior (&all_processes,
detach_inferior (); detach_or_kill_inferior_callback);
else
kill_inferior ();
exit (0); exit (0);
} }
else else
@ -1941,6 +2085,7 @@ process_serial_event (void)
int signal; int signal;
unsigned int len; unsigned int len;
CORE_ADDR mem_addr; CORE_ADDR mem_addr;
int pid;
unsigned char sig; unsigned char sig;
int packet_len; int packet_len;
int new_packet_len = -1; int new_packet_len = -1;
@ -1976,12 +2121,22 @@ process_serial_event (void)
break; break;
case 'D': case 'D':
require_running (own_buf); require_running (own_buf);
fprintf (stderr, "Detaching from inferior\n");
if (detach_inferior () != 0) if (multi_process)
{
i++; /* skip ';' */
pid = strtol (&own_buf[i], NULL, 16);
}
else
pid =
ptid_get_pid (((struct inferior_list_entry *) current_inferior)->id);
fprintf (stderr, "Detaching from process %d\n", pid);
if (detach_inferior (pid) != 0)
write_enn (own_buf); write_enn (own_buf);
else else
{ {
discard_queued_stop_replies (); discard_queued_stop_replies (pid);
write_ok (own_buf); write_ok (own_buf);
if (extended_protocol) if (extended_protocol)
@ -1989,7 +2144,7 @@ process_serial_event (void)
/* Treat this like a normal program exit. */ /* Treat this like a normal program exit. */
last_status.kind = TARGET_WAITKIND_EXITED; last_status.kind = TARGET_WAITKIND_EXITED;
last_status.value.integer = 0; last_status.value.integer = 0;
last_ptid = signal_pid; last_ptid = pid_to_ptid (pid);
current_inferior = NULL; current_inferior = NULL;
} }
@ -2001,9 +2156,8 @@ process_serial_event (void)
/* If we are attached, then we can exit. Otherwise, we /* If we are attached, then we can exit. Otherwise, we
need to hang around doing nothing, until the child is need to hang around doing nothing, until the child is
gone. */ gone. */
if (!attached) for_each_inferior (&all_processes,
join_inferior (); join_inferiors_callback);
exit (0); exit (0);
} }
} }
@ -2018,16 +2172,38 @@ process_serial_event (void)
case 'H': case 'H':
if (own_buf[1] == 'c' || own_buf[1] == 'g' || own_buf[1] == 's') if (own_buf[1] == 'c' || own_buf[1] == 'g' || own_buf[1] == 's')
{ {
unsigned long gdb_id, thread_id; ptid_t gdb_id, thread_id;
int pid;
require_running (own_buf); require_running (own_buf);
gdb_id = strtoul (&own_buf[2], NULL, 16);
if (gdb_id == 0 || gdb_id == -1) gdb_id = read_ptid (&own_buf[2], NULL);
thread_id = gdb_id;
pid = ptid_get_pid (gdb_id);
if (ptid_equal (gdb_id, null_ptid)
|| ptid_equal (gdb_id, minus_one_ptid))
thread_id = null_ptid;
else if (pid != 0
&& ptid_equal (pid_to_ptid (pid),
gdb_id))
{
struct thread_info *thread =
(struct thread_info *) find_inferior (&all_threads,
first_thread_of,
&pid);
if (!thread)
{
write_enn (own_buf);
break;
}
thread_id = ((struct inferior_list_entry *)thread)->id;
}
else else
{ {
thread_id = gdb_id_to_thread_id (gdb_id); thread_id = gdb_id_to_thread_id (gdb_id);
if (thread_id == 0) if (ptid_equal (thread_id, null_ptid))
{ {
write_enn (own_buf); write_enn (own_buf);
break; break;
@ -2036,7 +2212,7 @@ process_serial_event (void)
if (own_buf[1] == 'g') if (own_buf[1] == 'g')
{ {
if (thread_id == 0) if (ptid_equal (thread_id, null_ptid))
{ {
/* GDB is telling us to choose any thread. Check if /* GDB is telling us to choose any thread. Check if
the currently selected thread is still valid. If the currently selected thread is still valid. If
@ -2194,13 +2370,12 @@ process_serial_event (void)
case 'k': case 'k':
response_needed = 0; response_needed = 0;
if (!target_running ()) if (!target_running ())
/* The packet we received doesn't make sense - but we /* The packet we received doesn't make sense - but we can't
can't reply to it, either. */ reply to it, either. */
return; return;
fprintf (stderr, "Killing inferior\n"); fprintf (stderr, "Killing all inferiors\n");
kill_inferior (); for_each_inferior (&all_processes, kill_inferior_callback);
discard_queued_stop_replies ();
/* When using the extended protocol, we wait with no program /* When using the extended protocol, we wait with no program
running. The traditional protocol will exit instead. */ running. The traditional protocol will exit instead. */
@ -2217,12 +2392,13 @@ process_serial_event (void)
} }
case 'T': case 'T':
{ {
unsigned long gdb_id, thread_id; ptid_t gdb_id, thread_id;
require_running (own_buf); require_running (own_buf);
gdb_id = strtoul (&own_buf[1], NULL, 16);
gdb_id = read_ptid (&own_buf[1], NULL);
thread_id = gdb_id_to_thread_id (gdb_id); thread_id = gdb_id_to_thread_id (gdb_id);
if (thread_id == 0) if (ptid_equal (thread_id, null_ptid))
{ {
write_enn (own_buf); write_enn (own_buf);
break; break;
@ -2242,10 +2418,8 @@ process_serial_event (void)
if (extended_protocol) if (extended_protocol)
{ {
if (target_running ()) if (target_running ())
{ for_each_inferior (&all_processes,
kill_inferior (); kill_inferior_callback);
discard_queued_stop_replies ();
}
fprintf (stderr, "GDBserver restarting\n"); fprintf (stderr, "GDBserver restarting\n");
/* Wait till we are at 1st instruction in prog. */ /* Wait till we are at 1st instruction in prog. */
@ -2323,7 +2497,8 @@ handle_target_event (int err, gdb_client_data client_data)
if (debug_threads) if (debug_threads)
fprintf (stderr, "handling possible target event\n"); fprintf (stderr, "handling possible target event\n");
last_ptid = mywait (&last_status, TARGET_WNOHANG, 1); last_ptid = mywait (minus_one_ptid, &last_status,
TARGET_WNOHANG, 1);
if (last_status.kind != TARGET_WAITKIND_IGNORE) if (last_status.kind != TARGET_WAITKIND_IGNORE)
{ {

View File

@ -85,6 +85,70 @@ typedef unsigned char gdb_byte;
least the size of a (void *). */ least the size of a (void *). */
typedef long long CORE_ADDR; typedef long long CORE_ADDR;
typedef unsigned long long ULONGEST;
/* The ptid struct is a collection of the various "ids" necessary
for identifying the inferior. This consists of the process id
(pid), thread id (tid), and other fields necessary for uniquely
identifying the inferior process/thread being debugged. When
manipulating ptids, the constructors, accessors, and predicate
declared in server.h should be used. These are as follows:
ptid_build - Make a new ptid from a pid, lwp, and tid.
pid_to_ptid - Make a new ptid from just a pid.
ptid_get_pid - Fetch the pid component of a ptid.
ptid_get_lwp - Fetch the lwp component of a ptid.
ptid_get_tid - Fetch the tid component of a ptid.
ptid_equal - Test to see if two ptids are equal.
Please do NOT access the struct ptid members directly (except, of
course, in the implementation of the above ptid manipulation
functions). */
struct ptid
{
/* Process id */
int pid;
/* Lightweight process id */
long lwp;
/* Thread id */
long tid;
};
typedef struct ptid ptid_t;
/* The -1 ptid, often used to indicate either an error condition or a
"don't care" condition, i.e, "run all threads". */
extern ptid_t minus_one_ptid;
/* The null or zero ptid, often used to indicate no process. */
extern ptid_t null_ptid;
/* Attempt to find and return an existing ptid with the given PID,
LWP, and TID components. If none exists, create a new one and
return that. */
ptid_t ptid_build (int pid, long lwp, long tid);
/* Create a ptid from just a pid. */
ptid_t pid_to_ptid (int pid);
/* Fetch the pid (process id) component from a ptid. */
int ptid_get_pid (ptid_t ptid);
/* Fetch the lwp (lightweight process) component from a ptid. */
long ptid_get_lwp (ptid_t ptid);
/* Fetch the tid (thread id) component from a ptid. */
long ptid_get_tid (ptid_t ptid);
/* Compare two ptids to see if they are equal. */
extern int ptid_equal (ptid_t p1, ptid_t p2);
/* Return true if this ptid represents a process id. */
extern int ptid_is_pid (ptid_t ptid);
/* Generic information for tracking a list of ``inferiors'' - threads, /* Generic information for tracking a list of ``inferiors'' - threads,
processes, etc. */ processes, etc. */
struct inferior_list struct inferior_list
@ -94,7 +158,7 @@ struct inferior_list
}; };
struct inferior_list_entry struct inferior_list_entry
{ {
unsigned long id; ptid_t id;
struct inferior_list_entry *next; struct inferior_list_entry *next;
}; };
@ -108,6 +172,36 @@ struct dll_info
CORE_ADDR base_addr; CORE_ADDR base_addr;
}; };
struct sym_cache;
struct breakpoint;
struct process_info_private;
struct process_info
{
struct inferior_list_entry head;
int attached;
/* The symbol cache. */
struct sym_cache *symbol_cache;
/* If this flag has been set, assume symbol cache misses are
failures. */
int all_symbols_looked_up;
/* The list of memory breakpoints. */
struct breakpoint *breakpoints;
/* Private target data. */
struct process_info_private *private;
};
/* Return a pointer to the process that corresponds to the current
thread (current_inferior). It is an error to call this if there is
no current thread selected. */
struct process_info *current_process (void);
#include "regcache.h" #include "regcache.h"
#include "gdb/signals.h" #include "gdb/signals.h"
#include "gdb_signals.h" #include "gdb_signals.h"
@ -120,22 +214,33 @@ void initialize_low ();
/* From inferiors.c. */ /* From inferiors.c. */
extern struct inferior_list all_processes;
extern struct inferior_list all_threads; extern struct inferior_list all_threads;
extern struct inferior_list all_dlls; extern struct inferior_list all_dlls;
extern int dlls_changed; extern int dlls_changed;
void initialize_inferiors (void);
void add_inferior_to_list (struct inferior_list *list, void add_inferior_to_list (struct inferior_list *list,
struct inferior_list_entry *new_inferior); struct inferior_list_entry *new_inferior);
void for_each_inferior (struct inferior_list *list, void for_each_inferior (struct inferior_list *list,
void (*action) (struct inferior_list_entry *)); void (*action) (struct inferior_list_entry *));
extern struct thread_info *current_inferior; extern struct thread_info *current_inferior;
void remove_inferior (struct inferior_list *list, void remove_inferior (struct inferior_list *list,
struct inferior_list_entry *entry); struct inferior_list_entry *entry);
void remove_thread (struct thread_info *thread); void remove_thread (struct thread_info *thread);
void add_thread (unsigned long thread_id, void *target_data, unsigned int); void add_thread (ptid_t ptid, void *target_data);
unsigned int thread_id_to_gdb_id (unsigned long);
unsigned int thread_to_gdb_id (struct thread_info *); struct process_info *add_process (int pid, int attached);
unsigned long gdb_id_to_thread_id (unsigned int); void remove_process (struct process_info *process);
struct process_info *find_process_pid (int pid);
struct thread_info *find_thread_pid (ptid_t ptid);
ptid_t thread_id_to_gdb_id (ptid_t);
ptid_t thread_to_gdb_id (struct thread_info *);
ptid_t gdb_id_to_thread_id (ptid_t);
struct thread_info *gdb_id_to_thread (unsigned int); struct thread_info *gdb_id_to_thread (unsigned int);
void clear_inferiors (void); void clear_inferiors (void);
struct inferior_list_entry *find_inferior struct inferior_list_entry *find_inferior
@ -144,7 +249,7 @@ struct inferior_list_entry *find_inferior
void *), void *),
void *arg); void *arg);
struct inferior_list_entry *find_inferior_id (struct inferior_list *list, struct inferior_list_entry *find_inferior_id (struct inferior_list *list,
unsigned long id); ptid_t id);
void *inferior_target_data (struct thread_info *); void *inferior_target_data (struct thread_info *);
void set_inferior_target_data (struct thread_info *, void *); void set_inferior_target_data (struct thread_info *, void *);
void *inferior_regcache_data (struct thread_info *); void *inferior_regcache_data (struct thread_info *);
@ -157,9 +262,9 @@ void unloaded_dll (const char *name, CORE_ADDR base_addr);
/* Public variables in server.c */ /* Public variables in server.c */
extern unsigned long cont_thread; extern ptid_t cont_thread;
extern unsigned long general_thread; extern ptid_t general_thread;
extern unsigned long step_thread; extern ptid_t step_thread;
extern int server_waiting; extern int server_waiting;
extern int debug_threads; extern int debug_threads;
@ -172,6 +277,7 @@ extern int disable_packet_Tthread;
extern int disable_packet_qC; extern int disable_packet_qC;
extern int disable_packet_qfThreadInfo; extern int disable_packet_qfThreadInfo;
extern int multi_process;
extern int non_stop; extern int non_stop;
/* Functions from event-loop.c. */ /* Functions from event-loop.c. */
@ -188,7 +294,7 @@ extern void start_event_loop (void);
extern void handle_serial_event (int err, gdb_client_data client_data); extern void handle_serial_event (int err, gdb_client_data client_data);
extern void handle_target_event (int err, gdb_client_data client_data); extern void handle_target_event (int err, gdb_client_data client_data);
extern void push_event (unsigned long ptid, struct target_waitstatus *status); extern void push_event (ptid_t ptid, struct target_waitstatus *status);
/* Functions from hostio.c. */ /* Functions from hostio.c. */
extern int handle_vFile (char *, int, int *); extern int handle_vFile (char *, int, int *);
@ -203,6 +309,9 @@ extern int all_symbols_looked_up;
extern int noack_mode; extern int noack_mode;
extern int transport_is_reliable; extern int transport_is_reliable;
ptid_t read_ptid (char *buf, char **obuf);
char *write_ptid (char *buf, ptid_t ptid);
int putpkt (char *buf); int putpkt (char *buf);
int putpkt_binary (char *buf, int len); int putpkt_binary (char *buf, int len);
int putpkt_notif (char *buf); int putpkt_notif (char *buf);
@ -219,7 +328,7 @@ void convert_ascii_to_int (char *from, unsigned char *to, int n);
void convert_int_to_ascii (unsigned char *from, char *to, int n); void convert_int_to_ascii (unsigned char *from, char *to, int n);
void new_thread_notify (int id); void new_thread_notify (int id);
void dead_thread_notify (int id); void dead_thread_notify (int id);
void prepare_resume_reply (char *buf, unsigned long thread_id, void prepare_resume_reply (char *buf, ptid_t ptid,
struct target_waitstatus *status); struct target_waitstatus *status);
const char *decode_address_to_semicolon (CORE_ADDR *addrp, const char *start); const char *decode_address_to_semicolon (CORE_ADDR *addrp, const char *start);
@ -244,6 +353,7 @@ int remote_escape_output (const gdb_byte *buffer, int len,
gdb_byte *out_buf, int *out_len, gdb_byte *out_buf, int *out_len,
int out_maxlen); int out_maxlen);
void clear_symbol_cache (struct sym_cache **symcache_p);
int look_up_one_symbol (const char *name, CORE_ADDR *addrp); int look_up_one_symbol (const char *name, CORE_ADDR *addrp);
void monitor_output (const char *msg); void monitor_output (const char *msg);

View File

@ -268,6 +268,7 @@ static int
spu_create_inferior (char *program, char **allargs) spu_create_inferior (char *program, char **allargs)
{ {
int pid; int pid;
ptid_t ptid;
pid = fork (); pid = fork ();
if (pid < 0) if (pid < 0)
@ -289,7 +290,10 @@ spu_create_inferior (char *program, char **allargs)
_exit (0177); _exit (0177);
} }
add_thread (pid, NULL, pid); add_process (pid, 0);
ptid = ptid_build (pid, pid, 0);
add_thread (ptid, NULL);
return pid; return pid;
} }
@ -297,6 +301,8 @@ spu_create_inferior (char *program, char **allargs)
int int
spu_attach (unsigned long pid) spu_attach (unsigned long pid)
{ {
ptid_t ptid;
if (ptrace (PTRACE_ATTACH, pid, 0, 0) != 0) if (ptrace (PTRACE_ATTACH, pid, 0, 0) != 0)
{ {
fprintf (stderr, "Cannot attach to process %ld: %s (%d)\n", pid, fprintf (stderr, "Cannot attach to process %ld: %s (%d)\n", pid,
@ -305,27 +311,32 @@ spu_attach (unsigned long pid)
_exit (0177); _exit (0177);
} }
add_thread (pid, NULL, pid); add_process (pid, 1);
ptid = ptid_build (pid, pid, 0);
add_thread (ptid, NULL);
return 0; return 0;
} }
/* Kill the inferior process. */ /* Kill the inferior process. */
static void static int
spu_kill (void) spu_kill (int)
{ {
ptrace (PTRACE_KILL, current_tid, 0, 0); ptrace (PTRACE_KILL, current_tid, 0, 0);
remove_process (pid);
return 0;
} }
/* Detach from inferior process. */ /* Detach from inferior process. */
static int static int
spu_detach (void) spu_detach (int pid)
{ {
ptrace (PTRACE_DETACH, current_tid, 0, 0); ptrace (PTRACE_DETACH, current_tid, 0, 0);
remove_process (pid);
return 0; return 0;
} }
static void static void
spu_join (void) spu_join (int pid)
{ {
int status, ret; int status, ret;
@ -338,9 +349,9 @@ spu_join (void)
/* Return nonzero if the given thread is still alive. */ /* Return nonzero if the given thread is still alive. */
static int static int
spu_thread_alive (unsigned long tid) spu_thread_alive (ptid_t ptid)
{ {
return tid == current_tid; return ptid_get_lwp (ptid) == current_tid;
} }
/* Resume process. */ /* Resume process. */
@ -350,8 +361,8 @@ spu_resume (struct thread_resume *resume_info, size_t n)
size_t i; size_t i;
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
if (resume_info[i].thread == -1 if (ptid_equal (resume_info[i].thread, minus_one_ptid)
|| resume_info[i].thread == current_tid) || ptid_get_lwp (resume_info[i].thread) == current_tid)
break; break;
if (i == n) if (i == n)
@ -371,8 +382,8 @@ spu_resume (struct thread_resume *resume_info, size_t n)
} }
/* Wait for process, returns status. */ /* Wait for process, returns status. */
static unsigned long static ptid_t
spu_wait (struct target_waitstatus *ourstatus, int options) spu_wait (ptid_t ptid, struct target_waitstatus *ourstatus, int options)
{ {
int tid = current_tid; int tid = current_tid;
int w; int w;
@ -415,7 +426,8 @@ spu_wait (struct target_waitstatus *ourstatus, int options)
ourstatus->kind = TARGET_WAITKIND_EXITED; ourstatus->kind = TARGET_WAITKIND_EXITED;
ourstatus->value.integer = WEXITSTATUS (w); ourstatus->value.integer = WEXITSTATUS (w);
clear_inferiors (); clear_inferiors ();
return ret; remove_process (ret);
return pid_to_ptid (ret);
} }
else if (!WIFSTOPPED (w)) else if (!WIFSTOPPED (w))
{ {
@ -423,7 +435,8 @@ spu_wait (struct target_waitstatus *ourstatus, int options)
ourstatus->kind = TARGET_WAITKIND_SIGNALLED; ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
ourstatus->value.sig = target_signal_from_host (WTERMSIG (w)); ourstatus->value.sig = target_signal_from_host (WTERMSIG (w));
clear_inferiors (); clear_inferiors ();
return ret; remove_process (ret);
return pid_to_ptid (ret);
} }
/* After attach, we may have received a SIGSTOP. Do not return this /* After attach, we may have received a SIGSTOP. Do not return this
@ -432,12 +445,12 @@ spu_wait (struct target_waitstatus *ourstatus, int options)
{ {
ourstatus->kind = TARGET_WAITKIND_STOPPED; ourstatus->kind = TARGET_WAITKIND_STOPPED;
ourstatus->value.sig = TARGET_SIGNAL_0; ourstatus->value.sig = TARGET_SIGNAL_0;
return ret; return ptid_build (ret, ret, 0);
} }
ourstatus->kind = TARGET_WAITKIND_STOPPED; ourstatus->kind = TARGET_WAITKIND_STOPPED;
ourstatus->value.sig = target_signal_from_host (WSTOPSIG (w)); ourstatus->value.sig = target_signal_from_host (WSTOPSIG (w));
return ret; return ptid_build (ret, ret, 0);
} }
/* Fetch inferior registers. */ /* Fetch inferior registers. */

View File

@ -29,10 +29,7 @@ set_desired_inferior (int use_general)
struct thread_info *found; struct thread_info *found;
if (use_general == 1) if (use_general == 1)
{ found = find_thread_pid (general_thread);
found = (struct thread_info *) find_inferior_id (&all_threads,
general_thread);
}
else else
{ {
found = NULL; found = NULL;
@ -40,14 +37,14 @@ set_desired_inferior (int use_general)
/* If we are continuing any (all) thread(s), use step_thread /* If we are continuing any (all) thread(s), use step_thread
to decide which thread to step and/or send the specified to decide which thread to step and/or send the specified
signal to. */ signal to. */
if ((step_thread != 0 && step_thread != -1) if ((!ptid_equal (step_thread, null_ptid)
&& (cont_thread == 0 || cont_thread == -1)) && !ptid_equal (step_thread, minus_one_ptid))
found = (struct thread_info *) find_inferior_id (&all_threads, && (ptid_equal (cont_thread, null_ptid)
step_thread); || ptid_equal (cont_thread, minus_one_ptid)))
found = find_thread_pid (step_thread);
if (found == NULL) if (found == NULL)
found = (struct thread_info *) find_inferior_id (&all_threads, found = find_thread_pid (cont_thread);
cont_thread);
} }
if (found == NULL) if (found == NULL)
@ -88,28 +85,24 @@ write_inferior_memory (CORE_ADDR memaddr, const unsigned char *myaddr,
return res; return res;
} }
unsigned long ptid_t
mywait (struct target_waitstatus *ourstatus, int options, mywait (ptid_t ptid, struct target_waitstatus *ourstatus, int options,
int connected_wait) int connected_wait)
{ {
unsigned long ret; ptid_t ret;
if (connected_wait) if (connected_wait)
server_waiting = 1; server_waiting = 1;
ret = (*the_target->wait) (ourstatus, options); ret = (*the_target->wait) (ptid, ourstatus, options);
if (ourstatus->kind == TARGET_WAITKIND_EXITED if (ourstatus->kind == TARGET_WAITKIND_EXITED)
|| ourstatus->kind == TARGET_WAITKIND_SIGNALLED) fprintf (stderr,
{ "\nChild exited with status %d\n", ourstatus->value.sig);
if (ourstatus->kind == TARGET_WAITKIND_EXITED) else if (ourstatus->kind == TARGET_WAITKIND_SIGNALLED)
fprintf (stderr, fprintf (stderr, "\nChild terminated with signal = 0x%x (%s)\n",
"\nChild exited with status %d\n", ourstatus->value.sig); target_signal_to_host (ourstatus->value.sig),
if (ourstatus->kind == TARGET_WAITKIND_SIGNALLED) target_signal_to_name (ourstatus->value.sig));
fprintf (stderr, "\nChild terminated with signal = 0x%x (%s)\n",
target_signal_to_host (ourstatus->value.sig),
target_signal_to_name (ourstatus->value.sig));
}
if (connected_wait) if (connected_wait)
server_waiting = 0; server_waiting = 0;
@ -137,3 +130,27 @@ set_target_ops (struct target_ops *target)
the_target = (struct target_ops *) xmalloc (sizeof (*the_target)); the_target = (struct target_ops *) xmalloc (sizeof (*the_target));
memcpy (the_target, target, sizeof (*the_target)); memcpy (the_target, target, sizeof (*the_target));
} }
/* Convert pid to printable format. */
const char *
target_pid_to_str (ptid_t ptid)
{
static char buf[80];
if (ptid_equal (ptid, minus_one_ptid))
snprintf (buf, sizeof (buf), "<all threads>");
else if (ptid_equal (ptid, null_ptid))
snprintf (buf, sizeof (buf), "<null thread>");
else if (ptid_get_tid (ptid) != 0)
snprintf (buf, sizeof (buf), "Thread %d.0x%lx",
ptid_get_pid (ptid), ptid_get_tid (ptid));
else if (ptid_get_lwp (ptid) != 0)
snprintf (buf, sizeof (buf), "LWP %d.%ld",
ptid_get_pid (ptid), ptid_get_lwp (ptid));
else
snprintf (buf, sizeof (buf), "Process %d",
ptid_get_pid (ptid));
return buf;
}

View File

@ -43,7 +43,7 @@ enum resume_kind
struct thread_resume struct thread_resume
{ {
unsigned long thread; ptid_t thread;
/* How to "resume". */ /* How to "resume". */
enum resume_kind kind; enum resume_kind kind;
@ -96,7 +96,7 @@ struct target_waitstatus
{ {
int integer; int integer;
enum target_signal sig; enum target_signal sig;
unsigned long related_pid; ptid_t related_pid;
char *execd_pathname; char *execd_pathname;
} }
value; value;
@ -129,31 +129,38 @@ struct target_ops
int (*attach) (unsigned long pid); int (*attach) (unsigned long pid);
/* Kill all inferiors. */ /* Kill inferior PID. Return -1 on failure, and 0 on success. */
void (*kill) (void); int (*kill) (int pid);
/* Detach from all inferiors. /* Detach from inferior PID. Return -1 on failure, and 0 on
Return -1 on failure, and 0 on success. */ success. */
int (*detach) (void); int (*detach) (int pid);
/* Wait for inferiors to end. */ /* Wait for inferior PID to exit. */
void (*join) (int pid);
void (*join) (void);
/* Return 1 iff the thread with process ID PID is alive. */ /* Return 1 iff the thread with process ID PID is alive. */
int (*thread_alive) (unsigned long pid); int (*thread_alive) (ptid_t pid);
/* Resume the inferior process. */ /* Resume the inferior process. */
void (*resume) (struct thread_resume *resume_info, size_t n); void (*resume) (struct thread_resume *resume_info, size_t n);
/* Wait for the inferior process or thread to change state. Store /* Wait for the inferior process or thread to change state. Store
status through argument pointer STATUS. */ status through argument pointer STATUS.
unsigned long (*wait) (struct target_waitstatus *status, int options); PTID = -1 to wait for any pid to do something, PTID(pid,0,0) to
wait for any thread of process pid to do something. Return ptid
of child, or -1 in case of error; store status through argument
pointer STATUS. OPTIONS is a bit set of options defined as
TARGET_W* above. If options contains TARGET_WNOHANG and there's
no child stop to report, return is
null_ptid/TARGET_WAITKIND_IGNORE. */
ptid_t (*wait) (ptid_t ptid, struct target_waitstatus *status, int options);
/* Fetch registers from the inferior process. /* Fetch registers from the inferior process.
@ -280,11 +287,11 @@ void set_target_ops (struct target_ops *);
#define myattach(pid) \ #define myattach(pid) \
(*the_target->attach) (pid) (*the_target->attach) (pid)
#define kill_inferior() \ #define kill_inferior(pid) \
(*the_target->kill) () (*the_target->kill) (pid)
#define detach_inferior() \ #define detach_inferior(pid) \
(*the_target->detach) () (*the_target->detach) (pid)
#define mythread_alive(pid) \ #define mythread_alive(pid) \
(*the_target->thread_alive) (pid) (*the_target->thread_alive) (pid)
@ -295,8 +302,8 @@ void set_target_ops (struct target_ops *);
#define store_inferior_registers(regno) \ #define store_inferior_registers(regno) \
(*the_target->store_registers) (regno) (*the_target->store_registers) (regno)
#define join_inferior() \ #define join_inferior(pid) \
(*the_target->join) () (*the_target->join) (pid)
#define target_supports_non_stop() \ #define target_supports_non_stop() \
(the_target->supports_non_stop ? (*the_target->supports_non_stop ) () : 0) (the_target->supports_non_stop ? (*the_target->supports_non_stop ) () : 0)
@ -308,8 +315,8 @@ void set_target_ops (struct target_ops *);
int start_non_stop (int nonstop); int start_non_stop (int nonstop);
unsigned long mywait (struct target_waitstatus *ourstatus, int options, ptid_t mywait (ptid_t ptid, struct target_waitstatus *ourstatus, int options,
int connected_wait); int connected_wait);
int read_inferior_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len); int read_inferior_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len);
@ -318,4 +325,6 @@ int write_inferior_memory (CORE_ADDR memaddr, const unsigned char *myaddr,
void set_desired_inferior (int id); void set_desired_inferior (int id);
const char *target_pid_to_str (ptid_t);
#endif /* TARGET_H */ #endif /* TARGET_H */

View File

@ -35,14 +35,7 @@ static int thread_db_use_events;
#include <stdint.h> #include <stdint.h>
/* Structure that identifies the child process for the static int find_one_thread (ptid_t);
<proc_service.h> interface. */
static struct ps_prochandle proc_handle;
/* Connection to the libthread_db library. */
static td_thragent_t *thread_agent;
static int find_one_thread (int);
static int find_new_threads_callback (const td_thrhandle_t *th_p, void *data); static int find_new_threads_callback (const td_thrhandle_t *th_p, void *data);
static const char * static const char *
@ -137,6 +130,7 @@ thread_db_create_event (CORE_ADDR where)
td_event_msg_t msg; td_event_msg_t msg;
td_err_e err; td_err_e err;
struct lwp_info *lwp; struct lwp_info *lwp;
struct process_info_private *proc = current_process()->private;
if (debug_threads) if (debug_threads)
fprintf (stderr, "Thread creation event.\n"); fprintf (stderr, "Thread creation event.\n");
@ -145,7 +139,7 @@ thread_db_create_event (CORE_ADDR where)
In the LinuxThreads implementation, this is safe, In the LinuxThreads implementation, this is safe,
because all events come from the manager thread because all events come from the manager thread
(except for its own creation, of course). */ (except for its own creation, of course). */
err = td_ta_event_getmsg (thread_agent, &msg); err = td_ta_event_getmsg (proc->thread_agent, &msg);
if (err != TD_OK) if (err != TD_OK)
fprintf (stderr, "thread getmsg err: %s\n", fprintf (stderr, "thread getmsg err: %s\n",
thread_db_err_str (err)); thread_db_err_str (err));
@ -155,7 +149,7 @@ thread_db_create_event (CORE_ADDR where)
created threads. */ created threads. */
lwp = get_thread_lwp (current_inferior); lwp = get_thread_lwp (current_inferior);
if (lwp->thread_known == 0) if (lwp->thread_known == 0)
find_one_thread (lwpid_of (lwp)); find_one_thread (lwp->head.id);
/* msg.event == TD_EVENT_CREATE */ /* msg.event == TD_EVENT_CREATE */
@ -181,6 +175,7 @@ thread_db_enable_reporting ()
td_thr_events_t events; td_thr_events_t events;
td_notify_t notify; td_notify_t notify;
td_err_e err; td_err_e err;
struct process_info_private *proc = current_process()->private;
/* Set the process wide mask saying which events we're interested in. */ /* Set the process wide mask saying which events we're interested in. */
td_event_emptyset (&events); td_event_emptyset (&events);
@ -192,7 +187,7 @@ thread_db_enable_reporting ()
td_event_addset (&events, TD_DEATH); td_event_addset (&events, TD_DEATH);
#endif #endif
err = td_ta_set_event (thread_agent, &events); err = td_ta_set_event (proc->thread_agent, &events);
if (err != TD_OK) if (err != TD_OK)
{ {
warning ("Unable to set global thread event mask: %s", warning ("Unable to set global thread event mask: %s",
@ -201,7 +196,7 @@ thread_db_enable_reporting ()
} }
/* Get address for thread creation breakpoint. */ /* Get address for thread creation breakpoint. */
err = td_ta_event_addr (thread_agent, TD_CREATE, &notify); err = td_ta_event_addr (proc->thread_agent, TD_CREATE, &notify);
if (err != TD_OK) if (err != TD_OK)
{ {
warning ("Unable to get location for thread creation breakpoint: %s", warning ("Unable to get location for thread creation breakpoint: %s",
@ -216,7 +211,7 @@ thread_db_enable_reporting ()
with actual thread deaths (via wait). */ with actual thread deaths (via wait). */
/* Get address for thread death breakpoint. */ /* Get address for thread death breakpoint. */
err = td_ta_event_addr (thread_agent, TD_DEATH, &notify); err = td_ta_event_addr (proc->thread_agent, TD_DEATH, &notify);
if (err != TD_OK) if (err != TD_OK)
{ {
warning ("Unable to get location for thread death breakpoint: %s", warning ("Unable to get location for thread death breakpoint: %s",
@ -231,21 +226,23 @@ thread_db_enable_reporting ()
} }
static int static int
find_one_thread (int lwpid) find_one_thread (ptid_t ptid)
{ {
td_thrhandle_t th; td_thrhandle_t th;
td_thrinfo_t ti; td_thrinfo_t ti;
td_err_e err; td_err_e err;
struct thread_info *inferior; struct thread_info *inferior;
struct lwp_info *lwp; struct lwp_info *lwp;
struct process_info_private *proc = current_process()->private;
int lwpid = ptid_get_lwp (ptid);
inferior = (struct thread_info *) find_inferior_id (&all_threads, lwpid); inferior = (struct thread_info *) find_inferior_id (&all_threads, ptid);
lwp = get_thread_lwp (inferior); lwp = get_thread_lwp (inferior);
if (lwp->thread_known) if (lwp->thread_known)
return 1; return 1;
/* Get information about this thread. */ /* Get information about this thread. */
err = td_ta_map_lwp2thr (thread_agent, lwpid_of (lwp), &th); err = td_ta_map_lwp2thr (proc->thread_agent, lwpid, &th);
if (err != TD_OK) if (err != TD_OK)
error ("Cannot get thread handle for LWP %d: %s", error ("Cannot get thread handle for LWP %d: %s",
lwpid, thread_db_err_str (err)); lwpid, thread_db_err_str (err));
@ -259,10 +256,10 @@ find_one_thread (int lwpid)
fprintf (stderr, "Found thread %ld (LWP %d)\n", fprintf (stderr, "Found thread %ld (LWP %d)\n",
ti.ti_tid, ti.ti_lid); ti.ti_tid, ti.ti_lid);
if (lwpid_of (lwp) != ti.ti_lid) if (lwpid != ti.ti_lid)
{ {
warning ("PID mismatch! Expected %ld, got %ld", warning ("PID mismatch! Expected %ld, got %ld",
(long) lwpid_of (lwp), (long) ti.ti_lid); (long) lwpid, (long) ti.ti_lid);
return 0; return 0;
} }
@ -289,29 +286,24 @@ static void
maybe_attach_thread (const td_thrhandle_t *th_p, td_thrinfo_t *ti_p) maybe_attach_thread (const td_thrhandle_t *th_p, td_thrinfo_t *ti_p)
{ {
td_err_e err; td_err_e err;
struct thread_info *inferior;
struct lwp_info *lwp; struct lwp_info *lwp;
inferior = (struct thread_info *) find_inferior_id (&all_threads, lwp = find_lwp_pid (pid_to_ptid (ti_p->ti_lid));
ti_p->ti_lid); if (lwp != NULL)
if (inferior != NULL)
return; return;
if (debug_threads) if (debug_threads)
fprintf (stderr, "Attaching to thread %ld (LWP %d)\n", fprintf (stderr, "Attaching to thread %ld (LWP %d)\n",
ti_p->ti_tid, ti_p->ti_lid); ti_p->ti_tid, ti_p->ti_lid);
linux_attach_lwp (ti_p->ti_lid); linux_attach_lwp (ti_p->ti_lid);
inferior = (struct thread_info *) find_inferior_id (&all_threads, lwp = find_lwp_pid (pid_to_ptid (ti_p->ti_lid));
ti_p->ti_lid); if (lwp == NULL)
if (inferior == NULL)
{ {
warning ("Could not attach to thread %ld (LWP %d)\n", warning ("Could not attach to thread %ld (LWP %d)\n",
ti_p->ti_tid, ti_p->ti_lid); ti_p->ti_tid, ti_p->ti_lid);
return; return;
} }
lwp = inferior_target_data (inferior);
lwp->thread_known = 1; lwp->thread_known = 1;
lwp->th = *th_p; lwp->th = *th_p;
@ -347,15 +339,18 @@ static void
thread_db_find_new_threads (void) thread_db_find_new_threads (void)
{ {
td_err_e err; td_err_e err;
ptid_t ptid = ((struct inferior_list_entry *) current_inferior)->id;
struct process_info_private *proc = current_process()->private;
/* This function is only called when we first initialize thread_db. /* This function is only called when we first initialize thread_db.
First locate the initial thread. If it is not ready for First locate the initial thread. If it is not ready for
debugging yet, then stop. */ debugging yet, then stop. */
if (find_one_thread (all_threads.head->id) == 0) if (find_one_thread (ptid) == 0)
return; return;
/* Iterate over all user-space threads to discover new threads. */ /* Iterate over all user-space threads to discover new threads. */
err = td_ta_thr_iter (thread_agent, find_new_threads_callback, NULL, err = td_ta_thr_iter (proc->thread_agent,
find_new_threads_callback, NULL,
TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS); TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
if (err != TD_OK) if (err != TD_OK)
@ -385,18 +380,22 @@ thread_db_get_tls_address (struct thread_info *thread, CORE_ADDR offset,
psaddr_t addr; psaddr_t addr;
td_err_e err; td_err_e err;
struct lwp_info *lwp; struct lwp_info *lwp;
struct thread_info *saved_inferior;
lwp = get_thread_lwp (thread); lwp = get_thread_lwp (thread);
if (!lwp->thread_known) if (!lwp->thread_known)
find_one_thread (lwpid_of (lwp)); find_one_thread (lwp->head.id);
if (!lwp->thread_known) if (!lwp->thread_known)
return TD_NOTHR; return TD_NOTHR;
saved_inferior = current_inferior;
current_inferior = thread;
/* Note the cast through uintptr_t: this interface only works if /* Note the cast through uintptr_t: this interface only works if
a target address fits in a psaddr_t, which is a host pointer. a target address fits in a psaddr_t, which is a host pointer.
So a 32-bit debugger can not access 64-bit TLS through this. */ So a 32-bit debugger can not access 64-bit TLS through this. */
err = td_thr_tls_get_addr (&lwp->th, (psaddr_t) (uintptr_t) load_module, err = td_thr_tls_get_addr (&lwp->th, (psaddr_t) (uintptr_t) load_module,
offset, &addr); offset, &addr);
current_inferior = saved_inferior;
if (err == TD_OK) if (err == TD_OK)
{ {
*address = (CORE_ADDR) (uintptr_t) addr; *address = (CORE_ADDR) (uintptr_t) addr;
@ -413,6 +412,8 @@ int
thread_db_init (int use_events) thread_db_init (int use_events)
{ {
int err; int err;
struct process_info *proc = current_process ();
struct process_info_private *priv = proc->private;
/* FIXME drow/2004-10-16: This is the "overall process ID", which /* FIXME drow/2004-10-16: This is the "overall process ID", which
GNU/Linux calls tgid, "thread group ID". When we support GNU/Linux calls tgid, "thread group ID". When we support
@ -424,14 +425,10 @@ thread_db_init (int use_events)
This isn't the only place in gdbserver that assumes that the first This isn't the only place in gdbserver that assumes that the first
process in the list is the thread group leader. */ process in the list is the thread group leader. */
proc_handle.pid = ((struct inferior_list_entry *)current_inferior)->id;
/* Allow new symbol lookups. */
all_symbols_looked_up = 0;
thread_db_use_events = use_events; thread_db_use_events = use_events;
err = td_ta_new (&proc_handle, &thread_agent); err = td_ta_new (&priv->proc_handle, &priv->thread_agent);
switch (err) switch (err)
{ {
case TD_NOLIBTHREAD: case TD_NOLIBTHREAD:
@ -445,7 +442,7 @@ thread_db_init (int use_events)
return 0; return 0;
thread_db_find_new_threads (); thread_db_find_new_threads ();
thread_db_look_up_symbols (); thread_db_look_up_symbols ();
all_symbols_looked_up = 1; proc->all_symbols_looked_up = 1;
return 1; return 1;
default: default:

View File

@ -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 /* Get the thread ID from the current selected inferior (the current
thread). */ thread). */
static DWORD static ptid_t
current_inferior_tid (void) current_inferior_ptid (void)
{ {
win32_thread_info *th = inferior_target_data (current_inferior); return ((struct inferior_list_entry*) current_inferior)->id;
return th->tid; }
/* 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. */ /* 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 /* Find a thread record given a thread id. If GET_CONTEXT is set then
also retrieve the context for this thread. */ also retrieve the context for this thread. */
static win32_thread_info * static win32_thread_info *
thread_rec (DWORD id, int get_context) thread_rec (ptid_t ptid, int get_context)
{ {
struct thread_info *thread; struct thread_info *thread;
win32_thread_info *th; 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) if (thread == NULL)
return NULL; return NULL;
@ -169,20 +175,21 @@ thread_rec (DWORD id, int get_context)
/* Add a thread to the thread list. */ /* Add a thread to the thread list. */
static win32_thread_info * static win32_thread_info *
child_add_thread (DWORD tid, HANDLE h) child_add_thread (DWORD pid, DWORD tid, HANDLE h)
{ {
win32_thread_info *th; 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; return th;
th = xcalloc (1, sizeof (*th)); th = xcalloc (1, sizeof (*th));
th->tid = tid; th->tid = tid;
th->h = h; th->h = h;
add_thread (tid, th, (unsigned int) tid); add_thread (ptid, th);
set_inferior_regcache_data ((struct thread_info *) set_inferior_regcache_data ((struct thread_info *)
find_inferior_id (&all_threads, tid), find_inferior_id (&all_threads, ptid),
new_register_cache ()); new_register_cache ());
if (the_low_target.thread_added != NULL) 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. */ /* Delete a thread from the list of threads. */
static void static void
child_delete_thread (DWORD id) child_delete_thread (DWORD pid, DWORD tid)
{ {
struct inferior_list_entry *thread; struct inferior_list_entry *thread;
ptid_t ptid;
/* If the last thread is exiting, just return. */ /* If the last thread is exiting, just return. */
if (all_threads.head == all_threads.tail) if (all_threads.head == all_threads.tail)
return; return;
thread = find_inferior_id (&all_threads, id); ptid = ptid_build (pid, tid, 0);
thread = find_inferior_id (&all_threads, ptid);
if (thread == NULL) if (thread == NULL)
return; return;
@ -250,7 +259,7 @@ child_init_thread_list (void)
} }
static 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; last_sig = TARGET_SIGNAL_0;
@ -263,6 +272,7 @@ do_initial_child_stuff (HANDLE proch, DWORD pid)
memset (&current_event, 0, sizeof (current_event)); memset (&current_event, 0, sizeof (current_event));
add_process (pid, attached);
child_init_thread_list (); child_init_thread_list ();
if (the_low_target.initial_stuff != NULL) if (the_low_target.initial_stuff != NULL)
@ -320,7 +330,7 @@ static void
child_fetch_inferior_registers (int r) child_fetch_inferior_registers (int r)
{ {
int regno; 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) if (r == -1 || r == 0 || r > NUM_REGS)
child_fetch_inferior_registers (NUM_REGS); child_fetch_inferior_registers (NUM_REGS);
else else
@ -334,7 +344,7 @@ static void
child_store_inferior_registers (int r) child_store_inferior_registers (int r)
{ {
int regno; 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) if (r == -1 || r == 0 || r > NUM_REGS)
child_store_inferior_registers (NUM_REGS); child_store_inferior_registers (NUM_REGS);
else else
@ -540,7 +550,7 @@ win32_create_inferior (char *program, char **program_args)
CloseHandle (pi.hThread); CloseHandle (pi.hThread);
#endif #endif
do_initial_child_stuff (pi.hProcess, pi.dwProcessId); do_initial_child_stuff (pi.hProcess, pi.dwProcessId, 0);
return current_process_id; return current_process_id;
} }
@ -571,7 +581,7 @@ win32_attach (unsigned long pid)
/* win32_wait needs to know we're attaching. */ /* win32_wait needs to know we're attaching. */
attaching = 1; attaching = 1;
do_initial_child_stuff (h, pid); do_initial_child_stuff (h, pid, 1);
return 0; return 0;
} }
@ -639,11 +649,13 @@ win32_clear_inferiors (void)
} }
/* Kill all inferiors. */ /* Kill all inferiors. */
static void static int
win32_kill (void) win32_kill (int pid)
{ {
struct process_info *process;
if (current_process_handle == NULL) if (current_process_handle == NULL)
return; return -1;
TerminateProcess (current_process_handle, 0); TerminateProcess (current_process_handle, 0);
for (;;) for (;;)
@ -662,12 +674,17 @@ win32_kill (void)
} }
win32_clear_inferiors (); win32_clear_inferiors ();
process = find_process_pid (pid);
remove_process (process);
return 0;
} }
/* Detach from all inferiors. */ /* Detach from inferior PID. */
static int static int
win32_detach (void) win32_detach (int pid)
{ {
struct process_info *process;
winapi_DebugActiveProcessStop DebugActiveProcessStop = NULL; winapi_DebugActiveProcessStop DebugActiveProcessStop = NULL;
winapi_DebugSetProcessKillOnExit DebugSetProcessKillOnExit = NULL; winapi_DebugSetProcessKillOnExit DebugSetProcessKillOnExit = NULL;
#ifdef _WIN32_WCE #ifdef _WIN32_WCE
@ -684,7 +701,7 @@ win32_detach (void)
{ {
struct thread_resume resume; struct thread_resume resume;
resume.thread = -1; resume.thread = minus_one_ptid;
resume.kind = resume_continue; resume.kind = resume_continue;
resume.sig = 0; resume.sig = 0;
win32_resume (&resume, 1); win32_resume (&resume, 1);
@ -694,6 +711,8 @@ win32_detach (void)
return -1; return -1;
DebugSetProcessKillOnExit (FALSE); DebugSetProcessKillOnExit (FALSE);
process = find_process_pid (pid);
remove_process (process);
win32_clear_inferiors (); win32_clear_inferiors ();
return 0; return 0;
@ -701,11 +720,9 @@ win32_detach (void)
/* Wait for inferiors to end. */ /* Wait for inferiors to end. */
static void static void
win32_join (void) win32_join (int pid)
{ {
extern unsigned long signal_pid; HANDLE h = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid);
HANDLE h = OpenProcess (PROCESS_ALL_ACCESS, FALSE, signal_pid);
if (h != NULL) if (h != NULL)
{ {
WaitForSingleObject (h, INFINITE); WaitForSingleObject (h, INFINITE);
@ -715,13 +732,13 @@ win32_join (void)
/* Return 1 iff the thread with thread ID TID is alive. */ /* Return 1 iff the thread with thread ID TID is alive. */
static int static int
win32_thread_alive (unsigned long tid) win32_thread_alive (ptid_t ptid)
{ {
int res; int res;
/* Our thread list is reliable; don't bother to poll target /* Our thread list is reliable; don't bother to poll target
threads. */ threads. */
if (find_inferior_id (&all_threads, tid) != NULL) if (find_inferior_id (&all_threads, ptid) != NULL)
res = 1; res = 1;
else else
res = 0; res = 0;
@ -738,11 +755,12 @@ win32_resume (struct thread_resume *resume_info, size_t n)
int step; int step;
win32_thread_info *th; win32_thread_info *th;
DWORD continue_status = DBG_CONTINUE; DWORD continue_status = DBG_CONTINUE;
ptid_t ptid;
/* This handles the very limited set of resume packets that GDB can /* This handles the very limited set of resume packets that GDB can
currently produce. */ currently produce. */
if (n == 1 && resume_info[0].thread == -1) if (n == 1 && ptid_equal (resume_info[0].thread, minus_one_ptid))
tid = -1; tid = -1;
else if (n > 1) else if (n > 1)
tid = -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. */ the Windows resume code do the right thing for thread switching. */
tid = current_event.dwThreadId; 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; sig = resume_info[0].sig;
step = resume_info[0].kind == resume_step; 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; last_sig = TARGET_SIGNAL_0;
/* Get context for the currently selected thread. */ /* 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)
{ {
if (th->context.ContextFlags) if (th->context.ContextFlags)
@ -1295,6 +1314,8 @@ auto_delete_breakpoint (CORE_ADDR stop_pc)
static int static int
get_child_debug_event (struct target_waitstatus *ourstatus) get_child_debug_event (struct target_waitstatus *ourstatus)
{ {
ptid_t ptid;
last_sig = TARGET_SIGNAL_0; last_sig = TARGET_SIGNAL_0;
ourstatus->kind = TARGET_WAITKIND_SPURIOUS; ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
@ -1349,9 +1370,9 @@ get_child_debug_event (struct target_waitstatus *ourstatus)
gotevent: gotevent:
ptid = debug_event_ptid (&current_event);
current_inferior = current_inferior =
(struct thread_info *) find_inferior_id (&all_threads, (struct thread_info *) find_inferior_id (&all_threads, ptid);
current_event.dwThreadId);
switch (current_event.dwDebugEventCode) switch (current_event.dwDebugEventCode)
{ {
@ -1362,8 +1383,9 @@ get_child_debug_event (struct target_waitstatus *ourstatus)
(unsigned) current_event.dwThreadId)); (unsigned) current_event.dwThreadId));
/* Record the existence of this thread. */ /* Record the existence of this thread. */
child_add_thread (current_event.dwThreadId, child_add_thread (current_event.dwProcessId,
current_event.u.CreateThread.hThread); current_event.dwThreadId,
current_event.u.CreateThread.hThread);
break; break;
case EXIT_THREAD_DEBUG_EVENT: case EXIT_THREAD_DEBUG_EVENT:
@ -1371,7 +1393,8 @@ get_child_debug_event (struct target_waitstatus *ourstatus)
"for pid=%d tid=%x\n", "for pid=%d tid=%x\n",
(unsigned) current_event.dwProcessId, (unsigned) current_event.dwProcessId,
(unsigned) current_event.dwThreadId)); (unsigned) current_event.dwThreadId));
child_delete_thread (current_event.dwThreadId); child_delete_thread (current_event.dwProcessId,
current_event.dwThreadId);
break; break;
case CREATE_PROCESS_DEBUG_EVENT: case CREATE_PROCESS_DEBUG_EVENT:
@ -1388,10 +1411,11 @@ get_child_debug_event (struct target_waitstatus *ourstatus)
ourstatus->value.execd_pathname = "Main executable"; ourstatus->value.execd_pathname = "Main executable";
/* Add the main thread. */ /* Add the main thread. */
child_add_thread (main_thread_id, child_add_thread (current_event.dwProcessId,
main_thread_id,
current_event.u.CreateProcessInfo.hThread); current_event.u.CreateProcessInfo.hThread);
ourstatus->value.related_pid = current_event.dwThreadId; ourstatus->value.related_pid = debug_event_ptid (&current_event);
#ifdef _WIN32_WCE #ifdef _WIN32_WCE
if (!attaching) if (!attaching)
{ {
@ -1467,17 +1491,18 @@ get_child_debug_event (struct target_waitstatus *ourstatus)
} }
current_inferior = current_inferior =
(struct thread_info *) find_inferior_id (&all_threads, (struct thread_info *) find_inferior_id (&all_threads, ptid);
current_event.dwThreadId);
return 1; return 1;
} }
/* Wait for the inferior process to change state. /* Wait for the inferior process to change state.
STATUS will be filled in with a response code to send to GDB. STATUS will be filled in with a response code to send to GDB.
Returns the signal which caused the process to stop. */ Returns the signal which caused the process to stop. */
static unsigned long static ptid_t
win32_wait (struct target_waitstatus *ourstatus, int options) win32_wait (ptid_t ptid, struct target_waitstatus *ourstatus, int options)
{ {
struct process_info *process;
while (1) while (1)
{ {
if (!get_child_debug_event (ourstatus)) 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", OUTMSG2 (("Child exited with retcode = %x\n",
ourstatus->value.integer)); ourstatus->value.integer));
process = find_process_pid (current_process_id);
remove_process (process);
win32_clear_inferiors (); win32_clear_inferiors ();
return current_event.dwProcessId; return pid_to_ptid (current_event.dwProcessId);
case TARGET_WAITKIND_STOPPED: case TARGET_WAITKIND_STOPPED:
case TARGET_WAITKIND_LOADED: case TARGET_WAITKIND_LOADED:
OUTMSG2 (("Child Stopped with signal = %d \n", 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) if (ourstatus->kind == TARGET_WAITKIND_LOADED)
ourstatus->kind = TARGET_WAITKIND_STOPPED; ourstatus->kind = TARGET_WAITKIND_STOPPED;
return current_event.dwThreadId; return debug_event_ptid (&current_event);
default: default:
OUTMSG (("Ignoring unknown internal event, %d\n", ourstatus->kind)); OUTMSG (("Ignoring unknown internal event, %d\n", ourstatus->kind));
/* fall-through */ /* fall-through */