1/* Abstract base class inherited by all process_stratum targets 2 3 Copyright (C) 2018-2023 Free Software Foundation, Inc. 4 5 This file is part of GDB. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20#include "defs.h" 21#include "process-stratum-target.h" 22#include "inferior.h" 23#include <algorithm> 24 25process_stratum_target::~process_stratum_target () 26{ 27} 28 29struct address_space * 30process_stratum_target::thread_address_space (ptid_t ptid) 31{ 32 /* Fall-back to the "main" address space of the inferior. */ 33 inferior *inf = find_inferior_ptid (this, ptid); 34 35 if (inf == NULL || inf->aspace == NULL) 36 internal_error (_("Can't determine the current " 37 "address space of thread %s\n"), 38 target_pid_to_str (ptid).c_str ()); 39 40 return inf->aspace; 41} 42 43struct gdbarch * 44process_stratum_target::thread_architecture (ptid_t ptid) 45{ 46 inferior *inf = find_inferior_ptid (this, ptid); 47 gdb_assert (inf != NULL); 48 return inf->gdbarch; 49} 50 51bool 52process_stratum_target::has_all_memory () 53{ 54 /* If no inferior selected, then we can't read memory here. */ 55 return inferior_ptid != null_ptid; 56} 57 58bool 59process_stratum_target::has_memory () 60{ 61 /* If no inferior selected, then we can't read memory here. */ 62 return inferior_ptid != null_ptid; 63} 64 65bool 66process_stratum_target::has_stack () 67{ 68 /* If no inferior selected, there's no stack. */ 69 return inferior_ptid != null_ptid; 70} 71 72bool 73process_stratum_target::has_registers () 74{ 75 /* Can't read registers from no inferior. */ 76 return inferior_ptid != null_ptid; 77} 78 79bool 80process_stratum_target::has_execution (inferior *inf) 81{ 82 /* If there's a process running already, we can't make it run 83 through hoops. */ 84 return inf->pid != 0; 85} 86 87/* See process-stratum-target.h. */ 88 89void 90process_stratum_target::follow_exec (inferior *follow_inf, ptid_t ptid, 91 const char *execd_pathname) 92{ 93 inferior *orig_inf = current_inferior (); 94 95 if (orig_inf != follow_inf) 96 { 97 /* Execution continues in a new inferior, push the original inferior's 98 process target on the new inferior's target stack. The process target 99 may decide to unpush itself from the original inferior's target stack 100 after that, at its discretion. */ 101 follow_inf->push_target (orig_inf->process_target ()); 102 thread_info *t = add_thread (follow_inf->process_target (), ptid); 103 104 /* Leave the new inferior / thread as the current inferior / thread. */ 105 switch_to_thread (t); 106 } 107} 108 109/* See process-stratum-target.h. */ 110 111void 112process_stratum_target::follow_fork (inferior *child_inf, ptid_t child_ptid, 113 target_waitkind fork_kind, 114 bool follow_child, 115 bool detach_on_fork) 116{ 117 if (child_inf != nullptr) 118 { 119 child_inf->push_target (this); 120 add_thread_silent (this, child_ptid); 121 } 122} 123 124/* See process-stratum-target.h. */ 125 126void 127process_stratum_target::maybe_add_resumed_with_pending_wait_status 128 (thread_info *thread) 129{ 130 gdb_assert (!thread->resumed_with_pending_wait_status_node.is_linked ()); 131 132 if (thread->resumed () && thread->has_pending_waitstatus ()) 133 { 134 infrun_debug_printf ("adding to resumed threads with event list: %s", 135 thread->ptid.to_string ().c_str ()); 136 m_resumed_with_pending_wait_status.push_back (*thread); 137 } 138} 139 140/* See process-stratum-target.h. */ 141 142void 143process_stratum_target::maybe_remove_resumed_with_pending_wait_status 144 (thread_info *thread) 145{ 146 if (thread->resumed () && thread->has_pending_waitstatus ()) 147 { 148 infrun_debug_printf ("removing from resumed threads with event list: %s", 149 thread->ptid.to_string ().c_str ()); 150 gdb_assert (thread->resumed_with_pending_wait_status_node.is_linked ()); 151 auto it = m_resumed_with_pending_wait_status.iterator_to (*thread); 152 m_resumed_with_pending_wait_status.erase (it); 153 } 154 else 155 gdb_assert (!thread->resumed_with_pending_wait_status_node.is_linked ()); 156} 157 158/* See process-stratum-target.h. */ 159 160thread_info * 161process_stratum_target::random_resumed_with_pending_wait_status 162 (inferior *inf, ptid_t filter_ptid) 163{ 164 auto matches = [inf, filter_ptid] (const thread_info &thread) 165 { 166 return thread.inf == inf && thread.ptid.matches (filter_ptid); 167 }; 168 169 /* First see how many matching events we have. */ 170 const auto &l = m_resumed_with_pending_wait_status; 171 unsigned int count = std::count_if (l.begin (), l.end (), matches); 172 173 if (count == 0) 174 return nullptr; 175 176 /* Now randomly pick a thread out of those that match the criteria. */ 177 int random_selector 178 = (int) ((count * (double) rand ()) / (RAND_MAX + 1.0)); 179 180 if (count > 1) 181 infrun_debug_printf ("Found %u events, selecting #%d", 182 count, random_selector); 183 184 /* Select the Nth thread that matches. */ 185 auto it = std::find_if (l.begin (), l.end (), 186 [&random_selector, &matches] 187 (const thread_info &thread) 188 { 189 if (!matches (thread)) 190 return false; 191 192 return random_selector-- == 0; 193 }); 194 195 gdb_assert (it != l.end ()); 196 197 return &*it; 198} 199 200/* See process-stratum-target.h. */ 201 202std::set<process_stratum_target *> 203all_non_exited_process_targets () 204{ 205 /* Inferiors may share targets. To eliminate duplicates, use a set. */ 206 std::set<process_stratum_target *> targets; 207 for (inferior *inf : all_non_exited_inferiors ()) 208 targets.insert (inf->process_target ()); 209 210 return targets; 211} 212 213/* See process-stratum-target.h. */ 214 215void 216switch_to_target_no_thread (process_stratum_target *target) 217{ 218 for (inferior *inf : all_inferiors (target)) 219 { 220 switch_to_inferior_no_thread (inf); 221 break; 222 } 223} 224