]> Git Repo - binutils.git/blob - gdb/process-stratum-target.c
Automatic date update in version.in
[binutils.git] / gdb / process-stratum-target.c
1 /* Abstract base class inherited by all process_stratum targets
2
3    Copyright (C) 2018-2022 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
25 process_stratum_target::~process_stratum_target ()
26 {
27 }
28
29 struct address_space *
30 process_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
43 struct gdbarch *
44 process_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
51 bool
52 process_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
58 bool
59 process_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
65 bool
66 process_stratum_target::has_stack ()
67 {
68   /* If no inferior selected, there's no stack.  */
69   return inferior_ptid != null_ptid;
70 }
71
72 bool
73 process_stratum_target::has_registers ()
74 {
75   /* Can't read registers from no inferior.  */
76   return inferior_ptid != null_ptid;
77 }
78
79 bool
80 process_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
89 void
90 process_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
111 void
112 process_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
126 void
127 process_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
142 void
143 process_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
160 thread_info *
161 process_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
202 std::set<process_stratum_target *>
203 all_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
215 void
216 switch_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 }
This page took 0.037305 seconds and 4 git commands to generate.