[gdb/testsuite] Fix gdb.threads/threadcrash.exp with glibc debuginfo
[binutils-gdb.git] / gdb / process-stratum-target.c
blobce8ff28958e0563da16c5cdd08ac1732cc962764
1 /* Abstract base class inherited by all process_stratum targets
3 Copyright (C) 2018-2024 Free Software Foundation, Inc.
5 This file is part of GDB.
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.
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.
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/>. */
20 #include "process-stratum-target.h"
21 #include "inferior.h"
22 #include <algorithm>
24 process_stratum_target::~process_stratum_target ()
28 struct gdbarch *
29 process_stratum_target::thread_architecture (ptid_t ptid)
31 inferior *inf = find_inferior_ptid (this, ptid);
32 gdb_assert (inf != NULL);
33 return inf->arch ();
36 bool
37 process_stratum_target::has_all_memory ()
39 /* If no inferior selected, then we can't read memory here. */
40 return inferior_ptid != null_ptid;
43 bool
44 process_stratum_target::has_memory ()
46 /* If no inferior selected, then we can't read memory here. */
47 return inferior_ptid != null_ptid;
50 bool
51 process_stratum_target::has_stack ()
53 /* If no inferior selected, there's no stack. */
54 return inferior_ptid != null_ptid;
57 bool
58 process_stratum_target::has_registers ()
60 /* Can't read registers from no inferior. */
61 return inferior_ptid != null_ptid;
64 bool
65 process_stratum_target::has_execution (inferior *inf)
67 /* If there's a process running already, we can't make it run
68 through hoops. */
69 return inf->pid != 0;
72 /* See process-stratum-target.h. */
74 void
75 process_stratum_target::follow_exec (inferior *follow_inf, ptid_t ptid,
76 const char *execd_pathname)
78 inferior *orig_inf = current_inferior ();
80 if (orig_inf != follow_inf)
82 /* Execution continues in a new inferior, push the original inferior's
83 process target on the new inferior's target stack. The process target
84 may decide to unpush itself from the original inferior's target stack
85 after that, at its discretion. */
86 follow_inf->push_target (orig_inf->process_target ());
87 thread_info *t = add_thread (follow_inf->process_target (), ptid);
89 /* Leave the new inferior / thread as the current inferior / thread. */
90 switch_to_thread (t);
94 /* See process-stratum-target.h. */
96 void
97 process_stratum_target::follow_fork (inferior *child_inf, ptid_t child_ptid,
98 target_waitkind fork_kind,
99 bool follow_child,
100 bool detach_on_fork)
102 if (child_inf != nullptr)
104 child_inf->push_target (this);
105 add_thread_silent (this, child_ptid);
109 /* See process-stratum-target.h. */
111 void
112 process_stratum_target::maybe_add_resumed_with_pending_wait_status
113 (thread_info *thread)
115 gdb_assert (!thread->resumed_with_pending_wait_status_node.is_linked ());
117 if (thread->resumed () && thread->has_pending_waitstatus ())
119 infrun_debug_printf ("adding to resumed threads with event list: %s",
120 thread->ptid.to_string ().c_str ());
121 m_resumed_with_pending_wait_status.push_back (*thread);
125 /* See process-stratum-target.h. */
127 void
128 process_stratum_target::maybe_remove_resumed_with_pending_wait_status
129 (thread_info *thread)
131 if (thread->resumed () && thread->has_pending_waitstatus ())
133 infrun_debug_printf ("removing from resumed threads with event list: %s",
134 thread->ptid.to_string ().c_str ());
135 gdb_assert (thread->resumed_with_pending_wait_status_node.is_linked ());
136 auto it = m_resumed_with_pending_wait_status.iterator_to (*thread);
137 m_resumed_with_pending_wait_status.erase (it);
139 else
140 gdb_assert (!thread->resumed_with_pending_wait_status_node.is_linked ());
143 /* See process-stratum-target.h. */
145 thread_info *
146 process_stratum_target::random_resumed_with_pending_wait_status
147 (inferior *inf, ptid_t filter_ptid)
149 auto matches = [inf, filter_ptid] (const thread_info &thread)
151 return thread.inf == inf && thread.ptid.matches (filter_ptid);
154 /* First see how many matching events we have. */
155 const auto &l = m_resumed_with_pending_wait_status;
156 unsigned int count = std::count_if (l.begin (), l.end (), matches);
158 if (count == 0)
159 return nullptr;
161 /* Now randomly pick a thread out of those that match the criteria. */
162 int random_selector
163 = (int) ((count * (double) rand ()) / (RAND_MAX + 1.0));
165 if (count > 1)
166 infrun_debug_printf ("Found %u events, selecting #%d",
167 count, random_selector);
169 /* Select the Nth thread that matches. */
170 auto it = std::find_if (l.begin (), l.end (),
171 [&random_selector, &matches]
172 (const thread_info &thread)
174 if (!matches (thread))
175 return false;
177 return random_selector-- == 0;
180 gdb_assert (it != l.end ());
182 return &*it;
185 /* See process-stratum-target.h. */
187 thread_info *
188 process_stratum_target::find_thread (ptid_t ptid)
190 inferior *inf = find_inferior_ptid (this, ptid);
191 if (inf == NULL)
192 return NULL;
193 return inf->find_thread (ptid);
196 /* See process-stratum-target.h. */
198 std::set<process_stratum_target *>
199 all_non_exited_process_targets ()
201 /* Inferiors may share targets. To eliminate duplicates, use a set. */
202 std::set<process_stratum_target *> targets;
203 for (inferior *inf : all_non_exited_inferiors ())
204 targets.insert (inf->process_target ());
206 return targets;
209 /* See process-stratum-target.h. */
211 void
212 switch_to_target_no_thread (process_stratum_target *target)
214 for (inferior *inf : all_inferiors (target))
216 switch_to_inferior_no_thread (inf);
217 break;