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>
Non-stop mode support.

View File

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

View File

@ -30,12 +30,88 @@ struct thread_info
unsigned int gdb_id;
};
struct inferior_list all_processes;
struct inferior_list all_threads;
struct inferior_list all_dlls;
int dlls_changed;
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_dll(inf) ((struct dll_info *)(inf))
@ -93,7 +169,7 @@ remove_inferior (struct inferior_list *list,
}
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));
@ -108,40 +184,38 @@ add_thread (unsigned long thread_id, void *target_data, unsigned int gdb_id)
new_thread->target_data = target_data;
set_inferior_regcache_data (new_thread, new_register_cache ());
new_thread->gdb_id = gdb_id;
}
unsigned int
thread_id_to_gdb_id (unsigned long thread_id)
ptid_t
thread_id_to_gdb_id (ptid_t thread_id)
{
struct inferior_list_entry *inf = all_threads.head;
while (inf != NULL)
{
struct thread_info *thread = get_thread (inf);
if (inf->id == thread_id)
return thread->gdb_id;
if (ptid_equal (inf->id, thread_id))
return thread_id;
inf = inf->next;
}
return 0;
return null_ptid;
}
unsigned int
ptid_t
thread_to_gdb_id (struct thread_info *thread)
{
return thread->gdb_id;
return thread->entry.id;
}
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;
while (inf != NULL)
{
struct thread_info *thread = get_thread (inf);
if (thread->gdb_id == gdb_id)
if (ptid_equal (thread->entry.id, ptid))
return thread;
inf = inf->next;
}
@ -149,12 +223,12 @@ gdb_id_to_thread (unsigned int gdb_id)
return NULL;
}
unsigned long
gdb_id_to_thread_id (unsigned int gdb_id)
ptid_t
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
@ -192,13 +266,13 @@ find_inferior (struct inferior_list *list,
}
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;
while (inf != NULL)
{
if (inf->id == id)
if (ptid_equal (inf->id, id))
return inf;
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));
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->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;
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);
}
@ -327,7 +401,7 @@ pull_pid_from_list (struct inferior_list *list, unsigned long pid)
{
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)
return 0;
else
@ -337,3 +411,56 @@ pull_pid_from_list (struct inferior_list *list, unsigned long pid)
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>
#endif
#include "gdb_proc_service.h"
#ifdef HAVE_LINUX_REGSETS
typedef void (*regset_fill_func) (void *);
typedef void (*regset_store_func) (const void *);
@ -41,6 +43,19 @@ struct regset_info
extern struct regset_info target_regsets[];
#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
{
/* Architecture-specific setup. */
@ -78,14 +93,14 @@ struct linux_target_ops
extern struct linux_target_ops the_low_target;
#define pid_of(proc) ((proc)->head.id)
#define lwpid_of(proc) ((proc)->head.id)
#define pid_of(proc) ptid_get_pid ((proc)->head.id)
#define lwpid_of(proc) ptid_get_lwp ((proc)->head.id)
#define get_lwp(inf) ((struct lwp_info *)(inf))
#define get_thread_lwp(thr) (get_lwp (inferior_target_data (thr)))
#define get_lwp_thread(proc) ((struct thread_info *) \
find_inferior_id (&all_threads, \
lwpid_of (get_lwp (proc))))
get_lwp (proc)->head.id))
struct lwp_info
{
@ -106,6 +121,11 @@ struct lwp_info
event already received in a wait()). */
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. */
int last_status;
@ -150,3 +170,5 @@ void linux_attach_lwp (unsigned long pid);
int thread_db_init (int use_events);
int thread_db_get_tls_address (struct thread_info *thread, CORE_ADDR offset,
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);
};
struct breakpoint *breakpoints;
void
set_breakpoint_at (CORE_ADDR where, int (*handler) (CORE_ADDR))
{
struct process_info *proc = current_process ();
struct breakpoint *bp;
if (breakpoint_data == NULL)
@ -67,24 +66,25 @@ set_breakpoint_at (CORE_ADDR where, int (*handler) (CORE_ADDR))
bp->pc = where;
bp->handler = handler;
bp->next = breakpoints;
breakpoints = bp;
bp->next = proc->breakpoints;
proc->breakpoints = bp;
}
static void
delete_breakpoint (struct breakpoint *bp)
{
struct process_info *proc = current_process ();
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,
breakpoint_len);
free (bp);
return;
}
cur = breakpoints;
cur = proc->breakpoints;
while (cur->next)
{
if (cur->next == bp)
@ -102,7 +102,8 @@ delete_breakpoint (struct breakpoint *bp)
static struct breakpoint *
find_breakpoint_at (CORE_ADDR where)
{
struct breakpoint *bp = breakpoints;
struct process_info *proc = current_process ();
struct breakpoint *bp = proc->breakpoints;
while (bp != NULL)
{
@ -225,7 +226,8 @@ set_breakpoint_data (const unsigned char *bp_data, int bp_len)
void
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;
for (; bp != NULL; bp = bp->next)
@ -258,7 +260,8 @@ check_mem_read (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
void
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;
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
delete_all_breakpoints (void)
{
while (breakpoints)
delete_breakpoint (breakpoints);
struct process_info *proc = current_process ();
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);
/* 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 */

View File

@ -102,8 +102,7 @@ ps_lgetregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, prgregset_t gregset)
struct lwp_info *lwp;
struct thread_info *reg_inferior, *save_inferior;
lwp = (struct lwp_info *) find_inferior_id (&all_lwps,
lwpid);
lwp = find_lwp_pid (pid_to_ptid (lwpid));
if (lwp == NULL)
return PS_ERR;
@ -157,5 +156,5 @@ ps_lsetfpregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, void *fpregset)
pid_t
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. */
struct sym_cache
{
const char *name;
char *name;
CORE_ADDR addr;
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;
struct ui_file *gdb_stdlog;
@ -317,6 +310,29 @@ fromhex (int a)
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
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;
}
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.
The data of the packet is in BUF, and the length of the
packet is in CNT. Returns >= 0 on success, -1 otherwise. */
@ -957,12 +1070,12 @@ dead_thread_notify (int id)
}
void
prepare_resume_reply (char *buf, unsigned long ptid,
prepare_resume_reply (char *buf, ptid_t ptid,
struct target_waitstatus *status)
{
if (debug_threads)
fprintf (stderr, "Writing resume reply for %lu:%d\n\n",
ptid, status->kind);
fprintf (stderr, "Writing resume reply for %s:%d\n\n",
target_pid_to_str (ptid), status->kind);
switch (status->kind)
{
@ -978,7 +1091,7 @@ prepare_resume_reply (char *buf, unsigned long ptid,
saved_inferior = current_inferior;
current_inferior = gdb_id_to_thread (ptid);
current_inferior = find_thread_pid (ptid);
if (the_target->stopped_by_watchpoint != NULL
&& (*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
if we do not specify a thread, and there's no way for
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
GDB's back. */
if (!non_stop)
general_thread = ptid;
sprintf (buf, "thread:%lx;", ptid);
sprintf (buf, "thread:");
buf += strlen (buf);
buf = write_ptid (buf, ptid);
strcat (buf, ";");
buf += strlen (buf);
}
}
@ -1043,10 +1159,18 @@ prepare_resume_reply (char *buf, unsigned long ptid,
}
break;
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;
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;
default:
error ("unhandled waitkind");
@ -1174,6 +1298,31 @@ decode_search_memory_packet (const char *buf, int packet_len,
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.
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;
int len;
struct sym_cache *sym;
struct process_info *proc;
proc = current_process ();
/* 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)
{
*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
libpthread.so. It might not be an appropriate time to look
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;
/* Send the request. */
@ -1257,8 +1409,8 @@ look_up_one_symbol (const char *name, CORE_ADDR *addrp)
sym = xmalloc (sizeof (*sym));
sym->name = xstrdup (name);
sym->addr = *addrp;
sym->next = symbol_cache;
symbol_cache = sym;
sym->next = proc->symbol_cache;
proc->symbol_cache = sym;
return 1;
}

View File

@ -32,17 +32,17 @@
#include <malloc.h>
#endif
unsigned long cont_thread;
unsigned long general_thread;
unsigned long step_thread;
ptid_t cont_thread;
ptid_t general_thread;
ptid_t step_thread;
int server_waiting;
static int extended_protocol;
static int attached;
static int response_needed;
static int exit_requested;
int multi_process;
int non_stop;
static char **program_argv, **wrapper_argv;
@ -90,7 +90,7 @@ int disable_packet_qfThreadInfo;
/* Last status reported to GDB. */
static struct target_waitstatus last_status;
static unsigned long last_ptid;
static ptid_t last_ptid;
static char *own_buf;
static unsigned char *mem_buf;
@ -104,7 +104,7 @@ struct vstop_notif
struct vstop_notif *next;
/* Thread or process that got the event. */
unsigned long ptid;
ptid_t ptid;
/* Event info. */
struct target_waitstatus status;
@ -116,7 +116,7 @@ static struct vstop_notif *notif_queue = NULL;
/* Put a stop reply to the stop reply queue. */
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;
@ -153,7 +153,7 @@ queue_stop_reply (unsigned long ptid, struct target_waitstatus *status)
we aren't sending one yet. */
void
push_event (unsigned long ptid, struct target_waitstatus *status)
push_event (ptid_t ptid, struct target_waitstatus *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
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;
notif_queue = next;
next = reply->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)
{
char **new_argv = argv;
attached = 0;
if (wrapper_argv != NULL)
{
@ -253,13 +263,13 @@ start_inferior (char **argv)
if (wrapper_argv != NULL)
{
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.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)
return signal_pid;
@ -268,7 +278,7 @@ start_inferior (char **argv)
{
(*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)
return signal_pid;
}
@ -279,7 +289,7 @@ start_inferior (char **argv)
/* Wait till we are at 1st instruction in program, return new pid
(assuming success). */
last_ptid = mywait (&last_status, 0, 0);
last_ptid = mywait (pid_to_ptid (signal_pid), &last_status, 0, 0);
return signal_pid;
}
@ -293,8 +303,6 @@ attach_inferior (int pid)
if (myattach (pid) != 0)
return -1;
attached = 1;
fprintf (stderr, "Attached; pid = %d\n", pid);
fflush (stderr);
@ -305,7 +313,7 @@ attach_inferior (int pid)
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
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. */
if (strcmp ("qC", own_buf) == 0 && !disable_packet_qC)
{
unsigned long gdb_id;
ptid_t gdb_id;
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;
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);
}
sprintf (own_buf, "QC%lx", gdb_id);
sprintf (own_buf, "QC");
own_buf += 2;
own_buf = write_ptid (own_buf, gdb_id);
return;
}
@ -684,21 +695,28 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
{
if (strcmp ("qfThreadInfo", own_buf) == 0)
{
ptid_t gdb_id;
require_running (own_buf);
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;
return;
}
if (strcmp ("qsThreadInfo", own_buf) == 0)
{
ptid_t gdb_id;
require_running (own_buf);
if (thread_ptr != NULL)
{
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;
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
&& (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);
/* 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)
strcat (own_buf, ";qXfer:osdata:read+");
strcat (own_buf, ";multiprocess+");
if (target_supports_non_stop ())
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;
CORE_ADDR parts[2], address = 0;
int i, err;
unsigned long ptid = 0;
ptid_t ptid = null_ptid;
require_running (own_buf);
@ -1111,7 +1146,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
}
if (i == 0)
ptid = strtoul (p, NULL, 16);
ptid = read_ptid (p, NULL);
else
decode_address (&parts[i - 1], p, len);
p = p2;
@ -1121,7 +1156,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
err = 1;
else
{
struct thread_info *thread = gdb_id_to_thread (ptid);
struct thread_info *thread = find_thread_pid (ptid);
if (thread == NULL)
err = 2;
@ -1208,10 +1243,30 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
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);
strcpy (own_buf, attached ? "1" : "0");
struct process_info *process;
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;
}
@ -1227,7 +1282,7 @@ handle_v_cont (char *own_buf)
char *p, *q;
int n = 0, i = 0;
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
for every action. */
@ -1277,7 +1332,7 @@ handle_v_cont (char *own_buf)
if (p[0] == 0)
{
resume_info[i].thread = -1;
resume_info[i].thread = minus_one_ptid;
default_action = resume_info[i];
/* 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] == ':')
{
unsigned int gdb_id = strtoul (p + 1, &q, 16);
unsigned long thread_id;
ptid_t ptid = read_ptid (p + 1, &q);
if (p == q)
goto err;
@ -1294,11 +1348,7 @@ handle_v_cont (char *own_buf)
if (p[0] != ';' && p[0] != 0)
goto err;
thread_id = gdb_id_to_thread_id (gdb_id);
if (thread_id)
resume_info[i].thread = thread_id;
else
goto err;
resume_info[i].thread = ptid;
i++;
}
@ -1309,11 +1359,11 @@ handle_v_cont (char *own_buf)
/* Still used in occasional places in the backend. */
if (n == 1
&& resume_info[0].thread != -1
&& !ptid_equal (resume_info[0].thread, minus_one_ptid)
&& resume_info[0].kind != resume_stop)
cont_thread = resume_info[0].thread;
else
cont_thread = -1;
cont_thread = minus_one_ptid;
set_desired_inferior (0);
if (!non_stop)
@ -1327,7 +1377,7 @@ handle_v_cont (char *own_buf)
write_ok (own_buf);
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);
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. */
static void
handle_v_stopped (char *own_buf)
@ -1473,7 +1547,8 @@ handle_v_stopped (char *own_buf)
struct vstop_notif *head;
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;
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 (target_running ())
if (!multi_process && target_running ())
{
fprintf (stderr, "Already debugging a process\n");
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 (target_running ())
if (!multi_process && target_running ())
{
fprintf (stderr, "Already debugging a process\n");
write_enn (own_buf);
@ -1532,6 +1607,18 @@ handle_v_requests (char *own_buf, int packet_len, int *new_packet_len)
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)
{
handle_v_stopped (own_buf);
@ -1556,7 +1643,8 @@ myresume (char *own_buf, int step, int sig)
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)
{
@ -1572,7 +1660,7 @@ myresume (char *own_buf, int step, int sig)
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].sig = 0;
n++;
@ -1587,7 +1675,7 @@ myresume (char *own_buf, int step, int sig)
write_ok (own_buf);
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);
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
stopped thread. */
static void
queue_stop_reply_callback (struct inferior_list_entry *entry)
static int
queue_stop_reply_callback (struct inferior_list_entry *entry, void *arg)
{
struct target_waitstatus status;
int pid = * (int *) arg;
status.kind = TARGET_WAITKIND_STOPPED;
status.value.sig = TARGET_SIGNAL_TRAP;
if (pid == -1
|| ptid_get_pid (entry->id) == pid)
{
struct target_waitstatus status;
/* Pass the last stop reply back to GDB, but don't notify. */
queue_stop_reply (entry->id, &status);
status.kind = TARGET_WAITKIND_STOPPED;
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. */
@ -1623,8 +1719,9 @@ handle_status (char *own_buf)
if (non_stop)
{
discard_queued_stop_replies ();
for_each_inferior (&all_threads, queue_stop_reply_callback);
int pid = -1;
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
stopped thread, which is the same handling of the vStopped
@ -1690,6 +1787,52 @@ gdbserver_show_disableable (FILE *stream)
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
main (int argc, char *argv[])
{
@ -1827,6 +1970,7 @@ main (int argc, char *argv[])
exit (1);
}
initialize_inferiors ();
initialize_async_io ();
initialize_low ();
@ -1861,7 +2005,7 @@ main (int argc, char *argv[])
{
last_status.kind = TARGET_WAITKIND_EXITED;
last_status.value.integer = 0;
last_ptid = -1;
last_ptid = minus_one_ptid;
}
/* Don't report shared library events on the initial connection,
@ -1871,8 +2015,9 @@ main (int argc, char *argv[])
if (setjmp (toplevel))
{
fprintf (stderr, "Killing inferior\n");
kill_inferior ();
fprintf (stderr, "Killing all inferiors\n");
for_each_inferior (&all_processes,
kill_inferior_callback);
exit (1);
}
@ -1891,6 +2036,7 @@ main (int argc, char *argv[])
while (1)
{
noack_mode = 0;
multi_process = 0;
non_stop = 0;
remote_open (port);
@ -1916,10 +2062,8 @@ main (int argc, char *argv[])
if (exit_requested)
{
if (attached)
detach_inferior ();
else
kill_inferior ();
for_each_inferior (&all_processes,
detach_or_kill_inferior_callback);
exit (0);
}
else
@ -1941,6 +2085,7 @@ process_serial_event (void)
int signal;
unsigned int len;
CORE_ADDR mem_addr;
int pid;
unsigned char sig;
int packet_len;
int new_packet_len = -1;
@ -1976,12 +2121,22 @@ process_serial_event (void)
break;
case 'D':
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);
else
{
discard_queued_stop_replies ();
discard_queued_stop_replies (pid);
write_ok (own_buf);
if (extended_protocol)
@ -1989,7 +2144,7 @@ process_serial_event (void)
/* Treat this like a normal program exit. */
last_status.kind = TARGET_WAITKIND_EXITED;
last_status.value.integer = 0;
last_ptid = signal_pid;
last_ptid = pid_to_ptid (pid);
current_inferior = NULL;
}
@ -2001,9 +2156,8 @@ process_serial_event (void)
/* If we are attached, then we can exit. Otherwise, we
need to hang around doing nothing, until the child is
gone. */
if (!attached)
join_inferior ();
for_each_inferior (&all_processes,
join_inferiors_callback);
exit (0);
}
}
@ -2018,16 +2172,38 @@ process_serial_event (void)
case 'H':
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);
gdb_id = strtoul (&own_buf[2], NULL, 16);
if (gdb_id == 0 || gdb_id == -1)
thread_id = gdb_id;
gdb_id = read_ptid (&own_buf[2], NULL);
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
{
thread_id = gdb_id_to_thread_id (gdb_id);
if (thread_id == 0)
if (ptid_equal (thread_id, null_ptid))
{
write_enn (own_buf);
break;
@ -2036,7 +2212,7 @@ process_serial_event (void)
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
the currently selected thread is still valid. If
@ -2194,13 +2370,12 @@ process_serial_event (void)
case 'k':
response_needed = 0;
if (!target_running ())
/* The packet we received doesn't make sense - but we
can't reply to it, either. */
/* The packet we received doesn't make sense - but we can't
reply to it, either. */
return;
fprintf (stderr, "Killing inferior\n");
kill_inferior ();
discard_queued_stop_replies ();
fprintf (stderr, "Killing all inferiors\n");
for_each_inferior (&all_processes, kill_inferior_callback);
/* When using the extended protocol, we wait with no program
running. The traditional protocol will exit instead. */
@ -2217,12 +2392,13 @@ process_serial_event (void)
}
case 'T':
{
unsigned long gdb_id, thread_id;
ptid_t gdb_id, thread_id;
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);
if (thread_id == 0)
if (ptid_equal (thread_id, null_ptid))
{
write_enn (own_buf);
break;
@ -2242,10 +2418,8 @@ process_serial_event (void)
if (extended_protocol)
{
if (target_running ())
{
kill_inferior ();
discard_queued_stop_replies ();
}
for_each_inferior (&all_processes,
kill_inferior_callback);
fprintf (stderr, "GDBserver restarting\n");
/* 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)
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)
{

View File

@ -85,6 +85,70 @@ typedef unsigned char gdb_byte;
least the size of a (void *). */
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,
processes, etc. */
struct inferior_list
@ -94,7 +158,7 @@ struct inferior_list
};
struct inferior_list_entry
{
unsigned long id;
ptid_t id;
struct inferior_list_entry *next;
};
@ -108,6 +172,36 @@ struct dll_info
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 "gdb/signals.h"
#include "gdb_signals.h"
@ -120,22 +214,33 @@ void initialize_low ();
/* From inferiors.c. */
extern struct inferior_list all_processes;
extern struct inferior_list all_threads;
extern struct inferior_list all_dlls;
extern int dlls_changed;
void initialize_inferiors (void);
void add_inferior_to_list (struct inferior_list *list,
struct inferior_list_entry *new_inferior);
void for_each_inferior (struct inferior_list *list,
void (*action) (struct inferior_list_entry *));
extern struct thread_info *current_inferior;
void remove_inferior (struct inferior_list *list,
struct inferior_list_entry *entry);
void remove_thread (struct thread_info *thread);
void add_thread (unsigned long thread_id, void *target_data, unsigned int);
unsigned int thread_id_to_gdb_id (unsigned long);
unsigned int thread_to_gdb_id (struct thread_info *);
unsigned long gdb_id_to_thread_id (unsigned int);
void add_thread (ptid_t ptid, void *target_data);
struct process_info *add_process (int pid, int attached);
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);
void clear_inferiors (void);
struct inferior_list_entry *find_inferior
@ -144,7 +249,7 @@ struct inferior_list_entry *find_inferior
void *),
void *arg);
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 set_inferior_target_data (struct thread_info *, void *);
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 */
extern unsigned long cont_thread;
extern unsigned long general_thread;
extern unsigned long step_thread;
extern ptid_t cont_thread;
extern ptid_t general_thread;
extern ptid_t step_thread;
extern int server_waiting;
extern int debug_threads;
@ -172,6 +277,7 @@ extern int disable_packet_Tthread;
extern int disable_packet_qC;
extern int disable_packet_qfThreadInfo;
extern int multi_process;
extern int non_stop;
/* 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_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. */
extern int handle_vFile (char *, int, int *);
@ -203,6 +309,9 @@ extern int all_symbols_looked_up;
extern int noack_mode;
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_binary (char *buf, int len);
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 new_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);
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,
int out_maxlen);
void clear_symbol_cache (struct sym_cache **symcache_p);
int look_up_one_symbol (const char *name, CORE_ADDR *addrp);
void monitor_output (const char *msg);

View File

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

View File

@ -29,10 +29,7 @@ set_desired_inferior (int use_general)
struct thread_info *found;
if (use_general == 1)
{
found = (struct thread_info *) find_inferior_id (&all_threads,
general_thread);
}
found = find_thread_pid (general_thread);
else
{
found = NULL;
@ -40,14 +37,14 @@ set_desired_inferior (int use_general)
/* If we are continuing any (all) thread(s), use step_thread
to decide which thread to step and/or send the specified
signal to. */
if ((step_thread != 0 && step_thread != -1)
&& (cont_thread == 0 || cont_thread == -1))
found = (struct thread_info *) find_inferior_id (&all_threads,
step_thread);
if ((!ptid_equal (step_thread, null_ptid)
&& !ptid_equal (step_thread, minus_one_ptid))
&& (ptid_equal (cont_thread, null_ptid)
|| ptid_equal (cont_thread, minus_one_ptid)))
found = find_thread_pid (step_thread);
if (found == NULL)
found = (struct thread_info *) find_inferior_id (&all_threads,
cont_thread);
found = find_thread_pid (cont_thread);
}
if (found == NULL)
@ -88,28 +85,24 @@ write_inferior_memory (CORE_ADDR memaddr, const unsigned char *myaddr,
return res;
}
unsigned long
mywait (struct target_waitstatus *ourstatus, int options,
ptid_t
mywait (ptid_t ptid, struct target_waitstatus *ourstatus, int options,
int connected_wait)
{
unsigned long ret;
ptid_t ret;
if (connected_wait)
server_waiting = 1;
ret = (*the_target->wait) (ourstatus, options);
ret = (*the_target->wait) (ptid, ourstatus, options);
if (ourstatus->kind == TARGET_WAITKIND_EXITED
|| ourstatus->kind == TARGET_WAITKIND_SIGNALLED)
{
if (ourstatus->kind == TARGET_WAITKIND_EXITED)
fprintf (stderr,
"\nChild exited with status %d\n", ourstatus->value.sig);
if (ourstatus->kind == TARGET_WAITKIND_SIGNALLED)
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 (ourstatus->kind == TARGET_WAITKIND_EXITED)
fprintf (stderr,
"\nChild exited with status %d\n", ourstatus->value.sig);
else if (ourstatus->kind == TARGET_WAITKIND_SIGNALLED)
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)
server_waiting = 0;
@ -137,3 +130,27 @@ set_target_ops (struct target_ops *target)
the_target = (struct target_ops *) xmalloc (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
{
unsigned long thread;
ptid_t thread;
/* How to "resume". */
enum resume_kind kind;
@ -96,7 +96,7 @@ struct target_waitstatus
{
int integer;
enum target_signal sig;
unsigned long related_pid;
ptid_t related_pid;
char *execd_pathname;
}
value;
@ -129,31 +129,38 @@ struct target_ops
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.
Return -1 on failure, and 0 on success. */
/* Detach from inferior PID. Return -1 on failure, and 0 on
success. */
int (*detach) (void);
int (*detach) (int pid);
/* Wait for inferiors to end. */
void (*join) (void);
/* Wait for inferior PID to exit. */
void (*join) (int pid);
/* 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. */
void (*resume) (struct thread_resume *resume_info, size_t n);
/* 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.
@ -280,11 +287,11 @@ void set_target_ops (struct target_ops *);
#define myattach(pid) \
(*the_target->attach) (pid)
#define kill_inferior() \
(*the_target->kill) ()
#define kill_inferior(pid) \
(*the_target->kill) (pid)
#define detach_inferior() \
(*the_target->detach) ()
#define detach_inferior(pid) \
(*the_target->detach) (pid)
#define mythread_alive(pid) \
(*the_target->thread_alive) (pid)
@ -295,8 +302,8 @@ void set_target_ops (struct target_ops *);
#define store_inferior_registers(regno) \
(*the_target->store_registers) (regno)
#define join_inferior() \
(*the_target->join) ()
#define join_inferior(pid) \
(*the_target->join) (pid)
#define target_supports_non_stop() \
(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);
unsigned long mywait (struct target_waitstatus *ourstatus, int options,
int connected_wait);
ptid_t mywait (ptid_t ptid, struct target_waitstatus *ourstatus, int options,
int connected_wait);
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);
const char *target_pid_to_str (ptid_t);
#endif /* TARGET_H */

View File

@ -35,14 +35,7 @@ static int thread_db_use_events;
#include <stdint.h>
/* Structure that identifies the child process for the
<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_one_thread (ptid_t);
static int find_new_threads_callback (const td_thrhandle_t *th_p, void *data);
static const char *
@ -137,6 +130,7 @@ thread_db_create_event (CORE_ADDR where)
td_event_msg_t msg;
td_err_e err;
struct lwp_info *lwp;
struct process_info_private *proc = current_process()->private;
if (debug_threads)
fprintf (stderr, "Thread creation event.\n");
@ -145,7 +139,7 @@ thread_db_create_event (CORE_ADDR where)
In the LinuxThreads implementation, this is safe,
because all events come from the manager thread
(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)
fprintf (stderr, "thread getmsg err: %s\n",
thread_db_err_str (err));
@ -155,7 +149,7 @@ thread_db_create_event (CORE_ADDR where)
created threads. */
lwp = get_thread_lwp (current_inferior);
if (lwp->thread_known == 0)
find_one_thread (lwpid_of (lwp));
find_one_thread (lwp->head.id);
/* msg.event == TD_EVENT_CREATE */
@ -181,6 +175,7 @@ thread_db_enable_reporting ()
td_thr_events_t events;
td_notify_t notify;
td_err_e err;
struct process_info_private *proc = current_process()->private;
/* Set the process wide mask saying which events we're interested in. */
td_event_emptyset (&events);
@ -192,7 +187,7 @@ thread_db_enable_reporting ()
td_event_addset (&events, TD_DEATH);
#endif
err = td_ta_set_event (thread_agent, &events);
err = td_ta_set_event (proc->thread_agent, &events);
if (err != TD_OK)
{
warning ("Unable to set global thread event mask: %s",
@ -201,7 +196,7 @@ thread_db_enable_reporting ()
}
/* 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)
{
warning ("Unable to get location for thread creation breakpoint: %s",
@ -216,7 +211,7 @@ thread_db_enable_reporting ()
with actual thread deaths (via wait). */
/* 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)
{
warning ("Unable to get location for thread death breakpoint: %s",
@ -231,21 +226,23 @@ thread_db_enable_reporting ()
}
static int
find_one_thread (int lwpid)
find_one_thread (ptid_t ptid)
{
td_thrhandle_t th;
td_thrinfo_t ti;
td_err_e err;
struct thread_info *inferior;
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);
if (lwp->thread_known)
return 1;
/* 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)
error ("Cannot get thread handle for LWP %d: %s",
lwpid, thread_db_err_str (err));
@ -259,10 +256,10 @@ find_one_thread (int lwpid)
fprintf (stderr, "Found thread %ld (LWP %d)\n",
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",
(long) lwpid_of (lwp), (long) ti.ti_lid);
(long) lwpid, (long) ti.ti_lid);
return 0;
}
@ -289,29 +286,24 @@ static void
maybe_attach_thread (const td_thrhandle_t *th_p, td_thrinfo_t *ti_p)
{
td_err_e err;
struct thread_info *inferior;
struct lwp_info *lwp;
inferior = (struct thread_info *) find_inferior_id (&all_threads,
ti_p->ti_lid);
if (inferior != NULL)
lwp = find_lwp_pid (pid_to_ptid (ti_p->ti_lid));
if (lwp != NULL)
return;
if (debug_threads)
fprintf (stderr, "Attaching to thread %ld (LWP %d)\n",
ti_p->ti_tid, ti_p->ti_lid);
linux_attach_lwp (ti_p->ti_lid);
inferior = (struct thread_info *) find_inferior_id (&all_threads,
ti_p->ti_lid);
if (inferior == NULL)
lwp = find_lwp_pid (pid_to_ptid (ti_p->ti_lid));
if (lwp == NULL)
{
warning ("Could not attach to thread %ld (LWP %d)\n",
ti_p->ti_tid, ti_p->ti_lid);
return;
}
lwp = inferior_target_data (inferior);
lwp->thread_known = 1;
lwp->th = *th_p;
@ -347,15 +339,18 @@ static void
thread_db_find_new_threads (void)
{
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.
First locate the initial thread. If it is not ready for
debugging yet, then stop. */
if (find_one_thread (all_threads.head->id) == 0)
if (find_one_thread (ptid) == 0)
return;
/* 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_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
if (err != TD_OK)
@ -385,18 +380,22 @@ thread_db_get_tls_address (struct thread_info *thread, CORE_ADDR offset,
psaddr_t addr;
td_err_e err;
struct lwp_info *lwp;
struct thread_info *saved_inferior;
lwp = get_thread_lwp (thread);
if (!lwp->thread_known)
find_one_thread (lwpid_of (lwp));
find_one_thread (lwp->head.id);
if (!lwp->thread_known)
return TD_NOTHR;
saved_inferior = current_inferior;
current_inferior = thread;
/* Note the cast through uintptr_t: this interface only works if
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. */
err = td_thr_tls_get_addr (&lwp->th, (psaddr_t) (uintptr_t) load_module,
offset, &addr);
current_inferior = saved_inferior;
if (err == TD_OK)
{
*address = (CORE_ADDR) (uintptr_t) addr;
@ -413,6 +412,8 @@ int
thread_db_init (int use_events)
{
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
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
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;
err = td_ta_new (&proc_handle, &thread_agent);
err = td_ta_new (&priv->proc_handle, &priv->thread_agent);
switch (err)
{
case TD_NOLIBTHREAD:
@ -445,7 +442,7 @@ thread_db_init (int use_events)
return 0;
thread_db_find_new_threads ();
thread_db_look_up_symbols ();
all_symbols_looked_up = 1;
proc->all_symbols_looked_up = 1;
return 1;
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
thread). */
static DWORD
current_inferior_tid (void)
static ptid_t
current_inferior_ptid (void)
{
win32_thread_info *th = inferior_target_data (current_inferior);
return th->tid;
return ((struct inferior_list_entry*) current_inferior)->id;
}
/* The current debug event from WaitForDebugEvent. */
static ptid_t
debug_event_ptid (DEBUG_EVENT *event)
{
return ptid_build (event->dwProcessId, event->dwThreadId, 0);
}
/* Get the thread context of the thread associated with TH. */
@ -137,12 +143,12 @@ win32_set_thread_context (win32_thread_info *th)
/* Find a thread record given a thread id. If GET_CONTEXT is set then
also retrieve the context for this thread. */
static win32_thread_info *
thread_rec (DWORD id, int get_context)
thread_rec (ptid_t ptid, int get_context)
{
struct thread_info *thread;
win32_thread_info *th;
thread = (struct thread_info *) find_inferior_id (&all_threads, id);
thread = (struct thread_info *) find_inferior_id (&all_threads, ptid);
if (thread == NULL)
return NULL;
@ -169,20 +175,21 @@ thread_rec (DWORD id, int get_context)
/* Add a thread to the thread list. */
static win32_thread_info *
child_add_thread (DWORD tid, HANDLE h)
child_add_thread (DWORD pid, DWORD tid, HANDLE h)
{
win32_thread_info *th;
ptid_t ptid = ptid_build (pid, tid, 0);
if ((th = thread_rec (tid, FALSE)))
if ((th = thread_rec (ptid, FALSE)))
return th;
th = xcalloc (1, sizeof (*th));
th->tid = tid;
th->h = h;
add_thread (tid, th, (unsigned int) tid);
add_thread (ptid, th);
set_inferior_regcache_data ((struct thread_info *)
find_inferior_id (&all_threads, tid),
find_inferior_id (&all_threads, ptid),
new_register_cache ());
if (the_low_target.thread_added != NULL)
@ -204,15 +211,17 @@ delete_thread_info (struct inferior_list_entry *thread)
/* Delete a thread from the list of threads. */
static void
child_delete_thread (DWORD id)
child_delete_thread (DWORD pid, DWORD tid)
{
struct inferior_list_entry *thread;
ptid_t ptid;
/* If the last thread is exiting, just return. */
if (all_threads.head == all_threads.tail)
return;
thread = find_inferior_id (&all_threads, id);
ptid = ptid_build (pid, tid, 0);
thread = find_inferior_id (&all_threads, ptid);
if (thread == NULL)
return;
@ -250,7 +259,7 @@ child_init_thread_list (void)
}
static void
do_initial_child_stuff (HANDLE proch, DWORD pid)
do_initial_child_stuff (HANDLE proch, DWORD pid, int attached)
{
last_sig = TARGET_SIGNAL_0;
@ -263,6 +272,7 @@ do_initial_child_stuff (HANDLE proch, DWORD pid)
memset (&current_event, 0, sizeof (current_event));
add_process (pid, attached);
child_init_thread_list ();
if (the_low_target.initial_stuff != NULL)
@ -320,7 +330,7 @@ static void
child_fetch_inferior_registers (int r)
{
int regno;
win32_thread_info *th = thread_rec (current_inferior_tid (), TRUE);
win32_thread_info *th = thread_rec (current_inferior_ptid (), TRUE);
if (r == -1 || r == 0 || r > NUM_REGS)
child_fetch_inferior_registers (NUM_REGS);
else
@ -334,7 +344,7 @@ static void
child_store_inferior_registers (int r)
{
int regno;
win32_thread_info *th = thread_rec (current_inferior_tid (), TRUE);
win32_thread_info *th = thread_rec (current_inferior_ptid (), TRUE);
if (r == -1 || r == 0 || r > NUM_REGS)
child_store_inferior_registers (NUM_REGS);
else
@ -540,7 +550,7 @@ win32_create_inferior (char *program, char **program_args)
CloseHandle (pi.hThread);
#endif
do_initial_child_stuff (pi.hProcess, pi.dwProcessId);
do_initial_child_stuff (pi.hProcess, pi.dwProcessId, 0);
return current_process_id;
}
@ -571,7 +581,7 @@ win32_attach (unsigned long pid)
/* win32_wait needs to know we're attaching. */
attaching = 1;
do_initial_child_stuff (h, pid);
do_initial_child_stuff (h, pid, 1);
return 0;
}
@ -639,11 +649,13 @@ win32_clear_inferiors (void)
}
/* Kill all inferiors. */
static void
win32_kill (void)
static int
win32_kill (int pid)
{
struct process_info *process;
if (current_process_handle == NULL)
return;
return -1;
TerminateProcess (current_process_handle, 0);
for (;;)
@ -662,12 +674,17 @@ win32_kill (void)
}
win32_clear_inferiors ();
process = find_process_pid (pid);
remove_process (process);
return 0;
}
/* Detach from all inferiors. */
/* Detach from inferior PID. */
static int
win32_detach (void)
win32_detach (int pid)
{
struct process_info *process;
winapi_DebugActiveProcessStop DebugActiveProcessStop = NULL;
winapi_DebugSetProcessKillOnExit DebugSetProcessKillOnExit = NULL;
#ifdef _WIN32_WCE
@ -684,7 +701,7 @@ win32_detach (void)
{
struct thread_resume resume;
resume.thread = -1;
resume.thread = minus_one_ptid;
resume.kind = resume_continue;
resume.sig = 0;
win32_resume (&resume, 1);
@ -694,6 +711,8 @@ win32_detach (void)
return -1;
DebugSetProcessKillOnExit (FALSE);
process = find_process_pid (pid);
remove_process (process);
win32_clear_inferiors ();
return 0;
@ -701,11 +720,9 @@ win32_detach (void)
/* Wait for inferiors to end. */
static void
win32_join (void)
win32_join (int pid)
{
extern unsigned long signal_pid;
HANDLE h = OpenProcess (PROCESS_ALL_ACCESS, FALSE, signal_pid);
HANDLE h = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid);
if (h != NULL)
{
WaitForSingleObject (h, INFINITE);
@ -715,13 +732,13 @@ win32_join (void)
/* Return 1 iff the thread with thread ID TID is alive. */
static int
win32_thread_alive (unsigned long tid)
win32_thread_alive (ptid_t ptid)
{
int res;
/* Our thread list is reliable; don't bother to poll target
threads. */
if (find_inferior_id (&all_threads, tid) != NULL)
if (find_inferior_id (&all_threads, ptid) != NULL)
res = 1;
else
res = 0;
@ -738,11 +755,12 @@ win32_resume (struct thread_resume *resume_info, size_t n)
int step;
win32_thread_info *th;
DWORD continue_status = DBG_CONTINUE;
ptid_t ptid;
/* This handles the very limited set of resume packets that GDB can
currently produce. */
if (n == 1 && resume_info[0].thread == -1)
if (n == 1 && ptid_equal (resume_info[0].thread, minus_one_ptid))
tid = -1;
else if (n > 1)
tid = -1;
@ -751,7 +769,7 @@ win32_resume (struct thread_resume *resume_info, size_t n)
the Windows resume code do the right thing for thread switching. */
tid = current_event.dwThreadId;
if (resume_info[0].thread != -1)
if (!ptid_equal (resume_info[0].thread, minus_one_ptid))
{
sig = resume_info[0].sig;
step = resume_info[0].kind == resume_step;
@ -777,7 +795,8 @@ win32_resume (struct thread_resume *resume_info, size_t n)
last_sig = TARGET_SIGNAL_0;
/* Get context for the currently selected thread. */
th = thread_rec (current_event.dwThreadId, FALSE);
ptid = debug_event_ptid (&current_event);
th = thread_rec (ptid, FALSE);
if (th)
{
if (th->context.ContextFlags)
@ -1295,6 +1314,8 @@ auto_delete_breakpoint (CORE_ADDR stop_pc)
static int
get_child_debug_event (struct target_waitstatus *ourstatus)
{
ptid_t ptid;
last_sig = TARGET_SIGNAL_0;
ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
@ -1349,9 +1370,9 @@ get_child_debug_event (struct target_waitstatus *ourstatus)
gotevent:
ptid = debug_event_ptid (&current_event);
current_inferior =
(struct thread_info *) find_inferior_id (&all_threads,
current_event.dwThreadId);
(struct thread_info *) find_inferior_id (&all_threads, ptid);
switch (current_event.dwDebugEventCode)
{
@ -1362,8 +1383,9 @@ get_child_debug_event (struct target_waitstatus *ourstatus)
(unsigned) current_event.dwThreadId));
/* Record the existence of this thread. */
child_add_thread (current_event.dwThreadId,
current_event.u.CreateThread.hThread);
child_add_thread (current_event.dwProcessId,
current_event.dwThreadId,
current_event.u.CreateThread.hThread);
break;
case EXIT_THREAD_DEBUG_EVENT:
@ -1371,7 +1393,8 @@ get_child_debug_event (struct target_waitstatus *ourstatus)
"for pid=%d tid=%x\n",
(unsigned) current_event.dwProcessId,
(unsigned) current_event.dwThreadId));
child_delete_thread (current_event.dwThreadId);
child_delete_thread (current_event.dwProcessId,
current_event.dwThreadId);
break;
case CREATE_PROCESS_DEBUG_EVENT:
@ -1388,10 +1411,11 @@ get_child_debug_event (struct target_waitstatus *ourstatus)
ourstatus->value.execd_pathname = "Main executable";
/* Add the main thread. */
child_add_thread (main_thread_id,
child_add_thread (current_event.dwProcessId,
main_thread_id,
current_event.u.CreateProcessInfo.hThread);
ourstatus->value.related_pid = current_event.dwThreadId;
ourstatus->value.related_pid = debug_event_ptid (&current_event);
#ifdef _WIN32_WCE
if (!attaching)
{
@ -1467,17 +1491,18 @@ get_child_debug_event (struct target_waitstatus *ourstatus)
}
current_inferior =
(struct thread_info *) find_inferior_id (&all_threads,
current_event.dwThreadId);
(struct thread_info *) find_inferior_id (&all_threads, ptid);
return 1;
}
/* Wait for the inferior process to change state.
STATUS will be filled in with a response code to send to GDB.
Returns the signal which caused the process to stop. */
static unsigned long
win32_wait (struct target_waitstatus *ourstatus, int options)
static ptid_t
win32_wait (ptid_t ptid, struct target_waitstatus *ourstatus, int options)
{
struct process_info *process;
while (1)
{
if (!get_child_debug_event (ourstatus))
@ -1489,8 +1514,10 @@ win32_wait (struct target_waitstatus *ourstatus, int options)
OUTMSG2 (("Child exited with retcode = %x\n",
ourstatus->value.integer));
process = find_process_pid (current_process_id);
remove_process (process);
win32_clear_inferiors ();
return current_event.dwProcessId;
return pid_to_ptid (current_event.dwProcessId);
case TARGET_WAITKIND_STOPPED:
case TARGET_WAITKIND_LOADED:
OUTMSG2 (("Child Stopped with signal = %d \n",
@ -1512,7 +1539,7 @@ win32_wait (struct target_waitstatus *ourstatus, int options)
if (ourstatus->kind == TARGET_WAITKIND_LOADED)
ourstatus->kind = TARGET_WAITKIND_STOPPED;
return current_event.dwThreadId;
return debug_event_ptid (&current_event);
default:
OUTMSG (("Ignoring unknown internal event, %d\n", ourstatus->kind));
/* fall-through */