Merge remote-tracking branch 'origin/master' into amd-common
authorLaurent Morichetti <laurent.morichetti@amd.com>
Sat, 11 Jan 2020 23:23:46 +0000 (15:23 -0800)
committerLaurent Morichetti <laurent.morichetti@amd.com>
Sat, 11 Jan 2020 23:23:46 +0000 (15:23 -0800)
Change-Id: I96a19b82dab210c7d98d33c5cd889b0a6f47806d

125 files changed:
bfd/version.h
gdb/ChangeLog
gdb/Makefile.in
gdb/NEWS
gdb/aarch64-linux-nat.c
gdb/ada-tasks.c
gdb/aix-thread.c
gdb/amd64-fbsd-tdep.c
gdb/amd64-linux-nat.c
gdb/break-catch-sig.c
gdb/break-catch-syscall.c
gdb/breakpoint.c
gdb/bsd-kvm.c
gdb/bsd-uthread.c
gdb/btrace.c
gdb/corelow.c
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/doc/guile.texi
gdb/doc/python.texi
gdb/event-top.c
gdb/exceptions.c
gdb/exec.c
gdb/exec.h
gdb/fbsd-nat.c
gdb/fbsd-tdep.c
gdb/fork-child.c
gdb/gdbarch-selftests.c
gdb/gdbserver/ChangeLog
gdb/gdbserver/fork-child.c
gdb/gdbserver/inferiors.c
gdb/gdbserver/linux-low.c
gdb/gdbserver/lynx-low.c
gdb/gdbserver/nto-low.c
gdb/gdbserver/remote-utils.c
gdb/gdbserver/target.c
gdb/gdbserver/target.h
gdb/gdbserver/win32-low.c
gdb/gdbsupport/common-gdbthread.h
gdb/gdbthread.h
gdb/i386-fbsd-tdep.c
gdb/i386-linux-nat.c
gdb/inf-child.c
gdb/inf-ptrace.c
gdb/infcall.c
gdb/infcmd.c
gdb/inferior-iter.h
gdb/inferior.c
gdb/inferior.h
gdb/infrun.c
gdb/infrun.h
gdb/inline-frame.c
gdb/inline-frame.h
gdb/linux-fork.c
gdb/linux-nat.c
gdb/linux-nat.h
gdb/linux-tdep.c
gdb/linux-thread-db.c
gdb/mi/mi-interp.c
gdb/mi/mi-main.c
gdb/nat/fork-inferior.c
gdb/nat/fork-inferior.h
gdb/nto-procfs.c
gdb/ppc-fbsd-tdep.c
gdb/proc-service.c
gdb/process-stratum-target.c
gdb/process-stratum-target.h
gdb/procfs.c
gdb/progspace-and-thread.c
gdb/progspace.c
gdb/python/py-threadevent.c
gdb/ravenscar-thread.c
gdb/record-btrace.c
gdb/record-full.c
gdb/regcache.c
gdb/regcache.h
gdb/remote.c
gdb/riscv-fbsd-tdep.c
gdb/serial.c
gdb/serial.h
gdb/sol-thread.c
gdb/sol2-tdep.c
gdb/solib-svr4.c
gdb/stap-probe.c
gdb/symfile.c
gdb/target-connection.c [new file with mode: 0644]
gdb/target-connection.h [new file with mode: 0644]
gdb/target-delegates.c
gdb/target.c
gdb/target.h
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.base/fork-running-state.exp
gdb/testsuite/gdb.base/kill-detach-inferiors-cmd.exp
gdb/testsuite/gdb.base/quit-live.exp
gdb/testsuite/gdb.base/remote-exec-file.exp [new file with mode: 0644]
gdb/testsuite/gdb.base/stap-probe.c
gdb/testsuite/gdb.base/stap-probe.exp
gdb/testsuite/gdb.guile/scm-progspace.exp
gdb/testsuite/gdb.linespec/linespec.exp
gdb/testsuite/gdb.mi/new-ui-mi-sync.exp
gdb/testsuite/gdb.mi/user-selected-context-sync.exp
gdb/testsuite/gdb.multi/multi-target.c [new file with mode: 0644]
gdb/testsuite/gdb.multi/multi-target.exp [new file with mode: 0644]
gdb/testsuite/gdb.multi/remove-inferiors.exp
gdb/testsuite/gdb.multi/tids-gid-reset.c [new file with mode: 0644]
gdb/testsuite/gdb.multi/tids-gid-reset.exp [new file with mode: 0644]
gdb/testsuite/gdb.multi/watchpoint-multi.exp
gdb/testsuite/gdb.python/py-inferior.exp
gdb/testsuite/gdb.server/bkpt-other-inferior.exp [new file with mode: 0644]
gdb/testsuite/gdb.server/connect-without-multi-process.exp
gdb/testsuite/gdb.server/extended-remote-restart.exp
gdb/testsuite/gdb.threads/async.c [new file with mode: 0644]
gdb/testsuite/gdb.threads/async.exp [new file with mode: 0644]
gdb/testsuite/gdb.threads/fork-plus-threads.exp
gdb/testsuite/gdb.threads/forking-threads-plus-breakpoint.exp
gdb/testsuite/gdb.trace/report.exp
gdb/testsuite/lib/gdbserver-support.exp
gdb/thread-iter.c
gdb/thread-iter.h
gdb/thread.c
gdb/top.c
gdb/tracectf.c
gdb/tracefile-tfile.c
gdb/tracefile.h
gdb/windows-nat.c

index a7060135c1234cf946528f6f1d5e196bc104a33d..a39938344f5eb7fb529a62eb0eb1e3fba289155f 100644 (file)
@@ -16,7 +16,7 @@
 
    In releases, the date is not included in either version strings or
    sonames.  */
-#define BFD_VERSION_DATE 20200110
+#define BFD_VERSION_DATE 20200111
 #define BFD_VERSION @bfd_version@
 #define BFD_VERSION_STRING  @bfd_version_package@ @bfd_version_string@
 #define REPORT_BUGS_TO @report_bugs_to@
index 425bafa9b26a55133a020a31fca8649511490ec3..ed2856c2466203cc85139e1564ae0d8663b29f12 100644 (file)
@@ -1,3 +1,649 @@
+2020-01-10  Tankut Baris Aktemur  <tankut.baris.aktemur@intel.com>
+
+       * inferior.c (print_inferior): Switch inferior before printing it.
+
+2020-01-10  Aleksandar Paunovic  <aleksandar.paunovic@intel.com>
+           Pedro Alves  <palves@redhat.com>
+
+       * progspace-and-thread.c (switch_to_program_space_and_thread):
+       Assert there's an inferior for PSPACE.  Use
+       switch_to_inferior_no_thread to switch the inferior too.
+       * progspace.c (program_space::~program_space): Call
+       clear_symtab_users here, with SYMFILE_DEFER_BP_RESET.
+       (program_space::free_all_objfiles): Don't call clear_symtab_users
+       here.
+       * symfile.c (symbol_file_clear): Call clear_symtab_users here.
+
+2020-01-10  Pedro Alves  <palves@redhat.com>
+
+       * NEWS: Mention multi-target debugging, "info connections", and
+       "add-inferior -no-connection".
+
+2020-01-10  Pedro Alves  <palves@redhat.com>
+
+       * infrun.c: Include "target-connection.h".
+       (check_multi_target_resumption): New.
+       (proceed): Call it.
+       * target-connection.c (make_target_connection_string): Make
+       extern.
+       * target-connection.h (make_target_connection_string): Declare.
+
+2020-01-10  Pedro Alves  <palves@redhat.com>
+
+       * Makefile.in (COMMON_SFILES): Add target-connection.c.
+       * inferior.c (uiout_field_connection): New function.
+       (print_inferior): Add new "connection-id" column.
+       (add_inferior_command): Show connection number/string of added
+       inferior.
+       * process-stratum-target.h
+       (process_stratum_target::connection_string): New virtual method.
+       (process_stratum_target::connection_number): New field.
+       * remote.c (remote_target::connection_string): New override.
+       * target-connection.c: New file.
+       * target-connection.h: New file.
+       * target.c (decref_target): Remove process_stratum targets from
+       the connection list.
+       (target_stack::push): Add process_stratum targets to the
+       connection list.
+
+2020-01-10  Pedro Alves  <palves@redhat.com>
+
+       Revert:
+       2016-04-12  Pedro Alves  <palves@redhat.com>
+       * serial.c (serial_open, serial_fdopen_ops, do_serial_close):
+       Remove references to name.
+       * serial.h (struct serial) <name>: Delete.
+
+2020-01-10  Pedro Alves  <palves@redhat.com>
+
+       * gdbarch-selftests.c (register_to_value_test): Remove "target
+       already pushed" check.
+
+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
+       directly.  Instead find the first thread in the thread list and
+       use switch_to_thread.
+
+2020-01-10  Pedro Alves  <palves@redhat.com>
+
+       * remote.c (remote_target::remote_add_inferior): Don't bind a
+       process to the current inferior if the current inferior is already
+       bound to a process.
+
+2020-01-10  Tankut Baris Aktemur  <tankut.baris.aktemur@intel.com>
+           Pedro Alves  <palves@redhat.com>
+
+       * remote.c (remote_target::remote_parse_stop_reply) <W/X packets>:
+       If no process is specified, return null_ptid instead of
+       inferior_ptid.
+       (remote_target::wait_as): Handle TARGET_WAITKIND_EXITED /
+       TARGET_WAITKIND_SIGNALLED with no pid.
+
+2020-01-10  Pedro Alves  <palves@redhat.com>
+
+       * remote.c (first_remote_resumed_thread): New.
+       (remote_target::wait_as): Use it as default event_ptid instead of
+       inferior_ptid.
+
+2020-01-10  Pedro Alves  <palves@redhat.com>
+
+       * infrun.c (handle_no_resumed): Use all_non_exited_inferiors.
+
+2020-01-10  Pedro Alves  <palves@redhat.com>
+
+       * tracefile-tfile.c (tfile_target::close): Assert that trace_fd is
+       not -1.
+
+2020-01-10  Pedro Alves  <palves@redhat.com>
+
+       * break-catch-sig.c (signal_catchpoint_print_it): Don't pass a
+       ptid to get_last_target_status.
+       * break-catch-syscall.c (print_it_catch_syscall): Don't pass a
+       ptid to get_last_target_status.
+       * infcmd.c (continue_command): Don't pass a target_waitstatus to
+       get_last_target_status.
+       (info_program_command): Don't pass a target_waitstatus to
+       get_last_target_status.
+       * infrun.c (init_wait_for_inferior): Use
+       nullify_last_target_wait_ptid.
+       (get_last_target_status): Handle nullptr arguments.
+       (nullify_last_target_wait_ptid): Clear target_last_waitstatus.
+       (print_stop_event): Don't pass a ptid to get_last_target_status.
+       (normal_stop): Don't pass a ptid to get_last_target_status.
+       * infrun.h (get_last_target_status, set_last_target_status): Move
+       comments here and update.
+       (nullify_last_target_wait_ptid): Declare.
+       * linux-fork.c (fork_load_infrun_state): Remove local extern
+       declaration of nullify_last_target_wait_ptid.
+       * linux-nat.c (get_detach_signal): Don't pass a target_waitstatus
+       to get_last_target_status.
+
+2020-01-10  Pedro Alves  <palves@redhat.com>
+
+       * gdbthread.h (scoped_restore_current_thread)
+       <dont_restore, restore, m_dont_restore>: Declare.
+       * thread.c (thread_alive): Add assertion.  Return bool.
+       (switch_to_thread_if_alive): New.
+       (prune_threads): Switch inferior/thread.
+       (print_thread_info_1): Switch thread before calling target methods.
+       (scoped_restore_current_thread::restore): New, factored out from
+       ...
+       (scoped_restore_current_thread::~scoped_restore_current_thread):
+       ... this.
+       (scoped_restore_current_thread::scoped_restore_current_thread):
+       Add assertion.
+       (thread_apply_all_command, thread_select): Use
+       switch_to_thread_if_alive.
+       * infrun.c (proceed, restart_threads, handle_signal_stop)
+       (switch_back_to_stepped_thread): Switch current thread before
+       calling target methods.
+
+2020-01-10  Pedro Alves <palves@redhat.com>
+
+       * inferior.c (switch_to_inferior_no_thread): New function,
+       factored out from ...
+       (inferior_command): ... here.
+       * inferior.h (switch_to_inferior_no_thread): Declare.
+       * mi/mi-main.c (run_one_inferior): Use
+       switch_to_inferior_no_thread.
+
+2020-01-10  Pedro Alves  <palves@redhat.com>
+
+       * infcmd.c (kill_command): Remove dead code.
+
+2020-01-10  Pedro Alves  <palves@redhat.com>
+
+       * remote.c (remote_target::mourn_inferior): No longer check
+       whether the target is running.
+
+2020-01-10  Pedro Alves  <palves@redhat.com>
+
+       * corelow.c (core_target::has_execution): Change parameter type to
+       inferior pointer.
+       * inferior.c (number_of_live_inferiors): Use
+       inferior::has_execution instead of target_has_execution_1.
+       * inferior.h (inferior::has_execution): New.
+       * linux-thread-db.c (thread_db_target::update_thread_list): Use
+       inferior::has_execution instead of target_has_execution_1.
+       * process-stratum-target.c
+       (process_stratum_target::has_execution): Change parameter type to
+       inferior pointer.  Check the inferior's PID instead of
+       inferior_ptid.
+       * process-stratum-target.h
+       (process_stratum_target::has_execution): Change parameter type to
+       inferior pointer.
+       * record-full.c (record_full_core_target::has_execution): Change
+       parameter type to inferior pointer.
+       * target.c (target_has_execution_1): Change parameter type to
+       inferior pointer.
+       (target_has_execution_current): Adjust.
+       * target.h (target_ops::has_execution): Change parameter type to
+       inferior pointer.
+       (target_has_execution_1): Change parameter type to inferior
+       pointer.  Change return type to bool.
+       * tracefile.h (tracefile_target::has_execution): Change parameter
+       type to inferior pointer.
+
+2020-01-10  Pedro Alves  <palves@redhat.com>
+
+       * exceptions.c (print_flush): Remove current_top_target() check.
+
+2020-01-10  Pedro Alves  <palves@redhat.com>
+
+       * remote.c (show_remote_exec_file): Show the current inferior's
+       exec-file instead of the command variable's value.
+
+2020-01-10  Pedro Alves  <palves@redhat.com>
+
+       * record-full.c (record_full_resume_ptid): New global.
+       (record_full_target::resume): Set it.
+       (record_full_wait_1): Use record_full_resume_ptid instead of
+       inferior_ptid.
+
+2020-01-10  Pedro Alves  <palves@redhat.com>
+
+       * gdbthread.h (scoped_restore_current_thread)
+       <dont_restore, restore, m_dont_restore>: Declare.
+       * thread.c (thread_alive): Add assertion.  Return bool.
+       (switch_to_thread_if_alive): New.
+       (prune_threads): Switch inferior/thread.
+       (print_thread_info_1): Switch thread before calling target methods.
+       (scoped_restore_current_thread::restore): New, factored out from
+       ...
+       (scoped_restore_current_thread::~scoped_restore_current_thread):
+       ... this.
+       (scoped_restore_current_thread::scoped_restore_current_thread):
+       Add assertion.
+       (thread_apply_all_command, thread_select): Use
+       switch_to_thread_if_alive.
+
+2020-01-10  George Barrett  <bob@bob131.so>
+
+       * stap-probe.c (stap_modify_semaphore): Don't check for null
+       semaphores.
+       (stap_probe::set_semaphore, stap_probe::clear_semaphore): Check
+       for null semaphores.
+
 2020-01-09  Andrew Burgess  <andrew.burgess@embecosm.com>
 
        * tui/tui-source.c (tui_source_window::do_scroll_vertical): Update
index 084c83dcef7ef25458f7a71796e0c2cef6bc22df..e852b140e7acd0306e77347694ed59e95231226f 100644 (file)
@@ -1141,6 +1141,7 @@ COMMON_SFILES = \
        symmisc.c \
        symtab.c \
        target.c \
+       target-connection.c \
        target-dcache.c \
        target-descriptions.c \
        target-memory.c \
index 8405bd06320aa70e438e182820aaabfae9fccb63..1305eceecafae888bdeb1c9d5334ad48247241f5 100644 (file)
--- a/gdb/NEWS
+++ b/gdb/NEWS
   This feature is still in testing, so it is disabled by default.  You
   can turn it on using 'maint set worker-threads unlimited'.
 
+* Multi-target debugging support
+
+  GDB now supports debugging multiple target connections
+  simultaneously.  For example, you can now have each inferior
+  connected to different remote servers running in different machines,
+  or have one inferior debugging a local native process, an inferior
+  debugging a core dump, etc.
+
+  This support is experimental and comes with some limitations -- you
+  can only resume multiple targets simultaneously if all targets
+  support non-stop mode, and all remote stubs or servers must support
+  the same set of remote protocol features exactly.  See also "info
+  connections" and "add-inferior -no-connection" below, and "maint set
+  target-non-stop" in the user manual.
+
 * Python API
 
   ** The gdb.Value type has a new method 'format_string' which returns a
@@ -243,6 +258,9 @@ show debug remote-packet-max-chars
   "set debug remote".
   The default is 512 bytes.
 
+info connections
+  Lists the target connections currently in use.
+
 * Changed commands
 
 help
@@ -287,6 +305,17 @@ show print raw-frame-arguments
   old commands are now deprecated and may be removed in a future
   release.
 
+add-inferior [-no-connection]
+  The add-inferior command now supports a "-no-connection" flag that
+  makes the new inferior start with no target connection associated.
+  By default, the new inferior inherits the target connection of the
+  current inferior.  See also "info connections".
+
+info inferior
+  This command's output now includes a new "Connection" column
+  indicating which target connection an inferior is bound to.  See
+  "info connections" above.
+
 maint test-options require-delimiter
 maint test-options unknown-is-error
 maint test-options unknown-is-operand
index 4e712ebfb7511fcdb6f848e4c335476450e1286d..b385b5866c0d718f569066b5a473373ef40ae30b 100644 (file)
@@ -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;
index 4f83084bcd0c874a2daab5e9626a4cd2400c8dde..0b7a8eb4ad46378eadea684c679020c3aa1966cf 100644 (file)
@@ -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."),
index efecf417dbb33d5bd2596c43bcdda351454e949a..b9b25d5e3cb637f7a79cd8bf1f00f2cc49672a52 100644 (file)
@@ -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
index f71bddfe06653e79f4d5d5d1f85d412913da8d9e..b0639ed95a672102ccf0395c99610dc2ad074b90 100644 (file)
@@ -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);
 
index f98d992070a340d0c37d249f0a8c10a3c5d71aa9..27748ff9860081f577de143b1b197ab314dc2e4f 100644 (file)
@@ -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;
index a9ec583414003fe412ca4f3e06fcceff17335d33..c645746aa834f83f3eabdd9db809b1b94961863e 100644 (file)
@@ -181,12 +181,11 @@ static enum print_stop_action
 signal_catchpoint_print_it (bpstat bs)
 {
   struct breakpoint *b = bs->breakpoint_at;
-  ptid_t ptid;
   struct target_waitstatus last;
   const char *signal_name;
   struct ui_out *uiout = current_uiout;
 
-  get_last_target_status (&ptid, &last);
+  get_last_target_status (nullptr, nullptr, &last);
 
   signal_name = signal_to_name_or_int (last.value.sig);
 
index 97eb100e6de9c32c4fccb52f3b3597ee57c65d80..553c01cb320378e9c83031769867ed9959a5e79c 100644 (file)
@@ -182,12 +182,11 @@ print_it_catch_syscall (bpstat bs)
      syscall is.  It can be in the TARGET_WAITKIND_SYSCALL_ENTRY
      or TARGET_WAITKIND_SYSCALL_RETURN, and depending on it we
      must print "called syscall" or "returned from syscall".  */
-  ptid_t ptid;
   struct target_waitstatus last;
   struct syscall s;
   struct gdbarch *gdbarch = bs->bp_location_at->gdbarch;
 
-  get_last_target_status (&ptid, &last);
+  get_last_target_status (nullptr, nullptr, &last);
 
   get_syscall_by_number (gdbarch, last.value.syscall_number, &s);
 
index 75b45c3db8657cafec63b6c040d7636ab39b758b..9e8291b4af0d2084731d801ec3990899ba633d13 100644 (file)
@@ -393,7 +393,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)
        {
@@ -402,8 +402,10 @@ breakpoints_should_be_inserted_now (void)
          return 1;
        }
 
-      if (threads_are_executing ())
-       return 1;
+      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
         stopped, we still have events to process.  */
@@ -2891,7 +2893,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,
@@ -2947,7 +2949,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,
@@ -11909,7 +11911,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);
index 28e6fcfa14415187e0d57e99c81a2b3f3ea11a7b..f864ba8b41ced3688fc922ef47ffbc571de3f0bb 100644 (file)
@@ -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);
index eb9dcb615b869e585c0b8c8852bdf76e8936ed88..a8622a8b0e47346e94ef49aaf2e39431a4fac0a9 100644 (file)
@@ -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);
index 407f01ad740f0e43a54f157cace35fad42aa4f38..a91a67681302ad032e6974fcebfca9d8ca92f3eb 100644 (file)
@@ -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."));
 
index 0ec70c28b90d16b540a3eb08250af8ef74b968c1..c53bf1df8fd80a542d940efccd5d27b419308378 100644 (file)
@@ -94,7 +94,7 @@ public:
   bool has_memory () override;
   bool has_stack () override;
   bool has_registers () override;
-  bool has_execution (ptid_t) override { return false; }
+  bool has_execution (inferior *inf) override { return false; }
 
   bool info_proc (const char *, enum info_proc_what) override;
 
@@ -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);
 
index e8903d8b464c7bd17a9b01a13a51f12015f9a896..3e89aedaaa3c4271179adb3165fa0de513608923 100644 (file)
@@ -1,3 +1,14 @@
+2020-01-10  Pedro Alves  <palves@redhat.com>
+
+       * gdb.texinfo (Starting): Say "current inferior not connected"
+       instead of "GDB not connected".
+       (Inferiors and Programs): Rename node to ...
+       (Inferiors Connections and Programs): ... this.  Update all
+       references.  Talk about multiple target connections.  Update "info
+       inferiors" info to mention the connections column.  Describe "info
+       connections".  Document "add-inferior -no-connection".
+       * guile.texi, python.texi: Update cross references.
+
 2020-01-01  Joel Brobecker  <brobecker@adacore.com>
 
        * gdb.texinfo, refcard.tex: Update copyright year range.
index 65137b17396466d6d9179a910979df65057e3b16..67882d0cd89bf61b0e79520e5896b698eebbf862 100644 (file)
@@ -2250,8 +2250,8 @@ kill a child process.
 * Input/Output::                Your program's input and output
 * Attach::                      Debugging an already-running process
 * Kill Process::                Killing the child process
-
-* Inferiors and Programs::      Debugging multiple inferiors and programs
+* Inferiors Connections and Programs:: Debugging multiple inferiors
+                                        connections and programs
 * Threads::                     Debugging programs with multiple threads
 * Forks::                       Debugging forks
 * Checkpoint/Restart::          Setting a @emph{bookmark} to return to later
@@ -2506,27 +2506,28 @@ $@file{.zshenv} for the Z shell, or the file specified in the
 @itemx set auto-connect-native-target off
 @itemx show auto-connect-native-target
 
-By default, if not connected to any target yet (e.g., with
-@code{target remote}), the @code{run} command starts your program as a
-native process under @value{GDBN}, on your local machine.  If you're
-sure you don't want to debug programs on your local machine, you can
-tell @value{GDBN} to not connect to the native target automatically
-with the @code{set auto-connect-native-target off} command.
+By default, if the current inferior is not connected to any target yet
+(e.g., with @code{target remote}), the @code{run} command starts your
+program as a native process under @value{GDBN}, on your local machine.
+If you're sure you don't want to debug programs on your local machine,
+you can tell @value{GDBN} to not connect to the native target
+automatically with the @code{set auto-connect-native-target off}
+command.
 
-If @code{on}, which is the default, and if @value{GDBN} is not
+If @code{on}, which is the default, and if the current inferior is not
 connected to a target already, the @code{run} command automaticaly
 connects to the native target, if one is available.
 
-If @code{off}, and if @value{GDBN} is not connected to a target
-already, the @code{run} command fails with an error:
+If @code{off}, and if the current inferior is not connected to a
+target already, the @code{run} command fails with an error:
 
 @smallexample
 (@value{GDBP}) run
 Don't know how to run.  Try "help target".
 @end smallexample
 
-If @value{GDBN} is already connected to a target, @value{GDBN} always
-uses it with the @code{run} command.
+If the current inferior is already connected to a target, @value{GDBN}
+always uses it with the @code{run} command.
 
 In any case, you can explicitly connect to the native target with the
 @code{target native} command.  For example,
@@ -2956,15 +2957,17 @@ next type @code{run}, @value{GDBN} notices that the file has changed, and
 reads the symbol table again (while trying to preserve your current
 breakpoint settings).
 
