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
16 changed files with 1586 additions and 458 deletions
|
@ -1,3 +1,206 @@
|
||||||
|
2009-04-01 Pedro Alves <pedro@codesourcery.com>
|
||||||
|
|
||||||
|
Implement the multiprocess extensions, and add linux multiprocess
|
||||||
|
support.
|
||||||
|
|
||||||
|
* server.h (ULONGEST): Declare.
|
||||||
|
(struct ptid, ptid_t): New.
|
||||||
|
(minus_one_ptid, null_ptid): Declare.
|
||||||
|
(ptid_build, pid_to_ptid, ptid_get_pid, ptid_get_lwp)
|
||||||
|
(ptid_get_tid, ptid_equal, ptid_is_pid): Declare.
|
||||||
|
(struct inferior_list_entry): Change `id' type from unsigned from
|
||||||
|
to ptid_t.
|
||||||
|
(struct sym_cache, struct breakpoint, struct
|
||||||
|
process_info_private): Forward declare.
|
||||||
|
(struct process_info): Declare.
|
||||||
|
(current_process): Declare.
|
||||||
|
(all_processes): Declare.
|
||||||
|
(initialize_inferiors): Declare.
|
||||||
|
(add_thread): Adjust to use ptid_t.
|
||||||
|
(thread_id_to_gdb_id, thread_to_gdb_id, gdb_id_to_thread_id): Ditto.
|
||||||
|
(add_process, remove_process, find_thread_pid): Declare.
|
||||||
|
(find_inferior_id): Adjust to use ptid_t.
|
||||||
|
(cont_thread, general_thread, step_thread): Change type to ptid_t.
|
||||||
|
(multi_process): Declare.
|
||||||
|
(push_event): Adjust to use ptid_t.
|
||||||
|
(read_ptid, write_ptid): Declare.
|
||||||
|
(prepare_resume_reply): Adjust to use ptid_t.
|
||||||
|
(clear_symbol_cache): Declare.
|
||||||
|
* inferiors.c (all_processes): New.
|
||||||
|
(null_ptid, minus_one_ptid): New.
|
||||||
|
(ptid_build, pid_to_ptid, ptid_get_pid, ptid_get_lwp)
|
||||||
|
(ptid_get_tid, ptid_equal, ptid_is_pid): New.
|
||||||
|
(add_thread): Change unsigned long to ptid. Remove gdb_id
|
||||||
|
parameter. Adjust.
|
||||||
|
(thread_id_to_gdb_id, thread_to_gdb_id): Change unsigned long to ptid.
|
||||||
|
(gdb_id_to_thread): Rename to ...
|
||||||
|
(find_thread_pid): ... this. Change unsigned long to ptid.
|
||||||
|
(gdb_id_to_thread_id, find_inferior_id): Change unsigned long to ptid.
|
||||||
|
(loaded_dll, pull_pid_from_list): Adjust.
|
||||||
|
(add_process, remove_process, find_process_pid)
|
||||||
|
(get_thread_process, current_process, initialize_inferiors): New.
|
||||||
|
* target.h (struct thread_resume) <thread>: Change type to ptid_t.
|
||||||
|
(struct target_waitstatus) <related_pid>: Ditto.
|
||||||
|
(struct target_ops) <kill, detach>: Add `pid' argument. Change
|
||||||
|
return type to int.
|
||||||
|
(struct target_ops) <join>: Add `pid' argument.
|
||||||
|
(struct target_ops) <thread_alive>: Change pid's type to ptid_t.
|
||||||
|
(struct target_ops) <wait>: Add `ptid' field. Change return type
|
||||||
|
to ptid.
|
||||||
|
(kill_inferior, detach_inferior, join_inferior): Add `pid' argument.
|
||||||
|
(mywait): Add `ptid' argument. Change return type to ptid_t.
|
||||||
|
(target_pid_to_str): Declare.
|
||||||
|
* target.c (set_desired_inferior): Adjust to use ptids.
|
||||||
|
(mywait): Add new `ptid' argument. Adjust.
|
||||||
|
(target_pid_to_str): New.
|
||||||
|
* mem-break.h (free_all_breakpoints): Declare.
|
||||||
|
* mem-break.c (breakpoints): Delelete.
|
||||||
|
(set_breakpoint_at, delete_breakpoint, find_breakpoint_at)
|
||||||
|
(check_mem_read, check_mem_write, delete_all_breakpoints): Adjust
|
||||||
|
to use per-process breakpoint list.
|
||||||
|
(free_all_breakpoints): New.
|
||||||
|
* remote-utils.c (struct sym_cache) <name>: Drop `const'.
|
||||||
|
(symbol_cache, all_symbols_looked_up): Delete.
|
||||||
|
(hexchars): New.
|
||||||
|
(ishex, unpack_varlen_hex, write_ptid, hex_or_minus_one,
|
||||||
|
read_ptid): New.
|
||||||
|
(prepare_resume_reply): Change ptid argument's type from unsigned
|
||||||
|
long to ptid_t. Adjust. Implement W;process and X;process.
|
||||||
|
(free_sym_cache, clear_symbol_cache): New.
|
||||||
|
(look_up_one_symbol): Adjust to per-process symbol cache. *
|
||||||
|
* server.c (cont_thread, general_thread, step_thread): Change type
|
||||||
|
to ptid_t.
|
||||||
|
(attached): Delete.
|
||||||
|
(multi_process): New.
|
||||||
|
(last_ptid): Change type to ptid_t.
|
||||||
|
(struct vstop_notif) <ptid>: Change type to ptid_t.
|
||||||
|
(queue_stop_reply, push_event): Change `ptid' argument's type to
|
||||||
|
ptid_t.
|
||||||
|
(discard_queued_stop_replies): Add `pid' argument.
|
||||||
|
(start_inferior): Adjust to use ptids. Adjust to mywait interface
|
||||||
|
changes. Don't reference the `attached' global.
|
||||||
|
(attach_inferior): Adjust to mywait interface changes.
|
||||||
|
(handle_query): Adjust to use ptids. Parse GDB's qSupported
|
||||||
|
features. Handle and report "multiprocess+". Handle
|
||||||
|
"qAttached:PID".
|
||||||
|
(handle_v_cont): Adjust to use ptids. Adjust to mywait interface
|
||||||
|
changes.
|
||||||
|
(handle_v_kill): New.
|
||||||
|
(handle_v_stopped): Adjust to use target_pid_to_str.
|
||||||
|
(handle_v_requests): Allow multiple attaches and runs when
|
||||||
|
multiprocess extensions are in effect. Handle "vKill".
|
||||||
|
(myresume): Adjust to use ptids.
|
||||||
|
(queue_stop_reply_callback): Add `arg' parameter. Handle it.
|
||||||
|
(handle_status): Adjust to discard_queued_stop_replies interface
|
||||||
|
change.
|
||||||
|
(first_thread_of, kill_inferior_callback)
|
||||||
|
(detach_or_kill_inferior_callback, join_inferiors_callback): New.
|
||||||
|
(main): Call initialize_inferiors. Adjust to use ptids, killing
|
||||||
|
and detaching from all inferiors. Handle multiprocess packet
|
||||||
|
variants.
|
||||||
|
* linux-low.h: Include gdb_proc_service.h.
|
||||||
|
(struct process_info_private): New.
|
||||||
|
(struct linux_target_ops) <pid_of>: Use ptid_get_pid.
|
||||||
|
<lwpid_of>: Use ptid_get_lwp.
|
||||||
|
(get_lwp_thread): Adjust.
|
||||||
|
(struct lwp_info): Add `dead' member.
|
||||||
|
(find_lwp_pid): Declare.
|
||||||
|
* linux-low.c (thread_db_active): Delete.
|
||||||
|
(new_inferior): Adjust comment.
|
||||||
|
(inferior_pid): Delete.
|
||||||
|
(linux_add_process): New.
|
||||||
|
(handle_extended_wait): Adjust.
|
||||||
|
(add_lwp): Change unsigned long to ptid.
|
||||||
|
(linux_create_inferior): Add process to processes table. Adjust
|
||||||
|
to use ptids. Don't set new_inferior here.
|
||||||
|
(linux_attach_lwp): Rename to ...
|
||||||
|
(linux_attach_lwp_1): ... this. Add `initial' argument. Handle
|
||||||
|
it. Adjust to use ptids.
|
||||||
|
(linux_attach_lwp): New.
|
||||||
|
(linux_attach): Add process to processes table. Don't set
|
||||||
|
new_inferior here.
|
||||||
|
(struct counter): New.
|
||||||
|
(second_thread_of_pid_p, last_thread_of_process_p): New.
|
||||||
|
(linux_kill_one_lwp): Add `args' parameter. Handle it. Adjust to
|
||||||
|
multiple processes.
|
||||||
|
(linux_kill): Add `pid' argument. Handle it. Adjust to multiple
|
||||||
|
processes. Remove process from process table.
|
||||||
|
(linux_detach_one_lwp): Add `args' parameter. Handle it. Adjust
|
||||||
|
to multiple processes.
|
||||||
|
(any_thread_of): New.
|
||||||
|
(linux_detach): Add `pid' argument, and handle it. Remove process
|
||||||
|
from processes table.
|
||||||
|
(linux_join): Add `pid' argument. Handle it.
|
||||||
|
(linux_thread_alive): Change unsighed long argument to ptid_t.
|
||||||
|
Consider dead lwps as not being alive.
|
||||||
|
(status_pending_p): Rename `dummy' argument to `arg'. Filter out
|
||||||
|
threads we're not interested in.
|
||||||
|
(same_lwp, find_lwp_pid): New.
|
||||||
|
(linux_wait_for_lwp): Change `pid' argument's type from int to
|
||||||
|
ptid_t. Adjust.
|
||||||
|
(linux_wait_for_event): Rename to ...
|
||||||
|
(linux_wait_for_event_1): ... this. Change `pid' argument's type
|
||||||
|
from int to ptid_t. Adjust.
|
||||||
|
(linux_wait_for_event): New.
|
||||||
|
(linux_wait_1): Add `ptid' argument. Change return type to
|
||||||
|
ptid_t. Adjust. Use last_thread_of_process_p. Remove processes
|
||||||
|
that exit from the process table.
|
||||||
|
(linux_wait): Add `ptid' argument. Change return type to ptid_t.
|
||||||
|
Adjust.
|
||||||
|
(mark_lwp_dead): New.
|
||||||
|
(wait_for_sigstop): Adjust to use ptids. If a process exits while
|
||||||
|
stopping all threads, mark its main lwp as dead.
|
||||||
|
(linux_set_resume_request, linux_resume_one_thread): Adjust to use
|
||||||
|
ptids.
|
||||||
|
(fetch_register, usr_store_inferior_registers)
|
||||||
|
(regsets_fetch_inferior_registers)
|
||||||
|
(regsets_store_inferior_registers, linux_read_memory)
|
||||||
|
(linux_write_memory): Inline `inferior_pid'.
|
||||||
|
(linux_look_up_symbols): Adjust to use per-process
|
||||||
|
`thread_db_active'.
|
||||||
|
(linux_request_interrupt): Adjust to use ptids.
|
||||||
|
(linux_read_auxv): Inline `inferior_pid'.
|
||||||
|
(initialize_low): Don't reference thread_db_active.
|
||||||
|
* gdb_proc_service.h (struct ps_prochandle) <pid>: Remove.
|
||||||
|
* proc-service.c (ps_lgetregs): Use find_lwp_pid.
|
||||||
|
(ps_getpid): Return the pid of the current inferior.
|
||||||
|
* thread-db.c (proc_handle, thread_agent): Delete.
|
||||||
|
(thread_db_create_event, thread_db_enable_reporting): Adjust to
|
||||||
|
per-process data.
|
||||||
|
(find_one_thread): Change argument type to ptid_t. Adjust to
|
||||||
|
per-process data.
|
||||||
|
(maybe_attach_thread): Adjust to per-process data and ptids.
|
||||||
|
(thread_db_find_new_threads): Ditto.
|
||||||
|
(thread_db_init): Ditto.
|
||||||
|
* spu-low.c (spu_create_inferior, spu_attach): Add process to
|
||||||
|
processes table. Adjust to use ptids.
|
||||||
|
(spu_kill, spu_detach): Adjust interface. Remove process from
|
||||||
|
processes table.
|
||||||
|
(spu_join, spu_thread_alive): Adjust interface.
|
||||||
|
(spu_wait): Adjust interface. Remove process from processes
|
||||||
|
table. Adjust to use ptids.
|
||||||
|
* win32-low.c (current_inferior_tid): Delete.
|
||||||
|
(current_inferior_ptid): New.
|
||||||
|
(debug_event_ptid): New.
|
||||||
|
(thread_rec): Take a ptid. Adjust.
|
||||||
|
(child_add_thread): Add `pid' argument. Adjust to use ptids.
|
||||||
|
(child_delete_thread): Ditto.
|
||||||
|
(do_initial_child_stuff): Add `attached' argument. Add process to
|
||||||
|
processes table.
|
||||||
|
(child_fetch_inferior_registers, child_store_inferior_registers):
|
||||||
|
Adjust.
|
||||||
|
(win32_create_inferior): Pass 0 to do_initial_child_stuff.
|
||||||
|
(win32_attach): Pass 1 to do_initial_child_stuff.
|
||||||
|
(win32_kill): Adjust interface. Remove process from processes
|
||||||
|
table.
|
||||||
|
(win32_detach): Ditto.
|
||||||
|
(win32_join): Adjust interface.
|
||||||
|
(win32_thread_alive): Take a ptid.
|
||||||
|
(win32_resume): Adjust to use ptids.
|
||||||
|
(get_child_debug_event): Ditto.
|
||||||
|
(win32_wait): Adjust interface. Remove exiting process from
|
||||||
|
processes table.
|
||||||
|
|
||||||
2009-04-01 Pedro Alves <pedro@codesourcery.com>
|
2009-04-01 Pedro Alves <pedro@codesourcery.com>
|
||||||
|
|
||||||
Non-stop mode support.
|
Non-stop mode support.
|
||||||
|
|
|
@ -66,8 +66,8 @@ typedef elf_gregset_t prgregset_t;
|
||||||
/* Structure that identifies the target process. */
|
/* Structure that identifies the target process. */
|
||||||
struct ps_prochandle
|
struct ps_prochandle
|
||||||
{
|
{
|
||||||
/* The process id is all we need. */
|
/* We don't need to track anything. All context is served from the
|
||||||
pid_t pid;
|
current inferior. */
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* gdb_proc_service.h */
|
#endif /* gdb_proc_service.h */
|
||||||
|
|
|
@ -30,12 +30,88 @@ struct thread_info
|
||||||
unsigned int gdb_id;
|
unsigned int gdb_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct inferior_list all_processes;
|
||||||
struct inferior_list all_threads;
|
struct inferior_list all_threads;
|
||||||
struct inferior_list all_dlls;
|
struct inferior_list all_dlls;
|
||||||
int dlls_changed;
|
int dlls_changed;
|
||||||
|
|
||||||
struct thread_info *current_inferior;
|
struct thread_info *current_inferior;
|
||||||
|
|
||||||
|
|
||||||
|
/* Oft used ptids */
|
||||||
|
ptid_t null_ptid;
|
||||||
|
ptid_t minus_one_ptid;
|
||||||
|
|
||||||
|
/* Create a ptid given the necessary PID, LWP, and TID components. */
|
||||||
|
|
||||||
|
ptid_t
|
||||||
|
ptid_build (int pid, long lwp, long tid)
|
||||||
|
{
|
||||||
|
ptid_t ptid;
|
||||||
|
|
||||||
|
ptid.pid = pid;
|
||||||
|
ptid.lwp = lwp;
|
||||||
|
ptid.tid = tid;
|
||||||
|
return ptid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create a ptid from just a pid. */
|
||||||
|
|
||||||
|
ptid_t
|
||||||
|
pid_to_ptid (int pid)
|
||||||
|
{
|
||||||
|
return ptid_build (pid, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fetch the pid (process id) component from a ptid. */
|
||||||
|
|
||||||
|
int
|
||||||
|
ptid_get_pid (ptid_t ptid)
|
||||||
|
{
|
||||||
|
return ptid.pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fetch the lwp (lightweight process) component from a ptid. */
|
||||||
|
|
||||||
|
long
|
||||||
|
ptid_get_lwp (ptid_t ptid)
|
||||||
|
{
|
||||||
|
return ptid.lwp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fetch the tid (thread id) component from a ptid. */
|
||||||
|
|
||||||
|
long
|
||||||
|
ptid_get_tid (ptid_t ptid)
|
||||||
|
{
|
||||||
|
return ptid.tid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ptid_equal() is used to test equality of two ptids. */
|
||||||
|
|
||||||
|
int
|
||||||
|
ptid_equal (ptid_t ptid1, ptid_t ptid2)
|
||||||
|
{
|
||||||
|
return (ptid1.pid == ptid2.pid
|
||||||
|
&& ptid1.lwp == ptid2.lwp
|
||||||
|
&& ptid1.tid == ptid2.tid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return true if this ptid represents a process. */
|
||||||
|
|
||||||
|
int
|
||||||
|
ptid_is_pid (ptid_t ptid)
|
||||||
|
{
|
||||||
|
if (ptid_equal (minus_one_ptid, ptid))
|
||||||
|
return 0;
|
||||||
|
if (ptid_equal (null_ptid, ptid))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return (ptid_get_pid (ptid) != 0
|
||||||
|
&& ptid_get_lwp (ptid) == 0
|
||||||
|
&& ptid_get_tid (ptid) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
#define get_thread(inf) ((struct thread_info *)(inf))
|
#define get_thread(inf) ((struct thread_info *)(inf))
|
||||||
#define get_dll(inf) ((struct dll_info *)(inf))
|
#define get_dll(inf) ((struct dll_info *)(inf))
|
||||||
|
|
||||||
|
@ -93,7 +169,7 @@ remove_inferior (struct inferior_list *list,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
add_thread (unsigned long thread_id, void *target_data, unsigned int gdb_id)
|
add_thread (ptid_t thread_id, void *target_data)
|
||||||
{
|
{
|
||||||
struct thread_info *new_thread = xmalloc (sizeof (*new_thread));
|
struct thread_info *new_thread = xmalloc (sizeof (*new_thread));
|
||||||
|
|
||||||
|
@ -108,40 +184,38 @@ add_thread (unsigned long thread_id, void *target_data, unsigned int gdb_id)
|
||||||
|
|
||||||
new_thread->target_data = target_data;
|
new_thread->target_data = target_data;
|
||||||
set_inferior_regcache_data (new_thread, new_register_cache ());
|
set_inferior_regcache_data (new_thread, new_register_cache ());
|
||||||
new_thread->gdb_id = gdb_id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int
|
ptid_t
|
||||||
thread_id_to_gdb_id (unsigned long thread_id)
|
thread_id_to_gdb_id (ptid_t thread_id)
|
||||||
{
|
{
|
||||||
struct inferior_list_entry *inf = all_threads.head;
|
struct inferior_list_entry *inf = all_threads.head;
|
||||||
|
|
||||||
while (inf != NULL)
|
while (inf != NULL)
|
||||||
{
|
{
|
||||||
struct thread_info *thread = get_thread (inf);
|
if (ptid_equal (inf->id, thread_id))
|
||||||
if (inf->id == thread_id)
|
return thread_id;
|
||||||
return thread->gdb_id;
|
|
||||||
inf = inf->next;
|
inf = inf->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return null_ptid;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int
|
ptid_t
|
||||||
thread_to_gdb_id (struct thread_info *thread)
|
thread_to_gdb_id (struct thread_info *thread)
|
||||||
{
|
{
|
||||||
return thread->gdb_id;
|
return thread->entry.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct thread_info *
|
struct thread_info *
|
||||||
gdb_id_to_thread (unsigned int gdb_id)
|
find_thread_pid (ptid_t ptid)
|
||||||
{
|
{
|
||||||
struct inferior_list_entry *inf = all_threads.head;
|
struct inferior_list_entry *inf = all_threads.head;
|
||||||
|
|
||||||
while (inf != NULL)
|
while (inf != NULL)
|
||||||
{
|
{
|
||||||
struct thread_info *thread = get_thread (inf);
|
struct thread_info *thread = get_thread (inf);
|
||||||
if (thread->gdb_id == gdb_id)
|
if (ptid_equal (thread->entry.id, ptid))
|
||||||
return thread;
|
return thread;
|
||||||
inf = inf->next;
|
inf = inf->next;
|
||||||
}
|
}
|
||||||
|
@ -149,12 +223,12 @@ gdb_id_to_thread (unsigned int gdb_id)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long
|
ptid_t
|
||||||
gdb_id_to_thread_id (unsigned int gdb_id)
|
gdb_id_to_thread_id (ptid_t gdb_id)
|
||||||
{
|
{
|
||||||
struct thread_info *thread = gdb_id_to_thread (gdb_id);
|
struct thread_info *thread = find_thread_pid (gdb_id);
|
||||||
|
|
||||||
return thread ? thread->entry.id : 0;
|
return thread ? thread->entry.id : null_ptid;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -192,13 +266,13 @@ find_inferior (struct inferior_list *list,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct inferior_list_entry *
|
struct inferior_list_entry *
|
||||||
find_inferior_id (struct inferior_list *list, unsigned long id)
|
find_inferior_id (struct inferior_list *list, ptid_t id)
|
||||||
{
|
{
|
||||||
struct inferior_list_entry *inf = list->head;
|
struct inferior_list_entry *inf = list->head;
|
||||||
|
|
||||||
while (inf != NULL)
|
while (inf != NULL)
|
||||||
{
|
{
|
||||||
if (inf->id == id)
|
if (ptid_equal (inf->id, id))
|
||||||
return inf;
|
return inf;
|
||||||
inf = inf->next;
|
inf = inf->next;
|
||||||
}
|
}
|
||||||
|
@ -267,7 +341,7 @@ loaded_dll (const char *name, CORE_ADDR base_addr)
|
||||||
struct dll_info *new_dll = xmalloc (sizeof (*new_dll));
|
struct dll_info *new_dll = xmalloc (sizeof (*new_dll));
|
||||||
memset (new_dll, 0, sizeof (*new_dll));
|
memset (new_dll, 0, sizeof (*new_dll));
|
||||||
|
|
||||||
new_dll->entry.id = -1;
|
new_dll->entry.id = minus_one_ptid;
|
||||||
|
|
||||||
new_dll->name = xstrdup (name);
|
new_dll->name = xstrdup (name);
|
||||||
new_dll->base_addr = base_addr;
|
new_dll->base_addr = base_addr;
|
||||||
|
@ -318,7 +392,7 @@ add_pid_to_list (struct inferior_list *list, unsigned long pid)
|
||||||
struct inferior_list_entry *new_entry;
|
struct inferior_list_entry *new_entry;
|
||||||
|
|
||||||
new_entry = xmalloc (sizeof (struct inferior_list_entry));
|
new_entry = xmalloc (sizeof (struct inferior_list_entry));
|
||||||
new_entry->id = pid;
|
new_entry->id = pid_to_ptid (pid);
|
||||||
add_inferior_to_list (list, new_entry);
|
add_inferior_to_list (list, new_entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,7 +401,7 @@ pull_pid_from_list (struct inferior_list *list, unsigned long pid)
|
||||||
{
|
{
|
||||||
struct inferior_list_entry *new_entry;
|
struct inferior_list_entry *new_entry;
|
||||||
|
|
||||||
new_entry = find_inferior_id (list, pid);
|
new_entry = find_inferior_id (list, pid_to_ptid (pid));
|
||||||
if (new_entry == NULL)
|
if (new_entry == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
|
@ -337,3 +411,56 @@ pull_pid_from_list (struct inferior_list *list, unsigned long pid)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct process_info *
|
||||||
|
add_process (int pid, int attached)
|
||||||
|
{
|
||||||
|
struct process_info *process;
|
||||||
|
|
||||||
|
process = xcalloc (1, sizeof (*process));
|
||||||
|
|
||||||
|
process->head.id = pid_to_ptid (pid);
|
||||||
|
process->attached = attached;
|
||||||
|
|
||||||
|
add_inferior_to_list (&all_processes, &process->head);
|
||||||
|
|
||||||
|
return process;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
remove_process (struct process_info *process)
|
||||||
|
{
|
||||||
|
clear_symbol_cache (&process->symbol_cache);
|
||||||
|
free_all_breakpoints (process);
|
||||||
|
remove_inferior (&all_processes, &process->head);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct process_info *
|
||||||
|
find_process_pid (int pid)
|
||||||
|
{
|
||||||
|
return (struct process_info *)
|
||||||
|
find_inferior_id (&all_processes, pid_to_ptid (pid));
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct process_info *
|
||||||
|
get_thread_process (struct thread_info *thread)
|
||||||
|
{
|
||||||
|
int pid = ptid_get_pid (thread->entry.id);
|
||||||
|
return find_process_pid (pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct process_info *
|
||||||
|
current_process (void)
|
||||||
|
{
|
||||||
|
if (current_inferior == NULL)
|
||||||
|
fatal ("Current inferior requested, but current_inferior is NULL\n");
|
||||||
|
|
||||||
|
return get_thread_process (current_inferior);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
initialize_inferiors (void)
|
||||||
|
{
|
||||||
|
null_ptid = ptid_build (0, 0, 0);
|
||||||
|
minus_one_ptid = ptid_build (-1, 0, 0);
|
||||||
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -21,6 +21,8 @@
|
||||||
#include <thread_db.h>
|
#include <thread_db.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "gdb_proc_service.h"
|
||||||
|
|
||||||
#ifdef HAVE_LINUX_REGSETS
|
#ifdef HAVE_LINUX_REGSETS
|
||||||
typedef void (*regset_fill_func) (void *);
|
typedef void (*regset_fill_func) (void *);
|
||||||
typedef void (*regset_store_func) (const void *);
|
typedef void (*regset_store_func) (const void *);
|
||||||
|
@ -41,6 +43,19 @@ struct regset_info
|
||||||
extern struct regset_info target_regsets[];
|
extern struct regset_info target_regsets[];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct process_info_private
|
||||||
|
{
|
||||||
|
/* True if this process has loaded thread_db, and it is active. */
|
||||||
|
int thread_db_active;
|
||||||
|
|
||||||
|
/* Structure that identifies the child process for the
|
||||||
|
<proc_service.h> interface. */
|
||||||
|
struct ps_prochandle proc_handle;
|
||||||
|
|
||||||
|
/* Connection to the libthread_db library. */
|
||||||
|
td_thragent_t *thread_agent;
|
||||||
|
};
|
||||||
|
|
||||||
struct linux_target_ops
|
struct linux_target_ops
|
||||||
{
|
{
|
||||||
/* Architecture-specific setup. */
|
/* Architecture-specific setup. */
|
||||||
|
@ -78,14 +93,14 @@ struct linux_target_ops
|
||||||
|
|
||||||
extern struct linux_target_ops the_low_target;
|
extern struct linux_target_ops the_low_target;
|
||||||
|
|
||||||
#define pid_of(proc) ((proc)->head.id)
|
#define pid_of(proc) ptid_get_pid ((proc)->head.id)
|
||||||
#define lwpid_of(proc) ((proc)->head.id)
|
#define lwpid_of(proc) ptid_get_lwp ((proc)->head.id)
|
||||||
|
|
||||||
#define get_lwp(inf) ((struct lwp_info *)(inf))
|
#define get_lwp(inf) ((struct lwp_info *)(inf))
|
||||||
#define get_thread_lwp(thr) (get_lwp (inferior_target_data (thr)))
|
#define get_thread_lwp(thr) (get_lwp (inferior_target_data (thr)))
|
||||||
#define get_lwp_thread(proc) ((struct thread_info *) \
|
#define get_lwp_thread(proc) ((struct thread_info *) \
|
||||||
find_inferior_id (&all_threads, \
|
find_inferior_id (&all_threads, \
|
||||||
lwpid_of (get_lwp (proc))))
|
get_lwp (proc)->head.id))
|
||||||
|
|
||||||
struct lwp_info
|
struct lwp_info
|
||||||
{
|
{
|
||||||
|
@ -106,6 +121,11 @@ struct lwp_info
|
||||||
event already received in a wait()). */
|
event already received in a wait()). */
|
||||||
int stopped;
|
int stopped;
|
||||||
|
|
||||||
|
/* If this flag is set, the lwp is known to be dead already (exit
|
||||||
|
event already received in a wait(), and is cached in
|
||||||
|
status_pending). */
|
||||||
|
int dead;
|
||||||
|
|
||||||
/* When stopped is set, the last wait status recorded for this lwp. */
|
/* When stopped is set, the last wait status recorded for this lwp. */
|
||||||
int last_status;
|
int last_status;
|
||||||
|
|
||||||
|
@ -150,3 +170,5 @@ void linux_attach_lwp (unsigned long pid);
|
||||||
int thread_db_init (int use_events);
|
int thread_db_init (int use_events);
|
||||||
int thread_db_get_tls_address (struct thread_info *thread, CORE_ADDR offset,
|
int thread_db_get_tls_address (struct thread_info *thread, CORE_ADDR offset,
|
||||||
CORE_ADDR load_module, CORE_ADDR *address);
|
CORE_ADDR load_module, CORE_ADDR *address);
|
||||||
|
|
||||||
|
struct lwp_info *find_lwp_pid (ptid_t ptid);
|
||||||
|
|
|
@ -46,11 +46,10 @@ struct breakpoint
|
||||||
int (*handler) (CORE_ADDR);
|
int (*handler) (CORE_ADDR);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct breakpoint *breakpoints;
|
|
||||||
|
|
||||||
void
|
void
|
||||||
set_breakpoint_at (CORE_ADDR where, int (*handler) (CORE_ADDR))
|
set_breakpoint_at (CORE_ADDR where, int (*handler) (CORE_ADDR))
|
||||||
{
|
{
|
||||||
|
struct process_info *proc = current_process ();
|
||||||
struct breakpoint *bp;
|
struct breakpoint *bp;
|
||||||
|
|
||||||
if (breakpoint_data == NULL)
|
if (breakpoint_data == NULL)
|
||||||
|
@ -67,24 +66,25 @@ set_breakpoint_at (CORE_ADDR where, int (*handler) (CORE_ADDR))
|
||||||
bp->pc = where;
|
bp->pc = where;
|
||||||
bp->handler = handler;
|
bp->handler = handler;
|
||||||
|
|
||||||
bp->next = breakpoints;
|
bp->next = proc->breakpoints;
|
||||||
breakpoints = bp;
|
proc->breakpoints = bp;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
delete_breakpoint (struct breakpoint *bp)
|
delete_breakpoint (struct breakpoint *bp)
|
||||||
{
|
{
|
||||||
|
struct process_info *proc = current_process ();
|
||||||
struct breakpoint *cur;
|
struct breakpoint *cur;
|
||||||
|
|
||||||
if (breakpoints == bp)
|
if (proc->breakpoints == bp)
|
||||||
{
|
{
|
||||||
breakpoints = bp->next;
|
proc->breakpoints = bp->next;
|
||||||
(*the_target->write_memory) (bp->pc, bp->old_data,
|
(*the_target->write_memory) (bp->pc, bp->old_data,
|
||||||
breakpoint_len);
|
breakpoint_len);
|
||||||
free (bp);
|
free (bp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cur = breakpoints;
|
cur = proc->breakpoints;
|
||||||
while (cur->next)
|
while (cur->next)
|
||||||
{
|
{
|
||||||
if (cur->next == bp)
|
if (cur->next == bp)
|
||||||
|
@ -102,7 +102,8 @@ delete_breakpoint (struct breakpoint *bp)
|
||||||
static struct breakpoint *
|
static struct breakpoint *
|
||||||
find_breakpoint_at (CORE_ADDR where)
|
find_breakpoint_at (CORE_ADDR where)
|
||||||
{
|
{
|
||||||
struct breakpoint *bp = breakpoints;
|
struct process_info *proc = current_process ();
|
||||||
|
struct breakpoint *bp = proc->breakpoints;
|
||||||
|
|
||||||
while (bp != NULL)
|
while (bp != NULL)
|
||||||
{
|
{
|
||||||
|
@ -225,7 +226,8 @@ set_breakpoint_data (const unsigned char *bp_data, int bp_len)
|
||||||
void
|
void
|
||||||
check_mem_read (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
|
check_mem_read (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
|
||||||
{
|
{
|
||||||
struct breakpoint *bp = breakpoints;
|
struct process_info *proc = current_process ();
|
||||||
|
struct breakpoint *bp = proc->breakpoints;
|
||||||
CORE_ADDR mem_end = mem_addr + mem_len;
|
CORE_ADDR mem_end = mem_addr + mem_len;
|
||||||
|
|
||||||
for (; bp != NULL; bp = bp->next)
|
for (; bp != NULL; bp = bp->next)
|
||||||
|
@ -258,7 +260,8 @@ check_mem_read (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
|
||||||
void
|
void
|
||||||
check_mem_write (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
|
check_mem_write (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
|
||||||
{
|
{
|
||||||
struct breakpoint *bp = breakpoints;
|
struct process_info *proc = current_process ();
|
||||||
|
struct breakpoint *bp = proc->breakpoints;
|
||||||
CORE_ADDR mem_end = mem_addr + mem_len;
|
CORE_ADDR mem_end = mem_addr + mem_len;
|
||||||
|
|
||||||
for (; bp != NULL; bp = bp->next)
|
for (; bp != NULL; bp = bp->next)
|
||||||
|
@ -290,11 +293,29 @@ check_mem_write (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Delete all breakpoints. */
|
/* Delete all breakpoints, and un-insert them from the inferior. */
|
||||||
|
|
||||||
void
|
void
|
||||||
delete_all_breakpoints (void)
|
delete_all_breakpoints (void)
|
||||||
{
|
{
|
||||||
while (breakpoints)
|
struct process_info *proc = current_process ();
|
||||||
delete_breakpoint (breakpoints);
|
|
||||||
|
while (proc->breakpoints)
|
||||||
|
delete_breakpoint (proc->breakpoints);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release all breakpoints, but do not try to un-insert them from the
|
||||||
|
inferior. */
|
||||||
|
|
||||||
|
void
|
||||||
|
free_all_breakpoints (struct process_info *proc)
|
||||||
|
{
|
||||||
|
struct breakpoint *bp;
|
||||||
|
|
||||||
|
while (proc->breakpoints)
|
||||||
|
{
|
||||||
|
bp = proc->breakpoints;
|
||||||
|
proc->breakpoints = bp->next;
|
||||||
|
free (bp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,4 +75,9 @@ void set_breakpoint_data (const unsigned char *bp_data, int bp_len);
|
||||||
|
|
||||||
void delete_all_breakpoints (void);
|
void delete_all_breakpoints (void);
|
||||||
|
|
||||||
|
/* Delete all breakpoints, but do not try to un-insert them from the
|
||||||
|
inferior. */
|
||||||
|
|
||||||
|
void free_all_breakpoints (struct process_info *proc);
|
||||||
|
|
||||||
#endif /* MEM_BREAK_H */
|
#endif /* MEM_BREAK_H */
|
||||||
|
|
|
@ -102,8 +102,7 @@ ps_lgetregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, prgregset_t gregset)
|
||||||
struct lwp_info *lwp;
|
struct lwp_info *lwp;
|
||||||
struct thread_info *reg_inferior, *save_inferior;
|
struct thread_info *reg_inferior, *save_inferior;
|
||||||
|
|
||||||
lwp = (struct lwp_info *) find_inferior_id (&all_lwps,
|
lwp = find_lwp_pid (pid_to_ptid (lwpid));
|
||||||
lwpid);
|
|
||||||
if (lwp == NULL)
|
if (lwp == NULL)
|
||||||
return PS_ERR;
|
return PS_ERR;
|
||||||
|
|
||||||
|
@ -157,5 +156,5 @@ ps_lsetfpregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, void *fpregset)
|
||||||
pid_t
|
pid_t
|
||||||
ps_getpid (gdb_ps_prochandle_t ph)
|
ps_getpid (gdb_ps_prochandle_t ph)
|
||||||
{
|
{
|
||||||
return ph->pid;
|
return pid_of (get_thread_lwp (current_inferior));
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,18 +79,11 @@ typedef int socklen_t;
|
||||||
/* A cache entry for a successfully looked-up symbol. */
|
/* A cache entry for a successfully looked-up symbol. */
|
||||||
struct sym_cache
|
struct sym_cache
|
||||||
{
|
{
|
||||||
const char *name;
|
char *name;
|
||||||
CORE_ADDR addr;
|
CORE_ADDR addr;
|
||||||
struct sym_cache *next;
|
struct sym_cache *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The symbol cache. */
|
|
||||||
static struct sym_cache *symbol_cache;
|
|
||||||
|
|
||||||
/* If this flag has been set, assume cache misses are
|
|
||||||
failures. */
|
|
||||||
int all_symbols_looked_up;
|
|
||||||
|
|
||||||
int remote_debug = 0;
|
int remote_debug = 0;
|
||||||
struct ui_file *gdb_stdlog;
|
struct ui_file *gdb_stdlog;
|
||||||
|
|
||||||
|
@ -317,6 +310,29 @@ fromhex (int a)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char hexchars[] = "0123456789abcdef";
|
||||||
|
|
||||||
|
static int
|
||||||
|
ishex (int ch, int *val)
|
||||||
|
{
|
||||||
|
if ((ch >= 'a') && (ch <= 'f'))
|
||||||
|
{
|
||||||
|
*val = ch - 'a' + 10;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if ((ch >= 'A') && (ch <= 'F'))
|
||||||
|
{
|
||||||
|
*val = ch - 'A' + 10;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if ((ch >= '0') && (ch <= '9'))
|
||||||
|
{
|
||||||
|
*val = ch - '0';
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
unhexify (char *bin, const char *hex, int count)
|
unhexify (char *bin, const char *hex, int count)
|
||||||
{
|
{
|
||||||
|
@ -523,6 +539,103 @@ try_rle (char *buf, int remaining, unsigned char *csum, char **p)
|
||||||
return n + 1;
|
return n + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
unpack_varlen_hex (char *buff, /* packet to parse */
|
||||||
|
ULONGEST *result)
|
||||||
|
{
|
||||||
|
int nibble;
|
||||||
|
ULONGEST retval = 0;
|
||||||
|
|
||||||
|
while (ishex (*buff, &nibble))
|
||||||
|
{
|
||||||
|
buff++;
|
||||||
|
retval = retval << 4;
|
||||||
|
retval |= nibble & 0x0f;
|
||||||
|
}
|
||||||
|
*result = retval;
|
||||||
|
return buff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write a PTID to BUF. Returns BUF+CHARACTERS_WRITTEN. */
|
||||||
|
|
||||||
|
char *
|
||||||
|
write_ptid (char *buf, ptid_t ptid)
|
||||||
|
{
|
||||||
|
int pid, tid;
|
||||||
|
|
||||||
|
if (multi_process)
|
||||||
|
{
|
||||||
|
pid = ptid_get_pid (ptid);
|
||||||
|
if (pid < 0)
|
||||||
|
buf += sprintf (buf, "p-%x.", -pid);
|
||||||
|
else
|
||||||
|
buf += sprintf (buf, "p%x.", pid);
|
||||||
|
}
|
||||||
|
tid = ptid_get_lwp (ptid);
|
||||||
|
if (tid < 0)
|
||||||
|
buf += sprintf (buf, "-%x", -tid);
|
||||||
|
else
|
||||||
|
buf += sprintf (buf, "%x", tid);
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONGEST
|
||||||
|
hex_or_minus_one (char *buf, char **obuf)
|
||||||
|
{
|
||||||
|
ULONGEST ret;
|
||||||
|
|
||||||
|
if (strncmp (buf, "-1", 2) == 0)
|
||||||
|
{
|
||||||
|
ret = (ULONGEST) -1;
|
||||||
|
buf += 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
buf = unpack_varlen_hex (buf, &ret);
|
||||||
|
|
||||||
|
if (obuf)
|
||||||
|
*obuf = buf;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Extract a PTID from BUF. If non-null, OBUF is set to the to one
|
||||||
|
passed the last parsed char. Returns null_ptid on error. */
|
||||||
|
ptid_t
|
||||||
|
read_ptid (char *buf, char **obuf)
|
||||||
|
{
|
||||||
|
char *p = buf;
|
||||||
|
char *pp;
|
||||||
|
ULONGEST pid = 0, tid = 0;
|
||||||
|
|
||||||
|
if (*p == 'p')
|
||||||
|
{
|
||||||
|
/* Multi-process ptid. */
|
||||||
|
pp = unpack_varlen_hex (p + 1, &pid);
|
||||||
|
if (*pp != '.')
|
||||||
|
error ("invalid remote ptid: %s\n", p);
|
||||||
|
|
||||||
|
p = pp + 1;
|
||||||
|
|
||||||
|
tid = hex_or_minus_one (p, &pp);
|
||||||
|
|
||||||
|
if (obuf)
|
||||||
|
*obuf = pp;
|
||||||
|
return ptid_build (pid, tid, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No multi-process. Just a tid. */
|
||||||
|
tid = hex_or_minus_one (p, &pp);
|
||||||
|
|
||||||
|
/* Since the stub is not sending a process id, then default to
|
||||||
|
what's in the current inferior. */
|
||||||
|
pid = ptid_get_pid (((struct inferior_list_entry *) current_inferior)->id);
|
||||||
|
|
||||||
|
if (obuf)
|
||||||
|
*obuf = pp;
|
||||||
|
return ptid_build (pid, tid, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* Send a packet to the remote machine, with error checking.
|
/* Send a packet to the remote machine, with error checking.
|
||||||
The data of the packet is in BUF, and the length of the
|
The data of the packet is in BUF, and the length of the
|
||||||
packet is in CNT. Returns >= 0 on success, -1 otherwise. */
|
packet is in CNT. Returns >= 0 on success, -1 otherwise. */
|
||||||
|
@ -957,12 +1070,12 @@ dead_thread_notify (int id)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
prepare_resume_reply (char *buf, unsigned long ptid,
|
prepare_resume_reply (char *buf, ptid_t ptid,
|
||||||
struct target_waitstatus *status)
|
struct target_waitstatus *status)
|
||||||
{
|
{
|
||||||
if (debug_threads)
|
if (debug_threads)
|
||||||
fprintf (stderr, "Writing resume reply for %lu:%d\n\n",
|
fprintf (stderr, "Writing resume reply for %s:%d\n\n",
|
||||||
ptid, status->kind);
|
target_pid_to_str (ptid), status->kind);
|
||||||
|
|
||||||
switch (status->kind)
|
switch (status->kind)
|
||||||
{
|
{
|
||||||
|
@ -978,7 +1091,7 @@ prepare_resume_reply (char *buf, unsigned long ptid,
|
||||||
|
|
||||||
saved_inferior = current_inferior;
|
saved_inferior = current_inferior;
|
||||||
|
|
||||||
current_inferior = gdb_id_to_thread (ptid);
|
current_inferior = find_thread_pid (ptid);
|
||||||
|
|
||||||
if (the_target->stopped_by_watchpoint != NULL
|
if (the_target->stopped_by_watchpoint != NULL
|
||||||
&& (*the_target->stopped_by_watchpoint) ())
|
&& (*the_target->stopped_by_watchpoint) ())
|
||||||
|
@ -1021,13 +1134,16 @@ prepare_resume_reply (char *buf, unsigned long ptid,
|
||||||
in GDB will claim this event belongs to inferior_ptid
|
in GDB will claim this event belongs to inferior_ptid
|
||||||
if we do not specify a thread, and there's no way for
|
if we do not specify a thread, and there's no way for
|
||||||
gdbserver to know what inferior_ptid is. */
|
gdbserver to know what inferior_ptid is. */
|
||||||
if (1 || general_thread != ptid)
|
if (1 || !ptid_equal (general_thread, ptid))
|
||||||
{
|
{
|
||||||
/* In non-stop, don't change the general thread behind
|
/* In non-stop, don't change the general thread behind
|
||||||
GDB's back. */
|
GDB's back. */
|
||||||
if (!non_stop)
|
if (!non_stop)
|
||||||
general_thread = ptid;
|
general_thread = ptid;
|
||||||
sprintf (buf, "thread:%lx;", ptid);
|
sprintf (buf, "thread:");
|
||||||
|
buf += strlen (buf);
|
||||||
|
buf = write_ptid (buf, ptid);
|
||||||
|
strcat (buf, ";");
|
||||||
buf += strlen (buf);
|
buf += strlen (buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1043,10 +1159,18 @@ prepare_resume_reply (char *buf, unsigned long ptid,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TARGET_WAITKIND_EXITED:
|
case TARGET_WAITKIND_EXITED:
|
||||||
sprintf (buf, "W%02x", status->value.integer);
|
if (multi_process)
|
||||||
|
sprintf (buf, "W%x;process:%x",
|
||||||
|
status->value.integer, ptid_get_pid (ptid));
|
||||||
|
else
|
||||||
|
sprintf (buf, "W%02x", status->value.integer);
|
||||||
break;
|
break;
|
||||||
case TARGET_WAITKIND_SIGNALLED:
|
case TARGET_WAITKIND_SIGNALLED:
|
||||||
sprintf (buf, "X%02x", status->value.sig);
|
if (multi_process)
|
||||||
|
sprintf (buf, "X%x;process:%x",
|
||||||
|
status->value.sig, ptid_get_pid (ptid));
|
||||||
|
else
|
||||||
|
sprintf (buf, "X%02x", status->value.sig);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error ("unhandled waitkind");
|
error ("unhandled waitkind");
|
||||||
|
@ -1174,6 +1298,31 @@ decode_search_memory_packet (const char *buf, int packet_len,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
free_sym_cache (struct sym_cache *sym)
|
||||||
|
{
|
||||||
|
if (sym != NULL)
|
||||||
|
{
|
||||||
|
free (sym->name);
|
||||||
|
free (sym);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
clear_symbol_cache (struct sym_cache **symcache_p)
|
||||||
|
{
|
||||||
|
struct sym_cache *sym, *next;
|
||||||
|
|
||||||
|
/* Check the cache first. */
|
||||||
|
for (sym = *symcache_p; sym; sym = next)
|
||||||
|
{
|
||||||
|
next = sym->next;
|
||||||
|
free_sym_cache (sym);
|
||||||
|
}
|
||||||
|
|
||||||
|
*symcache_p = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Ask GDB for the address of NAME, and return it in ADDRP if found.
|
/* Ask GDB for the address of NAME, and return it in ADDRP if found.
|
||||||
Returns 1 if the symbol is found, 0 if it is not, -1 on error. */
|
Returns 1 if the symbol is found, 0 if it is not, -1 on error. */
|
||||||
|
|
||||||
|
@ -1183,9 +1332,12 @@ look_up_one_symbol (const char *name, CORE_ADDR *addrp)
|
||||||
char own_buf[266], *p, *q;
|
char own_buf[266], *p, *q;
|
||||||
int len;
|
int len;
|
||||||
struct sym_cache *sym;
|
struct sym_cache *sym;
|
||||||
|
struct process_info *proc;
|
||||||
|
|
||||||
|
proc = current_process ();
|
||||||
|
|
||||||
/* Check the cache first. */
|
/* Check the cache first. */
|
||||||
for (sym = symbol_cache; sym; sym = sym->next)
|
for (sym = proc->symbol_cache; sym; sym = sym->next)
|
||||||
if (strcmp (name, sym->name) == 0)
|
if (strcmp (name, sym->name) == 0)
|
||||||
{
|
{
|
||||||
*addrp = sym->addr;
|
*addrp = sym->addr;
|
||||||
|
@ -1197,7 +1349,7 @@ look_up_one_symbol (const char *name, CORE_ADDR *addrp)
|
||||||
in any libraries loaded after that point, only in symbols in
|
in any libraries loaded after that point, only in symbols in
|
||||||
libpthread.so. It might not be an appropriate time to look
|
libpthread.so. It might not be an appropriate time to look
|
||||||
up a symbol, e.g. while we're trying to fetch registers. */
|
up a symbol, e.g. while we're trying to fetch registers. */
|
||||||
if (all_symbols_looked_up)
|
if (proc->all_symbols_looked_up)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Send the request. */
|
/* Send the request. */
|
||||||
|
@ -1257,8 +1409,8 @@ look_up_one_symbol (const char *name, CORE_ADDR *addrp)
|
||||||
sym = xmalloc (sizeof (*sym));
|
sym = xmalloc (sizeof (*sym));
|
||||||
sym->name = xstrdup (name);
|
sym->name = xstrdup (name);
|
||||||
sym->addr = *addrp;
|
sym->addr = *addrp;
|
||||||
sym->next = symbol_cache;
|
sym->next = proc->symbol_cache;
|
||||||
symbol_cache = sym;
|
proc->symbol_cache = sym;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,17 +32,17 @@
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
unsigned long cont_thread;
|
ptid_t cont_thread;
|
||||||
unsigned long general_thread;
|
ptid_t general_thread;
|
||||||
unsigned long step_thread;
|
ptid_t step_thread;
|
||||||
|
|
||||||
int server_waiting;
|
int server_waiting;
|
||||||
|
|
||||||
static int extended_protocol;
|
static int extended_protocol;
|
||||||
static int attached;
|
|
||||||
static int response_needed;
|
static int response_needed;
|
||||||
static int exit_requested;
|
static int exit_requested;
|
||||||
|
|
||||||
|
int multi_process;
|
||||||
int non_stop;
|
int non_stop;
|
||||||
|
|
||||||
static char **program_argv, **wrapper_argv;
|
static char **program_argv, **wrapper_argv;
|
||||||
|
@ -90,7 +90,7 @@ int disable_packet_qfThreadInfo;
|
||||||
|
|
||||||
/* Last status reported to GDB. */
|
/* Last status reported to GDB. */
|
||||||
static struct target_waitstatus last_status;
|
static struct target_waitstatus last_status;
|
||||||
static unsigned long last_ptid;
|
static ptid_t last_ptid;
|
||||||
|
|
||||||
static char *own_buf;
|
static char *own_buf;
|
||||||
static unsigned char *mem_buf;
|
static unsigned char *mem_buf;
|
||||||
|
@ -104,7 +104,7 @@ struct vstop_notif
|
||||||
struct vstop_notif *next;
|
struct vstop_notif *next;
|
||||||
|
|
||||||
/* Thread or process that got the event. */
|
/* Thread or process that got the event. */
|
||||||
unsigned long ptid;
|
ptid_t ptid;
|
||||||
|
|
||||||
/* Event info. */
|
/* Event info. */
|
||||||
struct target_waitstatus status;
|
struct target_waitstatus status;
|
||||||
|
@ -116,7 +116,7 @@ static struct vstop_notif *notif_queue = NULL;
|
||||||
/* Put a stop reply to the stop reply queue. */
|
/* Put a stop reply to the stop reply queue. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
queue_stop_reply (unsigned long ptid, struct target_waitstatus *status)
|
queue_stop_reply (ptid_t ptid, struct target_waitstatus *status)
|
||||||
{
|
{
|
||||||
struct vstop_notif *new_notif;
|
struct vstop_notif *new_notif;
|
||||||
|
|
||||||
|
@ -153,7 +153,7 @@ queue_stop_reply (unsigned long ptid, struct target_waitstatus *status)
|
||||||
we aren't sending one yet. */
|
we aren't sending one yet. */
|
||||||
|
|
||||||
void
|
void
|
||||||
push_event (unsigned long ptid, struct target_waitstatus *status)
|
push_event (ptid_t ptid, struct target_waitstatus *status)
|
||||||
{
|
{
|
||||||
queue_stop_reply (ptid, status);
|
queue_stop_reply (ptid, status);
|
||||||
|
|
||||||
|
@ -170,19 +170,30 @@ push_event (unsigned long ptid, struct target_waitstatus *status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get rid of the currently pending stop replies. */
|
/* Get rid of the currently pending stop replies for PID. If PID is
|
||||||
|
-1, then apply to all processes. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
discard_queued_stop_replies (void)
|
discard_queued_stop_replies (int pid)
|
||||||
{
|
{
|
||||||
struct vstop_notif *next;
|
struct vstop_notif *prev = NULL, *reply, *next;
|
||||||
|
|
||||||
while (notif_queue)
|
for (reply = notif_queue; reply; reply = next)
|
||||||
{
|
{
|
||||||
next = notif_queue->next;
|
next = reply->next;
|
||||||
notif_queue = next;
|
|
||||||
|
|
||||||
free (next);
|
if (pid == -1
|
||||||
|
|| ptid_get_pid (reply->ptid) == pid)
|
||||||
|
{
|
||||||
|
if (reply == notif_queue)
|
||||||
|
notif_queue = next;
|
||||||
|
else
|
||||||
|
prev->next = reply->next;
|
||||||
|
|
||||||
|
free (reply);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
prev = reply;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,7 +220,6 @@ static int
|
||||||
start_inferior (char **argv)
|
start_inferior (char **argv)
|
||||||
{
|
{
|
||||||
char **new_argv = argv;
|
char **new_argv = argv;
|
||||||
attached = 0;
|
|
||||||
|
|
||||||
if (wrapper_argv != NULL)
|
if (wrapper_argv != NULL)
|
||||||
{
|
{
|
||||||
|
@ -253,13 +263,13 @@ start_inferior (char **argv)
|
||||||
if (wrapper_argv != NULL)
|
if (wrapper_argv != NULL)
|
||||||
{
|
{
|
||||||
struct thread_resume resume_info;
|
struct thread_resume resume_info;
|
||||||
unsigned long ptid;
|
ptid_t ptid;
|
||||||
|
|
||||||
resume_info.thread = -1;
|
resume_info.thread = pid_to_ptid (signal_pid);
|
||||||
resume_info.kind = resume_continue;
|
resume_info.kind = resume_continue;
|
||||||
resume_info.sig = 0;
|
resume_info.sig = 0;
|
||||||
|
|
||||||
ptid = mywait (&last_status, 0, 0);
|
ptid = mywait (pid_to_ptid (signal_pid), &last_status, 0, 0);
|
||||||
|
|
||||||
if (last_status.kind != TARGET_WAITKIND_STOPPED)
|
if (last_status.kind != TARGET_WAITKIND_STOPPED)
|
||||||
return signal_pid;
|
return signal_pid;
|
||||||
|
@ -268,7 +278,7 @@ start_inferior (char **argv)
|
||||||
{
|
{
|
||||||
(*the_target->resume) (&resume_info, 1);
|
(*the_target->resume) (&resume_info, 1);
|
||||||
|
|
||||||
mywait (&last_status, 0, 0);
|
mywait (pid_to_ptid (signal_pid), &last_status, 0, 0);
|
||||||
if (last_status.kind != TARGET_WAITKIND_STOPPED)
|
if (last_status.kind != TARGET_WAITKIND_STOPPED)
|
||||||
return signal_pid;
|
return signal_pid;
|
||||||
}
|
}
|
||||||
|
@ -279,7 +289,7 @@ start_inferior (char **argv)
|
||||||
|
|
||||||
/* Wait till we are at 1st instruction in program, return new pid
|
/* Wait till we are at 1st instruction in program, return new pid
|
||||||
(assuming success). */
|
(assuming success). */
|
||||||
last_ptid = mywait (&last_status, 0, 0);
|
last_ptid = mywait (pid_to_ptid (signal_pid), &last_status, 0, 0);
|
||||||
|
|
||||||
return signal_pid;
|
return signal_pid;
|
||||||
}
|
}
|
||||||
|
@ -293,8 +303,6 @@ attach_inferior (int pid)
|
||||||
if (myattach (pid) != 0)
|
if (myattach (pid) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
attached = 1;
|
|
||||||
|
|
||||||
fprintf (stderr, "Attached; pid = %d\n", pid);
|
fprintf (stderr, "Attached; pid = %d\n", pid);
|
||||||
fflush (stderr);
|
fflush (stderr);
|
||||||
|
|
||||||
|
@ -305,7 +313,7 @@ attach_inferior (int pid)
|
||||||
|
|
||||||
if (!non_stop)
|
if (!non_stop)
|
||||||
{
|
{
|
||||||
last_ptid = mywait (&last_status, 0, 0);
|
last_ptid = mywait (pid_to_ptid (pid), &last_status, 0, 0);
|
||||||
|
|
||||||
/* GDB knows to ignore the first SIGSTOP after attaching to a running
|
/* GDB knows to ignore the first SIGSTOP after attaching to a running
|
||||||
process using the "attach" command, but this is different; it's
|
process using the "attach" command, but this is different; it's
|
||||||
|
@ -656,10 +664,11 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
|
||||||
/* Reply the current thread id. */
|
/* Reply the current thread id. */
|
||||||
if (strcmp ("qC", own_buf) == 0 && !disable_packet_qC)
|
if (strcmp ("qC", own_buf) == 0 && !disable_packet_qC)
|
||||||
{
|
{
|
||||||
unsigned long gdb_id;
|
ptid_t gdb_id;
|
||||||
require_running (own_buf);
|
require_running (own_buf);
|
||||||
|
|
||||||
if (general_thread != 0 && general_thread != -1)
|
if (!ptid_equal (general_thread, null_ptid)
|
||||||
|
&& !ptid_equal (general_thread, minus_one_ptid))
|
||||||
gdb_id = general_thread;
|
gdb_id = general_thread;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -667,7 +676,9 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
|
||||||
gdb_id = thread_to_gdb_id ((struct thread_info *)thread_ptr);
|
gdb_id = thread_to_gdb_id ((struct thread_info *)thread_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
sprintf (own_buf, "QC%lx", gdb_id);
|
sprintf (own_buf, "QC");
|
||||||
|
own_buf += 2;
|
||||||
|
own_buf = write_ptid (own_buf, gdb_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -684,21 +695,28 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
|
||||||
{
|
{
|
||||||
if (strcmp ("qfThreadInfo", own_buf) == 0)
|
if (strcmp ("qfThreadInfo", own_buf) == 0)
|
||||||
{
|
{
|
||||||
|
ptid_t gdb_id;
|
||||||
|
|
||||||
require_running (own_buf);
|
require_running (own_buf);
|
||||||
thread_ptr = all_threads.head;
|
thread_ptr = all_threads.head;
|
||||||
sprintf (own_buf, "m%x",
|
|
||||||
thread_to_gdb_id ((struct thread_info *)thread_ptr));
|
*own_buf++ = 'm';
|
||||||
|
gdb_id = thread_to_gdb_id ((struct thread_info *)thread_ptr);
|
||||||
|
write_ptid (own_buf, gdb_id);
|
||||||
thread_ptr = thread_ptr->next;
|
thread_ptr = thread_ptr->next;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp ("qsThreadInfo", own_buf) == 0)
|
if (strcmp ("qsThreadInfo", own_buf) == 0)
|
||||||
{
|
{
|
||||||
|
ptid_t gdb_id;
|
||||||
|
|
||||||
require_running (own_buf);
|
require_running (own_buf);
|
||||||
if (thread_ptr != NULL)
|
if (thread_ptr != NULL)
|
||||||
{
|
{
|
||||||
sprintf (own_buf, "m%x",
|
*own_buf++ = 'm';
|
||||||
thread_to_gdb_id ((struct thread_info *)thread_ptr));
|
gdb_id = thread_to_gdb_id ((struct thread_info *)thread_ptr);
|
||||||
|
write_ptid (own_buf, gdb_id);
|
||||||
thread_ptr = thread_ptr->next;
|
thread_ptr = thread_ptr->next;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1046,6 +1064,21 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
|
||||||
if (strncmp ("qSupported", own_buf, 10) == 0
|
if (strncmp ("qSupported", own_buf, 10) == 0
|
||||||
&& (own_buf[10] == ':' || own_buf[10] == '\0'))
|
&& (own_buf[10] == ':' || own_buf[10] == '\0'))
|
||||||
{
|
{
|
||||||
|
char *p = &own_buf[10];
|
||||||
|
|
||||||
|
/* Process each feature being provided by GDB. The first
|
||||||
|
feature will follow a ':', and latter features will follow
|
||||||
|
';'. */
|
||||||
|
if (*p == ':')
|
||||||
|
for (p = strtok (p + 1, ";");
|
||||||
|
p != NULL;
|
||||||
|
p = strtok (NULL, ";"))
|
||||||
|
{
|
||||||
|
/* Record if GDB knows about multiprocess support. */
|
||||||
|
if (strcmp (p, "multiprocess+") == 0)
|
||||||
|
multi_process = 1;
|
||||||
|
}
|
||||||
|
|
||||||
sprintf (own_buf, "PacketSize=%x;QPassSignals+", PBUFSIZ - 1);
|
sprintf (own_buf, "PacketSize=%x;QPassSignals+", PBUFSIZ - 1);
|
||||||
|
|
||||||
/* We do not have any hook to indicate whether the target backend
|
/* We do not have any hook to indicate whether the target backend
|
||||||
|
@ -1073,6 +1106,8 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
|
||||||
if (the_target->qxfer_osdata != NULL)
|
if (the_target->qxfer_osdata != NULL)
|
||||||
strcat (own_buf, ";qXfer:osdata:read+");
|
strcat (own_buf, ";qXfer:osdata:read+");
|
||||||
|
|
||||||
|
strcat (own_buf, ";multiprocess+");
|
||||||
|
|
||||||
if (target_supports_non_stop ())
|
if (target_supports_non_stop ())
|
||||||
strcat (own_buf, ";QNonStop+");
|
strcat (own_buf, ";QNonStop+");
|
||||||
|
|
||||||
|
@ -1086,7 +1121,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
|
||||||
char *p = own_buf + 12;
|
char *p = own_buf + 12;
|
||||||
CORE_ADDR parts[2], address = 0;
|
CORE_ADDR parts[2], address = 0;
|
||||||
int i, err;
|
int i, err;
|
||||||
unsigned long ptid = 0;
|
ptid_t ptid = null_ptid;
|
||||||
|
|
||||||
require_running (own_buf);
|
require_running (own_buf);
|
||||||
|
|
||||||
|
@ -1111,7 +1146,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
ptid = strtoul (p, NULL, 16);
|
ptid = read_ptid (p, NULL);
|
||||||
else
|
else
|
||||||
decode_address (&parts[i - 1], p, len);
|
decode_address (&parts[i - 1], p, len);
|
||||||
p = p2;
|
p = p2;
|
||||||
|
@ -1121,7 +1156,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
|
||||||
err = 1;
|
err = 1;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
struct thread_info *thread = gdb_id_to_thread (ptid);
|
struct thread_info *thread = find_thread_pid (ptid);
|
||||||
|
|
||||||
if (thread == NULL)
|
if (thread == NULL)
|
||||||
err = 2;
|
err = 2;
|
||||||
|
@ -1208,10 +1243,30 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp (own_buf, "qAttached") == 0)
|
if (strcmp (own_buf, "qAttached") == 0
|
||||||
|
|| strncmp (own_buf, "qAttached:", sizeof ("qAttached:") - 1) == 0)
|
||||||
{
|
{
|
||||||
require_running (own_buf);
|
struct process_info *process;
|
||||||
strcpy (own_buf, attached ? "1" : "0");
|
|
||||||
|
if (own_buf[sizeof ("qAttached") - 1])
|
||||||
|
{
|
||||||
|
int pid = strtoul (own_buf + sizeof ("qAttached:") - 1, NULL, 16);
|
||||||
|
process = (struct process_info *)
|
||||||
|
find_inferior_id (&all_processes, pid_to_ptid (pid));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
require_running (own_buf);
|
||||||
|
process = current_process ();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process == NULL)
|
||||||
|
{
|
||||||
|
write_enn (own_buf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy (own_buf, process->attached ? "1" : "0");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1227,7 +1282,7 @@ handle_v_cont (char *own_buf)
|
||||||
char *p, *q;
|
char *p, *q;
|
||||||
int n = 0, i = 0;
|
int n = 0, i = 0;
|
||||||
struct thread_resume *resume_info;
|
struct thread_resume *resume_info;
|
||||||
struct thread_resume default_action = {0};
|
struct thread_resume default_action = {{0}};
|
||||||
|
|
||||||
/* Count the number of semicolons in the packet. There should be one
|
/* Count the number of semicolons in the packet. There should be one
|
||||||
for every action. */
|
for every action. */
|
||||||
|
@ -1277,7 +1332,7 @@ handle_v_cont (char *own_buf)
|
||||||
|
|
||||||
if (p[0] == 0)
|
if (p[0] == 0)
|
||||||
{
|
{
|
||||||
resume_info[i].thread = -1;
|
resume_info[i].thread = minus_one_ptid;
|
||||||
default_action = resume_info[i];
|
default_action = resume_info[i];
|
||||||
|
|
||||||
/* Note: we don't increment i here, we'll overwrite this entry
|
/* Note: we don't increment i here, we'll overwrite this entry
|
||||||
|
@ -1285,8 +1340,7 @@ handle_v_cont (char *own_buf)
|
||||||
}
|
}
|
||||||
else if (p[0] == ':')
|
else if (p[0] == ':')
|
||||||
{
|
{
|
||||||
unsigned int gdb_id = strtoul (p + 1, &q, 16);
|
ptid_t ptid = read_ptid (p + 1, &q);
|
||||||
unsigned long thread_id;
|
|
||||||
|
|
||||||
if (p == q)
|
if (p == q)
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -1294,11 +1348,7 @@ handle_v_cont (char *own_buf)
|
||||||
if (p[0] != ';' && p[0] != 0)
|
if (p[0] != ';' && p[0] != 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
thread_id = gdb_id_to_thread_id (gdb_id);
|
resume_info[i].thread = ptid;
|
||||||
if (thread_id)
|
|
||||||
resume_info[i].thread = thread_id;
|
|
||||||
else
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
@ -1309,11 +1359,11 @@ handle_v_cont (char *own_buf)
|
||||||
|
|
||||||
/* Still used in occasional places in the backend. */
|
/* Still used in occasional places in the backend. */
|
||||||
if (n == 1
|
if (n == 1
|
||||||
&& resume_info[0].thread != -1
|
&& !ptid_equal (resume_info[0].thread, minus_one_ptid)
|
||||||
&& resume_info[0].kind != resume_stop)
|
&& resume_info[0].kind != resume_stop)
|
||||||
cont_thread = resume_info[0].thread;
|
cont_thread = resume_info[0].thread;
|
||||||
else
|
else
|
||||||
cont_thread = -1;
|
cont_thread = minus_one_ptid;
|
||||||
set_desired_inferior (0);
|
set_desired_inferior (0);
|
||||||
|
|
||||||
if (!non_stop)
|
if (!non_stop)
|
||||||
|
@ -1327,7 +1377,7 @@ handle_v_cont (char *own_buf)
|
||||||
write_ok (own_buf);
|
write_ok (own_buf);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
last_ptid = mywait (&last_status, 0, 1);
|
last_ptid = mywait (minus_one_ptid, &last_status, 0, 1);
|
||||||
prepare_resume_reply (own_buf, last_ptid, &last_status);
|
prepare_resume_reply (own_buf, last_ptid, &last_status);
|
||||||
disable_async_io ();
|
disable_async_io ();
|
||||||
}
|
}
|
||||||
|
@ -1462,6 +1512,30 @@ handle_v_run (char *own_buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Kill process. Return 1 if successful, 0 if failure. */
|
||||||
|
int
|
||||||
|
handle_v_kill (char *own_buf)
|
||||||
|
{
|
||||||
|
int pid;
|
||||||
|
char *p = &own_buf[6];
|
||||||
|
|
||||||
|
pid = strtol (p, NULL, 16);
|
||||||
|
if (pid != 0 && kill_inferior (pid) == 0)
|
||||||
|
{
|
||||||
|
last_status.kind = TARGET_WAITKIND_SIGNALLED;
|
||||||
|
last_status.value.sig = TARGET_SIGNAL_KILL;
|
||||||
|
last_ptid = pid_to_ptid (pid);
|
||||||
|
discard_queued_stop_replies (pid);
|
||||||
|
write_ok (own_buf);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
write_enn (own_buf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Handle a 'vStopped' packet. */
|
/* Handle a 'vStopped' packet. */
|
||||||
static void
|
static void
|
||||||
handle_v_stopped (char *own_buf)
|
handle_v_stopped (char *own_buf)
|
||||||
|
@ -1473,7 +1547,8 @@ handle_v_stopped (char *own_buf)
|
||||||
struct vstop_notif *head;
|
struct vstop_notif *head;
|
||||||
|
|
||||||
if (remote_debug)
|
if (remote_debug)
|
||||||
fprintf (stderr, "vStopped: acking %ld\n", notif_queue->ptid);
|
fprintf (stderr, "vStopped: acking %s\n",
|
||||||
|
target_pid_to_str (notif_queue->ptid));
|
||||||
|
|
||||||
head = notif_queue;
|
head = notif_queue;
|
||||||
notif_queue = notif_queue->next;
|
notif_queue = notif_queue->next;
|
||||||
|
@ -1510,7 +1585,7 @@ handle_v_requests (char *own_buf, int packet_len, int *new_packet_len)
|
||||||
|
|
||||||
if (strncmp (own_buf, "vAttach;", 8) == 0)
|
if (strncmp (own_buf, "vAttach;", 8) == 0)
|
||||||
{
|
{
|
||||||
if (target_running ())
|
if (!multi_process && target_running ())
|
||||||
{
|
{
|
||||||
fprintf (stderr, "Already debugging a process\n");
|
fprintf (stderr, "Already debugging a process\n");
|
||||||
write_enn (own_buf);
|
write_enn (own_buf);
|
||||||
|
@ -1522,7 +1597,7 @@ handle_v_requests (char *own_buf, int packet_len, int *new_packet_len)
|
||||||
|
|
||||||
if (strncmp (own_buf, "vRun;", 5) == 0)
|
if (strncmp (own_buf, "vRun;", 5) == 0)
|
||||||
{
|
{
|
||||||
if (target_running ())
|
if (!multi_process && target_running ())
|
||||||
{
|
{
|
||||||
fprintf (stderr, "Already debugging a process\n");
|
fprintf (stderr, "Already debugging a process\n");
|
||||||
write_enn (own_buf);
|
write_enn (own_buf);
|
||||||
|
@ -1532,6 +1607,18 @@ handle_v_requests (char *own_buf, int packet_len, int *new_packet_len)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (strncmp (own_buf, "vKill;", 6) == 0)
|
||||||
|
{
|
||||||
|
if (!target_running ())
|
||||||
|
{
|
||||||
|
fprintf (stderr, "No process to kill\n");
|
||||||
|
write_enn (own_buf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
handle_v_kill (own_buf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (strncmp (own_buf, "vStopped", 8) == 0)
|
if (strncmp (own_buf, "vStopped", 8) == 0)
|
||||||
{
|
{
|
||||||
handle_v_stopped (own_buf);
|
handle_v_stopped (own_buf);
|
||||||
|
@ -1556,7 +1643,8 @@ myresume (char *own_buf, int step, int sig)
|
||||||
|
|
||||||
set_desired_inferior (0);
|
set_desired_inferior (0);
|
||||||
|
|
||||||
valid_cont_thread = (cont_thread != 0 && cont_thread != -1);
|
valid_cont_thread = (!ptid_equal (cont_thread, null_ptid)
|
||||||
|
&& !ptid_equal (cont_thread, minus_one_ptid));
|
||||||
|
|
||||||
if (step || sig || valid_cont_thread)
|
if (step || sig || valid_cont_thread)
|
||||||
{
|
{
|
||||||
|
@ -1572,7 +1660,7 @@ myresume (char *own_buf, int step, int sig)
|
||||||
|
|
||||||
if (!valid_cont_thread)
|
if (!valid_cont_thread)
|
||||||
{
|
{
|
||||||
resume_info[n].thread = -1;
|
resume_info[n].thread = minus_one_ptid;
|
||||||
resume_info[n].kind = resume_continue;
|
resume_info[n].kind = resume_continue;
|
||||||
resume_info[n].sig = 0;
|
resume_info[n].sig = 0;
|
||||||
n++;
|
n++;
|
||||||
|
@ -1587,7 +1675,7 @@ myresume (char *own_buf, int step, int sig)
|
||||||
write_ok (own_buf);
|
write_ok (own_buf);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
last_ptid = mywait (&last_status, 0, 1);
|
last_ptid = mywait (minus_one_ptid, &last_status, 0, 1);
|
||||||
prepare_resume_reply (own_buf, last_ptid, &last_status);
|
prepare_resume_reply (own_buf, last_ptid, &last_status);
|
||||||
disable_async_io ();
|
disable_async_io ();
|
||||||
}
|
}
|
||||||
|
@ -1596,16 +1684,24 @@ myresume (char *own_buf, int step, int sig)
|
||||||
/* Callback for for_each_inferior. Make a new stop reply for each
|
/* Callback for for_each_inferior. Make a new stop reply for each
|
||||||
stopped thread. */
|
stopped thread. */
|
||||||
|
|
||||||
static void
|
static int
|
||||||
queue_stop_reply_callback (struct inferior_list_entry *entry)
|
queue_stop_reply_callback (struct inferior_list_entry *entry, void *arg)
|
||||||
{
|
{
|
||||||
struct target_waitstatus status;
|
int pid = * (int *) arg;
|
||||||
|
|
||||||
status.kind = TARGET_WAITKIND_STOPPED;
|
if (pid == -1
|
||||||
status.value.sig = TARGET_SIGNAL_TRAP;
|
|| ptid_get_pid (entry->id) == pid)
|
||||||
|
{
|
||||||
|
struct target_waitstatus status;
|
||||||
|
|
||||||
/* Pass the last stop reply back to GDB, but don't notify. */
|
status.kind = TARGET_WAITKIND_STOPPED;
|
||||||
queue_stop_reply (entry->id, &status);
|
status.value.sig = TARGET_SIGNAL_TRAP;
|
||||||
|
|
||||||
|
/* Pass the last stop reply back to GDB, but don't notify. */
|
||||||
|
queue_stop_reply (entry->id, &status);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Status handler for the '?' packet. */
|
/* Status handler for the '?' packet. */
|
||||||
|
@ -1623,8 +1719,9 @@ handle_status (char *own_buf)
|
||||||
|
|
||||||
if (non_stop)
|
if (non_stop)
|
||||||
{
|
{
|
||||||
discard_queued_stop_replies ();
|
int pid = -1;
|
||||||
for_each_inferior (&all_threads, queue_stop_reply_callback);
|
discard_queued_stop_replies (pid);
|
||||||
|
find_inferior (&all_threads, queue_stop_reply_callback, &pid);
|
||||||
|
|
||||||
/* The first is sent immediatly. OK is sent if there is no
|
/* The first is sent immediatly. OK is sent if there is no
|
||||||
stopped thread, which is the same handling of the vStopped
|
stopped thread, which is the same handling of the vStopped
|
||||||
|
@ -1690,6 +1787,52 @@ gdbserver_show_disableable (FILE *stream)
|
||||||
break; \
|
break; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
first_thread_of (struct inferior_list_entry *entry, void *args)
|
||||||
|
{
|
||||||
|
int pid = * (int *) args;
|
||||||
|
|
||||||
|
if (ptid_get_pid (entry->id) == pid)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
kill_inferior_callback (struct inferior_list_entry *entry)
|
||||||
|
{
|
||||||
|
struct process_info *process = (struct process_info *) entry;
|
||||||
|
int pid = ptid_get_pid (process->head.id);
|
||||||
|
|
||||||
|
kill_inferior (pid);
|
||||||
|
discard_queued_stop_replies (pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
detach_or_kill_inferior_callback (struct inferior_list_entry *entry)
|
||||||
|
{
|
||||||
|
struct process_info *process = (struct process_info *) entry;
|
||||||
|
int pid = ptid_get_pid (process->head.id);
|
||||||
|
|
||||||
|
if (process->attached)
|
||||||
|
detach_inferior (pid);
|
||||||
|
else
|
||||||
|
kill_inferior (pid);
|
||||||
|
|
||||||
|
discard_queued_stop_replies (pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
join_inferiors_callback (struct inferior_list_entry *entry)
|
||||||
|
{
|
||||||
|
struct process_info *process = (struct process_info *) entry;
|
||||||
|
|
||||||
|
/* If we are attached, then we can exit. Otherwise, we need to hang
|
||||||
|
around doing nothing, until the child is gone. */
|
||||||
|
if (!process->attached)
|
||||||
|
join_inferior (ptid_get_pid (process->head.id));
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char *argv[])
|
main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
@ -1827,6 +1970,7 @@ main (int argc, char *argv[])
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
initialize_inferiors ();
|
||||||
initialize_async_io ();
|
initialize_async_io ();
|
||||||
initialize_low ();
|
initialize_low ();
|
||||||
|
|
||||||
|
@ -1861,7 +2005,7 @@ main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
last_status.kind = TARGET_WAITKIND_EXITED;
|
last_status.kind = TARGET_WAITKIND_EXITED;
|
||||||
last_status.value.integer = 0;
|
last_status.value.integer = 0;
|
||||||
last_ptid = -1;
|
last_ptid = minus_one_ptid;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Don't report shared library events on the initial connection,
|
/* Don't report shared library events on the initial connection,
|
||||||
|
@ -1871,8 +2015,9 @@ main (int argc, char *argv[])
|
||||||
|
|
||||||
if (setjmp (toplevel))
|
if (setjmp (toplevel))
|
||||||
{
|
{
|
||||||
fprintf (stderr, "Killing inferior\n");
|
fprintf (stderr, "Killing all inferiors\n");
|
||||||
kill_inferior ();
|
for_each_inferior (&all_processes,
|
||||||
|
kill_inferior_callback);
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1891,6 +2036,7 @@ main (int argc, char *argv[])
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
noack_mode = 0;
|
noack_mode = 0;
|
||||||
|
multi_process = 0;
|
||||||
non_stop = 0;
|
non_stop = 0;
|
||||||
|
|
||||||
remote_open (port);
|
remote_open (port);
|
||||||
|
@ -1916,10 +2062,8 @@ main (int argc, char *argv[])
|
||||||
|
|
||||||
if (exit_requested)
|
if (exit_requested)
|
||||||
{
|
{
|
||||||
if (attached)
|
for_each_inferior (&all_processes,
|
||||||
detach_inferior ();
|
detach_or_kill_inferior_callback);
|
||||||
else
|
|
||||||
kill_inferior ();
|
|
||||||
exit (0);
|
exit (0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1941,6 +2085,7 @@ process_serial_event (void)
|
||||||
int signal;
|
int signal;
|
||||||
unsigned int len;
|
unsigned int len;
|
||||||
CORE_ADDR mem_addr;
|
CORE_ADDR mem_addr;
|
||||||
|
int pid;
|
||||||
unsigned char sig;
|
unsigned char sig;
|
||||||
int packet_len;
|
int packet_len;
|
||||||
int new_packet_len = -1;
|
int new_packet_len = -1;
|
||||||
|
@ -1976,12 +2121,22 @@ process_serial_event (void)
|
||||||
break;
|
break;
|
||||||
case 'D':
|
case 'D':
|
||||||
require_running (own_buf);
|
require_running (own_buf);
|
||||||
fprintf (stderr, "Detaching from inferior\n");
|
|
||||||
if (detach_inferior () != 0)
|
if (multi_process)
|
||||||
|
{
|
||||||
|
i++; /* skip ';' */
|
||||||
|
pid = strtol (&own_buf[i], NULL, 16);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pid =
|
||||||
|
ptid_get_pid (((struct inferior_list_entry *) current_inferior)->id);
|
||||||
|
|
||||||
|
fprintf (stderr, "Detaching from process %d\n", pid);
|
||||||
|
if (detach_inferior (pid) != 0)
|
||||||
write_enn (own_buf);
|
write_enn (own_buf);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
discard_queued_stop_replies ();
|
discard_queued_stop_replies (pid);
|
||||||
write_ok (own_buf);
|
write_ok (own_buf);
|
||||||
|
|
||||||
if (extended_protocol)
|
if (extended_protocol)
|
||||||
|
@ -1989,7 +2144,7 @@ process_serial_event (void)
|
||||||
/* Treat this like a normal program exit. */
|
/* Treat this like a normal program exit. */
|
||||||
last_status.kind = TARGET_WAITKIND_EXITED;
|
last_status.kind = TARGET_WAITKIND_EXITED;
|
||||||
last_status.value.integer = 0;
|
last_status.value.integer = 0;
|
||||||
last_ptid = signal_pid;
|
last_ptid = pid_to_ptid (pid);
|
||||||
|
|
||||||
current_inferior = NULL;
|
current_inferior = NULL;
|
||||||
}
|
}
|
||||||
|
@ -2001,9 +2156,8 @@ process_serial_event (void)
|
||||||
/* If we are attached, then we can exit. Otherwise, we
|
/* If we are attached, then we can exit. Otherwise, we
|
||||||
need to hang around doing nothing, until the child is
|
need to hang around doing nothing, until the child is
|
||||||
gone. */
|
gone. */
|
||||||
if (!attached)
|
for_each_inferior (&all_processes,
|
||||||
join_inferior ();
|
join_inferiors_callback);
|
||||||
|
|
||||||
exit (0);
|
exit (0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2018,16 +2172,38 @@ process_serial_event (void)
|
||||||
case 'H':
|
case 'H':
|
||||||
if (own_buf[1] == 'c' || own_buf[1] == 'g' || own_buf[1] == 's')
|
if (own_buf[1] == 'c' || own_buf[1] == 'g' || own_buf[1] == 's')
|
||||||
{
|
{
|
||||||
unsigned long gdb_id, thread_id;
|
ptid_t gdb_id, thread_id;
|
||||||
|
int pid;
|
||||||
|
|
||||||
require_running (own_buf);
|
require_running (own_buf);
|
||||||
gdb_id = strtoul (&own_buf[2], NULL, 16);
|
|
||||||
if (gdb_id == 0 || gdb_id == -1)
|
gdb_id = read_ptid (&own_buf[2], NULL);
|
||||||
thread_id = gdb_id;
|
|
||||||
|
pid = ptid_get_pid (gdb_id);
|
||||||
|
|
||||||
|
if (ptid_equal (gdb_id, null_ptid)
|
||||||
|
|| ptid_equal (gdb_id, minus_one_ptid))
|
||||||
|
thread_id = null_ptid;
|
||||||
|
else if (pid != 0
|
||||||
|
&& ptid_equal (pid_to_ptid (pid),
|
||||||
|
gdb_id))
|
||||||
|
{
|
||||||
|
struct thread_info *thread =
|
||||||
|
(struct thread_info *) find_inferior (&all_threads,
|
||||||
|
first_thread_of,
|
||||||
|
&pid);
|
||||||
|
if (!thread)
|
||||||
|
{
|
||||||
|
write_enn (own_buf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
thread_id = ((struct inferior_list_entry *)thread)->id;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
thread_id = gdb_id_to_thread_id (gdb_id);
|
thread_id = gdb_id_to_thread_id (gdb_id);
|
||||||
if (thread_id == 0)
|
if (ptid_equal (thread_id, null_ptid))
|
||||||
{
|
{
|
||||||
write_enn (own_buf);
|
write_enn (own_buf);
|
||||||
break;
|
break;
|
||||||
|
@ -2036,7 +2212,7 @@ process_serial_event (void)
|
||||||
|
|
||||||
if (own_buf[1] == 'g')
|
if (own_buf[1] == 'g')
|
||||||
{
|
{
|
||||||
if (thread_id == 0)
|
if (ptid_equal (thread_id, null_ptid))
|
||||||
{
|
{
|
||||||
/* GDB is telling us to choose any thread. Check if
|
/* GDB is telling us to choose any thread. Check if
|
||||||
the currently selected thread is still valid. If
|
the currently selected thread is still valid. If
|
||||||
|
@ -2194,13 +2370,12 @@ process_serial_event (void)
|
||||||
case 'k':
|
case 'k':
|
||||||
response_needed = 0;
|
response_needed = 0;
|
||||||
if (!target_running ())
|
if (!target_running ())
|
||||||
/* The packet we received doesn't make sense - but we
|
/* The packet we received doesn't make sense - but we can't
|
||||||
can't reply to it, either. */
|
reply to it, either. */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
fprintf (stderr, "Killing inferior\n");
|
fprintf (stderr, "Killing all inferiors\n");
|
||||||
kill_inferior ();
|
for_each_inferior (&all_processes, kill_inferior_callback);
|
||||||
discard_queued_stop_replies ();
|
|
||||||
|
|
||||||
/* When using the extended protocol, we wait with no program
|
/* When using the extended protocol, we wait with no program
|
||||||
running. The traditional protocol will exit instead. */
|
running. The traditional protocol will exit instead. */
|
||||||
|
@ -2217,12 +2392,13 @@ process_serial_event (void)
|
||||||
}
|
}
|
||||||
case 'T':
|
case 'T':
|
||||||
{
|
{
|
||||||
unsigned long gdb_id, thread_id;
|
ptid_t gdb_id, thread_id;
|
||||||
|
|
||||||
require_running (own_buf);
|
require_running (own_buf);
|
||||||
gdb_id = strtoul (&own_buf[1], NULL, 16);
|
|
||||||
|
gdb_id = read_ptid (&own_buf[1], NULL);
|
||||||
thread_id = gdb_id_to_thread_id (gdb_id);
|
thread_id = gdb_id_to_thread_id (gdb_id);
|
||||||
if (thread_id == 0)
|
if (ptid_equal (thread_id, null_ptid))
|
||||||
{
|
{
|
||||||
write_enn (own_buf);
|
write_enn (own_buf);
|
||||||
break;
|
break;
|
||||||
|
@ -2242,10 +2418,8 @@ process_serial_event (void)
|
||||||
if (extended_protocol)
|
if (extended_protocol)
|
||||||
{
|
{
|
||||||
if (target_running ())
|
if (target_running ())
|
||||||
{
|
for_each_inferior (&all_processes,
|
||||||
kill_inferior ();
|
kill_inferior_callback);
|
||||||
discard_queued_stop_replies ();
|
|
||||||
}
|
|
||||||
fprintf (stderr, "GDBserver restarting\n");
|
fprintf (stderr, "GDBserver restarting\n");
|
||||||
|
|
||||||
/* Wait till we are at 1st instruction in prog. */
|
/* Wait till we are at 1st instruction in prog. */
|
||||||
|
@ -2323,7 +2497,8 @@ handle_target_event (int err, gdb_client_data client_data)
|
||||||
if (debug_threads)
|
if (debug_threads)
|
||||||
fprintf (stderr, "handling possible target event\n");
|
fprintf (stderr, "handling possible target event\n");
|
||||||
|
|
||||||
last_ptid = mywait (&last_status, TARGET_WNOHANG, 1);
|
last_ptid = mywait (minus_one_ptid, &last_status,
|
||||||
|
TARGET_WNOHANG, 1);
|
||||||
|
|
||||||
if (last_status.kind != TARGET_WAITKIND_IGNORE)
|
if (last_status.kind != TARGET_WAITKIND_IGNORE)
|
||||||
{
|
{
|
||||||
|
|
|
@ -85,6 +85,70 @@ typedef unsigned char gdb_byte;
|
||||||
least the size of a (void *). */
|
least the size of a (void *). */
|
||||||
typedef long long CORE_ADDR;
|
typedef long long CORE_ADDR;
|
||||||
|
|
||||||
|
typedef unsigned long long ULONGEST;
|
||||||
|
|
||||||
|
/* The ptid struct is a collection of the various "ids" necessary
|
||||||
|
for identifying the inferior. This consists of the process id
|
||||||
|
(pid), thread id (tid), and other fields necessary for uniquely
|
||||||
|
identifying the inferior process/thread being debugged. When
|
||||||
|
manipulating ptids, the constructors, accessors, and predicate
|
||||||
|
declared in server.h should be used. These are as follows:
|
||||||
|
|
||||||
|
ptid_build - Make a new ptid from a pid, lwp, and tid.
|
||||||
|
pid_to_ptid - Make a new ptid from just a pid.
|
||||||
|
ptid_get_pid - Fetch the pid component of a ptid.
|
||||||
|
ptid_get_lwp - Fetch the lwp component of a ptid.
|
||||||
|
ptid_get_tid - Fetch the tid component of a ptid.
|
||||||
|
ptid_equal - Test to see if two ptids are equal.
|
||||||
|
|
||||||
|
Please do NOT access the struct ptid members directly (except, of
|
||||||
|
course, in the implementation of the above ptid manipulation
|
||||||
|
functions). */
|
||||||
|
|
||||||
|
struct ptid
|
||||||
|
{
|
||||||
|
/* Process id */
|
||||||
|
int pid;
|
||||||
|
|
||||||
|
/* Lightweight process id */
|
||||||
|
long lwp;
|
||||||
|
|
||||||
|
/* Thread id */
|
||||||
|
long tid;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct ptid ptid_t;
|
||||||
|
|
||||||
|
/* The -1 ptid, often used to indicate either an error condition or a
|
||||||
|
"don't care" condition, i.e, "run all threads". */
|
||||||
|
extern ptid_t minus_one_ptid;
|
||||||
|
|
||||||
|
/* The null or zero ptid, often used to indicate no process. */
|
||||||
|
extern ptid_t null_ptid;
|
||||||
|
|
||||||
|
/* Attempt to find and return an existing ptid with the given PID,
|
||||||
|
LWP, and TID components. If none exists, create a new one and
|
||||||
|
return that. */
|
||||||
|
ptid_t ptid_build (int pid, long lwp, long tid);
|
||||||
|
|
||||||
|
/* Create a ptid from just a pid. */
|
||||||
|
ptid_t pid_to_ptid (int pid);
|
||||||
|
|
||||||
|
/* Fetch the pid (process id) component from a ptid. */
|
||||||
|
int ptid_get_pid (ptid_t ptid);
|
||||||
|
|
||||||
|
/* Fetch the lwp (lightweight process) component from a ptid. */
|
||||||
|
long ptid_get_lwp (ptid_t ptid);
|
||||||
|
|
||||||
|
/* Fetch the tid (thread id) component from a ptid. */
|
||||||
|
long ptid_get_tid (ptid_t ptid);
|
||||||
|
|
||||||
|
/* Compare two ptids to see if they are equal. */
|
||||||
|
extern int ptid_equal (ptid_t p1, ptid_t p2);
|
||||||
|
|
||||||
|
/* Return true if this ptid represents a process id. */
|
||||||
|
extern int ptid_is_pid (ptid_t ptid);
|
||||||
|
|
||||||
/* Generic information for tracking a list of ``inferiors'' - threads,
|
/* Generic information for tracking a list of ``inferiors'' - threads,
|
||||||
processes, etc. */
|
processes, etc. */
|
||||||
struct inferior_list
|
struct inferior_list
|
||||||
|
@ -94,7 +158,7 @@ struct inferior_list
|
||||||
};
|
};
|
||||||
struct inferior_list_entry
|
struct inferior_list_entry
|
||||||
{
|
{
|
||||||
unsigned long id;
|
ptid_t id;
|
||||||
struct inferior_list_entry *next;
|
struct inferior_list_entry *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -108,6 +172,36 @@ struct dll_info
|
||||||
CORE_ADDR base_addr;
|
CORE_ADDR base_addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct sym_cache;
|
||||||
|
struct breakpoint;
|
||||||
|
struct process_info_private;
|
||||||
|
|
||||||
|
struct process_info
|
||||||
|
{
|
||||||
|
struct inferior_list_entry head;
|
||||||
|
|
||||||
|
int attached;
|
||||||
|
|
||||||
|
/* The symbol cache. */
|
||||||
|
struct sym_cache *symbol_cache;
|
||||||
|
|
||||||
|
/* If this flag has been set, assume symbol cache misses are
|
||||||
|
failures. */
|
||||||
|
int all_symbols_looked_up;
|
||||||
|
|
||||||
|
/* The list of memory breakpoints. */
|
||||||
|
struct breakpoint *breakpoints;
|
||||||
|
|
||||||
|
/* Private target data. */
|
||||||
|
struct process_info_private *private;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Return a pointer to the process that corresponds to the current
|
||||||
|
thread (current_inferior). It is an error to call this if there is
|
||||||
|
no current thread selected. */
|
||||||
|
|
||||||
|
struct process_info *current_process (void);
|
||||||
|
|
||||||
#include "regcache.h"
|
#include "regcache.h"
|
||||||
#include "gdb/signals.h"
|
#include "gdb/signals.h"
|
||||||
#include "gdb_signals.h"
|
#include "gdb_signals.h"
|
||||||
|
@ -120,22 +214,33 @@ void initialize_low ();
|
||||||
|
|
||||||
/* From inferiors.c. */
|
/* From inferiors.c. */
|
||||||
|
|
||||||
|
extern struct inferior_list all_processes;
|
||||||
extern struct inferior_list all_threads;
|
extern struct inferior_list all_threads;
|
||||||
extern struct inferior_list all_dlls;
|
extern struct inferior_list all_dlls;
|
||||||
extern int dlls_changed;
|
extern int dlls_changed;
|
||||||
|
|
||||||
|
void initialize_inferiors (void);
|
||||||
|
|
||||||
void add_inferior_to_list (struct inferior_list *list,
|
void add_inferior_to_list (struct inferior_list *list,
|
||||||
struct inferior_list_entry *new_inferior);
|
struct inferior_list_entry *new_inferior);
|
||||||
void for_each_inferior (struct inferior_list *list,
|
void for_each_inferior (struct inferior_list *list,
|
||||||
void (*action) (struct inferior_list_entry *));
|
void (*action) (struct inferior_list_entry *));
|
||||||
|
|
||||||
extern struct thread_info *current_inferior;
|
extern struct thread_info *current_inferior;
|
||||||
void remove_inferior (struct inferior_list *list,
|
void remove_inferior (struct inferior_list *list,
|
||||||
struct inferior_list_entry *entry);
|
struct inferior_list_entry *entry);
|
||||||
void remove_thread (struct thread_info *thread);
|
void remove_thread (struct thread_info *thread);
|
||||||
void add_thread (unsigned long thread_id, void *target_data, unsigned int);
|
void add_thread (ptid_t ptid, void *target_data);
|
||||||
unsigned int thread_id_to_gdb_id (unsigned long);
|
|
||||||
unsigned int thread_to_gdb_id (struct thread_info *);
|
struct process_info *add_process (int pid, int attached);
|
||||||
unsigned long gdb_id_to_thread_id (unsigned int);
|
void remove_process (struct process_info *process);
|
||||||
|
struct process_info *find_process_pid (int pid);
|
||||||
|
|
||||||
|
struct thread_info *find_thread_pid (ptid_t ptid);
|
||||||
|
|
||||||
|
ptid_t thread_id_to_gdb_id (ptid_t);
|
||||||
|
ptid_t thread_to_gdb_id (struct thread_info *);
|
||||||
|
ptid_t gdb_id_to_thread_id (ptid_t);
|
||||||
struct thread_info *gdb_id_to_thread (unsigned int);
|
struct thread_info *gdb_id_to_thread (unsigned int);
|
||||||
void clear_inferiors (void);
|
void clear_inferiors (void);
|
||||||
struct inferior_list_entry *find_inferior
|
struct inferior_list_entry *find_inferior
|
||||||
|
@ -144,7 +249,7 @@ struct inferior_list_entry *find_inferior
|
||||||
void *),
|
void *),
|
||||||
void *arg);
|
void *arg);
|
||||||
struct inferior_list_entry *find_inferior_id (struct inferior_list *list,
|
struct inferior_list_entry *find_inferior_id (struct inferior_list *list,
|
||||||
unsigned long id);
|
ptid_t id);
|
||||||
void *inferior_target_data (struct thread_info *);
|
void *inferior_target_data (struct thread_info *);
|
||||||
void set_inferior_target_data (struct thread_info *, void *);
|
void set_inferior_target_data (struct thread_info *, void *);
|
||||||
void *inferior_regcache_data (struct thread_info *);
|
void *inferior_regcache_data (struct thread_info *);
|
||||||
|
@ -157,9 +262,9 @@ void unloaded_dll (const char *name, CORE_ADDR base_addr);
|
||||||
|
|
||||||
/* Public variables in server.c */
|
/* Public variables in server.c */
|
||||||
|
|
||||||
extern unsigned long cont_thread;
|
extern ptid_t cont_thread;
|
||||||
extern unsigned long general_thread;
|
extern ptid_t general_thread;
|
||||||
extern unsigned long step_thread;
|
extern ptid_t step_thread;
|
||||||
|
|
||||||
extern int server_waiting;
|
extern int server_waiting;
|
||||||
extern int debug_threads;
|
extern int debug_threads;
|
||||||
|
@ -172,6 +277,7 @@ extern int disable_packet_Tthread;
|
||||||
extern int disable_packet_qC;
|
extern int disable_packet_qC;
|
||||||
extern int disable_packet_qfThreadInfo;
|
extern int disable_packet_qfThreadInfo;
|
||||||
|
|
||||||
|
extern int multi_process;
|
||||||
extern int non_stop;
|
extern int non_stop;
|
||||||
|
|
||||||
/* Functions from event-loop.c. */
|
/* Functions from event-loop.c. */
|
||||||
|
@ -188,7 +294,7 @@ extern void start_event_loop (void);
|
||||||
extern void handle_serial_event (int err, gdb_client_data client_data);
|
extern void handle_serial_event (int err, gdb_client_data client_data);
|
||||||
extern void handle_target_event (int err, gdb_client_data client_data);
|
extern void handle_target_event (int err, gdb_client_data client_data);
|
||||||
|
|
||||||
extern void push_event (unsigned long ptid, struct target_waitstatus *status);
|
extern void push_event (ptid_t ptid, struct target_waitstatus *status);
|
||||||
|
|
||||||
/* Functions from hostio.c. */
|
/* Functions from hostio.c. */
|
||||||
extern int handle_vFile (char *, int, int *);
|
extern int handle_vFile (char *, int, int *);
|
||||||
|
@ -203,6 +309,9 @@ extern int all_symbols_looked_up;
|
||||||
extern int noack_mode;
|
extern int noack_mode;
|
||||||
extern int transport_is_reliable;
|
extern int transport_is_reliable;
|
||||||
|
|
||||||
|
ptid_t read_ptid (char *buf, char **obuf);
|
||||||
|
char *write_ptid (char *buf, ptid_t ptid);
|
||||||
|
|
||||||
int putpkt (char *buf);
|
int putpkt (char *buf);
|
||||||
int putpkt_binary (char *buf, int len);
|
int putpkt_binary (char *buf, int len);
|
||||||
int putpkt_notif (char *buf);
|
int putpkt_notif (char *buf);
|
||||||
|
@ -219,7 +328,7 @@ void convert_ascii_to_int (char *from, unsigned char *to, int n);
|
||||||
void convert_int_to_ascii (unsigned char *from, char *to, int n);
|
void convert_int_to_ascii (unsigned char *from, char *to, int n);
|
||||||
void new_thread_notify (int id);
|
void new_thread_notify (int id);
|
||||||
void dead_thread_notify (int id);
|
void dead_thread_notify (int id);
|
||||||
void prepare_resume_reply (char *buf, unsigned long thread_id,
|
void prepare_resume_reply (char *buf, ptid_t ptid,
|
||||||
struct target_waitstatus *status);
|
struct target_waitstatus *status);
|
||||||
|
|
||||||
const char *decode_address_to_semicolon (CORE_ADDR *addrp, const char *start);
|
const char *decode_address_to_semicolon (CORE_ADDR *addrp, const char *start);
|
||||||
|
@ -244,6 +353,7 @@ int remote_escape_output (const gdb_byte *buffer, int len,
|
||||||
gdb_byte *out_buf, int *out_len,
|
gdb_byte *out_buf, int *out_len,
|
||||||
int out_maxlen);
|
int out_maxlen);
|
||||||
|
|
||||||
|
void clear_symbol_cache (struct sym_cache **symcache_p);
|
||||||
int look_up_one_symbol (const char *name, CORE_ADDR *addrp);
|
int look_up_one_symbol (const char *name, CORE_ADDR *addrp);
|
||||||
|
|
||||||
void monitor_output (const char *msg);
|
void monitor_output (const char *msg);
|
||||||
|
|
|
@ -268,6 +268,7 @@ static int
|
||||||
spu_create_inferior (char *program, char **allargs)
|
spu_create_inferior (char *program, char **allargs)
|
||||||
{
|
{
|
||||||
int pid;
|
int pid;
|
||||||
|
ptid_t ptid;
|
||||||
|
|
||||||
pid = fork ();
|
pid = fork ();
|
||||||
if (pid < 0)
|
if (pid < 0)
|
||||||
|
@ -289,7 +290,10 @@ spu_create_inferior (char *program, char **allargs)
|
||||||
_exit (0177);
|
_exit (0177);
|
||||||
}
|
}
|
||||||
|
|
||||||
add_thread (pid, NULL, pid);
|
add_process (pid, 0);
|
||||||
|
|
||||||
|
ptid = ptid_build (pid, pid, 0);
|
||||||
|
add_thread (ptid, NULL);
|
||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,6 +301,8 @@ spu_create_inferior (char *program, char **allargs)
|
||||||
int
|
int
|
||||||
spu_attach (unsigned long pid)
|
spu_attach (unsigned long pid)
|
||||||
{
|
{
|
||||||
|
ptid_t ptid;
|
||||||
|
|
||||||
if (ptrace (PTRACE_ATTACH, pid, 0, 0) != 0)
|
if (ptrace (PTRACE_ATTACH, pid, 0, 0) != 0)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "Cannot attach to process %ld: %s (%d)\n", pid,
|
fprintf (stderr, "Cannot attach to process %ld: %s (%d)\n", pid,
|
||||||
|
@ -305,27 +311,32 @@ spu_attach (unsigned long pid)
|
||||||
_exit (0177);
|
_exit (0177);
|
||||||
}
|
}
|
||||||
|
|
||||||
add_thread (pid, NULL, pid);
|
add_process (pid, 1);
|
||||||
|
ptid = ptid_build (pid, pid, 0);
|
||||||
|
add_thread (ptid, NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Kill the inferior process. */
|
/* Kill the inferior process. */
|
||||||
static void
|
static int
|
||||||
spu_kill (void)
|
spu_kill (int)
|
||||||
{
|
{
|
||||||
ptrace (PTRACE_KILL, current_tid, 0, 0);
|
ptrace (PTRACE_KILL, current_tid, 0, 0);
|
||||||
|
remove_process (pid);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Detach from inferior process. */
|
/* Detach from inferior process. */
|
||||||
static int
|
static int
|
||||||
spu_detach (void)
|
spu_detach (int pid)
|
||||||
{
|
{
|
||||||
ptrace (PTRACE_DETACH, current_tid, 0, 0);
|
ptrace (PTRACE_DETACH, current_tid, 0, 0);
|
||||||
|
remove_process (pid);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
spu_join (void)
|
spu_join (int pid)
|
||||||
{
|
{
|
||||||
int status, ret;
|
int status, ret;
|
||||||
|
|
||||||
|
@ -338,9 +349,9 @@ spu_join (void)
|
||||||
|
|
||||||
/* Return nonzero if the given thread is still alive. */
|
/* Return nonzero if the given thread is still alive. */
|
||||||
static int
|
static int
|
||||||
spu_thread_alive (unsigned long tid)
|
spu_thread_alive (ptid_t ptid)
|
||||||
{
|
{
|
||||||
return tid == current_tid;
|
return ptid_get_lwp (ptid) == current_tid;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Resume process. */
|
/* Resume process. */
|
||||||
|
@ -350,8 +361,8 @@ spu_resume (struct thread_resume *resume_info, size_t n)
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++)
|
||||||
if (resume_info[i].thread == -1
|
if (ptid_equal (resume_info[i].thread, minus_one_ptid)
|
||||||
|| resume_info[i].thread == current_tid)
|
|| ptid_get_lwp (resume_info[i].thread) == current_tid)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (i == n)
|
if (i == n)
|
||||||
|
@ -371,8 +382,8 @@ spu_resume (struct thread_resume *resume_info, size_t n)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait for process, returns status. */
|
/* Wait for process, returns status. */
|
||||||
static unsigned long
|
static ptid_t
|
||||||
spu_wait (struct target_waitstatus *ourstatus, int options)
|
spu_wait (ptid_t ptid, struct target_waitstatus *ourstatus, int options)
|
||||||
{
|
{
|
||||||
int tid = current_tid;
|
int tid = current_tid;
|
||||||
int w;
|
int w;
|
||||||
|
@ -415,7 +426,8 @@ spu_wait (struct target_waitstatus *ourstatus, int options)
|
||||||
ourstatus->kind = TARGET_WAITKIND_EXITED;
|
ourstatus->kind = TARGET_WAITKIND_EXITED;
|
||||||
ourstatus->value.integer = WEXITSTATUS (w);
|
ourstatus->value.integer = WEXITSTATUS (w);
|
||||||
clear_inferiors ();
|
clear_inferiors ();
|
||||||
return ret;
|
remove_process (ret);
|
||||||
|
return pid_to_ptid (ret);
|
||||||
}
|
}
|
||||||
else if (!WIFSTOPPED (w))
|
else if (!WIFSTOPPED (w))
|
||||||
{
|
{
|
||||||
|
@ -423,7 +435,8 @@ spu_wait (struct target_waitstatus *ourstatus, int options)
|
||||||
ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
|
ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
|
||||||
ourstatus->value.sig = target_signal_from_host (WTERMSIG (w));
|
ourstatus->value.sig = target_signal_from_host (WTERMSIG (w));
|
||||||
clear_inferiors ();
|
clear_inferiors ();
|
||||||
return ret;
|
remove_process (ret);
|
||||||
|
return pid_to_ptid (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* After attach, we may have received a SIGSTOP. Do not return this
|
/* After attach, we may have received a SIGSTOP. Do not return this
|
||||||
|
@ -432,12 +445,12 @@ spu_wait (struct target_waitstatus *ourstatus, int options)
|
||||||
{
|
{
|
||||||
ourstatus->kind = TARGET_WAITKIND_STOPPED;
|
ourstatus->kind = TARGET_WAITKIND_STOPPED;
|
||||||
ourstatus->value.sig = TARGET_SIGNAL_0;
|
ourstatus->value.sig = TARGET_SIGNAL_0;
|
||||||
return ret;
|
return ptid_build (ret, ret, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ourstatus->kind = TARGET_WAITKIND_STOPPED;
|
ourstatus->kind = TARGET_WAITKIND_STOPPED;
|
||||||
ourstatus->value.sig = target_signal_from_host (WSTOPSIG (w));
|
ourstatus->value.sig = target_signal_from_host (WSTOPSIG (w));
|
||||||
return ret;
|
return ptid_build (ret, ret, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fetch inferior registers. */
|
/* Fetch inferior registers. */
|
||||||
|
|
|
@ -29,10 +29,7 @@ set_desired_inferior (int use_general)
|
||||||
struct thread_info *found;
|
struct thread_info *found;
|
||||||
|
|
||||||
if (use_general == 1)
|
if (use_general == 1)
|
||||||
{
|
found = find_thread_pid (general_thread);
|
||||||
found = (struct thread_info *) find_inferior_id (&all_threads,
|
|
||||||
general_thread);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
found = NULL;
|
found = NULL;
|
||||||
|
@ -40,14 +37,14 @@ set_desired_inferior (int use_general)
|
||||||
/* If we are continuing any (all) thread(s), use step_thread
|
/* If we are continuing any (all) thread(s), use step_thread
|
||||||
to decide which thread to step and/or send the specified
|
to decide which thread to step and/or send the specified
|
||||||
signal to. */
|
signal to. */
|
||||||
if ((step_thread != 0 && step_thread != -1)
|
if ((!ptid_equal (step_thread, null_ptid)
|
||||||
&& (cont_thread == 0 || cont_thread == -1))
|
&& !ptid_equal (step_thread, minus_one_ptid))
|
||||||
found = (struct thread_info *) find_inferior_id (&all_threads,
|
&& (ptid_equal (cont_thread, null_ptid)
|
||||||
step_thread);
|
|| ptid_equal (cont_thread, minus_one_ptid)))
|
||||||
|
found = find_thread_pid (step_thread);
|
||||||
|
|
||||||
if (found == NULL)
|
if (found == NULL)
|
||||||
found = (struct thread_info *) find_inferior_id (&all_threads,
|
found = find_thread_pid (cont_thread);
|
||||||
cont_thread);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (found == NULL)
|
if (found == NULL)
|
||||||
|
@ -88,28 +85,24 @@ write_inferior_memory (CORE_ADDR memaddr, const unsigned char *myaddr,
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long
|
ptid_t
|
||||||
mywait (struct target_waitstatus *ourstatus, int options,
|
mywait (ptid_t ptid, struct target_waitstatus *ourstatus, int options,
|
||||||
int connected_wait)
|
int connected_wait)
|
||||||
{
|
{
|
||||||
unsigned long ret;
|
ptid_t ret;
|
||||||
|
|
||||||
if (connected_wait)
|
if (connected_wait)
|
||||||
server_waiting = 1;
|
server_waiting = 1;
|
||||||
|
|
||||||
ret = (*the_target->wait) (ourstatus, options);
|
ret = (*the_target->wait) (ptid, ourstatus, options);
|
||||||
|
|
||||||
if (ourstatus->kind == TARGET_WAITKIND_EXITED
|
if (ourstatus->kind == TARGET_WAITKIND_EXITED)
|
||||||
|| ourstatus->kind == TARGET_WAITKIND_SIGNALLED)
|
fprintf (stderr,
|
||||||
{
|
"\nChild exited with status %d\n", ourstatus->value.sig);
|
||||||
if (ourstatus->kind == TARGET_WAITKIND_EXITED)
|
else if (ourstatus->kind == TARGET_WAITKIND_SIGNALLED)
|
||||||
fprintf (stderr,
|
fprintf (stderr, "\nChild terminated with signal = 0x%x (%s)\n",
|
||||||
"\nChild exited with status %d\n", ourstatus->value.sig);
|
target_signal_to_host (ourstatus->value.sig),
|
||||||
if (ourstatus->kind == TARGET_WAITKIND_SIGNALLED)
|
target_signal_to_name (ourstatus->value.sig));
|
||||||
fprintf (stderr, "\nChild terminated with signal = 0x%x (%s)\n",
|
|
||||||
target_signal_to_host (ourstatus->value.sig),
|
|
||||||
target_signal_to_name (ourstatus->value.sig));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (connected_wait)
|
if (connected_wait)
|
||||||
server_waiting = 0;
|
server_waiting = 0;
|
||||||
|
@ -137,3 +130,27 @@ set_target_ops (struct target_ops *target)
|
||||||
the_target = (struct target_ops *) xmalloc (sizeof (*the_target));
|
the_target = (struct target_ops *) xmalloc (sizeof (*the_target));
|
||||||
memcpy (the_target, target, sizeof (*the_target));
|
memcpy (the_target, target, sizeof (*the_target));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Convert pid to printable format. */
|
||||||
|
|
||||||
|
const char *
|
||||||
|
target_pid_to_str (ptid_t ptid)
|
||||||
|
{
|
||||||
|
static char buf[80];
|
||||||
|
|
||||||
|
if (ptid_equal (ptid, minus_one_ptid))
|
||||||
|
snprintf (buf, sizeof (buf), "<all threads>");
|
||||||
|
else if (ptid_equal (ptid, null_ptid))
|
||||||
|
snprintf (buf, sizeof (buf), "<null thread>");
|
||||||
|
else if (ptid_get_tid (ptid) != 0)
|
||||||
|
snprintf (buf, sizeof (buf), "Thread %d.0x%lx",
|
||||||
|
ptid_get_pid (ptid), ptid_get_tid (ptid));
|
||||||
|
else if (ptid_get_lwp (ptid) != 0)
|
||||||
|
snprintf (buf, sizeof (buf), "LWP %d.%ld",
|
||||||
|
ptid_get_pid (ptid), ptid_get_lwp (ptid));
|
||||||
|
else
|
||||||
|
snprintf (buf, sizeof (buf), "Process %d",
|
||||||
|
ptid_get_pid (ptid));
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ enum resume_kind
|
||||||
|
|
||||||
struct thread_resume
|
struct thread_resume
|
||||||
{
|
{
|
||||||
unsigned long thread;
|
ptid_t thread;
|
||||||
|
|
||||||
/* How to "resume". */
|
/* How to "resume". */
|
||||||
enum resume_kind kind;
|
enum resume_kind kind;
|
||||||
|
@ -96,7 +96,7 @@ struct target_waitstatus
|
||||||
{
|
{
|
||||||
int integer;
|
int integer;
|
||||||
enum target_signal sig;
|
enum target_signal sig;
|
||||||
unsigned long related_pid;
|
ptid_t related_pid;
|
||||||
char *execd_pathname;
|
char *execd_pathname;
|
||||||
}
|
}
|
||||||
value;
|
value;
|
||||||
|
@ -129,31 +129,38 @@ struct target_ops
|
||||||
|
|
||||||
int (*attach) (unsigned long pid);
|
int (*attach) (unsigned long pid);
|
||||||
|
|
||||||
/* Kill all inferiors. */
|
/* Kill inferior PID. Return -1 on failure, and 0 on success. */
|
||||||
|
|
||||||
void (*kill) (void);
|
int (*kill) (int pid);
|
||||||
|
|
||||||
/* Detach from all inferiors.
|
/* Detach from inferior PID. Return -1 on failure, and 0 on
|
||||||
Return -1 on failure, and 0 on success. */
|
success. */
|
||||||
|
|
||||||
int (*detach) (void);
|
int (*detach) (int pid);
|
||||||
|
|
||||||
/* Wait for inferiors to end. */
|
/* Wait for inferior PID to exit. */
|
||||||
|
void (*join) (int pid);
|
||||||
void (*join) (void);
|
|
||||||
|
|
||||||
/* Return 1 iff the thread with process ID PID is alive. */
|
/* Return 1 iff the thread with process ID PID is alive. */
|
||||||
|
|
||||||
int (*thread_alive) (unsigned long pid);
|
int (*thread_alive) (ptid_t pid);
|
||||||
|
|
||||||
/* Resume the inferior process. */
|
/* Resume the inferior process. */
|
||||||
|
|
||||||
void (*resume) (struct thread_resume *resume_info, size_t n);
|
void (*resume) (struct thread_resume *resume_info, size_t n);
|
||||||
|
|
||||||
/* Wait for the inferior process or thread to change state. Store
|
/* Wait for the inferior process or thread to change state. Store
|
||||||
status through argument pointer STATUS. */
|
status through argument pointer STATUS.
|
||||||
|
|
||||||
unsigned long (*wait) (struct target_waitstatus *status, int options);
|
PTID = -1 to wait for any pid to do something, PTID(pid,0,0) to
|
||||||
|
wait for any thread of process pid to do something. Return ptid
|
||||||
|
of child, or -1 in case of error; store status through argument
|
||||||
|
pointer STATUS. OPTIONS is a bit set of options defined as
|
||||||
|
TARGET_W* above. If options contains TARGET_WNOHANG and there's
|
||||||
|
no child stop to report, return is
|
||||||
|
null_ptid/TARGET_WAITKIND_IGNORE. */
|
||||||
|
|
||||||
|
ptid_t (*wait) (ptid_t ptid, struct target_waitstatus *status, int options);
|
||||||
|
|
||||||
/* Fetch registers from the inferior process.
|
/* Fetch registers from the inferior process.
|
||||||
|
|
||||||
|
@ -280,11 +287,11 @@ void set_target_ops (struct target_ops *);
|
||||||
#define myattach(pid) \
|
#define myattach(pid) \
|
||||||
(*the_target->attach) (pid)
|
(*the_target->attach) (pid)
|
||||||
|
|
||||||
#define kill_inferior() \
|
#define kill_inferior(pid) \
|
||||||
(*the_target->kill) ()
|
(*the_target->kill) (pid)
|
||||||
|
|
||||||
#define detach_inferior() \
|
#define detach_inferior(pid) \
|
||||||
(*the_target->detach) ()
|
(*the_target->detach) (pid)
|
||||||
|
|
||||||
#define mythread_alive(pid) \
|
#define mythread_alive(pid) \
|
||||||
(*the_target->thread_alive) (pid)
|
(*the_target->thread_alive) (pid)
|
||||||
|
@ -295,8 +302,8 @@ void set_target_ops (struct target_ops *);
|
||||||
#define store_inferior_registers(regno) \
|
#define store_inferior_registers(regno) \
|
||||||
(*the_target->store_registers) (regno)
|
(*the_target->store_registers) (regno)
|
||||||
|
|
||||||
#define join_inferior() \
|
#define join_inferior(pid) \
|
||||||
(*the_target->join) ()
|
(*the_target->join) (pid)
|
||||||
|
|
||||||
#define target_supports_non_stop() \
|
#define target_supports_non_stop() \
|
||||||
(the_target->supports_non_stop ? (*the_target->supports_non_stop ) () : 0)
|
(the_target->supports_non_stop ? (*the_target->supports_non_stop ) () : 0)
|
||||||
|
@ -308,8 +315,8 @@ void set_target_ops (struct target_ops *);
|
||||||
|
|
||||||
int start_non_stop (int nonstop);
|
int start_non_stop (int nonstop);
|
||||||
|
|
||||||
unsigned long mywait (struct target_waitstatus *ourstatus, int options,
|
ptid_t mywait (ptid_t ptid, struct target_waitstatus *ourstatus, int options,
|
||||||
int connected_wait);
|
int connected_wait);
|
||||||
|
|
||||||
int read_inferior_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len);
|
int read_inferior_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len);
|
||||||
|
|
||||||
|
@ -318,4 +325,6 @@ int write_inferior_memory (CORE_ADDR memaddr, const unsigned char *myaddr,
|
||||||
|
|
||||||
void set_desired_inferior (int id);
|
void set_desired_inferior (int id);
|
||||||
|
|
||||||
|
const char *target_pid_to_str (ptid_t);
|
||||||
|
|
||||||
#endif /* TARGET_H */
|
#endif /* TARGET_H */
|
||||||
|
|
|
@ -35,14 +35,7 @@ static int thread_db_use_events;
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
/* Structure that identifies the child process for the
|
static int find_one_thread (ptid_t);
|
||||||
<proc_service.h> interface. */
|
|
||||||
static struct ps_prochandle proc_handle;
|
|
||||||
|
|
||||||
/* Connection to the libthread_db library. */
|
|
||||||
static td_thragent_t *thread_agent;
|
|
||||||
|
|
||||||
static int find_one_thread (int);
|
|
||||||
static int find_new_threads_callback (const td_thrhandle_t *th_p, void *data);
|
static int find_new_threads_callback (const td_thrhandle_t *th_p, void *data);
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
|
@ -137,6 +130,7 @@ thread_db_create_event (CORE_ADDR where)
|
||||||
td_event_msg_t msg;
|
td_event_msg_t msg;
|
||||||
td_err_e err;
|
td_err_e err;
|
||||||
struct lwp_info *lwp;
|
struct lwp_info *lwp;
|
||||||
|
struct process_info_private *proc = current_process()->private;
|
||||||
|
|
||||||
if (debug_threads)
|
if (debug_threads)
|
||||||
fprintf (stderr, "Thread creation event.\n");
|
fprintf (stderr, "Thread creation event.\n");
|
||||||
|
@ -145,7 +139,7 @@ thread_db_create_event (CORE_ADDR where)
|
||||||
In the LinuxThreads implementation, this is safe,
|
In the LinuxThreads implementation, this is safe,
|
||||||
because all events come from the manager thread
|
because all events come from the manager thread
|
||||||
(except for its own creation, of course). */
|
(except for its own creation, of course). */
|
||||||
err = td_ta_event_getmsg (thread_agent, &msg);
|
err = td_ta_event_getmsg (proc->thread_agent, &msg);
|
||||||
if (err != TD_OK)
|
if (err != TD_OK)
|
||||||
fprintf (stderr, "thread getmsg err: %s\n",
|
fprintf (stderr, "thread getmsg err: %s\n",
|
||||||
thread_db_err_str (err));
|
thread_db_err_str (err));
|
||||||
|
@ -155,7 +149,7 @@ thread_db_create_event (CORE_ADDR where)
|
||||||
created threads. */
|
created threads. */
|
||||||
lwp = get_thread_lwp (current_inferior);
|
lwp = get_thread_lwp (current_inferior);
|
||||||
if (lwp->thread_known == 0)
|
if (lwp->thread_known == 0)
|
||||||
find_one_thread (lwpid_of (lwp));
|
find_one_thread (lwp->head.id);
|
||||||
|
|
||||||
/* msg.event == TD_EVENT_CREATE */
|
/* msg.event == TD_EVENT_CREATE */
|
||||||
|
|
||||||
|
@ -181,6 +175,7 @@ thread_db_enable_reporting ()
|
||||||
td_thr_events_t events;
|
td_thr_events_t events;
|
||||||
td_notify_t notify;
|
td_notify_t notify;
|
||||||
td_err_e err;
|
td_err_e err;
|
||||||
|
struct process_info_private *proc = current_process()->private;
|
||||||
|
|
||||||
/* Set the process wide mask saying which events we're interested in. */
|
/* Set the process wide mask saying which events we're interested in. */
|
||||||
td_event_emptyset (&events);
|
td_event_emptyset (&events);
|
||||||
|
@ -192,7 +187,7 @@ thread_db_enable_reporting ()
|
||||||
td_event_addset (&events, TD_DEATH);
|
td_event_addset (&events, TD_DEATH);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
err = td_ta_set_event (thread_agent, &events);
|
err = td_ta_set_event (proc->thread_agent, &events);
|
||||||
if (err != TD_OK)
|
if (err != TD_OK)
|
||||||
{
|
{
|
||||||
warning ("Unable to set global thread event mask: %s",
|
warning ("Unable to set global thread event mask: %s",
|
||||||
|
@ -201,7 +196,7 @@ thread_db_enable_reporting ()
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get address for thread creation breakpoint. */
|
/* Get address for thread creation breakpoint. */
|
||||||
err = td_ta_event_addr (thread_agent, TD_CREATE, ¬ify);
|
err = td_ta_event_addr (proc->thread_agent, TD_CREATE, ¬ify);
|
||||||
if (err != TD_OK)
|
if (err != TD_OK)
|
||||||
{
|
{
|
||||||
warning ("Unable to get location for thread creation breakpoint: %s",
|
warning ("Unable to get location for thread creation breakpoint: %s",
|
||||||
|
@ -216,7 +211,7 @@ thread_db_enable_reporting ()
|
||||||
with actual thread deaths (via wait). */
|
with actual thread deaths (via wait). */
|
||||||
|
|
||||||
/* Get address for thread death breakpoint. */
|
/* Get address for thread death breakpoint. */
|
||||||
err = td_ta_event_addr (thread_agent, TD_DEATH, ¬ify);
|
err = td_ta_event_addr (proc->thread_agent, TD_DEATH, ¬ify);
|
||||||
if (err != TD_OK)
|
if (err != TD_OK)
|
||||||
{
|
{
|
||||||
warning ("Unable to get location for thread death breakpoint: %s",
|
warning ("Unable to get location for thread death breakpoint: %s",
|
||||||
|
@ -231,21 +226,23 @@ thread_db_enable_reporting ()
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
find_one_thread (int lwpid)
|
find_one_thread (ptid_t ptid)
|
||||||
{
|
{
|
||||||
td_thrhandle_t th;
|
td_thrhandle_t th;
|
||||||
td_thrinfo_t ti;
|
td_thrinfo_t ti;
|
||||||
td_err_e err;
|
td_err_e err;
|
||||||
struct thread_info *inferior;
|
struct thread_info *inferior;
|
||||||
struct lwp_info *lwp;
|
struct lwp_info *lwp;
|
||||||
|
struct process_info_private *proc = current_process()->private;
|
||||||
|
int lwpid = ptid_get_lwp (ptid);
|
||||||
|
|
||||||
inferior = (struct thread_info *) find_inferior_id (&all_threads, lwpid);
|
inferior = (struct thread_info *) find_inferior_id (&all_threads, ptid);
|
||||||
lwp = get_thread_lwp (inferior);
|
lwp = get_thread_lwp (inferior);
|
||||||
if (lwp->thread_known)
|
if (lwp->thread_known)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/* Get information about this thread. */
|
/* Get information about this thread. */
|
||||||
err = td_ta_map_lwp2thr (thread_agent, lwpid_of (lwp), &th);
|
err = td_ta_map_lwp2thr (proc->thread_agent, lwpid, &th);
|
||||||
if (err != TD_OK)
|
if (err != TD_OK)
|
||||||
error ("Cannot get thread handle for LWP %d: %s",
|
error ("Cannot get thread handle for LWP %d: %s",
|
||||||
lwpid, thread_db_err_str (err));
|
lwpid, thread_db_err_str (err));
|
||||||
|
@ -259,10 +256,10 @@ find_one_thread (int lwpid)
|
||||||
fprintf (stderr, "Found thread %ld (LWP %d)\n",
|
fprintf (stderr, "Found thread %ld (LWP %d)\n",
|
||||||
ti.ti_tid, ti.ti_lid);
|
ti.ti_tid, ti.ti_lid);
|
||||||
|
|
||||||
if (lwpid_of (lwp) != ti.ti_lid)
|
if (lwpid != ti.ti_lid)
|
||||||
{
|
{
|
||||||
warning ("PID mismatch! Expected %ld, got %ld",
|
warning ("PID mismatch! Expected %ld, got %ld",
|
||||||
(long) lwpid_of (lwp), (long) ti.ti_lid);
|
(long) lwpid, (long) ti.ti_lid);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,29 +286,24 @@ static void
|
||||||
maybe_attach_thread (const td_thrhandle_t *th_p, td_thrinfo_t *ti_p)
|
maybe_attach_thread (const td_thrhandle_t *th_p, td_thrinfo_t *ti_p)
|
||||||
{
|
{
|
||||||
td_err_e err;
|
td_err_e err;
|
||||||
struct thread_info *inferior;
|
|
||||||
struct lwp_info *lwp;
|
struct lwp_info *lwp;
|
||||||
|
|
||||||
inferior = (struct thread_info *) find_inferior_id (&all_threads,
|
lwp = find_lwp_pid (pid_to_ptid (ti_p->ti_lid));
|
||||||
ti_p->ti_lid);
|
if (lwp != NULL)
|
||||||
if (inferior != NULL)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (debug_threads)
|
if (debug_threads)
|
||||||
fprintf (stderr, "Attaching to thread %ld (LWP %d)\n",
|
fprintf (stderr, "Attaching to thread %ld (LWP %d)\n",
|
||||||
ti_p->ti_tid, ti_p->ti_lid);
|
ti_p->ti_tid, ti_p->ti_lid);
|
||||||
linux_attach_lwp (ti_p->ti_lid);
|
linux_attach_lwp (ti_p->ti_lid);
|
||||||
inferior = (struct thread_info *) find_inferior_id (&all_threads,
|
lwp = find_lwp_pid (pid_to_ptid (ti_p->ti_lid));
|
||||||
ti_p->ti_lid);
|
if (lwp == NULL)
|
||||||
if (inferior == NULL)
|
|
||||||
{
|
{
|
||||||
warning ("Could not attach to thread %ld (LWP %d)\n",
|
warning ("Could not attach to thread %ld (LWP %d)\n",
|
||||||
ti_p->ti_tid, ti_p->ti_lid);
|
ti_p->ti_tid, ti_p->ti_lid);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
lwp = inferior_target_data (inferior);
|
|
||||||
|
|
||||||
lwp->thread_known = 1;
|
lwp->thread_known = 1;
|
||||||
lwp->th = *th_p;
|
lwp->th = *th_p;
|
||||||
|
|
||||||
|
@ -347,15 +339,18 @@ static void
|
||||||
thread_db_find_new_threads (void)
|
thread_db_find_new_threads (void)
|
||||||
{
|
{
|
||||||
td_err_e err;
|
td_err_e err;
|
||||||
|
ptid_t ptid = ((struct inferior_list_entry *) current_inferior)->id;
|
||||||
|
struct process_info_private *proc = current_process()->private;
|
||||||
|
|
||||||
/* This function is only called when we first initialize thread_db.
|
/* This function is only called when we first initialize thread_db.
|
||||||
First locate the initial thread. If it is not ready for
|
First locate the initial thread. If it is not ready for
|
||||||
debugging yet, then stop. */
|
debugging yet, then stop. */
|
||||||
if (find_one_thread (all_threads.head->id) == 0)
|
if (find_one_thread (ptid) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Iterate over all user-space threads to discover new threads. */
|
/* Iterate over all user-space threads to discover new threads. */
|
||||||
err = td_ta_thr_iter (thread_agent, find_new_threads_callback, NULL,
|
err = td_ta_thr_iter (proc->thread_agent,
|
||||||
|
find_new_threads_callback, NULL,
|
||||||
TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
|
TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
|
||||||
TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
|
TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
|
||||||
if (err != TD_OK)
|
if (err != TD_OK)
|
||||||
|
@ -385,18 +380,22 @@ thread_db_get_tls_address (struct thread_info *thread, CORE_ADDR offset,
|
||||||
psaddr_t addr;
|
psaddr_t addr;
|
||||||
td_err_e err;
|
td_err_e err;
|
||||||
struct lwp_info *lwp;
|
struct lwp_info *lwp;
|
||||||
|
struct thread_info *saved_inferior;
|
||||||
|
|
||||||
lwp = get_thread_lwp (thread);
|
lwp = get_thread_lwp (thread);
|
||||||
if (!lwp->thread_known)
|
if (!lwp->thread_known)
|
||||||
find_one_thread (lwpid_of (lwp));
|
find_one_thread (lwp->head.id);
|
||||||
if (!lwp->thread_known)
|
if (!lwp->thread_known)
|
||||||
return TD_NOTHR;
|
return TD_NOTHR;
|
||||||
|
|
||||||
|
saved_inferior = current_inferior;
|
||||||
|
current_inferior = thread;
|
||||||
/* Note the cast through uintptr_t: this interface only works if
|
/* Note the cast through uintptr_t: this interface only works if
|
||||||
a target address fits in a psaddr_t, which is a host pointer.
|
a target address fits in a psaddr_t, which is a host pointer.
|
||||||
So a 32-bit debugger can not access 64-bit TLS through this. */
|
So a 32-bit debugger can not access 64-bit TLS through this. */
|
||||||
err = td_thr_tls_get_addr (&lwp->th, (psaddr_t) (uintptr_t) load_module,
|
err = td_thr_tls_get_addr (&lwp->th, (psaddr_t) (uintptr_t) load_module,
|
||||||
offset, &addr);
|
offset, &addr);
|
||||||
|
current_inferior = saved_inferior;
|
||||||
if (err == TD_OK)
|
if (err == TD_OK)
|
||||||
{
|
{
|
||||||
*address = (CORE_ADDR) (uintptr_t) addr;
|
*address = (CORE_ADDR) (uintptr_t) addr;
|
||||||
|
@ -413,6 +412,8 @@ int
|
||||||
thread_db_init (int use_events)
|
thread_db_init (int use_events)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
struct process_info *proc = current_process ();
|
||||||
|
struct process_info_private *priv = proc->private;
|
||||||
|
|
||||||
/* FIXME drow/2004-10-16: This is the "overall process ID", which
|
/* FIXME drow/2004-10-16: This is the "overall process ID", which
|
||||||
GNU/Linux calls tgid, "thread group ID". When we support
|
GNU/Linux calls tgid, "thread group ID". When we support
|
||||||
|
@ -424,14 +425,10 @@ thread_db_init (int use_events)
|
||||||
|
|
||||||
This isn't the only place in gdbserver that assumes that the first
|
This isn't the only place in gdbserver that assumes that the first
|
||||||
process in the list is the thread group leader. */
|
process in the list is the thread group leader. */
|
||||||
proc_handle.pid = ((struct inferior_list_entry *)current_inferior)->id;
|
|
||||||
|
|
||||||
/* Allow new symbol lookups. */
|
|
||||||
all_symbols_looked_up = 0;
|
|
||||||
|
|
||||||
thread_db_use_events = use_events;
|
thread_db_use_events = use_events;
|
||||||
|
|
||||||
err = td_ta_new (&proc_handle, &thread_agent);
|
err = td_ta_new (&priv->proc_handle, &priv->thread_agent);
|
||||||
switch (err)
|
switch (err)
|
||||||
{
|
{
|
||||||
case TD_NOLIBTHREAD:
|
case TD_NOLIBTHREAD:
|
||||||
|
@ -445,7 +442,7 @@ thread_db_init (int use_events)
|
||||||
return 0;
|
return 0;
|
||||||
thread_db_find_new_threads ();
|
thread_db_find_new_threads ();
|
||||||
thread_db_look_up_symbols ();
|
thread_db_look_up_symbols ();
|
||||||
all_symbols_looked_up = 1;
|
proc->all_symbols_looked_up = 1;
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -94,11 +94,17 @@ static void win32_resume (struct thread_resume *resume_info, size_t n);
|
||||||
|
|
||||||
/* Get the thread ID from the current selected inferior (the current
|
/* Get the thread ID from the current selected inferior (the current
|
||||||
thread). */
|
thread). */
|
||||||
static DWORD
|
static ptid_t
|
||||||
current_inferior_tid (void)
|
current_inferior_ptid (void)
|
||||||
{
|
{
|
||||||
win32_thread_info *th = inferior_target_data (current_inferior);
|
return ((struct inferior_list_entry*) current_inferior)->id;
|
||||||
return th->tid;
|
}
|
||||||
|
|
||||||
|
/* The current debug event from WaitForDebugEvent. */
|
||||||
|
static ptid_t
|
||||||
|
debug_event_ptid (DEBUG_EVENT *event)
|
||||||
|
{
|
||||||
|
return ptid_build (event->dwProcessId, event->dwThreadId, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the thread context of the thread associated with TH. */
|
/* Get the thread context of the thread associated with TH. */
|
||||||
|
@ -137,12 +143,12 @@ win32_set_thread_context (win32_thread_info *th)
|
||||||
/* Find a thread record given a thread id. If GET_CONTEXT is set then
|
/* Find a thread record given a thread id. If GET_CONTEXT is set then
|
||||||
also retrieve the context for this thread. */
|
also retrieve the context for this thread. */
|
||||||
static win32_thread_info *
|
static win32_thread_info *
|
||||||
thread_rec (DWORD id, int get_context)
|
thread_rec (ptid_t ptid, int get_context)
|
||||||
{
|
{
|
||||||
struct thread_info *thread;
|
struct thread_info *thread;
|
||||||
win32_thread_info *th;
|
win32_thread_info *th;
|
||||||
|
|
||||||
thread = (struct thread_info *) find_inferior_id (&all_threads, id);
|
thread = (struct thread_info *) find_inferior_id (&all_threads, ptid);
|
||||||
if (thread == NULL)
|
if (thread == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -169,20 +175,21 @@ thread_rec (DWORD id, int get_context)
|
||||||
|
|
||||||
/* Add a thread to the thread list. */
|
/* Add a thread to the thread list. */
|
||||||
static win32_thread_info *
|
static win32_thread_info *
|
||||||
child_add_thread (DWORD tid, HANDLE h)
|
child_add_thread (DWORD pid, DWORD tid, HANDLE h)
|
||||||
{
|
{
|
||||||
win32_thread_info *th;
|
win32_thread_info *th;
|
||||||
|
ptid_t ptid = ptid_build (pid, tid, 0);
|
||||||
|
|
||||||
if ((th = thread_rec (tid, FALSE)))
|
if ((th = thread_rec (ptid, FALSE)))
|
||||||
return th;
|
return th;
|
||||||
|
|
||||||
th = xcalloc (1, sizeof (*th));
|
th = xcalloc (1, sizeof (*th));
|
||||||
th->tid = tid;
|
th->tid = tid;
|
||||||
th->h = h;
|
th->h = h;
|
||||||
|
|
||||||
add_thread (tid, th, (unsigned int) tid);
|
add_thread (ptid, th);
|
||||||
set_inferior_regcache_data ((struct thread_info *)
|
set_inferior_regcache_data ((struct thread_info *)
|
||||||
find_inferior_id (&all_threads, tid),
|
find_inferior_id (&all_threads, ptid),
|
||||||
new_register_cache ());
|
new_register_cache ());
|
||||||
|
|
||||||
if (the_low_target.thread_added != NULL)
|
if (the_low_target.thread_added != NULL)
|
||||||
|
@ -204,15 +211,17 @@ delete_thread_info (struct inferior_list_entry *thread)
|
||||||
|
|
||||||
/* Delete a thread from the list of threads. */
|
/* Delete a thread from the list of threads. */
|
||||||
static void
|
static void
|
||||||
child_delete_thread (DWORD id)
|
child_delete_thread (DWORD pid, DWORD tid)
|
||||||
{
|
{
|
||||||
struct inferior_list_entry *thread;
|
struct inferior_list_entry *thread;
|
||||||
|
ptid_t ptid;
|
||||||
|
|
||||||
/* If the last thread is exiting, just return. */
|
/* If the last thread is exiting, just return. */
|
||||||
if (all_threads.head == all_threads.tail)
|
if (all_threads.head == all_threads.tail)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
thread = find_inferior_id (&all_threads, id);
|
ptid = ptid_build (pid, tid, 0);
|
||||||
|
thread = find_inferior_id (&all_threads, ptid);
|
||||||
if (thread == NULL)
|
if (thread == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -250,7 +259,7 @@ child_init_thread_list (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
do_initial_child_stuff (HANDLE proch, DWORD pid)
|
do_initial_child_stuff (HANDLE proch, DWORD pid, int attached)
|
||||||
{
|
{
|
||||||
last_sig = TARGET_SIGNAL_0;
|
last_sig = TARGET_SIGNAL_0;
|
||||||
|
|
||||||
|
@ -263,6 +272,7 @@ do_initial_child_stuff (HANDLE proch, DWORD pid)
|
||||||
|
|
||||||
memset (¤t_event, 0, sizeof (current_event));
|
memset (¤t_event, 0, sizeof (current_event));
|
||||||
|
|
||||||
|
add_process (pid, attached);
|
||||||
child_init_thread_list ();
|
child_init_thread_list ();
|
||||||
|
|
||||||
if (the_low_target.initial_stuff != NULL)
|
if (the_low_target.initial_stuff != NULL)
|
||||||
|
@ -320,7 +330,7 @@ static void
|
||||||
child_fetch_inferior_registers (int r)
|
child_fetch_inferior_registers (int r)
|
||||||
{
|
{
|
||||||
int regno;
|
int regno;
|
||||||
win32_thread_info *th = thread_rec (current_inferior_tid (), TRUE);
|
win32_thread_info *th = thread_rec (current_inferior_ptid (), TRUE);
|
||||||
if (r == -1 || r == 0 || r > NUM_REGS)
|
if (r == -1 || r == 0 || r > NUM_REGS)
|
||||||
child_fetch_inferior_registers (NUM_REGS);
|
child_fetch_inferior_registers (NUM_REGS);
|
||||||
else
|
else
|
||||||
|
@ -334,7 +344,7 @@ static void
|
||||||
child_store_inferior_registers (int r)
|
child_store_inferior_registers (int r)
|
||||||
{
|
{
|
||||||
int regno;
|
int regno;
|
||||||
win32_thread_info *th = thread_rec (current_inferior_tid (), TRUE);
|
win32_thread_info *th = thread_rec (current_inferior_ptid (), TRUE);
|
||||||
if (r == -1 || r == 0 || r > NUM_REGS)
|
if (r == -1 || r == 0 || r > NUM_REGS)
|
||||||
child_store_inferior_registers (NUM_REGS);
|
child_store_inferior_registers (NUM_REGS);
|
||||||
else
|
else
|
||||||
|
@ -540,7 +550,7 @@ win32_create_inferior (char *program, char **program_args)
|
||||||
CloseHandle (pi.hThread);
|
CloseHandle (pi.hThread);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
do_initial_child_stuff (pi.hProcess, pi.dwProcessId);
|
do_initial_child_stuff (pi.hProcess, pi.dwProcessId, 0);
|
||||||
|
|
||||||
return current_process_id;
|
return current_process_id;
|
||||||
}
|
}
|
||||||
|
@ -571,7 +581,7 @@ win32_attach (unsigned long pid)
|
||||||
|
|
||||||
/* win32_wait needs to know we're attaching. */
|
/* win32_wait needs to know we're attaching. */
|
||||||
attaching = 1;
|
attaching = 1;
|
||||||
do_initial_child_stuff (h, pid);
|
do_initial_child_stuff (h, pid, 1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -639,11 +649,13 @@ win32_clear_inferiors (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Kill all inferiors. */
|
/* Kill all inferiors. */
|
||||||
static void
|
static int
|
||||||
win32_kill (void)
|
win32_kill (int pid)
|
||||||
{
|
{
|
||||||
|
struct process_info *process;
|
||||||
|
|
||||||
if (current_process_handle == NULL)
|
if (current_process_handle == NULL)
|
||||||
return;
|
return -1;
|
||||||
|
|
||||||
TerminateProcess (current_process_handle, 0);
|
TerminateProcess (current_process_handle, 0);
|
||||||
for (;;)
|
for (;;)
|
||||||
|
@ -662,12 +674,17 @@ win32_kill (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
win32_clear_inferiors ();
|
win32_clear_inferiors ();
|
||||||
|
|
||||||
|
process = find_process_pid (pid);
|
||||||
|
remove_process (process);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Detach from all inferiors. */
|
/* Detach from inferior PID. */
|
||||||
static int
|
static int
|
||||||
win32_detach (void)
|
win32_detach (int pid)
|
||||||
{
|
{
|
||||||
|
struct process_info *process;
|
||||||
winapi_DebugActiveProcessStop DebugActiveProcessStop = NULL;
|
winapi_DebugActiveProcessStop DebugActiveProcessStop = NULL;
|
||||||
winapi_DebugSetProcessKillOnExit DebugSetProcessKillOnExit = NULL;
|
winapi_DebugSetProcessKillOnExit DebugSetProcessKillOnExit = NULL;
|
||||||
#ifdef _WIN32_WCE
|
#ifdef _WIN32_WCE
|
||||||
|
@ -684,7 +701,7 @@ win32_detach (void)
|
||||||
|
|
||||||
{
|
{
|
||||||
struct thread_resume resume;
|
struct thread_resume resume;
|
||||||
resume.thread = -1;
|
resume.thread = minus_one_ptid;
|
||||||
resume.kind = resume_continue;
|
resume.kind = resume_continue;
|
||||||
resume.sig = 0;
|
resume.sig = 0;
|
||||||
win32_resume (&resume, 1);
|
win32_resume (&resume, 1);
|
||||||
|
@ -694,6 +711,8 @@ win32_detach (void)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
DebugSetProcessKillOnExit (FALSE);
|
DebugSetProcessKillOnExit (FALSE);
|
||||||
|
process = find_process_pid (pid);
|
||||||
|
remove_process (process);
|
||||||
|
|
||||||
win32_clear_inferiors ();
|
win32_clear_inferiors ();
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -701,11 +720,9 @@ win32_detach (void)
|
||||||
|
|
||||||
/* Wait for inferiors to end. */
|
/* Wait for inferiors to end. */
|
||||||
static void
|
static void
|
||||||
win32_join (void)
|
win32_join (int pid)
|
||||||
{
|
{
|
||||||
extern unsigned long signal_pid;
|
HANDLE h = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid);
|
||||||
|
|
||||||
HANDLE h = OpenProcess (PROCESS_ALL_ACCESS, FALSE, signal_pid);
|
|
||||||
if (h != NULL)
|
if (h != NULL)
|
||||||
{
|
{
|
||||||
WaitForSingleObject (h, INFINITE);
|
WaitForSingleObject (h, INFINITE);
|
||||||
|
@ -715,13 +732,13 @@ win32_join (void)
|
||||||
|
|
||||||
/* Return 1 iff the thread with thread ID TID is alive. */
|
/* Return 1 iff the thread with thread ID TID is alive. */
|
||||||
static int
|
static int
|
||||||
win32_thread_alive (unsigned long tid)
|
win32_thread_alive (ptid_t ptid)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
/* Our thread list is reliable; don't bother to poll target
|
/* Our thread list is reliable; don't bother to poll target
|
||||||
threads. */
|
threads. */
|
||||||
if (find_inferior_id (&all_threads, tid) != NULL)
|
if (find_inferior_id (&all_threads, ptid) != NULL)
|
||||||
res = 1;
|
res = 1;
|
||||||
else
|
else
|
||||||
res = 0;
|
res = 0;
|
||||||
|
@ -738,11 +755,12 @@ win32_resume (struct thread_resume *resume_info, size_t n)
|
||||||
int step;
|
int step;
|
||||||
win32_thread_info *th;
|
win32_thread_info *th;
|
||||||
DWORD continue_status = DBG_CONTINUE;
|
DWORD continue_status = DBG_CONTINUE;
|
||||||
|
ptid_t ptid;
|
||||||
|
|
||||||
/* This handles the very limited set of resume packets that GDB can
|
/* This handles the very limited set of resume packets that GDB can
|
||||||
currently produce. */
|
currently produce. */
|
||||||
|
|
||||||
if (n == 1 && resume_info[0].thread == -1)
|
if (n == 1 && ptid_equal (resume_info[0].thread, minus_one_ptid))
|
||||||
tid = -1;
|
tid = -1;
|
||||||
else if (n > 1)
|
else if (n > 1)
|
||||||
tid = -1;
|
tid = -1;
|
||||||
|
@ -751,7 +769,7 @@ win32_resume (struct thread_resume *resume_info, size_t n)
|
||||||
the Windows resume code do the right thing for thread switching. */
|
the Windows resume code do the right thing for thread switching. */
|
||||||
tid = current_event.dwThreadId;
|
tid = current_event.dwThreadId;
|
||||||
|
|
||||||
if (resume_info[0].thread != -1)
|
if (!ptid_equal (resume_info[0].thread, minus_one_ptid))
|
||||||
{
|
{
|
||||||
sig = resume_info[0].sig;
|
sig = resume_info[0].sig;
|
||||||
step = resume_info[0].kind == resume_step;
|
step = resume_info[0].kind == resume_step;
|
||||||
|
@ -777,7 +795,8 @@ win32_resume (struct thread_resume *resume_info, size_t n)
|
||||||
last_sig = TARGET_SIGNAL_0;
|
last_sig = TARGET_SIGNAL_0;
|
||||||
|
|
||||||
/* Get context for the currently selected thread. */
|
/* Get context for the currently selected thread. */
|
||||||
th = thread_rec (current_event.dwThreadId, FALSE);
|
ptid = debug_event_ptid (¤t_event);
|
||||||
|
th = thread_rec (ptid, FALSE);
|
||||||
if (th)
|
if (th)
|
||||||
{
|
{
|
||||||
if (th->context.ContextFlags)
|
if (th->context.ContextFlags)
|
||||||
|
@ -1295,6 +1314,8 @@ auto_delete_breakpoint (CORE_ADDR stop_pc)
|
||||||
static int
|
static int
|
||||||
get_child_debug_event (struct target_waitstatus *ourstatus)
|
get_child_debug_event (struct target_waitstatus *ourstatus)
|
||||||
{
|
{
|
||||||
|
ptid_t ptid;
|
||||||
|
|
||||||
last_sig = TARGET_SIGNAL_0;
|
last_sig = TARGET_SIGNAL_0;
|
||||||
ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
|
ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
|
||||||
|
|
||||||
|
@ -1349,9 +1370,9 @@ get_child_debug_event (struct target_waitstatus *ourstatus)
|
||||||
|
|
||||||
gotevent:
|
gotevent:
|
||||||
|
|
||||||
|
ptid = debug_event_ptid (¤t_event);
|
||||||
current_inferior =
|
current_inferior =
|
||||||
(struct thread_info *) find_inferior_id (&all_threads,
|
(struct thread_info *) find_inferior_id (&all_threads, ptid);
|
||||||
current_event.dwThreadId);
|
|
||||||
|
|
||||||
switch (current_event.dwDebugEventCode)
|
switch (current_event.dwDebugEventCode)
|
||||||
{
|
{
|
||||||
|
@ -1362,8 +1383,9 @@ get_child_debug_event (struct target_waitstatus *ourstatus)
|
||||||
(unsigned) current_event.dwThreadId));
|
(unsigned) current_event.dwThreadId));
|
||||||
|
|
||||||
/* Record the existence of this thread. */
|
/* Record the existence of this thread. */
|
||||||
child_add_thread (current_event.dwThreadId,
|
child_add_thread (current_event.dwProcessId,
|
||||||
current_event.u.CreateThread.hThread);
|
current_event.dwThreadId,
|
||||||
|
current_event.u.CreateThread.hThread);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EXIT_THREAD_DEBUG_EVENT:
|
case EXIT_THREAD_DEBUG_EVENT:
|
||||||
|
@ -1371,7 +1393,8 @@ get_child_debug_event (struct target_waitstatus *ourstatus)
|
||||||
"for pid=%d tid=%x\n",
|
"for pid=%d tid=%x\n",
|
||||||
(unsigned) current_event.dwProcessId,
|
(unsigned) current_event.dwProcessId,
|
||||||
(unsigned) current_event.dwThreadId));
|
(unsigned) current_event.dwThreadId));
|
||||||
child_delete_thread (current_event.dwThreadId);
|
child_delete_thread (current_event.dwProcessId,
|
||||||
|
current_event.dwThreadId);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CREATE_PROCESS_DEBUG_EVENT:
|
case CREATE_PROCESS_DEBUG_EVENT:
|
||||||
|
@ -1388,10 +1411,11 @@ get_child_debug_event (struct target_waitstatus *ourstatus)
|
||||||
ourstatus->value.execd_pathname = "Main executable";
|
ourstatus->value.execd_pathname = "Main executable";
|
||||||
|
|
||||||
/* Add the main thread. */
|
/* Add the main thread. */
|
||||||
child_add_thread (main_thread_id,
|
child_add_thread (current_event.dwProcessId,
|
||||||
|
main_thread_id,
|
||||||
current_event.u.CreateProcessInfo.hThread);
|
current_event.u.CreateProcessInfo.hThread);
|
||||||
|
|
||||||
ourstatus->value.related_pid = current_event.dwThreadId;
|
ourstatus->value.related_pid = debug_event_ptid (¤t_event);
|
||||||
#ifdef _WIN32_WCE
|
#ifdef _WIN32_WCE
|
||||||
if (!attaching)
|
if (!attaching)
|
||||||
{
|
{
|
||||||
|
@ -1467,17 +1491,18 @@ get_child_debug_event (struct target_waitstatus *ourstatus)
|
||||||
}
|
}
|
||||||
|
|
||||||
current_inferior =
|
current_inferior =
|
||||||
(struct thread_info *) find_inferior_id (&all_threads,
|
(struct thread_info *) find_inferior_id (&all_threads, ptid);
|
||||||
current_event.dwThreadId);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait for the inferior process to change state.
|
/* Wait for the inferior process to change state.
|
||||||
STATUS will be filled in with a response code to send to GDB.
|
STATUS will be filled in with a response code to send to GDB.
|
||||||
Returns the signal which caused the process to stop. */
|
Returns the signal which caused the process to stop. */
|
||||||
static unsigned long
|
static ptid_t
|
||||||
win32_wait (struct target_waitstatus *ourstatus, int options)
|
win32_wait (ptid_t ptid, struct target_waitstatus *ourstatus, int options)
|
||||||
{
|
{
|
||||||
|
struct process_info *process;
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
if (!get_child_debug_event (ourstatus))
|
if (!get_child_debug_event (ourstatus))
|
||||||
|
@ -1489,8 +1514,10 @@ win32_wait (struct target_waitstatus *ourstatus, int options)
|
||||||
OUTMSG2 (("Child exited with retcode = %x\n",
|
OUTMSG2 (("Child exited with retcode = %x\n",
|
||||||
ourstatus->value.integer));
|
ourstatus->value.integer));
|
||||||
|
|
||||||
|
process = find_process_pid (current_process_id);
|
||||||
|
remove_process (process);
|
||||||
win32_clear_inferiors ();
|
win32_clear_inferiors ();
|
||||||
return current_event.dwProcessId;
|
return pid_to_ptid (current_event.dwProcessId);
|
||||||
case TARGET_WAITKIND_STOPPED:
|
case TARGET_WAITKIND_STOPPED:
|
||||||
case TARGET_WAITKIND_LOADED:
|
case TARGET_WAITKIND_LOADED:
|
||||||
OUTMSG2 (("Child Stopped with signal = %d \n",
|
OUTMSG2 (("Child Stopped with signal = %d \n",
|
||||||
|
@ -1512,7 +1539,7 @@ win32_wait (struct target_waitstatus *ourstatus, int options)
|
||||||
if (ourstatus->kind == TARGET_WAITKIND_LOADED)
|
if (ourstatus->kind == TARGET_WAITKIND_LOADED)
|
||||||
ourstatus->kind = TARGET_WAITKIND_STOPPED;
|
ourstatus->kind = TARGET_WAITKIND_STOPPED;
|
||||||
|
|
||||||
return current_event.dwThreadId;
|
return debug_event_ptid (¤t_event);
|
||||||
default:
|
default:
|
||||||
OUTMSG (("Ignoring unknown internal event, %d\n", ourstatus->kind));
|
OUTMSG (("Ignoring unknown internal event, %d\n", ourstatus->kind));
|
||||||
/* fall-through */
|
/* fall-through */
|
||||||
|
|
Loading…
Reference in a new issue