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:
parent
bd99dc8583
commit
95954743cb
@ -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.
|
||||
|
@ -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 */
|
||||
|
@ -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
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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. */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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, ¬ify);
|
||||
err = td_ta_event_addr (proc->thread_agent, TD_CREATE, ¬ify);
|
||||
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, ¬ify);
|
||||
err = td_ta_event_addr (proc->thread_agent, TD_DEATH, ¬ify);
|
||||
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:
|
||||
|
@ -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 (¤t_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 (¤t_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 (¤t_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 (¤t_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 (¤t_event);
|
||||
default:
|
||||
OUTMSG (("Ignoring unknown internal event, %d\n", ourstatus->kind));
|
||||
/* fall-through */
|
||||
|
Loading…
Reference in New Issue
Block a user