-@node Inferiors and Programs
-@section Debugging Multiple Inferiors and Programs
+@node Inferiors Connections and Programs
+@section Debugging Multiple Inferiors Connections and Programs
 
 @value{GDBN} lets you run and debug multiple programs in a single
 session.  In addition, @value{GDBN} on some systems may let you run
 several programs simultaneously (otherwise you have to exit from one
-before starting another).  In the most general case, you can have
-multiple threads of execution in each of multiple processes, launched
-from multiple executables.
+before starting another).  On some systems @value{GDBN} may even let
+you debug several programs simultaneously on different remote systems.
+In the most general case, you can have multiple threads of execution
+in each of multiple processes, launched from multiple executables,
+running on different machines.
 
 @cindex inferior
 @value{GDBN} represents the state of each program execution with an
@@ -2998,6 +3001,11 @@ the inferior number assigned by @value{GDBN}
 @item
 the target system's inferior identifier
 
+@item
+the target connection the inferior is bound to, including the unique
+connection number assigned by @value{GDBN}, and the protocol used by
+the connection.
+
 @item
 the name of the executable the inferior is running.
 
@@ -3013,9 +3021,51 @@ For example,
 
 @smallexample
 (@value{GDBP}) info inferiors
-  Num  Description       Executable
-  2    process 2307      hello
-* 1    process 3401      goodbye
+  Num  Description       Connection                      Executable
+* 1    process 3401      1 (native)                      goodbye
+  2    process 2307      2 (extended-remote host:10000)  hello
+@end smallexample
+
+To find out what open target connections exist at any moment, use
+@w{@code{info connections}}:
+
+@table @code
+@kindex info connections [ @var{id}@dots{} ]
+@item info connections
+Print a list of all open target connections currently being managed by
+@value{GDBN}.  By default all connections are printed, but the
+argument @var{id}@dots{} -- a space separated list of connections
+numbers -- can be used to limit the display to just the requested
+connections.
+
+@value{GDBN} displays for each connection (in this order):
+
+@enumerate
+@item
+the connection number assigned by @value{GDBN}.
+
+@item
+the protocol used by the connection.
+
+@item
+a textual description of the protocol used by the connection.
+
+@end enumerate
+
+@noindent
+An asterisk @samp{*} preceding the connection number indicates the
+connection of the current inferior.
+
+For example,
+@end table
+@c end table here to get a little more width for example
+
+@smallexample
+(@value{GDBP}) info connections
+  Num  What                        Description
+* 1    extended-remote host:10000  Extended remote serial target in gdb-specific protocol
+  2    native                      Native process
+  3    core                        Local core dump file
 @end smallexample
 
 To switch focus between inferiors, use the @code{inferior} command:
@@ -3044,13 +3094,22 @@ remove inferiors from the debugging session use the
 
 @table @code
 @kindex add-inferior
-@item add-inferior [ -copies @var{n} ] [ -exec @var{executable} ]
+@item add-inferior [ -copies @var{n} ] [ -exec @var{executable} ] [-no-connection ]
 Adds @var{n} inferiors to be run using @var{executable} as the
 executable; @var{n} defaults to 1.  If no executable is specified,
 the inferiors begins empty, with no program.  You can still assign or
 change the program assigned to the inferior at any time by using the
 @code{file} command with the executable name as its argument.
 
+By default, the new inferior begins connected to the same target
+connection as the current inferior.  For example, if the current
+inferior was connected to @code{gdbserver} with @code{target remote},
+then the new inferior will be connected to the same @code{gdbserver}
+instance.  The @samp{-no-connection} option starts the new inferior
+with no connection yet.  You can then for example use the @code{target
+remote} command to connect to some other @code{gdbserver} instance,
+use @code{run} to spawn a local program, etc.
+
 @kindex clone-inferior
 @item clone-inferior [ -copies @var{n} ] [ @var{infno} ]
 Adds @var{n} inferiors ready to execute the same program as inferior
@@ -3060,15 +3119,15 @@ want to run another instance of the inferior you are debugging.
 
 @smallexample
 (@value{GDBP}) info inferiors
-  Num  Description       Executable
-* 1    process 29964     helloworld
+  Num  Description       Connection   Executable
+* 1    process 29964     1 (native)   helloworld
 (@value{GDBP}) clone-inferior
 Added inferior 2.
 1 inferiors added.
 (@value{GDBP}) info inferiors
-  Num  Description       Executable
-  2    <null>            helloworld
-* 1    process 29964     helloworld
+  Num  Description       Connection   Executable
+* 1    process 29964     1 (native)   helloworld
+  2    <null>            1 (native)   helloworld
 @end smallexample
 
 You can now simply switch focus to inferior 2 and run it.
@@ -3721,14 +3780,14 @@ If you choose to set @samp{detach-on-fork} mode off, then @value{GDBN}
 will retain control of all forked processes (including nested forks).
 You can list the forked processes under the control of @value{GDBN} by
 using the @w{@code{info inferiors}} command, and switch from one fork
-to another by using the @code{inferior} command (@pxref{Inferiors and
-Programs, ,Debugging Multiple Inferiors and Programs}).
+to another by using the @code{inferior} command (@pxref{Inferiors Connections and
+Programs, ,Debugging Multiple Inferiors Connections and Programs}).
 
 To quit debugging one of the forked processes, you can either detach
 from it by using the @w{@code{detach inferiors}} command (allowing it
 to run independently), or kill it using the @w{@code{kill inferiors}}
-command.  @xref{Inferiors and Programs, ,Debugging Multiple Inferiors
-and Programs}.
+command.  @xref{Inferiors Connections and Programs, ,Debugging
+Multiple Inferiors Connections and Programs}.
 
 If you ask to debug a child process and a @code{vfork} is followed by an
 @code{exec}, @value{GDBN} executes the new target up to the first
@@ -11911,8 +11970,8 @@ gdbserver that supports the @code{qGetTIBAddr} request.
 This variable contains the address of the thread information block.
 
 @item $_inferior
-The number of the current inferior.  @xref{Inferiors and
-Programs, ,Debugging Multiple Inferiors and Programs}.
+The number of the current inferior.  @xref{Inferiors Connections and
+Programs, ,Debugging Multiple Inferiors Connections and Programs}.
 
 @item $_thread
 The thread number of the current thread.  @xref{thread numbers}.
@@ -13108,7 +13167,7 @@ character.
 
 @value{GDBN} caches data exchanged between the debugger and a target.
 Each cache is associated with the address space of the inferior.
-@xref{Inferiors and Programs}, about inferior and address space.
+@xref{Inferiors Connections and Programs}, about inferior and address space.
 Such caching generally improves performance in remote debugging
 (@pxref{Remote Debugging}), because it reduces the overhead of the
 remote protocol by bundling memory reads and writes into large chunks.
@@ -28524,7 +28583,7 @@ groups can be obtained using @samp{-list-thread-groups --available}.
 In general, the content of a thread group may be only retrieved only
 after attaching to that thread group.
 
-Thread groups are related to inferiors (@pxref{Inferiors and
+Thread groups are related to inferiors (@pxref{Inferiors Connections and
 Programs}).  Each inferior corresponds to a thread group of a special
 type @samp{process}, and some additional operations are permitted on
 such thread groups.
@@ -35903,7 +35962,7 @@ popup menu, but is needless clutter on the command line, and
 -add-inferior
 @end smallexample
 
-Creates a new inferior (@pxref{Inferiors and Programs}).  The created
+Creates a new inferior (@pxref{Inferiors Connections and Programs}).  The created
 inferior is not associated with any executable.  Such association may
 be established with the @samp{-file-exec-and-symbols} command
 (@pxref{GDB/MI File Commands}).  The command response has a single
@@ -46189,11 +46248,11 @@ command, otherwise you may get an error that looks something like
 @command{gdbserver} can also debug multiple inferiors at once,
 described in
 @ifset man
-the @value{GDBN} manual in node @code{Inferiors and Programs}
--- shell command @code{info -f gdb -n 'Inferiors and Programs'}.
+the @value{GDBN} manual in node @code{Inferiors Connections and Programs}
+-- shell command @code{info -f gdb -n 'Inferiors Connections and Programs'}.
 @end ifset
 @ifclear man
-@ref{Inferiors and Programs}.
+@ref{Inferiors Connections and Programs}.
 @end ifclear
 In such case use the @code{extended-remote} @value{GDBN} command variant:
 
index 53b8695c69149a673324ae39fec98fe17bbfd04f..c0bff7972f7d3810bb6f9bd55ac8050ac80ce477 100644 (file)
@@ -2155,7 +2155,7 @@ A program space, or @dfn{progspace}, represents a symbolic view
 of an address space.
 It consists of all of the objfiles of the program.
 @xref{Objfiles In Guile}.
-@xref{Inferiors and Programs, program spaces}, for more details
+@xref{Inferiors Connections and Programs, program spaces}, for more details
 about program spaces.
 
 Each progspace is represented by an instance of the @code{<gdb:progspace>}
@@ -2178,7 +2178,7 @@ if the program it refers to is not loaded in @value{GDBN} any longer.
 @deffn {Scheme Procedure} current-progspace
 This function returns the program space of the currently selected inferior.
 There is always a current progspace, this never returns @code{#f}.
-@xref{Inferiors and Programs}.
+@xref{Inferiors Connections and Programs}.
 @end deffn
 
 @deffn {Scheme Procedure} progspaces
index 8124077ab33a1f794bcdd8c04530cd61200d0ce7..100b2b2b61d926951ba16529e362bcd10ac7da86 100644 (file)
@@ -2928,7 +2928,7 @@ itself.
 
 @findex gdb.Inferior
 Programs which are being run under @value{GDBN} are called inferiors
-(@pxref{Inferiors and Programs}).  Python scripts can access
+(@pxref{Inferiors Connections and Programs}).  Python scripts can access
 information about and manipulate inferiors controlled by @value{GDBN}
 via objects of the @code{gdb.Inferior} class.
 
@@ -4161,7 +4161,7 @@ A program space, or @dfn{progspace}, represents a symbolic view
 of an address space.
 It consists of all of the objfiles of the program.
 @xref{Objfiles In Python}.
-@xref{Inferiors and Programs, program spaces}, for more details
+@xref{Inferiors Connections and Programs, program spaces}, for more details
 about program spaces.
 
 The following progspace-related functions are available in the
@@ -4170,7 +4170,7 @@ The following progspace-related functions are available in the
 @findex gdb.current_progspace
 @defun gdb.current_progspace ()
 This function returns the program space of the currently selected inferior.
-@xref{Inferiors and Programs}.  This is identical to
+@xref{Inferiors Connections and Programs}.  This is identical to
 @code{gdb.selected_inferior().progspace} (@pxref{Inferiors In Python}) and is
 included for historical compatibility.
 @end defun
index a5f8c68be98e8ef9b928b6fb82607ecd0853c22f..3f10b21280d6626382932b30ffce702c9c814167 100644 (file)
@@ -1137,12 +1137,16 @@ async_disconnect (gdb_client_data arg)
       exception_print (gdb_stderr, exception);
     }
 
-  try
-    {
-      pop_all_targets ();
-    }
-  catch (const gdb_exception &exception)
+  for (inferior *inf : all_inferiors ())
     {
+      switch_to_inferior_no_thread (inf);
+      try
+       {
+         pop_all_targets ();
+       }
+      catch (const gdb_exception &exception)
+       {
+       }
     }
 
   signal (SIGHUP, SIG_DFL);    /*FIXME: ???????????  */
index 587988ac803f501d4c8d89b2228a9cf4d7ea15b8..52cee4e2f6d73ecdfadde9db9c44f7cc1da26b2a 100644 (file)
@@ -39,11 +39,7 @@ print_flush (void)
     deprecated_error_begin_hook ();
 
   gdb::optional<target_terminal::scoped_restore_terminal_state> term_state;
-  /* While normally there's always something pushed on the target
-     stack, the NULL check is needed here because we can get here very
-     early during startup, before the target stack is first
-     initialized.  */
-  if (current_top_target () != NULL && target_supports_terminal_ours ())
+  if (target_supports_terminal_ours ())
     {
       term_state.emplace ();
       target_terminal::ours_for_output ();
index 906ae616b0f79d0c2149a62960fe08be019f3904..468f9f57f76cceee2156f77887d58dcd0cb595fe 100644 (file)
@@ -547,10 +547,23 @@ 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))
-       push_target (&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);
+       }
     }
 }
 
@@ -628,21 +641,39 @@ 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;
+
+         for (inferior *inf : all_inferiors ())
+           {
+             if (inf->pspace != curr_pspace)
+               continue;
 
-         ALL_PSPACES (pspace)
-           if (pspace->target_sections.sections
-               != pspace->target_sections.sections_end)
-             return;
+             if (inf->pspace->target_sections.sections
+                 != inf->pspace->target_sections.sections_end)
+               continue;
 
-         unpush_target (&exec_ops);
+             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);
+}
+
 \f
 
 enum target_xfer_status
index e50a3a0f49a9ac7fdc8c67c9dc4dc7cd3c8516e0..54e6ff4d9bab6c2c6f730b1faaf5a4062e20ce65 100644 (file)
@@ -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
index f0f1e791cbd2f5fe01438c83968800e5b955667e..698d1f0b35e108f961b288108cb38f8f8e298dcb 100644 (file)
@@ -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
index ff642d5658699914fea0419fbcb98fbef2d1ebb5..9e5d23a4bc8def5dd4b7edd309bd123c807a7987 100644 (file)
@@ -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);
 
index 3e9e7f9e2c45a71071f6fe79240cc66427dd70ac..65a189e0487897fc67b3bc5bcff7a545a248398b 100644 (file)
@@ -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;
 }
index 031d40f4ef05618a1f1d2a646b84bf9198434d77..47f4d99d18c9211f03d4066d72c6dc2ba0bb72f2 100644 (file)
@@ -71,11 +71,6 @@ register_to_value_test (struct gdbarch *gdbarch)
       builtin->builtin_char32,
     };
 
-  /* Error out if debugging something, because we're going to push the
-     test target, which would pop any existing target.  */
-  if (current_top_target ()->stratum () >= process_stratum)
-   error (_("target already pushed"));
-
   /* Create a mock environment.  An inferior with a thread, with a
      process_stratum target pushed.  */
 
index 63778e2d2a3581595ef5f3cf9a3baa57f29f28ba..b62ed4c02b47e8bcee507045e566419c571a4b3b 100644 (file)
@@ -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>
 
index 0a53a250bd4eca3d42de78b14f7bbf78f07b255b..7a71ec0b1cafbc7dddaafb1cccd4d42e0ab8353f 100644 (file)
@@ -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;
index fe7161c446c084a6d41350aa7bbcb9d66917ee2a..cf6e914863b69e79d8afc466b5f1e66502696ec3 100644 (file)
@@ -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);
index 4255795ea674bc660a745757977fd9c286d0285f..676dea26c637afbd0a146f78810f20ccbda0b830 100644 (file)
@@ -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,
index decbe49c51b7215f1dcac08c1ac0b8b886de2931..a5b019396fa4f784ca54853ffdc1ce2e989e4ba5 100644 (file)
@@ -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,
index 8af5cf6f4768b327bb35e9dc1953ded6bdc827c5..b4dea479b9c3a01d8ec08cbe612cff5dd37121dd 100644 (file)
@@ -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,
index b757740ecec204fdbf277de1d41ea31de4a67bc8..b8a8c6576f974b57264d1f6f8c18de79a5b72cb8 100644 (file)
@@ -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;
 
index f3887b3e87793993c5874c48c8550ae54a36b69b..a4593cf6df91c1f58951aa17b95d7ddbe0d55cbb 100644 (file)
@@ -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));
 }
 
index 2681078cf2154a9bd1fa60a5622b3f9400581e9e..1b0810ba04987e2522a00735833ee7c7e5d290bc 100644 (file)
@@ -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);
index 340f65bbf95a49ccf4677adc972d62673f4ca8e3..2c4a9b1074b2f857d744b3831204604146395935 100644 (file)
@@ -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,
index 57d087030165f2b5992ef8d7fff0694ad3e5e53f..050ad80322b500321e5210cbb045225c661ad8e8 100644 (file)
 #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 */
index dc7e248bc03abae1aa2ef73bb07c7071b8e7b512..f205e29dd7dd2f1e4957c2ae3473e15a770fa454 100644 (file)
@@ -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);
-
-/* Marks thread PTID as executing, or not.  If PTID is minus_one_ptid,
-   marks all threads.
+   pointed at by {TARG,PTID}.  */
+extern void set_resumed (process_stratum_target *targ,
+                        ptid_t ptid, bool resumed);
+
+/* 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.  */
@@ -645,7 +670,13 @@ public:
 
   DISABLE_COPY_AND_ASSIGN (scoped_restore_current_thread);
 
+  /* Cancel restoring on scope exit.  */
+  void dont_restore () { m_dont_restore = true; }
+
 private:
+  void restore ();
+
+  bool m_dont_restore = false;
   /* Use the "class" keyword here, because of a clash with a "thread_info"
      function in the Darwin API.  */
   class thread_info *m_thread;
index cb66bbf6c7a0befc74b352ba73842452ae755d76..d072709929067d7a0eb6875b54bcbe91f8778a80 100644 (file)
@@ -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);
 
index 9ed4c9c09ba96403cf620ac65fa6fe3b32858787..32cd879de80b9bb87050fb6599f3822d179e3909 100644 (file)
@@ -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;
index a9bb8d22af753333993763970a49c8c9a7b09fcf..48330948895085e4ec8e82f35d77276c0457439a 100644 (file)
@@ -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);
 }
 
index 4ad1cd0622725c90a1414fb5471f032453d60e79..ecd82ada4ed3deaa5cfed5c575a51fdd830c338a 100644 (file)
@@ -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 ();
 }
index 26111378c89a1d21738975cf7c05050a86bd8ccb..240644a4eef9cfcc909053c08a6a91dc21adf974 100644 (file)
@@ -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 ();
 
index a1f9d4e08c82931775f9526e29c80bd5df5c775a..2bf21e26f1924e0af1b3c94ff88e677a3be80909 100644 (file)
@@ -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,11 +862,11 @@ continue_command (const char *args, int from_tty)
        tp = inferior_thread ();
       else
        {
+         process_stratum_target *last_target;
          ptid_t last_ptid;
-         struct target_waitstatus ws;
 
-         get_last_target_status (&last_ptid, &ws);
-         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;
@@ -882,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 ();
@@ -893,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);
 }
 \f
 /* Record the starting point of a "step" or "next" command.  */
@@ -1113,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);
 
@@ -1317,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);
+
+      thread_info *current = inferior_thread ();
 
-      for (thread_info *tp : all_non_exited_threads (resume_ptid))
+      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
@@ -1983,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)
     {
@@ -1991,18 +2008,17 @@ info_program_command (const char *args, int from_tty)
     }
 
   if (non_stop)
-    ptid = inferior_ptid;
-  else
     {
-      struct target_waitstatus ws;
-
-      get_last_target_status (&ptid, &ws);
+      ptid = inferior_ptid;
+      proc_target = current_inferior ()->process_target ();
     }
+  else
+    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."));
@@ -2511,20 +2527,6 @@ kill_command (const char *arg, int from_tty)
     printf_unfiltered (_("[Inferior %d (%s) killed]\n"),
                       infnum, pid_str.c_str ());
 
-  /* If we still have other inferiors to debug, then don't mess with
-     with their threads.  */
-  if (!have_inferiors ())
-    {
-      init_thread_list ();             /* Destroy thread info.  */
-
-      /* Killing off the inferior can leave us with a core file.  If
-        so, print the state we are left in.  */
-      if (target_has_stack)
-       {
-         printf_filtered (_("In %s,\n"), target_longname);
-         print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC, 1);
-       }
-    }
   bfd_cache_close_all ();
 }
 
@@ -2805,12 +2807,16 @@ 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;
     }
-
-  attach_post_wait (args, from_tty, mode);
+  else
+    attach_post_wait (args, from_tty, mode);
 }
 
 /* We had just found out that the target was already attached to an
@@ -2927,20 +2933,15 @@ disconnect_command (const char *args, int from_tty)
     deprecated_detach_hook ();
 }
 
-void 
-interrupt_target_1 (int all_threads)
-{
-  ptid_t ptid;
-
-  if (all_threads)
-    ptid = minus_one_ptid;
-  else
-    ptid = inferior_ptid;
+/* 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.  */
 
-  if (non_stop)
-    target_stop (ptid);
-  else
-    target_interrupt ();
+static void
+stop_current_target_threads_ns (ptid_t ptid)
+{
+  target_stop (ptid);
 
   /* Tag the thread as having been explicitly requested to stop, so
      other parts of gdb know not to resume this thread automatically,
@@ -2948,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]
index fb6da8a305fb7074cb87ea7b1c8d0fe7b2c926f6..8061dcca4efec016daa07b7a2064c523c48e0d19 100644 (file)
@@ -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) */
index e0c2ab24dd81991a2469e5e1e237eb338832809c..eb090dfde1a5850c6619b51440762e277e1a008f 100644 (file)
@@ -90,6 +90,8 @@ inferior::inferior (int pid_)
     registry_data ()
 {
   inferior_alloc_data (this);
+
+  m_target_stack.push (get_dummy_target ());
 }
 
 struct inferior *
@@ -247,6 +249,7 @@ inferior_appeared (struct inferior *inf, int pid)
 {
   /* If this is the first inferior with threads, reset the global
      thread id.  */
+  delete_exited_threads ();
   if (!any_thread_p ())
     init_thread_list ();
 
@@ -275,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;
 
@@ -292,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.  */
@@ -339,12 +342,12 @@ 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 ())
-    if (target_has_execution_1 (ptid_t (inf->pid)))
+  for (inferior *inf : all_non_exited_inferiors (proc_target))
+    if (inf->has_execution ())
       for (thread_info *tp ATTRIBUTE_UNUSED : inf->non_exited_threads ())
        {
          /* Found a live thread in this inferior, go to the next
@@ -361,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
@@ -425,6 +428,31 @@ print_selected_inferior (struct ui_out *uiout)
                  inf->num, inferior_pid_to_str (inf->pid).c_str (), filename);
 }
 
+/* Helper for print_inferior.  Returns the 'connection-id' string for
+   PROC_TARGET.  */
+
+static std::string
+uiout_field_connection (process_stratum_target *proc_target)
+{
+  if (proc_target == NULL)
+    {
+      return {};
+    }
+  else if (proc_target->connection_string () != NULL)
+    {
+      return string_printf ("%d (%s %s)",
+                           proc_target->connection_number,
+                           proc_target->shortname (),
+                           proc_target->connection_string ());
+    }
+  else
+    {
+      return string_printf ("%d (%s)",
+                           proc_target->connection_number,
+                           proc_target->shortname ());
+    }
+}
+
 /* Prints the list of inferiors and their details on UIOUT.  This is a
    version of 'info_inferior_command' suitable for use from MI.
 
@@ -436,6 +464,7 @@ static void
 print_inferior (struct ui_out *uiout, const char *requested_inferiors)
 {
   int inf_count = 0;
+  size_t connection_id_len = 20;
 
   /* Compute number of inferiors we will print.  */
   for (inferior *inf : all_inferiors ())
@@ -443,6 +472,10 @@ print_inferior (struct ui_out *uiout, const char *requested_inferiors)
       if (!number_is_in_list (requested_inferiors, inf->num))
        continue;
 
+      std::string conn = uiout_field_connection (inf->process_target ());
+      if (connection_id_len < conn.size ())
+       connection_id_len = conn.size ();
+
       ++inf_count;
     }
 
@@ -452,13 +485,20 @@ print_inferior (struct ui_out *uiout, const char *requested_inferiors)
       return;
     }
 
-  ui_out_emit_table table_emitter (uiout, 4, inf_count, "inferiors");
+  ui_out_emit_table table_emitter (uiout, 5, inf_count, "inferiors");
   uiout->table_header (1, ui_left, "current", "");
   uiout->table_header (4, ui_left, "number", "Num");
   uiout->table_header (17, ui_left, "target-id", "Description");
+  uiout->table_header (connection_id_len, ui_left,
+                      "connection-id", "Connection");
   uiout->table_header (17, ui_left, "exec", "Executable");
 
   uiout->table_body ();
+
+  /* Restore the current thread after the loop because we switch the
+     inferior in the loop.  */
+  scoped_restore_current_pspace_and_thread restore_pspace_thread;
+  inferior *current_inf = current_inferior ();
   for (inferior *inf : all_inferiors ())
     {
       if (!number_is_in_list (requested_inferiors, inf->num))
@@ -466,15 +506,22 @@ print_inferior (struct ui_out *uiout, const char *requested_inferiors)
 
       ui_out_emit_tuple tuple_emitter (uiout, NULL);
 
-      if (inf == current_inferior ())
+      if (inf == current_inf)
        uiout->field_string ("current", "*");
       else
        uiout->field_skip ("current");
 
       uiout->field_signed ("number", inf->num);
 
+      /* Because target_pid_to_str uses current_top_target,
+        switch the inferior.  */
+      switch_to_inferior_no_thread (inf);
+
       uiout->field_string ("target-id", inferior_pid_to_str (inf->pid));
 
+      std::string conn = uiout_field_connection (inf->process_target ());
+      uiout->field_string ("connection-id", conn.c_str ());
+
       if (inf->pspace->pspace_exec_filename != NULL)
        uiout->field_string ("exec", inf->pspace->pspace_exec_filename);
       else
@@ -574,6 +621,16 @@ kill_inferior_command (const char *args, int from_tty)
   bfd_cache_close_all ();
 }
 
