| /* Abstract base class inherited by all process_stratum targets | |
| Copyright (C) 2018-2023 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 PROCESS_STRATUM_TARGET_H | |
| #define PROCESS_STRATUM_TARGET_H | |
| #include "target.h" | |
| #include <set> | |
| #include "gdbsupport/intrusive_list.h" | |
| #include "gdbsupport/gdb-checked-static-cast.h" | |
| #include "gdbthread.h" | |
| /* Abstract base class inherited by all process_stratum targets. */ | |
| class process_stratum_target : public target_ops | |
| { | |
| public: | |
| ~process_stratum_target () override = 0; | |
| 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; } | |
| bool supports_non_stop () override { return false; } | |
| bool supports_disable_randomization () override { return false; } | |
| /* This default implementation returns the inferior's address | |
| space. */ | |
| struct address_space *thread_address_space (ptid_t ptid) override; | |
| /* This default implementation always returns target_gdbarch (). */ | |
| struct gdbarch *thread_architecture (ptid_t ptid) override; | |
| /* Default implementations for process_stratum targets. Return true | |
| if there's a selected inferior, false otherwise. */ | |
| bool has_all_memory () override; | |
| bool has_memory () override; | |
| bool has_stack () override; | |
| bool has_registers () override; | |
| bool has_execution (inferior *inf) override; | |
| /* Default implementation of follow_exec. | |
| If the current inferior and FOLLOW_INF are different (execution continues | |
| in a new inferior), push this process target to FOLLOW_INF's target stack | |
| and add an initial thread to FOLLOW_INF. */ | |
| void follow_exec (inferior *follow_inf, ptid_t ptid, | |
| const char *execd_pathname) override; | |
| /* Default implementation of follow_fork. | |
| If a child inferior was created by infrun while following the fork | |
| (CHILD_INF is non-nullptr), push this target on CHILD_INF's target stack | |
| and add an initial thread with ptid CHILD_PTID. */ | |
| void follow_fork (inferior *child_inf, ptid_t child_ptid, | |
| target_waitkind fork_kind, bool follow_child, | |
| bool detach_on_fork) 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; | |
| /* If THREAD is resumed and has a pending wait status, add it to the | |
| target's "resumed with pending wait status" list. */ | |
| void maybe_add_resumed_with_pending_wait_status (thread_info *thread); | |
| /* If THREAD is resumed and has a pending wait status, remove it from the | |
| target's "resumed with pending wait status" list. */ | |
| void maybe_remove_resumed_with_pending_wait_status (thread_info *thread); | |
| /* Return true if this target has at least one resumed thread with a pending | |
| wait status. */ | |
| bool has_resumed_with_pending_wait_status () const | |
| { return !m_resumed_with_pending_wait_status.empty (); } | |
| /* Return a random resumed thread with pending wait status belonging to INF | |
| and matching FILTER_PTID. */ | |
| thread_info *random_resumed_with_pending_wait_status | |
| (inferior *inf, ptid_t filter_ptid); | |
| /* Search function to lookup a (non-exited) thread by 'ptid'. */ | |
| thread_info *find_thread (ptid_t ptid); | |
| /* The connection number. Visible in "info connections". */ | |
| int connection_number = 0; | |
| /* Whether resumed threads must be committed to the target. | |
| When true, resumed threads must be committed to the execution | |
| target. | |
| When false, the target may leave resumed threads stopped when | |
| it's convenient or efficient to do so. When the core requires | |
| resumed threads to be committed again, this is set back to true | |
| and calls the `commit_resumed` method to allow the target to do | |
| so. | |
| To simplify the implementation of targets, the following methods | |
| are guaranteed to be called with COMMIT_RESUMED_STATE set to | |
| false: | |
| - resume | |
| - stop | |
| - wait | |
| Knowing this, the target doesn't need to implement different | |
| behaviors depending on the COMMIT_RESUMED_STATE, and can simply | |
| assume that it is false. | |
| Targets can take advantage of this to batch resumption requests, | |
| for example. In that case, the target doesn't actually resume in | |
| its `resume` implementation. Instead, it takes note of the | |
| resumption intent in `resume` and defers the actual resumption to | |
| `commit_resumed`. For example, the remote target uses this to | |
| coalesce multiple resumption requests in a single vCont | |
| packet. */ | |
| bool commit_resumed_state = false; | |
| private: | |
| /* List of threads managed by this target which simultaneously are resumed | |
| and have a pending wait status. | |
| This is done for optimization reasons, it would be possible to walk the | |
| inferior thread lists to find these threads. But since this is something | |
| we need to do quite frequently in the hot path, maintaining this list | |
| avoids walking the thread lists repeatedly. */ | |
| thread_info_resumed_with_pending_wait_status_list | |
| m_resumed_with_pending_wait_status; | |
| }; | |
| /* 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 gdb::checked_static_cast<process_stratum_target *> (target); | |
| } | |
| /* Return a collection of targets that have non-exited inferiors. */ | |
| extern std::set<process_stratum_target *> all_non_exited_process_targets (); | |
| /* Switch to the first inferior (and program space) of TARGET, and | |
| switch to no thread selected. */ | |
| extern void switch_to_target_no_thread (process_stratum_target *target); | |
| #endif /* !defined (PROCESS_STRATUM_TARGET_H) */ |