Multi-target support
This commit adds multi-target support to GDB. What this means is that with this commit, GDB can now be connected to different targets at the same time. E.g., you can debug a live native process and a core dump at the same time, connect to multiple gdbservers, etc. Actually, the word "target" is overloaded in gdb. We already have a target stack, with pushes several target_ops instances on top of one another. We also have "info target" already, which means something completely different to what this patch does. So from here on, I'll be using the "target connections" term, to mean an open process_stratum target, pushed on a target stack. This patch makes gdb have multiple target stacks, and multiple process_stratum targets open simultaneously. The user-visible changes / commands will also use this terminology, but of course it's all open to debate. User-interface-wise, not that much changes. The main difference is that each inferior may have its own target connection. A target connection (e.g., a target extended-remote connection) may support debugging multiple processes, just as before. Say you're debugging against gdbserver in extended-remote mode, and you do "add-inferior" to prepare to spawn a new process, like: (gdb) target extended-remote :9999 ... (gdb) start ... (gdb) add-inferior Added inferior 2 (gdb) inferior 2 [Switching to inferior 2 [<null>] (<noexec>)] (gdb) file a.out ... (gdb) start ... At this point, you have two inferiors connected to the same gdbserver. With this commit, GDB will maintain a target stack per inferior, instead of a global target stack. To preserve the behavior above, by default, "add-inferior" makes the new inferior inherit a copy of the target stack of the current inferior. Same across a fork - the child inherits a copy of the target stack of the parent. While the target stacks are copied, the targets themselves are not. Instead, target_ops is made a refcounted_object, which means that target_ops instances are refcounted, which each inferior counting for a reference. What if you want to create an inferior and connect it to some _other_ target? For that, this commit introduces a new "add-inferior -no-connection" option that makes the new inferior not share the current inferior's target. So you could do: (gdb) target extended-remote :9999 Remote debugging using :9999 ... (gdb) add-inferior -no-connection [New inferior 2] Added inferior 2 (gdb) inferior 2 [Switching to inferior 2 [<null>] (<noexec>)] (gdb) info inferiors Num Description Executable 1 process 18401 target:/home/pedro/tmp/main * 2 <null> (gdb) tar extended-remote :10000 Remote debugging using :10000 ... (gdb) info inferiors Num Description Executable 1 process 18401 target:/home/pedro/tmp/main * 2 process 18450 target:/home/pedro/tmp/main (gdb) A following patch will extended "info inferiors" to include a column indicating which connection an inferior is bound to, along with a couple other UI tweaks. Other than that, debugging is the same as before. Users interact with inferiors and threads as before. The only difference is that inferiors may be bound to processes running in different machines. That's pretty much all there is to it in terms of noticeable UI changes. On to implementation. Since we can be connected to different systems at the same time, a ptid_t is no longer a unique identifier. Instead a thread can be identified by a pair of ptid_t and 'process_stratum_target *', the later being the instance of the process_stratum target that owns the process/thread. Note that process_stratum_target inherits from target_ops, and all process_stratum targets inherit from process_stratum_target. In earlier patches, many places in gdb were converted to refer to threads by thread_info pointer instead of ptid_t, but there are still places in gdb where we start with a pid/tid and need to find the corresponding inferior or thread_info objects. So you'll see in the patch many places adding a process_stratum_target parameter to functions that used to take only a ptid_t. Since each inferior has its own target stack now, we can always find the process_stratum target for an inferior. That is done via a inf->process_target() convenience method. Since each inferior has its own target stack, we need to handle the "beneath" calls when servicing target calls. The solution I settled with is just to make sure to switch the current inferior to the inferior you want before making a target call. Not relying on global context is just not feasible in current GDB. Fortunately, there aren't that many places that need to do that, because generally most code that calls target methods already has the current context pointing to the right inferior/thread. Note, to emphasize -- there's no method to "switch to this target stack". Instead, you switch the current inferior, and that implicitly switches the target stack. In some spots, we need to iterate over all inferiors so that we reach all target stacks. Native targets are still singletons. There's always only a single instance of such targets. Remote targets however, we'll have one instance per remote connection. The exec target is still a singleton. There's only one instance. I did not see the point of instanciating more than one exec_target object. After vfork, we need to make sure to push the exec target on the new inferior. See exec_on_vfork. For type safety, functions that need a {target, ptid} pair to identify a thread, take a process_stratum_target pointer for target parameter instead of target_ops *. Some shared code in gdb/nat/ also need to gain a target pointer parameter. This poses an issue, since gdbserver doesn't have process_stratum_target, only target_ops. To fix this, this commit renames gdbserver's target_ops to process_stratum_target. I think this makes sense. There's no concept of target stack in gdbserver, and gdbserver's target_ops really implements a process_stratum-like target. The thread and inferior iterator functions also gain process_stratum_target parameters. These are used to be able to iterate over threads and inferiors of a given target. Following usual conventions, if the target pointer is null, then we iterate over threads and inferiors of all targets. I tried converting "add-inferior" to the gdb::option framework, as a preparatory patch, but that stumbled on the fact that gdb::option does not support file options yet, for "add-inferior -exec". I have a WIP patchset that adds that, but it's not a trivial patch, mainly due to need to integrate readline's filename completion, so I deferred that to some other time. In infrun.c/infcmd.c, the main change is that we need to poll events out of all targets. See do_target_wait. Right after collecting an event, we switch the current inferior to an inferior bound to the target that reported the event, so that target methods can be used while handling the event. This makes most of the code transparent to multi-targets. See fetch_inferior_event. infrun.c:stop_all_threads is interesting -- in this function we need to stop all threads of all targets. What the function does is send an asynchronous stop request to all threads, and then synchronously waits for events, with target_wait, rinse repeat, until all it finds are stopped threads. Now that we have multiple targets, it's not efficient to synchronously block in target_wait waiting for events out of one target. Instead, we implement a mini event loop, with interruptible_select, select'ing on one file descriptor per target. For this to work, we need to be able to ask the target for a waitable file descriptor. Such file descriptors already exist, they are the descriptors registered in the main event loop with add_file_handler, inside the target_async implementations. This commit adds a new target_async_wait_fd target method that just returns the file descriptor in question. See wait_one / stop_all_threads in infrun.c. The 'threads_executing' global is made a per-target variable. Since it is only relevant to process_stratum_target targets, this is where it is put, instead of in target_ops. You'll notice that remote.c includes some FIXME notes. These refer to the fact that the global arrays that hold data for the remote packets supported are still globals. For example, if we connect to two different servers/stubs, then each might support different remote protocol features. They might even be different architectures, like e.g., one ARM baremetal stub, and a x86 gdbserver, to debug a host/controller scenario as a single program. That isn't going to work correctly today, because of said globals. I'm leaving fixing that for another pass, since it does not appear to be trivial, and I'd rather land the base work first. It's already useful to be able to debug multiple instances of the same server (e.g., a distributed cluster, where you have full control over the servers installed), so I think as is it's already reasonable incremental progress. Current limitations: - You can only resume more that one target at the same time if all targets support asynchronous debugging, and support non-stop mode. It should be possible to support mixed all-stop + non-stop backends, but that is left for another time. This means that currently in order to do multi-target with gdbserver you need to issue "maint set target-non-stop on". I would like to make that mode be the default, but we're not there yet. Note that I'm talking about how the target backend works, only. User-visible all-stop mode works just fine. - As explained above, connecting to different remote servers at the same time is likely to produce bad results if they don't support the exact set of RSP features. FreeBSD updates courtesy of John Baldwin. gdb/ChangeLog: 2020-01-10 Pedro Alves <palves@redhat.com> John Baldwin <jhb@FreeBSD.org> * aarch64-linux-nat.c (aarch64_linux_nat_target::thread_architecture): Adjust. * ada-tasks.c (print_ada_task_info): Adjust find_thread_ptid call. (task_command_1): Likewise. * aix-thread.c (sync_threadlists, aix_thread_target::resume) (aix_thread_target::wait, aix_thread_target::fetch_registers) (aix_thread_target::store_registers) (aix_thread_target::thread_alive): Adjust. * amd64-fbsd-tdep.c: Include "inferior.h". (amd64fbsd_get_thread_local_address): Pass down target. * amd64-linux-nat.c (ps_get_thread_area): Use ps_prochandle thread's gdbarch instead of target_gdbarch. * break-catch-sig.c (signal_catchpoint_print_it): Adjust call to get_last_target_status. * break-catch-syscall.c (print_it_catch_syscall): Likewise. * breakpoint.c (breakpoints_should_be_inserted_now): Consider all inferiors. (update_inserted_breakpoint_locations): Skip if inferiors with no execution. (update_global_location_list): When handling moribund locations, find representative inferior for location's pspace, and use thread count of its process_stratum target. * bsd-kvm.c (bsd_kvm_target_open): Pass target down. * bsd-uthread.c (bsd_uthread_target::wait): Use as_process_stratum_target and adjust thread_change_ptid and add_thread calls. (bsd_uthread_target::update_thread_list): Use as_process_stratum_target and adjust find_thread_ptid, thread_change_ptid and add_thread calls. * btrace.c (maint_btrace_packet_history_cmd): Adjust find_thread_ptid call. * corelow.c (add_to_thread_list): Adjust add_thread call. (core_target_open): Adjust add_thread_silent and thread_count calls. (core_target::pid_to_str): Adjust find_inferior_ptid call. * ctf.c (ctf_target_open): Adjust add_thread_silent call. * event-top.c (async_disconnect): Pop targets from all inferiors. * exec.c (add_target_sections): Push exec target on all inferiors sharing the program space. (remove_target_sections): Remove the exec target from all inferiors sharing the program space. (exec_on_vfork): New. * exec.h (exec_on_vfork): Declare. * fbsd-nat.c (fbsd_add_threads): Add fbsd_nat_target parameter. Pass it down. (fbsd_nat_target::update_thread_list): Adjust. (fbsd_nat_target::resume): Adjust. (fbsd_handle_debug_trap): Add fbsd_nat_target parameter. Pass it down. (fbsd_nat_target::wait, fbsd_nat_target::post_attach): Adjust. * fbsd-tdep.c (fbsd_corefile_thread): Adjust get_thread_arch_regcache call. * fork-child.c (gdb_startup_inferior): Pass target down to startup_inferior and set_executing. * gdbthread.h (struct process_stratum_target): Forward declare. (add_thread, add_thread_silent, add_thread_with_info) (in_thread_list): Add process_stratum_target parameter. (find_thread_ptid(inferior*, ptid_t)): New overload. (find_thread_ptid, thread_change_ptid): Add process_stratum_target parameter. (all_threads()): Delete overload. (all_threads, all_non_exited_threads): Add process_stratum_target parameter. (all_threads_safe): Use brace initialization. (thread_count): Add process_stratum_target parameter. (set_resumed, set_running, set_stop_requested, set_executing) (threads_are_executing, finish_thread_state): Add process_stratum_target parameter. (switch_to_thread): Use is_current_thread. * i386-fbsd-tdep.c: Include "inferior.h". (i386fbsd_get_thread_local_address): Pass down target. * i386-linux-nat.c (i386_linux_nat_target::low_resume): Adjust. * inf-child.c (inf_child_target::maybe_unpush_target): Remove have_inferiors check. * inf-ptrace.c (inf_ptrace_target::create_inferior) (inf_ptrace_target::attach): Adjust. * infcall.c (run_inferior_call): Adjust. * infcmd.c (run_command_1): Pass target to scoped_finish_thread_state. (proceed_thread_callback): Skip inferiors with no execution. (continue_command): Rename 'all_threads' local to avoid hiding 'all_threads' function. Adjust get_last_target_status call. (prepare_one_step): Adjust set_running call. (signal_command): Use user_visible_resume_target. Compare thread pointers instead of inferior_ptid. (info_program_command): Adjust to pass down target. (attach_command): Mark target's 'thread_executing' flag. (stop_current_target_threads_ns): New, factored out from ... (interrupt_target_1): ... this. Switch inferior before making target calls. * inferior-iter.h (struct all_inferiors_iterator, struct all_inferiors_range) (struct all_inferiors_safe_range) (struct all_non_exited_inferiors_range): Filter on process_stratum_target too. Remove explicit. * inferior.c (inferior::inferior): Push dummy target on target stack. (find_inferior_pid, find_inferior_ptid, number_of_live_inferiors): Add process_stratum_target parameter, and pass it down. (have_live_inferiors): Adjust. (switch_to_inferior_and_push_target): New. (add_inferior_command, clone_inferior_command): Handle "-no-connection" parameter. Use switch_to_inferior_and_push_target. (_initialize_inferior): Mention "-no-connection" option in the help of "add-inferior" and "clone-inferior" commands. * inferior.h: Include "process-stratum-target.h". (interrupt_target_1): Use bool. (struct inferior) <push_target, unpush_target, target_is_pushed, find_target_beneath, top_target, process_target, target_at, m_stack>: New. (discard_all_inferiors): Delete. (find_inferior_pid, find_inferior_ptid, number_of_live_inferiors) (all_inferiors, all_non_exited_inferiors): Add process_stratum_target parameter. * infrun.c: Include "gdb_select.h" and <unordered_map>. (target_last_proc_target): New global. (follow_fork_inferior): Push target on new inferior. Pass target to add_thread_silent. Call exec_on_vfork. Handle target's reference count. (follow_fork): Adjust get_last_target_status call. Also consider target. (follow_exec): Push target on new inferior. (struct execution_control_state) <target>: New field. (user_visible_resume_target): New. (do_target_resume): Call target_async. (resume_1): Set target's threads_executing flag. Consider resume target. (commit_resume_all_targets): New. (proceed): Also consider resume target. Skip threads of inferiors with no execution. Commit resumtion in all targets. (start_remote): Pass current inferior to wait_for_inferior. (infrun_thread_stop_requested): Consider target as well. Pass thread_info pointer to clear_inline_frame_state instead of ptid. (infrun_thread_thread_exit): Consider target as well. (random_pending_event_thread): New inferior parameter. Use it. (do_target_wait): Rename to ... (do_target_wait_1): ... this. Add inferior parameter, and pass it down. (threads_are_resumed_pending_p, do_target_wait): New. (prepare_for_detach): Adjust calls. (wait_for_inferior): New inferior parameter. Handle it. Use do_target_wait_1 instead of do_target_wait. (fetch_inferior_event): Adjust. Switch to representative inferior. Pass target down. (set_last_target_status): Add process_stratum_target parameter. Save target in global. (get_last_target_status): Add process_stratum_target parameter and handle it. (nullify_last_target_wait_ptid): Clear 'target_last_proc_target'. (context_switch): Check inferior_ptid == null_ptid before calling inferior_thread(). (get_inferior_stop_soon): Pass down target. (wait_one): Rename to ... (poll_one_curr_target): ... this. (struct wait_one_event): New. (wait_one): New. (stop_all_threads): Adjust. (handle_no_resumed, handle_inferior_event): Adjust to consider the event's target. (switch_back_to_stepped_thread): Also consider target. (print_stop_event): Update. (normal_stop): Update. Also consider the resume target. * infrun.h (wait_for_inferior): Remove declaration. (user_visible_resume_target): New declaration. (get_last_target_status, set_last_target_status): New process_stratum_target parameter. * inline-frame.c (clear_inline_frame_state(ptid_t)): Add process_stratum_target parameter, and use it. (clear_inline_frame_state (thread_info*)): New. * inline-frame.c (clear_inline_frame_state(ptid_t)): Add process_stratum_target parameter. (clear_inline_frame_state (thread_info*)): Declare. * linux-fork.c (delete_checkpoint_command): Pass target down to find_thread_ptid. (checkpoint_command): Adjust. * linux-nat.c (linux_nat_target::follow_fork): Switch to thread instead of just tweaking inferior_ptid. (linux_nat_switch_fork): Pass target down to thread_change_ptid. (exit_lwp): Pass target down to find_thread_ptid. (attach_proc_task_lwp_callback): Pass target down to add_thread/set_running/set_executing. (linux_nat_target::attach): Pass target down to thread_change_ptid. (get_detach_signal): Pass target down to find_thread_ptid. Consider last target status's target. (linux_resume_one_lwp_throw, resume_lwp) (linux_handle_syscall_trap, linux_handle_extended_wait, wait_lwp) (stop_wait_callback, save_stop_reason, linux_nat_filter_event) (linux_nat_wait_1, resume_stopped_resumed_lwps): Pass target down. (linux_nat_target::async_wait_fd): New. (linux_nat_stop_lwp, linux_nat_target::thread_address_space): Pass target down. * linux-nat.h (linux_nat_target::async_wait_fd): Declare. * linux-tdep.c (get_thread_arch_regcache): Pass target down. * linux-thread-db.c (struct thread_db_info::process_target): New field. (add_thread_db_info): Save target. (get_thread_db_info): New process_stratum_target parameter. Also match target. (delete_thread_db_info): New process_stratum_target parameter. Also match target. (thread_from_lwp): Adjust to pass down target. (thread_db_notice_clone): Pass down target. (check_thread_db_callback): Pass down target. (try_thread_db_load_1): Always push the thread_db target. (try_thread_db_load, record_thread): Pass target down. (thread_db_target::detach): Pass target down. Always unpush the thread_db target. (thread_db_target::wait, thread_db_target::mourn_inferior): Pass target down. Always unpush the thread_db target. (find_new_threads_callback, thread_db_find_new_threads_2) (thread_db_target::update_thread_list): Pass target down. (thread_db_target::pid_to_str): Pass current inferior down. (thread_db_target::get_thread_local_address): Pass target down. (thread_db_target::resume, maintenance_check_libthread_db): Pass target down. * nto-procfs.c (nto_procfs_target::update_thread_list): Adjust. * procfs.c (procfs_target::procfs_init_inferior): Declare. (proc_set_current_signal, do_attach, procfs_target::wait): Adjust. (procfs_init_inferior): Rename to ... (procfs_target::procfs_init_inferior): ... this and adjust. (procfs_target::create_inferior, procfs_notice_thread) (procfs_do_thread_registers): Adjust. * ppc-fbsd-tdep.c: Include "inferior.h". (ppcfbsd_get_thread_local_address): Pass down target. * proc-service.c (ps_xfer_memory): Switch current inferior and program space as well. (get_ps_regcache): Pass target down. * process-stratum-target.c (process_stratum_target::thread_address_space) (process_stratum_target::thread_architecture): Pass target down. * process-stratum-target.h (process_stratum_target::threads_executing): New field. (as_process_stratum_target): New. * ravenscar-thread.c (ravenscar_thread_target::update_inferior_ptid): Pass target down. (ravenscar_thread_target::wait, ravenscar_add_thread): Pass target down. * record-btrace.c (record_btrace_target::info_record): Adjust. (record_btrace_target::record_method) (record_btrace_target::record_is_replaying) (record_btrace_target::fetch_registers) (get_thread_current_frame_id, record_btrace_target::resume) (record_btrace_target::wait, record_btrace_target::stop): Pass target down. * record-full.c (record_full_wait_1): Switch to event thread. Pass target down. * regcache.c (regcache::regcache) (get_thread_arch_aspace_regcache, get_thread_arch_regcache): Add process_stratum_target parameter and handle it. (current_thread_target): New global. (get_thread_regcache): Add process_stratum_target parameter and handle it. Switch inferior before calling target method. (get_thread_regcache): Pass target down. (get_thread_regcache_for_ptid): Pass target down. (registers_changed_ptid): Add process_stratum_target parameter and handle it. (registers_changed_thread, registers_changed): Pass target down. (test_get_thread_arch_aspace_regcache): New. (current_regcache_test): Define a couple local test_target_ops instances and use them for testing. (readwrite_regcache): Pass process_stratum_target parameter. (cooked_read_test, cooked_write_test): Pass mock_target down. * regcache.h (get_thread_regcache, get_thread_arch_regcache) (get_thread_arch_aspace_regcache): Add process_stratum_target parameter. (regcache::target): New method. (regcache::regcache, regcache::get_thread_arch_aspace_regcache) (regcache::registers_changed_ptid): Add process_stratum_target parameter. (regcache::m_target): New field. (registers_changed_ptid): Add process_stratum_target parameter. * remote.c (remote_state::supports_vCont_probed): New field. (remote_target::async_wait_fd): New method. (remote_unpush_and_throw): Add remote_target parameter. (get_current_remote_target): Adjust. (remote_target::remote_add_inferior): Push target. (remote_target::remote_add_thread) (remote_target::remote_notice_new_inferior) (get_remote_thread_info): Pass target down. (remote_target::update_thread_list): Skip threads of inferiors bound to other targets. (remote_target::close): Don't discard inferiors. (remote_target::add_current_inferior_and_thread) (remote_target::process_initial_stop_replies) (remote_target::start_remote) (remote_target::remote_serial_quit_handler): Pass down target. (remote_target::remote_unpush_target): New remote_target parameter. Unpush the target from all inferiors. (remote_target::remote_unpush_and_throw): New remote_target parameter. Pass it down. (remote_target::open_1): Check whether the current inferior has execution instead of checking whether any inferior is live. Pass target down. (remote_target::remote_detach_1): Pass down target. Use remote_unpush_target. (extended_remote_target::attach): Pass down target. (remote_target::remote_vcont_probe): Set supports_vCont_probed. (remote_target::append_resumption): Pass down target. (remote_target::append_pending_thread_resumptions) (remote_target::remote_resume_with_hc, remote_target::resume) (remote_target::commit_resume): Pass down target. (remote_target::remote_stop_ns): Check supports_vCont_probed. (remote_target::interrupt_query) (remote_target::remove_new_fork_children) (remote_target::check_pending_events_prevent_wildcard_vcont) (remote_target::remote_parse_stop_reply) (remote_target::process_stop_reply): Pass down target. (first_remote_resumed_thread): New remote_target parameter. Pass it down. (remote_target::wait_as): Pass down target. (unpush_and_perror): New remote_target parameter. Pass it down. (remote_target::readchar, remote_target::remote_serial_write) (remote_target::getpkt_or_notif_sane_1) (remote_target::kill_new_fork_children, remote_target::kill): Pass down target. (remote_target::mourn_inferior): Pass down target. Use remote_unpush_target. (remote_target::core_of_thread) (remote_target::remote_btrace_maybe_reopen): Pass down target. (remote_target::pid_to_exec_file) (remote_target::thread_handle_to_thread_info): Pass down target. (remote_target::async_wait_fd): New. * riscv-fbsd-tdep.c: Include "inferior.h". (riscv_fbsd_get_thread_local_address): Pass down target. * sol2-tdep.c (sol2_core_pid_to_str): Pass down target. * sol-thread.c (sol_thread_target::wait, ps_lgetregs, ps_lsetregs) (ps_lgetfpregs, ps_lsetfpregs, sol_update_thread_list_callback): Adjust. * solib-spu.c (spu_skip_standalone_loader): Pass down target. * solib-svr4.c (enable_break): Pass down target. * spu-multiarch.c (parse_spufs_run): Pass down target. * spu-tdep.c (spu2ppu_sniffer): Pass down target. * target-delegates.c: Regenerate. * target.c (g_target_stack): Delete. (current_top_target): Return the current inferior's top target. (target_has_execution_1): Refer to the passed-in inferior's top target. (target_supports_terminal_ours): Check whether the initial inferior was already created. (decref_target): New. (target_stack::push): Incref/decref the target. (push_target, push_target, unpush_target): Adjust. (target_stack::unpush): Defref target. (target_is_pushed): Return bool. Adjust to refer to the current inferior's target stack. (dispose_inferior): Delete, and inline parts ... (target_preopen): ... here. Only dispose of the current inferior. (target_detach): Hold strong target reference while detaching. Pass target down. (target_thread_name): Add assertion. (target_resume): Pass down target. (target_ops::beneath, find_target_at): Adjust to refer to the current inferior's target stack. (get_dummy_target): New. (target_pass_ctrlc): Pass the Ctrl-C to the first inferior that has a thread running. (initialize_targets): Rename to ... (_initialize_target): ... this. * target.h: Include "gdbsupport/refcounted-object.h". (struct target_ops): Inherit refcounted_object. (target_ops::shortname, target_ops::longname): Make const. (target_ops::async_wait_fd): New method. (decref_target): Declare. (struct target_ops_ref_policy): New. (target_ops_ref): New typedef. (get_dummy_target): Declare function. (target_is_pushed): Return bool. * thread-iter.c (all_matching_threads_iterator::m_inf_matches) (all_matching_threads_iterator::all_matching_threads_iterator): Handle filter target. * thread-iter.h (struct all_matching_threads_iterator, struct all_matching_threads_range, class all_non_exited_threads_range): Filter by target too. Remove explicit. * thread.c (threads_executing): Delete. (inferior_thread): Pass down current inferior. (clear_thread_inferior_resources): Pass down thread pointer instead of ptid_t. (add_thread_silent, add_thread_with_info, add_thread): Add process_stratum_target parameter. Use it for thread and inferior searches. (is_current_thread): New. (thread_info::deletable): Use it. (find_thread_ptid, thread_count, in_thread_list) (thread_change_ptid, set_resumed, set_running): New process_stratum_target parameter. Pass it down. (set_executing): New process_stratum_target parameter. Pass it down. Adjust reference to 'threads_executing'. (threads_are_executing): New process_stratum_target parameter. Adjust reference to 'threads_executing'. (set_stop_requested, finish_thread_state): New process_stratum_target parameter. Pass it down. (switch_to_thread): Also match inferior. (switch_to_thread): New process_stratum_target parameter. Pass it down. (update_threads_executing): Reimplement. * top.c (quit_force): Pop targets from all inferior. (gdb_init): Don't call initialize_targets. * windows-nat.c (windows_nat_target) <get_windows_debug_event>: Declare. (windows_add_thread, windows_delete_thread): Adjust. (get_windows_debug_event): Rename to ... (windows_nat_target::get_windows_debug_event): ... this. Adjust. * tracefile-tfile.c (tfile_target_open): Pass down target. * gdbsupport/common-gdbthread.h (struct process_stratum_target): Forward declare. (switch_to_thread): Add process_stratum_target parameter. * mi/mi-interp.c (mi_on_resume_1): Add process_stratum_target parameter. Use it. (mi_on_resume): Pass target down. * nat/fork-inferior.c (startup_inferior): Add process_stratum_target parameter. Pass it down. * nat/fork-inferior.h (startup_inferior): Add process_stratum_target parameter. * python/py-threadevent.c (py_get_event_thread): Pass target down. gdb/gdbserver/ChangeLog: 2020-01-10 Pedro Alves <palves@redhat.com> * fork-child.c (post_fork_inferior): Pass target down to startup_inferior. * inferiors.c (switch_to_thread): Add process_stratum_target parameter. * lynx-low.c (lynx_target_ops): Now a process_stratum_target. * nto-low.c (nto_target_ops): Now a process_stratum_target. * linux-low.c (linux_target_ops): Now a process_stratum_target. * remote-utils.c (prepare_resume_reply): Pass the target to switch_to_thread. * target.c (the_target): Now a process_stratum_target. (done_accessing_memory): Pass the target to switch_to_thread. (set_target_ops): Ajust to use process_stratum_target. * target.h (struct target_ops): Rename to ... (struct process_stratum_target): ... this. (the_target, set_target_ops): Adjust. (prepare_to_access_memory): Adjust comment. * win32-low.c (child_xfer_memory): Adjust to use process_stratum_target. (win32_target_ops): Now a process_stratum_target.
This commit is contained in:
parent
75c6c844d9
commit
5b6d1e4fa4
419
gdb/ChangeLog
419
gdb/ChangeLog
@ -1,3 +1,422 @@
|
||||
2020-01-10 Pedro Alves <palves@redhat.com>
|
||||
John Baldwin <jhb@FreeBSD.org>
|
||||
|
||||
* aarch64-linux-nat.c
|
||||
(aarch64_linux_nat_target::thread_architecture): Adjust.
|
||||
* ada-tasks.c (print_ada_task_info): Adjust find_thread_ptid call.
|
||||
(task_command_1): Likewise.
|
||||
* aix-thread.c (sync_threadlists, aix_thread_target::resume)
|
||||
(aix_thread_target::wait, aix_thread_target::fetch_registers)
|
||||
(aix_thread_target::store_registers)
|
||||
(aix_thread_target::thread_alive): Adjust.
|
||||
* amd64-fbsd-tdep.c: Include "inferior.h".
|
||||
(amd64fbsd_get_thread_local_address): Pass down target.
|
||||
* amd64-linux-nat.c (ps_get_thread_area): Use ps_prochandle
|
||||
thread's gdbarch instead of target_gdbarch.
|
||||
* break-catch-sig.c (signal_catchpoint_print_it): Adjust call to
|
||||
get_last_target_status.
|
||||
* break-catch-syscall.c (print_it_catch_syscall): Likewise.
|
||||
* breakpoint.c (breakpoints_should_be_inserted_now): Consider all
|
||||
inferiors.
|
||||
(update_inserted_breakpoint_locations): Skip if inferiors with no
|
||||
execution.
|
||||
(update_global_location_list): When handling moribund locations,
|
||||
find representative inferior for location's pspace, and use thread
|
||||
count of its process_stratum target.
|
||||
* bsd-kvm.c (bsd_kvm_target_open): Pass target down.
|
||||
* bsd-uthread.c (bsd_uthread_target::wait): Use
|
||||
as_process_stratum_target and adjust thread_change_ptid and
|
||||
add_thread calls.
|
||||
(bsd_uthread_target::update_thread_list): Use
|
||||
as_process_stratum_target and adjust find_thread_ptid,
|
||||
thread_change_ptid and add_thread calls.
|
||||
* btrace.c (maint_btrace_packet_history_cmd): Adjust
|
||||
find_thread_ptid call.
|
||||
* corelow.c (add_to_thread_list): Adjust add_thread call.
|
||||
(core_target_open): Adjust add_thread_silent and thread_count
|
||||
calls.
|
||||
(core_target::pid_to_str): Adjust find_inferior_ptid call.
|
||||
* ctf.c (ctf_target_open): Adjust add_thread_silent call.
|
||||
* event-top.c (async_disconnect): Pop targets from all inferiors.
|
||||
* exec.c (add_target_sections): Push exec target on all inferiors
|
||||
sharing the program space.
|
||||
(remove_target_sections): Remove the exec target from all
|
||||
inferiors sharing the program space.
|
||||
(exec_on_vfork): New.
|
||||
* exec.h (exec_on_vfork): Declare.
|
||||
* fbsd-nat.c (fbsd_add_threads): Add fbsd_nat_target parameter.
|
||||
Pass it down.
|
||||
(fbsd_nat_target::update_thread_list): Adjust.
|
||||
(fbsd_nat_target::resume): Adjust.
|
||||
(fbsd_handle_debug_trap): Add fbsd_nat_target parameter. Pass it
|
||||
down.
|
||||
(fbsd_nat_target::wait, fbsd_nat_target::post_attach): Adjust.
|
||||
* fbsd-tdep.c (fbsd_corefile_thread): Adjust
|
||||
get_thread_arch_regcache call.
|
||||
* fork-child.c (gdb_startup_inferior): Pass target down to
|
||||
startup_inferior and set_executing.
|
||||
* gdbthread.h (struct process_stratum_target): Forward declare.
|
||||
(add_thread, add_thread_silent, add_thread_with_info)
|
||||
(in_thread_list): Add process_stratum_target parameter.
|
||||
(find_thread_ptid(inferior*, ptid_t)): New overload.
|
||||
(find_thread_ptid, thread_change_ptid): Add process_stratum_target
|
||||
parameter.
|
||||
(all_threads()): Delete overload.
|
||||
(all_threads, all_non_exited_threads): Add process_stratum_target
|
||||
parameter.
|
||||
(all_threads_safe): Use brace initialization.
|
||||
(thread_count): Add process_stratum_target parameter.
|
||||
(set_resumed, set_running, set_stop_requested, set_executing)
|
||||
(threads_are_executing, finish_thread_state): Add
|
||||
process_stratum_target parameter.
|
||||
(switch_to_thread): Use is_current_thread.
|
||||
* i386-fbsd-tdep.c: Include "inferior.h".
|
||||
(i386fbsd_get_thread_local_address): Pass down target.
|
||||
* i386-linux-nat.c (i386_linux_nat_target::low_resume): Adjust.
|
||||
* inf-child.c (inf_child_target::maybe_unpush_target): Remove
|
||||
have_inferiors check.
|
||||
* inf-ptrace.c (inf_ptrace_target::create_inferior)
|
||||
(inf_ptrace_target::attach): Adjust.
|
||||
* infcall.c (run_inferior_call): Adjust.
|
||||
* infcmd.c (run_command_1): Pass target to
|
||||
scoped_finish_thread_state.
|
||||
(proceed_thread_callback): Skip inferiors with no execution.
|
||||
(continue_command): Rename 'all_threads' local to avoid hiding
|
||||
'all_threads' function. Adjust get_last_target_status call.
|
||||
(prepare_one_step): Adjust set_running call.
|
||||
(signal_command): Use user_visible_resume_target. Compare thread
|
||||
pointers instead of inferior_ptid.
|
||||
(info_program_command): Adjust to pass down target.
|
||||
(attach_command): Mark target's 'thread_executing' flag.
|
||||
(stop_current_target_threads_ns): New, factored out from ...
|
||||
(interrupt_target_1): ... this. Switch inferior before making
|
||||
target calls.
|
||||
* inferior-iter.h
|
||||
(struct all_inferiors_iterator, struct all_inferiors_range)
|
||||
(struct all_inferiors_safe_range)
|
||||
(struct all_non_exited_inferiors_range): Filter on
|
||||
process_stratum_target too. Remove explicit.
|
||||
* inferior.c (inferior::inferior): Push dummy target on target
|
||||
stack.
|
||||
(find_inferior_pid, find_inferior_ptid, number_of_live_inferiors):
|
||||
Add process_stratum_target parameter, and pass it down.
|
||||
(have_live_inferiors): Adjust.
|
||||
(switch_to_inferior_and_push_target): New.
|
||||
(add_inferior_command, clone_inferior_command): Handle
|
||||
"-no-connection" parameter. Use
|
||||
switch_to_inferior_and_push_target.
|
||||
(_initialize_inferior): Mention "-no-connection" option in
|
||||
the help of "add-inferior" and "clone-inferior" commands.
|
||||
* inferior.h: Include "process-stratum-target.h".
|
||||
(interrupt_target_1): Use bool.
|
||||
(struct inferior) <push_target, unpush_target, target_is_pushed,
|
||||
find_target_beneath, top_target, process_target, target_at,
|
||||
m_stack>: New.
|
||||
(discard_all_inferiors): Delete.
|
||||
(find_inferior_pid, find_inferior_ptid, number_of_live_inferiors)
|
||||
(all_inferiors, all_non_exited_inferiors): Add
|
||||
process_stratum_target parameter.
|
||||
* infrun.c: Include "gdb_select.h" and <unordered_map>.
|
||||
(target_last_proc_target): New global.
|
||||
(follow_fork_inferior): Push target on new inferior. Pass target
|
||||
to add_thread_silent. Call exec_on_vfork. Handle target's
|
||||
reference count.
|
||||
(follow_fork): Adjust get_last_target_status call. Also consider
|
||||
target.
|
||||
(follow_exec): Push target on new inferior.
|
||||
(struct execution_control_state) <target>: New field.
|
||||
(user_visible_resume_target): New.
|
||||
(do_target_resume): Call target_async.
|
||||
(resume_1): Set target's threads_executing flag. Consider resume
|
||||
target.
|
||||
(commit_resume_all_targets): New.
|
||||
(proceed): Also consider resume target. Skip threads of inferiors
|
||||
with no execution. Commit resumtion in all targets.
|
||||
(start_remote): Pass current inferior to wait_for_inferior.
|
||||
(infrun_thread_stop_requested): Consider target as well. Pass
|
||||
thread_info pointer to clear_inline_frame_state instead of ptid.
|
||||
(infrun_thread_thread_exit): Consider target as well.
|
||||
(random_pending_event_thread): New inferior parameter. Use it.
|
||||
(do_target_wait): Rename to ...
|
||||
(do_target_wait_1): ... this. Add inferior parameter, and pass it
|
||||
down.
|
||||
(threads_are_resumed_pending_p, do_target_wait): New.
|
||||
(prepare_for_detach): Adjust calls.
|
||||
(wait_for_inferior): New inferior parameter. Handle it. Use
|
||||
do_target_wait_1 instead of do_target_wait.
|
||||
(fetch_inferior_event): Adjust. Switch to representative
|
||||
inferior. Pass target down.
|
||||
(set_last_target_status): Add process_stratum_target parameter.
|
||||
Save target in global.
|
||||
(get_last_target_status): Add process_stratum_target parameter and
|
||||
handle it.
|
||||
(nullify_last_target_wait_ptid): Clear 'target_last_proc_target'.
|
||||
(context_switch): Check inferior_ptid == null_ptid before calling
|
||||
inferior_thread().
|
||||
(get_inferior_stop_soon): Pass down target.
|
||||
(wait_one): Rename to ...
|
||||
(poll_one_curr_target): ... this.
|
||||
(struct wait_one_event): New.
|
||||
(wait_one): New.
|
||||
(stop_all_threads): Adjust.
|
||||
(handle_no_resumed, handle_inferior_event): Adjust to consider the
|
||||
event's target.
|
||||
(switch_back_to_stepped_thread): Also consider target.
|
||||
(print_stop_event): Update.
|
||||
(normal_stop): Update. Also consider the resume target.
|
||||
* infrun.h (wait_for_inferior): Remove declaration.
|
||||
(user_visible_resume_target): New declaration.
|
||||
(get_last_target_status, set_last_target_status): New
|
||||
process_stratum_target parameter.
|
||||
* inline-frame.c (clear_inline_frame_state(ptid_t)): Add
|
||||
process_stratum_target parameter, and use it.
|
||||
(clear_inline_frame_state (thread_info*)): New.
|
||||
* inline-frame.c (clear_inline_frame_state(ptid_t)): Add
|
||||
process_stratum_target parameter.
|
||||
(clear_inline_frame_state (thread_info*)): Declare.
|
||||
* linux-fork.c (delete_checkpoint_command): Pass target down to
|
||||
find_thread_ptid.
|
||||
(checkpoint_command): Adjust.
|
||||
* linux-nat.c (linux_nat_target::follow_fork): Switch to thread
|
||||
instead of just tweaking inferior_ptid.
|
||||
(linux_nat_switch_fork): Pass target down to thread_change_ptid.
|
||||
(exit_lwp): Pass target down to find_thread_ptid.
|
||||
(attach_proc_task_lwp_callback): Pass target down to
|
||||
add_thread/set_running/set_executing.
|
||||
(linux_nat_target::attach): Pass target down to
|
||||
thread_change_ptid.
|
||||
(get_detach_signal): Pass target down to find_thread_ptid.
|
||||
Consider last target status's target.
|
||||
(linux_resume_one_lwp_throw, resume_lwp)
|
||||
(linux_handle_syscall_trap, linux_handle_extended_wait, wait_lwp)
|
||||
(stop_wait_callback, save_stop_reason, linux_nat_filter_event)
|
||||
(linux_nat_wait_1, resume_stopped_resumed_lwps): Pass target down.
|
||||
(linux_nat_target::async_wait_fd): New.
|
||||
(linux_nat_stop_lwp, linux_nat_target::thread_address_space): Pass
|
||||
target down.
|
||||
* linux-nat.h (linux_nat_target::async_wait_fd): Declare.
|
||||
* linux-tdep.c (get_thread_arch_regcache): Pass target down.
|
||||
* linux-thread-db.c (struct thread_db_info::process_target): New
|
||||
field.
|
||||
(add_thread_db_info): Save target.
|
||||
(get_thread_db_info): New process_stratum_target parameter. Also
|
||||
match target.
|
||||
(delete_thread_db_info): New process_stratum_target parameter.
|
||||
Also match target.
|
||||
(thread_from_lwp): Adjust to pass down target.
|
||||
(thread_db_notice_clone): Pass down target.
|
||||
(check_thread_db_callback): Pass down target.
|
||||
(try_thread_db_load_1): Always push the thread_db target.
|
||||
(try_thread_db_load, record_thread): Pass target down.
|
||||
(thread_db_target::detach): Pass target down. Always unpush the
|
||||
thread_db target.
|
||||
(thread_db_target::wait, thread_db_target::mourn_inferior): Pass
|
||||
target down. Always unpush the thread_db target.
|
||||
(find_new_threads_callback, thread_db_find_new_threads_2)
|
||||
(thread_db_target::update_thread_list): Pass target down.
|
||||
(thread_db_target::pid_to_str): Pass current inferior down.
|
||||
(thread_db_target::get_thread_local_address): Pass target down.
|
||||
(thread_db_target::resume, maintenance_check_libthread_db): Pass
|
||||
target down.
|
||||
* nto-procfs.c (nto_procfs_target::update_thread_list): Adjust.
|
||||
* procfs.c (procfs_target::procfs_init_inferior): Declare.
|
||||
(proc_set_current_signal, do_attach, procfs_target::wait): Adjust.
|
||||
(procfs_init_inferior): Rename to ...
|
||||
(procfs_target::procfs_init_inferior): ... this and adjust.
|
||||
(procfs_target::create_inferior, procfs_notice_thread)
|
||||
(procfs_do_thread_registers): Adjust.
|
||||
* ppc-fbsd-tdep.c: Include "inferior.h".
|
||||
(ppcfbsd_get_thread_local_address): Pass down target.
|
||||
* proc-service.c (ps_xfer_memory): Switch current inferior and
|
||||
program space as well.
|
||||
(get_ps_regcache): Pass target down.
|
||||
* process-stratum-target.c
|
||||
(process_stratum_target::thread_address_space)
|
||||
(process_stratum_target::thread_architecture): Pass target down.
|
||||
* process-stratum-target.h
|
||||
(process_stratum_target::threads_executing): New field.
|
||||
(as_process_stratum_target): New.
|
||||
* ravenscar-thread.c
|
||||
(ravenscar_thread_target::update_inferior_ptid): Pass target down.
|
||||
(ravenscar_thread_target::wait, ravenscar_add_thread): Pass target
|
||||
down.
|
||||
* record-btrace.c (record_btrace_target::info_record): Adjust.
|
||||
(record_btrace_target::record_method)
|
||||
(record_btrace_target::record_is_replaying)
|
||||
(record_btrace_target::fetch_registers)
|
||||
(get_thread_current_frame_id, record_btrace_target::resume)
|
||||
(record_btrace_target::wait, record_btrace_target::stop): Pass
|
||||
target down.
|
||||
* record-full.c (record_full_wait_1): Switch to event thread.
|
||||
Pass target down.
|
||||
* regcache.c (regcache::regcache)
|
||||
(get_thread_arch_aspace_regcache, get_thread_arch_regcache): Add
|
||||
process_stratum_target parameter and handle it.
|
||||
(current_thread_target): New global.
|
||||
(get_thread_regcache): Add process_stratum_target parameter and
|
||||
handle it. Switch inferior before calling target method.
|
||||
(get_thread_regcache): Pass target down.
|
||||
(get_thread_regcache_for_ptid): Pass target down.
|
||||
(registers_changed_ptid): Add process_stratum_target parameter and
|
||||
handle it.
|
||||
(registers_changed_thread, registers_changed): Pass target down.
|
||||
(test_get_thread_arch_aspace_regcache): New.
|
||||
(current_regcache_test): Define a couple local test_target_ops
|
||||
instances and use them for testing.
|
||||
(readwrite_regcache): Pass process_stratum_target parameter.
|
||||
(cooked_read_test, cooked_write_test): Pass mock_target down.
|
||||
* regcache.h (get_thread_regcache, get_thread_arch_regcache)
|
||||
(get_thread_arch_aspace_regcache): Add process_stratum_target
|
||||
parameter.
|
||||
(regcache::target): New method.
|
||||
(regcache::regcache, regcache::get_thread_arch_aspace_regcache)
|
||||
(regcache::registers_changed_ptid): Add process_stratum_target
|
||||
parameter.
|
||||
(regcache::m_target): New field.
|
||||
(registers_changed_ptid): Add process_stratum_target parameter.
|
||||
* remote.c (remote_state::supports_vCont_probed): New field.
|
||||
(remote_target::async_wait_fd): New method.
|
||||
(remote_unpush_and_throw): Add remote_target parameter.
|
||||
(get_current_remote_target): Adjust.
|
||||
(remote_target::remote_add_inferior): Push target.
|
||||
(remote_target::remote_add_thread)
|
||||
(remote_target::remote_notice_new_inferior)
|
||||
(get_remote_thread_info): Pass target down.
|
||||
(remote_target::update_thread_list): Skip threads of inferiors
|
||||
bound to other targets. (remote_target::close): Don't discard
|
||||
inferiors. (remote_target::add_current_inferior_and_thread)
|
||||
(remote_target::process_initial_stop_replies)
|
||||
(remote_target::start_remote)
|
||||
(remote_target::remote_serial_quit_handler): Pass down target.
|
||||
(remote_target::remote_unpush_target): New remote_target
|
||||
parameter. Unpush the target from all inferiors.
|
||||
(remote_target::remote_unpush_and_throw): New remote_target
|
||||
parameter. Pass it down.
|
||||
(remote_target::open_1): Check whether the current inferior has
|
||||
execution instead of checking whether any inferior is live. Pass
|
||||
target down.
|
||||
(remote_target::remote_detach_1): Pass down target. Use
|
||||
remote_unpush_target.
|
||||
(extended_remote_target::attach): Pass down target.
|
||||
(remote_target::remote_vcont_probe): Set supports_vCont_probed.
|
||||
(remote_target::append_resumption): Pass down target.
|
||||
(remote_target::append_pending_thread_resumptions)
|
||||
(remote_target::remote_resume_with_hc, remote_target::resume)
|
||||
(remote_target::commit_resume): Pass down target.
|
||||
(remote_target::remote_stop_ns): Check supports_vCont_probed.
|
||||
(remote_target::interrupt_query)
|
||||
(remote_target::remove_new_fork_children)
|
||||
(remote_target::check_pending_events_prevent_wildcard_vcont)
|
||||
(remote_target::remote_parse_stop_reply)
|
||||
(remote_target::process_stop_reply): Pass down target.
|
||||
(first_remote_resumed_thread): New remote_target parameter. Pass
|
||||
it down.
|
||||
(remote_target::wait_as): Pass down target.
|
||||
(unpush_and_perror): New remote_target parameter. Pass it down.
|
||||
(remote_target::readchar, remote_target::remote_serial_write)
|
||||
(remote_target::getpkt_or_notif_sane_1)
|
||||
(remote_target::kill_new_fork_children, remote_target::kill): Pass
|
||||
down target.
|
||||
(remote_target::mourn_inferior): Pass down target. Use
|
||||
remote_unpush_target.
|
||||
(remote_target::core_of_thread)
|
||||
(remote_target::remote_btrace_maybe_reopen): Pass down target.
|
||||
(remote_target::pid_to_exec_file)
|
||||
(remote_target::thread_handle_to_thread_info): Pass down target.
|
||||
(remote_target::async_wait_fd): New.
|
||||
* riscv-fbsd-tdep.c: Include "inferior.h".
|
||||
(riscv_fbsd_get_thread_local_address): Pass down target.
|
||||
* sol2-tdep.c (sol2_core_pid_to_str): Pass down target.
|
||||
* sol-thread.c (sol_thread_target::wait, ps_lgetregs, ps_lsetregs)
|
||||
(ps_lgetfpregs, ps_lsetfpregs, sol_update_thread_list_callback):
|
||||
Adjust.
|
||||
* solib-spu.c (spu_skip_standalone_loader): Pass down target.
|
||||
* solib-svr4.c (enable_break): Pass down target.
|
||||
* spu-multiarch.c (parse_spufs_run): Pass down target.
|
||||
* spu-tdep.c (spu2ppu_sniffer): Pass down target.
|
||||
* target-delegates.c: Regenerate.
|
||||
* target.c (g_target_stack): Delete.
|
||||
(current_top_target): Return the current inferior's top target.
|
||||
(target_has_execution_1): Refer to the passed-in inferior's top
|
||||
target.
|
||||
(target_supports_terminal_ours): Check whether the initial
|
||||
inferior was already created.
|
||||
(decref_target): New.
|
||||
(target_stack::push): Incref/decref the target.
|
||||
(push_target, push_target, unpush_target): Adjust.
|
||||
(target_stack::unpush): Defref target.
|
||||
(target_is_pushed): Return bool. Adjust to refer to the current
|
||||
inferior's target stack.
|
||||
(dispose_inferior): Delete, and inline parts ...
|
||||
(target_preopen): ... here. Only dispose of the current inferior.
|
||||
(target_detach): Hold strong target reference while detaching.
|
||||
Pass target down.
|
||||
(target_thread_name): Add assertion.
|
||||
(target_resume): Pass down target.
|
||||
(target_ops::beneath, find_target_at): Adjust to refer to the
|
||||
current inferior's target stack.
|
||||
(get_dummy_target): New.
|
||||
(target_pass_ctrlc): Pass the Ctrl-C to the first inferior that
|
||||
has a thread running.
|
||||
(initialize_targets): Rename to ...
|
||||
(_initialize_target): ... this.
|
||||
* target.h: Include "gdbsupport/refcounted-object.h".
|
||||
(struct target_ops): Inherit refcounted_object.
|
||||
(target_ops::shortname, target_ops::longname): Make const.
|
||||
(target_ops::async_wait_fd): New method.
|
||||
(decref_target): Declare.
|
||||
(struct target_ops_ref_policy): New.
|
||||
(target_ops_ref): New typedef.
|
||||
(get_dummy_target): Declare function.
|
||||
(target_is_pushed): Return bool.
|
||||
* thread-iter.c (all_matching_threads_iterator::m_inf_matches)
|
||||
(all_matching_threads_iterator::all_matching_threads_iterator):
|
||||
Handle filter target.
|
||||
* thread-iter.h (struct all_matching_threads_iterator, struct
|
||||
all_matching_threads_range, class all_non_exited_threads_range):
|
||||
Filter by target too. Remove explicit.
|
||||
* thread.c (threads_executing): Delete.
|
||||
(inferior_thread): Pass down current inferior.
|
||||
(clear_thread_inferior_resources): Pass down thread pointer
|
||||
instead of ptid_t.
|
||||
(add_thread_silent, add_thread_with_info, add_thread): Add
|
||||
process_stratum_target parameter. Use it for thread and inferior
|
||||
searches.
|
||||
(is_current_thread): New.
|
||||
(thread_info::deletable): Use it.
|
||||
(find_thread_ptid, thread_count, in_thread_list)
|
||||
(thread_change_ptid, set_resumed, set_running): New
|
||||
process_stratum_target parameter. Pass it down.
|
||||
(set_executing): New process_stratum_target parameter. Pass it
|
||||
down. Adjust reference to 'threads_executing'.
|
||||
(threads_are_executing): New process_stratum_target parameter.
|
||||
Adjust reference to 'threads_executing'.
|
||||
(set_stop_requested, finish_thread_state): New
|
||||
process_stratum_target parameter. Pass it down.
|
||||
(switch_to_thread): Also match inferior.
|
||||
(switch_to_thread): New process_stratum_target parameter. Pass it
|
||||
down.
|
||||
(update_threads_executing): Reimplement.
|
||||
* top.c (quit_force): Pop targets from all inferior.
|
||||
(gdb_init): Don't call initialize_targets.
|
||||
* windows-nat.c (windows_nat_target) <get_windows_debug_event>:
|
||||
Declare.
|
||||
(windows_add_thread, windows_delete_thread): Adjust.
|
||||
(get_windows_debug_event): Rename to ...
|
||||
(windows_nat_target::get_windows_debug_event): ... this. Adjust.
|
||||
* tracefile-tfile.c (tfile_target_open): Pass down target.
|
||||
* gdbsupport/common-gdbthread.h (struct process_stratum_target):
|
||||
Forward declare.
|
||||
(switch_to_thread): Add process_stratum_target parameter.
|
||||
* mi/mi-interp.c (mi_on_resume_1): Add process_stratum_target
|
||||
parameter. Use it.
|
||||
(mi_on_resume): Pass target down.
|
||||
* nat/fork-inferior.c (startup_inferior): Add
|
||||
process_stratum_target parameter. Pass it down.
|
||||
* nat/fork-inferior.h (startup_inferior): Add
|
||||
process_stratum_target parameter.
|
||||
* python/py-threadevent.c (py_get_event_thread): Pass target down.
|
||||
|
||||
2020-01-10 Pedro Alves <palves@redhat.com>
|
||||
|
||||
* remote.c (remote_target::start_remote): Don't set inferior_ptid
|
||||
|
@ -959,7 +959,7 @@ aarch64_linux_nat_target::thread_architecture (ptid_t ptid)
|
||||
|
||||
/* Find the current gdbarch the same way as process_stratum_target. Only
|
||||
return it if the current vector length matches the one in the tdep. */
|
||||
inferior *inf = find_inferior_ptid (ptid);
|
||||
inferior *inf = find_inferior_ptid (this, ptid);
|
||||
gdb_assert (inf != NULL);
|
||||
if (vq == gdbarch_tdep (inf->gdbarch)->vq)
|
||||
return inf->gdbarch;
|
||||
|
@ -1128,7 +1128,7 @@ print_ada_task_info (struct ui_out *uiout,
|
||||
if (uiout->is_mi_like_p ())
|
||||
{
|
||||
thread_info *thread = (ada_task_is_alive (task_info)
|
||||
? find_thread_ptid (task_info->ptid)
|
||||
? find_thread_ptid (inf, task_info->ptid)
|
||||
: nullptr);
|
||||
|
||||
if (thread != NULL)
|
||||
@ -1343,7 +1343,7 @@ task_command_1 (const char *taskno_str, int from_tty, struct inferior *inf)
|
||||
computed if target_get_ada_task_ptid has not been implemented for
|
||||
our target (yet). Rather than cause an assertion error in that case,
|
||||
it's nicer for the user to just refuse to perform the task switch. */
|
||||
thread_info *tp = find_thread_ptid (task_info->ptid);
|
||||
thread_info *tp = find_thread_ptid (inf, task_info->ptid);
|
||||
if (tp == NULL)
|
||||
error (_("Unable to compute thread ID for task %s.\n"
|
||||
"Cannot switch to this task."),
|
||||
|
@ -805,7 +805,11 @@ sync_threadlists (void)
|
||||
priv->pdtid = pbuf[pi].pdtid;
|
||||
priv->tid = pbuf[pi].tid;
|
||||
|
||||
thread = add_thread_with_info (ptid_t (infpid, 0, pbuf[pi].pthid), priv);
|
||||
process_stratum_target *proc_target
|
||||
= current_inferior ()->process_target ();
|
||||
thread = add_thread_with_info (proc_target,
|
||||
ptid_t (infpid, 0, pbuf[pi].pthid),
|
||||
priv);
|
||||
|
||||
pi++;
|
||||
}
|
||||
@ -837,7 +841,9 @@ sync_threadlists (void)
|
||||
}
|
||||
else
|
||||
{
|
||||
thread = add_thread (pptid);
|
||||
process_stratum_target *proc_target
|
||||
= current_inferior ()->process_target ();
|
||||
thread = add_thread (proc_target, pptid);
|
||||
|
||||
aix_thread_info *priv = new aix_thread_info;
|
||||
thread->priv.reset (priv);
|
||||
@ -1043,7 +1049,7 @@ aix_thread_target::resume (ptid_t ptid, int step, enum gdb_signal sig)
|
||||
}
|
||||
else
|
||||
{
|
||||
thread = find_thread_ptid (ptid);
|
||||
thread = find_thread_ptid (current_inferior (), ptid);
|
||||
if (!thread)
|
||||
error (_("aix-thread resume: unknown pthread %ld"),
|
||||
ptid.lwp ());
|
||||
@ -1089,7 +1095,9 @@ aix_thread_target::wait (ptid_t ptid, struct target_waitstatus *status,
|
||||
if (!pd_active && status->kind == TARGET_WAITKIND_STOPPED
|
||||
&& status->value.sig == GDB_SIGNAL_TRAP)
|
||||
{
|
||||
struct regcache *regcache = get_thread_regcache (ptid);
|
||||
process_stratum_target *proc_target
|
||||
= current_inferior ()->process_target ();
|
||||
struct regcache *regcache = get_thread_regcache (proc_target, ptid);
|
||||
struct gdbarch *gdbarch = regcache->arch ();
|
||||
|
||||
if (regcache_read_pc (regcache)
|
||||
@ -1354,7 +1362,7 @@ aix_thread_target::fetch_registers (struct regcache *regcache, int regno)
|
||||
beneath ()->fetch_registers (regcache, regno);
|
||||
else
|
||||
{
|
||||
thread = find_thread_ptid (regcache->ptid ());
|
||||
thread = find_thread_ptid (current_inferior (), regcache->ptid ());
|
||||
aix_thread_info *priv = get_aix_thread_info (thread);
|
||||
tid = priv->tid;
|
||||
|
||||
@ -1692,7 +1700,7 @@ aix_thread_target::store_registers (struct regcache *regcache, int regno)
|
||||
beneath ()->store_registers (regcache, regno);
|
||||
else
|
||||
{
|
||||
thread = find_thread_ptid (regcache->ptid ());
|
||||
thread = find_thread_ptid (current_inferior (), regcache->ptid ());
|
||||
aix_thread_info *priv = get_aix_thread_info (thread);
|
||||
tid = priv->tid;
|
||||
|
||||
@ -1740,7 +1748,9 @@ aix_thread_target::thread_alive (ptid_t ptid)
|
||||
|
||||
/* We update the thread list every time the child stops, so all
|
||||
valid threads should be in the thread list. */
|
||||
return in_thread_list (ptid);
|
||||
process_stratum_target *proc_target
|
||||
= current_inferior ()->process_target ();
|
||||
return in_thread_list (proc_target, ptid);
|
||||
}
|
||||
|
||||
/* Return a printable representation of composite PID for use in
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "amd64-tdep.h"
|
||||
#include "fbsd-tdep.h"
|
||||
#include "solib-svr4.h"
|
||||
#include "inferior.h"
|
||||
|
||||
/* Support for signal handlers. */
|
||||
|
||||
@ -212,7 +213,8 @@ amd64fbsd_get_thread_local_address (struct gdbarch *gdbarch, ptid_t ptid,
|
||||
{
|
||||
struct regcache *regcache;
|
||||
|
||||
regcache = get_thread_arch_regcache (ptid, gdbarch);
|
||||
regcache = get_thread_arch_regcache (current_inferior ()->process_target (),
|
||||
ptid, gdbarch);
|
||||
|
||||
target_fetch_registers (regcache, AMD64_FSBASE_REGNUM);
|
||||
|
||||
|
@ -383,7 +383,7 @@ ps_err_e
|
||||
ps_get_thread_area (struct ps_prochandle *ph,
|
||||
lwpid_t lwpid, int idx, void **base)
|
||||
{
|
||||
if (gdbarch_bfd_arch_info (target_gdbarch ())->bits_per_word == 32)
|
||||
if (gdbarch_bfd_arch_info (ph->thread->inf->gdbarch)->bits_per_word == 32)
|
||||
{
|
||||
unsigned int base_addr;
|
||||
ps_err_e result;
|
||||
|
@ -185,7 +185,7 @@ signal_catchpoint_print_it (bpstat bs)
|
||||
const char *signal_name;
|
||||
struct ui_out *uiout = current_uiout;
|
||||
|
||||
get_last_target_status (nullptr, &last);
|
||||
get_last_target_status (nullptr, nullptr, &last);
|
||||
|
||||
signal_name = signal_to_name_or_int (last.value.sig);
|
||||
|
||||
|
@ -186,7 +186,7 @@ print_it_catch_syscall (bpstat bs)
|
||||
struct syscall s;
|
||||
struct gdbarch *gdbarch = bs->bp_location_at->gdbarch;
|
||||
|
||||
get_last_target_status (nullptr, &last);
|
||||
get_last_target_status (nullptr, nullptr, &last);
|
||||
|
||||
get_syscall_by_number (gdbarch, last.value.syscall_number, &s);
|
||||
|
||||
|
@ -389,7 +389,7 @@ breakpoints_should_be_inserted_now (void)
|
||||
no threads under GDB's control yet. */
|
||||
return 1;
|
||||
}
|
||||
else if (target_has_execution)
|
||||
else
|
||||
{
|
||||
if (always_inserted_mode)
|
||||
{
|
||||
@ -398,7 +398,9 @@ breakpoints_should_be_inserted_now (void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (threads_are_executing ())
|
||||
for (inferior *inf : all_inferiors ())
|
||||
if (inf->has_execution ()
|
||||
&& threads_are_executing (inf->process_target ()))
|
||||
return 1;
|
||||
|
||||
/* Don't remove breakpoints yet if, even though all threads are
|
||||
@ -2887,7 +2889,7 @@ update_inserted_breakpoint_locations (void)
|
||||
if we aren't attached to any process yet, we should still
|
||||
insert breakpoints. */
|
||||
if (!gdbarch_has_global_breakpoints (target_gdbarch ())
|
||||
&& inferior_ptid == null_ptid)
|
||||
&& (inferior_ptid == null_ptid || !target_has_execution))
|
||||
continue;
|
||||
|
||||
val = insert_bp_location (bl, &tmp_error_stream, &disabled_breaks,
|
||||
@ -2943,7 +2945,7 @@ insert_breakpoint_locations (void)
|
||||
if we aren't attached to any process yet, we should still
|
||||
insert breakpoints. */
|
||||
if (!gdbarch_has_global_breakpoints (target_gdbarch ())
|
||||
&& inferior_ptid == null_ptid)
|
||||
&& (inferior_ptid == null_ptid || !target_has_execution))
|
||||
continue;
|
||||
|
||||
val = insert_bp_location (bl, &tmp_error_stream, &disabled_breaks,
|
||||
@ -11903,7 +11905,18 @@ update_global_location_list (enum ugll_insert_mode insert_mode)
|
||||
around. We simply always ignore hardware watchpoint
|
||||
traps we can no longer explain. */
|
||||
|
||||
old_loc->events_till_retirement = 3 * (thread_count () + 1);
|
||||
process_stratum_target *proc_target = nullptr;
|
||||
for (inferior *inf : all_inferiors ())
|
||||
if (inf->pspace == old_loc->pspace)
|
||||
{
|
||||
proc_target = inf->process_target ();
|
||||
break;
|
||||
}
|
||||
if (proc_target != nullptr)
|
||||
old_loc->events_till_retirement
|
||||
= 3 * (thread_count (proc_target) + 1);
|
||||
else
|
||||
old_loc->events_till_retirement = 1;
|
||||
old_loc->owner = NULL;
|
||||
|
||||
moribund_locations.push_back (old_loc);
|
||||
|
@ -136,7 +136,7 @@ bsd_kvm_target_open (const char *arg, int from_tty)
|
||||
core_kd = temp_kd;
|
||||
push_target (&bsd_kvm_ops);
|
||||
|
||||
add_thread_silent (bsd_kvm_ptid);
|
||||
add_thread_silent (&bsd_kvm_ops, bsd_kvm_ptid);
|
||||
inferior_ptid = bsd_kvm_ptid;
|
||||
|
||||
target_fetch_registers (get_current_regcache (), -1);
|
||||
|
@ -381,9 +381,11 @@ bsd_uthread_target::wait (ptid_t ptid, struct target_waitstatus *status,
|
||||
{
|
||||
enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
|
||||
CORE_ADDR addr;
|
||||
process_stratum_target *beneath
|
||||
= as_process_stratum_target (this->beneath ());
|
||||
|
||||
/* Pass the request to the layer beneath. */
|
||||
ptid = beneath ()->wait (ptid, status, options);
|
||||
ptid = beneath->wait (ptid, status, options);
|
||||
|
||||
/* If the process is no longer alive, there's no point in figuring
|
||||
out the thread ID. It will fail anyway. */
|
||||
@ -414,13 +416,13 @@ bsd_uthread_target::wait (ptid_t ptid, struct target_waitstatus *status,
|
||||
ptid with tid set, then ptid is still the initial thread of
|
||||
the process. Notify GDB core about it. */
|
||||
if (inferior_ptid.tid () == 0
|
||||
&& ptid.tid () != 0 && !in_thread_list (ptid))
|
||||
thread_change_ptid (inferior_ptid, ptid);
|
||||
&& ptid.tid () != 0 && !in_thread_list (beneath, ptid))
|
||||
thread_change_ptid (beneath, inferior_ptid, ptid);
|
||||
|
||||
/* Don't let the core see a ptid without a corresponding thread. */
|
||||
thread_info *thread = find_thread_ptid (ptid);
|
||||
thread_info *thread = find_thread_ptid (beneath, ptid);
|
||||
if (thread == NULL || thread->state == THREAD_EXITED)
|
||||
add_thread (ptid);
|
||||
add_thread (beneath, ptid);
|
||||
|
||||
return ptid;
|
||||
}
|
||||
@ -467,16 +469,18 @@ bsd_uthread_target::update_thread_list ()
|
||||
{
|
||||
ptid_t ptid = ptid_t (pid, 0, addr);
|
||||
|
||||
thread_info *thread = find_thread_ptid (ptid);
|
||||
process_stratum_target *proc_target
|
||||
= as_process_stratum_target (this->beneath ());
|
||||
thread_info *thread = find_thread_ptid (proc_target, ptid);
|
||||
if (thread == nullptr || thread->state == THREAD_EXITED)
|
||||
{
|
||||
/* If INFERIOR_PTID doesn't have a tid member yet, then ptid
|
||||
is still the initial thread of the process. Notify GDB
|
||||
core about it. */
|
||||
if (inferior_ptid.tid () == 0)
|
||||
thread_change_ptid (inferior_ptid, ptid);
|
||||
thread_change_ptid (proc_target, inferior_ptid, ptid);
|
||||
else
|
||||
add_thread (ptid);
|
||||
add_thread (proc_target, ptid);
|
||||
}
|
||||
|
||||
addr = bsd_uthread_read_memory_address (addr + offset);
|
||||
|
@ -3228,7 +3228,7 @@ maint_btrace_packet_history_cmd (const char *arg, int from_tty)
|
||||
struct btrace_thread_info *btinfo;
|
||||
unsigned int size, begin, end, from, to;
|
||||
|
||||
thread_info *tp = find_thread_ptid (inferior_ptid);
|
||||
thread_info *tp = find_thread_ptid (current_inferior (), inferior_ptid);
|
||||
if (tp == NULL)
|
||||
error (_("No thread."));
|
||||
|
||||
|
@ -314,7 +314,7 @@ add_to_thread_list (bfd *abfd, asection *asect, void *reg_sect_arg)
|
||||
|
||||
ptid = ptid_t (pid, lwpid, 0);
|
||||
|
||||
add_thread (ptid);
|
||||
add_thread (inf->process_target (), ptid);
|
||||
|
||||
/* Warning, Will Robinson, looking at BFD private data! */
|
||||
|
||||
@ -472,7 +472,7 @@ core_target_open (const char *arg, int from_tty)
|
||||
{
|
||||
inferior_appeared (current_inferior (), CORELOW_PID);
|
||||
inferior_ptid = ptid_t (CORELOW_PID);
|
||||
add_thread_silent (inferior_ptid);
|
||||
add_thread_silent (target, inferior_ptid);
|
||||
}
|
||||
else
|
||||
switch_to_thread (thread);
|
||||
@ -540,7 +540,7 @@ core_target_open (const char *arg, int from_tty)
|
||||
/* Current thread should be NUM 1 but the user does not know that.
|
||||
If a program is single threaded gdb in general does not mention
|
||||
anything about threads. That is why the test is >= 2. */
|
||||
if (thread_count () >= 2)
|
||||
if (thread_count (target) >= 2)
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -944,7 +944,7 @@ core_target::pid_to_str (ptid_t ptid)
|
||||
|
||||
/* Otherwise, this isn't a "threaded" core -- use the PID field, but
|
||||
only if it isn't a fake PID. */
|
||||
inf = find_inferior_ptid (ptid);
|
||||
inf = find_inferior_ptid (this, ptid);
|
||||
if (inf != NULL && !inf->fake_pid_p)
|
||||
return normal_pid_to_str (ptid);
|
||||
|
||||
|
@ -1137,6 +1137,9 @@ async_disconnect (gdb_client_data arg)
|
||||
exception_print (gdb_stderr, exception);
|
||||
}
|
||||
|
||||
for (inferior *inf : all_inferiors ())
|
||||
{
|
||||
switch_to_inferior_no_thread (inf);
|
||||
try
|
||||
{
|
||||
pop_all_targets ();
|
||||
@ -1144,6 +1147,7 @@ async_disconnect (gdb_client_data arg)
|
||||
catch (const gdb_exception &exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
signal (SIGHUP, SIG_DFL); /*FIXME: ??????????? */
|
||||
raise (SIGHUP);
|
||||
|
47
gdb/exec.c
47
gdb/exec.c
@ -547,12 +547,25 @@ add_target_sections (void *owner,
|
||||
table->sections[space + i].owner = owner;
|
||||
}
|
||||
|
||||
scoped_restore_current_thread restore_thread;
|
||||
program_space *curr_pspace = current_program_space;
|
||||
|
||||
/* If these are the first file sections we can provide memory
|
||||
from, push the file_stratum target. */
|
||||
if (!target_is_pushed (&exec_ops))
|
||||
from, push the file_stratum target. Must do this in all
|
||||
inferiors sharing the program space. */
|
||||
for (inferior *inf : all_inferiors ())
|
||||
{
|
||||
if (inf->pspace != curr_pspace)
|
||||
continue;
|
||||
|
||||
if (inf->target_is_pushed (&exec_ops))
|
||||
continue;
|
||||
|
||||
switch_to_inferior_no_thread (inf);
|
||||
push_target (&exec_ops);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Add the sections of OBJFILE to the current set of target sections. */
|
||||
|
||||
@ -628,20 +641,38 @@ remove_target_sections (void *owner)
|
||||
old_count = resize_section_table (table, dest - src);
|
||||
|
||||
/* If we don't have any more sections to read memory from,
|
||||
remove the file_stratum target from the stack. */
|
||||
remove the file_stratum target from the stack of each
|
||||
inferior sharing the program space. */
|
||||
if (old_count + (dest - src) == 0)
|
||||
{
|
||||
struct program_space *pspace;
|
||||
scoped_restore_current_thread restore_thread;
|
||||
program_space *curr_pspace = current_program_space;
|
||||
|
||||
ALL_PSPACES (pspace)
|
||||
if (pspace->target_sections.sections
|
||||
!= pspace->target_sections.sections_end)
|
||||
return;
|
||||
for (inferior *inf : all_inferiors ())
|
||||
{
|
||||
if (inf->pspace != curr_pspace)
|
||||
continue;
|
||||
|
||||
if (inf->pspace->target_sections.sections
|
||||
!= inf->pspace->target_sections.sections_end)
|
||||
continue;
|
||||
|
||||
switch_to_inferior_no_thread (inf);
|
||||
unpush_target (&exec_ops);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* See exec.h. */
|
||||
|
||||
void
|
||||
exec_on_vfork ()
|
||||
{
|
||||
if (current_program_space->target_sections.sections
|
||||
!= current_program_space->target_sections.sections_end)
|
||||
push_target (&exec_ops);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -44,6 +44,13 @@ extern int build_section_table (struct bfd *, struct target_section **,
|
||||
|
||||
extern void clear_section_table (struct target_section_table *table);
|
||||
|
||||
/* The current inferior is a child vforked and its program space is
|
||||
shared with its parent. This pushes the exec target on the
|
||||
current/child inferior's target stack if there are sections in the
|
||||
program space's section table. */
|
||||
|
||||
extern void exec_on_vfork ();
|
||||
|
||||
/* Read from mappable read-only sections of BFD executable files.
|
||||
Return TARGET_XFER_OK, if read is successful. Return
|
||||
TARGET_XFER_EOF if read is done. Return TARGET_XFER_E_IO
|
||||
|
@ -991,11 +991,11 @@ fbsd_enable_proc_events (pid_t pid)
|
||||
called to discover new threads each time the thread list is updated. */
|
||||
|
||||
static void
|
||||
fbsd_add_threads (pid_t pid)
|
||||
fbsd_add_threads (fbsd_nat_target *target, pid_t pid)
|
||||
{
|
||||
int i, nlwps;
|
||||
|
||||
gdb_assert (!in_thread_list (ptid_t (pid)));
|
||||
gdb_assert (!in_thread_list (target, ptid_t (pid)));
|
||||
nlwps = ptrace (PT_GETNUMLWPS, pid, NULL, 0);
|
||||
if (nlwps == -1)
|
||||
perror_with_name (("ptrace"));
|
||||
@ -1010,7 +1010,7 @@ fbsd_add_threads (pid_t pid)
|
||||
{
|
||||
ptid_t ptid = ptid_t (pid, lwps[i], 0);
|
||||
|
||||
if (!in_thread_list (ptid))
|
||||
if (!in_thread_list (target, ptid))
|
||||
{
|
||||
#ifdef PT_LWP_EVENTS
|
||||
struct ptrace_lwpinfo pl;
|
||||
@ -1026,7 +1026,7 @@ fbsd_add_threads (pid_t pid)
|
||||
fprintf_unfiltered (gdb_stdlog,
|
||||
"FLWP: adding thread for LWP %u\n",
|
||||
lwps[i]);
|
||||
add_thread (ptid);
|
||||
add_thread (target, ptid);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1043,7 +1043,7 @@ fbsd_nat_target::update_thread_list ()
|
||||
#else
|
||||
prune_threads ();
|
||||
|
||||
fbsd_add_threads (inferior_ptid.pid ());
|
||||
fbsd_add_threads (this, inferior_ptid.pid ());
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1174,7 +1174,7 @@ fbsd_nat_target::resume (ptid_t ptid, int step, enum gdb_signal signo)
|
||||
if (ptid.lwp_p ())
|
||||
{
|
||||
/* If ptid is a specific LWP, suspend all other LWPs in the process. */
|
||||
inferior *inf = find_inferior_ptid (ptid);
|
||||
inferior *inf = find_inferior_ptid (this, ptid);
|
||||
|
||||
for (thread_info *tp : inf->non_exited_threads ())
|
||||
{
|
||||
@ -1193,7 +1193,7 @@ fbsd_nat_target::resume (ptid_t ptid, int step, enum gdb_signal signo)
|
||||
{
|
||||
/* If ptid is a wildcard, resume all matching threads (they won't run
|
||||
until the process is continued however). */
|
||||
for (thread_info *tp : all_non_exited_threads (ptid))
|
||||
for (thread_info *tp : all_non_exited_threads (this, ptid))
|
||||
if (ptrace (PT_RESUME, tp->ptid.lwp (), NULL, 0) == -1)
|
||||
perror_with_name (("ptrace"));
|
||||
ptid = inferior_ptid;
|
||||
@ -1239,7 +1239,8 @@ fbsd_nat_target::resume (ptid_t ptid, int step, enum gdb_signal signo)
|
||||
core, return true. */
|
||||
|
||||
static bool
|
||||
fbsd_handle_debug_trap (ptid_t ptid, const struct ptrace_lwpinfo &pl)
|
||||
fbsd_handle_debug_trap (fbsd_nat_target *target, ptid_t ptid,
|
||||
const struct ptrace_lwpinfo &pl)
|
||||
{
|
||||
|
||||
/* Ignore traps without valid siginfo or for signals other than
|
||||
@ -1266,7 +1267,7 @@ fbsd_handle_debug_trap (ptid_t ptid, const struct ptrace_lwpinfo &pl)
|
||||
if (pl.pl_siginfo.si_code == TRAP_BRKPT)
|
||||
{
|
||||
/* Fixup PC for the software breakpoint. */
|
||||
struct regcache *regcache = get_thread_regcache (ptid);
|
||||
struct regcache *regcache = get_thread_regcache (target, ptid);
|
||||
struct gdbarch *gdbarch = regcache->arch ();
|
||||
int decr_pc = gdbarch_decr_pc_after_break (gdbarch);
|
||||
|
||||
@ -1340,7 +1341,7 @@ fbsd_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
|
||||
threads might be skipped during post_attach that
|
||||
have not yet reported their PL_FLAG_EXITED event.
|
||||
Ignore EXITED events for an unknown LWP. */
|
||||
thread_info *thr = find_thread_ptid (wptid);
|
||||
thread_info *thr = find_thread_ptid (this, wptid);
|
||||
if (thr != nullptr)
|
||||
{
|
||||
if (debug_fbsd_lwp)
|
||||
@ -1364,13 +1365,13 @@ fbsd_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
|
||||
PL_FLAG_BORN in case the first stop reported after
|
||||
attaching to an existing process is a PL_FLAG_BORN
|
||||
event. */
|
||||
if (in_thread_list (ptid_t (pid)))
|
||||
if (in_thread_list (this, ptid_t (pid)))
|
||||
{
|
||||
if (debug_fbsd_lwp)
|
||||
fprintf_unfiltered (gdb_stdlog,
|
||||
"FLWP: using LWP %u for first thread\n",
|
||||
pl.pl_lwpid);
|
||||
thread_change_ptid (ptid_t (pid), wptid);
|
||||
thread_change_ptid (this, ptid_t (pid), wptid);
|
||||
}
|
||||
|
||||
#ifdef PT_LWP_EVENTS
|
||||
@ -1380,13 +1381,13 @@ fbsd_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
|
||||
threads might be added by fbsd_add_threads that have
|
||||
not yet reported their PL_FLAG_BORN event. Ignore
|
||||
BORN events for an already-known LWP. */
|
||||
if (!in_thread_list (wptid))
|
||||
if (!in_thread_list (this, wptid))
|
||||
{
|
||||
if (debug_fbsd_lwp)
|
||||
fprintf_unfiltered (gdb_stdlog,
|
||||
"FLWP: adding thread for LWP %u\n",
|
||||
pl.pl_lwpid);
|
||||
add_thread (wptid);
|
||||
add_thread (this, wptid);
|
||||
}
|
||||
ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
|
||||
return wptid;
|
||||
@ -1474,7 +1475,7 @@ fbsd_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
|
||||
#endif
|
||||
|
||||
#ifdef USE_SIGTRAP_SIGINFO
|
||||
if (fbsd_handle_debug_trap (wptid, pl))
|
||||
if (fbsd_handle_debug_trap (this, wptid, pl))
|
||||
return wptid;
|
||||
#endif
|
||||
|
||||
@ -1633,7 +1634,7 @@ void
|
||||
fbsd_nat_target::post_attach (int pid)
|
||||
{
|
||||
fbsd_enable_proc_events (pid);
|
||||
fbsd_add_threads (pid);
|
||||
fbsd_add_threads (this, pid);
|
||||
}
|
||||
|
||||
#ifdef PL_FLAG_EXEC
|
||||
|
@ -673,7 +673,8 @@ fbsd_corefile_thread (struct thread_info *info,
|
||||
{
|
||||
struct regcache *regcache;
|
||||
|
||||
regcache = get_thread_arch_regcache (info->ptid, args->gdbarch);
|
||||
regcache = get_thread_arch_regcache (info->inf->process_target (),
|
||||
info->ptid, args->gdbarch);
|
||||
|
||||
target_fetch_registers (regcache, -1);
|
||||
|
||||
|
@ -128,10 +128,13 @@ postfork_child_hook ()
|
||||
ptid_t
|
||||
gdb_startup_inferior (pid_t pid, int num_traps)
|
||||
{
|
||||
ptid_t ptid = startup_inferior (pid, num_traps, NULL, NULL);
|
||||
inferior *inf = current_inferior ();
|
||||
process_stratum_target *proc_target = inf->process_target ();
|
||||
|
||||
ptid_t ptid = startup_inferior (proc_target, pid, num_traps, NULL, NULL);
|
||||
|
||||
/* Mark all threads non-executing. */
|
||||
set_executing (ptid, 0);
|
||||
set_executing (proc_target, ptid, 0);
|
||||
|
||||
return ptid;
|
||||
}
|
||||
|
@ -1,3 +1,25 @@
|
||||
2020-01-10 Pedro Alves <palves@redhat.com>
|
||||
|
||||
* fork-child.c (post_fork_inferior): Pass target down to
|
||||
startup_inferior.
|
||||
* inferiors.c (switch_to_thread): Add process_stratum_target
|
||||
parameter.
|
||||
* lynx-low.c (lynx_target_ops): Now a process_stratum_target.
|
||||
* nto-low.c (nto_target_ops): Now a process_stratum_target.
|
||||
* linux-low.c (linux_target_ops): Now a process_stratum_target.
|
||||
* remote-utils.c (prepare_resume_reply): Pass the target to
|
||||
switch_to_thread.
|
||||
* target.c (the_target): Now a process_stratum_target.
|
||||
(done_accessing_memory): Pass the target to switch_to_thread.
|
||||
(set_target_ops): Ajust to use process_stratum_target.
|
||||
* target.h (struct target_ops): Rename to ...
|
||||
(struct process_stratum_target): ... this.
|
||||
(the_target, set_target_ops): Adjust.
|
||||
(prepare_to_access_memory): Adjust comment.
|
||||
* win32-low.c (child_xfer_memory): Adjust to use
|
||||
process_stratum_target.
|
||||
(win32_target_ops): Now a process_stratum_target.
|
||||
|
||||
2020-01-06 Eli Zaretskii <eliz@gnu.org>
|
||||
Pedro Alves <palves@redhat.com>
|
||||
|
||||
|
@ -107,7 +107,8 @@ post_fork_inferior (int pid, const char *program)
|
||||
atexit (restore_old_foreground_pgrp);
|
||||
#endif
|
||||
|
||||
startup_inferior (pid, START_INFERIOR_TRAPS_EXPECTED,
|
||||
startup_inferior (the_target, pid,
|
||||
START_INFERIOR_TRAPS_EXPECTED,
|
||||
&cs.last_status, &cs.last_ptid);
|
||||
current_thread->last_resume_kind = resume_stop;
|
||||
current_thread->last_status = cs.last_status;
|
||||
|
@ -216,7 +216,7 @@ current_process (void)
|
||||
/* See gdbsupport/common-gdbthread.h. */
|
||||
|
||||
void
|
||||
switch_to_thread (ptid_t ptid)
|
||||
switch_to_thread (process_stratum_target *ops, ptid_t ptid)
|
||||
{
|
||||
gdb_assert (ptid != minus_one_ptid);
|
||||
current_thread = find_thread_ptid (ptid);
|
||||
|
@ -7354,7 +7354,7 @@ linux_get_hwcap2 (int wordsize)
|
||||
return hwcap2;
|
||||
}
|
||||
|
||||
static struct target_ops linux_target_ops = {
|
||||
static process_stratum_target linux_target_ops = {
|
||||
linux_create_inferior,
|
||||
linux_post_create_inferior,
|
||||
linux_attach,
|
||||
|
@ -721,7 +721,7 @@ lynx_request_interrupt (void)
|
||||
|
||||
/* The LynxOS target_ops vector. */
|
||||
|
||||
static struct target_ops lynx_target_ops = {
|
||||
static process_stratum_target lynx_target_ops = {
|
||||
lynx_create_inferior,
|
||||
NULL, /* post_create_inferior */
|
||||
lynx_attach,
|
||||
|
@ -931,7 +931,7 @@ nto_sw_breakpoint_from_kind (int kind, int *size)
|
||||
}
|
||||
|
||||
|
||||
static struct target_ops nto_target_ops = {
|
||||
static process_stratum_target nto_target_ops = {
|
||||
nto_create_inferior,
|
||||
NULL, /* post_create_inferior */
|
||||
nto_attach,
|
||||
|
@ -1208,7 +1208,7 @@ prepare_resume_reply (char *buf, ptid_t ptid,
|
||||
|
||||
saved_thread = current_thread;
|
||||
|
||||
switch_to_thread (ptid);
|
||||
switch_to_thread (the_target, ptid);
|
||||
|
||||
regp = current_target_desc ()->expedite_regs;
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include "tracepoint.h"
|
||||
#include "gdbsupport/byte-vector.h"
|
||||
|
||||
struct target_ops *the_target;
|
||||
process_stratum_target *the_target;
|
||||
|
||||
int
|
||||
set_desired_thread ()
|
||||
@ -119,7 +119,7 @@ done_accessing_memory (void)
|
||||
|
||||
/* Restore the previous selected thread. */
|
||||
cs.general_thread = prev_general_thread;
|
||||
switch_to_thread (cs.general_thread);
|
||||
switch_to_thread (the_target, cs.general_thread);
|
||||
}
|
||||
|
||||
int
|
||||
@ -284,9 +284,9 @@ start_non_stop (int nonstop)
|
||||
}
|
||||
|
||||
void
|
||||
set_target_ops (struct target_ops *target)
|
||||
set_target_ops (process_stratum_target *target)
|
||||
{
|
||||
the_target = XNEW (struct target_ops);
|
||||
the_target = XNEW (process_stratum_target);
|
||||
memcpy (the_target, target, sizeof (*the_target));
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,10 @@ struct thread_resume
|
||||
CORE_ADDR step_range_end; /* Exclusive */
|
||||
};
|
||||
|
||||
struct target_ops
|
||||
/* GDBserver doesn't have a concept of strata like GDB, but we call
|
||||
its target vector "process_stratum" anyway for the benefit of
|
||||
shared code. */
|
||||
struct process_stratum_target
|
||||
{
|
||||
/* Start a new process.
|
||||
|
||||
@ -476,9 +479,9 @@ struct target_ops
|
||||
bool (*thread_handle) (ptid_t ptid, gdb_byte **handle, int *handle_len);
|
||||
};
|
||||
|
||||
extern struct target_ops *the_target;
|
||||
extern process_stratum_target *the_target;
|
||||
|
||||
void set_target_ops (struct target_ops *);
|
||||
void set_target_ops (process_stratum_target *);
|
||||
|
||||
#define create_inferior(program, program_args) \
|
||||
(*the_target->create_inferior) (program, program_args)
|
||||
@ -702,7 +705,7 @@ ptid_t mywait (ptid_t ptid, struct target_waitstatus *ourstatus, int options,
|
||||
int connected_wait);
|
||||
|
||||
/* Prepare to read or write memory from the inferior process. See the
|
||||
corresponding target_ops methods for more details. */
|
||||
corresponding process_stratum_target methods for more details. */
|
||||
|
||||
int prepare_to_access_memory (void);
|
||||
void done_accessing_memory (void);
|
||||
|
@ -307,7 +307,7 @@ win32_stopped_data_address (void)
|
||||
/* Transfer memory from/to the debugged process. */
|
||||
static int
|
||||
child_xfer_memory (CORE_ADDR memaddr, char *our, int len,
|
||||
int write, struct target_ops *target)
|
||||
int write, process_stratum_target *target)
|
||||
{
|
||||
BOOL success;
|
||||
SIZE_T done = 0;
|
||||
@ -1795,7 +1795,7 @@ win32_sw_breakpoint_from_kind (int kind, int *size)
|
||||
return the_low_target.breakpoint;
|
||||
}
|
||||
|
||||
static struct target_ops win32_target_ops = {
|
||||
static process_stratum_target win32_target_ops = {
|
||||
win32_create_inferior,
|
||||
NULL, /* post_create_inferior */
|
||||
win32_attach,
|
||||
|
@ -19,7 +19,10 @@
|
||||
#ifndef COMMON_COMMON_GDBTHREAD_H
|
||||
#define COMMON_COMMON_GDBTHREAD_H
|
||||
|
||||
struct process_stratum_target;
|
||||
|
||||
/* Switch from one thread to another. */
|
||||
extern void switch_to_thread (ptid_t ptid);
|
||||
extern void switch_to_thread (process_stratum_target *proc_target,
|
||||
ptid_t ptid);
|
||||
|
||||
#endif /* COMMON_COMMON_GDBTHREAD_H */
|
||||
|
125
gdb/gdbthread.h
125
gdb/gdbthread.h
@ -34,6 +34,7 @@ struct symtab;
|
||||
#include "gdbsupport/forward-scope-exit.h"
|
||||
|
||||
struct inferior;
|
||||
struct process_stratum_target;
|
||||
|
||||
/* Frontend view of the thread state. Possible extensions: stepping,
|
||||
finishing, until(ling),...
|
||||
@ -304,7 +305,7 @@ public:
|
||||
from saying that there is an active target and we are stopped at
|
||||
a breakpoint, for instance. This is a real indicator whether the
|
||||
thread is off and running. */
|
||||
int executing = 0;
|
||||
bool executing = false;
|
||||
|
||||
/* Non-zero if this thread is resumed from infrun's perspective.
|
||||
Note that a thread can be marked both as not-executing and
|
||||
@ -419,15 +420,18 @@ extern void init_thread_list (void);
|
||||
that a new thread is found, and return the pointer to
|
||||
the new thread. Caller my use this pointer to
|
||||
initialize the private thread data. */
|
||||
extern struct thread_info *add_thread (ptid_t ptid);
|
||||
extern struct thread_info *add_thread (process_stratum_target *targ,
|
||||
ptid_t ptid);
|
||||
|
||||
/* Same as add_thread, but does not print a message
|
||||
about new thread. */
|
||||
extern struct thread_info *add_thread_silent (ptid_t ptid);
|
||||
/* Same as add_thread, but does not print a message about new
|
||||
thread. */
|
||||
extern struct thread_info *add_thread_silent (process_stratum_target *targ,
|
||||
ptid_t ptid);
|
||||
|
||||
/* Same as add_thread, and sets the private info. */
|
||||
extern struct thread_info *add_thread_with_info (ptid_t ptid,
|
||||
struct private_thread_info *);
|
||||
extern struct thread_info *add_thread_with_info (process_stratum_target *targ,
|
||||
ptid_t ptid,
|
||||
private_thread_info *);
|
||||
|
||||
/* Delete an existing thread list entry. */
|
||||
extern void delete_thread (struct thread_info *thread);
|
||||
@ -468,14 +472,18 @@ extern int show_inferior_qualified_tids (void);
|
||||
const char *print_thread_id (struct thread_info *thr);
|
||||
|
||||
/* Boolean test for an already-known ptid. */
|
||||
extern int in_thread_list (ptid_t ptid);
|
||||
extern bool in_thread_list (process_stratum_target *targ, ptid_t ptid);
|
||||
|
||||
/* Boolean test for an already-known global thread id (GDB's homegrown
|
||||
global id, not the system's). */
|
||||
extern int valid_global_thread_id (int global_id);
|
||||
|
||||
/* Find thread PTID of inferior INF. */
|
||||
extern thread_info *find_thread_ptid (inferior *inf, ptid_t ptid);
|
||||
|
||||
/* Search function to lookup a thread by 'pid'. */
|
||||
extern struct thread_info *find_thread_ptid (ptid_t ptid);
|
||||
extern struct thread_info *find_thread_ptid (process_stratum_target *targ,
|
||||
ptid_t ptid);
|
||||
|
||||
/* Search function to lookup a thread by 'ptid'. Only searches in
|
||||
threads of INF. */
|
||||
@ -500,7 +508,8 @@ extern struct thread_info *any_thread_of_inferior (inferior *inf);
|
||||
extern struct thread_info *any_live_thread_of_inferior (inferior *inf);
|
||||
|
||||
/* Change the ptid of thread OLD_PTID to NEW_PTID. */
|
||||
void thread_change_ptid (ptid_t old_ptid, ptid_t new_ptid);
|
||||
void thread_change_ptid (process_stratum_target *targ,
|
||||
ptid_t old_ptid, ptid_t new_ptid);
|
||||
|
||||
/* Iterator function to call a user-provided callback function
|
||||
once for each known thread. */
|
||||
@ -511,34 +520,44 @@ extern struct thread_info *iterate_over_threads (thread_callback_func, void *);
|
||||
iterators. Must be done after struct thread_info is defined. */
|
||||
#include "thread-iter.h"
|
||||
|
||||
/* Return a range that can be used to walk over all threads of all
|
||||
inferiors, with range-for. Used like this:
|
||||
/* Return a range that can be used to walk over threads, with
|
||||
range-for.
|
||||
|
||||
Used like this, it walks over all threads of all inferiors of all
|
||||
targets:
|
||||
|
||||
for (thread_info *thr : all_threads ())
|
||||
{ .... }
|
||||
*/
|
||||
inline all_threads_range
|
||||
all_threads ()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
/* Likewise, but accept a filter PTID. */
|
||||
FILTER_PTID can be used to filter out threads that don't match.
|
||||
FILTER_PTID can be:
|
||||
|
||||
- minus_one_ptid, meaning walk all threads of all inferiors of
|
||||
PROC_TARGET. If PROC_TARGET is NULL, then of all targets.
|
||||
|
||||
- A process ptid, in which case walk all threads of the specified
|
||||
process. PROC_TARGET must be non-NULL in this case.
|
||||
|
||||
- A thread ptid, in which case walk that thread only. PROC_TARGET
|
||||
must be non-NULL in this case.
|
||||
*/
|
||||
|
||||
inline all_matching_threads_range
|
||||
all_threads (ptid_t filter_ptid)
|
||||
all_threads (process_stratum_target *proc_target = nullptr,
|
||||
ptid_t filter_ptid = minus_one_ptid)
|
||||
{
|
||||
return all_matching_threads_range (filter_ptid);
|
||||
return all_matching_threads_range (proc_target, filter_ptid);
|
||||
}
|
||||
|
||||
/* Return a range that can be used to walk over all non-exited threads
|
||||
of all inferiors, with range-for. FILTER_PTID can be used to
|
||||
filter out thread that don't match. */
|
||||
of all inferiors, with range-for. Arguments are like all_threads
|
||||
above. */
|
||||
|
||||
inline all_non_exited_threads_range
|
||||
all_non_exited_threads (ptid_t filter_ptid = minus_one_ptid)
|
||||
all_non_exited_threads (process_stratum_target *proc_target = nullptr,
|
||||
ptid_t filter_ptid = minus_one_ptid)
|
||||
{
|
||||
return all_non_exited_threads_range (filter_ptid);
|
||||
return all_non_exited_threads_range (proc_target, filter_ptid);
|
||||
}
|
||||
|
||||
/* Return a range that can be used to walk over all threads of all
|
||||
@ -554,10 +573,10 @@ all_non_exited_threads (ptid_t filter_ptid = minus_one_ptid)
|
||||
inline all_threads_safe_range
|
||||
all_threads_safe ()
|
||||
{
|
||||
return all_threads_safe_range ();
|
||||
return {};
|
||||
}
|
||||
|
||||
extern int thread_count (void);
|
||||
extern int thread_count (process_stratum_target *proc_target);
|
||||
|
||||
/* Return true if we have any thread in any inferior. */
|
||||
extern bool any_thread_p ();
|
||||
@ -571,44 +590,50 @@ extern void switch_to_no_thread ();
|
||||
/* Switch from one thread to another. Does not read registers. */
|
||||
extern void switch_to_thread_no_regs (struct thread_info *thread);
|
||||
|
||||
/* Marks or clears thread(s) PTID as resumed. If PTID is
|
||||
MINUS_ONE_PTID, applies to all threads. If ptid_is_pid(PTID) is
|
||||
true, applies to all threads of the process pointed at by PTID. */
|
||||
extern void set_resumed (ptid_t ptid, int resumed);
|
||||
|
||||
/* Marks thread PTID is running, or stopped.
|
||||
If PTID is minus_one_ptid, marks all threads. */
|
||||
extern void set_running (ptid_t ptid, int running);
|
||||
|
||||
/* Marks or clears thread(s) PTID as having been requested to stop.
|
||||
If PTID is MINUS_ONE_PTID, applies to all threads. If
|
||||
/* Marks or clears thread(s) PTID of TARG as resumed. If PTID is
|
||||
MINUS_ONE_PTID, applies to all threads of TARG. If
|
||||
ptid_is_pid(PTID) is true, applies to all threads of the process
|
||||
pointed at by PTID. If STOP, then the THREAD_STOP_REQUESTED
|
||||
observer is called with PTID as argument. */
|
||||
extern void set_stop_requested (ptid_t ptid, int stop);
|
||||
pointed at by {TARG,PTID}. */
|
||||
extern void set_resumed (process_stratum_target *targ,
|
||||
ptid_t ptid, bool resumed);
|
||||
|
||||
/* Marks thread PTID as executing, or not. If PTID is minus_one_ptid,
|
||||
marks all threads.
|
||||
/* Marks thread PTID of TARG as running, or as stopped. If PTID is
|
||||
minus_one_ptid, marks all threads of TARG. */
|
||||
extern void set_running (process_stratum_target *targ,
|
||||
ptid_t ptid, bool running);
|
||||
|
||||
/* Marks or clears thread(s) PTID of TARG as having been requested to
|
||||
stop. If PTID is MINUS_ONE_PTID, applies to all threads of TARG.
|
||||
If ptid_is_pid(PTID) is true, applies to all threads of the process
|
||||
pointed at by {TARG, PTID}. If STOP, then the
|
||||
THREAD_STOP_REQUESTED observer is called with PTID as argument. */
|
||||
extern void set_stop_requested (process_stratum_target *targ,
|
||||
ptid_t ptid, bool stop);
|
||||
|
||||
/* Marks thread PTID of TARG as executing, or not. If PTID is
|
||||
minus_one_ptid, marks all threads of TARG.
|
||||
|
||||
Note that this is different from the running state. See the
|
||||
description of state and executing fields of struct
|
||||
thread_info. */
|
||||
extern void set_executing (ptid_t ptid, int executing);
|
||||
extern void set_executing (process_stratum_target *targ,
|
||||
ptid_t ptid, bool executing);
|
||||
|
||||
/* True if any (known or unknown) thread is or may be executing. */
|
||||
extern int threads_are_executing (void);
|
||||
/* True if any (known or unknown) thread of TARG is or may be
|
||||
executing. */
|
||||
extern bool threads_are_executing (process_stratum_target *targ);
|
||||
|
||||
/* Merge the executing property of thread PTID over to its thread
|
||||
state property (frontend running/stopped view).
|
||||
/* Merge the executing property of thread PTID of TARG over to its
|
||||
thread state property (frontend running/stopped view).
|
||||
|
||||
"not executing" -> "stopped"
|
||||
"executing" -> "running"
|
||||
"exited" -> "exited"
|
||||
|
||||
If PTID is minus_one_ptid, go over all threads.
|
||||
If PTID is minus_one_ptid, go over all threads of TARG.
|
||||
|
||||
Notifications are only emitted if the thread state did change. */
|
||||
extern void finish_thread_state (ptid_t ptid);
|
||||
extern void finish_thread_state (process_stratum_target *targ, ptid_t ptid);
|
||||
|
||||
/* Calls finish_thread_state on scope exit, unless release() is called
|
||||
to disengage. */
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "i387-tdep.h"
|
||||
#include "fbsd-tdep.h"
|
||||
#include "solib-svr4.h"
|
||||
#include "inferior.h"
|
||||
|
||||
/* Support for signal handlers. */
|
||||
|
||||
@ -332,7 +333,8 @@ i386fbsd_get_thread_local_address (struct gdbarch *gdbarch, ptid_t ptid,
|
||||
if (tdep->fsbase_regnum == -1)
|
||||
error (_("Unable to fetch %%gsbase"));
|
||||
|
||||
regcache = get_thread_arch_regcache (ptid, gdbarch);
|
||||
regcache = get_thread_arch_regcache (current_inferior ()->process_target (),
|
||||
ptid, gdbarch);
|
||||
|
||||
target_fetch_registers (regcache, tdep->fsbase_regnum + 1);
|
||||
|
||||
|
@ -657,7 +657,7 @@ i386_linux_nat_target::low_resume (ptid_t ptid, int step, enum gdb_signal signal
|
||||
|
||||
if (step)
|
||||
{
|
||||
struct regcache *regcache = get_thread_regcache (ptid);
|
||||
struct regcache *regcache = get_thread_regcache (this, ptid);
|
||||
struct gdbarch *gdbarch = regcache->arch ();
|
||||
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
|
||||
ULONGEST pc;
|
||||
|
@ -206,7 +206,7 @@ inf_child_target::mourn_inferior ()
|
||||
void
|
||||
inf_child_target::maybe_unpush_target ()
|
||||
{
|
||||
if (!inf_child_explicitly_opened && !have_inferiors ())
|
||||
if (!inf_child_explicitly_opened)
|
||||
unpush_target (this);
|
||||
}
|
||||
|
||||
|
@ -136,7 +136,7 @@ inf_ptrace_target::create_inferior (const char *exec_file,
|
||||
/* We have something that executes now. We'll be running through
|
||||
the shell at this point (if startup-with-shell is true), but the
|
||||
pid shouldn't change. */
|
||||
add_thread_silent (ptid);
|
||||
add_thread_silent (this, ptid);
|
||||
|
||||
unpusher.release ();
|
||||
|
||||
@ -235,10 +235,10 @@ inf_ptrace_target::attach (const char *args, int from_tty)
|
||||
|
||||
/* Always add a main thread. If some target extends the ptrace
|
||||
target, it should decorate the ptid later with more info. */
|
||||
thread_info *thr = add_thread_silent (inferior_ptid);
|
||||
thread_info *thr = add_thread_silent (this, inferior_ptid);
|
||||
/* Don't consider the thread stopped until we've processed its
|
||||
initial SIGSTOP stop. */
|
||||
set_executing (thr->ptid, true);
|
||||
set_executing (this, thr->ptid, true);
|
||||
|
||||
unpusher.release ();
|
||||
}
|
||||
|
@ -649,7 +649,8 @@ run_inferior_call (struct call_thread_fsm *sm,
|
||||
if (!was_running
|
||||
&& call_thread_ptid == inferior_ptid
|
||||
&& stop_stack_dummy == STOP_STACK_DUMMY)
|
||||
finish_thread_state (user_visible_resume_ptid (0));
|
||||
finish_thread_state (call_thread->inf->process_target (),
|
||||
user_visible_resume_ptid (0));
|
||||
|
||||
enable_watchpoints_after_interactive_call_stop ();
|
||||
|
||||
|
106
gdb/infcmd.c
106
gdb/infcmd.c
@ -645,10 +645,19 @@ run_command_1 (const char *args, int from_tty, enum run_how run_how)
|
||||
events --- the frontend shouldn't see them as stopped. In
|
||||
all-stop, always finish the state of all threads, as we may be
|
||||
resuming more than just the new process. */
|
||||
ptid_t finish_ptid = (non_stop
|
||||
? ptid_t (current_inferior ()->pid)
|
||||
: minus_one_ptid);
|
||||
scoped_finish_thread_state finish_state (finish_ptid);
|
||||
process_stratum_target *finish_target;
|
||||
ptid_t finish_ptid;
|
||||
if (non_stop)
|
||||
{
|
||||
finish_target = current_inferior ()->process_target ();
|
||||
finish_ptid = ptid_t (current_inferior ()->pid);
|
||||
}
|
||||
else
|
||||
{
|
||||
finish_target = nullptr;
|
||||
finish_ptid = minus_one_ptid;
|
||||
}
|
||||
scoped_finish_thread_state finish_state (finish_target, finish_ptid);
|
||||
|
||||
/* Pass zero for FROM_TTY, because at this point the "run" command
|
||||
has done its thing; now we are setting up the running program. */
|
||||
@ -718,6 +727,9 @@ proceed_thread_callback (struct thread_info *thread, void *arg)
|
||||
if (thread->state != THREAD_STOPPED)
|
||||
return 0;
|
||||
|
||||
if (!thread->inf->has_execution ())
|
||||
return 0;
|
||||
|
||||
switch_to_thread (thread);
|
||||
clear_proceed_status (0);
|
||||
proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
|
||||
@ -811,7 +823,7 @@ static void
|
||||
continue_command (const char *args, int from_tty)
|
||||
{
|
||||
int async_exec;
|
||||
int all_threads = 0;
|
||||
bool all_threads_p = false;
|
||||
|
||||
ERROR_NO_INFERIOR;
|
||||
|
||||
@ -823,17 +835,17 @@ continue_command (const char *args, int from_tty)
|
||||
{
|
||||
if (startswith (args, "-a"))
|
||||
{
|
||||
all_threads = 1;
|
||||
all_threads_p = true;
|
||||
args += sizeof ("-a") - 1;
|
||||
if (*args == '\0')
|
||||
args = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!non_stop && all_threads)
|
||||
if (!non_stop && all_threads_p)
|
||||
error (_("`-a' is meaningless in all-stop mode."));
|
||||
|
||||
if (args != NULL && all_threads)
|
||||
if (args != NULL && all_threads_p)
|
||||
error (_("Can't resume all threads and specify "
|
||||
"proceed count simultaneously."));
|
||||
|
||||
@ -850,10 +862,11 @@ continue_command (const char *args, int from_tty)
|
||||
tp = inferior_thread ();
|
||||
else
|
||||
{
|
||||
process_stratum_target *last_target;
|
||||
ptid_t last_ptid;
|
||||
|
||||
get_last_target_status (&last_ptid, nullptr);
|
||||
tp = find_thread_ptid (last_ptid);
|
||||
get_last_target_status (&last_target, &last_ptid, nullptr);
|
||||
tp = find_thread_ptid (last_target, last_ptid);
|
||||
}
|
||||
if (tp != NULL)
|
||||
bs = tp->control.stop_bpstat;
|
||||
@ -881,7 +894,7 @@ continue_command (const char *args, int from_tty)
|
||||
ERROR_NO_INFERIOR;
|
||||
ensure_not_tfind_mode ();
|
||||
|
||||
if (!non_stop || !all_threads)
|
||||
if (!non_stop || !all_threads_p)
|
||||
{
|
||||
ensure_valid_thread ();
|
||||
ensure_not_running ();
|
||||
@ -892,7 +905,7 @@ continue_command (const char *args, int from_tty)
|
||||
if (from_tty)
|
||||
printf_filtered (_("Continuing.\n"));
|
||||
|
||||
continue_1 (all_threads);
|
||||
continue_1 (all_threads_p);
|
||||
}
|
||||
|
||||
/* Record the starting point of a "step" or "next" command. */
|
||||
@ -1112,7 +1125,7 @@ prepare_one_step (struct step_command_fsm *sm)
|
||||
|
||||
/* Pretend that we've ran. */
|
||||
resume_ptid = user_visible_resume_ptid (1);
|
||||
set_running (resume_ptid, 1);
|
||||
set_running (tp->inf->process_target (), resume_ptid, true);
|
||||
|
||||
step_into_inline_frame (tp);
|
||||
|
||||
@ -1316,10 +1329,14 @@ signal_command (const char *signum_exp, int from_tty)
|
||||
/* This indicates what will be resumed. Either a single thread,
|
||||
a whole process, or all threads of all processes. */
|
||||
ptid_t resume_ptid = user_visible_resume_ptid (0);
|
||||
process_stratum_target *resume_target
|
||||
= user_visible_resume_target (resume_ptid);
|
||||
|
||||
for (thread_info *tp : all_non_exited_threads (resume_ptid))
|
||||
thread_info *current = inferior_thread ();
|
||||
|
||||
for (thread_info *tp : all_non_exited_threads (resume_target, resume_ptid))
|
||||
{
|
||||
if (tp->ptid == inferior_ptid)
|
||||
if (tp == current)
|
||||
continue;
|
||||
|
||||
if (tp->suspend.stop_signal != GDB_SIGNAL_0
|
||||
@ -1982,6 +1999,7 @@ info_program_command (const char *args, int from_tty)
|
||||
bpstat bs;
|
||||
int num, stat;
|
||||
ptid_t ptid;
|
||||
process_stratum_target *proc_target;
|
||||
|
||||
if (!target_has_execution)
|
||||
{
|
||||
@ -1990,14 +2008,17 @@ info_program_command (const char *args, int from_tty)
|
||||
}
|
||||
|
||||
if (non_stop)
|
||||
{
|
||||
ptid = inferior_ptid;
|
||||
proc_target = current_inferior ()->process_target ();
|
||||
}
|
||||
else
|
||||
get_last_target_status (&ptid, nullptr);
|
||||
get_last_target_status (&proc_target, &ptid, nullptr);
|
||||
|
||||
if (ptid == null_ptid || ptid == minus_one_ptid)
|
||||
error (_("No selected thread."));
|
||||
|
||||
thread_info *tp = find_thread_ptid (ptid);
|
||||
thread_info *tp = find_thread_ptid (proc_target, ptid);
|
||||
|
||||
if (tp->state == THREAD_EXITED)
|
||||
error (_("Invalid selected thread."));
|
||||
@ -2786,11 +2807,15 @@ attach_command (const char *args, int from_tty)
|
||||
add_inferior_continuation (attach_command_continuation, a,
|
||||
attach_command_continuation_free_args);
|
||||
|
||||
/* Let infrun consider waiting for events out of this
|
||||
target. */
|
||||
inferior->process_target ()->threads_executing = true;
|
||||
|
||||
if (!target_is_async_p ())
|
||||
mark_infrun_async_event_handler ();
|
||||
return;
|
||||
}
|
||||
|
||||
else
|
||||
attach_post_wait (args, from_tty, mode);
|
||||
}
|
||||
|
||||
@ -2908,20 +2933,15 @@ disconnect_command (const char *args, int from_tty)
|
||||
deprecated_detach_hook ();
|
||||
}
|
||||
|
||||
void
|
||||
interrupt_target_1 (int all_threads)
|
||||
/* Stop PTID in the current target, and tag the PTID threads as having
|
||||
been explicitly requested to stop. PTID can be a thread, a
|
||||
process, or minus_one_ptid, meaning all threads of all inferiors of
|
||||
the current target. */
|
||||
|
||||
static void
|
||||
stop_current_target_threads_ns (ptid_t ptid)
|
||||
{
|
||||
ptid_t ptid;
|
||||
|
||||
if (all_threads)
|
||||
ptid = minus_one_ptid;
|
||||
else
|
||||
ptid = inferior_ptid;
|
||||
|
||||
if (non_stop)
|
||||
target_stop (ptid);
|
||||
else
|
||||
target_interrupt ();
|
||||
|
||||
/* Tag the thread as having been explicitly requested to stop, so
|
||||
other parts of gdb know not to resume this thread automatically,
|
||||
@ -2929,8 +2949,32 @@ interrupt_target_1 (int all_threads)
|
||||
non-stop mode, as when debugging a multi-threaded application in
|
||||
all-stop mode, we will only get one stop event --- it's undefined
|
||||
which thread will report the event. */
|
||||
set_stop_requested (current_inferior ()->process_target (),
|
||||
ptid, 1);
|
||||
}
|
||||
|
||||
/* See inferior.h. */
|
||||
|
||||
void
|
||||
interrupt_target_1 (bool all_threads)
|
||||
{
|
||||
if (non_stop)
|
||||
set_stop_requested (ptid, 1);
|
||||
{
|
||||
if (all_threads)
|
||||
{
|
||||
scoped_restore_current_thread restore_thread;
|
||||
|
||||
for (inferior *inf : all_inferiors ())
|
||||
{
|
||||
switch_to_inferior_no_thread (inf);
|
||||
stop_current_target_threads_ns (minus_one_ptid);
|
||||
}
|
||||
}
|
||||
else
|
||||
stop_current_target_threads_ns (inferior_ptid);
|
||||
}
|
||||
else
|
||||
target_interrupt ();
|
||||
}
|
||||
|
||||
/* interrupt [-a]
|
||||
|
@ -36,18 +36,23 @@ public:
|
||||
typedef int difference_type;
|
||||
|
||||
/* Create an iterator pointing at HEAD. */
|
||||
explicit all_inferiors_iterator (inferior *head)
|
||||
: m_inf (head)
|
||||
{}
|
||||
all_inferiors_iterator (process_stratum_target *proc_target, inferior *head)
|
||||
: m_proc_target (proc_target)
|
||||
{
|
||||
/* Advance M_INF to the first inferior's position. */
|
||||
for (m_inf = head; m_inf != NULL; m_inf = m_inf->next)
|
||||
if (m_inf_matches ())
|
||||
return;
|
||||
}
|
||||
|
||||
/* Create a one-past-end iterator. */
|
||||
all_inferiors_iterator ()
|
||||
: m_inf (nullptr)
|
||||
: m_proc_target (nullptr), m_inf (nullptr)
|
||||
{}
|
||||
|
||||
all_inferiors_iterator &operator++ ()
|
||||
{
|
||||
m_inf = m_inf->next;
|
||||
advance ();
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -58,6 +63,30 @@ public:
|
||||
{ return m_inf != other.m_inf; }
|
||||
|
||||
private:
|
||||
/* Advance to next inferior, skipping filtered inferiors. */
|
||||
void advance ()
|
||||
{
|
||||
/* The loop below is written in the natural way as-if we'd always
|
||||
start at the beginning of the inferior list. This
|
||||
fast-forwards the algorithm to the actual current position. */
|
||||
goto start;
|
||||
|
||||
while (m_inf != NULL)
|
||||
{
|
||||
if (m_inf_matches ())
|
||||
return;
|
||||
start:
|
||||
m_inf = m_inf->next;
|
||||
}
|
||||
}
|
||||
|
||||
bool m_inf_matches ()
|
||||
{
|
||||
return (m_proc_target == nullptr
|
||||
|| m_proc_target == m_inf->process_target ());
|
||||
}
|
||||
|
||||
process_stratum_target *m_proc_target;
|
||||
inferior *m_inf;
|
||||
};
|
||||
|
||||
@ -80,10 +109,17 @@ using all_non_exited_inferiors_iterator
|
||||
inferiors with range-for. */
|
||||
struct all_inferiors_range
|
||||
{
|
||||
all_inferiors_range (process_stratum_target *proc_target = nullptr)
|
||||
: m_filter_target (proc_target)
|
||||
{}
|
||||
|
||||
all_inferiors_iterator begin () const
|
||||
{ return all_inferiors_iterator (inferior_list); }
|
||||
{ return all_inferiors_iterator (m_filter_target, inferior_list); }
|
||||
all_inferiors_iterator end () const
|
||||
{ return all_inferiors_iterator (); }
|
||||
|
||||
private:
|
||||
process_stratum_target *m_filter_target;
|
||||
};
|
||||
|
||||
/* Iterate over all inferiors, safely. */
|
||||
@ -97,10 +133,26 @@ using all_inferiors_safe_iterator
|
||||
|
||||
struct all_inferiors_safe_range
|
||||
{
|
||||
explicit all_inferiors_safe_range (process_stratum_target *filter_target)
|
||||
: m_filter_target (filter_target)
|
||||
{}
|
||||
|
||||
all_inferiors_safe_range ()
|
||||
: m_filter_target (nullptr)
|
||||
{}
|
||||
|
||||
all_inferiors_safe_iterator begin () const
|
||||
{ return all_inferiors_safe_iterator (inferior_list); }
|
||||
{
|
||||
return (all_inferiors_safe_iterator
|
||||
(all_inferiors_iterator (m_filter_target, inferior_list)));
|
||||
}
|
||||
|
||||
all_inferiors_safe_iterator end () const
|
||||
{ return all_inferiors_safe_iterator (); }
|
||||
|
||||
private:
|
||||
/* The filter. */
|
||||
process_stratum_target *m_filter_target;
|
||||
};
|
||||
|
||||
/* A range adapter that makes it possible to iterate over all
|
||||
@ -108,10 +160,22 @@ struct all_inferiors_safe_range
|
||||
|
||||
struct all_non_exited_inferiors_range
|
||||
{
|
||||
explicit all_non_exited_inferiors_range (process_stratum_target *filter_target)
|
||||
: m_filter_target (filter_target)
|
||||
{}
|
||||
|
||||
all_non_exited_inferiors_range ()
|
||||
: m_filter_target (nullptr)
|
||||
{}
|
||||
|
||||
all_non_exited_inferiors_iterator begin () const
|
||||
{ return all_non_exited_inferiors_iterator (inferior_list); }
|
||||
{ return all_non_exited_inferiors_iterator (m_filter_target, inferior_list); }
|
||||
all_non_exited_inferiors_iterator end () const
|
||||
{ return all_non_exited_inferiors_iterator (); }
|
||||
|
||||
private:
|
||||
/* The filter. */
|
||||
process_stratum_target *m_filter_target;
|
||||
};
|
||||
|
||||
#endif /* !defined (INFERIOR_ITER_H) */
|
||||
|
@ -90,6 +90,8 @@ inferior::inferior (int pid_)
|
||||
registry_data ()
|
||||
{
|
||||
inferior_alloc_data (this);
|
||||
|
||||
m_target_stack.push (get_dummy_target ());
|
||||
}
|
||||
|
||||
struct inferior *
|
||||
@ -276,14 +278,14 @@ find_inferior_id (int num)
|
||||
}
|
||||
|
||||
struct inferior *
|
||||
find_inferior_pid (int pid)
|
||||
find_inferior_pid (process_stratum_target *targ, int pid)
|
||||
{
|
||||
/* Looking for inferior pid == 0 is always wrong, and indicative of
|
||||
a bug somewhere else. There may be more than one with pid == 0,
|
||||
for instance. */
|
||||
gdb_assert (pid != 0);
|
||||
|
||||
for (inferior *inf : all_inferiors ())
|
||||
for (inferior *inf : all_inferiors (targ))
|
||||
if (inf->pid == pid)
|
||||
return inf;
|
||||
|
||||
@ -293,9 +295,9 @@ find_inferior_pid (int pid)
|
||||
/* See inferior.h */
|
||||
|
||||
struct inferior *
|
||||
find_inferior_ptid (ptid_t ptid)
|
||||
find_inferior_ptid (process_stratum_target *targ, ptid_t ptid)
|
||||
{
|
||||
return find_inferior_pid (ptid.pid ());
|
||||
return find_inferior_pid (targ, ptid.pid ());
|
||||
}
|
||||
|
||||
/* See inferior.h. */
|
||||
@ -340,11 +342,11 @@ have_inferiors (void)
|
||||
in the middle of a 'mourn' operation. */
|
||||
|
||||
int
|
||||
number_of_live_inferiors (void)
|
||||
number_of_live_inferiors (process_stratum_target *proc_target)
|
||||
{
|
||||
int num_inf = 0;
|
||||
|
||||
for (inferior *inf : all_non_exited_inferiors ())
|
||||
for (inferior *inf : all_non_exited_inferiors (proc_target))
|
||||
if (inf->has_execution ())
|
||||
for (thread_info *tp ATTRIBUTE_UNUSED : inf->non_exited_threads ())
|
||||
{
|
||||
@ -362,7 +364,7 @@ number_of_live_inferiors (void)
|
||||
int
|
||||
have_live_inferiors (void)
|
||||
{
|
||||
return number_of_live_inferiors () > 0;
|
||||
return number_of_live_inferiors (NULL) > 0;
|
||||
}
|
||||
|
||||
/* Prune away any unused inferiors, and then prune away no longer used
|
||||
@ -694,7 +696,28 @@ add_inferior_with_spaces (void)
|
||||
return inf;
|
||||
}
|
||||
|
||||
/* add-inferior [-copies N] [-exec FILENAME] */
|
||||
/* Switch to inferior NEW_INF, a new inferior, and unless
|
||||
NO_CONNECTION is true, push the process_stratum_target of ORG_INF
|
||||
to NEW_INF. */
|
||||
|
||||
static void
|
||||
switch_to_inferior_and_push_target (inferior *new_inf,
|
||||
bool no_connection, inferior *org_inf)
|
||||
{
|
||||
process_stratum_target *proc_target = org_inf->process_target ();
|
||||
|
||||
/* Switch over temporarily, while reading executable and
|
||||
symbols. */
|
||||
switch_to_inferior_no_thread (new_inf);
|
||||
|
||||
/* Reuse the target for new inferior. */
|
||||
if (!no_connection && proc_target != NULL)
|
||||
push_target (proc_target);
|
||||
|
||||
printf_filtered (_("Added inferior %d\n"), new_inf->num);
|
||||
}
|
||||
|
||||
/* add-inferior [-copies N] [-exec FILENAME] [-no-connection] */
|
||||
|
||||
static void
|
||||
add_inferior_command (const char *args, int from_tty)
|
||||
@ -702,6 +725,7 @@ add_inferior_command (const char *args, int from_tty)
|
||||
int i, copies = 1;
|
||||
gdb::unique_xmalloc_ptr<char> exec;
|
||||
symfile_add_flags add_flags = 0;
|
||||
bool no_connection = false;
|
||||
|
||||
if (from_tty)
|
||||
add_flags |= SYMFILE_VERBOSE;
|
||||
@ -721,6 +745,8 @@ add_inferior_command (const char *args, int from_tty)
|
||||
error (_("No argument to -copies"));
|
||||
copies = parse_and_eval_long (*argv);
|
||||
}
|
||||
else if (strcmp (*argv, "-no-connection") == 0)
|
||||
no_connection = true;
|
||||
else if (strcmp (*argv, "-exec") == 0)
|
||||
{
|
||||
++argv;
|
||||
@ -734,32 +760,32 @@ add_inferior_command (const char *args, int from_tty)
|
||||
}
|
||||
}
|
||||
|
||||
inferior *orginf = current_inferior ();
|
||||
|
||||
scoped_restore_current_pspace_and_thread restore_pspace_thread;
|
||||
|
||||
for (i = 0; i < copies; ++i)
|
||||
{
|
||||
struct inferior *inf = add_inferior_with_spaces ();
|
||||
inferior *inf = add_inferior_with_spaces ();
|
||||
|
||||
printf_filtered (_("Added inferior %d\n"), inf->num);
|
||||
switch_to_inferior_and_push_target (inf, no_connection, orginf);
|
||||
|
||||
if (exec != NULL)
|
||||
{
|
||||
/* Switch over temporarily, while reading executable and
|
||||
symbols. */
|
||||
switch_to_inferior_no_thread (inf);
|
||||
exec_file_attach (exec.get (), from_tty);
|
||||
symbol_file_add_main (exec.get (), add_flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* clone-inferior [-copies N] [ID] */
|
||||
/* clone-inferior [-copies N] [ID] [-no-connection] */
|
||||
|
||||
static void
|
||||
clone_inferior_command (const char *args, int from_tty)
|
||||
{
|
||||
int i, copies = 1;
|
||||
struct inferior *orginf = NULL;
|
||||
bool no_connection = false;
|
||||
|
||||
if (args)
|
||||
{
|
||||
@ -780,6 +806,8 @@ clone_inferior_command (const char *args, int from_tty)
|
||||
if (copies < 0)
|
||||
error (_("Invalid copies number"));
|
||||
}
|
||||
else if (strcmp (*argv, "-no-connection") == 0)
|
||||
no_connection = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -825,15 +853,13 @@ clone_inferior_command (const char *args, int from_tty)
|
||||
inf->aspace = pspace->aspace;
|
||||
inf->gdbarch = orginf->gdbarch;
|
||||
|
||||
switch_to_inferior_and_push_target (inf, no_connection, orginf);
|
||||
|
||||
/* If the original inferior had a user specified target
|
||||
description, make the clone use it too. */
|
||||
if (target_desc_info_from_user_p (inf->tdesc_info))
|
||||
copy_inferior_target_desc_info (inf, orginf);
|
||||
|
||||
printf_filtered (_("Added inferior %d.\n"), inf->num);
|
||||
|
||||
set_current_inferior (inf);
|
||||
switch_to_no_thread ();
|
||||
clone_program_space (pspace, orginf->pspace);
|
||||
}
|
||||
}
|
||||
@ -894,10 +920,13 @@ By default all inferiors are displayed."));
|
||||
|
||||
c = add_com ("add-inferior", no_class, add_inferior_command, _("\
|
||||
Add a new inferior.\n\
|
||||
Usage: add-inferior [-copies N] [-exec FILENAME]\n\
|
||||
Usage: add-inferior [-copies N] [-exec FILENAME] [-no-connection]\n\
|
||||
N is the optional number of inferiors to add, default is 1.\n\
|
||||
FILENAME is the file name of the executable to use\n\
|
||||
as main program."));
|
||||
as main program.\n\
|
||||
By default, the new inferior inherits the current inferior's connection.\n\
|
||||
If -no-connection is specified, the new inferior begins with\n\
|
||||
no target connection yet."));
|
||||
set_cmd_completer (c, filename_completer);
|
||||
|
||||
add_com ("remove-inferiors", no_class, remove_inferior_command, _("\
|
||||
@ -906,11 +935,14 @@ Usage: remove-inferiors ID..."));
|
||||
|
||||
add_com ("clone-inferior", no_class, clone_inferior_command, _("\
|
||||
Clone inferior ID.\n\
|
||||
Usage: clone-inferior [-copies N] [ID]\n\
|
||||
Add N copies of inferior ID. The new inferior has the same\n\
|
||||
Usage: clone-inferior [-copies N] [-no-connection] [ID]\n\
|
||||
Add N copies of inferior ID. The new inferiors have the same\n\
|
||||
executable loaded as the copied inferior. If -copies is not specified,\n\
|
||||
adds 1 copy. If ID is not specified, it is the current inferior\n\
|
||||
that is cloned."));
|
||||
that is cloned.\n\
|
||||
By default, the new inferiors inherit the copied inferior's connection.\n\
|
||||
If -no-connection is specified, the new inferiors begin with\n\
|
||||
no target connection yet."));
|
||||
|
||||
add_cmd ("inferiors", class_run, detach_inferior_command, _("\
|
||||
Detach from inferior ID (or list of IDS).\n\
|
||||
|
@ -56,6 +56,8 @@ struct thread_info;
|
||||
#include "gdbsupport/common-inferior.h"
|
||||
#include "gdbthread.h"
|
||||
|
||||
#include "process-stratum-target.h"
|
||||
|
||||
struct infcall_suspend_state;
|
||||
struct infcall_control_state;
|
||||
|
||||
@ -206,7 +208,7 @@ extern void registers_info (const char *, int);
|
||||
|
||||
extern void continue_1 (int all_threads);
|
||||
|
||||
extern void interrupt_target_1 (int all_threads);
|
||||
extern void interrupt_target_1 (bool all_threads);
|
||||
|
||||
using delete_longjmp_breakpoint_cleanup
|
||||
= FORWARD_SCOPE_EXIT (delete_longjmp_breakpoint);
|
||||
@ -343,6 +345,35 @@ public:
|
||||
/* Returns true if we can delete this inferior. */
|
||||
bool deletable () const { return refcount () == 0; }
|
||||
|
||||
/* Push T in this inferior's target stack. */
|
||||
void push_target (struct target_ops *t)
|
||||
{ m_target_stack.push (t); }
|
||||
|
||||
/* Unpush T from this inferior's target stack. */
|
||||
int unpush_target (struct target_ops *t)
|
||||
{ return m_target_stack.unpush (t); }
|
||||
|
||||
/* Returns true if T is pushed in this inferior's target stack. */
|
||||
bool target_is_pushed (target_ops *t)
|
||||
{ return m_target_stack.is_pushed (t); }
|
||||
|
||||
/* Find the target beneath T in this inferior's target stack. */
|
||||
target_ops *find_target_beneath (const target_ops *t)
|
||||
{ return m_target_stack.find_beneath (t); }
|
||||
|
||||
/* Return the target at the top of this inferior's target stack. */
|
||||
target_ops *top_target ()
|
||||
{ return m_target_stack.top (); }
|
||||
|
||||
/* Return the target at process_stratum level in this inferior's
|
||||
target stack. */
|
||||
struct process_stratum_target *process_target ()
|
||||
{ return (process_stratum_target *) m_target_stack.at (process_stratum); }
|
||||
|
||||
/* Return the target at STRATUM in this inferior's target stack. */
|
||||
target_ops *target_at (enum strata stratum)
|
||||
{ return m_target_stack.at (stratum); }
|
||||
|
||||
bool has_execution ()
|
||||
{ return target_has_execution_1 (this); }
|
||||
|
||||
@ -507,6 +538,10 @@ public:
|
||||
|
||||
/* Per inferior data-pointers required by other GDB modules. */
|
||||
REGISTRY_FIELDS;
|
||||
|
||||
private:
|
||||
/* The inferior's target stack. */
|
||||
target_stack m_target_stack;
|
||||
};
|
||||
|
||||
/* Keep a registry of per-inferior data-pointers required by other GDB
|
||||
@ -537,14 +572,14 @@ extern void exit_inferior_num_silent (int num);
|
||||
|
||||
extern void inferior_appeared (struct inferior *inf, int pid);
|
||||
|
||||
/* Get rid of all inferiors. */
|
||||
extern void discard_all_inferiors (void);
|
||||
/* Search function to lookup an inferior of TARG by target 'pid'. */
|
||||
extern struct inferior *find_inferior_pid (process_stratum_target *targ,
|
||||
int pid);
|
||||
|
||||
/* Search function to lookup an inferior by target 'pid'. */
|
||||
extern struct inferior *find_inferior_pid (int pid);
|
||||
|
||||
/* Search function to lookup an inferior whose pid is equal to 'ptid.pid'. */
|
||||
extern struct inferior *find_inferior_ptid (ptid_t ptid);
|
||||
/* Search function to lookup an inferior of TARG whose pid is equal to
|
||||
'ptid.pid'. */
|
||||
extern struct inferior *find_inferior_ptid (process_stratum_target *targ,
|
||||
ptid_t ptid);
|
||||
|
||||
/* Search function to lookup an inferior by GDB 'num'. */
|
||||
extern struct inferior *find_inferior_id (int num);
|
||||
@ -571,8 +606,9 @@ extern struct inferior *iterate_over_inferiors (int (*) (struct inferior *,
|
||||
/* Returns true if the inferior list is not empty. */
|
||||
extern int have_inferiors (void);
|
||||
|
||||
/* Returns the number of live inferiors (real live processes). */
|
||||
extern int number_of_live_inferiors (void);
|
||||
/* Returns the number of live inferiors running on PROC_TARGET (real
|
||||
live processes with execution). */
|
||||
extern int number_of_live_inferiors (process_stratum_target *proc_target);
|
||||
|
||||
/* Returns true if there are any live inferiors in the inferior list
|
||||
(not cores, not executables, real live processes). */
|
||||
@ -629,18 +665,18 @@ all_inferiors_safe ()
|
||||
*/
|
||||
|
||||
inline all_inferiors_range
|
||||
all_inferiors ()
|
||||
all_inferiors (process_stratum_target *proc_target = nullptr)
|
||||
{
|
||||
return {};
|
||||
return all_inferiors_range (proc_target);
|
||||
}
|
||||
|
||||
/* Return a range that can be used to walk over all inferiors with PID
|
||||
not zero, with range-for. */
|
||||
|
||||
inline all_non_exited_inferiors_range
|
||||
all_non_exited_inferiors ()
|
||||
all_non_exited_inferiors (process_stratum_target *proc_target = nullptr)
|
||||
{
|
||||
return {};
|
||||
return all_non_exited_inferiors_range (proc_target);
|
||||
}
|
||||
|
||||
/* Prune away automatically added inferiors that aren't required
|
||||
|
541
gdb/infrun.c
541
gdb/infrun.c
File diff suppressed because it is too large
Load Diff
18
gdb/infrun.h
18
gdb/infrun.h
@ -25,6 +25,7 @@ struct target_waitstatus;
|
||||
struct frame_info;
|
||||
struct address_space;
|
||||
struct return_value_info;
|
||||
struct process_stratum_target;
|
||||
|
||||
/* True if we are debugging run control. */
|
||||
extern unsigned int debug_infrun;
|
||||
@ -93,7 +94,13 @@ extern void proceed (CORE_ADDR, enum gdb_signal);
|
||||
resumed. */
|
||||
extern ptid_t user_visible_resume_ptid (int step);
|
||||
|
||||
extern void wait_for_inferior (void);
|
||||
/* Return the process_stratum target that we will proceed, in the
|
||||
perspective of the user/frontend. If RESUME_PTID is
|
||||
MINUS_ONE_PTID, then we'll resume all threads of all targets, so
|
||||
the function returns NULL. Otherwise, we'll be resuming a process
|
||||
or thread of the current process, so we return the current
|
||||
inferior's process stratum target. */
|
||||
extern process_stratum_target *user_visible_resume_target (ptid_t resume_ptid);
|
||||
|
||||
/* Return control to GDB when the inferior stops for real. Print
|
||||
appropriate messages, remove breakpoints, give terminal our modes,
|
||||
@ -101,15 +108,16 @@ extern void wait_for_inferior (void);
|
||||
target, false otherwise. */
|
||||
extern int normal_stop (void);
|
||||
|
||||
/* Return the cached copy of the last ptid/waitstatus returned
|
||||
/* Return the cached copy of the last target/ptid/waitstatus returned
|
||||
by target_wait()/deprecated_target_wait_hook(). The data is
|
||||
actually cached by handle_inferior_event(), which gets called
|
||||
immediately after target_wait()/deprecated_target_wait_hook(). */
|
||||
extern void get_last_target_status (ptid_t *ptid,
|
||||
extern void get_last_target_status (process_stratum_target **target,
|
||||
ptid_t *ptid,
|
||||
struct target_waitstatus *status);
|
||||
|
||||
/* Set the cached copy of the last ptid/waitstatus. */
|
||||
extern void set_last_target_status (ptid_t ptid,
|
||||
/* Set the cached copy of the last target/ptid/waitstatus. */
|
||||
extern void set_last_target_status (process_stratum_target *target, ptid_t ptid,
|
||||
struct target_waitstatus status);
|
||||
|
||||
/* Clear the cached copy of the last ptid/waitstatus returned by
|
||||
|
@ -95,37 +95,54 @@ find_inline_frame_state (thread_info *thread)
|
||||
return &state;
|
||||
}
|
||||
|
||||
/* Forget about any hidden inlined functions in PTID, which is new or
|
||||
about to be resumed. PTID may be minus_one_ptid (all processes)
|
||||
or a PID (all threads in this process). */
|
||||
/* See inline-frame.h. */
|
||||
|
||||
void
|
||||
clear_inline_frame_state (ptid_t ptid)
|
||||
clear_inline_frame_state (process_stratum_target *target, ptid_t filter_ptid)
|
||||
{
|
||||
if (ptid == minus_one_ptid)
|
||||
{
|
||||
inline_states.clear ();
|
||||
return;
|
||||
}
|
||||
gdb_assert (target != NULL);
|
||||
|
||||
if (ptid.is_pid ())
|
||||
if (filter_ptid == minus_one_ptid || filter_ptid.is_pid ())
|
||||
{
|
||||
int pid = ptid.pid ();
|
||||
auto matcher = [target, &filter_ptid] (const inline_state &state)
|
||||
{
|
||||
thread_info *t = state.thread;
|
||||
return (t->inf->process_target () == target
|
||||
&& t->ptid.matches (filter_ptid));
|
||||
};
|
||||
|
||||
auto it = std::remove_if (inline_states.begin (), inline_states.end (),
|
||||
[pid] (const inline_state &state)
|
||||
{
|
||||
return pid == state.thread->inf->pid;
|
||||
});
|
||||
matcher);
|
||||
|
||||
inline_states.erase (it, inline_states.end ());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = std::find_if (inline_states.begin (), inline_states.end (),
|
||||
[&ptid] (const inline_state &state)
|
||||
|
||||
auto matcher = [target, &filter_ptid] (const inline_state &state)
|
||||
{
|
||||
return ptid == state.thread->ptid;
|
||||
thread_info *t = state.thread;
|
||||
return (t->inf->process_target () == target
|
||||
&& filter_ptid == t->ptid);
|
||||
};
|
||||
|
||||
auto it = std::find_if (inline_states.begin (), inline_states.end (),
|
||||
matcher);
|
||||
|
||||
if (it != inline_states.end ())
|
||||
unordered_remove (inline_states, it);
|
||||
}
|
||||
|
||||
/* See inline-frame.h. */
|
||||
|
||||
void
|
||||
clear_inline_frame_state (thread_info *thread)
|
||||
{
|
||||
auto it = std::find_if (inline_states.begin (), inline_states.end (),
|
||||
[thread] (const inline_state &state)
|
||||
{
|
||||
return thread == state.thread;
|
||||
});
|
||||
|
||||
if (it != inline_states.end ())
|
||||
|
@ -23,6 +23,7 @@
|
||||
struct frame_info;
|
||||
struct frame_unwind;
|
||||
struct bpstats;
|
||||
struct process_stratum_target;
|
||||
|
||||
/* The inline frame unwinder. */
|
||||
|
||||
@ -39,10 +40,15 @@ extern const struct frame_unwind inline_frame_unwind;
|
||||
void skip_inline_frames (thread_info *thread, struct bpstats *stop_chain);
|
||||
|
||||
/* Forget about any hidden inlined functions in PTID, which is new or
|
||||
about to be resumed. If PTID is minus_one_ptid, forget about all
|
||||
hidden inlined functions. */
|
||||
about to be resumed. PTID may be minus_one_ptid (all processes of
|
||||
TARGET) or a PID (all threads in this process of TARGET). */
|
||||
|
||||
void clear_inline_frame_state (ptid_t ptid);
|
||||
void clear_inline_frame_state (process_stratum_target *target, ptid_t ptid);
|
||||
|
||||
/* Forget about any hidden inlined functions in THREAD, which is new
|
||||
or about to be resumed. */
|
||||
|
||||
void clear_inline_frame_state (thread_info *thread);
|
||||
|
||||
/* Step into an inlined function by unhiding it. */
|
||||
|
||||
|
@ -519,7 +519,7 @@ Please switch to another checkpoint before deleting the current one"));
|
||||
list, waitpid the ptid.
|
||||
If fi->parent_ptid is a part of lwp and it is stopped, waitpid the
|
||||
ptid. */
|
||||
thread_info *parent = find_thread_ptid (pptid);
|
||||
thread_info *parent = find_thread_ptid (linux_target, pptid);
|
||||
if ((parent == NULL && find_fork_ptid (pptid))
|
||||
|| (parent != NULL && parent->state == THREAD_STOPPED))
|
||||
{
|
||||
@ -679,7 +679,7 @@ checkpoint_command (const char *args, int from_tty)
|
||||
error (_("checkpoint: call_function_by_hand returned null."));
|
||||
|
||||
retpid = value_as_long (ret);
|
||||
get_last_target_status (&last_target_ptid, &last_target_waitstatus);
|
||||
get_last_target_status (nullptr, &last_target_ptid, &last_target_waitstatus);
|
||||
|
||||
fp = find_fork_pid (retpid);
|
||||
|
||||
|
@ -515,9 +515,12 @@ linux_nat_target::follow_fork (int follow_child, int detach_fork)
|
||||
}
|
||||
else
|
||||
{
|
||||
scoped_restore save_inferior_ptid
|
||||
= make_scoped_restore (&inferior_ptid);
|
||||
inferior_ptid = child_ptid;
|
||||
/* Switching inferior_ptid is not enough, because then
|
||||
inferior_thread () would crash by not finding the thread
|
||||
in the current inferior. */
|
||||
scoped_restore_current_thread restore_current_thread;
|
||||
thread_info *child = find_thread_ptid (this, child_ptid);
|
||||
switch_to_thread (child);
|
||||
|
||||
/* Let the thread_db layer learn about this new process. */
|
||||
check_for_thread_db ();
|
||||
@ -989,7 +992,7 @@ linux_nat_switch_fork (ptid_t new_ptid)
|
||||
/* This changes the thread's ptid while preserving the gdb thread
|
||||
num. Also changes the inferior pid, while preserving the
|
||||
inferior num. */
|
||||
thread_change_ptid (inferior_ptid, new_ptid);
|
||||
thread_change_ptid (linux_target, inferior_ptid, new_ptid);
|
||||
|
||||
/* We've just told GDB core that the thread changed target id, but,
|
||||
in fact, it really is a different thread, with different register
|
||||
@ -1002,7 +1005,7 @@ linux_nat_switch_fork (ptid_t new_ptid)
|
||||
static void
|
||||
exit_lwp (struct lwp_info *lp)
|
||||
{
|
||||
struct thread_info *th = find_thread_ptid (lp->ptid);
|
||||
struct thread_info *th = find_thread_ptid (linux_target, lp->ptid);
|
||||
|
||||
if (th)
|
||||
{
|
||||
@ -1162,9 +1165,9 @@ attach_proc_task_lwp_callback (ptid_t ptid)
|
||||
/* Also add the LWP to gdb's thread list, in case a
|
||||
matching libthread_db is not found (or the process uses
|
||||
raw clone). */
|
||||
add_thread (lp->ptid);
|
||||
set_running (lp->ptid, 1);
|
||||
set_executing (lp->ptid, 1);
|
||||
add_thread (linux_target, lp->ptid);
|
||||
set_running (linux_target, lp->ptid, 1);
|
||||
set_executing (linux_target, lp->ptid, 1);
|
||||
}
|
||||
|
||||
return 1;
|
||||
@ -1203,7 +1206,7 @@ linux_nat_target::attach (const char *args, int from_tty)
|
||||
ptid = ptid_t (inferior_ptid.pid (),
|
||||
inferior_ptid.pid (),
|
||||
0);
|
||||
thread_change_ptid (inferior_ptid, ptid);
|
||||
thread_change_ptid (linux_target, inferior_ptid, ptid);
|
||||
|
||||
/* Add the initial process as the first LWP to the list. */
|
||||
lp = add_initial_lwp (ptid);
|
||||
@ -1304,7 +1307,7 @@ get_detach_signal (struct lwp_info *lp)
|
||||
signo = gdb_signal_from_host (WSTOPSIG (lp->status));
|
||||
else
|
||||
{
|
||||
struct thread_info *tp = find_thread_ptid (lp->ptid);
|
||||
struct thread_info *tp = find_thread_ptid (linux_target, lp->ptid);
|
||||
|
||||
if (target_is_non_stop_p () && !tp->executing)
|
||||
{
|
||||
@ -1316,10 +1319,12 @@ get_detach_signal (struct lwp_info *lp)
|
||||
else if (!target_is_non_stop_p ())
|
||||
{
|
||||
ptid_t last_ptid;
|
||||
process_stratum_target *last_target;
|
||||
|
||||
get_last_target_status (&last_ptid, nullptr);
|
||||
get_last_target_status (&last_target, &last_ptid, nullptr);
|
||||
|
||||
if (lp->ptid.lwp () == last_ptid.lwp ())
|
||||
if (last_target == linux_target
|
||||
&& lp->ptid.lwp () == last_ptid.lwp ())
|
||||
signo = tp->suspend.stop_signal;
|
||||
}
|
||||
}
|
||||
@ -1516,7 +1521,7 @@ linux_resume_one_lwp_throw (struct lwp_info *lp, int step,
|
||||
handle the case of stepping a breakpoint instruction). */
|
||||
if (step)
|
||||
{
|
||||
struct regcache *regcache = get_thread_regcache (lp->ptid);
|
||||
struct regcache *regcache = get_thread_regcache (linux_target, lp->ptid);
|
||||
|
||||
lp->stop_pc = regcache_read_pc (regcache);
|
||||
}
|
||||
@ -1535,7 +1540,7 @@ linux_resume_one_lwp_throw (struct lwp_info *lp, int step,
|
||||
lp->stopped = 0;
|
||||
lp->core = -1;
|
||||
lp->stop_reason = TARGET_STOPPED_BY_NO_REASON;
|
||||
registers_changed_ptid (lp->ptid);
|
||||
registers_changed_ptid (linux_target, lp->ptid);
|
||||
}
|
||||
|
||||
/* Called when we try to resume a stopped LWP and that errors out. If
|
||||
@ -1594,7 +1599,7 @@ resume_lwp (struct lwp_info *lp, int step, enum gdb_signal signo)
|
||||
{
|
||||
if (lp->stopped)
|
||||
{
|
||||
struct inferior *inf = find_inferior_ptid (lp->ptid);
|
||||
struct inferior *inf = find_inferior_ptid (linux_target, lp->ptid);
|
||||
|
||||
if (inf->vfork_child != NULL)
|
||||
{
|
||||
@ -1648,7 +1653,7 @@ linux_nat_resume_callback (struct lwp_info *lp, struct lwp_info *except)
|
||||
{
|
||||
struct thread_info *thread;
|
||||
|
||||
thread = find_thread_ptid (lp->ptid);
|
||||
thread = find_thread_ptid (linux_target, lp->ptid);
|
||||
if (thread != NULL)
|
||||
{
|
||||
signo = thread->suspend.stop_signal;
|
||||
@ -1805,7 +1810,7 @@ linux_handle_syscall_trap (struct lwp_info *lp, int stopping)
|
||||
{
|
||||
struct target_waitstatus *ourstatus = &lp->waitstatus;
|
||||
struct gdbarch *gdbarch = target_thread_architecture (lp->ptid);
|
||||
thread_info *thread = find_thread_ptid (lp->ptid);
|
||||
thread_info *thread = find_thread_ptid (linux_target, lp->ptid);
|
||||
int syscall_number = (int) gdbarch_get_syscall_number (gdbarch, thread);
|
||||
|
||||
if (stopping)
|
||||
@ -2025,15 +2030,15 @@ linux_handle_extended_wait (struct lwp_info *lp, int status)
|
||||
/* The process is not using thread_db. Add the LWP to
|
||||
GDB's list. */
|
||||
target_post_attach (new_lp->ptid.lwp ());
|
||||
add_thread (new_lp->ptid);
|
||||
add_thread (linux_target, new_lp->ptid);
|
||||
}
|
||||
|
||||
/* Even if we're stopping the thread for some reason
|
||||
internal to this module, from the perspective of infrun
|
||||
and the user/frontend, this new thread is running until
|
||||
it next reports a stop. */
|
||||
set_running (new_lp->ptid, 1);
|
||||
set_executing (new_lp->ptid, 1);
|
||||
set_running (linux_target, new_lp->ptid, 1);
|
||||
set_executing (linux_target, new_lp->ptid, 1);
|
||||
|
||||
if (WSTOPSIG (status) != SIGSTOP)
|
||||
{
|
||||
@ -2256,7 +2261,7 @@ wait_lwp (struct lwp_info *lp)
|
||||
|
||||
if (lp->must_set_ptrace_flags)
|
||||
{
|
||||
struct inferior *inf = find_inferior_pid (lp->ptid.pid ());
|
||||
inferior *inf = find_inferior_pid (linux_target, lp->ptid.pid ());
|
||||
int options = linux_nat_ptrace_options (inf->attach_flag);
|
||||
|
||||
linux_enable_event_reporting (lp->ptid.lwp (), options);
|
||||
@ -2483,7 +2488,7 @@ linux_nat_target::low_status_is_event (int status)
|
||||
static int
|
||||
stop_wait_callback (struct lwp_info *lp)
|
||||
{
|
||||
struct inferior *inf = find_inferior_ptid (lp->ptid);
|
||||
inferior *inf = find_inferior_ptid (linux_target, lp->ptid);
|
||||
|
||||
/* If this is a vfork parent, bail out, it is not going to report
|
||||
any SIGSTOP until the vfork is done with. */
|
||||
@ -2576,7 +2581,7 @@ status_callback (struct lwp_info *lp)
|
||||
if (lp->stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT
|
||||
|| lp->stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT)
|
||||
{
|
||||
struct regcache *regcache = get_thread_regcache (lp->ptid);
|
||||
struct regcache *regcache = get_thread_regcache (linux_target, lp->ptid);
|
||||
CORE_ADDR pc;
|
||||
int discard = 0;
|
||||
|
||||
@ -2697,7 +2702,7 @@ save_stop_reason (struct lwp_info *lp)
|
||||
if (!linux_target->low_status_is_event (lp->status))
|
||||
return;
|
||||
|
||||
regcache = get_thread_regcache (lp->ptid);
|
||||
regcache = get_thread_regcache (linux_target, lp->ptid);
|
||||
gdbarch = regcache->arch ();
|
||||
|
||||
pc = regcache_read_pc (regcache);
|
||||
@ -2959,7 +2964,7 @@ linux_nat_filter_event (int lwpid, int status)
|
||||
lp = add_lwp (ptid_t (lwpid, lwpid, 0));
|
||||
lp->stopped = 1;
|
||||
lp->resumed = 1;
|
||||
add_thread (lp->ptid);
|
||||
add_thread (linux_target, lp->ptid);
|
||||
}
|
||||
|
||||
if (WIFSTOPPED (status) && !lp)
|
||||
@ -2985,7 +2990,7 @@ linux_nat_filter_event (int lwpid, int status)
|
||||
|
||||
if (WIFSTOPPED (status) && lp->must_set_ptrace_flags)
|
||||
{
|
||||
struct inferior *inf = find_inferior_pid (lp->ptid.pid ());
|
||||
inferior *inf = find_inferior_pid (linux_target, lp->ptid.pid ());
|
||||
int options = linux_nat_ptrace_options (inf->attach_flag);
|
||||
|
||||
linux_enable_event_reporting (lp->ptid.lwp (), options);
|
||||
@ -3151,7 +3156,7 @@ linux_nat_filter_event (int lwpid, int status)
|
||||
if (!lp->step
|
||||
&& WSTOPSIG (status) && sigismember (&pass_mask, WSTOPSIG (status))
|
||||
&& (WSTOPSIG (status) != SIGSTOP
|
||||
|| !find_thread_ptid (lp->ptid)->stop_requested)
|
||||
|| !find_thread_ptid (linux_target, lp->ptid)->stop_requested)
|
||||
&& !linux_wstatus_maybe_breakpoint (status))
|
||||
{
|
||||
linux_resume_one_lwp (lp, lp->step, signo);
|
||||
@ -3270,7 +3275,7 @@ linux_nat_wait_1 (ptid_t ptid, struct target_waitstatus *ourstatus,
|
||||
if (inferior_ptid.is_pid ())
|
||||
{
|
||||
/* Upgrade the main thread's ptid. */
|
||||
thread_change_ptid (inferior_ptid,
|
||||
thread_change_ptid (linux_target, inferior_ptid,
|
||||
ptid_t (inferior_ptid.pid (),
|
||||
inferior_ptid.pid (), 0));
|
||||
|
||||
@ -3415,7 +3420,7 @@ linux_nat_wait_1 (ptid_t ptid, struct target_waitstatus *ourstatus,
|
||||
if (lp->stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT
|
||||
&& !USE_SIGTRAP_SIGINFO)
|
||||
{
|
||||
struct regcache *regcache = get_thread_regcache (lp->ptid);
|
||||
struct regcache *regcache = get_thread_regcache (linux_target, lp->ptid);
|
||||
struct gdbarch *gdbarch = regcache->arch ();
|
||||
int decr_pc = gdbarch_decr_pc_after_break (gdbarch);
|
||||
|
||||
@ -3516,7 +3521,7 @@ resume_stopped_resumed_lwps (struct lwp_info *lp, const ptid_t wait_ptid)
|
||||
}
|
||||
else
|
||||
{
|
||||
struct regcache *regcache = get_thread_regcache (lp->ptid);
|
||||
struct regcache *regcache = get_thread_regcache (linux_target, lp->ptid);
|
||||
struct gdbarch *gdbarch = regcache->arch ();
|
||||
|
||||
try
|
||||
@ -4264,6 +4269,12 @@ linux_async_pipe (int enable)
|
||||
return previous;
|
||||
}
|
||||
|
||||
int
|
||||
linux_nat_target::async_wait_fd ()
|
||||
{
|
||||
return linux_nat_event_pipe[0];
|
||||
}
|
||||
|
||||
/* target_async implementation. */
|
||||
|
||||
void
|
||||
@ -4321,7 +4332,7 @@ linux_nat_stop_lwp (struct lwp_info *lwp)
|
||||
|
||||
if (debug_linux_nat)
|
||||
{
|
||||
if (find_thread_ptid (lwp->ptid)->stop_requested)
|
||||
if (find_thread_ptid (linux_target, lwp->ptid)->stop_requested)
|
||||
fprintf_unfiltered (gdb_stdlog,
|
||||
"LNSL: already stopped/stop_requested %s\n",
|
||||
target_pid_to_str (lwp->ptid).c_str ());
|
||||
@ -4378,7 +4389,7 @@ linux_nat_target::thread_address_space (ptid_t ptid)
|
||||
pid = ptid.pid ();
|
||||
}
|
||||
|
||||
inf = find_inferior_pid (pid);
|
||||
inf = find_inferior_pid (this, pid);
|
||||
gdb_assert (inf != NULL);
|
||||
return inf->aspace;
|
||||
}
|
||||
|
@ -88,6 +88,7 @@ public:
|
||||
bool supports_non_stop () override;
|
||||
bool always_non_stop_p () override;
|
||||
|
||||
int async_wait_fd () override;
|
||||
void async (int) override;
|
||||
|
||||
void close () override;
|
||||
|
@ -1651,7 +1651,8 @@ linux_corefile_thread (struct thread_info *info,
|
||||
{
|
||||
struct regcache *regcache;
|
||||
|
||||
regcache = get_thread_arch_regcache (info->ptid, args->gdbarch);
|
||||
regcache = get_thread_arch_regcache (info->inf->process_target (),
|
||||
info->ptid, args->gdbarch);
|
||||
|
||||
target_fetch_registers (regcache, -1);
|
||||
gdb::byte_vector siginfo_data = linux_get_siginfo_data (info, args->gdbarch);
|
||||
|
@ -168,6 +168,9 @@ struct thread_db_info
|
||||
{
|
||||
struct thread_db_info *next;
|
||||
|
||||
/* The target this thread_db_info is bound to. */
|
||||
process_stratum_target *process_target;
|
||||
|
||||
/* Process id this object refers to. */
|
||||
int pid;
|
||||
|
||||
@ -228,6 +231,7 @@ add_thread_db_info (void *handle)
|
||||
{
|
||||
struct thread_db_info *info = XCNEW (struct thread_db_info);
|
||||
|
||||
info->process_target = current_inferior ()->process_target ();
|
||||
info->pid = inferior_ptid.pid ();
|
||||
info->handle = handle;
|
||||
|
||||
@ -246,12 +250,12 @@ add_thread_db_info (void *handle)
|
||||
related to process PID, if any; NULL otherwise. */
|
||||
|
||||
static struct thread_db_info *
|
||||
get_thread_db_info (int pid)
|
||||
get_thread_db_info (process_stratum_target *targ, int pid)
|
||||
{
|
||||
struct thread_db_info *info;
|
||||
|
||||
for (info = thread_db_list; info; info = info->next)
|
||||
if (pid == info->pid)
|
||||
if (targ == info->process_target && pid == info->pid)
|
||||
return info;
|
||||
|
||||
return NULL;
|
||||
@ -265,14 +269,14 @@ static const char *thread_db_err_str (td_err_e err);
|
||||
LIBTHREAD_DB_SO's dlopen'ed handle. */
|
||||
|
||||
static void
|
||||
delete_thread_db_info (int pid)
|
||||
delete_thread_db_info (process_stratum_target *targ, int pid)
|
||||
{
|
||||
struct thread_db_info *info, *info_prev;
|
||||
|
||||
info_prev = NULL;
|
||||
|
||||
for (info = thread_db_list; info; info_prev = info, info = info->next)
|
||||
if (pid == info->pid)
|
||||
if (targ == info->process_target && pid == info->pid)
|
||||
break;
|
||||
|
||||
if (info == NULL)
|
||||
@ -406,7 +410,7 @@ thread_from_lwp (thread_info *stopped, ptid_t ptid)
|
||||
LWP. */
|
||||
gdb_assert (ptid.lwp () != 0);
|
||||
|
||||
info = get_thread_db_info (ptid.pid ());
|
||||
info = get_thread_db_info (stopped->inf->process_target (), ptid.pid ());
|
||||
|
||||
/* Access an lwp we know is stopped. */
|
||||
info->proc_handle.thread = stopped;
|
||||
@ -422,7 +426,7 @@ thread_from_lwp (thread_info *stopped, ptid_t ptid)
|
||||
thread_db_err_str (err));
|
||||
|
||||
/* Fill the cache. */
|
||||
tp = find_thread_ptid (ptid);
|
||||
tp = find_thread_ptid (stopped->inf->process_target (), ptid);
|
||||
return record_thread (info, tp, ptid, &th, &ti);
|
||||
}
|
||||
|
||||
@ -434,12 +438,12 @@ thread_db_notice_clone (ptid_t parent, ptid_t child)
|
||||
{
|
||||
struct thread_db_info *info;
|
||||
|
||||
info = get_thread_db_info (child.pid ());
|
||||
info = get_thread_db_info (linux_target, child.pid ());
|
||||
|
||||
if (info == NULL)
|
||||
return 0;
|
||||
|
||||
thread_info *stopped = find_thread_ptid (parent);
|
||||
thread_info *stopped = find_thread_ptid (linux_target, parent);
|
||||
|
||||
thread_from_lwp (stopped, child);
|
||||
|
||||
@ -684,13 +688,13 @@ check_thread_db_callback (const td_thrhandle_t *th, void *arg)
|
||||
to how GDB accesses TLS could result in this passing
|
||||
without exercising the calls it's supposed to. */
|
||||
ptid_t ptid = ptid_t (tdb_testinfo->info->pid, ti.ti_lid, 0);
|
||||
struct thread_info *thread_info = find_thread_ptid (ptid);
|
||||
thread_info *thread_info = find_thread_ptid (linux_target, ptid);
|
||||
if (thread_info != NULL && thread_info->priv != NULL)
|
||||
{
|
||||
LOG ("; errno");
|
||||
|
||||
scoped_restore_current_thread restore_current_thread;
|
||||
switch_to_thread (ptid);
|
||||
switch_to_thread (thread_info);
|
||||
|
||||
expression_up expr = parse_expression ("(int) errno");
|
||||
struct value *val = evaluate_expression (expr.get ());
|
||||
@ -940,10 +944,8 @@ try_thread_db_load_1 (struct thread_db_info *info)
|
||||
}
|
||||
|
||||
/* The thread library was detected. Activate the thread_db target
|
||||
if this is the first process using it. */
|
||||
if (thread_db_list->next == NULL)
|
||||
for this process. */
|
||||
push_target (&the_thread_db_target);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1013,7 +1015,8 @@ try_thread_db_load (const char *library, bool check_auto_load_safe)
|
||||
return true;
|
||||
|
||||
/* This library "refused" to work on current inferior. */
|
||||
delete_thread_db_info (inferior_ptid.pid ());
|
||||
delete_thread_db_info (current_inferior ()->process_target (),
|
||||
inferior_ptid.pid ());
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1182,7 +1185,8 @@ thread_db_load (void)
|
||||
{
|
||||
struct thread_db_info *info;
|
||||
|
||||
info = get_thread_db_info (inferior_ptid.pid ());
|
||||
info = get_thread_db_info (current_inferior ()->process_target (),
|
||||
inferior_ptid.pid ());
|
||||
|
||||
if (info != NULL)
|
||||
return true;
|
||||
@ -1349,7 +1353,7 @@ record_thread (struct thread_db_info *info,
|
||||
thread with this PTID, but it's marked exited, then the kernel
|
||||
reused the tid of an old thread. */
|
||||
if (tp == NULL || tp->state == THREAD_EXITED)
|
||||
tp = add_thread_with_info (ptid, priv);
|
||||
tp = add_thread_with_info (info->process_target, ptid, priv);
|
||||
else
|
||||
tp->priv.reset (priv);
|
||||
|
||||
@ -1362,15 +1366,13 @@ record_thread (struct thread_db_info *info,
|
||||
void
|
||||
thread_db_target::detach (inferior *inf, int from_tty)
|
||||
{
|
||||
delete_thread_db_info (inf->pid);
|
||||
delete_thread_db_info (inf->process_target (), inf->pid);
|
||||
|
||||
beneath ()->detach (inf, from_tty);
|
||||
|
||||
/* NOTE: From this point on, inferior_ptid is null_ptid. */
|
||||
|
||||
/* If there are no more processes using libpthread, detach the
|
||||
thread_db target ops. */
|
||||
if (!thread_db_list)
|
||||
/* Detach the thread_db target from this inferior. */
|
||||
unpush_target (this);
|
||||
}
|
||||
|
||||
@ -1380,7 +1382,10 @@ thread_db_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
|
||||
{
|
||||
struct thread_db_info *info;
|
||||
|
||||
ptid = beneath ()->wait (ptid, ourstatus, options);
|
||||
process_stratum_target *beneath
|
||||
= as_process_stratum_target (this->beneath ());
|
||||
|
||||
ptid = beneath->wait (ptid, ourstatus, options);
|
||||
|
||||
switch (ourstatus->kind)
|
||||
{
|
||||
@ -1391,7 +1396,7 @@ thread_db_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
|
||||
return ptid;
|
||||
}
|
||||
|
||||
info = get_thread_db_info (ptid.pid ());
|
||||
info = get_thread_db_info (beneath, ptid.pid ());
|
||||
|
||||
/* If this process isn't using thread_db, we're done. */
|
||||
if (info == NULL)
|
||||
@ -1401,15 +1406,14 @@ thread_db_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
|
||||
{
|
||||
/* New image, it may or may not end up using thread_db. Assume
|
||||
not unless we find otherwise. */
|
||||
delete_thread_db_info (ptid.pid ());
|
||||
if (!thread_db_list)
|
||||
unpush_target (&the_thread_db_target);
|
||||
delete_thread_db_info (beneath, ptid.pid ());
|
||||
unpush_target (this);
|
||||
|
||||
return ptid;
|
||||
}
|
||||
|
||||
/* Fill in the thread's user-level thread id and status. */
|
||||
thread_from_lwp (find_thread_ptid (ptid), ptid);
|
||||
thread_from_lwp (find_thread_ptid (beneath, ptid), ptid);
|
||||
|
||||
return ptid;
|
||||
}
|
||||
@ -1417,13 +1421,15 @@ thread_db_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
|
||||
void
|
||||
thread_db_target::mourn_inferior ()
|
||||
{
|
||||
delete_thread_db_info (inferior_ptid.pid ());
|
||||
process_stratum_target *target_beneath
|
||||
= as_process_stratum_target (this->beneath ());
|
||||
|
||||
beneath ()->mourn_inferior ();
|
||||
delete_thread_db_info (target_beneath, inferior_ptid.pid ());
|
||||
|
||||
/* Detach thread_db target ops. */
|
||||
if (!thread_db_list)
|
||||
unpush_target (&the_thread_db_target);
|
||||
target_beneath->mourn_inferior ();
|
||||
|
||||
/* Detach the thread_db target from this inferior. */
|
||||
unpush_target (this);
|
||||
}
|
||||
|
||||
struct callback_data
|
||||
@ -1488,7 +1494,7 @@ find_new_threads_callback (const td_thrhandle_t *th_p, void *data)
|
||||
}
|
||||
|
||||
ptid_t ptid (info->pid, ti.ti_lid);
|
||||
tp = find_thread_ptid (ptid);
|
||||
tp = find_thread_ptid (info->process_target, ptid);
|
||||
if (tp == NULL || tp->priv == NULL)
|
||||
record_thread (info, tp, ptid, th_p, &ti);
|
||||
|
||||
@ -1555,7 +1561,8 @@ thread_db_find_new_threads_2 (thread_info *stopped, bool until_no_new)
|
||||
struct thread_db_info *info;
|
||||
int i, loop;
|
||||
|
||||
info = get_thread_db_info (stopped->ptid.pid ());
|
||||
info = get_thread_db_info (stopped->inf->process_target (),
|
||||
stopped->ptid.pid ());
|
||||
|
||||
/* Access an lwp we know is stopped. */
|
||||
info->proc_handle.thread = stopped;
|
||||
@ -1598,16 +1605,14 @@ thread_db_target::update_thread_list ()
|
||||
|
||||
for (inferior *inf : all_inferiors ())
|
||||
{
|
||||
struct thread_info *thread;
|
||||
|
||||
if (inf->pid == 0)
|
||||
continue;
|
||||
|
||||
info = get_thread_db_info (inf->pid);
|
||||
info = get_thread_db_info (inf->process_target (), inf->pid);
|
||||
if (info == NULL)
|
||||
continue;
|
||||
|
||||
thread = any_live_thread_of_inferior (inf);
|
||||
thread_info *thread = any_live_thread_of_inferior (inf);
|
||||
if (thread == NULL || thread->executing)
|
||||
continue;
|
||||
|
||||
@ -1635,7 +1640,7 @@ thread_db_target::update_thread_list ()
|
||||
std::string
|
||||
thread_db_target::pid_to_str (ptid_t ptid)
|
||||
{
|
||||
struct thread_info *thread_info = find_thread_ptid (ptid);
|
||||
thread_info *thread_info = find_thread_ptid (current_inferior (), ptid);
|
||||
|
||||
if (thread_info != NULL && thread_info->priv != NULL)
|
||||
{
|
||||
@ -1728,9 +1733,10 @@ thread_db_target::get_thread_local_address (ptid_t ptid,
|
||||
CORE_ADDR offset)
|
||||
{
|
||||
struct thread_info *thread_info;
|
||||
|
||||
process_stratum_target *beneath
|
||||
= as_process_stratum_target (this->beneath ());
|
||||
/* Find the matching thread. */
|
||||
thread_info = find_thread_ptid (ptid);
|
||||
thread_info = find_thread_ptid (beneath, ptid);
|
||||
|
||||
/* We may not have discovered the thread yet. */
|
||||
if (thread_info != NULL && thread_info->priv == NULL)
|
||||
@ -1740,7 +1746,7 @@ thread_db_target::get_thread_local_address (ptid_t ptid,
|
||||
{
|
||||
td_err_e err;
|
||||
psaddr_t address;
|
||||
thread_db_info *info = get_thread_db_info (ptid.pid ());
|
||||
thread_db_info *info = get_thread_db_info (beneath, ptid.pid ());
|
||||
thread_db_thread_info *priv = get_thread_db_thread_info (thread_info);
|
||||
|
||||
/* Finally, get the address of the variable. */
|
||||
@ -1799,7 +1805,7 @@ thread_db_target::get_thread_local_address (ptid_t ptid,
|
||||
: (CORE_ADDR) (uintptr_t) address);
|
||||
}
|
||||
|
||||
return beneath ()->get_thread_local_address (ptid, lm, offset);
|
||||
return beneath->get_thread_local_address (ptid, lm, offset);
|
||||
}
|
||||
|
||||
/* Implement the to_get_ada_task_ptid target method for this target. */
|
||||
@ -1814,12 +1820,13 @@ thread_db_target::get_ada_task_ptid (long lwp, long thread)
|
||||
void
|
||||
thread_db_target::resume (ptid_t ptid, int step, enum gdb_signal signo)
|
||||
{
|
||||
struct thread_db_info *info;
|
||||
process_stratum_target *beneath
|
||||
= as_process_stratum_target (this->beneath ());
|
||||
|
||||
if (ptid == minus_one_ptid)
|
||||
info = get_thread_db_info (inferior_ptid.pid ());
|
||||
else
|
||||
info = get_thread_db_info (ptid.pid ());
|
||||
thread_db_info *info
|
||||
= get_thread_db_info (beneath, (ptid == minus_one_ptid
|
||||
? inferior_ptid.pid ()
|
||||
: ptid.pid ()));
|
||||
|
||||
/* This workaround is only needed for child fork lwps stopped in a
|
||||
PTRACE_O_TRACEFORK event. When the inferior is resumed, the
|
||||
@ -1827,7 +1834,7 @@ thread_db_target::resume (ptid_t ptid, int step, enum gdb_signal signo)
|
||||
if (info)
|
||||
info->need_stale_parent_threads_check = 0;
|
||||
|
||||
beneath ()->resume (ptid, step, signo);
|
||||
beneath->resume (ptid, step, signo);
|
||||
}
|
||||
|
||||
/* std::sort helper function for info_auto_load_libthread_db, sort the
|
||||
@ -1953,7 +1960,8 @@ maintenance_check_libthread_db (const char *args, int from_tty)
|
||||
if (inferior_pid == 0)
|
||||
error (_("No inferior running"));
|
||||
|
||||
info = get_thread_db_info (inferior_pid);
|
||||
info = get_thread_db_info (current_inferior ()->process_target (),
|
||||
inferior_pid);
|
||||
if (info == NULL)
|
||||
error (_("No libthread_db loaded"));
|
||||
|
||||
|
@ -961,7 +961,8 @@ multiple_inferiors_p ()
|
||||
}
|
||||
|
||||
static void
|
||||
mi_on_resume_1 (struct mi_interp *mi, ptid_t ptid)
|
||||
mi_on_resume_1 (struct mi_interp *mi,
|
||||
process_stratum_target *targ, ptid_t ptid)
|
||||
{
|
||||
/* To cater for older frontends, emit ^running, but do it only once
|
||||
per each command. We do it here, since at this point we know
|
||||
@ -984,7 +985,7 @@ mi_on_resume_1 (struct mi_interp *mi, ptid_t ptid)
|
||||
&& !multiple_inferiors_p ())
|
||||
fprintf_unfiltered (mi->raw_stdout, "*running,thread-id=\"all\"\n");
|
||||
else
|
||||
for (thread_info *tp : all_non_exited_threads (ptid))
|
||||
for (thread_info *tp : all_non_exited_threads (targ, ptid))
|
||||
mi_output_running (tp);
|
||||
|
||||
if (!running_result_record_printed && mi_proceeded)
|
||||
@ -1004,10 +1005,11 @@ mi_on_resume (ptid_t ptid)
|
||||
{
|
||||
struct thread_info *tp = NULL;
|
||||
|
||||
process_stratum_target *target = current_inferior ()->process_target ();
|
||||
if (ptid == minus_one_ptid || ptid.is_pid ())
|
||||
tp = inferior_thread ();
|
||||
else
|
||||
tp = find_thread_ptid (ptid);
|
||||
tp = find_thread_ptid (target, ptid);
|
||||
|
||||
/* Suppress output while calling an inferior function. */
|
||||
if (tp->control.in_infcall)
|
||||
@ -1023,7 +1025,7 @@ mi_on_resume (ptid_t ptid)
|
||||
target_terminal::scoped_restore_terminal_state term_state;
|
||||
target_terminal::ours_for_output ();
|
||||
|
||||
mi_on_resume_1 (mi, ptid);
|
||||
mi_on_resume_1 (mi, target, ptid);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -450,7 +450,7 @@ fork_inferior (const char *exec_file_arg, const std::string &allargs,
|
||||
/* See nat/fork-inferior.h. */
|
||||
|
||||
ptid_t
|
||||
startup_inferior (pid_t pid, int ntraps,
|
||||
startup_inferior (process_stratum_target *proc_target, pid_t pid, int ntraps,
|
||||
struct target_waitstatus *last_waitstatus,
|
||||
ptid_t *last_ptid)
|
||||
{
|
||||
@ -502,7 +502,7 @@ startup_inferior (pid_t pid, int ntraps,
|
||||
case TARGET_WAITKIND_SYSCALL_ENTRY:
|
||||
case TARGET_WAITKIND_SYSCALL_RETURN:
|
||||
/* Ignore gracefully during startup of the inferior. */
|
||||
switch_to_thread (event_ptid);
|
||||
switch_to_thread (proc_target, event_ptid);
|
||||
break;
|
||||
|
||||
case TARGET_WAITKIND_SIGNALLED:
|
||||
@ -527,12 +527,12 @@ startup_inferior (pid_t pid, int ntraps,
|
||||
/* Handle EXEC signals as if they were SIGTRAP signals. */
|
||||
xfree (ws.value.execd_pathname);
|
||||
resume_signal = GDB_SIGNAL_TRAP;
|
||||
switch_to_thread (event_ptid);
|
||||
switch_to_thread (proc_target, event_ptid);
|
||||
break;
|
||||
|
||||
case TARGET_WAITKIND_STOPPED:
|
||||
resume_signal = ws.value.sig;
|
||||
switch_to_thread (event_ptid);
|
||||
switch_to_thread (proc_target, event_ptid);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,8 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
struct process_stratum_target;
|
||||
|
||||
/* Number of traps that happen between exec'ing the shell to run an
|
||||
inferior and when we finally get to the inferior code, not counting
|
||||
the exec for the shell. This is 1 on all supported
|
||||
@ -50,7 +52,8 @@ extern pid_t fork_inferior (const char *exec_file_arg,
|
||||
/* Accept NTRAPS traps from the inferior.
|
||||
|
||||
Return the ptid of the inferior being started. */
|
||||
extern ptid_t startup_inferior (pid_t pid, int ntraps,
|
||||
extern ptid_t startup_inferior (process_stratum_target *proc_target,
|
||||
pid_t pid, int ntraps,
|
||||
struct target_waitstatus *mystatus,
|
||||
ptid_t *myptid);
|
||||
|
||||
|
@ -409,7 +409,7 @@ nto_procfs_target::update_thread_list ()
|
||||
(e.g. thread exited). */
|
||||
continue;
|
||||
ptid = ptid_t (pid, 0, tid);
|
||||
new_thread = find_thread_ptid (ptid);
|
||||
new_thread = find_thread_ptid (this, ptid);
|
||||
if (!new_thread)
|
||||
new_thread = add_thread (ptid);
|
||||
update_thread_private_data (new_thread, tid, status.state, 0);
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "ppc-fbsd-tdep.h"
|
||||
#include "fbsd-tdep.h"
|
||||
#include "solib-svr4.h"
|
||||
#include "inferior.h"
|
||||
|
||||
|
||||
/* 32-bit regset descriptions. */
|
||||
@ -289,7 +290,8 @@ ppcfbsd_get_thread_local_address (struct gdbarch *gdbarch, ptid_t ptid,
|
||||
struct regcache *regcache;
|
||||
int tp_offset, tp_regnum;
|
||||
|
||||
regcache = get_thread_arch_regcache (ptid, gdbarch);
|
||||
regcache = get_thread_arch_regcache (current_inferior ()->process_target (),
|
||||
ptid, gdbarch);
|
||||
|
||||
if (tdep->wordsize == 4)
|
||||
{
|
||||
|
@ -70,17 +70,22 @@ static ps_err_e
|
||||
ps_xfer_memory (const struct ps_prochandle *ph, psaddr_t addr,
|
||||
gdb_byte *buf, size_t len, int write)
|
||||
{
|
||||
scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
|
||||
int ret;
|
||||
CORE_ADDR core_addr = ps_addr_to_core_addr (addr);
|
||||
scoped_restore_current_inferior restore_inferior;
|
||||
set_current_inferior (ph->thread->inf);
|
||||
|
||||
scoped_restore_current_program_space restore_current_progspace;
|
||||
set_current_program_space (ph->thread->inf->pspace);
|
||||
|
||||
scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
|
||||
inferior_ptid = ph->thread->ptid;
|
||||
|
||||
CORE_ADDR core_addr = ps_addr_to_core_addr (addr);
|
||||
|
||||
int ret;
|
||||
if (write)
|
||||
ret = target_write_memory (core_addr, buf, len);
|
||||
else
|
||||
ret = target_read_memory (core_addr, buf, len);
|
||||
|
||||
return (ret == 0 ? PS_OK : PS_ERR);
|
||||
}
|
||||
|
||||
@ -135,7 +140,9 @@ static struct regcache *
|
||||
get_ps_regcache (struct ps_prochandle *ph, lwpid_t lwpid)
|
||||
{
|
||||
inferior *inf = ph->thread->inf;
|
||||
return get_thread_arch_regcache (ptid_t (inf->pid, lwpid), inf->gdbarch);
|
||||
return get_thread_arch_regcache (inf->process_target (),
|
||||
ptid_t (inf->pid, lwpid),
|
||||
inf->gdbarch);
|
||||
}
|
||||
|
||||
/* Get the general registers of LWP LWPID within the target process PH
|
||||
|
@ -29,7 +29,7 @@ struct address_space *
|
||||
process_stratum_target::thread_address_space (ptid_t ptid)
|
||||
{
|
||||
/* Fall-back to the "main" address space of the inferior. */
|
||||
inferior *inf = find_inferior_ptid (ptid);
|
||||
inferior *inf = find_inferior_ptid (this, ptid);
|
||||
|
||||
if (inf == NULL || inf->aspace == NULL)
|
||||
internal_error (__FILE__, __LINE__,
|
||||
@ -43,7 +43,7 @@ process_stratum_target::thread_address_space (ptid_t ptid)
|
||||
struct gdbarch *
|
||||
process_stratum_target::thread_architecture (ptid_t ptid)
|
||||
{
|
||||
inferior *inf = find_inferior_ptid (ptid);
|
||||
inferior *inf = find_inferior_ptid (this, ptid);
|
||||
gdb_assert (inf != NULL);
|
||||
return inf->gdbarch;
|
||||
}
|
||||
|
@ -51,6 +51,22 @@ public:
|
||||
bool has_stack () override;
|
||||
bool has_registers () override;
|
||||
bool has_execution (inferior *inf) override;
|
||||
|
||||
/* True if any thread is, or may be executing. We need to track
|
||||
this separately because until we fully sync the thread list, we
|
||||
won't know whether the target is fully stopped, even if we see
|
||||
stop events for all known threads, because any of those threads
|
||||
may have spawned new threads we haven't heard of yet. */
|
||||
bool threads_executing = false;
|
||||
};
|
||||
|
||||
/* Downcast TARGET to process_stratum_target. */
|
||||
|
||||
static inline process_stratum_target *
|
||||
as_process_stratum_target (target_ops *target)
|
||||
{
|
||||
gdb_assert (target->stratum () == process_stratum);
|
||||
return static_cast<process_stratum_target *> (target);
|
||||
}
|
||||
|
||||
#endif /* !defined (PROCESS_STRATUM_TARGET_H) */
|
||||
|
49
gdb/procfs.c
49
gdb/procfs.c
@ -160,6 +160,8 @@ public:
|
||||
|
||||
int can_use_hw_breakpoint (enum bptype, int, int) override;
|
||||
bool stopped_data_address (CORE_ADDR *) override;
|
||||
|
||||
void procfs_init_inferior (int pid);
|
||||
};
|
||||
|
||||
static procfs_target the_procfs_target;
|
||||
@ -1315,6 +1317,7 @@ proc_set_current_signal (procinfo *pi, int signo)
|
||||
char sinfo[sizeof (siginfo_t)];
|
||||
} arg;
|
||||
siginfo_t mysinfo;
|
||||
process_stratum_target *wait_target;
|
||||
ptid_t wait_ptid;
|
||||
struct target_waitstatus wait_status;
|
||||
|
||||
@ -1327,8 +1330,9 @@ proc_set_current_signal (procinfo *pi, int signo)
|
||||
pi = find_procinfo_or_die (pi->pid, 0);
|
||||
|
||||
/* The pointer is just a type alias. */
|
||||
get_last_target_status (&wait_ptid, &wait_status);
|
||||
if (wait_ptid == inferior_ptid
|
||||
get_last_target_status (&wait_target, &wait_ptid, &wait_status);
|
||||
if (wait_target == &the_procfs_target
|
||||
&& wait_ptid == inferior_ptid
|
||||
&& wait_status.kind == TARGET_WAITKIND_STOPPED
|
||||
&& wait_status.value.sig == gdb_signal_from_host (signo)
|
||||
&& proc_get_status (pi)
|
||||
@ -1987,7 +1991,7 @@ do_attach (ptid_t ptid)
|
||||
|
||||
/* Add it to gdb's thread list. */
|
||||
ptid = ptid_t (pi->pid, lwpid, 0);
|
||||
add_thread (ptid);
|
||||
add_thread (&the_procfs_target, ptid);
|
||||
|
||||
return ptid;
|
||||
}
|
||||
@ -2285,7 +2289,7 @@ wait_again:
|
||||
if (print_thread_events)
|
||||
printf_unfiltered (_("[%s exited]\n"),
|
||||
target_pid_to_str (retval).c_str ());
|
||||
delete_thread (find_thread_ptid (retval));
|
||||
delete_thread (find_thread_ptid (this, retval));
|
||||
status->kind = TARGET_WAITKIND_SPURIOUS;
|
||||
return retval;
|
||||
}
|
||||
@ -2307,7 +2311,7 @@ wait_again:
|
||||
if (!proc_run_process (pi, 0, 0))
|
||||
proc_error (pi, "target_wait, run_process", __LINE__);
|
||||
|
||||
inf = find_inferior_pid (pi->pid);
|
||||
inf = find_inferior_pid (this, pi->pid);
|
||||
if (inf->attach_flag)
|
||||
{
|
||||
/* Don't call wait: simulate waiting for exit,
|
||||
@ -2394,8 +2398,8 @@ wait_again:
|
||||
|
||||
temp_ptid = ptid_t (pi->pid, temp_tid, 0);
|
||||
/* If not in GDB's thread list, add it. */
|
||||
if (!in_thread_list (temp_ptid))
|
||||
add_thread (temp_ptid);
|
||||
if (!in_thread_list (this, temp_ptid))
|
||||
add_thread (this, temp_ptid);
|
||||
|
||||
/* Return to WFI, but tell it to immediately resume. */
|
||||
status->kind = TARGET_WAITKIND_SPURIOUS;
|
||||
@ -2406,7 +2410,7 @@ wait_again:
|
||||
if (print_thread_events)
|
||||
printf_unfiltered (_("[%s exited]\n"),
|
||||
target_pid_to_str (retval).c_str ());
|
||||
delete_thread (find_thread_ptid (retval));
|
||||
delete_thread (find_thread_ptid (this, retval));
|
||||
status->kind = TARGET_WAITKIND_SPURIOUS;
|
||||
return retval;
|
||||
}
|
||||
@ -2463,8 +2467,8 @@ wait_again:
|
||||
|
||||
/* If not in GDB's thread list, add it. */
|
||||
temp_ptid = ptid_t (pi->pid, temp_tid, 0);
|
||||
if (!in_thread_list (temp_ptid))
|
||||
add_thread (temp_ptid);
|
||||
if (!in_thread_list (this, temp_ptid))
|
||||
add_thread (this, temp_ptid);
|
||||
|
||||
status->kind = TARGET_WAITKIND_STOPPED;
|
||||
status->value.sig = GDB_SIGNAL_0;
|
||||
@ -2492,12 +2496,12 @@ wait_again:
|
||||
threads database, add it. */
|
||||
if (retval.pid () > 0
|
||||
&& retval != inferior_ptid
|
||||
&& !in_thread_list (retval))
|
||||
&& !in_thread_list (this, retval))
|
||||
{
|
||||
/* We have a new thread. We need to add it both to
|
||||
GDB's list and to our own. If we don't create a
|
||||
procinfo, resume may be unhappy later. */
|
||||
add_thread (retval);
|
||||
add_thread (this, retval);
|
||||
if (find_procinfo (retval.pid (),
|
||||
retval.lwp ()) == NULL)
|
||||
create_procinfo (retval.pid (),
|
||||
@ -2850,8 +2854,8 @@ procfs_target::mourn_inferior ()
|
||||
whatever is necessary to make the child ready to be debugged, and
|
||||
then wait for the child to synchronize. */
|
||||
|
||||
static void
|
||||
procfs_init_inferior (struct target_ops *ops, int pid)
|
||||
void
|
||||
procfs_target::procfs_init_inferior (int pid)
|
||||
{
|
||||
procinfo *pi;
|
||||
int fail;
|
||||
@ -2859,8 +2863,8 @@ procfs_init_inferior (struct target_ops *ops, int pid)
|
||||
|
||||
/* This routine called on the parent side (GDB side)
|
||||
after GDB forks the inferior. */
|
||||
if (!target_is_pushed (ops))
|
||||
push_target (ops);
|
||||
if (!target_is_pushed (this))
|
||||
push_target (this);
|
||||
|
||||
pi = create_procinfo (pid, 0);
|
||||
if (pi == NULL)
|
||||
@ -2921,8 +2925,7 @@ procfs_init_inferior (struct target_ops *ops, int pid)
|
||||
/* We already have a main thread registered in the thread table at
|
||||
this point, but it didn't have any lwp info yet. Notify the core
|
||||
about it. This changes inferior_ptid as well. */
|
||||
thread_change_ptid (ptid_t (pid),
|
||||
ptid_t (pid, lwpid, 0));
|
||||
thread_change_ptid (this, ptid_t (pid), ptid_t (pid, lwpid, 0));
|
||||
|
||||
gdb_startup_inferior (pid, START_INFERIOR_TRAPS_EXPECTED);
|
||||
}
|
||||
@ -3089,9 +3092,9 @@ procfs_target::create_inferior (const char *exec_file,
|
||||
/* We have something that executes now. We'll be running through
|
||||
the shell at this point (if startup-with-shell is true), but the
|
||||
pid shouldn't change. */
|
||||
add_thread_silent (ptid_t (pid));
|
||||
add_thread_silent (this, ptid_t (pid));
|
||||
|
||||
procfs_init_inferior (this, pid);
|
||||
procfs_init_inferior (pid);
|
||||
}
|
||||
|
||||
/* An observer for the "inferior_created" event. */
|
||||
@ -3108,9 +3111,9 @@ procfs_notice_thread (procinfo *pi, procinfo *thread, void *ptr)
|
||||
{
|
||||
ptid_t gdb_threadid = ptid_t (pi->pid, thread->tid, 0);
|
||||
|
||||
thread_info *thr = find_thread_ptid (gdb_threadid);
|
||||
thread_info *thr = find_thread_ptid (&the_procfs_target, gdb_threadid);
|
||||
if (thr == NULL || thr->state == THREAD_EXITED)
|
||||
add_thread (gdb_threadid);
|
||||
add_thread (&the_procfs_target, gdb_threadid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -3739,7 +3742,7 @@ procfs_do_thread_registers (bfd *obfd, ptid_t ptid,
|
||||
char *note_data, int *note_size,
|
||||
enum gdb_signal stop_signal)
|
||||
{
|
||||
struct regcache *regcache = get_thread_regcache (ptid);
|
||||
struct regcache *regcache = get_thread_regcache (&the_procfs_target, ptid);
|
||||
gdb_gregset_t gregs;
|
||||
gdb_fpregset_t fpregs;
|
||||
unsigned long merged_pid;
|
||||
|
@ -27,7 +27,9 @@ py_get_event_thread (ptid_t ptid)
|
||||
{
|
||||
if (non_stop)
|
||||
{
|
||||
thread_info *thread = find_thread_ptid (ptid);
|
||||
thread_info *thread
|
||||
= find_thread_ptid (current_inferior ()->process_target (),
|
||||
ptid);
|
||||
if (thread != nullptr)
|
||||
return thread_to_thread_object (thread);
|
||||
PyErr_SetString (PyExc_RuntimeError, "Could not find event thread");
|
||||
|
@ -219,6 +219,9 @@ get_base_thread_from_ravenscar_task (ptid_t ptid)
|
||||
void
|
||||
ravenscar_thread_target::update_inferior_ptid ()
|
||||
{
|
||||
process_stratum_target *proc_target
|
||||
= as_process_stratum_target (this->beneath ());
|
||||
|
||||
int base_cpu;
|
||||
|
||||
m_base_ptid = inferior_ptid;
|
||||
@ -239,8 +242,8 @@ ravenscar_thread_target::update_inferior_ptid ()
|
||||
/* The running thread may not have been added to
|
||||
system.tasking.debug's list yet; so ravenscar_update_thread_list
|
||||
may not always add it to the thread list. Add it here. */
|
||||
if (!find_thread_ptid (inferior_ptid))
|
||||
add_thread (inferior_ptid);
|
||||
if (!find_thread_ptid (proc_target, inferior_ptid))
|
||||
add_thread (proc_target, inferior_ptid);
|
||||
}
|
||||
|
||||
/* The Ravenscar Runtime exports a symbol which contains the ID of
|
||||
@ -336,12 +339,14 @@ ravenscar_thread_target::wait (ptid_t ptid,
|
||||
struct target_waitstatus *status,
|
||||
int options)
|
||||
{
|
||||
process_stratum_target *beneath
|
||||
= as_process_stratum_target (this->beneath ());
|
||||
ptid_t event_ptid;
|
||||
|
||||
inferior_ptid = m_base_ptid;
|
||||
if (ptid != minus_one_ptid)
|
||||
ptid = m_base_ptid;
|
||||
event_ptid = beneath ()->wait (ptid, status, 0);
|
||||
event_ptid = beneath->wait (ptid, status, 0);
|
||||
/* Find any new threads that might have been created, and update
|
||||
inferior_ptid to the active thread.
|
||||
|
||||
@ -367,8 +372,8 @@ ravenscar_thread_target::wait (ptid_t ptid,
|
||||
static void
|
||||
ravenscar_add_thread (struct ada_task_info *task)
|
||||
{
|
||||
if (find_thread_ptid (task->ptid) == NULL)
|
||||
add_thread (task->ptid);
|
||||
if (find_thread_ptid (current_inferior (), task->ptid) == NULL)
|
||||
add_thread (current_inferior ()->process_target (), task->ptid);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -556,10 +556,11 @@ record_btrace_target::info_record ()
|
||||
|
||||
DEBUG ("info");
|
||||
|
||||
tp = find_thread_ptid (inferior_ptid);
|
||||
if (tp == NULL)
|
||||
if (inferior_ptid == null_ptid)
|
||||
error (_("No thread."));
|
||||
|
||||
tp = inferior_thread ();
|
||||
|
||||
validate_registers_access ();
|
||||
|
||||
btinfo = &tp->btrace;
|
||||
@ -1373,7 +1374,8 @@ record_btrace_target::call_history_from (ULONGEST from, int size,
|
||||
enum record_method
|
||||
record_btrace_target::record_method (ptid_t ptid)
|
||||
{
|
||||
struct thread_info * const tp = find_thread_ptid (ptid);
|
||||
process_stratum_target *proc_target = current_inferior ()->process_target ();
|
||||
thread_info *const tp = find_thread_ptid (proc_target, ptid);
|
||||
|
||||
if (tp == NULL)
|
||||
error (_("No thread."));
|
||||
@ -1389,7 +1391,8 @@ record_btrace_target::record_method (ptid_t ptid)
|
||||
bool
|
||||
record_btrace_target::record_is_replaying (ptid_t ptid)
|
||||
{
|
||||
for (thread_info *tp : all_non_exited_threads (ptid))
|
||||
process_stratum_target *proc_target = current_inferior ()->process_target ();
|
||||
for (thread_info *tp : all_non_exited_threads (proc_target, ptid))
|
||||
if (btrace_is_replaying (tp))
|
||||
return true;
|
||||
|
||||
@ -1519,13 +1522,10 @@ record_btrace_target::remove_breakpoint (struct gdbarch *gdbarch,
|
||||
void
|
||||
record_btrace_target::fetch_registers (struct regcache *regcache, int regno)
|
||||
{
|
||||
struct btrace_insn_iterator *replay;
|
||||
struct thread_info *tp;
|
||||
|
||||
tp = find_thread_ptid (regcache->ptid ());
|
||||
thread_info *tp = find_thread_ptid (regcache->target (), regcache->ptid ());
|
||||
gdb_assert (tp != NULL);
|
||||
|
||||
replay = tp->btrace.replay;
|
||||
btrace_insn_iterator *replay = tp->btrace.replay;
|
||||
if (replay != NULL && !record_btrace_generating_corefile)
|
||||
{
|
||||
const struct btrace_insn *insn;
|
||||
@ -1966,6 +1966,8 @@ get_thread_current_frame_id (struct thread_info *tp)
|
||||
|
||||
switch_to_thread (tp);
|
||||
|
||||
process_stratum_target *proc_target = tp->inf->process_target ();
|
||||
|
||||
/* Clear the executing flag to allow changes to the current frame.
|
||||
We are not actually running, yet. We just started a reverse execution
|
||||
command or a record goto command.
|
||||
@ -1974,7 +1976,7 @@ get_thread_current_frame_id (struct thread_info *tp)
|
||||
move the thread. Since we need to recompute the stack, we temporarily
|
||||
set EXECUTING to false. */
|
||||
executing = tp->executing;
|
||||
set_executing (inferior_ptid, false);
|
||||
set_executing (proc_target, inferior_ptid, false);
|
||||
|
||||
id = null_frame_id;
|
||||
try
|
||||
@ -1984,13 +1986,13 @@ get_thread_current_frame_id (struct thread_info *tp)
|
||||
catch (const gdb_exception &except)
|
||||
{
|
||||
/* Restore the previous execution state. */
|
||||
set_executing (inferior_ptid, executing);
|
||||
set_executing (proc_target, inferior_ptid, executing);
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
/* Restore the previous execution state. */
|
||||
set_executing (inferior_ptid, executing);
|
||||
set_executing (proc_target, inferior_ptid, executing);
|
||||
|
||||
return id;
|
||||
}
|
||||
@ -2154,11 +2156,14 @@ record_btrace_target::resume (ptid_t ptid, int step, enum gdb_signal signal)
|
||||
record_btrace_wait below.
|
||||
|
||||
For all-stop targets, we only step INFERIOR_PTID and continue others. */
|
||||
|
||||
process_stratum_target *proc_target = current_inferior ()->process_target ();
|
||||
|
||||
if (!target_is_non_stop_p ())
|
||||
{
|
||||
gdb_assert (inferior_ptid.matches (ptid));
|
||||
|
||||
for (thread_info *tp : all_non_exited_threads (ptid))
|
||||
for (thread_info *tp : all_non_exited_threads (proc_target, ptid))
|
||||
{
|
||||
if (tp->ptid.matches (inferior_ptid))
|
||||
record_btrace_resume_thread (tp, flag);
|
||||
@ -2168,7 +2173,7 @@ record_btrace_target::resume (ptid_t ptid, int step, enum gdb_signal signal)
|
||||
}
|
||||
else
|
||||
{
|
||||
for (thread_info *tp : all_non_exited_threads (ptid))
|
||||
for (thread_info *tp : all_non_exited_threads (proc_target, ptid))
|
||||
record_btrace_resume_thread (tp, flag);
|
||||
}
|
||||
|
||||
@ -2526,7 +2531,8 @@ record_btrace_target::wait (ptid_t ptid, struct target_waitstatus *status,
|
||||
}
|
||||
|
||||
/* Keep a work list of moving threads. */
|
||||
for (thread_info *tp : all_non_exited_threads (ptid))
|
||||
process_stratum_target *proc_target = current_inferior ()->process_target ();
|
||||
for (thread_info *tp : all_non_exited_threads (proc_target, ptid))
|
||||
if ((tp->btrace.flags & (BTHR_MOVE | BTHR_STOP)) != 0)
|
||||
moving.push_back (tp);
|
||||
|
||||
@ -2646,7 +2652,10 @@ record_btrace_target::stop (ptid_t ptid)
|
||||
}
|
||||
else
|
||||
{
|
||||
for (thread_info *tp : all_non_exited_threads (ptid))
|
||||
process_stratum_target *proc_target
|
||||
= current_inferior ()->process_target ();
|
||||
|
||||
for (thread_info *tp : all_non_exited_threads (proc_target, ptid))
|
||||
{
|
||||
tp->btrace.flags &= ~BTHR_MOVE;
|
||||
tp->btrace.flags |= BTHR_STOP;
|
||||
|
@ -1228,6 +1228,8 @@ record_full_wait_1 (struct target_ops *ops,
|
||||
interested in the event. */
|
||||
|
||||
registers_changed ();
|
||||
switch_to_thread (current_inferior ()->process_target (),
|
||||
ret);
|
||||
regcache = get_current_regcache ();
|
||||
tmp_pc = regcache_read_pc (regcache);
|
||||
const struct address_space *aspace = regcache->aspace ();
|
||||
@ -1260,14 +1262,17 @@ record_full_wait_1 (struct target_ops *ops,
|
||||
|
||||
if (gdbarch_software_single_step_p (gdbarch))
|
||||
{
|
||||
process_stratum_target *proc_target
|
||||
= current_inferior ()->process_target ();
|
||||
|
||||
/* Try to insert the software single step breakpoint.
|
||||
If insert success, set step to 0. */
|
||||
set_executing (inferior_ptid, 0);
|
||||
set_executing (proc_target, inferior_ptid, 0);
|
||||
reinit_frame_cache ();
|
||||
|
||||
step = !insert_single_step_breakpoints (gdbarch);
|
||||
|
||||
set_executing (inferior_ptid, 1);
|
||||
set_executing (proc_target, inferior_ptid, 1);
|
||||
}
|
||||
|
||||
if (record_debug)
|
||||
@ -1290,6 +1295,8 @@ record_full_wait_1 (struct target_ops *ops,
|
||||
}
|
||||
else
|
||||
{
|
||||
switch_to_thread (current_inferior ()->process_target (),
|
||||
record_full_resume_ptid);
|
||||
struct regcache *regcache = get_current_regcache ();
|
||||
struct gdbarch *gdbarch = regcache->arch ();
|
||||
const struct address_space *aspace = regcache->aspace ();
|
||||
|
146
gdb/regcache.c
146
gdb/regcache.c
@ -196,10 +196,11 @@ reg_buffer::reg_buffer (gdbarch *gdbarch, bool has_pseudo)
|
||||
}
|
||||
}
|
||||
|
||||
regcache::regcache (gdbarch *gdbarch, const address_space *aspace_)
|
||||
regcache::regcache (process_stratum_target *target, gdbarch *gdbarch,
|
||||
const address_space *aspace_)
|
||||
/* The register buffers. A read/write register cache can only hold
|
||||
[0 .. gdbarch_num_regs). */
|
||||
: detached_regcache (gdbarch, false), m_aspace (aspace_)
|
||||
: detached_regcache (gdbarch, false), m_aspace (aspace_), m_target (target)
|
||||
{
|
||||
m_ptid = minus_one_ptid;
|
||||
}
|
||||
@ -320,14 +321,19 @@ reg_buffer::assert_regnum (int regnum) const
|
||||
std::forward_list<regcache *> regcache::current_regcache;
|
||||
|
||||
struct regcache *
|
||||
get_thread_arch_aspace_regcache (ptid_t ptid, struct gdbarch *gdbarch,
|
||||
get_thread_arch_aspace_regcache (process_stratum_target *target,
|
||||
ptid_t ptid, struct gdbarch *gdbarch,
|
||||
struct address_space *aspace)
|
||||
{
|
||||
gdb_assert (target != nullptr);
|
||||
|
||||
for (const auto ®cache : regcache::current_regcache)
|
||||
if (regcache->ptid () == ptid && regcache->arch () == gdbarch)
|
||||
if (regcache->target () == target
|
||||
&& regcache->ptid () == ptid
|
||||
&& regcache->arch () == gdbarch)
|
||||
return regcache;
|
||||
|
||||
regcache *new_regcache = new regcache (gdbarch, aspace);
|
||||
regcache *new_regcache = new regcache (target, gdbarch, aspace);
|
||||
|
||||
regcache::current_regcache.push_front (new_regcache);
|
||||
new_regcache->set_ptid (ptid);
|
||||
@ -336,26 +342,38 @@ get_thread_arch_aspace_regcache (ptid_t ptid, struct gdbarch *gdbarch,
|
||||
}
|
||||
|
||||
struct regcache *
|
||||
get_thread_arch_regcache (ptid_t ptid, struct gdbarch *gdbarch)
|
||||
get_thread_arch_regcache (process_stratum_target *target, ptid_t ptid,
|
||||
struct gdbarch *gdbarch)
|
||||
{
|
||||
scoped_restore_current_inferior restore_current_inferior;
|
||||
set_current_inferior (find_inferior_ptid (target, ptid));
|
||||
address_space *aspace = target_thread_address_space (ptid);
|
||||
|
||||
return get_thread_arch_aspace_regcache (ptid, gdbarch, aspace);
|
||||
return get_thread_arch_aspace_regcache (target, ptid, gdbarch, aspace);
|
||||
}
|
||||
|
||||
static process_stratum_target *current_thread_target;
|
||||
static ptid_t current_thread_ptid;
|
||||
static struct gdbarch *current_thread_arch;
|
||||
|
||||
struct regcache *
|
||||
get_thread_regcache (ptid_t ptid)
|
||||
get_thread_regcache (process_stratum_target *target, ptid_t ptid)
|
||||
{
|
||||
if (!current_thread_arch || current_thread_ptid != ptid)
|
||||
if (!current_thread_arch
|
||||
|| target != current_thread_target
|
||||
|| current_thread_ptid != ptid)
|
||||
{
|
||||
gdb_assert (ptid != null_ptid);
|
||||
|
||||
current_thread_ptid = ptid;
|
||||
current_thread_target = target;
|
||||
|
||||
scoped_restore_current_inferior restore_current_inferior;
|
||||
set_current_inferior (find_inferior_ptid (target, ptid));
|
||||
current_thread_arch = target_thread_architecture (ptid);
|
||||
}
|
||||
|
||||
return get_thread_arch_regcache (ptid, current_thread_arch);
|
||||
return get_thread_arch_regcache (target, ptid, current_thread_arch);
|
||||
}
|
||||
|
||||
/* See regcache.h. */
|
||||
@ -363,7 +381,8 @@ get_thread_regcache (ptid_t ptid)
|
||||
struct regcache *
|
||||
get_thread_regcache (thread_info *thread)
|
||||
{
|
||||
return get_thread_regcache (thread->ptid);
|
||||
return get_thread_regcache (thread->inf->process_target (),
|
||||
thread->ptid);
|
||||
}
|
||||
|
||||
struct regcache *
|
||||
@ -377,7 +396,11 @@ get_current_regcache (void)
|
||||
struct regcache *
|
||||
get_thread_regcache_for_ptid (ptid_t ptid)
|
||||
{
|
||||
return get_thread_regcache (ptid);
|
||||
/* This function doesn't take a process_stratum_target parameter
|
||||
because it's a gdbsupport/ routine implemented by both gdb and
|
||||
gdbserver. It always refers to a ptid of the current target. */
|
||||
process_stratum_target *proc_target = current_inferior ()->process_target ();
|
||||
return get_thread_regcache (proc_target, ptid);
|
||||
}
|
||||
|
||||
/* Observer for the target_changed event. */
|
||||
@ -412,29 +435,34 @@ regcache::regcache_thread_ptid_changed (ptid_t old_ptid, ptid_t new_ptid)
|
||||
Indicate that registers may have changed, so invalidate the cache. */
|
||||
|
||||
void
|
||||
registers_changed_ptid (ptid_t ptid)
|
||||
registers_changed_ptid (process_stratum_target *target, ptid_t ptid)
|
||||
{
|
||||
for (auto oit = regcache::current_regcache.before_begin (),
|
||||
it = std::next (oit);
|
||||
it != regcache::current_regcache.end ();
|
||||
)
|
||||
{
|
||||
if ((*it)->ptid ().matches (ptid))
|
||||
struct regcache *regcache = *it;
|
||||
if ((target == nullptr || regcache->target () == target)
|
||||
&& regcache->ptid ().matches (ptid))
|
||||
{
|
||||
delete *it;
|
||||
delete regcache;
|
||||
it = regcache::current_regcache.erase_after (oit);
|
||||
}
|
||||
else
|
||||
oit = it++;
|
||||
}
|
||||
|
||||
if (current_thread_ptid.matches (ptid))
|
||||
if ((target == nullptr || current_thread_target == target)
|
||||
&& current_thread_ptid.matches (ptid))
|
||||
{
|
||||
current_thread_target = NULL;
|
||||
current_thread_ptid = null_ptid;
|
||||
current_thread_arch = NULL;
|
||||
}
|
||||
|
||||
if (inferior_ptid.matches (ptid))
|
||||
if ((target == nullptr || current_inferior ()->process_target () == target)
|
||||
&& inferior_ptid.matches (ptid))
|
||||
{
|
||||
/* We just deleted the regcache of the current thread. Need to
|
||||
forget about any frames we have cached, too. */
|
||||
@ -447,13 +475,13 @@ registers_changed_ptid (ptid_t ptid)
|
||||
void
|
||||
registers_changed_thread (thread_info *thread)
|
||||
{
|
||||
registers_changed_ptid (thread->ptid);
|
||||
registers_changed_ptid (thread->inf->process_target (), thread->ptid);
|
||||
}
|
||||
|
||||
void
|
||||
registers_changed (void)
|
||||
{
|
||||
registers_changed_ptid (minus_one_ptid);
|
||||
registers_changed_ptid (nullptr, minus_one_ptid);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1400,6 +1428,21 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/* Wrapper around get_thread_arch_aspace_regcache that does some self checks. */
|
||||
|
||||
static void
|
||||
test_get_thread_arch_aspace_regcache (process_stratum_target *target,
|
||||
ptid_t ptid, struct gdbarch *gdbarch,
|
||||
address_space *aspace)
|
||||
{
|
||||
struct regcache *regcache
|
||||
= get_thread_arch_aspace_regcache (target, ptid, gdbarch, aspace);
|
||||
SELF_CHECK (regcache != NULL);
|
||||
SELF_CHECK (regcache->target () == target);
|
||||
SELF_CHECK (regcache->ptid () == ptid);
|
||||
SELF_CHECK (regcache->aspace () == aspace);
|
||||
}
|
||||
|
||||
static void
|
||||
current_regcache_test (void)
|
||||
{
|
||||
@ -1408,47 +1451,61 @@ current_regcache_test (void)
|
||||
|
||||
ptid_t ptid1 (1), ptid2 (2), ptid3 (3);
|
||||
|
||||
/* Get regcache from ptid1, a new regcache is added to
|
||||
test_target_ops test_target1;
|
||||
test_target_ops test_target2;
|
||||
|
||||
/* Get regcache from (target1,ptid1), a new regcache is added to
|
||||
current_regcache. */
|
||||
regcache *regcache = get_thread_arch_aspace_regcache (ptid1,
|
||||
test_get_thread_arch_aspace_regcache (&test_target1, ptid1,
|
||||
target_gdbarch (),
|
||||
NULL);
|
||||
|
||||
SELF_CHECK (regcache != NULL);
|
||||
SELF_CHECK (regcache->ptid () == ptid1);
|
||||
SELF_CHECK (regcache_access::current_regcache_size () == 1);
|
||||
|
||||
/* Get regcache from ptid2, a new regcache is added to
|
||||
/* Get regcache from (target1,ptid2), a new regcache is added to
|
||||
current_regcache. */
|
||||
regcache = get_thread_arch_aspace_regcache (ptid2,
|
||||
test_get_thread_arch_aspace_regcache (&test_target1, ptid2,
|
||||
target_gdbarch (),
|
||||
NULL);
|
||||
SELF_CHECK (regcache != NULL);
|
||||
SELF_CHECK (regcache->ptid () == ptid2);
|
||||
SELF_CHECK (regcache_access::current_regcache_size () == 2);
|
||||
|
||||
/* Get regcache from ptid3, a new regcache is added to
|
||||
/* Get regcache from (target1,ptid3), a new regcache is added to
|
||||
current_regcache. */
|
||||
regcache = get_thread_arch_aspace_regcache (ptid3,
|
||||
test_get_thread_arch_aspace_regcache (&test_target1, ptid3,
|
||||
target_gdbarch (),
|
||||
NULL);
|
||||
SELF_CHECK (regcache != NULL);
|
||||
SELF_CHECK (regcache->ptid () == ptid3);
|
||||
SELF_CHECK (regcache_access::current_regcache_size () == 3);
|
||||
|
||||
/* Get regcache from ptid2 again, nothing is added to
|
||||
/* Get regcache from (target1,ptid2) again, nothing is added to
|
||||
current_regcache. */
|
||||
regcache = get_thread_arch_aspace_regcache (ptid2,
|
||||
test_get_thread_arch_aspace_regcache (&test_target1, ptid2,
|
||||
target_gdbarch (),
|
||||
NULL);
|
||||
SELF_CHECK (regcache != NULL);
|
||||
SELF_CHECK (regcache->ptid () == ptid2);
|
||||
SELF_CHECK (regcache_access::current_regcache_size () == 3);
|
||||
|
||||
/* Mark ptid2 is changed, so regcache of ptid2 should be removed from
|
||||
current_regcache. */
|
||||
registers_changed_ptid (ptid2);
|
||||
SELF_CHECK (regcache_access::current_regcache_size () == 2);
|
||||
/* Get regcache from (target2,ptid2), a new regcache is added to
|
||||
current_regcache, since this time we're using a differen
|
||||
target. */
|
||||
test_get_thread_arch_aspace_regcache (&test_target2, ptid2,
|
||||
target_gdbarch (),
|
||||
NULL);
|
||||
SELF_CHECK (regcache_access::current_regcache_size () == 4);
|
||||
|
||||
/* Mark that (target1,ptid2) changed. The regcache of (target1,
|
||||
ptid2) should be removed from current_regcache. */
|
||||
registers_changed_ptid (&test_target1, ptid2);
|
||||
SELF_CHECK (regcache_access::current_regcache_size () == 3);
|
||||
|
||||
/* Get the regcache from (target2,ptid2) again, confirming the
|
||||
registers_changed_ptid call above did not delete it. */
|
||||
test_get_thread_arch_aspace_regcache (&test_target2, ptid2,
|
||||
target_gdbarch (),
|
||||
NULL);
|
||||
SELF_CHECK (regcache_access::current_regcache_size () == 3);
|
||||
|
||||
/* Confirm that marking all regcaches of all targets as changed
|
||||
clears current_regcache. */
|
||||
registers_changed_ptid (nullptr, minus_one_ptid);
|
||||
SELF_CHECK (regcache_access::current_regcache_size () == 0);
|
||||
}
|
||||
|
||||
class target_ops_no_register : public test_target_ops
|
||||
@ -1509,8 +1566,9 @@ target_ops_no_register::xfer_partial (enum target_object object,
|
||||
class readwrite_regcache : public regcache
|
||||
{
|
||||
public:
|
||||
readwrite_regcache (struct gdbarch *gdbarch)
|
||||
: regcache (gdbarch, nullptr)
|
||||
readwrite_regcache (process_stratum_target *target,
|
||||
struct gdbarch *gdbarch)
|
||||
: regcache (target, gdbarch, nullptr)
|
||||
{}
|
||||
};
|
||||
|
||||
@ -1577,7 +1635,7 @@ cooked_read_test (struct gdbarch *gdbarch)
|
||||
break;
|
||||
}
|
||||
|
||||
readwrite_regcache readwrite (gdbarch);
|
||||
readwrite_regcache readwrite (&mock_target, gdbarch);
|
||||
gdb::def_vector<gdb_byte> buf (register_size (gdbarch, nonzero_regnum));
|
||||
|
||||
readwrite.raw_read (nonzero_regnum, buf.data ());
|
||||
@ -1710,7 +1768,7 @@ cooked_write_test (struct gdbarch *gdbarch)
|
||||
}
|
||||
} pop_targets;
|
||||
|
||||
readwrite_regcache readwrite (gdbarch);
|
||||
readwrite_regcache readwrite (&mock_target, gdbarch);
|
||||
|
||||
const int num_regs = gdbarch_num_cooked_regs (gdbarch);
|
||||
|
||||
|
@ -29,17 +29,20 @@ struct regset;
|
||||
struct gdbarch;
|
||||
struct address_space;
|
||||
class thread_info;
|
||||
struct process_stratum_target;
|
||||
|
||||
extern struct regcache *get_current_regcache (void);
|
||||
extern struct regcache *get_thread_regcache (ptid_t ptid);
|
||||
extern struct regcache *get_thread_regcache (process_stratum_target *target,
|
||||
ptid_t ptid);
|
||||
|
||||
/* Get the regcache of THREAD. */
|
||||
extern struct regcache *get_thread_regcache (thread_info *thread);
|
||||
|
||||
extern struct regcache *get_thread_arch_regcache (ptid_t, struct gdbarch *);
|
||||
extern struct regcache *get_thread_arch_aspace_regcache (ptid_t,
|
||||
struct gdbarch *,
|
||||
struct address_space *);
|
||||
extern struct regcache *get_thread_arch_regcache
|
||||
(process_stratum_target *targ, ptid_t, struct gdbarch *);
|
||||
extern struct regcache *get_thread_arch_aspace_regcache
|
||||
(process_stratum_target *target, ptid_t,
|
||||
struct gdbarch *, struct address_space *);
|
||||
|
||||
extern enum register_status
|
||||
regcache_raw_read_signed (struct regcache *regcache,
|
||||
@ -385,13 +388,19 @@ public:
|
||||
this->m_ptid = ptid;
|
||||
}
|
||||
|
||||
process_stratum_target *target () const
|
||||
{
|
||||
return m_target;
|
||||
}
|
||||
|
||||
/* Dump the contents of a register from the register cache to the target
|
||||
debug. */
|
||||
void debug_print_register (const char *func, int regno);
|
||||
|
||||
static void regcache_thread_ptid_changed (ptid_t old_ptid, ptid_t new_ptid);
|
||||
protected:
|
||||
regcache (gdbarch *gdbarch, const address_space *aspace_);
|
||||
regcache (process_stratum_target *target, gdbarch *gdbarch,
|
||||
const address_space *aspace);
|
||||
|
||||
static std::forward_list<regcache *> current_regcache;
|
||||
|
||||
@ -421,14 +430,16 @@ private:
|
||||
|
||||
/* If this is a read-write cache, which thread's registers is
|
||||
it connected to? */
|
||||
process_stratum_target *m_target;
|
||||
ptid_t m_ptid;
|
||||
|
||||
friend struct regcache *
|
||||
get_thread_arch_aspace_regcache (ptid_t ptid, struct gdbarch *gdbarch,
|
||||
get_thread_arch_aspace_regcache (process_stratum_target *target, ptid_t ptid,
|
||||
struct gdbarch *gdbarch,
|
||||
struct address_space *aspace);
|
||||
|
||||
friend void
|
||||
registers_changed_ptid (ptid_t ptid);
|
||||
registers_changed_ptid (process_stratum_target *target, ptid_t ptid);
|
||||
};
|
||||
|
||||
class readonly_detached_regcache : public readable_regcache
|
||||
@ -451,7 +462,8 @@ public:
|
||||
};
|
||||
|
||||
extern void registers_changed (void);
|
||||
extern void registers_changed_ptid (ptid_t);
|
||||
extern void registers_changed_ptid (process_stratum_target *target,
|
||||
ptid_t ptid);
|
||||
|
||||
/* Indicate that registers of THREAD may have changed, so invalidate
|
||||
the cache. */
|
||||
|
213
gdb/remote.c
213
gdb/remote.c
@ -278,6 +278,9 @@ public: /* data */
|
||||
|
||||
/* The status of the stub support for the various vCont actions. */
|
||||
vCont_action_support supports_vCont;
|
||||
/* Whether vCont support was probed already. This is a workaround
|
||||
until packet_support is per-connection. */
|
||||
bool supports_vCont_probed;
|
||||
|
||||
/* True if the user has pressed Ctrl-C, but the target hasn't
|
||||
responded to that. */
|
||||
@ -537,6 +540,8 @@ public:
|
||||
|
||||
void async (int) override;
|
||||
|
||||
int async_wait_fd () override;
|
||||
|
||||
void thread_events (int) override;
|
||||
|
||||
int can_do_single_step () override;
|
||||
@ -1026,7 +1031,7 @@ static void remote_console_output (const char *msg);
|
||||
|
||||
static void remote_btrace_reset (remote_state *rs);
|
||||
|
||||
static void remote_unpush_and_throw (void);
|
||||
static void remote_unpush_and_throw (remote_target *target);
|
||||
|
||||
/* For "remote". */
|
||||
|
||||
@ -1376,7 +1381,7 @@ remote_arch_state::remote_arch_state (struct gdbarch *gdbarch)
|
||||
static remote_target *
|
||||
get_current_remote_target ()
|
||||
{
|
||||
target_ops *proc_target = find_target_at (process_stratum);
|
||||
target_ops *proc_target = current_inferior ()->process_target ();
|
||||
return dynamic_cast<remote_target *> (proc_target);
|
||||
}
|
||||
|
||||
@ -1657,6 +1662,7 @@ show_memory_packet_size (struct memory_packet_config *config)
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: needs to be per-remote-target. */
|
||||
static struct memory_packet_config memory_write_packet_config =
|
||||
{
|
||||
"memory-write-packet-size",
|
||||
@ -1730,6 +1736,7 @@ remote_target::get_memory_write_packet_size ()
|
||||
return get_memory_packet_size (&memory_write_packet_config);
|
||||
}
|
||||
|
||||
/* FIXME: needs to be per-remote-target. */
|
||||
static struct memory_packet_config memory_read_packet_config =
|
||||
{
|
||||
"memory-read-packet-size",
|
||||
@ -2086,6 +2093,9 @@ enum {
|
||||
PACKET_MAX
|
||||
};
|
||||
|
||||
/* FIXME: needs to be per-remote-target. Ignoring this for now,
|
||||
assuming all remote targets are the same server (thus all support
|
||||
the same packets). */
|
||||
static struct packet_config remote_protocol_packets[PACKET_MAX];
|
||||
|
||||
/* Returns the packet's corresponding "set remote foo-packet" command
|
||||
@ -2387,6 +2397,7 @@ remote_target::remote_add_inferior (bool fake_pid_p, int pid, int attached,
|
||||
inf = add_inferior_with_spaces ();
|
||||
}
|
||||
switch_to_inferior_no_thread (inf);
|
||||
push_target (this);
|
||||
inferior_appeared (inf, pid);
|
||||
}
|
||||
|
||||
@ -2402,7 +2413,8 @@ remote_target::remote_add_inferior (bool fake_pid_p, int pid, int attached,
|
||||
}
|
||||
|
||||
static remote_thread_info *get_remote_thread_info (thread_info *thread);
|
||||
static remote_thread_info *get_remote_thread_info (ptid_t ptid);
|
||||
static remote_thread_info *get_remote_thread_info (remote_target *target,
|
||||
ptid_t ptid);
|
||||
|
||||
/* Add thread PTID to GDB's thread list. Tag it as executing/running
|
||||
according to RUNNING. */
|
||||
@ -2420,13 +2432,13 @@ remote_target::remote_add_thread (ptid_t ptid, bool running, bool executing)
|
||||
might be confusing to the user. Be silent then, preserving the
|
||||
age old behavior. */
|
||||
if (rs->starting_up)
|
||||
thread = add_thread_silent (ptid);
|
||||
thread = add_thread_silent (this, ptid);
|
||||
else
|
||||
thread = add_thread (ptid);
|
||||
thread = add_thread (this, ptid);
|
||||
|
||||
get_remote_thread_info (thread)->vcont_resumed = executing;
|
||||
set_executing (ptid, executing);
|
||||
set_running (ptid, running);
|
||||
set_executing (this, ptid, executing);
|
||||
set_running (this, ptid, running);
|
||||
|
||||
return thread;
|
||||
}
|
||||
@ -2449,7 +2461,7 @@ remote_target::remote_notice_new_inferior (ptid_t currthread, int executing)
|
||||
/* If this is a new thread, add it to GDB's thread list.
|
||||
If we leave it up to WFI to do this, bad things will happen. */
|
||||
|
||||
thread_info *tp = find_thread_ptid (currthread);
|
||||
thread_info *tp = find_thread_ptid (this, currthread);
|
||||
if (tp != NULL && tp->state == THREAD_EXITED)
|
||||
{
|
||||
/* We're seeing an event on a thread id we knew had exited.
|
||||
@ -2458,7 +2470,7 @@ remote_target::remote_notice_new_inferior (ptid_t currthread, int executing)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!in_thread_list (currthread))
|
||||
if (!in_thread_list (this, currthread))
|
||||
{
|
||||
struct inferior *inf = NULL;
|
||||
int pid = currthread.pid ();
|
||||
@ -2471,8 +2483,8 @@ remote_target::remote_notice_new_inferior (ptid_t currthread, int executing)
|
||||
stub doesn't support qC. This is the first stop reported
|
||||
after an attach, so this is the main thread. Update the
|
||||
ptid in the thread list. */
|
||||
if (in_thread_list (ptid_t (pid)))
|
||||
thread_change_ptid (inferior_ptid, currthread);
|
||||
if (in_thread_list (this, ptid_t (pid)))
|
||||
thread_change_ptid (this, inferior_ptid, currthread);
|
||||
else
|
||||
{
|
||||
remote_add_thread (currthread, running, executing);
|
||||
@ -2488,7 +2500,7 @@ remote_target::remote_notice_new_inferior (ptid_t currthread, int executing)
|
||||
doesn't support qC. This is the first stop reported
|
||||
after an attach, so this is the main thread. Update the
|
||||
ptid in the thread list. */
|
||||
thread_change_ptid (inferior_ptid, currthread);
|
||||
thread_change_ptid (this, inferior_ptid, currthread);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2496,7 +2508,7 @@ remote_target::remote_notice_new_inferior (ptid_t currthread, int executing)
|
||||
extended-remote which already was debugging an inferior, we
|
||||
may not know about it yet. Add it before adding its child
|
||||
thread, so notifications are emitted in a sensible order. */
|
||||
if (find_inferior_pid (currthread.pid ()) == NULL)
|
||||
if (find_inferior_pid (this, currthread.pid ()) == NULL)
|
||||
{
|
||||
struct remote_state *rs = get_remote_state ();
|
||||
bool fake_pid_p = !remote_multi_process_p (rs);
|
||||
@ -2536,10 +2548,12 @@ get_remote_thread_info (thread_info *thread)
|
||||
return static_cast<remote_thread_info *> (thread->priv.get ());
|
||||
}
|
||||
|
||||
/* Return PTID's private thread data, creating it if necessary. */
|
||||
|
||||
static remote_thread_info *
|
||||
get_remote_thread_info (ptid_t ptid)
|
||||
get_remote_thread_info (remote_target *target, ptid_t ptid)
|
||||
{
|
||||
thread_info *thr = find_thread_ptid (ptid);
|
||||
thread_info *thr = find_thread_ptid (target, ptid);
|
||||
return get_remote_thread_info (thr);
|
||||
}
|
||||
|
||||
@ -3799,6 +3813,9 @@ remote_target::update_thread_list ()
|
||||
target. */
|
||||
for (thread_info *tp : all_threads_safe ())
|
||||
{
|
||||
if (tp->inf->process_target () != this)
|
||||
continue;
|
||||
|
||||
if (!context.contains_thread (tp->ptid))
|
||||
{
|
||||
/* Not found. */
|
||||
@ -3824,7 +3841,7 @@ remote_target::update_thread_list ()
|
||||
|
||||
remote_notice_new_inferior (item.ptid, executing);
|
||||
|
||||
thread_info *tp = find_thread_ptid (item.ptid);
|
||||
thread_info *tp = find_thread_ptid (this, item.ptid);
|
||||
remote_thread_info *info = get_remote_thread_info (tp);
|
||||
info->core = item.core;
|
||||
info->extra = std::move (item.extra);
|
||||
@ -4026,13 +4043,6 @@ remote_target::close ()
|
||||
/* Make sure we leave stdin registered in the event loop. */
|
||||
terminal_ours ();
|
||||
|
||||
/* We don't have a connection to the remote stub anymore. Get rid
|
||||
of all the inferiors and their threads we were controlling.
|
||||
Reset inferior_ptid to null_ptid first, as otherwise has_stack_frame
|
||||
will be unable to find the thread corresponding to (pid, 0, 0). */
|
||||
inferior_ptid = null_ptid;
|
||||
discard_all_inferiors ();
|
||||
|
||||
trace_reset_local_state ();
|
||||
|
||||
delete this;
|
||||
@ -4338,7 +4348,7 @@ remote_target::add_current_inferior_and_thread (char *wait_status)
|
||||
/* Add the main thread and switch to it. Don't try reading
|
||||
registers yet, since we haven't fetched the target description
|
||||
yet. */
|
||||
thread_info *tp = add_thread_silent (curr_ptid);
|
||||
thread_info *tp = add_thread_silent (this, curr_ptid);
|
||||
switch_to_thread_no_regs (tp);
|
||||
}
|
||||
|
||||
@ -4414,7 +4424,7 @@ remote_target::process_initial_stop_replies (int from_tty)
|
||||
if (ignore_event)
|
||||
continue;
|
||||
|
||||
struct thread_info *evthread = find_thread_ptid (event_ptid);
|
||||
thread_info *evthread = find_thread_ptid (this, event_ptid);
|
||||
|
||||
if (ws.kind == TARGET_WAITKIND_STOPPED)
|
||||
{
|
||||
@ -4434,14 +4444,14 @@ remote_target::process_initial_stop_replies (int from_tty)
|
||||
|| ws.value.sig != GDB_SIGNAL_0)
|
||||
evthread->suspend.waitstatus_pending_p = 1;
|
||||
|
||||
set_executing (event_ptid, 0);
|
||||
set_running (event_ptid, 0);
|
||||
set_executing (this, event_ptid, 0);
|
||||
set_running (this, event_ptid, 0);
|
||||
get_remote_thread_info (evthread)->vcont_resumed = 0;
|
||||
}
|
||||
|
||||
/* "Notice" the new inferiors before anything related to
|
||||
registers/memory. */
|
||||
for (inferior *inf : all_non_exited_inferiors ())
|
||||
for (inferior *inf : all_non_exited_inferiors (this))
|
||||
{
|
||||
inf->needs_setup = 1;
|
||||
|
||||
@ -4462,7 +4472,7 @@ remote_target::process_initial_stop_replies (int from_tty)
|
||||
|
||||
/* If all threads of an inferior were already stopped, we
|
||||
haven't setup the inferior yet. */
|
||||
for (inferior *inf : all_non_exited_inferiors ())
|
||||
for (inferior *inf : all_non_exited_inferiors (this))
|
||||
{
|
||||
if (inf->needs_setup)
|
||||
{
|
||||
@ -4476,7 +4486,7 @@ remote_target::process_initial_stop_replies (int from_tty)
|
||||
/* Now go over all threads that are stopped, and print their current
|
||||
frame. If all-stop, then if there's a signalled thread, pick
|
||||
that as current. */
|
||||
for (thread_info *thread : all_non_exited_threads ())
|
||||
for (thread_info *thread : all_non_exited_threads (this))
|
||||
{
|
||||
if (first == NULL)
|
||||
first = thread;
|
||||
@ -4515,7 +4525,7 @@ remote_target::process_initial_stop_replies (int from_tty)
|
||||
/* For "info program". */
|
||||
thread_info *thread = inferior_thread ();
|
||||
if (thread->state == THREAD_STOPPED)
|
||||
set_last_target_status (inferior_ptid, thread->suspend.waitstatus);
|
||||
set_last_target_status (this, inferior_ptid, thread->suspend.waitstatus);
|
||||
}
|
||||
|
||||
/* Start the remote connection and sync state. */
|
||||
@ -4688,7 +4698,7 @@ remote_target::start_remote (int from_tty, int extended_p)
|
||||
/* Let the stub know that we want it to return the thread. */
|
||||
set_continue_thread (minus_one_ptid);
|
||||
|
||||
if (thread_count () == 0)
|
||||
if (thread_count (this) == 0)
|
||||
{
|
||||
/* Target has no concept of threads at all. GDB treats
|
||||
non-threaded target as single-threaded; add a main
|
||||
@ -4714,14 +4724,15 @@ remote_target::start_remote (int from_tty, int extended_p)
|
||||
"warning: couldn't determine remote "
|
||||
"current thread; picking first in list.\n");
|
||||
|
||||
for (thread_info *tp : all_non_exited_threads ())
|
||||
for (thread_info *tp : all_non_exited_threads (this,
|
||||
minus_one_ptid))
|
||||
{
|
||||
switch_to_thread (tp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
switch_to_thread (find_thread_ptid (curr_thread));
|
||||
switch_to_thread (find_thread_ptid (this, curr_thread));
|
||||
}
|
||||
|
||||
/* init_wait_for_inferior should be called before get_offsets in order
|
||||
@ -4780,7 +4791,7 @@ remote_target::start_remote (int from_tty, int extended_p)
|
||||
remote_notif_get_pending_events (notif);
|
||||
}
|
||||
|
||||
if (thread_count () == 0)
|
||||
if (thread_count (this) == 0)
|
||||
{
|
||||
if (!extended_p)
|
||||
error (_("The target is not running (try extended-remote?)"));
|
||||
@ -5434,7 +5445,7 @@ remote_target::remote_serial_quit_handler ()
|
||||
{
|
||||
if (query (_("The target is not responding to GDB commands.\n"
|
||||
"Stop debugging it? ")))
|
||||
remote_unpush_and_throw ();
|
||||
remote_unpush_and_throw (this);
|
||||
}
|
||||
/* If ^C has already been sent once, offer to disconnect. */
|
||||
else if (!target_terminal::is_ours () && rs->ctrlc_pending_p)
|
||||
@ -5458,19 +5469,29 @@ remote_serial_quit_handler ()
|
||||
curr_quit_handler_target->remote_serial_quit_handler ();
|
||||
}
|
||||
|
||||
/* Remove any of the remote.c targets from target stack. Upper targets depend
|
||||
on it so remove them first. */
|
||||
/* Remove the remote target from the target stack of each inferior
|
||||
that is using it. Upper targets depend on it so remove them
|
||||
first. */
|
||||
|
||||
static void
|
||||
remote_unpush_target (void)
|
||||
remote_unpush_target (remote_target *target)
|
||||
{
|
||||
/* We have to unpush the target from all inferiors, even those that
|
||||
aren't running. */
|
||||
scoped_restore_current_inferior restore_current_inferior;
|
||||
|
||||
for (inferior *inf : all_inferiors (target))
|
||||
{
|
||||
switch_to_inferior_no_thread (inf);
|
||||
pop_all_targets_at_and_above (process_stratum);
|
||||
generic_mourn_inferior ();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
remote_unpush_and_throw (void)
|
||||
remote_unpush_and_throw (remote_target *target)
|
||||
{
|
||||
remote_unpush_target ();
|
||||
remote_unpush_target (target);
|
||||
throw_error (TARGET_CLOSE_ERROR, _("Disconnected from target."));
|
||||
}
|
||||
|
||||
@ -5487,7 +5508,7 @@ remote_target::open_1 (const char *name, int from_tty, int extended_p)
|
||||
/* If we're connected to a running target, target_preopen will kill it.
|
||||
Ask this question first, before target_preopen has a chance to kill
|
||||
anything. */
|
||||
if (curr_remote != NULL && !have_inferiors ())
|
||||
if (curr_remote != NULL && !target_has_execution)
|
||||
{
|
||||
if (from_tty
|
||||
&& !query (_("Already connected to a remote target. Disconnect? ")))
|
||||
@ -5616,7 +5637,7 @@ remote_target::open_1 (const char *name, int from_tty, int extended_p)
|
||||
/* Pop the partially set up target - unless something else did
|
||||
already before throwing the exception. */
|
||||
if (ex.error != TARGET_CLOSE_ERROR)
|
||||
remote_unpush_target ();
|
||||
remote_unpush_target (remote);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
@ -5680,10 +5701,10 @@ remote_target::remote_detach_1 (inferior *inf, int from_tty)
|
||||
remote_detach_pid (pid);
|
||||
|
||||
/* Exit only if this is the only active inferior. */
|
||||
if (from_tty && !rs->extended && number_of_live_inferiors () == 1)
|
||||
if (from_tty && !rs->extended && number_of_live_inferiors (this) == 1)
|
||||
puts_filtered (_("Ending remote debugging.\n"));
|
||||
|
||||
struct thread_info *tp = find_thread_ptid (inferior_ptid);
|
||||
thread_info *tp = find_thread_ptid (this, inferior_ptid);
|
||||
|
||||
/* Check to see if we are detaching a fork parent. Note that if we
|
||||
are detaching a fork child, tp == NULL. */
|
||||
@ -5785,10 +5806,10 @@ remote_target::disconnect (const char *args, int from_tty)
|
||||
error (_("Argument given to \"disconnect\" when remotely debugging."));
|
||||
|
||||
/* Make sure we unpush even the extended remote targets. Calling
|
||||
target_mourn_inferior won't unpush, and remote_mourn won't
|
||||
unpush if there is more than one inferior left. */
|
||||
unpush_target (this);
|
||||
generic_mourn_inferior ();
|
||||
target_mourn_inferior won't unpush, and
|
||||
remote_target::mourn_inferior won't unpush if there is more than
|
||||
one inferior left. */
|
||||
remote_unpush_target (this);
|
||||
|
||||
if (from_tty)
|
||||
puts_filtered ("Ending remote debugging.\n");
|
||||
@ -5876,10 +5897,10 @@ extended_remote_target::attach (const char *args, int from_tty)
|
||||
inferior_ptid = remote_current_thread (inferior_ptid);
|
||||
|
||||
/* Add the main thread to the thread list. */
|
||||
thread_info *thr = add_thread_silent (inferior_ptid);
|
||||
thread_info *thr = add_thread_silent (this, inferior_ptid);
|
||||
/* Don't consider the thread stopped until we've processed the
|
||||
saved stop reply. */
|
||||
set_executing (thr->ptid, true);
|
||||
set_executing (this, thr->ptid, true);
|
||||
}
|
||||
|
||||
/* Next, if the target can specify a description, read it. We do
|
||||
@ -5981,6 +6002,7 @@ remote_target::remote_vcont_probe ()
|
||||
}
|
||||
|
||||
packet_ok (rs->buf, &remote_protocol_packets[PACKET_vCont]);
|
||||
rs->supports_vCont_probed = true;
|
||||
}
|
||||
|
||||
/* Helper function for building "vCont" resumptions. Write a
|
||||
@ -6018,10 +6040,10 @@ remote_target::append_resumption (char *p, char *endp,
|
||||
{
|
||||
/* If we don't know about the target thread's tid, then
|
||||
we're resuming magic_null_ptid (see caller). */
|
||||
tp = find_thread_ptid (magic_null_ptid);
|
||||
tp = find_thread_ptid (this, magic_null_ptid);
|
||||
}
|
||||
else
|
||||
tp = find_thread_ptid (ptid);
|
||||
tp = find_thread_ptid (this, ptid);
|
||||
gdb_assert (tp != NULL);
|
||||
|
||||
if (tp->control.may_range_step)
|
||||
@ -6084,7 +6106,7 @@ char *
|
||||
remote_target::append_pending_thread_resumptions (char *p, char *endp,
|
||||
ptid_t ptid)
|
||||
{
|
||||
for (thread_info *thread : all_non_exited_threads (ptid))
|
||||
for (thread_info *thread : all_non_exited_threads (this, ptid))
|
||||
if (inferior_ptid != thread->ptid
|
||||
&& thread->suspend.stop_signal != GDB_SIGNAL_0)
|
||||
{
|
||||
@ -6117,7 +6139,7 @@ remote_target::remote_resume_with_hc (ptid_t ptid, int step,
|
||||
else
|
||||
set_continue_thread (ptid);
|
||||
|
||||
for (thread_info *thread : all_non_exited_threads ())
|
||||
for (thread_info *thread : all_non_exited_threads (this))
|
||||
resume_clear_thread_private_info (thread);
|
||||
|
||||
buf = rs->buf.data ();
|
||||
@ -6254,9 +6276,9 @@ remote_target::resume (ptid_t ptid, int step, enum gdb_signal siggnal)
|
||||
remote_thread_info *remote_thr;
|
||||
|
||||
if (minus_one_ptid == ptid || ptid.is_pid ())
|
||||
remote_thr = get_remote_thread_info (inferior_ptid);
|
||||
remote_thr = get_remote_thread_info (this, inferior_ptid);
|
||||
else
|
||||
remote_thr = get_remote_thread_info (ptid);
|
||||
remote_thr = get_remote_thread_info (this, ptid);
|
||||
|
||||
remote_thr->last_resume_step = step;
|
||||
remote_thr->last_resume_sig = siggnal;
|
||||
@ -6488,7 +6510,7 @@ remote_target::commit_resume ()
|
||||
may_global_wildcard_vcont = 1;
|
||||
|
||||
/* And assume every process is individually wildcard-able too. */
|
||||
for (inferior *inf : all_non_exited_inferiors ())
|
||||
for (inferior *inf : all_non_exited_inferiors (this))
|
||||
{
|
||||
remote_inferior *priv = get_remote_inferior (inf);
|
||||
|
||||
@ -6499,7 +6521,7 @@ remote_target::commit_resume ()
|
||||
disable process and global wildcard resumes appropriately. */
|
||||
check_pending_events_prevent_wildcard_vcont (&may_global_wildcard_vcont);
|
||||
|
||||
for (thread_info *tp : all_non_exited_threads ())
|
||||
for (thread_info *tp : all_non_exited_threads (this))
|
||||
{
|
||||
/* If a thread of a process is not meant to be resumed, then we
|
||||
can't wildcard that process. */
|
||||
@ -6528,7 +6550,7 @@ remote_target::commit_resume ()
|
||||
struct vcont_builder vcont_builder (this);
|
||||
|
||||
/* Threads first. */
|
||||
for (thread_info *tp : all_non_exited_threads ())
|
||||
for (thread_info *tp : all_non_exited_threads (this))
|
||||
{
|
||||
remote_thread_info *remote_thr = get_remote_thread_info (tp);
|
||||
|
||||
@ -6557,7 +6579,7 @@ remote_target::commit_resume ()
|
||||
supposed to be resumed. */
|
||||
any_process_wildcard = 0;
|
||||
|
||||
for (inferior *inf : all_non_exited_inferiors ())
|
||||
for (inferior *inf : all_non_exited_inferiors (this))
|
||||
{
|
||||
if (get_remote_inferior (inf)->may_wildcard_vcont)
|
||||
{
|
||||
@ -6578,7 +6600,7 @@ remote_target::commit_resume ()
|
||||
}
|
||||
else
|
||||
{
|
||||
for (inferior *inf : all_non_exited_inferiors ())
|
||||
for (inferior *inf : all_non_exited_inferiors (this))
|
||||
{
|
||||
if (get_remote_inferior (inf)->may_wildcard_vcont)
|
||||
{
|
||||
@ -6605,7 +6627,10 @@ remote_target::remote_stop_ns (ptid_t ptid)
|
||||
char *p = rs->buf.data ();
|
||||
char *endp = p + get_remote_packet_size ();
|
||||
|
||||
if (packet_support (PACKET_vCont) == PACKET_SUPPORT_UNKNOWN)
|
||||
/* FIXME: This supports_vCont_probed check is a workaround until
|
||||
packet_support is per-connection. */
|
||||
if (packet_support (PACKET_vCont) == PACKET_SUPPORT_UNKNOWN
|
||||
|| !rs->supports_vCont_probed)
|
||||
remote_vcont_probe ();
|
||||
|
||||
if (!rs->supports_vCont.t)
|
||||
@ -6762,7 +6787,7 @@ remote_target::interrupt_query ()
|
||||
if (query (_("The target is not responding to interrupt requests.\n"
|
||||
"Stop debugging it? ")))
|
||||
{
|
||||
remote_unpush_target ();
|
||||
remote_unpush_target (this);
|
||||
throw_error (TARGET_CLOSE_ERROR, _("Disconnected from target."));
|
||||
}
|
||||
}
|
||||
@ -6969,7 +6994,7 @@ remote_target::remove_new_fork_children (threads_listing_context *context)
|
||||
|
||||
/* For any threads stopped at a fork event, remove the corresponding
|
||||
fork child threads from the CONTEXT list. */
|
||||
for (thread_info *thread : all_non_exited_threads ())
|
||||
for (thread_info *thread : all_non_exited_threads (this))
|
||||
{
|
||||
struct target_waitstatus *ws = thread_pending_fork_status (thread);
|
||||
|
||||
@ -7011,7 +7036,7 @@ remote_target::check_pending_events_prevent_wildcard_vcont
|
||||
|| event->ws.kind == TARGET_WAITKIND_VFORKED)
|
||||
*may_global_wildcard = 0;
|
||||
|
||||
struct inferior *inf = find_inferior_ptid (event->ptid);
|
||||
struct inferior *inf = find_inferior_ptid (this, event->ptid);
|
||||
|
||||
/* This may be the first time we heard about this process.
|
||||
Regardless, we must not do a global wildcard resume, otherwise
|
||||
@ -7377,9 +7402,10 @@ Packet: '%s'\n"),
|
||||
|
||||
if (rsa == NULL)
|
||||
{
|
||||
inferior *inf = (event->ptid == null_ptid
|
||||
inferior *inf
|
||||
= (event->ptid == null_ptid
|
||||
? NULL
|
||||
: find_inferior_ptid (event->ptid));
|
||||
: find_inferior_ptid (this, event->ptid));
|
||||
/* If this is the first time we learn anything
|
||||
about this process, skip the registers
|
||||
included in this packet, since we don't yet
|
||||
@ -7639,7 +7665,7 @@ remote_target::process_stop_reply (struct stop_reply *stop_reply,
|
||||
if (!stop_reply->regcache.empty ())
|
||||
{
|
||||
struct regcache *regcache
|
||||
= get_thread_arch_regcache (ptid, stop_reply->arch);
|
||||
= get_thread_arch_regcache (this, ptid, stop_reply->arch);
|
||||
|
||||
for (cached_reg_t ® : stop_reply->regcache)
|
||||
{
|
||||
@ -7651,7 +7677,7 @@ remote_target::process_stop_reply (struct stop_reply *stop_reply,
|
||||
}
|
||||
|
||||
remote_notice_new_inferior (ptid, 0);
|
||||
remote_thread_info *remote_thr = get_remote_thread_info (ptid);
|
||||
remote_thread_info *remote_thr = get_remote_thread_info (this, ptid);
|
||||
remote_thr->core = stop_reply->core;
|
||||
remote_thr->stop_reason = stop_reply->stop_reason;
|
||||
remote_thr->watch_data_address = stop_reply->watch_data_address;
|
||||
@ -7721,9 +7747,9 @@ remote_target::wait_ns (ptid_t ptid, struct target_waitstatus *status, int optio
|
||||
/* Return the first resumed thread. */
|
||||
|
||||
static ptid_t
|
||||
first_remote_resumed_thread ()
|
||||
first_remote_resumed_thread (remote_target *target)
|
||||
{
|
||||
for (thread_info *tp : all_non_exited_threads (minus_one_ptid))
|
||||
for (thread_info *tp : all_non_exited_threads (target, minus_one_ptid))
|
||||
if (tp->resumed)
|
||||
return tp->ptid;
|
||||
return null_ptid;
|
||||
@ -7865,7 +7891,7 @@ remote_target::wait_as (ptid_t ptid, target_waitstatus *status, int options)
|
||||
if (event_ptid != null_ptid)
|
||||
record_currthread (rs, event_ptid);
|
||||
else
|
||||
event_ptid = first_remote_resumed_thread ();
|
||||
event_ptid = first_remote_resumed_thread (this);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -7873,7 +7899,7 @@ remote_target::wait_as (ptid_t ptid, target_waitstatus *status, int options)
|
||||
record_currthread (rs, minus_one_ptid);
|
||||
/* It's possible that the packet did not include a pid. */
|
||||
if (event_ptid == null_ptid)
|
||||
event_ptid = first_remote_resumed_thread ();
|
||||
event_ptid = first_remote_resumed_thread (this);
|
||||
/* EVENT_PTID could still be NULL_PTID. Double-check. */
|
||||
if (event_ptid == null_ptid)
|
||||
event_ptid = magic_null_ptid;
|
||||
@ -8988,11 +9014,11 @@ remote_target::files_info ()
|
||||
for output compatibility with throw_perror_with_name. */
|
||||
|
||||
static void
|
||||
unpush_and_perror (const char *string)
|
||||
unpush_and_perror (remote_target *target, const char *string)
|
||||
{
|
||||
int saved_errno = errno;
|
||||
|
||||
remote_unpush_target ();
|
||||
remote_unpush_target (target);
|
||||
throw_error (TARGET_CLOSE_ERROR, "%s: %s.", string,
|
||||
safe_strerror (saved_errno));
|
||||
}
|
||||
@ -9028,11 +9054,11 @@ remote_target::readchar (int timeout)
|
||||
switch ((enum serial_rc) ch)
|
||||
{
|
||||
case SERIAL_EOF:
|
||||
remote_unpush_target ();
|
||||
remote_unpush_target (this);
|
||||
throw_error (TARGET_CLOSE_ERROR, _("Remote connection closed"));
|
||||
/* no return */
|
||||
case SERIAL_ERROR:
|
||||
unpush_and_perror (_("Remote communication error. "
|
||||
unpush_and_perror (this, _("Remote communication error. "
|
||||
"Target disconnected."));
|
||||
/* no return */
|
||||
case SERIAL_TIMEOUT:
|
||||
@ -9061,7 +9087,7 @@ remote_target::remote_serial_write (const char *str, int len)
|
||||
|
||||
if (serial_write (rs->remote_desc, str, len))
|
||||
{
|
||||
unpush_and_perror (_("Remote communication error. "
|
||||
unpush_and_perror (this, _("Remote communication error. "
|
||||
"Target disconnected."));
|
||||
}
|
||||
|
||||
@ -9585,7 +9611,7 @@ remote_target::getpkt_or_notif_sane_1 (gdb::char_vector *buf,
|
||||
|
||||
if (forever) /* Watchdog went off? Kill the target. */
|
||||
{
|
||||
remote_unpush_target ();
|
||||
remote_unpush_target (this);
|
||||
throw_error (TARGET_CLOSE_ERROR,
|
||||
_("Watchdog timeout has expired. "
|
||||
"Target detached."));
|
||||
@ -9702,7 +9728,7 @@ remote_target::kill_new_fork_children (int pid)
|
||||
|
||||
/* Kill the fork child threads of any threads in process PID
|
||||
that are stopped at a fork event. */
|
||||
for (thread_info *thread : all_non_exited_threads ())
|
||||
for (thread_info *thread : all_non_exited_threads (this))
|
||||
{
|
||||
struct target_waitstatus *ws = &thread->pending_follow;
|
||||
|
||||
@ -9762,7 +9788,7 @@ remote_target::kill ()
|
||||
inferior, then we will tell gdbserver to exit and unpush the
|
||||
target. */
|
||||
if (res == -1 && !remote_multi_process_p (rs)
|
||||
&& number_of_live_inferiors () == 1)
|
||||
&& number_of_live_inferiors (this) == 1)
|
||||
{
|
||||
remote_kill_k ();
|
||||
|
||||
@ -9848,12 +9874,9 @@ remote_target::mourn_inferior ()
|
||||
discard_pending_stop_replies (current_inferior ());
|
||||
|
||||
/* In 'target remote' mode with one inferior, we close the connection. */
|
||||
if (!rs->extended && number_of_live_inferiors () <= 1)
|
||||
if (!rs->extended && number_of_live_inferiors (this) <= 1)
|
||||
{
|
||||
unpush_target (this);
|
||||
|
||||
/* remote_close takes care of doing most of the clean up. */
|
||||
generic_mourn_inferior ();
|
||||
remote_unpush_target (this);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -13437,7 +13460,7 @@ remote_target::set_disconnected_tracing (int val)
|
||||
int
|
||||
remote_target::core_of_thread (ptid_t ptid)
|
||||
{
|
||||
struct thread_info *info = find_thread_ptid (ptid);
|
||||
thread_info *info = find_thread_ptid (this, ptid);
|
||||
|
||||
if (info != NULL && info->priv != NULL)
|
||||
return get_remote_thread_info (info)->core;
|
||||
@ -13717,7 +13740,7 @@ remote_target::remote_btrace_maybe_reopen ()
|
||||
|
||||
scoped_restore_current_thread restore_thread;
|
||||
|
||||
for (thread_info *tp : all_non_exited_threads ())
|
||||
for (thread_info *tp : all_non_exited_threads (this))
|
||||
{
|
||||
set_general_thread (tp->ptid);
|
||||
|
||||
@ -13933,13 +13956,12 @@ char *
|
||||
remote_target::pid_to_exec_file (int pid)
|
||||
{
|
||||
static gdb::optional<gdb::char_vector> filename;
|
||||
struct inferior *inf;
|
||||
char *annex = NULL;
|
||||
|
||||
if (packet_support (PACKET_qXfer_exec_file) != PACKET_ENABLE)
|
||||
return NULL;
|
||||
|
||||
inf = find_inferior_pid (pid);
|
||||
inferior *inf = find_inferior_pid (this, pid);
|
||||
if (inf == NULL)
|
||||
internal_error (__FILE__, __LINE__,
|
||||
_("not currently attached to process %d"), pid);
|
||||
@ -14000,7 +14022,7 @@ remote_target::thread_handle_to_thread_info (const gdb_byte *thread_handle,
|
||||
int handle_len,
|
||||
inferior *inf)
|
||||
{
|
||||
for (thread_info *tp : all_non_exited_threads ())
|
||||
for (thread_info *tp : all_non_exited_threads (this))
|
||||
{
|
||||
remote_thread_info *priv = get_remote_thread_info (tp);
|
||||
|
||||
@ -14072,6 +14094,13 @@ remote_async_inferior_event_handler (gdb_client_data data)
|
||||
inferior_event_handler (INF_REG_EVENT, data);
|
||||
}
|
||||
|
||||
int
|
||||
remote_target::async_wait_fd ()
|
||||
{
|
||||
struct remote_state *rs = get_remote_state ();
|
||||
return rs->remote_desc->fd;
|
||||
}
|
||||
|
||||
void
|
||||
remote_target::async (int enable)
|
||||
{
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "trad-frame.h"
|
||||
#include "tramp-frame.h"
|
||||
#include "gdbarch.h"
|
||||
#include "inferior.h"
|
||||
|
||||
/* Register maps. */
|
||||
|
||||
@ -183,7 +184,8 @@ riscv_fbsd_get_thread_local_address (struct gdbarch *gdbarch, ptid_t ptid,
|
||||
{
|
||||
struct regcache *regcache;
|
||||
|
||||
regcache = get_thread_arch_regcache (ptid, gdbarch);
|
||||
regcache = get_thread_arch_regcache (current_inferior ()->process_target (),
|
||||
ptid, gdbarch);
|
||||
|
||||
target_fetch_registers (regcache, RISCV_TP_REGNUM);
|
||||
|
||||
|
@ -461,9 +461,13 @@ sol_thread_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
|
||||
/* See if we have a new thread. */
|
||||
if (rtnval.tid_p () && rtnval != save_ptid)
|
||||
{
|
||||
thread_info *thr = find_thread_ptid (rtnval);
|
||||
thread_info *thr = find_thread_ptid (current_inferior (), rtnval);
|
||||
if (thr == NULL || thr->state == THREAD_EXITED)
|
||||
add_thread (rtnval);
|
||||
{
|
||||
process_stratum_target *proc_target
|
||||
= current_inferior ()->process_target ();
|
||||
add_thread (proc_target, rtnval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -853,7 +857,8 @@ ps_lgetregs (struct ps_prochandle *ph, lwpid_t lwpid, prgregset_t gregset)
|
||||
{
|
||||
ptid_t ptid = ptid_t (inferior_ptid.pid (), lwpid, 0);
|
||||
struct regcache *regcache
|
||||
= get_thread_arch_regcache (ptid, target_gdbarch ());
|
||||
= get_thread_arch_regcache (current_inferior ()->process_target (),
|
||||
ptid, target_gdbarch ());
|
||||
|
||||
target_fetch_registers (regcache, -1);
|
||||
fill_gregset (regcache, (gdb_gregset_t *) gregset, -1);
|
||||
@ -869,7 +874,8 @@ ps_lsetregs (struct ps_prochandle *ph, lwpid_t lwpid,
|
||||
{
|
||||
ptid_t ptid = ptid_t (inferior_ptid.pid (), lwpid, 0);
|
||||
struct regcache *regcache
|
||||
= get_thread_arch_regcache (ptid, target_gdbarch ());
|
||||
= get_thread_arch_regcache (current_inferior ()->process_target (),
|
||||
ptid, target_gdbarch ());
|
||||
|
||||
supply_gregset (regcache, (const gdb_gregset_t *) gregset);
|
||||
target_store_registers (regcache, -1);
|
||||
@ -921,7 +927,8 @@ ps_lgetfpregs (struct ps_prochandle *ph, lwpid_t lwpid,
|
||||
{
|
||||
ptid_t ptid = ptid_t (inferior_ptid.pid (), lwpid, 0);
|
||||
struct regcache *regcache
|
||||
= get_thread_arch_regcache (ptid, target_gdbarch ());
|
||||
= get_thread_arch_regcache (current_inferior ()->process_target (),
|
||||
ptid, target_gdbarch ());
|
||||
|
||||
target_fetch_registers (regcache, -1);
|
||||
fill_fpregset (regcache, (gdb_fpregset_t *) fpregset, -1);
|
||||
@ -937,7 +944,8 @@ ps_lsetfpregs (struct ps_prochandle *ph, lwpid_t lwpid,
|
||||
{
|
||||
ptid_t ptid = ptid_t (inferior_ptid.pid (), lwpid, 0);
|
||||
struct regcache *regcache
|
||||
= get_thread_arch_regcache (ptid, target_gdbarch ());
|
||||
= get_thread_arch_regcache (current_inferior ()->process_target (),
|
||||
ptid, target_gdbarch ());
|
||||
|
||||
supply_fpregset (regcache, (const gdb_fpregset_t *) fpregset);
|
||||
target_store_registers (regcache, -1);
|
||||
@ -1037,9 +1045,13 @@ sol_update_thread_list_callback (const td_thrhandle_t *th, void *ignored)
|
||||
return -1;
|
||||
|
||||
ptid_t ptid = ptid_t (inferior_ptid.pid (), 0, ti.ti_tid);
|
||||
thread_info *thr = find_thread_ptid (ptid);
|
||||
thread_info *thr = find_thread_ptid (current_inferior (), ptid);
|
||||
if (thr == NULL || thr->state == THREAD_EXITED)
|
||||
add_thread (ptid);
|
||||
{
|
||||
process_stratum_target *proc_target
|
||||
= current_inferior ()->process_target ();
|
||||
add_thread (proc_target, ptid);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ sol2_core_pid_to_str (struct gdbarch *gdbarch, ptid_t ptid)
|
||||
/* GDB didn't use to put a NT_PSTATUS note in Solaris cores. If
|
||||
that's missing, then we're dealing with a fake PID corelow.c made
|
||||
up. */
|
||||
inf = find_inferior_ptid (ptid);
|
||||
inf = find_inferior_ptid (current_inferior ()->process_target (), ptid);
|
||||
if (inf == NULL || inf->fake_pid_p)
|
||||
return "<core>";
|
||||
|
||||
|
@ -2394,7 +2394,8 @@ enable_break (struct svr4_info *info, int from_tty)
|
||||
if (!load_addr_found)
|
||||
{
|
||||
struct regcache *regcache
|
||||
= get_thread_arch_regcache (inferior_ptid, target_gdbarch ());
|
||||
= get_thread_arch_regcache (current_inferior ()->process_target (),
|
||||
inferior_ptid, target_gdbarch ());
|
||||
|
||||
load_addr = (regcache_read_pc (regcache)
|
||||
- exec_entry_point (tmp_bfd.get (), tmp_bfd_target));
|
||||
|
@ -83,6 +83,7 @@ struct dummy_target : public target_ops
|
||||
bool can_async_p () override;
|
||||
bool is_async_p () override;
|
||||
void async (int arg0) override;
|
||||
int async_wait_fd () override;
|
||||
void thread_events (int arg0) override;
|
||||
bool supports_non_stop () override;
|
||||
bool always_non_stop_p () override;
|
||||
@ -251,6 +252,7 @@ struct debug_target : public target_ops
|
||||
bool can_async_p () override;
|
||||
bool is_async_p () override;
|
||||
void async (int arg0) override;
|
||||
int async_wait_fd () override;
|
||||
void thread_events (int arg0) override;
|
||||
bool supports_non_stop () override;
|
||||
bool always_non_stop_p () override;
|
||||
@ -2162,6 +2164,31 @@ debug_target::async (int arg0)
|
||||
fputs_unfiltered (")\n", gdb_stdlog);
|
||||
}
|
||||
|
||||
int
|
||||
target_ops::async_wait_fd ()
|
||||
{
|
||||
return this->beneath ()->async_wait_fd ();
|
||||
}
|
||||
|
||||
int
|
||||
dummy_target::async_wait_fd ()
|
||||
{
|
||||
noprocess ();
|
||||
}
|
||||
|
||||
int
|
||||
debug_target::async_wait_fd ()
|
||||
{
|
||||
int result;
|
||||
fprintf_unfiltered (gdb_stdlog, "-> %s->async_wait_fd (...)\n", this->beneath ()->shortname ());
|
||||
result = this->beneath ()->async_wait_fd ();
|
||||
fprintf_unfiltered (gdb_stdlog, "<- %s->async_wait_fd (", this->beneath ()->shortname ());
|
||||
fputs_unfiltered (") = ", gdb_stdlog);
|
||||
target_debug_print_int (result);
|
||||
fputs_unfiltered ("\n", gdb_stdlog);
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
target_ops::thread_events (int arg0)
|
||||
{
|
||||
|
168
gdb/target.c
168
gdb/target.c
@ -110,10 +110,6 @@ static std::unordered_map<const target_info *, target_open_ftype *>
|
||||
|
||||
static struct target_ops *the_debug_target;
|
||||
|
||||
/* The target stack. */
|
||||
|
||||
static target_stack g_target_stack;
|
||||
|
||||
/* Top of target stack. */
|
||||
/* The target structure we are currently using to talk to a process
|
||||
or file or whatever "inferior" we have. */
|
||||
@ -121,7 +117,7 @@ static target_stack g_target_stack;
|
||||
target_ops *
|
||||
current_top_target ()
|
||||
{
|
||||
return g_target_stack.top ();
|
||||
return current_inferior ()->top_target ();
|
||||
}
|
||||
|
||||
/* Command list for target. */
|
||||
@ -226,7 +222,9 @@ target_has_registers_1 (void)
|
||||
bool
|
||||
target_has_execution_1 (inferior *inf)
|
||||
{
|
||||
for (target_ops *t = current_top_target (); t != NULL; t = t->beneath ())
|
||||
for (target_ops *t = inf->top_target ();
|
||||
t != nullptr;
|
||||
t = inf->find_target_beneath (t))
|
||||
if (t->has_execution (inf))
|
||||
return true;
|
||||
|
||||
@ -501,13 +499,16 @@ target_terminal::info (const char *arg, int from_tty)
|
||||
bool
|
||||
target_supports_terminal_ours (void)
|
||||
{
|
||||
/* This can be called before there is any target, so we must check
|
||||
for nullptr here. */
|
||||
target_ops *top = current_top_target ();
|
||||
/* The current top target is the target at the top of the target
|
||||
stack of the current inferior. While normally there's always an
|
||||
inferior, we must check for nullptr here because we can get here
|
||||
very early during startup, before the initial inferior is first
|
||||
created. */
|
||||
inferior *inf = current_inferior ();
|
||||
|
||||
if (top == nullptr)
|
||||
if (inf == nullptr)
|
||||
return false;
|
||||
return top->supports_terminal_ours ();
|
||||
return inf->top_target ()->supports_terminal_ours ();
|
||||
}
|
||||
|
||||
static void
|
||||
@ -555,12 +556,25 @@ to_execution_direction must be implemented for reverse async");
|
||||
|
||||
/* See target.h. */
|
||||
|
||||
void
|
||||
decref_target (target_ops *t)
|
||||
{
|
||||
t->decref ();
|
||||
if (t->refcount () == 0)
|
||||
target_close (t);
|
||||
}
|
||||
|
||||
/* See target.h. */
|
||||
|
||||
void
|
||||
target_stack::push (target_ops *t)
|
||||
{
|
||||
/* If there's already a target at this stratum, remove it. */
|
||||
t->incref ();
|
||||
|
||||
strata stratum = t->stratum ();
|
||||
|
||||
/* If there's already a target at this stratum, remove it. */
|
||||
|
||||
if (m_stack[stratum] != NULL)
|
||||
unpush (m_stack[stratum]);
|
||||
|
||||
@ -576,15 +590,15 @@ target_stack::push (target_ops *t)
|
||||
void
|
||||
push_target (struct target_ops *t)
|
||||
{
|
||||
g_target_stack.push (t);
|
||||
current_inferior ()->push_target (t);
|
||||
}
|
||||
|
||||
/* See target.h */
|
||||
/* See target.h. */
|
||||
|
||||
void
|
||||
push_target (target_ops_up &&t)
|
||||
{
|
||||
g_target_stack.push (t.get ());
|
||||
current_inferior ()->push_target (t.get ());
|
||||
t.release ();
|
||||
}
|
||||
|
||||
@ -593,7 +607,7 @@ push_target (target_ops_up &&t)
|
||||
int
|
||||
unpush_target (struct target_ops *t)
|
||||
{
|
||||
return g_target_stack.unpush (t);
|
||||
return current_inferior ()->unpush_target (t);
|
||||
}
|
||||
|
||||
/* See target.h. */
|
||||
@ -625,10 +639,13 @@ target_stack::unpush (target_ops *t)
|
||||
if (m_top == stratum)
|
||||
m_top = t->beneath ()->stratum ();
|
||||
|
||||
/* Finally close the target. Note we do this after unchaining, so
|
||||
any target method calls from within the target_close
|
||||
implementation don't end up in T anymore. */
|
||||
target_close (t);
|
||||
/* Finally close the target, if there are no inferiors
|
||||
referencing this target still. Note we do this after unchaining,
|
||||
so any target method calls from within the target_close
|
||||
implementation don't end up in T anymore. Do leave the target
|
||||
open if we have are other inferiors referencing this target
|
||||
still. */
|
||||
decref_target (t);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -670,12 +687,13 @@ pop_all_targets (void)
|
||||
pop_all_targets_above (dummy_stratum);
|
||||
}
|
||||
|
||||
/* Return 1 if T is now pushed in the target stack. Return 0 otherwise. */
|
||||
/* Return true if T is now pushed in the current inferior's target
|
||||
stack. Return false otherwise. */
|
||||
|
||||
int
|
||||
target_is_pushed (struct target_ops *t)
|
||||
bool
|
||||
target_is_pushed (target_ops *t)
|
||||
{
|
||||
return g_target_stack.is_pushed (t);
|
||||
return current_inferior ()->target_is_pushed (t);
|
||||
}
|
||||
|
||||
/* Default implementation of to_get_thread_local_address. */
|
||||
@ -1947,33 +1965,6 @@ target_pre_inferior (int from_tty)
|
||||
agent_capability_invalidate ();
|
||||
}
|
||||
|
||||
/* Callback for iterate_over_inferiors. Gets rid of the given
|
||||
inferior. */
|
||||
|
||||
static int
|
||||
dispose_inferior (struct inferior *inf, void *args)
|
||||
{
|
||||
/* Not all killed inferiors can, or will ever be, removed from the
|
||||
inferior list. Killed inferiors clearly don't need to be killed
|
||||
again, so, we're done. */
|
||||
if (inf->pid == 0)
|
||||
return 0;
|
||||
|
||||
thread_info *thread = any_thread_of_inferior (inf);
|
||||
if (thread != NULL)
|
||||
{
|
||||
switch_to_thread (thread);
|
||||
|
||||
/* Core inferiors actually should be detached, not killed. */
|
||||
if (target_has_execution)
|
||||
target_kill ();
|
||||
else
|
||||
target_detach (inf, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This is to be called by the open routine before it does
|
||||
anything. */
|
||||
|
||||
@ -1982,12 +1973,19 @@ target_preopen (int from_tty)
|
||||
{
|
||||
dont_repeat ();
|
||||
|
||||
if (have_inferiors ())
|
||||
if (current_inferior ()->pid != 0)
|
||||
{
|
||||
if (!from_tty
|
||||
|| !have_live_inferiors ()
|
||||
|| !target_has_execution
|
||||
|| query (_("A program is being debugged already. Kill it? ")))
|
||||
iterate_over_inferiors (dispose_inferior, NULL);
|
||||
{
|
||||
/* Core inferiors actually should be detached, not
|
||||
killed. */
|
||||
if (target_has_execution)
|
||||
target_kill ();
|
||||
else
|
||||
target_detach (current_inferior (), 0);
|
||||
}
|
||||
else
|
||||
error (_("Program not killed."));
|
||||
}
|
||||
@ -2029,9 +2027,16 @@ target_detach (inferior *inf, int from_tty)
|
||||
|
||||
prepare_for_detach ();
|
||||
|
||||
/* Hold a strong reference because detaching may unpush the
|
||||
target. */
|
||||
auto proc_target_ref = target_ops_ref::new_reference (inf->process_target ());
|
||||
|
||||
current_top_target ()->detach (inf, from_tty);
|
||||
|
||||
registers_changed_ptid (save_pid_ptid);
|
||||
process_stratum_target *proc_target
|
||||
= as_process_stratum_target (proc_target_ref.get ());
|
||||
|
||||
registers_changed_ptid (proc_target, save_pid_ptid);
|
||||
|
||||
/* We have to ensure we have no frame cache left. Normally,
|
||||
registers_changed_ptid (save_pid_ptid) calls reinit_frame_cache when
|
||||
@ -2079,6 +2084,8 @@ target_pid_to_str (ptid_t ptid)
|
||||
const char *
|
||||
target_thread_name (struct thread_info *info)
|
||||
{
|
||||
gdb_assert (info->inf == current_inferior ());
|
||||
|
||||
return current_top_target ()->thread_name (info);
|
||||
}
|
||||
|
||||
@ -2102,16 +2109,18 @@ target_thread_info_to_thread_handle (struct thread_info *tip)
|
||||
void
|
||||
target_resume (ptid_t ptid, int step, enum gdb_signal signal)
|
||||
{
|
||||
process_stratum_target *curr_target = current_inferior ()->process_target ();
|
||||
|
||||
target_dcache_invalidate ();
|
||||
|
||||
current_top_target ()->resume (ptid, step, signal);
|
||||
|
||||
registers_changed_ptid (ptid);
|
||||
registers_changed_ptid (curr_target, ptid);
|
||||
/* We only set the internal executing state here. The user/frontend
|
||||
running state is set at a higher level. This also clears the
|
||||
thread's stop_pc as side effect. */
|
||||
set_executing (ptid, 1);
|
||||
clear_inline_frame_state (ptid);
|
||||
set_executing (curr_target, ptid, 1);
|
||||
clear_inline_frame_state (curr_target, ptid);
|
||||
}
|
||||
|
||||
/* If true, target_commit_resume is a nop. */
|
||||
@ -2536,7 +2545,6 @@ target_get_osdata (const char *type)
|
||||
return target_read_stralloc (t, TARGET_OBJECT_OSDATA, type);
|
||||
}
|
||||
|
||||
|
||||
/* Determine the current address space of thread PTID. */
|
||||
|
||||
struct address_space *
|
||||
@ -2555,7 +2563,7 @@ target_thread_address_space (ptid_t ptid)
|
||||
target_ops *
|
||||
target_ops::beneath () const
|
||||
{
|
||||
return g_target_stack.find_beneath (this);
|
||||
return current_inferior ()->find_target_beneath (this);
|
||||
}
|
||||
|
||||
void
|
||||
@ -3151,7 +3159,7 @@ target_stack::find_beneath (const target_ops *t) const
|
||||
struct target_ops *
|
||||
find_target_at (enum strata stratum)
|
||||
{
|
||||
return g_target_stack.at (stratum);
|
||||
return current_inferior ()->target_at (stratum);
|
||||
}
|
||||
|
||||
|
||||
@ -3247,6 +3255,14 @@ dummy_make_corefile_notes (struct target_ops *self,
|
||||
|
||||
static dummy_target the_dummy_target;
|
||||
|
||||
/* See target.h. */
|
||||
|
||||
target_ops *
|
||||
get_dummy_target ()
|
||||
{
|
||||
return &the_dummy_target;
|
||||
}
|
||||
|
||||
static const target_info dummy_target_info = {
|
||||
"None",
|
||||
N_("None"),
|
||||
@ -3333,7 +3349,33 @@ target_interrupt ()
|
||||
void
|
||||
target_pass_ctrlc (void)
|
||||
{
|
||||
/* Pass the Ctrl-C to the first target that has a thread
|
||||
running. */
|
||||
for (inferior *inf : all_inferiors ())
|
||||
{
|
||||
target_ops *proc_target = inf->process_target ();
|
||||
if (proc_target == NULL)
|
||||
continue;
|
||||
|
||||
for (thread_info *thr : inf->threads ())
|
||||
{
|
||||
/* A thread can be THREAD_STOPPED and executing, while
|
||||
running an infcall. */
|
||||
if (thr->state == THREAD_RUNNING || thr->executing)
|
||||
{
|
||||
/* We can get here quite deep in target layers. Avoid
|
||||
switching thread context or anything that would
|
||||
communicate with the target (e.g., to fetch
|
||||
registers), or flushing e.g., the frame cache. We
|
||||
just switch inferior in order to be able to call
|
||||
through the target_stack. */
|
||||
scoped_restore_current_inferior restore_inferior;
|
||||
set_current_inferior (inf);
|
||||
current_top_target ()->pass_ctrlc ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* See target.h. */
|
||||
@ -3981,10 +4023,8 @@ set_write_memory_permission (const char *args, int from_tty,
|
||||
}
|
||||
|
||||
void
|
||||
initialize_targets (void)
|
||||
_initialize_target ()
|
||||
{
|
||||
push_target (&the_dummy_target);
|
||||
|
||||
the_debug_target = new debug_target ();
|
||||
|
||||
add_info ("target", info_target_command, targ_desc);
|
||||
|
34
gdb/target.h
34
gdb/target.h
@ -43,6 +43,7 @@ struct inferior;
|
||||
#include "infrun.h" /* For enum exec_direction_kind. */
|
||||
#include "breakpoint.h" /* For enum bptype. */
|
||||
#include "gdbsupport/scoped_restore.h"
|
||||
#include "gdbsupport/refcounted-object.h"
|
||||
|
||||
/* This include file defines the interface between the main part
|
||||
of the debugger, and the part which is target-specific, or
|
||||
@ -427,6 +428,7 @@ struct target_info
|
||||
};
|
||||
|
||||
struct target_ops
|
||||
: public refcounted_object
|
||||
{
|
||||
/* Return this target's stratum. */
|
||||
virtual strata stratum () const = 0;
|
||||
@ -445,10 +447,10 @@ struct target_ops
|
||||
virtual const target_info &info () const = 0;
|
||||
|
||||
/* Name this target type. */
|
||||
const char *shortname ()
|
||||
const char *shortname () const
|
||||
{ return info ().shortname; }
|
||||
|
||||
const char *longname ()
|
||||
const char *longname () const
|
||||
{ return info ().longname; }
|
||||
|
||||
/* Close the target. This is where the target can handle
|
||||
@ -701,6 +703,8 @@ struct target_ops
|
||||
TARGET_DEFAULT_RETURN (false);
|
||||
virtual void async (int)
|
||||
TARGET_DEFAULT_NORETURN (tcomplain ());
|
||||
virtual int async_wait_fd ()
|
||||
TARGET_DEFAULT_NORETURN (noprocess ());
|
||||
virtual void thread_events (int)
|
||||
TARGET_DEFAULT_IGNORE ();
|
||||
/* This method must be implemented in some situations. See the
|
||||
@ -1264,6 +1268,27 @@ struct target_ops_deleter
|
||||
/* A unique pointer for target_ops. */
|
||||
typedef std::unique_ptr<target_ops, target_ops_deleter> target_ops_up;
|
||||
|
||||
/* Decref a target and close if, if there are no references left. */
|
||||
extern void decref_target (target_ops *t);
|
||||
|
||||
/* A policy class to interface gdb::ref_ptr with target_ops. */
|
||||
|
||||
struct target_ops_ref_policy
|
||||
{
|
||||
static void incref (target_ops *t)
|
||||
{
|
||||
t->incref ();
|
||||
}
|
||||
|
||||
static void decref (target_ops *t)
|
||||
{
|
||||
decref_target (t);
|
||||
}
|
||||
};
|
||||
|
||||
/* A gdb::ref_ptr pointer to a target_ops. */
|
||||
typedef gdb::ref_ptr<target_ops, target_ops_ref_policy> target_ops_ref;
|
||||
|
||||
/* Native target backends call this once at initialization time to
|
||||
inform the core about which is the target that can respond to "run"
|
||||
or "attach". Note: native targets are always singletons. */
|
||||
@ -1318,6 +1343,9 @@ private:
|
||||
|
||||
extern target_ops *current_top_target ();
|
||||
|
||||
/* Return the dummy target. */
|
||||
extern target_ops *get_dummy_target ();
|
||||
|
||||
/* Define easy words for doing these operations on our current target. */
|
||||
|
||||
#define target_shortname (current_top_target ()->shortname ())
|
||||
@ -2366,7 +2394,7 @@ extern void pop_all_targets_at_and_above (enum strata stratum);
|
||||
strictly above ABOVE_STRATUM. */
|
||||
extern void pop_all_targets_above (enum strata above_stratum);
|
||||
|
||||
extern int target_is_pushed (struct target_ops *t);
|
||||
extern bool target_is_pushed (target_ops *t);
|
||||
|
||||
extern CORE_ADDR target_translate_tls_address (struct objfile *objfile,
|
||||
CORE_ADDR offset);
|
||||
|
@ -58,16 +58,22 @@ all_threads_iterator::advance ()
|
||||
bool
|
||||
all_matching_threads_iterator::m_inf_matches ()
|
||||
{
|
||||
return (m_filter_ptid == minus_one_ptid
|
||||
|| m_filter_ptid.pid () == m_inf->pid);
|
||||
return ((m_filter_target == nullptr
|
||||
|| m_filter_target == m_inf->process_target ())
|
||||
&& (m_filter_ptid == minus_one_ptid
|
||||
|| m_filter_ptid.pid () == m_inf->pid));
|
||||
}
|
||||
|
||||
/* See thread-iter.h. */
|
||||
|
||||
all_matching_threads_iterator::all_matching_threads_iterator
|
||||
(ptid_t filter_ptid)
|
||||
: m_filter_ptid (filter_ptid)
|
||||
(process_stratum_target *filter_target, ptid_t filter_ptid)
|
||||
: m_filter_target (filter_target),
|
||||
m_filter_ptid (filter_ptid)
|
||||
{
|
||||
gdb_assert ((filter_target == nullptr && filter_ptid == minus_one_ptid)
|
||||
|| filter_target->stratum () == process_stratum);
|
||||
|
||||
m_thr = nullptr;
|
||||
for (m_inf = inferior_list; m_inf != NULL; m_inf = m_inf->next)
|
||||
if (m_inf_matches ())
|
||||
|
@ -92,12 +92,14 @@ public:
|
||||
|
||||
/* Creates an iterator that iterates over all threads that match
|
||||
FILTER_PTID. */
|
||||
explicit all_matching_threads_iterator (ptid_t filter_ptid);
|
||||
all_matching_threads_iterator (process_stratum_target *filter_target,
|
||||
ptid_t filter_ptid);
|
||||
|
||||
/* Create a one-past-end iterator. */
|
||||
all_matching_threads_iterator ()
|
||||
: m_inf (nullptr),
|
||||
m_thr (nullptr),
|
||||
m_filter_target (nullptr),
|
||||
m_filter_ptid (minus_one_ptid)
|
||||
{}
|
||||
|
||||
@ -131,6 +133,7 @@ private:
|
||||
thread_info *m_thr;
|
||||
|
||||
/* The filter. */
|
||||
process_stratum_target *m_filter_target;
|
||||
ptid_t m_filter_ptid;
|
||||
};
|
||||
|
||||
@ -211,20 +214,22 @@ struct all_threads_safe_range
|
||||
struct all_matching_threads_range
|
||||
{
|
||||
public:
|
||||
explicit all_matching_threads_range (ptid_t filter_ptid)
|
||||
: m_filter_ptid (filter_ptid)
|
||||
all_matching_threads_range (process_stratum_target *filter_target,
|
||||
ptid_t filter_ptid)
|
||||
: m_filter_target (filter_target), m_filter_ptid (filter_ptid)
|
||||
{}
|
||||
all_matching_threads_range ()
|
||||
: m_filter_ptid (minus_one_ptid)
|
||||
: m_filter_target (nullptr), m_filter_ptid (minus_one_ptid)
|
||||
{}
|
||||
|
||||
all_matching_threads_iterator begin () const
|
||||
{ return all_matching_threads_iterator (m_filter_ptid); }
|
||||
{ return all_matching_threads_iterator (m_filter_target, m_filter_ptid); }
|
||||
all_matching_threads_iterator end () const
|
||||
{ return all_matching_threads_iterator (); }
|
||||
|
||||
private:
|
||||
/* The filter. */
|
||||
process_stratum_target *m_filter_target;
|
||||
ptid_t m_filter_ptid;
|
||||
};
|
||||
|
||||
@ -236,20 +241,22 @@ private:
|
||||
class all_non_exited_threads_range
|
||||
{
|
||||
public:
|
||||
explicit all_non_exited_threads_range (ptid_t filter_ptid)
|
||||
: m_filter_ptid (filter_ptid)
|
||||
all_non_exited_threads_range (process_stratum_target *filter_target,
|
||||
ptid_t filter_ptid)
|
||||
: m_filter_target (filter_target), m_filter_ptid (filter_ptid)
|
||||
{}
|
||||
|
||||
all_non_exited_threads_range ()
|
||||
: m_filter_ptid (minus_one_ptid)
|
||||
: m_filter_target (nullptr), m_filter_ptid (minus_one_ptid)
|
||||
{}
|
||||
|
||||
all_non_exited_threads_iterator begin () const
|
||||
{ return all_non_exited_threads_iterator (m_filter_ptid); }
|
||||
{ return all_non_exited_threads_iterator (m_filter_target, m_filter_ptid); }
|
||||
all_non_exited_threads_iterator end () const
|
||||
{ return all_non_exited_threads_iterator (); }
|
||||
|
||||
private:
|
||||
process_stratum_target *m_filter_target;
|
||||
ptid_t m_filter_ptid;
|
||||
};
|
||||
|
||||
|
133
gdb/thread.c
133
gdb/thread.c
@ -55,13 +55,6 @@
|
||||
|
||||
static int highest_thread_num;
|
||||
|
||||
/* True if any thread is, or may be executing. We need to track this
|
||||
separately because until we fully sync the thread list, we won't
|
||||
know whether the target is fully stopped, even if we see stop
|
||||
events for all known threads, because any of those threads may have
|
||||
spawned new threads we haven't heard of yet. */
|
||||
static int threads_executing;
|
||||
|
||||
/* RAII type used to increase / decrease the refcount of each thread
|
||||
in a given list of threads. */
|
||||
|
||||
@ -89,7 +82,7 @@ private:
|
||||
struct thread_info*
|
||||
inferior_thread (void)
|
||||
{
|
||||
struct thread_info *tp = find_thread_ptid (inferior_ptid);
|
||||
struct thread_info *tp = find_thread_ptid (current_inferior (), inferior_ptid);
|
||||
gdb_assert (tp);
|
||||
return tp;
|
||||
}
|
||||
@ -195,7 +188,7 @@ clear_thread_inferior_resources (struct thread_info *tp)
|
||||
|
||||
thread_cancel_execution_command (tp);
|
||||
|
||||
clear_inline_frame_state (tp->ptid);
|
||||
clear_inline_frame_state (tp);
|
||||
}
|
||||
|
||||
/* Set the TP's state as exited. */
|
||||
@ -260,12 +253,11 @@ new_thread (struct inferior *inf, ptid_t ptid)
|
||||
}
|
||||
|
||||
struct thread_info *
|
||||
add_thread_silent (ptid_t ptid)
|
||||
add_thread_silent (process_stratum_target *targ, ptid_t ptid)
|
||||
{
|
||||
struct inferior *inf = find_inferior_ptid (ptid);
|
||||
gdb_assert (inf != NULL);
|
||||
inferior *inf;
|
||||
|
||||
thread_info *tp = find_thread_ptid (inf, ptid);
|
||||
thread_info *tp = find_thread_ptid (targ, ptid);
|
||||
if (tp)
|
||||
/* Found an old thread with the same id. It has to be dead,
|
||||
otherwise we wouldn't be adding a new thread with the same id.
|
||||
@ -281,7 +273,7 @@ add_thread_silent (ptid_t ptid)
|
||||
|
||||
if (inferior_ptid == ptid)
|
||||
{
|
||||
thread_info *new_thr = new_thread (inf, null_ptid);
|
||||
thread_info *new_thr = new_thread (tp->inf, null_ptid);
|
||||
|
||||
/* Make switch_to_thread not read from the thread. */
|
||||
new_thr->state = THREAD_EXITED;
|
||||
@ -300,10 +292,14 @@ add_thread_silent (ptid_t ptid)
|
||||
/* All done. */
|
||||
return new_thr;
|
||||
}
|
||||
else
|
||||
|
||||
inf = tp->inf;
|
||||
|
||||
/* Just go ahead and delete it. */
|
||||
delete_thread (tp);
|
||||
}
|
||||
else
|
||||
inf = find_inferior_ptid (targ, ptid);
|
||||
|
||||
tp = new_thread (inf, ptid);
|
||||
gdb::observers::new_thread.notify (tp);
|
||||
@ -312,9 +308,10 @@ add_thread_silent (ptid_t ptid)
|
||||
}
|
||||
|
||||
struct thread_info *
|
||||
add_thread_with_info (ptid_t ptid, private_thread_info *priv)
|
||||
add_thread_with_info (process_stratum_target *targ, ptid_t ptid,
|
||||
private_thread_info *priv)
|
||||
{
|
||||
struct thread_info *result = add_thread_silent (ptid);
|
||||
thread_info *result = add_thread_silent (targ, ptid);
|
||||
|
||||
result->priv.reset (priv);
|
||||
|
||||
@ -326,9 +323,9 @@ add_thread_with_info (ptid_t ptid, private_thread_info *priv)
|
||||
}
|
||||
|
||||
struct thread_info *
|
||||
add_thread (ptid_t ptid)
|
||||
add_thread (process_stratum_target *targ, ptid_t ptid)
|
||||
{
|
||||
return add_thread_with_info (ptid, NULL);
|
||||
return add_thread_with_info (targ, ptid, NULL);
|
||||
}
|
||||
|
||||
private_thread_info::~private_thread_info () = default;
|
||||
@ -352,6 +349,14 @@ thread_info::~thread_info ()
|
||||
xfree (this->name);
|
||||
}
|
||||
|
||||
/* Returns true if THR is the current thread. */
|
||||
|
||||
static bool
|
||||
is_current_thread (const thread_info *thr)
|
||||
{
|
||||
return thr->inf == current_inferior () && thr->ptid == inferior_ptid;
|
||||
}
|
||||
|
||||
/* See gdbthread.h. */
|
||||
|
||||
bool
|
||||
@ -359,7 +364,7 @@ thread_info::deletable () const
|
||||
{
|
||||
/* If this is the current thread, or there's code out there that
|
||||
relies on it existing (refcount > 0) we can't delete yet. */
|
||||
return refcount () == 0 && ptid != inferior_ptid;
|
||||
return refcount () == 0 && !is_current_thread (this);
|
||||
}
|
||||
|
||||
/* Add TP to the end of the step-over chain LIST_P. */
|
||||
@ -514,12 +519,12 @@ find_thread_id (struct inferior *inf, int thr_num)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Find a thread_info by matching PTID. */
|
||||
/* See gdbthread.h. */
|
||||
|
||||
struct thread_info *
|
||||
find_thread_ptid (ptid_t ptid)
|
||||
find_thread_ptid (process_stratum_target *targ, ptid_t ptid)
|
||||
{
|
||||
inferior *inf = find_inferior_ptid (ptid);
|
||||
inferior *inf = find_inferior_ptid (targ, ptid);
|
||||
if (inf == NULL)
|
||||
return NULL;
|
||||
return find_thread_ptid (inf, ptid);
|
||||
@ -584,9 +589,9 @@ any_thread_p ()
|
||||
}
|
||||
|
||||
int
|
||||
thread_count (void)
|
||||
thread_count (process_stratum_target *proc_target)
|
||||
{
|
||||
auto rng = all_threads ();
|
||||
auto rng = all_threads (proc_target);
|
||||
return std::distance (rng.begin (), rng.end ());
|
||||
}
|
||||
|
||||
@ -609,10 +614,10 @@ valid_global_thread_id (int global_id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
in_thread_list (ptid_t ptid)
|
||||
bool
|
||||
in_thread_list (process_stratum_target *targ, ptid_t ptid)
|
||||
{
|
||||
return find_thread_ptid (ptid) != nullptr;
|
||||
return find_thread_ptid (targ, ptid) != nullptr;
|
||||
}
|
||||
|
||||
/* Finds the first thread of the inferior. */
|
||||
@ -788,7 +793,8 @@ get_last_thread_stack_temporary (thread_info *tp)
|
||||
}
|
||||
|
||||
void
|
||||
thread_change_ptid (ptid_t old_ptid, ptid_t new_ptid)
|
||||
thread_change_ptid (process_stratum_target *targ,
|
||||
ptid_t old_ptid, ptid_t new_ptid)
|
||||
{
|
||||
struct inferior *inf;
|
||||
struct thread_info *tp;
|
||||
@ -796,7 +802,7 @@ thread_change_ptid (ptid_t old_ptid, ptid_t new_ptid)
|
||||
/* It can happen that what we knew as the target inferior id
|
||||
changes. E.g, target remote may only discover the remote process
|
||||
pid after adding the inferior to GDB's list. */
|
||||
inf = find_inferior_ptid (old_ptid);
|
||||
inf = find_inferior_ptid (targ, old_ptid);
|
||||
inf->pid = new_ptid.pid ();
|
||||
|
||||
tp = find_thread_ptid (inf, old_ptid);
|
||||
@ -808,9 +814,9 @@ thread_change_ptid (ptid_t old_ptid, ptid_t new_ptid)
|
||||
/* See gdbthread.h. */
|
||||
|
||||
void
|
||||
set_resumed (ptid_t ptid, int resumed)
|
||||
set_resumed (process_stratum_target *targ, ptid_t ptid, bool resumed)
|
||||
{
|
||||
for (thread_info *tp : all_non_exited_threads (ptid))
|
||||
for (thread_info *tp : all_non_exited_threads (targ, ptid))
|
||||
tp->resumed = resumed;
|
||||
}
|
||||
|
||||
@ -848,7 +854,7 @@ thread_info::set_running (bool running)
|
||||
}
|
||||
|
||||
void
|
||||
set_running (ptid_t ptid, int running)
|
||||
set_running (process_stratum_target *targ, ptid_t ptid, bool running)
|
||||
{
|
||||
/* We try not to notify the observer if no thread has actually
|
||||
changed the running state -- merely to reduce the number of
|
||||
@ -856,7 +862,7 @@ set_running (ptid_t ptid, int running)
|
||||
multiple *running notifications just fine. */
|
||||
bool any_started = false;
|
||||
|
||||
for (thread_info *tp : all_non_exited_threads (ptid))
|
||||
for (thread_info *tp : all_non_exited_threads (targ, ptid))
|
||||
if (set_running_thread (tp, running))
|
||||
any_started = true;
|
||||
|
||||
@ -878,32 +884,32 @@ set_executing_thread (thread_info *thr, bool executing)
|
||||
}
|
||||
|
||||
void
|
||||
set_executing (ptid_t ptid, int executing)
|
||||
set_executing (process_stratum_target *targ, ptid_t ptid, bool executing)
|
||||
{
|
||||
for (thread_info *tp : all_non_exited_threads (ptid))
|
||||
for (thread_info *tp : all_non_exited_threads (targ, ptid))
|
||||
set_executing_thread (tp, executing);
|
||||
|
||||
/* It only takes one running thread to spawn more threads. */
|
||||
if (executing)
|
||||
threads_executing = 1;
|
||||
targ->threads_executing = true;
|
||||
/* Only clear the flag if the caller is telling us everything is
|
||||
stopped. */
|
||||
else if (minus_one_ptid == ptid)
|
||||
threads_executing = 0;
|
||||
targ->threads_executing = false;
|
||||
}
|
||||
|
||||
/* See gdbthread.h. */
|
||||
|
||||
int
|
||||
threads_are_executing (void)
|
||||
bool
|
||||
threads_are_executing (process_stratum_target *target)
|
||||
{
|
||||
return threads_executing;
|
||||
return target->threads_executing;
|
||||
}
|
||||
|
||||
void
|
||||
set_stop_requested (ptid_t ptid, int stop)
|
||||
set_stop_requested (process_stratum_target *targ, ptid_t ptid, bool stop)
|
||||
{
|
||||
for (thread_info *tp : all_non_exited_threads (ptid))
|
||||
for (thread_info *tp : all_non_exited_threads (targ, ptid))
|
||||
tp->stop_requested = stop;
|
||||
|
||||
/* Call the stop requested observer so other components of GDB can
|
||||
@ -913,11 +919,11 @@ set_stop_requested (ptid_t ptid, int stop)
|
||||
}
|
||||
|
||||
void
|
||||
finish_thread_state (ptid_t ptid)
|
||||
finish_thread_state (process_stratum_target *targ, ptid_t ptid)
|
||||
{
|
||||
bool any_started = false;
|
||||
|
||||
for (thread_info *tp : all_non_exited_threads (ptid))
|
||||
for (thread_info *tp : all_non_exited_threads (targ, ptid))
|
||||
if (set_running_thread (tp, tp->executing))
|
||||
any_started = true;
|
||||
|
||||
@ -1333,7 +1339,7 @@ switch_to_thread (thread_info *thr)
|
||||
{
|
||||
gdb_assert (thr != NULL);
|
||||
|
||||
if (inferior_ptid == thr->ptid)
|
||||
if (is_current_thread (thr))
|
||||
return;
|
||||
|
||||
switch_to_thread_no_regs (thr);
|
||||
@ -1344,9 +1350,9 @@ switch_to_thread (thread_info *thr)
|
||||
/* See gdbsupport/common-gdbthread.h. */
|
||||
|
||||
void
|
||||
switch_to_thread (ptid_t ptid)
|
||||
switch_to_thread (process_stratum_target *proc_target, ptid_t ptid)
|
||||
{
|
||||
thread_info *thr = find_thread_ptid (ptid);
|
||||
thread_info *thr = find_thread_ptid (proc_target, ptid);
|
||||
switch_to_thread (thr);
|
||||
}
|
||||
|
||||
@ -2073,18 +2079,39 @@ print_selected_thread_frame (struct ui_out *uiout,
|
||||
}
|
||||
|
||||
/* Update the 'threads_executing' global based on the threads we know
|
||||
about right now. */
|
||||
about right now. This is used by infrun to tell whether we should
|
||||
pull events out of the current target. */
|
||||
|
||||
static void
|
||||
update_threads_executing (void)
|
||||
{
|
||||
threads_executing = 0;
|
||||
for (thread_info *tp : all_non_exited_threads ())
|
||||
process_stratum_target *targ = current_inferior ()->process_target ();
|
||||
|
||||
if (targ == NULL)
|
||||
return;
|
||||
|
||||
targ->threads_executing = false;
|
||||
|
||||
for (inferior *inf : all_non_exited_inferiors (targ))
|
||||
{
|
||||
if (!inf->has_execution ())
|
||||
continue;
|
||||
|
||||
/* If the process has no threads, then it must be we have a
|
||||
process-exit event pending. */
|
||||
if (inf->thread_list == NULL)
|
||||
{
|
||||
targ->threads_executing = true;
|
||||
return;
|
||||
}
|
||||
|
||||
for (thread_info *tp : inf->non_exited_threads ())
|
||||
{
|
||||
if (tp->executing)
|
||||
{
|
||||
threads_executing = 1;
|
||||
break;
|
||||
targ->threads_executing = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1740,6 +1740,9 @@ quit_force (int *exit_arg, int from_tty)
|
||||
|
||||
/* Give all pushed targets a chance to do minimal cleanup, and pop
|
||||
them all out. */
|
||||
for (inferior *inf : all_inferiors ())
|
||||
{
|
||||
switch_to_inferior_no_thread (inf);
|
||||
try
|
||||
{
|
||||
pop_all_targets ();
|
||||
@ -1748,6 +1751,7 @@ quit_force (int *exit_arg, int from_tty)
|
||||
{
|
||||
exception_print (gdb_stderr, ex);
|
||||
}
|
||||
}
|
||||
|
||||
/* Save the history information if it is appropriate to do so. */
|
||||
try
|
||||
@ -2298,7 +2302,6 @@ gdb_init (char *argv0)
|
||||
#endif
|
||||
|
||||
init_cmd_lists (); /* This needs to be done first. */
|
||||
initialize_targets (); /* Setup target_terminal macros for utils.c. */
|
||||
|
||||
init_page_info ();
|
||||
|
||||
|
@ -1169,7 +1169,7 @@ ctf_target_open (const char *dirname, int from_tty)
|
||||
|
||||
inferior_appeared (current_inferior (), CTF_PID);
|
||||
inferior_ptid = ptid_t (CTF_PID);
|
||||
add_thread_silent (inferior_ptid);
|
||||
add_thread_silent (&ctf_ops, inferior_ptid);
|
||||
|
||||
merge_uploaded_trace_state_variables (&uploaded_tsvs);
|
||||
merge_uploaded_tracepoints (&uploaded_tps);
|
||||
|
@ -557,7 +557,7 @@ tfile_target_open (const char *arg, int from_tty)
|
||||
|
||||
inferior_appeared (current_inferior (), TFILE_PID);
|
||||
inferior_ptid = ptid_t (TFILE_PID);
|
||||
add_thread_silent (inferior_ptid);
|
||||
add_thread_silent (&tfile_ops, inferior_ptid);
|
||||
|
||||
if (ts->traceframe_count <= 0)
|
||||
warning (_("No traceframes present in this file."));
|
||||
|
@ -350,6 +350,8 @@ struct windows_nat_target final : public x86_nat_target<inf_child_target>
|
||||
bool get_tib_address (ptid_t ptid, CORE_ADDR *addr) override;
|
||||
|
||||
const char *thread_name (struct thread_info *) override;
|
||||
|
||||
int get_windows_debug_event (int pid, struct target_waitstatus *ourstatus);
|
||||
};
|
||||
|
||||
static windows_nat_target the_windows_nat_target;
|
||||
@ -458,9 +460,9 @@ windows_add_thread (ptid_t ptid, HANDLE h, void *tlb, bool main_thread_p)
|
||||
the main thread silently (in reality, this thread is really
|
||||
more of a process to the user than a thread). */
|
||||
if (main_thread_p)
|
||||
add_thread_silent (ptid);
|
||||
add_thread_silent (&the_windows_nat_target, ptid);
|
||||
else
|
||||
add_thread (ptid);
|
||||
add_thread (&the_windows_nat_target, ptid);
|
||||
|
||||
/* Set the debug registers for the new thread if they are used. */
|
||||
if (debug_registers_used)
|
||||
@ -529,7 +531,7 @@ windows_delete_thread (ptid_t ptid, DWORD exit_code, bool main_thread_p)
|
||||
target_pid_to_str (ptid).c_str (),
|
||||
(unsigned) exit_code);
|
||||
|
||||
delete_thread (find_thread_ptid (ptid));
|
||||
delete_thread (find_thread_ptid (&the_windows_nat_target, ptid));
|
||||
|
||||
for (th = &thread_head;
|
||||
th->next != NULL && th->next->id != id;
|
||||
@ -1524,9 +1526,10 @@ ctrl_c_handler (DWORD event_type)
|
||||
|
||||
/* Get the next event from the child. Returns a non-zero thread id if the event
|
||||
requires handling by WFI (or whatever). */
|
||||
static int
|
||||
get_windows_debug_event (struct target_ops *ops,
|
||||
int pid, struct target_waitstatus *ourstatus)
|
||||
|
||||
int
|
||||
windows_nat_target::get_windows_debug_event (int pid,
|
||||
struct target_waitstatus *ourstatus)
|
||||
{
|
||||
BOOL debug_event;
|
||||
DWORD continue_status, event_code;
|
||||
@ -1556,8 +1559,7 @@ get_windows_debug_event (struct target_ops *ops,
|
||||
"CREATE_THREAD_DEBUG_EVENT"));
|
||||
if (saw_create != 1)
|
||||
{
|
||||
struct inferior *inf;
|
||||
inf = find_inferior_pid (current_event.dwProcessId);
|
||||
inferior *inf = find_inferior_pid (this, current_event.dwProcessId);
|
||||
if (!saw_create && inf->attach_flag)
|
||||
{
|
||||
/* Kludge around a Windows bug where first event is a create
|
||||
@ -1779,7 +1781,7 @@ windows_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
|
||||
the user tries to resume the execution in the inferior.
|
||||
This is a classic race that we should try to fix one day. */
|
||||
SetConsoleCtrlHandler (&ctrl_c_handler, TRUE);
|
||||
retval = get_windows_debug_event (this, pid, ourstatus);
|
||||
retval = get_windows_debug_event (pid, ourstatus);
|
||||
SetConsoleCtrlHandler (&ctrl_c_handler, FALSE);
|
||||
|
||||
if (retval)
|
||||
|
Loading…
x
Reference in New Issue
Block a user