+/* See inferior.h.  */
+
+void
+switch_to_inferior_no_thread (inferior *inf)
+{
+  set_current_inferior (inf);
+  switch_to_no_thread ();
+  set_current_program_space (inf->pspace);
+}
+
 static void
 inferior_command (const char *args, int from_tty)
 {
@@ -604,9 +661,7 @@ inferior_command (const char *args, int from_tty)
     }
   else
     {
-      set_current_inferior (inf);
-      switch_to_no_thread ();
-      set_current_program_space (inf->pspace);
+      switch_to_inferior_no_thread (inf);
 
       gdb::observers::user_selected_context_changed.notify
        (USER_SELECTED_INFERIOR);
@@ -685,7 +740,41 @@ 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);
+      if (proc_target->connection_string () != NULL)
+       printf_filtered (_("Added inferior %d on connection %d (%s %s)\n"),
+                        new_inf->num,
+                        proc_target->connection_number,
+                        proc_target->shortname (),
+                        proc_target->connection_string ());
+      else
+       printf_filtered (_("Added inferior %d on connection %d (%s)\n"),
+                        new_inf->num,
+                        proc_target->connection_number,
+                        proc_target->shortname ());
+    }
+  else
+    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)
@@ -693,6 +782,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;
@@ -712,6 +802,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;
@@ -725,35 +817,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.q.  */
-         set_current_program_space (inf->pspace);
-         set_current_inferior (inf);
-         switch_to_no_thread ();
-
          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)
     {
@@ -774,6 +863,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
            {
@@ -819,15 +910,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);
     }
 }
@@ -888,10 +977,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, _("\
@@ -900,11 +992,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\
index 3baac6efdabbbcb13ff90c40cb63fa87b4a4026d..4229c6017d92eb9742ef83e1b83688ed6a9e6b30 100644 (file)
@@ -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);
@@ -308,6 +310,10 @@ extern inferior *current_inferior ();
 
 extern void set_current_inferior (inferior *);
 
+/* Switch inferior (and program space) to INF, and switch to no thread
+   selected.  */
+extern void switch_to_inferior_no_thread (inferior *inf);
+
 /* GDB represents the state of each program execution with an object
    called an inferior.  An inferior typically corresponds to a process
    but is more general and applies also to targets that do not have a
@@ -339,6 +345,38 @@ 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); }
+
   /* Pointer to next inferior in singly-linked list of inferiors.  */
   struct inferior *next = NULL;
 
@@ -500,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
@@ -530,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);
@@ -564,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).  */
@@ -622,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
index fe479967cd4d5a9d85c45ba2e6c7303ffacf9764..8209b08d0834acb1ecc169ff824188d8e2ba62db 100644 (file)
@@ -29,6 +29,7 @@
 #include "gdbcore.h"
 #include "gdbcmd.h"
 #include "target.h"
+#include "target-connection.h"
 #include "gdbthread.h"
 #include "annotate.h"
 #include "symfile.h"
@@ -64,6 +65,8 @@
 #include "arch-utils.h"
 #include "gdbsupport/scope-exit.h"
 #include "gdbsupport/forward-scope-exit.h"
+#include "gdb_select.h"
+#include <unordered_map>
 
 /* Prototypes for local functions */
 
@@ -79,8 +82,6 @@ static void follow_inferior_reset_breakpoints (void);
 
 static int currently_stepping (struct thread_info *tp);
 
-void nullify_last_target_wait_ptid (void);
-
 static void insert_hp_step_resume_breakpoint_at_frame (struct frame_info *);
 
 static void insert_step_resume_breakpoint_at_caller (struct frame_info *);
@@ -91,6 +92,8 @@ static int maybe_software_singlestep (struct gdbarch *gdbarch, CORE_ADDR pc);
 
 static void resume (gdb_signal sig);
 
+static void wait_for_inferior (inferior *inf);
+
 /* Asynchronous signal handler registered as event loop source for
    when we have pending events ready to be passed to the core.  */
 static struct async_event_handler *infrun_async_inferior_event_token;
@@ -373,9 +376,10 @@ show_stop_on_solib_events (struct ui_file *file, int from_tty,
 
 static int stop_print_frame;
 
-/* This is a cached copy of the pid/waitstatus of the last event
-   returned by target_wait()/deprecated_target_wait_hook().  This
-   information is returned by get_last_target_status().  */
+/* This is a cached copy of the target/ptid/waitstatus of the last
+   event returned by target_wait()/deprecated_target_wait_hook().
+   This information is returned by get_last_target_status().  */
+static process_stratum_target *target_last_proc_target;
 static ptid_t target_last_wait_ptid;
 static struct target_waitstatus target_last_waitstatus;
 
@@ -481,10 +485,12 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
 
          scoped_restore_current_pspace_and_thread restore_pspace_thread;
 
-         inferior_ptid = child_ptid;
-         add_thread_silent (inferior_ptid);
          set_current_inferior (child_inf);
+         switch_to_no_thread ();
          child_inf->symfile_flags = SYMFILE_NO_READ;
+         push_target (parent_inf->process_target ());
+         add_thread_silent (child_inf->process_target (), child_ptid);
+         inferior_ptid = child_ptid;
 
          /* If this is a vfork child, then the address-space is
             shared with the parent.  */
@@ -493,6 +499,8 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
              child_inf->pspace = parent_inf->pspace;
              child_inf->aspace = parent_inf->aspace;
 
+             exec_on_vfork ();
+
              /* The parent will be frozen until the child is done
                 with the shared region.  Keep track of the
                 parent.  */
@@ -568,52 +576,64 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
 
       parent_pspace = parent_inf->pspace;
 
-      /* If we're vforking, we want to hold on to the parent until the
-        child exits or execs.  At child exec or exit time we can
-        remove the old breakpoints from the parent and detach or
-        resume debugging it.  Otherwise, detach the parent now; we'll
-        want to reuse it's program/address spaces, but we can't set
-        them to the child before removing breakpoints from the
-        parent, otherwise, the breakpoints module could decide to
-        remove breakpoints from the wrong process (since they'd be
-        assigned to the same address space).  */
+      process_stratum_target *target = parent_inf->process_target ();
 
-      if (has_vforked)
-       {
-         gdb_assert (child_inf->vfork_parent == NULL);
-         gdb_assert (parent_inf->vfork_child == NULL);
-         child_inf->vfork_parent = parent_inf;
-         child_inf->pending_detach = 0;
-         parent_inf->vfork_child = child_inf;
-         parent_inf->pending_detach = detach_fork;
-         parent_inf->waiting_for_vfork_done = 0;
-       }
-      else if (detach_fork)
-       {
-         if (print_inferior_events)
-           {
-             /* Ensure that we have a process ptid.  */
-             ptid_t process_ptid = ptid_t (parent_ptid.pid ());
+      {
+       /* Hold a strong reference to the target while (maybe)
+          detaching the parent.  Otherwise detaching could close the
+          target.  */
+       auto target_ref = target_ops_ref::new_reference (target);
+
+       /* If we're vforking, we want to hold on to the parent until
+          the child exits or execs.  At child exec or exit time we
+          can remove the old breakpoints from the parent and detach
+          or resume debugging it.  Otherwise, detach the parent now;
+          we'll want to reuse it's program/address spaces, but we
+          can't set them to the child before removing breakpoints
+          from the parent, otherwise, the breakpoints module could
+          decide to remove breakpoints from the wrong process (since
+          they'd be assigned to the same address space).  */
+
+       if (has_vforked)
+         {
+           gdb_assert (child_inf->vfork_parent == NULL);
+           gdb_assert (parent_inf->vfork_child == NULL);
+           child_inf->vfork_parent = parent_inf;
+           child_inf->pending_detach = 0;
+           parent_inf->vfork_child = child_inf;
+           parent_inf->pending_detach = detach_fork;
+           parent_inf->waiting_for_vfork_done = 0;
+         }
+       else if (detach_fork)
+         {
+           if (print_inferior_events)
+             {
+               /* Ensure that we have a process ptid.  */
+               ptid_t process_ptid = ptid_t (parent_ptid.pid ());
+
+               target_terminal::ours_for_output ();
+               fprintf_filtered (gdb_stdlog,
+                                 _("[Detaching after fork from "
+                                   "parent %s]\n"),
+                                 target_pid_to_str (process_ptid).c_str ());
+             }
 
-             target_terminal::ours_for_output ();
-             fprintf_filtered (gdb_stdlog,
-                               _("[Detaching after fork from "
-                                 "parent %s]\n"),
-                               target_pid_to_str (process_ptid).c_str ());
-           }
+           target_detach (parent_inf, 0);
+           parent_inf = NULL;
+         }
 
-         target_detach (parent_inf, 0);
-       }
+       /* Note that the detach above makes PARENT_INF dangling.  */
 
-      /* Note that the detach above makes PARENT_INF dangling.  */
+       /* Add the child thread to the appropriate lists, and switch
+          to this new thread, before cloning the program space, and
+          informing the solib layer about this new process.  */
 
-      /* Add the child thread to the appropriate lists, and switch to
-        this new thread, before cloning the program space, and
-        informing the solib layer about this new process.  */
+       set_current_inferior (child_inf);
+       push_target (target);
+      }
 
+      add_thread_silent (target, child_ptid);
       inferior_ptid = child_ptid;
-      add_thread_silent (inferior_ptid);
-      set_current_inferior (child_inf);
 
       /* If this is a vfork child, then the address-space is shared
         with the parent.  If we detached from the parent, then we can
@@ -622,6 +642,8 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
        {
          child_inf->pspace = parent_pspace;
          child_inf->aspace = child_inf->pspace->aspace;
+
+         exec_on_vfork ();
        }
       else
        {
@@ -668,11 +690,12 @@ follow_fork (void)
 
   if (!non_stop)
     {
+      process_stratum_target *wait_target;
       ptid_t wait_ptid;
       struct target_waitstatus wait_status;
 
       /* Get the last target status returned by target_wait().  */
-      get_last_target_status (&wait_ptid, &wait_status);
+      get_last_target_status (&wait_target, &wait_ptid, &wait_status);
 
       /* If not stopped at a fork event, then there's nothing else to
         do.  */
@@ -683,14 +706,14 @@ follow_fork (void)
       /* Check if we switched over from WAIT_PTID, since the event was
         reported.  */
       if (wait_ptid != minus_one_ptid
-         && inferior_ptid != wait_ptid)
+         && (current_inferior ()->process_target () != wait_target
+             || inferior_ptid != wait_ptid))
        {
          /* We did.  Switch back to WAIT_PTID thread, to tell the
             target to follow it (in either direction).  We'll
             afterwards refuse to resume, and inform the user what
             happened.  */
-         thread_info *wait_thread
-           = find_thread_ptid (wait_ptid);
+         thread_info *wait_thread = find_thread_ptid (wait_target, wait_ptid);
          switch_to_thread (wait_thread);
          should_resume = 0;
        }
@@ -736,6 +759,7 @@ follow_fork (void)
        parent = inferior_ptid;
        child = tp->pending_follow.value.related_pid;
 
+       process_stratum_target *parent_targ = tp->inf->process_target ();
        /* Set up inferior(s) as specified by the caller, and tell the
           target to do whatever is necessary to follow either parent
           or child.  */
@@ -751,7 +775,7 @@ follow_fork (void)
               or another.  The previous selected thread may be gone
               from the lists by now, but if it is still around, need
               to clear the pending follow request.  */
-           tp = find_thread_ptid (parent);
+           tp = find_thread_ptid (parent_targ, parent);
            if (tp)
              tp->pending_follow.kind = TARGET_WAITKIND_SPURIOUS;
 
@@ -762,7 +786,7 @@ follow_fork (void)
            /* If we followed the child, switch to it...  */
            if (follow_child)
              {
-               thread_info *child_thr = find_thread_ptid (child);
+               thread_info *child_thr = find_thread_ptid (parent_targ, child);
                switch_to_thread (child_thr);
 
                /* ... and preserve the stepping state, in case the
@@ -1191,9 +1215,11 @@ follow_exec (ptid_t ptid, const char *exec_file_target)
       inf->pid = pid;
       target_follow_exec (inf, exec_file_target);
 
-      set_current_inferior (inf);
-      set_current_program_space (inf->pspace);
-      add_thread (ptid);
+      inferior *org_inferior = current_inferior ();
+      switch_to_inferior_no_thread (inf);
+      push_target (org_inferior->process_target ());
+      thread_info *thr = add_thread (inf->process_target (), ptid);
+      switch_to_thread (thr);
     }
   else
     {
@@ -1887,6 +1913,7 @@ displaced_step_fixup (thread_info *event_thread, enum gdb_signal signal)
    discarded between events.  */
 struct execution_control_state
 {
+  process_stratum_target *target;
   ptid_t ptid;
   /* The thread that got the event, if this was a thread event; NULL
      otherwise.  */
@@ -2143,6 +2170,16 @@ user_visible_resume_ptid (int step)
   return resume_ptid;
 }
 
+/* See infrun.h.  */
+
+process_stratum_target *
+user_visible_resume_target (ptid_t resume_ptid)
+{
+  return (resume_ptid == minus_one_ptid && sched_multi
+         ? NULL
+         : current_inferior ()->process_target ());
+}
+
 /* Return a ptid representing the set of threads that we will resume,
    in the perspective of the target, assuming run control handling
    does not require leaving some threads stopped (e.g., stepping past
@@ -2207,6 +2244,9 @@ do_target_resume (ptid_t resume_ptid, int step, enum gdb_signal sig)
   target_resume (resume_ptid, step, sig);
 
   target_commit_resume ();
+
+  if (target_can_async_p ())
+    target_async (1);
 }
 
 /* Resume the inferior.  SIG is the signal to give the inferior
@@ -2250,6 +2290,7 @@ resume_1 (enum gdb_signal sig)
                              currently_stepping (tp));
        }
 
+      tp->inf->process_target ()->threads_executing = true;
       tp->resumed = 1;
 
       /* FIXME: What should we do if we are supposed to resume this
@@ -2735,10 +2776,12 @@ clear_proceed_status (int step)
   if (!non_stop && inferior_ptid != null_ptid)
     {
       ptid_t resume_ptid = user_visible_resume_ptid (step);
+      process_stratum_target *resume_target
+       = user_visible_resume_target (resume_ptid);
 
       /* In all-stop mode, delete the per-thread status of all threads
         we're about to resume, implicitly and explicitly.  */
-      for (thread_info *tp : all_non_exited_threads (resume_ptid))
+      for (thread_info *tp : all_non_exited_threads (resume_target, resume_ptid))
        clear_proceed_status_thread (tp);
     }
 
@@ -2815,6 +2858,86 @@ schedlock_applies (struct thread_info *tp)
                                            execution_direction)));
 }
 
+/* Calls target_commit_resume on all targets.  */
+
+static void
+commit_resume_all_targets ()
+{
+  scoped_restore_current_thread restore_thread;
+
+  /* Map between process_target and a representative inferior.  This
+     is to avoid committing a resume in the same target more than
+     once.  Resumptions must be idempotent, so this is an
+     optimization.  */
+  std::unordered_map<process_stratum_target *, inferior *> conn_inf;
+
+  for (inferior *inf : all_non_exited_inferiors ())
+    if (inf->has_execution ())
+      conn_inf[inf->process_target ()] = inf;
+
+  for (const auto &ci : conn_inf)
+    {
+      inferior *inf = ci.second;
+      switch_to_inferior_no_thread (inf);
+      target_commit_resume ();
+    }
+}
+
+/* Check that all the targets we're about to resume are in non-stop
+   mode.  Ideally, we'd only care whether all targets support
+   target-async, but we're not there yet.  E.g., stop_all_threads
+   doesn't know how to handle all-stop targets.  Also, the remote
+   protocol in all-stop mode is synchronous, irrespective of
+   target-async, which means that things like a breakpoint re-set
+   triggered by one target would try to read memory from all targets
+   and fail.  */
+
+static void
+check_multi_target_resumption (process_stratum_target *resume_target)
+{
+  if (!non_stop && resume_target == nullptr)
+    {
+      scoped_restore_current_thread restore_thread;
+
+      /* This is used to track whether we're resuming more than one
+        target.  */
+      process_stratum_target *first_connection = nullptr;
+
+      /* The first inferior we see with a target that does not work in
+        always-non-stop mode.  */
+      inferior *first_not_non_stop = nullptr;
+
+      for (inferior *inf : all_non_exited_inferiors (resume_target))
+       {
+         switch_to_inferior_no_thread (inf);
+
+         if (!target_has_execution)
+           continue;
+
+         process_stratum_target *proc_target
+           = current_inferior ()->process_target();
+
+         if (!target_is_non_stop_p ())
+           first_not_non_stop = inf;
+
+         if (first_connection == nullptr)
+           first_connection = proc_target;
+         else if (first_connection != proc_target
+                  && first_not_non_stop != nullptr)
+           {
+             switch_to_inferior_no_thread (first_not_non_stop);
+
+             proc_target = current_inferior ()->process_target();
+
+             error (_("Connection %d (%s) does not support "
+                      "multi-target resumption."),
+                    proc_target->connection_number,
+                    make_target_connection_string (proc_target).c_str ());
+           }
+       }
+    }
+}
+
 /* Basic routine for continuing the program in various fashions.
 
    ADDR is the address to resume at, or -1 for resume where stopped.
@@ -2829,7 +2952,6 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
   struct regcache *regcache;
   struct gdbarch *gdbarch;
   CORE_ADDR pc;
-  ptid_t resume_ptid;
   struct execution_control_state ecss;
   struct execution_control_state *ecs = &ecss;
   int started;
@@ -2861,6 +2983,13 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
 
   gdb_assert (!thread_is_in_step_over_chain (cur_thr));
 
+  ptid_t resume_ptid
+    = user_visible_resume_ptid (cur_thr->control.stepping_command);
+  process_stratum_target *resume_target
+    = user_visible_resume_target (resume_ptid);
+
+  check_multi_target_resumption (resume_target);
+
   if (addr == (CORE_ADDR) -1)
     {
       if (pc == cur_thr->suspend.stop_pc
@@ -2890,12 +3019,10 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
   if (siggnal != GDB_SIGNAL_DEFAULT)
     cur_thr->suspend.stop_signal = siggnal;
 
-  resume_ptid = user_visible_resume_ptid (cur_thr->control.stepping_command);
-
   /* If an exception is thrown from this point on, make sure to
      propagate GDB's knowledge of the executing state to the
      frontend/user running state.  */
-  scoped_finish_thread_state finish_state (resume_ptid);
+  scoped_finish_thread_state finish_state (resume_target, resume_ptid);
 
   /* Even if RESUME_PTID is a wildcard, and we end up resuming fewer
      threads (e.g., we might need to set threads stepping over
@@ -2904,7 +3031,7 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
      inferior function, as in that case we pretend the inferior
      doesn't run at all.  */
   if (!cur_thr->control.in_infcall)
