x86/Intel: adjust representation of embedded rounding / SAE
[binutils-gdb.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 (__FILE__, __LINE__,
37 _("Can't determine the current "
38 "address space of thread %s\n"),
39 target_pid_to_str (ptid).c_str ());
40
41 return inf->aspace;
42 }
43
44 struct gdbarch *
45 process_stratum_target::thread_architecture (ptid_t ptid)
46 {
47 inferior *inf = find_inferior_ptid (this, ptid);
48 gdb_assert (inf != NULL);
49 return inf->gdbarch;
50 }
51
52 bool
53 process_stratum_target::has_all_memory ()
54 {
55 /* If no inferior selected, then we can't read memory here. */
56 return inferior_ptid != null_ptid;
57 }
58
59 bool
60 process_stratum_target::has_memory ()
61 {
62 /* If no inferior selected, then we can't read memory here. */
63 return inferior_ptid != null_ptid;
64 }
65
66 bool
67 process_stratum_target::has_stack ()
68 {
69 /* If no inferior selected, there's no stack. */
70 return inferior_ptid != null_ptid;
71 }
72
73 bool
74 process_stratum_target::has_registers ()
75 {
76 /* Can't read registers from no inferior. */
77 return inferior_ptid != null_ptid;
78 }
79
80 bool
81 process_stratum_target::has_execution (inferior *inf)
82 {
83 /* If there's a process running already, we can't make it run
84 through hoops. */
85 return inf->pid != 0;
86 }
87
88 /* See process-stratum-target.h. */
89
90 void
91 process_stratum_target::follow_exec (inferior *follow_inf, ptid_t ptid,
92 const char *execd_pathname)
93 {
94 inferior *orig_inf = current_inferior ();
95
96 if (orig_inf != follow_inf)
97 {
98 /* Execution continues in a new inferior, push the original inferior's
99 process target on the new inferior's target stack. The process target
100 may decide to unpush itself from the original inferior's target stack
101 after that, at its discretion. */
102 follow_inf->push_target (orig_inf->process_target ());
103 thread_info *t = add_thread (follow_inf->process_target (), ptid);
104
105 /* Leave the new inferior / thread as the current inferior / thread. */
106 switch_to_thread (t);
107 }
108 }
109
110 /* See process-stratum-target.h. */
111
112 void
113 process_stratum_target::follow_fork (inferior *child_inf, ptid_t child_ptid,
114 target_waitkind fork_kind,
115 bool follow_child,
116 bool detach_on_fork)
117 {
118 if (child_inf != nullptr)
119 {
120 child_inf->push_target (this);
121 add_thread_silent (this, child_ptid);
122 }
123 }
124
125 /* See process-stratum-target.h. */
126
127 void
128 process_stratum_target::maybe_add_resumed_with_pending_wait_status
129 (thread_info *thread)
130 {
131 gdb_assert (!thread->resumed_with_pending_wait_status_node.is_linked ());
132
133 if (thread->resumed () && thread->has_pending_waitstatus ())
134 {
135 infrun_debug_printf ("adding to resumed threads with event list: %s",
136 thread->ptid.to_string ().c_str ());
137 m_resumed_with_pending_wait_status.push_back (*thread);
138 }
139 }
140
141 /* See process-stratum-target.h. */
142
143 void
144 process_stratum_target::maybe_remove_resumed_with_pending_wait_status
145 (thread_info *thread)
146 {
147 if (thread->resumed () && thread->has_pending_waitstatus ())
148 {
149 infrun_debug_printf ("removing from resumed threads with event list: %s",
150 thread->ptid.to_string ().c_str ());
151 gdb_assert (thread->resumed_with_pending_wait_status_node.is_linked ());
152 auto it = m_resumed_with_pending_wait_status.iterator_to (*thread);
153 m_resumed_with_pending_wait_status.erase (it);
154 }
155 else
156 gdb_assert (!thread->resumed_with_pending_wait_status_node.is_linked ());
157 }
158
159 /* See process-stratum-target.h. */
160
161 thread_info *
162 process_stratum_target::random_resumed_with_pending_wait_status
163 (inferior *inf, ptid_t filter_ptid)
164 {
165 auto matches = [inf, filter_ptid] (const thread_info &thread)
166 {
167 return thread.inf == inf && thread.ptid.matches (filter_ptid);
168 };
169
170 /* First see how many matching events we have. */
171 const auto &l = m_resumed_with_pending_wait_status;
172 unsigned int count = std::count_if (l.begin (), l.end (), matches);
173
174 if (count == 0)
175 return nullptr;
176
177 /* Now randomly pick a thread out of those that match the criteria. */
178 int random_selector
179 = (int) ((count * (double) rand ()) / (RAND_MAX + 1.0));
180
181 if (count > 1)
182 infrun_debug_printf ("Found %u events, selecting #%d",
183 count, random_selector);
184
185 /* Select the Nth thread that matches. */
186 auto it = std::find_if (l.begin (), l.end (),
187 [&random_selector, &matches]
188 (const thread_info &thread)
189 {
190 if (!matches (thread))
191 return false;
192
193 return random_selector-- == 0;
194 });
195
196 gdb_assert (it != l.end ());
197
198 return &*it;
199 }
200
201 /* See process-stratum-target.h. */
202
203 std::set<process_stratum_target *>
204 all_non_exited_process_targets ()
205 {
206 /* Inferiors may share targets. To eliminate duplicates, use a set. */
207 std::set<process_stratum_target *> targets;
208 for (inferior *inf : all_non_exited_inferiors ())
209 targets.insert (inf->process_target ());
210
211 return targets;
212 }
213
214 /* See process-stratum-target.h. */
215
216 void
217 switch_to_target_no_thread (process_stratum_target *target)
218 {
219 for (inferior *inf : all_inferiors (target))
220 {
221 switch_to_inferior_no_thread (inf);
222 break;
223 }
224 }