-   set_running (resume_ptid, 1);
+    set_running (resume_target, resume_ptid, 1);
 
   if (debug_infrun)
     fprintf_unfiltered (gdb_stdlog,
@@ -2939,8 +3066,11 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
      threads.  */
   if (!non_stop && !schedlock_applies (cur_thr))
     {
-      for (thread_info *tp : all_non_exited_threads (resume_ptid))
+      for (thread_info *tp : all_non_exited_threads (resume_target,
+                                                    resume_ptid))
        {
+         switch_to_thread_no_regs (tp);
+
          /* Ignore the current thread here.  It's handled
             afterwards.  */
          if (tp == cur_thr)
@@ -2958,6 +3088,8 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
 
          thread_step_over_chain_enqueue (tp);
        }
+
+      switch_to_thread (cur_thr);
     }
 
   /* Enqueue the current thread last, so that we move all other
@@ -2992,8 +3124,21 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
       {
        /* In all-stop, but the target is always in non-stop mode.
           Start all other threads that are implicitly resumed too.  */
-      for (thread_info *tp : all_non_exited_threads (resume_ptid))
-        {
+       for (thread_info *tp : all_non_exited_threads (resume_target,
+                                                      resume_ptid))
+         {
+           switch_to_thread_no_regs (tp);
+
+         if (!tp->inf->has_execution ())
+           {
+             if (debug_infrun)
+               fprintf_unfiltered (gdb_stdlog,
+                                   "infrun: proceed: [%s] target has "
+                                   "no execution\n",
+                                   target_pid_to_str (tp->ptid).c_str ());
+             continue;
+           }
+
          if (tp->resumed)
            {
              if (debug_infrun)
@@ -3036,10 +3181,15 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
       }
   }
 
-  target_commit_resume ();
+  commit_resume_all_targets ();
 
   finish_state.release ();
 
+  /* If we've switched threads above, switch back to the previously
+     current thread.  We don't want the user to see a different
+     selected thread.  */
+  switch_to_thread (cur_thr);
+
   /* Tell the event loop to wait for it to stop.  If the target
      supports asynchronous execution, it'll do this from within
      target_resume.  */
@@ -3053,10 +3203,8 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
 void
 start_remote (int from_tty)
 {
-  struct inferior *inferior;
-
-  inferior = current_inferior ();
-  inferior->control.stop_soon = STOP_QUIETLY_REMOTE;
+  inferior *inf = current_inferior ();
+  inf->control.stop_soon = STOP_QUIETLY_REMOTE;
 
   /* Always go on waiting for the target, regardless of the mode.  */
   /* FIXME: cagney/1999-09-23: At present it isn't possible to
@@ -3072,7 +3220,7 @@ start_remote (int from_tty)
      target_open() return to the caller an indication that the target
      is currently running and GDB state should be set to the same as
      for an async run.  */
-  wait_for_inferior ();
+  wait_for_inferior (inf);
 
   /* Now that the inferior has stopped, do any bookkeeping like
      loading shared libraries.  We want to do this before normal_stop,
@@ -3093,7 +3241,7 @@ init_wait_for_inferior (void)
 
   clear_proceed_status (0);
 
-  target_last_wait_ptid = minus_one_ptid;
+  nullify_last_target_wait_ptid ();
 
   previous_inferior_ptid = inferior_ptid;
 }
@@ -3123,11 +3271,13 @@ static int switch_back_to_stepped_thread (struct execution_control_state *ecs);
 static void
 infrun_thread_stop_requested (ptid_t ptid)
 {
+  process_stratum_target *curr_target = current_inferior ()->process_target ();
+
   /* PTID was requested to stop.  If the thread was already stopped,
      but the user/frontend doesn't know about that yet (e.g., the
      thread had been temporarily paused for some step-over), set up
      for reporting the stop now.  */
-  for (thread_info *tp : all_threads (ptid))
+  for (thread_info *tp : all_threads (curr_target, ptid))
     {
       if (tp->state != THREAD_RUNNING)
        continue;
@@ -3153,7 +3303,7 @@ infrun_thread_stop_requested (ptid_t ptid)
 
       /* Clear the inline-frame state, since we're re-processing the
         stop.  */
-      clear_inline_frame_state (tp->ptid);
+      clear_inline_frame_state (tp);
 
       /* If this thread was paused because some other thread was
         doing an inline-step over, let that finish first.  Once
@@ -3172,7 +3322,8 @@ infrun_thread_stop_requested (ptid_t ptid)
 static void
 infrun_thread_thread_exit (struct thread_info *tp, int silent)
 {
-  if (target_last_wait_ptid == tp->ptid)
+  if (target_last_proc_target == tp->inf->process_target ()
+      && target_last_wait_ptid == tp->ptid)
     nullify_last_target_wait_ptid ();
 }
 
@@ -3268,19 +3419,20 @@ print_target_wait_results (ptid_t waiton_ptid, ptid_t result_ptid,
    had events.  */
 
 static struct thread_info *
-random_pending_event_thread (ptid_t waiton_ptid)
+random_pending_event_thread (inferior *inf, ptid_t waiton_ptid)
 {
   int num_events = 0;
 
-  auto has_event = [] (thread_info *tp)
+  auto has_event = [&] (thread_info *tp)
     {
-      return (tp->resumed
+      return (tp->ptid.matches (waiton_ptid)
+             && tp->resumed
              && tp->suspend.waitstatus_pending_p);
     };
 
   /* First see how many events we have.  Count only resumed threads
      that have an event pending.  */
-  for (thread_info *tp : all_non_exited_threads (waiton_ptid))
+  for (thread_info *tp : inf->non_exited_threads ())
     if (has_event (tp))
       num_events++;
 
@@ -3297,7 +3449,7 @@ random_pending_event_thread (ptid_t waiton_ptid)
                        num_events, random_selector);
 
   /* Select the Nth thread that has had an event.  */
-  for (thread_info *tp : all_non_exited_threads (waiton_ptid))
+  for (thread_info *tp : inf->non_exited_threads ())
     if (has_event (tp))
       if (random_selector-- == 0)
        return tp;
@@ -3307,10 +3459,12 @@ random_pending_event_thread (ptid_t waiton_ptid)
 
 /* Wrapper for target_wait that first checks whether threads have
    pending statuses to report before actually asking the target for
-   more events.  */
+   more events.  INF is the inferior we're using to call target_wait
+   on.  */
 
 static ptid_t
-do_target_wait (ptid_t ptid, struct target_waitstatus *status, int options)
+do_target_wait_1 (inferior *inf, ptid_t ptid,
+                 target_waitstatus *status, int options)
 {
   ptid_t event_ptid;
   struct thread_info *tp;
@@ -3319,7 +3473,7 @@ do_target_wait (ptid_t ptid, struct target_waitstatus *status, int options)
      pending.  */
   if (ptid == minus_one_ptid || ptid.is_pid ())
     {
-      tp = random_pending_event_thread (ptid);
+      tp = random_pending_event_thread (inf, ptid);
     }
   else
     {
@@ -3329,7 +3483,7 @@ do_target_wait (ptid_t ptid, struct target_waitstatus *status, int options)
                            target_pid_to_str (ptid).c_str ());
 
       /* We have a specific thread to check.  */
-      tp = find_thread_ptid (ptid);
+      tp = find_thread_ptid (inf, ptid);
       gdb_assert (tp != NULL);
       if (!tp->suspend.waitstatus_pending_p)
        tp = NULL;
@@ -3436,6 +3590,109 @@ do_target_wait (ptid_t ptid, struct target_waitstatus *status, int options)
   return event_ptid;
 }
 
+/* Returns true if INF has any resumed thread with a status
+   pending.  */
+
+static bool
+threads_are_resumed_pending_p (inferior *inf)
+{
+  for (thread_info *tp : inf->non_exited_threads ())
+    if (tp->resumed
+       && tp->suspend.waitstatus_pending_p)
+      return true;
+
+  return false;
+}
+
+/* Wrapper for target_wait that first checks whether threads have
+   pending statuses to report before actually asking the target for
+   more events. Polls for events from all inferiors/targets.  */
+
+static bool
+do_target_wait (ptid_t wait_ptid, execution_control_state *ecs, int options)
+{
+  int num_inferiors = 0;
+  int random_selector;
+
+  /* For fairness, we pick the first inferior/target to poll at
+     random, and then continue polling the rest of the inferior list
+     starting from that one in a circular fashion until the whole list
+     is polled once.  */
+
+  auto inferior_matches = [&wait_ptid] (inferior *inf)
+    {
+      return (inf->process_target () != NULL
+             && (threads_are_executing (inf->process_target ())
+                 || threads_are_resumed_pending_p (inf))
+             && ptid_t (inf->pid).matches (wait_ptid));
+    };
+
+  /* First see how many resumed inferiors we have.  */
+  for (inferior *inf : all_inferiors ())
+    if (inferior_matches (inf))
+      num_inferiors++;
+
+  if (num_inferiors == 0)
+    {
+      ecs->ws.kind = TARGET_WAITKIND_IGNORE;
+      return false;
+    }
+
+  /* Now randomly pick an inferior out of those that were resumed.  */
+  random_selector = (int)
+    ((num_inferiors * (double) rand ()) / (RAND_MAX + 1.0));
+
+  if (debug_infrun && num_inferiors > 1)
+    fprintf_unfiltered (gdb_stdlog,
+                       "infrun: Found %d inferiors, starting at #%d\n",
+                       num_inferiors, random_selector);
+
+  /* Select the Nth inferior that was resumed.  */
+
+  inferior *selected = nullptr;
+
+  for (inferior *inf : all_inferiors ())
+    if (inferior_matches (inf))
+      if (random_selector-- == 0)
+       {
+         selected = inf;
+         break;
+       }
+
+  /* Now poll for events out of each of the resumed inferior's
+     targets, starting from the selected one.  */
+
+  auto do_wait = [&] (inferior *inf)
+  {
+    switch_to_inferior_no_thread (inf);
+
+    ecs->ptid = do_target_wait_1 (inf, wait_ptid, &ecs->ws, options);
+    ecs->target = inf->process_target ();
+    return (ecs->ws.kind != TARGET_WAITKIND_IGNORE);
+  };
+
+  /* Needed in all-stop+target-non-stop mode, because we end up here
+     spuriously after the target is all stopped and we've already
+     reported the stop to the user, polling for events.  */
+  scoped_restore_current_thread restore_thread;
+
+  int inf_num = selected->num;
+  for (inferior *inf = selected; inf != NULL; inf = inf->next)
+    if (inferior_matches (inf))
+      if (do_wait (inf))
+       return true;
+
+  for (inferior *inf = inferior_list;
+       inf != NULL && inf->num < inf_num;
+       inf = inf->next)
+    if (inferior_matches (inf))
+      if (do_wait (inf))
+       return true;
+
+  ecs->ws.kind = TARGET_WAITKIND_IGNORE;
+  return false;
+}
+
 /* Prepare and stabilize the inferior for detaching it.  E.g.,
    detaching while a thread is displaced stepping is a recipe for
    crashing it, as nothing would readjust the PC out of the scratch
@@ -3475,7 +3732,7 @@ prepare_for_detach (void)
         don't get any event.  */
       target_dcache_invalidate ();
 
-      ecs->ptid = do_target_wait (pid_ptid, &ecs->ws, 0);
+      do_target_wait (pid_ptid, ecs, 0);
 
       if (debug_infrun)
        print_target_wait_results (pid_ptid, ecs->ptid, &ecs->ws);
@@ -3483,7 +3740,8 @@ prepare_for_detach (void)
       /* If an error happens while handling the event, propagate GDB's
         knowledge of the executing state to the frontend/user running
         state.  */
-      scoped_finish_thread_state finish_state (minus_one_ptid);
+      scoped_finish_thread_state finish_state (inf->process_target (),
+                                              minus_one_ptid);
 
       /* Now figure out what to do with the result of the result.  */
       handle_inferior_event (ecs);
@@ -3511,8 +3769,8 @@ prepare_for_detach (void)
    When this function actually returns it means the inferior
    should be left stopped and GDB should read more commands.  */
 
-void
-wait_for_inferior (void)
+static void
+wait_for_inferior (inferior *inf)
 {
   if (debug_infrun)
     fprintf_unfiltered
@@ -3523,13 +3781,13 @@ wait_for_inferior (void)
   /* If an error happens while handling the event, propagate GDB's
      knowledge of the executing state to the frontend/user running
      state.  */
-  scoped_finish_thread_state finish_state (minus_one_ptid);
+  scoped_finish_thread_state finish_state
+    (inf->process_target (), minus_one_ptid);
 
   while (1)
     {
       struct execution_control_state ecss;
       struct execution_control_state *ecs = &ecss;
-      ptid_t waiton_ptid = minus_one_ptid;
 
       memset (ecs, 0, sizeof (*ecs));
 
@@ -3541,10 +3799,11 @@ wait_for_inferior (void)
         don't get any event.  */
       target_dcache_invalidate ();
 
-      ecs->ptid = do_target_wait (waiton_ptid, &ecs->ws, 0);
+      ecs->ptid = do_target_wait_1 (inf, minus_one_ptid, &ecs->ws, 0);
+      ecs->target = inf->process_target ();
 
       if (debug_infrun)
-       print_target_wait_results (waiton_ptid, ecs->ptid, &ecs->ws);
+       print_target_wait_results (minus_one_ptid, ecs->ptid, &ecs->ws);
 
       /* Now figure out what to do with the result of the result.  */
       handle_inferior_event (ecs);
@@ -3670,7 +3929,6 @@ fetch_inferior_event (void *client_data)
   struct execution_control_state ecss;
   struct execution_control_state *ecs = &ecss;
   int cmd_done = 0;
-  ptid_t waiton_ptid = minus_one_ptid;
 
   memset (ecs, 0, sizeof (*ecs));
 
@@ -3694,14 +3952,11 @@ fetch_inferior_event (void *client_data)
        set_current_traceframe (-1);
       }
 
-    gdb::optional<scoped_restore_current_thread> maybe_restore_thread;
-
-    if (non_stop)
-      /* In non-stop mode, the user/frontend should not notice a thread
-        switch due to internal events.  Make sure we reverse to the
-        user selected thread and frame after handling the event and
-        running any breakpoint commands.  */
-      maybe_restore_thread.emplace ();
+    /* The user/frontend should not notice a thread switch due to
+       internal events.  Make sure we revert to the user selected
+       thread and frame after handling the event and running any
+       breakpoint commands.  */
+    scoped_restore_current_thread restore_thread;
 
     overlay_cache_invalid = 1;
     /* Flush target cache before starting to handle each event.  Target
@@ -3714,17 +3969,28 @@ fetch_inferior_event (void *client_data)
       = make_scoped_restore (&execution_direction,
                             target_execution_direction ());
 
-    ecs->ptid = do_target_wait (waiton_ptid, &ecs->ws,
-                               target_can_async_p () ? TARGET_WNOHANG : 0);
+    if (!do_target_wait (minus_one_ptid, ecs, TARGET_WNOHANG))
+      return;
+
+    gdb_assert (ecs->ws.kind != TARGET_WAITKIND_IGNORE);
+
+    /* Switch to the target that generated the event, so we can do
+       target calls.  Any inferior bound to the target will do, so we
+       just switch to the first we find.  */
+    for (inferior *inf : all_inferiors (ecs->target))
+      {
+       switch_to_inferior_no_thread (inf);
+       break;
+      }
 
     if (debug_infrun)
-      print_target_wait_results (waiton_ptid, ecs->ptid, &ecs->ws);
+      print_target_wait_results (minus_one_ptid, ecs->ptid, &ecs->ws);
 
     /* If an error happens while handling the event, propagate GDB's
        knowledge of the executing state to the frontend/user running
        state.  */
     ptid_t finish_ptid = !target_is_non_stop_p () ? minus_one_ptid : ecs->ptid;
-    scoped_finish_thread_state finish_state (finish_ptid);
+    scoped_finish_thread_state finish_state (ecs->target, finish_ptid);
 
     /* Get executed before scoped_restore_current_thread above to apply
        still for the thread which has thrown the exception.  */
@@ -3738,7 +4004,7 @@ fetch_inferior_event (void *client_data)
 
     if (!ecs->wait_some_more)
       {
-       struct inferior *inf = find_inferior_ptid (ecs->ptid);
+       struct inferior *inf = find_inferior_ptid (ecs->target, ecs->ptid);
        int should_stop = 1;
        struct thread_info *thr = ecs->event_thread;
 
@@ -3778,6 +4044,19 @@ fetch_inferior_event (void *client_data)
                inferior_event_handler (INF_EXEC_COMPLETE, NULL);
                cmd_done = 1;
              }
+
+           /* If we got a TARGET_WAITKIND_NO_RESUMED event, then the
+              previously selected thread is gone.  We have two
+              choices - switch to no thread selected, or restore the
+              previously selected thread (now exited).  We chose the
+              later, just because that's what GDB used to do.  After
+              this, "info threads" says "The current thread <Thread
+              ID 2> has terminated." instead of "No thread
+              selected.".  */
+           if (!non_stop
+               && cmd_done
+               && ecs->ws.kind != TARGET_WAITKIND_NO_RESUMED)
+             restore_thread.dont_restore ();
          }
       }
 
@@ -3827,31 +4106,39 @@ init_thread_stepping_state (struct thread_info *tss)
   tss->step_after_step_resume_breakpoint = 0;
 }
 
-/* Set the cached copy of the last ptid/waitstatus.  */
+/* See infrun.h.  */
 
 void
-set_last_target_status (ptid_t ptid, struct target_waitstatus status)
+set_last_target_status (process_stratum_target *target, ptid_t ptid,
+                       target_waitstatus status)
 {
+  target_last_proc_target = target;
   target_last_wait_ptid = ptid;
   target_last_waitstatus = status;
 }
 
-/* Return the cached copy of the last pid/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().  */
+/* See infrun.h.  */
 
 void
-get_last_target_status (ptid_t *ptidp, struct target_waitstatus *status)
+get_last_target_status (process_stratum_target **target, ptid_t *ptid,
+                       target_waitstatus *status)
 {
-  *ptidp = target_last_wait_ptid;
-  *status = target_last_waitstatus;
+  if (target != nullptr)
+    *target = target_last_proc_target;
+  if (ptid != nullptr)
+    *ptid = target_last_wait_ptid;
+  if (status != nullptr)
+    *status = target_last_waitstatus;
 }
 
+/* See infrun.h.  */
+
 void
 nullify_last_target_wait_ptid (void)
 {
+  target_last_proc_target = nullptr;
   target_last_wait_ptid = minus_one_ptid;
+  target_last_waitstatus = {};
 }
 
 /* Switch thread contexts.  */
@@ -3861,7 +4148,8 @@ context_switch (execution_control_state *ecs)
 {
   if (debug_infrun
       && ecs->ptid != inferior_ptid
-      && ecs->event_thread != inferior_thread ())
+      && (inferior_ptid == null_ptid
+         || ecs->event_thread != inferior_thread ()))
     {
       fprintf_unfiltered (gdb_stdlog, "infrun: Switching context from %s ",
                          target_pid_to_str (inferior_ptid).c_str ());
@@ -4186,20 +4474,19 @@ fill_in_stop_func (struct gdbarch *gdbarch,
 static enum stop_kind
 get_inferior_stop_soon (execution_control_state *ecs)
 {
-  struct inferior *inf = find_inferior_ptid (ecs->ptid);
+  struct inferior *inf = find_inferior_ptid (ecs->target, ecs->ptid);
 
   gdb_assert (inf != NULL);
   return inf->control.stop_soon;
 }
 
-/* Wait for one event.  Store the resulting waitstatus in WS, and
-   return the event ptid.  */
+/* Poll for one event out of the current target.  Store the resulting
+   waitstatus in WS, and return the event ptid.  Does not block.  */
 
 static ptid_t
-wait_one (struct target_waitstatus *ws)
+poll_one_curr_target (struct target_waitstatus *ws)
 {
   ptid_t event_ptid;
-  ptid_t wait_ptid = minus_one_ptid;
 
   overlay_cache_invalid = 1;
 
@@ -4210,16 +4497,101 @@ wait_one (struct target_waitstatus *ws)
   target_dcache_invalidate ();
 
   if (deprecated_target_wait_hook)
-    event_ptid = deprecated_target_wait_hook (wait_ptid, ws, 0);
+    event_ptid = deprecated_target_wait_hook (minus_one_ptid, ws, TARGET_WNOHANG);
   else
-    event_ptid = target_wait (wait_ptid, ws, 0);
+    event_ptid = target_wait (minus_one_ptid, ws, TARGET_WNOHANG);
 
   if (debug_infrun)
-    print_target_wait_results (wait_ptid, event_ptid, ws);
+    print_target_wait_results (minus_one_ptid, event_ptid, ws);
 
   return event_ptid;
 }
 
+/* An event reported by wait_one.  */
+
+struct wait_one_event
+{
+  /* The target the event came out of.  */
+  process_stratum_target *target;
+
+  /* The PTID the event was for.  */
+  ptid_t ptid;
+
+  /* The waitstatus.  */
+  target_waitstatus ws;
+};
+
+/* Wait for one event out of any target.  */
+
+static wait_one_event
+wait_one ()
+{
+  while (1)
+    {
+      for (inferior *inf : all_inferiors ())
+       {
+         process_stratum_target *target = inf->process_target ();
+         if (target == NULL
+             || !target->is_async_p ()
+             || !target->threads_executing)
+           continue;
+
+         switch_to_inferior_no_thread (inf);
+
+         wait_one_event event;
+         event.target = target;
+         event.ptid = poll_one_curr_target (&event.ws);
+
+         if (event.ws.kind == TARGET_WAITKIND_NO_RESUMED)
+           {
+             /* If nothing is resumed, remove the target from the
+                event loop.  */
+             target_async (0);
+           }
+         else if (event.ws.kind != TARGET_WAITKIND_IGNORE)
+           return event;
+       }
+
+      /* Block waiting for some event.  */
+
+      fd_set readfds;
+      int nfds = 0;
+
+      FD_ZERO (&readfds);
+
+      for (inferior *inf : all_inferiors ())
+       {
+         process_stratum_target *target = inf->process_target ();
+         if (target == NULL
+             || !target->is_async_p ()
+             || !target->threads_executing)
+           continue;
+
+         int fd = target->async_wait_fd ();
+         FD_SET (fd, &readfds);
+         if (nfds <= fd)
+           nfds = fd + 1;
+       }
+
+      if (nfds == 0)
+       {
+         /* No waitable targets left.  All must be stopped.  */
+         return {NULL, minus_one_ptid, {TARGET_WAITKIND_NO_RESUMED}};
+       }
+
+      QUIT;
+
+      int numfds = interruptible_select (nfds, &readfds, 0, NULL, 0);
+      if (numfds < 0)
+       {
+         if (errno == EINTR)
+           continue;
+         else
+           perror_with_name ("interruptible_select");
+       }
+    }
+}
+
 /* Generate a wrapper for target_stopped_by_REASON that works on PTID
    instead of the current thread.  */
 #define THREAD_STOPPED_BY(REASON)              \
@@ -4242,7 +4614,7 @@ THREAD_STOPPED_BY (hw_breakpoint)
 /* Save the thread's event and stop reason to process it later.  */
 
 static void
-save_waitstatus (struct thread_info *tp, struct target_waitstatus *ws)
+save_waitstatus (struct thread_info *tp, const target_waitstatus *ws)
 {
   if (debug_infrun)
     {
@@ -4342,8 +4714,6 @@ stop_all_threads (void)
                            "iterations=%d\n", pass, iterations);
       while (1)
        {
-         ptid_t event_ptid;
-         struct target_waitstatus ws;
          int need_wait = 0;
 
          update_thread_list ();
@@ -4363,6 +4733,7 @@ stop_all_threads (void)
                                            "infrun:   %s executing, "
                                            "need stop\n",
                                            target_pid_to_str (t->ptid).c_str ());
+                     switch_to_thread_no_regs (t);
                      target_stop (t->ptid);
                      t->stop_requested = 1;
                    }
@@ -4400,28 +4771,29 @@ stop_all_threads (void)
          if (pass > 0)
            pass = -1;
 
-         event_ptid = wait_one (&ws);
+         wait_one_event event = wait_one ();
+
          if (debug_infrun)
            {
              fprintf_unfiltered (gdb_stdlog,
                                  "infrun: stop_all_threads %s %s\n",
-                                 target_waitstatus_to_string (&ws).c_str (),
-                                 target_pid_to_str (event_ptid).c_str ());
+                                 target_waitstatus_to_string (&event.ws).c_str (),
+                                 target_pid_to_str (event.ptid).c_str ());
            }
 
-         if (ws.kind == TARGET_WAITKIND_NO_RESUMED
-             || ws.kind == TARGET_WAITKIND_THREAD_EXITED
-             || ws.kind == TARGET_WAITKIND_EXITED
-             || ws.kind == TARGET_WAITKIND_SIGNALLED)
+         if (event.ws.kind == TARGET_WAITKIND_NO_RESUMED
+             || event.ws.kind == TARGET_WAITKIND_THREAD_EXITED
+             || event.ws.kind == TARGET_WAITKIND_EXITED
+             || event.ws.kind == TARGET_WAITKIND_SIGNALLED)
            {
              /* All resumed threads exited
                 or one thread/process exited/signalled.  */
            }
          else
            {
-             thread_info *t = find_thread_ptid (event_ptid);
+             thread_info *t = find_thread_ptid (event.target, event.ptid);
              if (t == NULL)
-               t = add_thread (event_ptid);
+               t = add_thread (event.target, event.ptid);
 
              t->stop_requested = 0;
              t->executing = 0;
@@ -4430,15 +4802,15 @@ stop_all_threads (void)
 
              /* This may be the first time we see the inferior report
                 a stop.  */
-             inferior *inf = find_inferior_ptid (event_ptid);
+             inferior *inf = find_inferior_ptid (event.target, event.ptid);
              if (inf->needs_setup)
                {
                  switch_to_thread_no_regs (t);
                  setup_inferior (0);
                }
 
-             if (ws.kind == TARGET_WAITKIND_STOPPED
-                 && ws.value.sig == GDB_SIGNAL_0)
+             if (event.ws.kind == TARGET_WAITKIND_STOPPED
+                 && event.ws.value.sig == GDB_SIGNAL_0)
                {
                  /* We caught the event that we intended to catch, so
                     there's no event pending.  */
@@ -4467,7 +4839,7 @@ stop_all_threads (void)
 
                  if (debug_infrun)
                    {
-                     std::string statstr = target_waitstatus_to_string (&ws);
+                     std::string statstr = target_waitstatus_to_string (&event.ws);
 
                      fprintf_unfiltered (gdb_stdlog,
                                          "infrun: target_wait %s, saving "
@@ -4479,10 +4851,10 @@ stop_all_threads (void)
                    }
 
                  /* Record for later.  */
-                 save_waitstatus (t, &ws);
+                 save_waitstatus (t, &event.ws);
 
-                 sig = (ws.kind == TARGET_WAITKIND_STOPPED
-                        ? ws.value.sig : GDB_SIGNAL_0);
+                 sig = (event.ws.kind == TARGET_WAITKIND_STOPPED
+                        ? event.ws.value.sig : GDB_SIGNAL_0);
 
                  if (displaced_step_fixup (t, sig) < 0)
                    {
@@ -4580,7 +4952,7 @@ handle_no_resumed (struct execution_control_state *ecs)
      the synchronous command show "no unwaited-for " to the user.  */
   update_thread_list ();
 
-  for (thread_info *thread : all_non_exited_threads ())
+  for (thread_info *thread : all_non_exited_threads (ecs->target))
     {
       if (thread->executing
          || thread->suspend.waitstatus_pending_p)
@@ -4600,11 +4972,8 @@ handle_no_resumed (struct execution_control_state *ecs)
      process exited meanwhile (thus updating the thread list results
      in an empty thread list).  In this case we know we'll be getting
      a process exit event shortly.  */
-  for (inferior *inf : all_inferiors ())
+  for (inferior *inf : all_non_exited_inferiors (ecs->target))
     {
-      if (inf->pid == 0)
-       continue;
-
       thread_info *thread = any_live_thread_of_inferior (inf);
       if (thread == NULL)
        {
@@ -4673,8 +5042,8 @@ handle_inferior_event (struct execution_control_state *ecs)
       && handle_no_resumed (ecs))
     return;
 
-  /* Cache the last pid/waitstatus.  */
-  set_last_target_status (ecs->ptid, ecs->ws);
+  /* Cache the last target/ptid/waitstatus.  */
+  set_last_target_status (ecs->target, ecs->ptid, ecs->ws);
 
   /* Always clear state belonging to the previous time we stopped.  */
   stop_stack_dummy = STOP_NONE;
@@ -4691,10 +5060,10 @@ handle_inferior_event (struct execution_control_state *ecs)
   if (ecs->ws.kind != TARGET_WAITKIND_EXITED
       && ecs->ws.kind != TARGET_WAITKIND_SIGNALLED)
     {
-      ecs->event_thread = find_thread_ptid (ecs->ptid);
+      ecs->event_thread = find_thread_ptid (ecs->target, ecs->ptid);
       /* If it's a new thread, add it to the thread database.  */
       if (ecs->event_thread == NULL)
-       ecs->event_thread = add_thread (ecs->ptid);
+       ecs->event_thread = add_thread (ecs->target, ecs->ptid);
 
       /* Disable range stepping.  If the next step request could use a
         range, this will be end up re-enabled then.  */
@@ -4766,10 +5135,10 @@ handle_inferior_event (struct execution_control_state *ecs)
     else
       mark_ptid = ecs->ptid;
 
-    set_executing (mark_ptid, 0);
+    set_executing (ecs->target, mark_ptid, 0);
 
     /* Likewise the resumed flag.  */
-    set_resumed (mark_ptid, 0);
+    set_resumed (ecs->target, mark_ptid, 0);
   }
 
   switch (ecs->ws.kind)
@@ -4870,7 +5239,7 @@ handle_inferior_event (struct execution_control_state *ecs)
     case TARGET_WAITKIND_EXITED:
     case TARGET_WAITKIND_SIGNALLED:
       inferior_ptid = ecs->ptid;
-      set_current_inferior (find_inferior_ptid (ecs->ptid));
+      set_current_inferior (find_inferior_ptid (ecs->target, ecs->ptid));
       set_current_program_space (current_inferior ()->pspace);
       handle_vfork_child_exec_or_exit (0);
       target_terminal::ours ();        /* Must do this before mourn anyway.  */
@@ -4943,7 +5312,7 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
        if (displaced_step_in_progress_thread (ecs->event_thread))
          {
            struct inferior *parent_inf
-             = find_inferior_ptid (ecs->ptid);
+             = find_inferior_ptid (ecs->target, ecs->ptid);
            struct regcache *child_regcache;
            CORE_ADDR parent_pc;
 
@@ -4974,7 +5343,8 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
               list yet at this point.  */
 
            child_regcache
-             = get_thread_arch_aspace_regcache (ecs->ws.value.related_pid,
+             = get_thread_arch_aspace_regcache (parent_inf->process_target (),
+                                                ecs->ws.value.related_pid,
                                                 gdbarch,
                                                 parent_inf->aspace);
            /* Read PC value of parent process.  */
@@ -5042,10 +5412,16 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
 
          ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0;
 
+         process_stratum_target *targ
+           = ecs->event_thread->inf->process_target ();
+
          should_resume = follow_fork ();
 
+         /* Note that one of these may be an invalid pointer,
+            depending on detach_fork.  */
          thread_info *parent = ecs->event_thread;
-         thread_info *child = find_thread_ptid (ecs->ws.value.related_pid);
+         thread_info *child
+           = find_thread_ptid (targ, ecs->ws.value.related_pid);
 
          /* At this point, the parent is marked running, and the
             child is marked stopped.  */
@@ -5207,6 +5583,8 @@ restart_threads (struct thread_info *event_thread)
 
   for (thread_info *tp : all_non_exited_threads ())
     {
+      switch_to_thread_no_regs (tp);
+
       if (tp == event_thread)
        {
          if (debug_infrun)
@@ -5470,9 +5848,8 @@ handle_signal_stop (struct execution_control_state *ecs)
     {
       struct regcache *regcache = get_thread_regcache (ecs->event_thread);
       struct gdbarch *reg_gdbarch = regcache->arch ();
-      scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
 
-      inferior_ptid = ecs->ptid;
+      switch_to_thread (ecs->event_thread);
 
       fprintf_unfiltered (gdb_stdlog, "infrun: stop_pc = %s\n",
                          paddress (reg_gdbarch,
@@ -5862,7 +6239,7 @@ handle_signal_stop (struct execution_control_state *ecs)
   if (random_signal)
     {
       /* Signal not for debugging purposes.  */
-      struct inferior *inf = find_inferior_ptid (ecs->ptid);
+      struct inferior *inf = find_inferior_ptid (ecs->target, ecs->ptid);
       enum gdb_signal stop_signal = ecs->event_thread->suspend.stop_signal;
 
       if (debug_infrun)
@@ -6915,10 +7292,13 @@ switch_back_to_stepped_thread (struct execution_control_state *ecs)
 
       for (thread_info *tp : all_non_exited_threads ())
         {
+         switch_to_thread_no_regs (tp);
+
          /* Ignore threads of processes the caller is not
             resuming.  */
          if (!sched_multi
-             && tp->ptid.pid () != ecs->ptid.pid ())
+             && (tp->inf->process_target () != ecs->target
+                 || tp->inf->pid != ecs->ptid.pid ()))
            continue;
 
          /* When stepping over a breakpoint, we lock all threads
@@ -6966,6 +7346,8 @@ switch_back_to_stepped_thread (struct execution_control_state *ecs)
              return 1;
            }
        }
+
+      switch_to_thread (ecs->event_thread);
     }
 
   return 0;
@@ -7855,10 +8237,9 @@ void
 print_stop_event (struct ui_out *uiout, bool displays)
 {
   struct target_waitstatus last;
-  ptid_t last_ptid;
   struct thread_info *tp;
 
-  get_last_target_status (&last_ptid, &last);
+  get_last_target_status (nullptr, nullptr, &last);
 
   {
     scoped_restore save_uiout = make_scoped_restore (&current_uiout, uiout);
@@ -7977,9 +8358,8 @@ int
 normal_stop (void)
 {
   struct target_waitstatus last;
-  ptid_t last_ptid;
 
-  get_last_target_status (&last_ptid, &last);
+  get_last_target_status (nullptr, nullptr, &last);
 
   new_stop_id ();
 
@@ -7988,10 +8368,10 @@ normal_stop (void)
      frontend/user running state.  A QUIT is an easy exception to see
      here, so do this before any filtered output.  */
 
-  gdb::optional<scoped_finish_thread_state> maybe_finish_thread_state;
+  ptid_t finish_ptid = null_ptid;
 
   if (!non_stop)
-    maybe_finish_thread_state.emplace (minus_one_ptid);
+    finish_ptid = minus_one_ptid;
   else if (last.kind == TARGET_WAITKIND_SIGNALLED
           || last.kind == TARGET_WAITKIND_EXITED)
     {
@@ -8001,10 +8381,17 @@ normal_stop (void)
         linux-fork.c automatically switches to another fork from
         within target_mourn_inferior.  */
       if (inferior_ptid != null_ptid)
-       maybe_finish_thread_state.emplace (ptid_t (inferior_ptid.pid ()));
+       finish_ptid = ptid_t (inferior_ptid.pid ());
     }
   else if (last.kind != TARGET_WAITKIND_NO_RESUMED)
-    maybe_finish_thread_state.emplace (inferior_ptid);
+    finish_ptid = inferior_ptid;
+
+  gdb::optional<scoped_finish_thread_state> maybe_finish_thread_state;
+  if (finish_ptid != null_ptid)
+    {
+      maybe_finish_thread_state.emplace
+       (user_visible_resume_target (finish_ptid), finish_ptid);
+    }
 
   /* As we're presenting a stop, and potentially removing breakpoints,
      update the thread list so we can tell whether there are threads
index 912514195e8503ceb8e35c3801f50210af65d190..8040b28f0172b00dc986de9a72bfb6dec8b930f5 100644 (file)
@@ -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,12 +108,22 @@ extern void wait_for_inferior (void);
    target, false otherwise.  */
 extern int normal_stop (void);
 
-extern void get_last_target_status (ptid_t *ptid,
+/* 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 (process_stratum_target **target,
+                                   ptid_t *ptid,
                                    struct target_waitstatus *status);
 
-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
+   target_wait().  */
+extern void nullify_last_target_wait_ptid ();
+
 /* Stop all threads.  Only returns after everything is halted.  */
 extern void stop_all_threads (void);
 
index 2ba57b06dfdc9e68deea938858847b400e4b1377..ae0af2e5a523797b1c1c1ca27bcebe9559fde726 100644 (file)
@@ -96,37 +96,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 matcher = [target, &filter_ptid] (const inline_state &state)
+    {
+      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 (),
-                         [&ptid] (const inline_state &state)
+                         [thread] (const inline_state &state)
                            {
-                             return ptid == state.thread->ptid;
+                             return thread == state.thread;
                            });
 
   if (it != inline_states.end ())
index 5fa162d067381358802052c74f428eb18b7981e2..f68d1242f6850af4be874fcec597ec96d6b41ef9 100644 (file)
@@ -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.  */
 
index dd925ea8c0682ef16c553fac2612a4bbca016834..c77fb6c73ac98dbef349e4af30d357bd451f2670 100644 (file)
@@ -215,7 +215,6 @@ call_lseek (int fd, off_t offset, int whence)
 static void
 fork_load_infrun_state (struct fork_info *fp)
 {
-  extern void nullify_last_target_wait_ptid ();
   int i;
 
   linux_nat_switch_fork (fp->ptid);
@@ -520,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))
     {
@@ -680,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);
 
index 4484fa5c87da4b1250ae7a71c33916e6b696d46c..45b71ea8627fbf372a7af854a703dd22ad5aa138 100644 (file)
@@ -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)
        {
@@ -1315,12 +1318,13 @@ get_detach_signal (struct lwp_info *lp)
        }
       else if (!target_is_non_stop_p ())
        {
-         struct target_waitstatus last;
          ptid_t last_ptid;
+         process_stratum_target *last_target;
 
-         get_last_target_status (&last_ptid, &last);
+         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;
        }
     }
@@ -1517,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);
     }
@@ -1536,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
@@ -1595,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)
        {
@@ -1649,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;
@@ -1806,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)
@@ -2026,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)
            {
@@ -2257,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);
@@ -2484,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.  */
@@ -2577,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;
 
@@ -2698,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);
@@ -2960,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)
@@ -2986,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);
@@ -3152,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);
@@ -3271,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));
 
@@ -3416,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);
 
@@ -3517,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
@@ -4265,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
@@ -4322,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 ());
@@ -4379,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;
 }
index 9bb438935f299ee66d317e3ee3b6dce84b4dc447..e02611fcf14cff52f2fc0343be37ab3e92a4939f 100644 (file)
@@ -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;
index 59d04c490a621741bcc3636217b71c0a307199d3..820657a1038ed05d96ad0506e6aa319e822e9228 100644 (file)
@@ -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);
index 54d96e9b19f2045c9716bf3d2385f322cfc3827f..ed37de6d198daffdc4fefe724cca470a0da49914 100644 (file)
@@ -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);
 }
 \f
@@ -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)
-    push_target (&the_thread_db_target);
-
+     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,16 +1366,14 @@ 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)
-    unpush_target (this);
+  /* Detach the thread_db target from this inferior.  */
+  unpush_target (this);
 }
 
 ptid_t
@@ -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 ());
+
+  delete_thread_db_info (target_beneath, inferior_ptid.pid ());
 
-  beneath ()->mourn_inferior ();
+  target_beneath->mourn_inferior ();
 
-  /* Detach thread_db target ops.  */
-  if (!thread_db_list)
-    unpush_target (&the_thread_db_target);
+  /* 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;
 
@@ -1622,7 +1627,7 @@ thread_db_target::update_thread_list ()
         stop.  That uses thread_db entry points that do not walk
         libpthread's thread list, so should be safe, as well as more
         efficient.  */
-      if (target_has_execution_1 (thread->ptid))
+      if (thread->inf->has_execution ())
        continue;
 
       thread_db_find_new_threads_1 (thread);
@@ -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"));
 
index b94f9c5940ad69afe5c7065421e1dbeb72746d3c..556f446c2e19ef2f49725135f61ea9981dbe9809 100644 (file)
@@ -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);
     }
 }
 
index e67738193bbc792bd71b90a789bcce6cf297a6a1..24daf3f883883433856cd0a0ab67e81abad37252 100644 (file)
@@ -414,11 +414,7 @@ run_one_inferior (struct inferior *inf, void *arg)
       switch_to_thread (tp);
     }
   else
-    {
-      set_current_inferior (inf);
-      switch_to_no_thread ();
-      set_current_program_space (inf->pspace);
-    }
+    switch_to_inferior_no_thread (inf);
   mi_execute_cli_command (run_cmd, async_p,
                          async_p ? "&" : NULL);
   return 0;
index 5e145d694ec08fdd01fe33f87418dfe4c7557af9..78f972a7496d44a8e056b15fec8915e26a0d3268 100644 (file)
@@ -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;
        }
 
index c387088c4bce90e4944aa2935c54e4f03dc917fd..9cbe9bd19d5a3b00591fa7b8efdc320550d29278 100644 (file)
@@ -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);
 
index 45920ee1dce1f706a094858b164f962421119d58..c31dbf136c8cb9966c20f33b73ef5a74c97e0d82 100644 (file)
@@ -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);
index 2213d5590d65097ae2ab3864ac7723bbb19ea536..8ae108438d3b684ee55335fdcb524690fd2a7063 100644 (file)
@@ -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)
     {
index 7593ffe389e5d43e812249f0f06daeec10279df9..86f79ad5838931faf15914c4930a094c15b9c85e 100644 (file)
@@ -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);
 }
 \f
@@ -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
index d6bc6abc4bb02724e02ec02ab4472ca775970333..f3fd9ee905db65e5bd52efa77c82608f3d3ad3e9 100644 (file)
@@ -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;
 }
@@ -77,9 +77,9 @@ process_stratum_target::has_registers ()
 }
 
 bool
-process_stratum_target::has_execution (ptid_t the_ptid)
+process_stratum_target::has_execution (inferior *inf)
 {
-  /* If there's no thread selected, then we can't make it run through
-     hoops.  */
-  return the_ptid != null_ptid;
+  /* If there's a process running already, we can't make it run
+     through hoops.  */
+  return inf->pid != 0;
 }
index 9cd2cf21f39871eaef40566e492e2d673d12274f..1be02100dcff31cd227053651e59cdde9a8f138f 100644 (file)
@@ -31,6 +31,16 @@ public:
 
   strata stratum () const final override { return process_stratum; }
 
+  /* Return a string representation of this target's open connection.
+     This string is used to distinguish different instances of a given
+     target type.  For example, when remote debugging, the target is
+     called "remote", but since we may have more than one remote
+     target open, connection_string() returns the connection serial
+     connection name, e.g., "localhost:10001", "192.168.0.1:20000",
+     etc.  This string is shown in several places, e.g., in "info
+     connections" and "info inferiors".  */
+  virtual const char *connection_string () { return nullptr; }
+
   /* We must default these because they must be implemented by any
      target that can run.  */
   bool can_async_p () override { return false; }
@@ -50,7 +60,26 @@ public:
   bool has_memory () override;
   bool has_stack () override;
   bool has_registers () override;
-  bool has_execution (ptid_t the_ptid) 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;
+
+  /* The connection number.  Visible in "info connections".  */
+  int connection_number = 0;
 };
 
+/* 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) */
index 2591d6d2012ad6f723db979157575f3a7f2d8e34..a59e32c6d7ad315527e4d2cb14cf826c20ec740c 100644 (file)
@@ -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;
index a1824e8935ef96efec6f0a422f1e59b7649cff11..698661d43fbff2f6fe073d48179a636ca05f922d 100644 (file)
@@ -25,8 +25,9 @@ void
 switch_to_program_space_and_thread (program_space *pspace)
 {
   inferior *inf = find_inferior_for_program_space (pspace);
+  gdb_assert (inf != nullptr);
 
-  if (inf != NULL && inf->pid != 0)
+  if (inf->pid != 0)
     {
       thread_info *tp = any_live_thread_of_inferior (inf);
 
@@ -39,6 +40,5 @@ switch_to_program_space_and_thread (program_space *pspace)
        }
     }
 
-  switch_to_no_thread ();
-  set_current_program_space (pspace);
+  switch_to_inferior_no_thread (inf);
 }
index 96f8acc64cd59106eee203ca0962ce9b4b35fba8..136104034795efef1ddd1451ed8bdf173670723a 100644 (file)
@@ -147,6 +147,9 @@ program_space::~program_space ()
   no_shared_libraries (NULL, 0);
   exec_close ();
   free_all_objfiles ();
+  /* Defer breakpoint re-set because we don't want to create new
+     locations for this pspace which we're tearing down.  */
+  clear_symtab_users (SYMFILE_DEFER_BP_RESET);
   if (!gdbarch_has_shared_address_space (target_gdbarch ()))
     free_address_space (this->aspace);
   clear_section_table (&this->target_sections);
@@ -168,8 +171,6 @@ program_space::free_all_objfiles ()
 
   while (!objfiles_list.empty ())
     objfiles_list.front ()->unlink ();
-
-  clear_symtab_users (0);
 }
 
 /* See progspace.h.  */
index 0fcf3e1f8d7e19b22f8c7e2b692e9c286fa2d1d3..3be86b71daa3327e8920926928f119732eb5da64 100644 (file)
@@ -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");
index db269597709ce3c76d14b055eb13aac600117e3f..59fdfaba794694434f1e3a2e59164f5de0caa98e 100644 (file)
@@ -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
index 7d45666cc55a45651780f8f77764cffa51daeba6..7e5b7860df6ee5d8c7de9c00a45660b823827f1b 100644 (file)
@@ -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;
index 056b03b3fc70fadfbdf9835e55c56ab6b0495cb1..f759a5185fd2a02a0d7d1235fe9d0ea303c3de9d 100644 (file)
@@ -319,7 +319,7 @@ public:
                         struct bp_target_info *,
                         enum remove_bp_reason) override;
 
-  bool has_execution (ptid_t) override;
+  bool has_execution (inferior *inf) override;
 };
 
 static record_full_target record_full_ops;
@@ -1036,6 +1036,9 @@ record_full_base_target::async (int enable)
   beneath ()->async (enable);
 }
 
+/* The PTID and STEP arguments last passed to
+   record_full_target::resume.  */
+static ptid_t record_full_resume_ptid = null_ptid;
 static int record_full_resume_step = 0;
 
 /* True if we've been resumed, and so each record_full_wait call should
@@ -1064,6 +1067,7 @@ static enum exec_direction_kind record_full_execution_dir = EXEC_FORWARD;
 void
 record_full_target::resume (ptid_t ptid, int step, enum gdb_signal signal)
 {
+  record_full_resume_ptid = inferior_ptid;
   record_full_resume_step = step;
   record_full_resumed = 1;
   record_full_execution_dir = ::execution_direction;
@@ -1190,7 +1194,8 @@ record_full_wait_1 (struct target_ops *ops,
          /* This is not a single step.  */
          ptid_t ret;
          CORE_ADDR tmp_pc;
-         struct gdbarch *gdbarch = target_thread_architecture (inferior_ptid);
+         struct gdbarch *gdbarch
+           = target_thread_architecture (record_full_resume_ptid);
 
          while (1)
            {
@@ -1223,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 ();
@@ -1255,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)
@@ -1285,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 ();
@@ -2239,7 +2251,7 @@ record_full_core_target::remove_breakpoint (struct gdbarch *gdbarch,
 /* "has_execution" method for prec over corefile.  */
 
 bool
-record_full_core_target::has_execution (ptid_t the_ptid)
+record_full_core_target::has_execution (inferior *inf)
 {
   return true;
 }
index 1580359cd485d460282fe2f43a57af3de0fe553d..b9f1b0a349fdbf0bf8cdf42352e41eb05c70fa2d 100644 (file)
@@ -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 &regcache : 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
-     current_regcache.  */
-  regcache *regcache = get_thread_arch_aspace_regcache (ptid1,
-                                                       target_gdbarch (),
-                                                       NULL);
+  test_target_ops test_target1;
+  test_target_ops test_target2;
 
-  SELF_CHECK (regcache != NULL);
-  SELF_CHECK (regcache->ptid () == ptid1);
+  /* Get regcache from (target1,ptid1), a new regcache is added to
+     current_regcache.  */
+  test_get_thread_arch_aspace_regcache (&test_target1, ptid1,
+                                       target_gdbarch (),
+                                       NULL);
   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,
-                                             target_gdbarch (),
-                                             NULL);
-  SELF_CHECK (regcache != NULL);
-  SELF_CHECK (regcache->ptid () == ptid2);
+  test_get_thread_arch_aspace_regcache (&test_target1, ptid2,
+                                       target_gdbarch (),
+                                       NULL);
   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,
-                                             target_gdbarch (),
-                                             NULL);
-  SELF_CHECK (regcache != NULL);
-  SELF_CHECK (regcache->ptid () == ptid3);
+  test_get_thread_arch_aspace_regcache (&test_target1, ptid3,
+                                       target_gdbarch (),
+                                       NULL);
   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,
-                                             target_gdbarch (),
-                                             NULL);
-  SELF_CHECK (regcache != NULL);
-  SELF_CHECK (regcache->ptid () == ptid2);
+  test_get_thread_arch_aspace_regcache (&test_target1, ptid2,
+                                       target_gdbarch (),
+                                       NULL);
   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);
 
index e2935eea74a4128fdf3a962af87e0a0070a84251..b8561d714c9edb268539c33b57a01deef42c8ef1 100644 (file)
@@ -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.  */
index 082499e6e84644aa3c20d34d6b678f7c343186ae..665e2773e15be3ae69da88bc4d38aae6030731d7 100644 (file)
@@ -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.  */
@@ -403,6 +406,8 @@ public:
   const target_info &info () const override
   { return remote_target_info; }
 
+  const char *connection_string () override;
+
   thread_control_capabilities get_thread_control_capabilities () override
   { return tc_schedlock; }
 
@@ -537,6 +542,8 @@ public:
 
   void async (int) override;
 
+  int async_wait_fd () override;
+
   void thread_events (int) override;
 
   int can_do_single_step () override;
@@ -1026,7 +1033,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".  */
 
@@ -1268,7 +1275,7 @@ static void
 show_remote_exec_file (struct ui_file *file, int from_tty,
                       struct cmd_list_element *cmd, const char *value)
 {
-  fprintf_filtered (file, "%s\n", remote_exec_file_var);
+  fprintf_filtered (file, "%s\n", get_remote_exec_file ());
 }
 
 static int
@@ -1376,7 +1383,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 +1664,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 +1738,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 +2095,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
@@ -2367,6 +2379,27 @@ remote_target::remote_add_inferior (bool fake_pid_p, int pid, int attached,
         between program/address spaces.  We simply bind the inferior
         to the program space's address space.  */
       inf = current_inferior ();
+
+      /* However, if the current inferior is already bound to a
+        process, find some other empty inferior.  */
+      if (inf->pid != 0)
+       {
+         inf = nullptr;
+         for (inferior *it : all_inferiors ())
+           if (it->pid == 0)
+             {
+               inf = it;
+               break;
+             }
+       }
+      if (inf == nullptr)
+       {
+         /* Since all inferiors were already bound to a process, add
+            a new inferior.  */
+         inf = add_inferior_with_spaces ();
+       }
+      switch_to_inferior_no_thread (inf);
+      push_target (this);
       inferior_appeared (inf, pid);
     }
 
@@ -2382,7 +2415,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.  */
@@ -2400,13 +2434,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;
 }
@@ -2429,7 +2463,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.
@@ -2438,7 +2472,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 ();
@@ -2451,8 +2485,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);
@@ -2468,7 +2502,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;
        }
 
@@ -2476,7 +2510,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);
@@ -2516,10 +2550,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);
 }
 
@@ -3779,6 +3815,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.  */
@@ -3804,7 +3843,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);
@@ -4006,13 +4045,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;
@@ -4318,7 +4350,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);
 }
 
@@ -4394,7 +4426,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)
        {
@@ -4414,14 +4446,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;
 
@@ -4442,7 +4474,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)
            {
@@ -4456,7 +4488,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;
@@ -4495,7 +4527,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.  */
@@ -4668,7 +4700,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
@@ -4681,8 +4713,8 @@ remote_target::start_remote (int from_tty, int extended_p)
             says should be current.  If we're reconnecting to a
             multi-threaded program, this will ideally be the thread
             that last reported an event before GDB disconnected.  */
-         inferior_ptid = get_current_thread (wait_status);
-         if (inferior_ptid == null_ptid)
+         ptid_t curr_thread = get_current_thread (wait_status);
+         if (curr_thread == null_ptid)
            {
              /* Odd... The target was able to list threads, but not
                 tell us which thread was current (no "thread"
@@ -4694,8 +4726,15 @@ remote_target::start_remote (int from_tty, int extended_p)
                                    "warning: couldn't determine remote "
                                    "current thread; picking first in list.\n");
 
-             inferior_ptid = inferior_list->thread_list->ptid;
+             for (thread_info *tp : all_non_exited_threads (this,
+                                                            minus_one_ptid))
+               {
+                 switch_to_thread (tp);
+                 break;
+               }
            }
+         else
+           switch_to_thread (find_thread_ptid (this, curr_thread));
        }
 
       /* init_wait_for_inferior should be called before get_offsets in order
@@ -4754,7 +4793,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?)"));
@@ -4816,6 +4855,17 @@ remote_target::start_remote (int from_tty, int extended_p)
     insert_breakpoints ();
 }
 
+const char *
+remote_target::connection_string ()
+{
+  remote_state *rs = get_remote_state ();
+
+  if (rs->remote_desc->name != NULL)
+    return rs->remote_desc->name;
+  else
+    return NULL;
+}
+
 /* Open a connection to a remote debugger.
    NAME is the filename used for communication.  */
 
@@ -5408,7 +5458,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)
@@ -5432,19 +5482,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)
 {
-  pop_all_targets_at_and_above (process_stratum);
+  /* 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."));
 }
 
@@ -5461,7 +5521,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? ")))
@@ -5590,7 +5650,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;
       }
   }
@@ -5654,10 +5714,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.  */
@@ -5759,10 +5819,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");
@@ -5850,10 +5910,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
@@ -5955,6 +6015,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
@@ -5992,10 +6053,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)
@@ -6058,7 +6119,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)
       {
@@ -6091,7 +6152,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 ();
@@ -6228,9 +6289,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;
@@ -6462,7 +6523,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);
 
@@ -6473,7 +6534,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.  */
@@ -6502,7 +6563,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);
 
@@ -6531,7 +6592,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)
        {
@@ -6552,7 +6613,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)
                {
@@ -6579,7 +6640,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)
@@ -6736,7 +6800,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."));
        }
     }
@@ -6943,7 +7007,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);
 
@@ -6985,7 +7049,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
@@ -7351,9 +7415,10 @@ Packet: '%s'\n"),
 
                  if (rsa == NULL)
                    {
-                     inferior *inf = (event->ptid == null_ptid
-                                      ? NULL
-                                      : find_inferior_ptid (event->ptid));
+                     inferior *inf
+                       = (event->ptid == null_ptid
+                          ? NULL
+                          : 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
@@ -7441,7 +7506,6 @@ Packet: '%s'\n"),
     case 'W':          /* Target exited.  */
     case 'X':
       {
-       int pid;
        ULONGEST value;
 
        /* GDB used to accept only 2 hex chars here.  Stubs should
@@ -7465,8 +7529,9 @@ Packet: '%s'\n"),
              event->ws.value.sig = GDB_SIGNAL_UNKNOWN;
          }
 
-       /* If no process is specified, assume inferior_ptid.  */
-       pid = inferior_ptid.pid ();
+       /* If no process is specified, return null_ptid, and let the
+          caller figure out the right process to use.  */
+       int pid = 0;
        if (*p == '\0')
          ;
        else if (*p == ';')
@@ -7613,7 +7678,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 &reg : stop_reply->regcache)
            {
@@ -7625,7 +7690,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;
@@ -7692,6 +7757,17 @@ 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 (remote_target *target)
+{
+  for (thread_info *tp : all_non_exited_threads (target, minus_one_ptid))
+    if (tp->resumed)
+      return tp->ptid;
+  return null_ptid;
+}
+
 /* Wait until the remote machine stops, then return, storing status in
    STATUS just as `wait' would.  */
 
@@ -7828,11 +7904,19 @@ 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 = inferior_ptid;
+       event_ptid = first_remote_resumed_thread (this);
     }
   else
-    /* A process exit.  Invalidate our notion of current thread.  */
-    record_currthread (rs, minus_one_ptid);
+    {
+      /* A process exit.  Invalidate our notion of current thread.  */
+      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 (this);
+      /* EVENT_PTID could still be NULL_PTID.  Double-check.  */
+      if (event_ptid == null_ptid)
+       event_ptid = magic_null_ptid;
+    }
 
   return event_ptid;
 }
@@ -8943,11 +9027,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));
 }
@@ -8983,12 +9067,12 @@ 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.  "
-                          "Target disconnected."));
+      unpush_and_perror (this, _("Remote communication error.  "
+                                "Target disconnected."));
       /* no return */
     case SERIAL_TIMEOUT:
       break;
@@ -9016,8 +9100,8 @@ remote_target::remote_serial_write (const char *str, int len)
 
   if (serial_write (rs->remote_desc, str, len))
     {
-      unpush_and_perror (_("Remote communication error.  "
-                          "Target disconnected."));
+      unpush_and_perror (this, _("Remote communication error.  "
+                                "Target disconnected."));
     }
 
   if (rs->got_ctrlc_during_io)
@@ -9540,7 +9624,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."));
@@ -9657,7 +9741,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;
 
@@ -9717,7 +9801,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 ();
 
@@ -9803,12 +9887,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;
     }
 
@@ -9843,26 +9924,6 @@ remote_target::mourn_inferior ()
 
   /* Call common code to mark the inferior as not running.  */
   generic_mourn_inferior ();
-
-  if (!have_inferiors ())
-    {
-      if (!remote_multi_process_p (rs))
-       {
-         /* Check whether the target is running now - some remote stubs
-            automatically restart after kill.  */
-         putpkt ("?");
-         getpkt (&rs->buf, 0);
-
-         if (rs->buf[0] == 'S' || rs->buf[0] == 'T')
-           {
-             /* Assume that the target has been restarted.  Set
-                inferior_ptid so that bits of core GDB realizes
-                there's something here, e.g., so that the user can
-                say "kill" again.  */
-             inferior_ptid = magic_null_ptid;
-           }
-       }
-    }
 }
 
 bool
@@ -13412,7 +13473,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;
@@ -13692,7 +13753,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);
 
@@ -13908,13 +13969,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);
@@ -13975,7 +14035,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);
 
@@ -14047,6 +14107,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)
 {
index 50781c803991eae04ee7542ba151614fb2fce779..157907373c4e16d3a9a433000588451238851c3c 100644 (file)
@@ -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);
 
index 804ef1826764b2344c5e8b58809090331d90abaa..a1c3b91c7c2fb89c7ee8765a0d77c316875e5408 100644 (file)
@@ -247,6 +247,7 @@ serial_open_ops_1 (const struct serial_ops *ops, const char *open_name)
       return NULL;
     }
 
+  scb->name = open_name != NULL ? xstrdup (open_name) : NULL;
   scb->next = scb_base;
   scb_base = scb;
 
@@ -291,6 +292,7 @@ serial_fdopen_ops (const int fd, const struct serial_ops *ops)
 
   scb = new_serial (ops);
 
+  scb->name = NULL;
   scb->next = scb_base;
   scb_base = scb;
 
@@ -330,6 +332,8 @@ do_serial_close (struct serial *scb, int really_close)
   if (really_close)
     scb->ops->close (scb);
 
+  xfree (scb->name);
+
   /* For serial_is_open.  */
   scb->bufp = NULL;
 
index 446b896345ff06ea7df1d24e529aae652212f7c2..8d67c4bf537a94e46d0dc2267baf0682d1980add 100644 (file)
@@ -240,6 +240,7 @@ struct serial
                                   buffer.  -ve for sticky errors.  */
     unsigned char *bufp;       /* Current byte */
     unsigned char buf[BUFSIZ]; /* Da buffer itself */
+    char *name;                        /* The name of the device or host */
     struct serial *next;       /* Pointer to the next `struct serial *' */
     int debug_p;               /* Trace this serial devices operation.  */
     int async_state;           /* Async internal state.  */
index a1def95ee61246c872f7b376e3a381f8130ddf4b..bf2325b6a9e7f712d0f110b1efdf435cfaea6ce9 100644 (file)
@@ -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;
 }
index 9016b31c3f8064157f134fb4fe2a5c12160b0cb3..03b510c9adedbbbad25a6ba95d3190cefaff04ba 100644 (file)
@@ -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>";
 
index 2d275f2b9c077d9b4b5242e359e6909e3347af49..3122f06939f5f88f01fe8fc515a0e8fcbbea5964 100644 (file)
@@ -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));
index 5e9a043ffebaf9ec933630fdb7c0a2ff84c3bff3..50f6d518133a3f7e47ee46f7b2df20d287e52fbe 100644 (file)
@@ -1430,9 +1430,6 @@ stap_modify_semaphore (CORE_ADDR address, int set, struct gdbarch *gdbarch)
   struct type *type = builtin_type (gdbarch)->builtin_unsigned_short;
   ULONGEST value;
 
-  if (address == 0)
-    return;
-
   /* Swallow errors.  */
   if (target_read_memory (address, bytes, TYPE_LENGTH (type)) != 0)
     {
@@ -1466,6 +1463,8 @@ stap_modify_semaphore (CORE_ADDR address, int set, struct gdbarch *gdbarch)
 void
 stap_probe::set_semaphore (struct objfile *objfile, struct gdbarch *gdbarch)
 {
+  if (m_sem_addr == 0)
+    return;
   stap_modify_semaphore (relocate_address (m_sem_addr, objfile), 1, gdbarch);
 }
 
@@ -1474,6 +1473,8 @@ stap_probe::set_semaphore (struct objfile *objfile, struct gdbarch *gdbarch)
 void
 stap_probe::clear_semaphore (struct objfile *objfile, struct gdbarch *gdbarch)
 {
+  if (m_sem_addr == 0)
+    return;
   stap_modify_semaphore (relocate_address (m_sem_addr, objfile), 0, gdbarch);
 }
 
index 0285f8fc34c1d4fa47dacf4370c45ef38a54e4cf..d5a797a32cba9fdfaea63cc046fe39b52049c821 100644 (file)
@@ -1243,6 +1243,8 @@ symbol_file_clear (int from_tty)
 
   current_program_space->free_all_objfiles ();
 
+  clear_symtab_users (0);
+
   gdb_assert (symfile_objfile == NULL);
   if (from_tty)
     printf_filtered (_("No symbol file now.\n"));
diff --git a/gdb/target-connection.c b/gdb/target-connection.c
new file mode 100644 (file)
index 0000000..c8c63ab
--- /dev/null
@@ -0,0 +1,159 @@
+/* List of target connections for GDB.
+
+   Copyright (C) 2017-2020 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "target-connection.h"
+
+#include <map>
+
+#include "inferior.h"
+#include "target.h"
+
+/* A map between connection number and representative process_stratum
+   target.  */
+static std::map<int, process_stratum_target *> process_targets;
+
+/* The highest connection number ever given to a target.  */
+static int highest_target_connection_num;
+
+/* See target-connection.h.  */
+
+void
+connection_list_add (process_stratum_target *t)
+{
+  if (t->connection_number == 0)
+    {
+      t->connection_number = ++highest_target_connection_num;
+      process_targets[t->connection_number] = t;
+    }
+}
+
+/* See target-connection.h.  */
+
+void
+connection_list_remove (process_stratum_target *t)
+{
+  process_targets.erase (t->connection_number);
+  t->connection_number = 0;
+}
+
+/* See target-connection.h.  */
+
+std::string
+make_target_connection_string (process_stratum_target *t)
+{
+  if (t->connection_string () != NULL)
+    return string_printf ("%s %s", t->shortname (),
+                         t->connection_string ());
+  else
+    return t->shortname ();
+}
+
+/* Prints the list of target connections and their details on UIOUT.
+
+   If REQUESTED_CONNECTIONS is not NULL, it's a list of GDB ids of the
+   target connections that should be printed.  Otherwise, all target
+   connections are printed.  */
+
+static void
+print_connection (struct ui_out *uiout, const char *requested_connections)
+{
+  int count = 0;
+  size_t what_len = 0;
+
+  /* Compute number of lines we will print.  */
+  for (const auto &it : process_targets)
+    {
+      if (!number_is_in_list (requested_connections, it.first))
+       continue;
+
+      ++count;
+
+      process_stratum_target *t = it.second;
+
+      size_t l = strlen (t->shortname ());
+      if (t->connection_string () != NULL)
+       l += 1 + strlen (t->connection_string ());
+
+      if (l > what_len)
+       what_len = l;
+    }
+
+  if (count == 0)
+    {
+      uiout->message (_("No connections.\n"));
+      return;
+    }
+
+  ui_out_emit_table table_emitter (uiout, 4, process_targets.size (),
+                                  "connections");
+
+  uiout->table_header (1, ui_left, "current", "");
+  uiout->table_header (4, ui_left, "number", "Num");
+  /* The text in the "what" column may include spaces.  Add one extra
+     space to visually separate the What and Description columns a
+     little better.  Compare:
+      "* 1    remote :9999 Remote serial target in gdb-specific protocol"
+      "* 1    remote :9999  Remote serial target in gdb-specific protocol"
+  */
+  uiout->table_header (what_len + 1, ui_left, "what", "What");
+  uiout->table_header (17, ui_left, "description", "Description");
+
+  uiout->table_body ();
+
+  for (const auto &it : process_targets)
+    {
+      process_stratum_target *t = it.second;
+
+      if (!number_is_in_list (requested_connections, t->connection_number))
+       continue;
+
+      ui_out_emit_tuple tuple_emitter (uiout, NULL);
+
+      if (current_inferior ()->process_target () == t)
+       uiout->field_string ("current", "*");
+      else
+       uiout->field_skip ("current");
+
+      uiout->field_signed ("number", t->connection_number);
+
+      uiout->field_string ("what", make_target_connection_string (t).c_str ());
+
+      uiout->field_string ("description", t->longname ());
+
+      uiout->text ("\n");
+    }
+}
+
+/* The "info connections" command.  */
+
+static void
+info_connections_command (const char *args, int from_tty)
+{
+  print_connection (current_uiout, args);
+}
+
+void
+_initialize_target_connection ()
+{
+  add_info ("connections", info_connections_command,
+           _("\
+Target connections in use.\n\
+Shows the list of target connections currently in use."));
+}
diff --git a/gdb/target-connection.h b/gdb/target-connection.h
new file mode 100644 (file)
index 0000000..f97e476
--- /dev/null
@@ -0,0 +1,40 @@
+/* List of target connections for GDB.
+
+   Copyright (C) 2017-2020 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef TARGET_CONNECTION_H
+#define TARGET_CONNECTION_H
+
+#include <string>
+
+struct process_stratum_target;
+
+/* Add a process target to the connection list, if not already
+   added.  */
+void connection_list_add (process_stratum_target *t);
+
+/* Remove a process target from the connection list.  */
+void connection_list_remove (process_stratum_target *t);
+
+/* Make a target connection string for T.  This is usually T's
+   shortname, but it includes the result of
+   process_stratum_target::connection_string() too if T supports
+   it.  */
+std::string make_target_connection_string (process_stratum_target *t);
+
+#endif /* TARGET_CONNECTION_H */
index 52034fe4360754077a0a985ffb713f7c7f95d5ae..5c2142b63fa115f911c3d9fb54d6ca242384cdbb 100644 (file)
@@ -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)
 {
index e3e30afd7a5450b65101ac2c90d8be7190bd65dd..f6058451d654351781106283138dc42e6860a54e 100644 (file)
@@ -49,6 +49,7 @@
 #include "gdbsupport/byte-vector.h"
 #include "terminal.h"
 #include <unordered_map>
+#include "target-connection.h"
 
 static void generic_tls_error (void) ATTRIBUTE_NORETURN;
 
@@ -110,10 +111,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 +118,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.  */
@@ -223,20 +220,22 @@ target_has_registers_1 (void)
   return 0;
 }
 
-int
-target_has_execution_1 (ptid_t the_ptid)
+bool
+target_has_execution_1 (inferior *inf)
 {
-  for (target_ops *t = current_top_target (); t != NULL; t = t->beneath ())
-    if (t->has_execution (the_ptid))
-      return 1;
+  for (target_ops *t = inf->top_target ();
+       t != nullptr;
+       t = inf->find_target_beneath (t))
+    if (t->has_execution (inf))
+      return true;
 
-  return 0;
+  return false;
 }
 
 int
 target_has_execution_current (void)
 {
-  return target_has_execution_1 (inferior_ptid);
+  return target_has_execution_1 (current_inferior ());
 }
 
 /* This is used to implement the various target commands.  */
@@ -501,13 +500,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 +557,32 @@ to_execution_direction must be implemented for reverse async");
 
 /* See target.h.  */
 
+void
+decref_target (target_ops *t)
+{
+  t->decref ();
+  if (t->refcount () == 0)
+    {
+      if (t->stratum () == process_stratum)
+       connection_list_remove (as_process_stratum_target (t));
+      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 (stratum == process_stratum)
+    connection_list_add (as_process_stratum_target (t));
+
+  /* If there's already a target at this stratum, remove it.  */
+
   if (m_stack[stratum] != NULL)
     unpush (m_stack[stratum]);
 
@@ -576,15 +598,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 +615,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 +647,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 +695,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 +1973,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 +1981,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 +2035,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 +2092,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 +2117,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 +2553,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 +2571,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 +3167,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);
 }
 
 \f
@@ -3247,6 +3263,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 +3357,33 @@ target_interrupt ()
 void
 target_pass_ctrlc (void)
 {
-  current_top_target ()->pass_ctrlc ();
+  /* 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 +4031,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);
index a8e551ce697f44cbd6511795e46564337ceaffb1..26b71cfeb09297156dfaf39ba556a7d733ae3a8b 100644 (file)
@@ -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
@@ -478,6 +480,13 @@ struct target_ops
       TARGET_DEFAULT_NORETURN (noprocess ());
     virtual void commit_resume ()
       TARGET_DEFAULT_IGNORE ();
+    /* See target_wait's description.  Note that implementations of
+       this method must not assume that inferior_ptid on entry is
+       pointing at the thread or inferior that ends up reporting an
+       event.  The reported event could be for some other thread in
+       the current inferior or even for a different process of the
+       current target.  inferior_ptid may also be null_ptid on
+       entry.  */
     virtual ptid_t wait (ptid_t, struct target_waitstatus *,
                         int TARGET_DEBUG_PRINTER (target_debug_print_options))
       TARGET_DEFAULT_FUNC (default_target_wait);
@@ -679,7 +688,7 @@ struct target_ops
     virtual bool has_memory () { return false; }
     virtual bool has_stack () { return false; }
     virtual bool has_registers () { return false; }
-    virtual bool has_execution (ptid_t) { return false; }
+    virtual bool has_execution (inferior *inf) { return false; }
 
     /* Control thread execution.  */
     virtual thread_control_capabilities get_thread_control_capabilities ()
@@ -694,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
@@ -1257,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.  */
@@ -1311,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 ())
@@ -1783,9 +1818,10 @@ extern int target_has_registers_1 (void);
    case this will become true after to_create_inferior or
    to_attach.  */
 
-extern int target_has_execution_1 (ptid_t);
+extern bool target_has_execution_1 (inferior *inf);
 
-/* Like target_has_execution_1, but always passes inferior_ptid.  */
+/* Like target_has_execution_1, but always passes
+   current_inferior().  */
 
 extern int target_has_execution_current (void);
 
@@ -2358,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);
index 536a9649595535c5f60c723f99442c18c48d99b5..e83e2195fa4e87b37bea7971f9944dbf229feae3 100644 (file)
@@ -1,3 +1,87 @@
+2020-01-10  Tankut Baris Aktemur  <tankut.baris.aktemur@intel.com>
+
+       * gdb.multi/multi-target.exp (setup): Factor out "info
+       connections" and "info inferiors" tests to ...
+       (test_info_inferiors): ... this new procedure.
+       (top level): Run new "info-inferiors" tests.
+
+2020-01-10  Pedro Alves  <palves@redhat.com>
+
+       * gdb.server/bkpt-other-inferior.exp: New file.
+
+2020-01-10  Pedro Alves  <palves@redhat.com>
+
+       * gdb.base/kill-detach-inferiors-cmd.exp: Adjust expected output
+       of "add-inferior".
+       * gdb.base/quit-live.exp: Likewise.
+       * gdb.base/remote-exec-file.exp: Likewise.
+       * gdb.guile/scm-progspace.exp: Likewise.
+       * gdb.linespec/linespec.exp: Likewise.
+       * gdb.mi/new-ui-mi-sync.exp: Likewise.
+       * gdb.mi/user-selected-context-sync.exp: Likewise.
+       * gdb.multi/multi-target.exp (setup): Add "info connection" and
+       "info inferiors" tests.
+       * gdb.multi/remove-inferiors.exp: Adjust expected output of
+       "add-inferior".
+       * gdb.multi/watchpoint-multi.exp: Likewise.
+       * gdb.python/py-inferior.exp: Likewise.
+       * gdb.server/extended-remote-restart.exp: Likewise.
+       * gdb.threads/fork-plus-threads.exp: Adjust expected output of
+       "info inferiors".
+       * gdb.threads/forking-threads-plus-breakpoint.exp: Likewise.
+       * gdb.trace/report.exp: Likewise.
+
+2020-01-10  Pedro Alves  <palves@redhat.com>
+
+       * gdb.multi/multi-target.c: New file.
+       * gdb.multi/multi-target.exp: New file.
+       * lib/gdbserver-support.exp (gdb_target_cmd): Handle "Non-stop
+       mode requested, but remote does not support non-stop".
+
+2020-01-10  Pedro Alves  <palves@redhat.com>
+
+       * gdb.server/extended-remote-restart.exp (test_reload): Explicitly
+       disconnect before reconnecting.
+
+2020-01-10  Tankut Baris Aktemur  <tankut.baris.aktemur@intel.com>
+           Pedro Alves  <palves@redhat.com>
+
+       * gdb.server/connect-without-multi-process.exp: Also test
+       continuing to end.
+
+2020-01-10  Pedro Alves  <palves@redhat.com>
+
+       * gdb.base/remote-exec-file.exp: New file.
+
+2020-01-10  Pedro Alves  <palves@redhat.com>
+
+       * gdb.base/fork-running-state.exp (do_test): Adjust expected
+       output.
+       * gdb.threads/async.c: New.
+       * gdb.threads/async.exp: New.
+       * gdb.multi/tids-gid-reset.c: New.
+       * gdb.multi/tids-gid-reset.exp: New.
+
+2020-01-10  George Barrett  <bob@bob131.so>
+
+       * gdb.base/stap-probe.c (relocation_marker): Add dummy variable
+       to help in finding the image relocation offset.
+       * gdb.base/stap-probe.exp (stap_test): Accept arbitrary compile
+       options in arguments.
+       (stap_test_no_debuginfo): Likewise.
+       (stap-probe-nosem-noopt-pie, stap-probe-nosem-noopt-nopie): Add
+       test variants.
+       (stap_test): Add null semaphore relocation test.
+
+2020-01-10  George Barrett  <bob@bob131.so>
+
+       * gdb.base/stap-probe.c: Rename USE_PROBES to USE_SEMAPHORES.
+       * gdb.base/stap-probe.exp: Likewise.
+       (stap_test): Pass argument as an additional flag.
+       (stap_test_no_debuginfo): Likewise.
+       (stap_test): Check `info probes stap' output for semaphore
+       addresses if the test binary is supposed to have them.
+
 2020-01-09  Andrew Burgess  <andrew.burgess@embecosm.com>
 
        * gdb.tui/basic.exp: Add more scrolling tests.
index c3bd0b01b29063eadb24bebbd5b1ef20571d11e7..f28f18c8854375b5b37036b36da6fc3ccd6c8022 100644 (file)
@@ -98,30 +98,19 @@ proc do_test { detach_on_fork follow_fork non_stop schedule_multiple } {
 
     set not_nl "\[^\r\n\]*"
 
-    if {$detach_on_fork == "on" && $non_stop == "on" && $follow_fork == "child"} {
+    if {$detach_on_fork == "on" && $follow_fork == "child"} {
        gdb_test "info threads" \
            "  2.1 ${not_nl}\\\(running\\\).*No selected thread.*"
-    } elseif {$detach_on_fork == "on" && $follow_fork == "child"} {
-       gdb_test "info threads" \
-           "\\\* 2.1 ${not_nl}\\\(running\\\)"
     } elseif {$detach_on_fork == "on"} {
        gdb_test "info threads" \
            "\\\* 1 ${not_nl}\\\(running\\\)"
-    } elseif {$non_stop == "on"
-             || ($schedule_multiple == "on" && $follow_fork == "parent")} {
+    } elseif {$non_stop == "on" || $schedule_multiple == "on"} {
        # Both parent and child should be marked running, and the
        # parent should be selected.
        gdb_test "info threads" \
            [multi_line \
                 "\\\* 1.1 ${not_nl} \\\(running\\\)${not_nl}" \
                 "  2.1 ${not_nl} \\\(running\\\)"]
-    } elseif {$schedule_multiple == "on" && $follow_fork == "child"} {
-       # Both parent and child should be marked running, and the
-       # child should be selected.
-       gdb_test "info threads" \
-           [multi_line \
-                "  1.1 ${not_nl} \\\(running\\\)${not_nl}" \
-                "\\\* 2.1 ${not_nl} \\\(running\\\)"]
     } else {
        set test "only $follow_fork marked running"
        gdb_test_multiple "info threads" $test {
@@ -131,7 +120,7 @@ proc do_test { detach_on_fork follow_fork non_stop schedule_multiple } {
            -re "\\\* 1.1 ${not_nl}\\\(running\\\)\r\n  2.1 ${not_nl}\r\n$gdb_prompt $" {
                gdb_assert [string eq $follow_fork "parent"] $test
            }
-           -re "1.1 ${not_nl}\r\n\\\* 2.1 ${not_nl}\\\(running\\\)\r\n$gdb_prompt $" {
+           -re "\\\* 1.1 ${not_nl}\r\n  2.1 ${not_nl}\\\(running\\\)\r\n$gdb_prompt $" {
                gdb_assert [string eq $follow_fork "child"] $test
            }
        }
index 600de9cd1030e49350ea53d09e935bfa9925c447..82e0c712c8f0e90b6bc99dd1aa7594cceee51701 100644 (file)
@@ -32,7 +32,7 @@ if [prepare_for_testing "failed to prepare" $executable] {
 runto_main
 
 # Add another forked inferior process.
-gdb_test "add-inferior" "Added inferior 2" "add inferior 2"
+gdb_test "add-inferior" "Added inferior 2 on connection .*" "add inferior 2"
 gdb_test "inferior 2" "Switching to inferior 2.*"
 gdb_test "file $binfile" "Reading symbols from .*" "load binary"
 gdb_test "start" "Temporary breakpoint.*Starting program.*"
@@ -40,7 +40,7 @@ gdb_test "start" "Temporary breakpoint.*Starting program.*"
 # Add an attached inferior process.
 set test_spawn_id [spawn_wait_for_attach $binfile]
 set test_pid [spawn_id_get_pid $test_spawn_id]
-gdb_test "add-inferior" "Added inferior 3" "add inferior 3"
+gdb_test "add-inferior" "Added inferior 3 on connection .*" "add inferior 3"
 gdb_test "inferior 3" "Switching to inferior 3.*"
 gdb_test "attach $test_pid" "Attaching to process.*" "attach to pid"
 
index 109c5e9272bd086969e1a0439ba5342d4c8dd526..c8e2f019b2d5ebba4b8b092ddf1b54a7940ec708 100644 (file)
@@ -120,7 +120,7 @@ proc quit_with_live_inferior {appear_how extra_inferior quit_how} {
     }
 
     if {$extra_inferior} {
-       gdb_test "add-inferior" "Added inferior 2*" \
+       gdb_test "add-inferior" "Added inferior 2 on connection .*" \
            "add empty inferior 2"
        gdb_test "inferior 2" "Switching to inferior 2.*" \
            "switch to inferior 2"
diff --git a/gdb/testsuite/gdb.base/remote-exec-file.exp b/gdb/testsuite/gdb.base/remote-exec-file.exp
new file mode 100644 (file)
index 0000000..a479a79
--- /dev/null
@@ -0,0 +1,46 @@
+# Copyright 2019-2020 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Check that "show remote exec-file" displays each inferior's
+# exec-file.  Regression test for a bug where "show remote exec-file"
+# would show the last exec-file set, irrespective of the current
+# inferior.
+
+clean_restart
+
+# Set remote exec-file in inferior 1.
+with_test_prefix "set inf 1" {
+    gdb_test_no_output "set remote exec-file prog1"
+}
+
+# Set remote exec-file in inferior 2.
+with_test_prefix "set inf 2" {
+    gdb_test "add-inferior" "Added inferior 2.*" "add inferior 2"
+    gdb_test "inferior 2" "Switching to inferior 2.*"
+    gdb_test_no_output "set remote exec-file prog2"
+}
+
+# Check that "show remote exec-file" diplays each inferior's
+# exec-file.
+
+with_test_prefix "show inf 1" {
+    gdb_test "inferior 1" "Switching to inferior 1.*"
+    gdb_test "show remote exec-file" "prog1"
+}
+
+with_test_prefix "show inf 2" {
+    gdb_test "inferior 2" "Switching to inferior 2.*"
+    gdb_test "show remote exec-file" "prog2"
+}
index f79e9e1cb33bc6114a2159a81b2ba394bdcd1cf1..5cb549498a5abc9a949e573bef600db9dcf451c1 100644 (file)
@@ -15,7 +15,7 @@
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
-#if USE_PROBES
+#if USE_SEMAPHORES
 
 #define _SDT_HAS_SEMAPHORES
 __extension__ unsigned short test_user_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes")));
@@ -31,6 +31,8 @@ __extension__ unsigned short test_pstr_semaphore __attribute__ ((unused)) __attr
 __extension__ unsigned short test_ps_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes")));
 #else
 
+int relocation_marker __attribute__ ((unused));
+
 #define TEST 1
 #define TEST2 1
 
index b35f350e4466bfacb462d230b76aead8c0cfbeef..398bc8936cc8bdabae7763e21100595c266b6770 100644 (file)
@@ -18,14 +18,20 @@ standard_testfile
 # Run the tests.  We run the tests two different ways: once with a
 # plain probe, and once with a probe that has an associated semaphore.
 # This returns -1 on failure to compile or start, 0 otherwise.
-proc stap_test {exec_name {arg ""}} {
+proc stap_test {exec_name {args ""}} {
     global testfile hex srcfile
 
     if {[prepare_for_testing "failed to prepare" ${exec_name} $srcfile \
-          [concat $arg debug]]} {
+          [concat $args debug]]} {
        return -1
     }
 
+    set semaphore_addr_var ""
+    if {[string first "-DUSE_SEMAPHORES" $args] == -1} {
+       gdb_test_no_output "set breakpoint always-inserted on"
+       set semaphore_addr_var [get_hexadecimal_valueof "&relocation_marker" "0"]
+    }
+
     if ![runto_main] {
        return -1
     }
@@ -33,15 +39,34 @@ proc stap_test {exec_name {arg ""}} {
     gdb_test "print \$_probe_argc" "No probe at PC $hex" \
        "check argument not at probe point"
 
-    gdb_test "info probes stap" \
-       "test *user *$hex .*"
-    
+    if {[string first "-DUSE_SEMAPHORES" $args] != -1} {
+       gdb_test "info probes stap" \
+           "test *user *$hex *$hex .*"
+    } else {
+       gdb_test "info probes stap" \
+           "test *user *$hex .*"
+    }
+
     if {[runto "-pstap test:user"]} {
        pass "run to -pstap test:user"
     } else {
        fail "run to -pstap test:user"
     }
 
+    if {[string first "-DUSE_SEMAPHORES" $args] == -1} {
+       set relocation_base \
+          [expr [get_hexadecimal_valueof "&relocation_marker" "0"] - $semaphore_addr_var]
+       if {$relocation_base != 0} {
+          # Checks that GDB doesn't mistakenly relocate and write to null
+          # semaphore addresses.  If it were to relocate a zero-valued
+          # semaphore address and increment the value at that address, we
+          # would expect to see "\200ELF" here instead.
+          gdb_test "p (*(char*) $relocation_base)@4" \
+               " = \"\\\\177ELF\"" \
+               "null semaphore relocation"
+       }
+    }
+
     # Test probe arguments.
     gdb_test "print \$_probe_argc" " = 1" \
     "print \$_probe_argc for probe user"
@@ -92,11 +117,11 @@ proc stap_test {exec_name {arg ""}} {
     return 0
 }
 
-proc stap_test_no_debuginfo {exec_name {arg ""}} {
+proc stap_test_no_debuginfo {exec_name {args ""}} {
     global testfile hex
 
     if {[prepare_for_testing "failed to prepare" ${exec_name} ${testfile}.c \
-          {$arg nodebug optimize=-O2}]} {
+          [concat $args nodebug optimize=-O2]]} {
        return -1
     }
 
@@ -163,10 +188,14 @@ with_test_prefix "without semaphore, not optimized" {
        untested "stap probe test failed"
          return -1
     }
+
+    foreach_with_prefix pie { "nopie" "pie" } {
+       stap_test "stap-probe-nosem-noopt-$pie" $pie
+    }
 }
 
 with_test_prefix "with semaphore, not optimized" {
-    stap_test "stap-probe-sem-noopt" "-DUSE_PROBES"
+    stap_test "stap-probe-sem-noopt" additional_flags=-DUSE_SEMAPHORES
 }
 
 with_test_prefix "without semaphore, optimized" {
@@ -174,5 +203,5 @@ with_test_prefix "without semaphore, optimized" {
 }
 
 with_test_prefix "with semaphore, optimized" {
-    stap_test_no_debuginfo "stap-probe-sem-opt" "-DUSE_PROBES"
+    stap_test_no_debuginfo "stap-probe-sem-opt" additional_flags=-DUSE_SEMAPHORES
 }
index 9b89ef425cefe054dad92a6e6d1f77b135292521..91a78e2ab8fd6bbb4fa3b82fbbf7f19e5f9311b2 100644 (file)
@@ -73,7 +73,7 @@ with_test_prefix "program unloaded" {
 # deleted.  We need to, for example, delete an inferior to get the progspace
 # to go away.
 
-gdb_test "add-inferior" "Added inferior 2" "create new inferior"
+gdb_test "add-inferior" "Added inferior 2.*" "create new inferior"
 gdb_test "inferior 2" ".*" "switch to new inferior"
 gdb_test_no_output "remove-inferiors 1" "remove first inferior"
 
index 38f1cf05738ca1eb5a6fac8e46dd483ea532da5a..be1b9189e2039cabda0eae30882fd962d18984bb 100644 (file)
@@ -201,7 +201,7 @@ gdb_test "break lspec.h:$line" \
 # Multi-inferior tests.
 #
 
-gdb_test "add-inferior" "Added inferior 2" \
+gdb_test "add-inferior" "Added inferior 2.*" \
     "add inferior for linespec tests"
 
 gdb_test "inferior 2" "Switching to inferior 2 .*" \
index b94f3f9b7cba01975197c291d5687c87a9c98f15..a55fae67dfe7d0e8899b6e860edbba7f5c0dc2f6 100644 (file)
@@ -83,7 +83,7 @@ proc do_test {sync_command} {
     # in the separate MI UI.  Note the "run" variant usually triggers
     # =thread-group-started/=thread-created/=library-loaded as well.
     with_spawn_id $gdb_main_spawn_id {
-       gdb_test "add-inferior" "Added inferior 2"
+       gdb_test "add-inferior" "Added inferior 2 on connection .*"
     }
 
     # Interrupt the program.
index 8a752b0c3e48ad02009c1528738a770dc707fff7..390df005542cc937fe287530bc5460161344a73e 100644 (file)
@@ -415,7 +415,7 @@ proc_with_prefix test_setup { mode } {
        # Add the second inferior now.  While this is not mandatory, it allows
        # us to assume that per-inferior thread numbering will be used,
        # simplifying test_continue_to_start a bit (Thread 1.2 and not Thread 2).
-       gdb_test "add-inferior" "Added inferior 2" "add inferior 2"
+       gdb_test "add-inferior" "Added inferior 2 on connection .*" "add inferior 2"
 
        # Prepare the first inferior for the test.
        test_continue_to_start $mode 1
diff --git a/gdb/testsuite/gdb.multi/multi-target.c b/gdb/testsuite/gdb.multi/multi-target.c
new file mode 100644 (file)
index 0000000..23ec6bd
--- /dev/null
@@ -0,0 +1,100 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2017-2020 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <limits.h>
+#include <string.h>
+#include <pthread.h>
+
+#define NUM_THREADS 1
+
+static pthread_barrier_t barrier;
+
+static void *
+thread_start (void *arg)
+{
+  pthread_barrier_wait (&barrier);
+
+  while (1)
+    sleep (1);
+  return NULL;
+}
+
+static void
+all_started (void)
+{
+}
+
+int wait_for_gdb;
+
+static void
+function1 (void)
+{
+  while (wait_for_gdb)
+    sleep (1);
+}
+
+static void
+function2 (void)
+{
+  while (wait_for_gdb)
+    sleep (1);
+}
+
+static void
+function3 (void)
+{
+}
+
+static void
+function4 (void)
+{
+}
+
+static void
+function5 (void)
+{
+}
+
+int
+main (int argc, char ** argv)
+{
+  pthread_t thread;
+  int len;
+
+  alarm (360);
+
+  pthread_barrier_init (&barrier, NULL, NUM_THREADS + 1);
+  pthread_create (&thread, NULL, thread_start, NULL);
+
+  pthread_barrier_wait (&barrier);
+  all_started ();
+
+  while (1)
+    {
+      function1 (); /* set break 1 here */
+      function2 (); /* set break 2 here */
+      function3 ();
+      function4 ();
+      function5 ();
+      sleep (1);
+    }
+
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.multi/multi-target.exp b/gdb/testsuite/gdb.multi/multi-target.exp
new file mode 100644 (file)
index 0000000..3588eb4
--- /dev/null
@@ -0,0 +1,446 @@
+# Copyright 2017-2020 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test multi-target features.
+
+load_lib gdbserver-support.exp
+
+standard_testfile
+
+# The plain remote target can't do multiple inferiors.
+if {[target_info gdb_protocol] != ""} {
+    return
+}
+
+if { [prepare_for_testing "failed to prepare" ${binfile} "${srcfile}" \
+         {debug pthreads}] } {
+    return
+}
+
+proc connect_target_extended_remote {binfile} {
+    set res [gdbserver_start "--multi" ""]
+    set gdbserver_gdbport [lindex $res 1]
+    return [gdb_target_cmd "extended-remote" $gdbserver_gdbport]
+}
+
+# Add and start inferior number NUM.  Returns true on success, false
+# otherwise.
+proc add_inferior {num target binfile {gcorefile ""}} {
+    # Start another inferior.
+    gdb_test "add-inferior -no-connection" "Added inferior $num" \
+       "add empty inferior $num"
+    gdb_test "inferior $num" "Switching to inferior $num.*" \
+       "switch to inferior $num"
+    gdb_test "file ${binfile}" ".*" "load file in inferior $num"
+    gdb_test_no_output "set remote exec-file ${binfile}" \
+       "set remote-exec file in inferior $num"
+
+    if {$target == "core"} {
+       gdb_test "core $gcorefile" "Core was generated by.*" \
+           "core [file tail $gcorefile], inf $num"
+       return 1
+    }
+
+    if {$target == "extended-remote"} {
+       if {[connect_target_extended_remote $binfile]} {
+           return 0
+       }
+    }
+    if ![runto "all_started"] then {
+       return 0
+    }
+    delete_breakpoints
+
+    return 1
+}
+
+proc prepare_core {} {
+    global gcorefile gcore_created
+    global binfile
+
+    clean_restart ${binfile}
+
+    if ![runto all_started] then {
+       return -1
+    }
+
+    global testfile
+    set gcorefile [standard_output_file $testfile.gcore]
+    set gcore_created [gdb_gcore_cmd $gcorefile "save a core file"]
+}
+
+proc next_live_inferior {inf} {
+    incr inf
+    if {$inf == 3} {
+       # 3 is a core.
+       return 4
+    }
+    if {$inf > 5} {
+       # 6 is a core.
+       return 1
+    }
+
+    return $inf
+}
+
+# Return true on success, false otherwise.
+
+proc setup {non-stop} {
+    global gcorefile gcore_created
+    global binfile
+
+    clean_restart ${binfile}
+
+    # multi-target depends on target running in non-stop mode.  Force
+    # it on for remote targets, until this is the default.
+    gdb_test_no_output "maint set target-non-stop on"
+
+    gdb_test_no_output "set non-stop ${non-stop}"
+
+    if ![runto all_started] then {
+       return 0
+    }
+
+    delete_breakpoints
+
+    # inferior 1 -> native
+    # inferior 2 -> extended-remote
+    # inferior 3 -> core
+    # inferior 4 -> native
+    # inferior 5 -> extended-remote
+    # inferior 6 -> core
+    if {![add_inferior 2 "extended-remote" $binfile]} {
+       return 0
+    }
+    if {![add_inferior 3 "core" $binfile $gcorefile]} {
+       return 0
+    }
+    if {![add_inferior 4 "native" $binfile]} {
+       return 0
+    }
+    if {![add_inferior 5 "extended-remote" $binfile]} {
+       return 0
+    }
+    if {![add_inferior 6 "core" $binfile $gcorefile]} {
+       return 0
+    }
+
+    # For debugging.
+    gdb_test "info threads" ".*"
+
+    # Make "continue" resume all inferiors.
+    if {${non-stop} == "off"} {
+       gdb_test_no_output "set schedule-multiple on"
+    }
+
+    return 1
+}
+
+# Test "continue" to breakpoints in different targets.  In non-stop
+# mode, also tests "interrupt -a".
+proc test_continue {non-stop} {
+    if {![setup ${non-stop}]} {
+       untested "setup failed"
+       return
+    }
+
+    proc set_break {inf} {
+       gdb_test "break function${inf} thread ${inf}.1" \
+       "Breakpoint .* function${inf}\\..*"
+    }
+
+    # Select inferior INF, and then run to a breakpoint on inferior
+    # INF+1.
+    proc test_continue_inf {inf} {
+       upvar 1 non-stop non-stop
+
+       global gdb_prompt
+       delete_breakpoints
+
+       set next_inf [next_live_inferior $inf]
+
+       gdb_test "inferior $inf" "Switching to inferior $inf.*"
+       set_break $next_inf
+
+       if {${non-stop} == "off"} {
+           gdb_test "continue" "hit Breakpoint .* function${next_inf}.*"
+       } else {
+           set msg "continue"
+           gdb_test_multiple "continue -a&" $msg {
+               -re "Continuing.*$gdb_prompt " {
+                   pass $msg
+               }
+           }
+
+           set msg "hit bp"
+           gdb_test_multiple "" $msg {
+               -re "hit Breakpoint .* function${next_inf}" {
+                   pass $msg
+               }
+           }
+
+           set msg "stop all threads"
+           gdb_test_multiple "interrupt -a" $msg {
+               -re "$gdb_prompt " {
+                   for {set i 0} {$i < 7} {incr i} {
+                       set ok 0
+                       gdb_test_multiple "" $msg {
+                           -re "Thread\[^\r\n\]*stopped\\." {
+                               set ok 1
+                           }
+                       }
+                       if {!$ok} {
+                           break
+                       }
+                   }
+                   gdb_assert $ok $msg
+               }
+           }
+       }
+    }
+
+    for {set i 1} {$i <= 5} {incr i} {
+       if {$i == 3} {
+           # This is a core inferior.
+           continue
+       }
+
+       with_test_prefix "inf$i" {
+           test_continue_inf $i
+       }
+    }
+}
+
+# Test interrupting multiple targets with Ctrl-C.
+
+proc test_ctrlc {} {
+    if {![setup "off"]} {
+       untested "setup failed"
+       return
+    }
+
+    delete_breakpoints
+
+    # Select inferior INF, continue all inferiors, and then Ctrl-C.
+    proc test_ctrlc_inf {inf} {
+       global gdb_prompt
+
+       gdb_test "inferior $inf" "Switching to inferior $inf.*"
+
+       set msg "continue"
+       gdb_test_multiple "continue" $msg {
+           -re "Continuing" {
+               pass $msg
+           }
+       }
+
+       after 200 { send_gdb "\003" }
+
+       set msg "send_gdb control C"
+       gdb_test_multiple "" $msg {
+           -re "received signal SIGINT.*$gdb_prompt $" {
+               pass $msg
+           }
+       }
+
+       set msg "all threads stopped"
+       gdb_test_multiple "info threads" "$msg" {
+           -re "\\\(running\\\).*$gdb_prompt $" {
+               fail $msg
+           }
+           -re "$gdb_prompt $" {
+               pass $msg
+           }
+       }
+    }
+
+    for {set i 1} {$i <= 5} {incr i} {
+       if {$i == 3} {
+           # This is a core inferior.
+           continue
+       }
+
+       with_test_prefix "inf$i" {
+           test_ctrlc_inf $i
+       }
+    }
+}
+
+# Test "next" bouncing between two breakpoints in two threads running
+# in different targets.
+proc test_ping_pong_next {} {
+    global srcfile
+
+    if {![setup "off"]} {
+       untested "setup failed"
+       return
+    }
+
+    # block/unblock inferiors 1 and 2 according to INF1 and INF2.
+    proc block {inf1 inf2} {
+       gdb_test "thread apply 1.1 p wait_for_gdb = $inf1" " = $inf1"
+       gdb_test "thread apply 2.1 p wait_for_gdb = $inf2" " = $inf2"
+    }
+
+    # We're use inferiors 1 and 2.  Make sure they're really connected
+    # to different targets.
+    gdb_test "thread apply 1.1 maint print target-stack" \
+       "- native.*"
+    gdb_test "thread apply 2.1 maint print target-stack" \
+       "- extended-remote.*"
+
+    # Set two breakpoints, one for each of inferior 1 and 2.  Inferior
+    # 1 is running on the native target, and inferior 2 is running on
+    # extended-gdbserver.  Run to breakpoint 1 to gets things started.
+    set line1 [gdb_get_line_number "set break 1 here"]
+    set line2 [gdb_get_line_number "set break 2 here"]
+
+    gdb_test "thread 1.1" "Switching to thread 1.1 .*"
+
+    gdb_test "break $srcfile:$line1 thread 1.1" \
+       "Breakpoint .*$srcfile:$line1\\..*"
+
+    gdb_test "continue" "hit Breakpoint .*"
+
+    gdb_test "break $srcfile:$line2 thread 2.1" \
+       "Breakpoint .*$srcfile:$line2\\..*"
+
+    # Now block inferior 1 and issue "next".  We should stop at the
+    # breakpoint for inferior 2, given schedlock off.
+    with_test_prefix "next inf 1" {
+       block 1 0
+       gdb_test "next" "Thread 2.1 .*hit Breakpoint .*$srcfile:$line2.*"
+    }
+
+    # Now unblock inferior 2 and block inferior 1.  "next" should run
+    # into the breakpoint in inferior 1.
+    with_test_prefix "next inf 2" {
+       block 0 1
+       gdb_test "next" "Thread 1.1 .*hit Breakpoint .*$srcfile:$line1.*"
+    }
+
+    # Try nexting inferior 1 again.
+    with_test_prefix "next inf 1 again" {
+       block 1 0
+       gdb_test "next" "Thread 2.1 .*hit Breakpoint .*$srcfile:$line2.*"
+    }
+}
+
+# Test "info inferiors" and "info connections".  MULTI_PROCESS
+# indicates whether the multi-process feature of remote targets is
+# turned off or on.
+proc test_info_inferiors {multi_process} {
+    setup "off"
+
+    gdb_test_no_output \
+       "set remote multiprocess-feature-packet $multi_process"
+
+    # Get the description for inferior INF for when the current
+    # inferior id is CURRENT.
+    proc inf_desc {inf current} {
+       set ws "\[ \t\]+"
+       global decimal
+       upvar multi_process multi_process
+
+       if {($multi_process == "off") && ($inf == 2 || $inf == 5)} {
+           set desc "Remote target"
+       } else {
+           set desc "process ${decimal}"
+       }
+
+       set desc "${inf}${ws}${desc}${ws}"
+       if {$inf == $current} {
+           return "\\* $desc"
+       } else {
+           return "  $desc"
+       }
+    }
+
+    # Get the "Num" column for CONNECTION for when the current
+    # inferior id is CURRENT_INF.
+    proc connection_num {connection current_inf} {
+       switch $current_inf {
+           "4" { set current_connection "1"}
+           "5" { set current_connection "4"}
+           "6" { set current_connection "5"}
+           default { set current_connection $current_inf}
+       }
+       if {$connection == $current_connection} {
+           return "\\* $connection"
+       } else {
+           return "  $connection"
+       }
+    }
+
+    set ws "\[ \t\]+"
+    global decimal binfile
+
+    # Test "info connections" and "info inferior" by switching to each
+    # inferior one by one.
+    for {set inf 1} {$inf <= 6} {incr inf} {
+       with_test_prefix "inferior $inf" {
+           gdb_test "inferior $inf" "Switching to inferior $inf.*"
+
+           gdb_test "info connections" \
+               [multi_line \
+                    "Num${ws}What${ws}Description${ws}" \
+                    "[connection_num 1 $inf]${ws}native${ws}Native process${ws}" \
+                    "[connection_num 2 $inf]${ws}extended-remote localhost:$decimal${ws}Extended remote serial target in gdb-specific protocol${ws}" \
+                    "[connection_num 3 $inf]${ws}core${ws}Local core dump file${ws}" \
+                    "[connection_num 4 $inf]${ws}extended-remote localhost:$decimal${ws}Extended remote serial target in gdb-specific protocol${ws}" \
+                    "[connection_num 5 $inf]${ws}core${ws}Local core dump file${ws}" \
+                   ]
+
+           gdb_test "info inferiors" \
+               [multi_line \
+                    "Num${ws}Description${ws}Connection${ws}Executable${ws}" \
+                    "[inf_desc 1 $inf]1 \\(native\\)${ws}${binfile}${ws}" \
+                    "[inf_desc 2 $inf]2 \\(extended-remote localhost:$decimal\\)${ws}${binfile}${ws}" \
+                    "[inf_desc 3 $inf]3 \\(core\\)${ws}${binfile}${ws}" \
+                    "[inf_desc 4 $inf]1 \\(native\\)${ws}${binfile}${ws}" \
+                    "[inf_desc 5 $inf]4 \\(extended-remote localhost:$decimal\\)${ws}${binfile}${ws}" \
+                    "[inf_desc 6 $inf]5 \\(core\\)${ws}${binfile}${ws}" \
+                   ]
+       }
+    }
+}
+
+# Make a core file with two threads upfront.  Several tests load the
+# same core file.
+prepare_core
+
+# Some basic "continue" + breakpoints tests.
+with_test_prefix "continue" {
+    foreach_with_prefix non-stop {"off" "on"} {
+       test_continue ${non-stop}
+    }
+}
+
+# Some basic all-stop Ctrl-C tests.
+with_test_prefix "interrupt" {
+    test_ctrlc
+}
+
+# Test ping-ponging between two targets with "next".
+with_test_prefix "ping-pong" {
+    test_ping_pong_next
+}
+
+# Test "info inferiors" and "info connections" commands.
+with_test_prefix "info-inferiors" {
+    foreach_with_prefix multi_process {"on" "off"} {
+       test_info_inferiors $multi_process
+    }
+}
index 27a94b8b0e0d770f5c939c074d368eed41c9f285..54c2c000290c936c7157bc87466e7fa3f8f7c425 100644 (file)
@@ -26,7 +26,7 @@ proc switch_to_inferior { num message } {
 }
 
 proc add_inferior { expected_num message } {
-    gdb_test "add-inferior" "Added inferior ${expected_num}" "${message}"
+    gdb_test "add-inferior" "Added inferior ${expected_num}( on connection .*)?" "${message}"
 }
 
 proc test_remove_inferiors { } {
diff --git a/gdb/testsuite/gdb.multi/tids-gid-reset.c b/gdb/testsuite/gdb.multi/tids-gid-reset.c
new file mode 100644 (file)
index 0000000..60cde1e
--- /dev/null
@@ -0,0 +1,22 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2019-2020 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+int
+main (void)
+{
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.multi/tids-gid-reset.exp b/gdb/testsuite/gdb.multi/tids-gid-reset.exp
new file mode 100644 (file)
index 0000000..0a31512
--- /dev/null
@@ -0,0 +1,96 @@
+# Copyright 2015-2020 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Check that letting the inferior exit and restarting it again resets
+# the global TID counter, and thus the new thread 1.1 should end up
+# with global TID == 1.
+#
+# Also, check the same but with another inferior still running, in
+# which case the new thread 1.1 should end up with global TID == 3.
+
+standard_testfile
+
+if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} {pthreads debug}] } {
+    return -1
+}
+
+with_test_prefix "single-inferior" {
+    with_test_prefix "before restart" {
+       clean_restart ${testfile}
+
+       if { ![runto_main] } then {
+           return -1
+       }
+
+       gdb_test "info threads -gid" "\\* 1 +1 +.*"
+    }
+
+    with_test_prefix "restart" {
+       gdb_continue_to_end
+       if { ![runto_main] } then {
+           return -1
+       }
+    }
+
+    with_test_prefix "after restart" {
+       gdb_test "info threads -gid" "\\* 1 +1 +.*"
+    }
+}
+
+# For the following tests, multiple inferiors are needed, therefore
+# non-extended gdbserver is not supported.
+if [use_gdb_stub] {
+    untested "using gdb stub"
+    return
+}
+
+# Test with multiple inferiors.  This time, since we restart inferior
+# 1 while inferior 2 still has threads, then the new thread 1.1 should
+# end up with GID == 3, since we won't be able to reset the global
+# thread ID counter.
+with_test_prefix "multi-inferior" {
+    gdb_test "add-inferior" "Added inferior 2.*" "add empty inferior 2"
+    gdb_test "inferior 2" "Switching to inferior 2 .*" "switch to inferior 2"
+    gdb_load ${binfile}
+
+    if ![runto_main] then {
+       fail "starting inferior 2"
+       return
+    }
+
+    gdb_test "inferior 1" "Switching to inferior 1 .*" \
+       "switch back to inferior 1"
+
+    with_test_prefix "before restart" {
+       gdb_test "info threads -gid" \
+           [multi_line \
+                "\\* 1\.1 +1 +.*" \
+                "  2\.1 +2 +.*"]
+    }
+
+    with_test_prefix "restart" {
+       gdb_continue_to_end
+       if { ![runto_main] } then {
+           return -1
+       }
+    }
+
+    with_test_prefix "after restart" {
+       gdb_test "info threads -gid" \
+           [multi_line \
+                "\\* 1\.1 +3 +.*" \
+                "  2\.1 +2 +.*"]
+    }
+}
index 4ff24ee29a84d59775a0768a6ef423ecedcfa3de..2d48b70f95e47a40e0c22e4e91c953cfcd4874d1 100644 (file)
@@ -53,7 +53,7 @@ if [support_displaced_stepping] {
 gdb_breakpoint main {temporary}
 gdb_test "run" "Temporary breakpoint.* main .*" "start to main inferior 1"
 
-gdb_test "add-inferior" "Added inferior 2" "add inferior 2"
+gdb_test "add-inferior" "Added inferior 2 on connection .*" "add inferior 2"
 gdb_test "inferior 2" "witching to inferior 2 .*" "switch to inferior 2, first time"
 gdb_load $binfile
 
index a9a36b448fd089c91848567462d8daade428432f..997da196bc62b5385b5ac464e4b3e6e8370cbb2a 100644 (file)
@@ -279,7 +279,7 @@ with_test_prefix "selected_inferior" {
     gdb_test "inferior 1" ".*" "switch to first inferior"
     gdb_test "py print (gdb.selected_inferior().num)" "1" "first inferior selected"
 
-    gdb_test "add-inferior" "Added inferior 3" "create new inferior"
+    gdb_test "add-inferior" "Added inferior 3 on connection .*" "create new inferior"
     gdb_test "inferior 3" ".*" "switch to third inferior"
     gdb_test "py print (gdb.selected_inferior().num)" "3" "third inferior selected"
     gdb_test "inferior 1" ".*" "switch back to first inferior"
@@ -288,7 +288,7 @@ with_test_prefix "selected_inferior" {
 
 # Test repr()/str()
 with_test_prefix "__repr__" {
-    gdb_test "add-inferior" "Added inferior 4" "add inferior 4"
+    gdb_test "add-inferior" "Added inferior 4 on connection .*" "add inferior 4"
     gdb_py_test_silent_cmd "python infs = gdb.inferiors()" "get inferior list" 1
     gdb_test "python print (infs\[0\])" "<gdb.Inferior num=1, pid=$decimal>"
     gdb_test "python print (infs)" \
diff --git a/gdb/testsuite/gdb.server/bkpt-other-inferior.exp b/gdb/testsuite/gdb.server/bkpt-other-inferior.exp
new file mode 100644 (file)
index 0000000..7ad38ea
--- /dev/null
@@ -0,0 +1,93 @@
+# Copyright 2019-2020 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test that GDB does not access the remote target's memory when
+# setting a breakpoint on a function that only exists in an inferior
+# that is not bound to the remote target.
+
+load_lib gdbserver-support.exp
+
+standard_testfile server.c
+
+if { [skip_gdbserver_tests] } {
+    return 0
+}
+
+if { [prepare_for_testing "failed to prepare" ${binfile} "${srcfile}" \
+         {debug pthreads}] } {
+    return
+}
+
+# Make sure we're disconnected, in case we're testing with an
+# extended-remote board, therefore already connected.
+gdb_test "disconnect" ".*"
+
+# Leave inferior 1 with the exec target, not connected.  Add another
+# inferior, and connect it to gdbserver.
+
+gdb_test "add-inferior" "Added inferior 2" \
+    "add inferior 2"
+gdb_test "inferior 2" "Switching to inferior 2.*" \
+    "switch to inferior 2"
+gdb_test "file ${binfile}" ".*" "load file in inferior 2"
+
+set target_exec [gdbserver_download_current_prog]
+
+# Start GDBserver.
+set res [gdbserver_start "" $target_exec]
+
+# Connect to GDBserver.
+set gdbserver_protocol [lindex $res 0]
+set gdbserver_gdbport [lindex $res 1]
+gdb_target_cmd $gdbserver_protocol $gdbserver_gdbport
+
+# Discard any symbol files that we have opened.
+set test "discard symbol table"
+gdb_test_multiple "file" $test {
+    -re "A program is being debugged already..*Are you sure you want to change the file.*y or n. $" {
+       gdb_test "y" ".*" $test \
+           {Discard symbol table from `.*'\? \(y or n\) } "y"
+    }
+}
+
+# At this point:
+#
+# - inferior 1 has symbols, and is not connected to any target.
+# - inferior 2 has no symbols, and is connected to gdbserver.
+
+# Setting a breakpoint at some function by name should set a
+# breakpoint on inferior 1, since it has symbols, and should not
+# result in any access to inferior 2's remote target.
+
+gdb_test_no_output "set debug remote 1"
+
+foreach inf_sel {1 2} {
+    with_test_prefix "inf $inf_sel" {
+       gdb_test "inferior $inf_sel" "Switching to inferior $inf_sel.*" \
+           "switch to inferior"
+
+       set test "set breakpoint"
+       gdb_test_multiple "break main" $test {
+           -re "Sending packet.*$gdb_prompt $" {
+               fail $test
+           }
+           -re "^break main\r\nBreakpoint .* at .*$gdb_prompt $" {
+               pass $test
+           }
+       }
+
+       delete_breakpoints
+    }
+}
index 6c7d162492f05453ec4eaa847a85838610d24d53..123089260dde2613b49e1d9ccabef49fca95cb5d 100644 (file)
@@ -14,7 +14,7 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 # Check that we can connect to GDBserver with the multiprocess
-# extensions disabled, and run to main.
+# extensions disabled, run to main, and finish the process.
 
 load_lib gdbserver-support.exp
 
@@ -52,6 +52,11 @@ proc do_test {multiprocess} {
        "target $gdbserver_protocol"
 
     gdb_test "continue" "main .*" "continue to main"
+
+    # The W/X packets do not include the PID of the exiting process
+    # without the multi-process extensions.  Check that we handle
+    # process exit correctly in that case.
+    gdb_continue_to_end
 }
 
 foreach multiprocess { "off" "auto" } {
index b34027348efff07db6018ad1d52c936e9500fe07..11f8a286ac96c7c18eece42c010aa72e7d45b906 100644 (file)
@@ -88,12 +88,16 @@ proc test_reload { do_kill_p follow_child_p } {
     gdb_breakpoint "breakpt"
     gdb_continue_to_breakpoint "breakpt"
 
-    # Check we have the expected inferiors.
+    set ws "\[ \t\]+"
+    set any_re "\[^\r\n\]+"
+    set connection_re $any_re
+    set executable_re $any_re
+
     gdb_test "info inferiors" \
        [multi_line \
-            "  Num  Description       Executable.*" \
-            "${parent_prefix} 1 +${live_inf_ptn} \[^\r\n\]+" \
-            "${child_prefix} 2 +${live_inf_ptn} \[^\r\n\]+" ] \
+            "  Num${ws}Description${ws}Connection${ws}Executable${ws}" \
+            "${parent_prefix} 1${ws}${live_inf_ptn}${ws}${connection_re}${executable_re}" \
+            "${child_prefix} 2${ws}${live_inf_ptn}${ws}${connection_re}${executable_re}" ] \
        "Check inferiors at breakpoint"
 
     if { $do_kill_p } {
@@ -107,13 +111,15 @@ proc test_reload { do_kill_p follow_child_p } {
        # Check the first inferior really did die.
        gdb_test "info inferiors" \
            [multi_line \
-                "  Num  Description       Executable.*" \
-                "${parent_prefix} 1 +${parent_inf_after_kill_ptn} \[^\r\n\]+" \
-                "${child_prefix} 2 +${child_inf_after_kill_ptn} \[^\r\n\]+" ] \
+                "  Num${ws}Description${ws}Connection${ws}Executable${ws}" \
+                "${parent_prefix} 1${ws}${parent_inf_after_kill_ptn}${ws}${connection_re}${executable_re}" \
+                "${child_prefix} 2${ws}${child_inf_after_kill_ptn}${ws}${connection_re}${executable_re}" ] \
            "Check inferior was killed"
     }
 
-    # Reconnect to the target.
+    # Disconnect, and reconnect to the target.
+    gdb_test "disconnect" ".*"
+
     if { [gdb_reconnect] == 0 } {
        pass "reconnect after fork"
     } else {
diff --git a/gdb/testsuite/gdb.threads/async.c b/gdb/testsuite/gdb.threads/async.c
new file mode 100644 (file)
index 0000000..6649270
--- /dev/null
@@ -0,0 +1,70 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2019-2020 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+#define NUM 2
+
+static pthread_barrier_t threads_started_barrier;
+
+static void *
+thread_function (void *arg)
+{
+  pthread_barrier_wait (&threads_started_barrier);
+
+  while (1)
+    {
+      /* Sleep a bit to give the other threads a chance to run.  */
+      usleep (1); /* set breakpoint here */
+    }
+
+  pthread_exit (NULL);
+}
+
+static void
+all_started (void)
+{
+}
+
+int
+main ()
+{
+  pthread_t threads[NUM];
+  long i;
+
+  pthread_barrier_init (&threads_started_barrier, NULL, NUM + 1);
+
+  for (i = 1; i <= NUM; i++)
+    {
+      int res;
+
+      res = pthread_create (&threads[i - 1],
+                           NULL,
+                           thread_function, NULL);
+    }
+
+  pthread_barrier_wait (&threads_started_barrier);
+
+  all_started ();
+
+  sleep (180);
+
+  exit (EXIT_SUCCESS);
+}
diff --git a/gdb/testsuite/gdb.threads/async.exp b/gdb/testsuite/gdb.threads/async.exp
new file mode 100644 (file)
index 0000000..d93b6eb
--- /dev/null
@@ -0,0 +1,98 @@
+# Copyright (C) 2019-2020 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+standard_testfile
+
+if {[build_executable "failed to prepare" $testfile $srcfile {debug pthreads}] == -1} {
+    return -1
+}
+
+# At this point GDB will be busy handling the breakpoint hits and
+# re-resuming the program.  Even if GDB internally switches thread
+# context, the user should not notice it.  The following part of the
+# testcase ensures that.
+
+# Switch to thread EXPECTED_THR, and then confirm that the thread
+# stays selected.
+
+proc test_current_thread {expected_thr} {
+    global decimal
+    global gdb_prompt
+    global binfile
+
+    clean_restart $binfile
+
+    if {![runto "all_started"]} {
+       fail "could not run to all_started"
+       return
+    }
+
+    # Set a breakpoint that continuously fires but doeesn't cause a stop.
+    gdb_breakpoint [concat [gdb_get_line_number "set breakpoint here"] " if 0"]
+
+    gdb_test "thread $expected_thr" "Switching to thread $expected_thr .*" \
+       "switch to thread $expected_thr"
+
+    # Continue the program in the background.
+    set test "continue&"
+    gdb_test_multiple "continue&" $test {
+       -re "Continuing\\.\r\n$gdb_prompt " {
+           pass $test
+       }
+    }
+
+    set test "current thread is $expected_thr"
+    set fails 0
+    for {set i 0} {$i < 10} {incr i} {
+       after 200
+
+       set cur_thread 0
+       gdb_test_multiple "thread" $test {
+           -re "Current thread is ($decimal) .*$gdb_prompt " {
+               set cur_thread $expect_out(1,string)
+           }
+       }
+
+       if {$cur_thread != $expected_thr} {
+           incr fails
+       }
+    }
+
+    gdb_assert {$fails == 0} $test
+
+    # Explicitly interrupt the target, because in all-stop/remote,
+    # that's all we can do when the target is running.  If we don't do
+    # this, we'd time out trying to kill the target, while bringing
+    # down gdb & gdbserver.
+    set test "interrupt"
+    gdb_test_multiple $test $test {
+       -re "^interrupt\r\n$gdb_prompt " {
+           gdb_test_multiple "" $test {
+               -re "Thread .* received signal SIGINT, Interrupt\\." {
+                   pass $test
+               }
+           }
+       }
+    }
+}
+
+# Try once with each thread as current, to avoid missing a bug just
+# because some part of GDB manages to switch to the right thread by
+# chance.
+for {set thr 1} {$thr <= 3} {incr thr} {
+    with_test_prefix "thread $thr" {
+       test_current_thread $thr
+    }
+}
index 9db964a1b597630e0e41c3ab252c32f57a81c55b..8d36b96810ba6bb69f564437ea7f26b955e87b09 100644 (file)
@@ -109,7 +109,7 @@ proc do_test { detach_on_fork } {
        "no threads left"
 
     gdb_test "info inferiors" \
-       "Num\[ \t\]+Description\[ \t\]+Executable\[ \t\]+\r\n\\* 1 \[^\r\n\]+" \
+       "Num\[ \t\]+Description\[ \t\]+Connection\[ \t\]+Executable\[ \t\]+\r\n\\* 1 \[^\r\n\]+" \
        "only inferior 1 left"
 }
 
index 17efbc7eb8bb13c3f4d0c238f4d36730712c7563..c4c9596be3129ebd8a3482029f29328bf9c3acf3 100644 (file)
@@ -142,7 +142,7 @@ proc do_test { cond_bp_target detach_on_fork displaced } {
        "no threads left"
 
     gdb_test "info inferiors" \
-       "Num\[ \t\]+Description\[ \t\]+Executable\[ \t\]+\r\n\\* 1 \[^\r\n\]+" \
+       "Num\[ \t\]+Description\[ \t\]+Connection\[ \t\]+Executable\[ \t\]+\r\n\\* 1 \[^\r\n\]+" \
        "only inferior 1 left"
 }
 
index 05ccc049be4c4cbb5cf8d82095fe424d690f1671..93029757b777a7a0aa94f63feca6fbf7b69cc002 100644 (file)
@@ -391,7 +391,7 @@ proc use_collected_data { data_source } {
        # There is always a thread of an inferior, either a live one or
        # a faked one.
        gdb_test "info threads" "\\* ${decimal}    (process|Thread) \[0-9\.\]+\[ \t\].*"
-       gdb_test "info inferiors" "\\* 1    process ${decimal} \[ \t\]+${binfile}.*"
+       gdb_test "info inferiors" "\\* 1    process ${decimal} \[ \t\]+\[^\r\n\]*\[ \t\]+${binfile}.*"
     }
 }
 
index 21ec418236cf0eade2669f5ba09d3ed13cda3015..12796e8a41edcf4e0f3680a61f60ab31073cf829 100644 (file)
@@ -64,6 +64,10 @@ proc gdb_target_cmd_ext { targetname serialport {additional_text ""} } {
            -re "Couldn't establish connection to remote.*$gdb_prompt $" {
                verbose "Connection failed"
            }
+           -re "Non-stop mode requested, but remote does not support non-stop.*$gdb_prompt $" {
+               verbose "remote does not support non-stop"
+               return 1
+           }
            -re "Remote MIPS debugging.*$additional_text.*$gdb_prompt" {
                verbose "Set target to $targetname"
                return 0
index 636d889689c6376d855fddafc6f345c77cfbf2c5..a6bbc50185a8f4ab45ced0fed307260821462f28 100644 (file)
@@ -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 ())
index 169d42a1f0641fa7ce49a043cb55d1d199976739..95dc562436813db4ae939bf7458f1a96c3ad3ad7 100644 (file)
@@ -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;
 };
 
index 4959f938c7f33dd4fc5328803db8e8dc9c838f23..03fdc05140c1b5862fa1f71a4e27ed556e3cf1a3 100644 (file)
 
 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;
-
-static int thread_alive (struct thread_info *);
-
 /* RAII type used to increase / decrease the refcount of each thread
    in a given list of threads.  */
 
@@ -91,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;
 }
@@ -197,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.  */
@@ -262,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.
@@ -283,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;
@@ -302,10 +292,14 @@ add_thread_silent (ptid_t ptid)
          /* All done.  */
          return new_thr;
        }
-      else
-       /* Just go ahead and delete it.  */
-       delete_thread (tp);
+
+      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);
@@ -314,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);
 
@@ -328,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;
@@ -354,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
@@ -361,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.  */
@@ -516,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);
@@ -586,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 ());
 }
 
@@ -611,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.  */
@@ -679,14 +682,38 @@ any_live_thread_of_inferior (inferior *inf)
 }
 
 /* Return true if TP is an active thread.  */
-static int
-thread_alive (struct thread_info *tp)
+static bool
+thread_alive (thread_info *tp)
 {
   if (tp->state == THREAD_EXITED)
-    return 0;
-  if (!target_thread_alive (tp->ptid))
-    return 0;
-  return 1;
+    return false;
+
+  /* Ensure we're looking at the right target stack.  */
+  gdb_assert (tp->inf == current_inferior ());
+
+  return target_thread_alive (tp->ptid);
+}
+
+/* Switch to thread TP if it is alive.  Returns true if successfully
+   switched, false otherwise.  */
+
+static bool
+switch_to_thread_if_alive (thread_info *thr)
+{
+  scoped_restore_current_thread restore_thread;
+
+  /* Switch inferior first, so that we're looking at the right target
+     stack.  */
+  switch_to_inferior_no_thread (thr->inf);
+
+  if (thread_alive (thr))
+    {
+      switch_to_thread (thr);
+      restore_thread.dont_restore ();
+      return true;
+    }
+
+  return false;
 }
 
 /* See gdbthreads.h.  */
@@ -694,9 +721,15 @@ thread_alive (struct thread_info *tp)
 void
 prune_threads (void)
 {
+  scoped_restore_current_thread restore_thread;
+
   for (thread_info *tp : all_threads_safe ())
-    if (!thread_alive (tp))
-      delete_thread (tp);
+    {
+      switch_to_inferior_no_thread (tp->inf);
+
+      if (!thread_alive (tp))
+       delete_thread (tp);
+    }
 }
 
 /* See gdbthreads.h.  */
@@ -760,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;
@@ -768,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);
@@ -780,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;
 }
 
@@ -820,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
@@ -828,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;
 
@@ -850,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
@@ -885,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;
 
@@ -1037,6 +1071,9 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
     gdb::optional<ui_out_emit_list> list_emitter;
     gdb::optional<ui_out_emit_table> table_emitter;
 
+    /* We'll be switching threads temporarily below.  */
+    scoped_restore_current_thread restore_thread;
+
     if (uiout->is_mi_like_p ())
       list_emitter.emplace (uiout, "threads");
     else
@@ -1054,6 +1091,10 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
 
            if (!uiout->is_mi_like_p ())
              {
+               /* Switch inferiors so we're looking at the right
+                  target stack.  */
+               switch_to_inferior_no_thread (tp->inf);
+
                target_id_col_width
                  = std::max (target_id_col_width,
                              thread_target_id_str (tp).size ());
@@ -1085,9 +1126,6 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
        uiout->table_body ();
       }
 
-    /* We'll be switching threads temporarily.  */
-    scoped_restore_current_thread restore_thread;
-
     for (inferior *inf : all_inferiors ())
       for (thread_info *tp : inf->threads ())
        {
@@ -1116,6 +1154,9 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
          if (show_global_ids || uiout->is_mi_like_p ())
            uiout->field_signed ("id", tp->global_num);
 
+         /* Switch to the thread (and inferior / target).  */
+         switch_to_thread (tp);
+
          /* For the CLI, we stuff everything into the target-id field.
             This is a gross hack to make the output come out looking
             correct.  The underlying problem here is that ui-out has no
@@ -1147,9 +1188,8 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
            uiout->text ("(running)\n");
          else
            {
-             /* The switch below puts us at the top of the stack (leaf
+             /* The switch above put us at the top of the stack (leaf
                 frame).  */
-             switch_to_thread (tp);
              print_stack_frame (get_selected_frame (NULL),
                                 /* For MI output, print frame level.  */
                                 uiout->is_mi_like_p (),
@@ -1299,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);
@@ -1310,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);
 }
 
@@ -1375,7 +1415,8 @@ restore_selected_frame (struct frame_id a_frame_id, int frame_level)
     }
 }
 
-scoped_restore_current_thread::~scoped_restore_current_thread ()
+void
+scoped_restore_current_thread::restore ()
 {
   /* If an entry of thread_info was previously selected, it won't be
      deleted because we've increased its refcount.  The thread represented
@@ -1402,6 +1443,22 @@ scoped_restore_current_thread::~scoped_restore_current_thread ()
       && target_has_stack
       && target_has_memory)
     restore_selected_frame (m_selected_frame_id, m_selected_frame_level);
+}
+
+scoped_restore_current_thread::~scoped_restore_current_thread ()
+{
+  if (!m_dont_restore)
+    {
+      try
+       {
+         restore ();
+       }
+      catch (const gdb_exception &ex)
+       {
+         /* We're in a dtor, there's really nothing else we can do
+            but swallow the exception.  */
+       }
+    }
 
   if (m_thread != NULL)
     m_thread->decref ();
@@ -1645,7 +1702,7 @@ thread_apply_all_command (const char *cmd, int from_tty)
       scoped_restore_current_thread restore_thread;
 
       for (thread_info *thr : thr_list_cpy)
-       if (thread_alive (thr))
+       if (switch_to_thread_if_alive (thr))
          thr_try_catch_cmd (thr, cmd, from_tty, flags);
     }
 }
@@ -1802,7 +1859,7 @@ thread_apply_command (const char *tidlist, int from_tty)
          continue;
        }
 
-      if (!thread_alive (tp))
+      if (!switch_to_thread_if_alive (tp))
        {
          warning (_("Thread %s has terminated."), print_thread_id (tp));
          continue;
@@ -1970,11 +2027,9 @@ show_print_thread_events (struct ui_file *file, int from_tty,
 void
 thread_select (const char *tidstr, thread_info *tp)
 {
-  if (!thread_alive (tp))
+  if (!switch_to_thread_if_alive (tp))
     error (_("Thread ID %s has terminated."), tidstr);
 
-  switch_to_thread (tp);
-
   annotate_thread_changed ();
 
   /* Since the current thread may have changed, see if there is any
@@ -2024,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 (tp->executing)
+      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)
        {
-         threads_executing = 1;
-         break;
+         targ->threads_executing = true;
+         return;
+       }
+
+      for (thread_info *tp : inf->non_exited_threads ())
+       {
+         if (tp->executing)
+           {
+             targ->threads_executing = true;
+             return;
+           }
        }
     }
 }
index 3b93683cfafae5e9a36ce8fb8409c3497cd383b9..a266bfa59256406b64624b1ee6547c1668b15293 100644 (file)
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -1740,13 +1740,17 @@ quit_force (int *exit_arg, int from_tty)
 
   /* Give all pushed targets a chance to do minimal cleanup, and pop
      them all out.  */
-  try
+  for (inferior *inf : all_inferiors ())
     {
-      pop_all_targets ();
-    }
-  catch (const gdb_exception &ex)
-    {
-      exception_print (gdb_stderr, ex);
+      switch_to_inferior_no_thread (inf);
+      try
+       {
+         pop_all_targets ();
+       }
+      catch (const gdb_exception &ex)
+       {
+         exception_print (gdb_stderr, ex);
+       }
     }
 
   /* Save the history information if it is appropriate to do so.  */
@@ -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 ();
 
index 5abfc1b56d013188ec7077409859678ece175c84..374e9bbcc50723e42bdef2d0cd33219c121c8f03 100644 (file)
@@ -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);
index 1ceb03e6918ec418c119a52da284380d7619d67b..c1a4a49337246e34d9586e4a2a8d8db836002d92 100644 (file)
@@ -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."));
@@ -616,8 +616,7 @@ tfile_interp_line (char *line, struct uploaded_tp **utpp,
 void
 tfile_target::close ()
 {
-  if (trace_fd < 0)
-    return;
+  gdb_assert (trace_fd != -1);
 
   inferior_ptid = null_ptid;   /* Avoid confusion from thread stuff.  */
   exit_inferior_silent (current_inferior ());
index 8f9dc0e06d7de9210d51747908ecd8ce46b7a525..9c7fdea72970b386bdaaafb387aa411d58bd1c4b 100644 (file)
@@ -127,7 +127,7 @@ public:
   bool has_memory () override;
   bool has_stack () override;
   bool has_registers () override;
-  bool has_execution (ptid_t) override { return false; }
+  bool has_execution (inferior *inf) override { return false; }
   bool thread_alive (ptid_t ptid) override;
 };
 
index 36a47f7cdbc28be0e4791a9e40795580a572166f..be5955d379fb4efcca6779b0aea1036d40657174 100644 (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)
This page took 0.181181 seconds and 4 git commands to generate.