4d23f1cbff4ae753c57903e533c8a9c4f7f6ab71
[binutils-gdb.git] / gdb / target / waitstatus.h
1 /* Target waitstatus definitions and prototypes.
2
3 Copyright (C) 1990-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 #ifndef TARGET_WAITSTATUS_H
21 #define TARGET_WAITSTATUS_H
22
23 #include "diagnostics.h"
24 #include "gdbsupport/gdb_signals.h"
25
26 /* Stuff for target_wait. */
27
28 /* Generally, what has the program done? */
29 enum target_waitkind
30 {
31 /* The program has exited. The exit status is in value.integer. */
32 TARGET_WAITKIND_EXITED,
33
34 /* The program has stopped with a signal. Which signal is in
35 value.sig. */
36 TARGET_WAITKIND_STOPPED,
37
38 /* The program has terminated with a signal. Which signal is in
39 value.sig. */
40 TARGET_WAITKIND_SIGNALLED,
41
42 /* The program is letting us know that it dynamically loaded
43 something (e.g. it called load(2) on AIX). */
44 TARGET_WAITKIND_LOADED,
45
46 /* The program has forked. A "related" process' PTID is in
47 value.related_pid. I.e., if the child forks, value.related_pid
48 is the parent's ID. */
49 TARGET_WAITKIND_FORKED,
50
51 /* The program has vforked. A "related" process's PTID is in
52 value.related_pid. */
53 TARGET_WAITKIND_VFORKED,
54
55 /* The program has exec'ed a new executable file. The new file's
56 pathname is pointed to by value.execd_pathname. */
57 TARGET_WAITKIND_EXECD,
58
59 /* The program had previously vforked, and now the child is done
60 with the shared memory region, because it exec'ed or exited.
61 Note that the event is reported to the vfork parent. This is
62 only used if GDB did not stay attached to the vfork child,
63 otherwise, a TARGET_WAITKIND_EXECD or
64 TARGET_WAITKIND_EXIT|SIGNALLED event associated with the child
65 has the same effect. */
66 TARGET_WAITKIND_VFORK_DONE,
67
68 /* The program has entered or returned from a system call. On
69 HP-UX, this is used in the hardware watchpoint implementation.
70 The syscall's unique integer ID number is in
71 value.syscall_id. */
72 TARGET_WAITKIND_SYSCALL_ENTRY,
73 TARGET_WAITKIND_SYSCALL_RETURN,
74
75 /* Nothing happened, but we stopped anyway. This perhaps should
76 be handled within target_wait, but I'm not sure target_wait
77 should be resuming the inferior. */
78 TARGET_WAITKIND_SPURIOUS,
79
80 /* An event has occurred, but we should wait again.
81 Remote_async_wait() returns this when there is an event
82 on the inferior, but the rest of the world is not interested in
83 it. The inferior has not stopped, but has just sent some output
84 to the console, for instance. In this case, we want to go back
85 to the event loop and wait there for another event from the
86 inferior, rather than being stuck in the remote_async_wait()
87 function. This way the event loop is responsive to other events,
88 like for instance the user typing. */
89 TARGET_WAITKIND_IGNORE,
90
91 /* The target has run out of history information,
92 and cannot run backward any further. */
93 TARGET_WAITKIND_NO_HISTORY,
94
95 /* There are no resumed children left in the program. */
96 TARGET_WAITKIND_NO_RESUMED,
97
98 /* The thread was created. */
99 TARGET_WAITKIND_THREAD_CREATED,
100
101 /* The thread has exited. The exit status is in value.integer. */
102 TARGET_WAITKIND_THREAD_EXITED,
103 };
104
105 /* Return KIND as a string. */
106
107 static inline const char *
108 target_waitkind_str (target_waitkind kind)
109 {
110 /* Make sure the compiler warns if a new TARGET_WAITKIND enumerator is added
111 but not handled here. */
112 DIAGNOSTIC_PUSH
113 DIAGNOSTIC_ERROR_SWITCH
114 switch (kind)
115 {
116 case TARGET_WAITKIND_EXITED:
117 return "EXITED";
118 case TARGET_WAITKIND_STOPPED:
119 return "STOPPED";
120 case TARGET_WAITKIND_SIGNALLED:
121 return "SIGNALLED";
122 case TARGET_WAITKIND_LOADED:
123 return "LOADED";
124 case TARGET_WAITKIND_FORKED:
125 return "FORKED";
126 case TARGET_WAITKIND_VFORKED:
127 return "VFORKED";
128 case TARGET_WAITKIND_EXECD:
129 return "EXECD";
130 case TARGET_WAITKIND_VFORK_DONE:
131 return "VFORK_DONE";
132 case TARGET_WAITKIND_SYSCALL_ENTRY:
133 return "SYSCALL_ENTRY";
134 case TARGET_WAITKIND_SYSCALL_RETURN:
135 return "SYSCALL_RETURN";
136 case TARGET_WAITKIND_SPURIOUS:
137 return "SPURIOUS";
138 case TARGET_WAITKIND_IGNORE:
139 return "IGNORE";
140 case TARGET_WAITKIND_NO_HISTORY:
141 return "NO_HISTORY";
142 case TARGET_WAITKIND_NO_RESUMED:
143 return "NO_RESUMED";
144 case TARGET_WAITKIND_THREAD_CREATED:
145 return "THREAD_CREATED";
146 case TARGET_WAITKIND_THREAD_EXITED:
147 return "THREAD_EXITED";
148 };
149 DIAGNOSTIC_POP
150
151 gdb_assert_not_reached ("invalid target_waitkind value: %d\n", (int) kind);
152 }
153
154 struct target_waitstatus
155 {
156 /* Default constructor. */
157 target_waitstatus () = default;
158
159 /* Copy constructor. */
160
161 target_waitstatus (const target_waitstatus &other)
162 {
163 m_kind = other.m_kind;
164 m_value = other.m_value;
165
166 if (m_kind == TARGET_WAITKIND_EXECD)
167 m_value.execd_pathname = xstrdup (m_value.execd_pathname);
168 }
169
170 /* Move constructor. */
171
172 target_waitstatus (target_waitstatus &&other)
173 {
174 m_kind = other.m_kind;
175 m_value = other.m_value;
176
177 if (m_kind == TARGET_WAITKIND_EXECD)
178 other.m_value.execd_pathname = nullptr;
179
180 other.reset ();
181 }
182
183 /* Copy assignment operator. */
184
185 target_waitstatus &operator= (const target_waitstatus &rhs)
186 {
187 this->reset ();
188 m_kind = rhs.m_kind;
189 m_value = rhs.m_value;
190
191 if (m_kind == TARGET_WAITKIND_EXECD)
192 m_value.execd_pathname = xstrdup (m_value.execd_pathname);
193
194 return *this;
195 }
196
197 /* Move assignment operator. */
198
199 target_waitstatus &operator= (target_waitstatus &&rhs)
200 {
201 this->reset ();
202 m_kind = rhs.m_kind;
203 m_value = rhs.m_value;
204
205 if (m_kind == TARGET_WAITKIND_EXECD)
206 rhs.m_value.execd_pathname = nullptr;
207
208 rhs.reset ();
209
210 return *this;
211 }
212
213 /* Destructor. */
214
215 ~target_waitstatus ()
216 {
217 this->reset ();
218 }
219
220 /* Setters: set the wait status kind plus any associated data. */
221
222 target_waitstatus &set_exited (int exit_status)
223 {
224 this->reset ();
225 m_kind = TARGET_WAITKIND_EXITED;
226 m_value.exit_status = exit_status;
227 return *this;
228 }
229
230 target_waitstatus &set_stopped (gdb_signal sig)
231 {
232 this->reset ();
233 m_kind = TARGET_WAITKIND_STOPPED;
234 m_value.sig = sig;
235 return *this;
236 }
237
238 target_waitstatus &set_signalled (gdb_signal sig)
239 {
240 this->reset ();
241 m_kind = TARGET_WAITKIND_SIGNALLED;
242 m_value.sig = sig;
243 return *this;
244 }
245
246 target_waitstatus &set_loaded ()
247 {
248 this->reset ();
249 m_kind = TARGET_WAITKIND_LOADED;
250 return *this;
251 }
252
253 target_waitstatus &set_forked (ptid_t child_ptid)
254 {
255 this->reset ();
256 m_kind = TARGET_WAITKIND_FORKED;
257 m_value.child_ptid = child_ptid;
258 return *this;
259 }
260
261 target_waitstatus &set_vforked (ptid_t child_ptid)
262 {
263 this->reset ();
264 m_kind = TARGET_WAITKIND_VFORKED;
265 m_value.child_ptid = child_ptid;
266 return *this;
267 }
268
269 target_waitstatus &set_execd (gdb::unique_xmalloc_ptr<char> execd_pathname)
270 {
271 this->reset ();
272 m_kind = TARGET_WAITKIND_EXECD;
273 m_value.execd_pathname = execd_pathname.release ();
274 return *this;
275 }
276
277 target_waitstatus &set_vfork_done ()
278 {
279 this->reset ();
280 m_kind = TARGET_WAITKIND_VFORK_DONE;
281 return *this;
282 }
283
284 target_waitstatus &set_syscall_entry (int syscall_number)
285 {
286 this->reset ();
287 m_kind = TARGET_WAITKIND_SYSCALL_ENTRY;
288 m_value.syscall_number = syscall_number;
289 return *this;
290 }
291
292 target_waitstatus &set_syscall_return (int syscall_number)
293 {
294 this->reset ();
295 m_kind = TARGET_WAITKIND_SYSCALL_RETURN;
296 m_value.syscall_number = syscall_number;
297 return *this;
298 }
299
300 target_waitstatus &set_spurious ()
301 {
302 this->reset ();
303 m_kind = TARGET_WAITKIND_SPURIOUS;
304 return *this;
305 }
306
307 target_waitstatus &set_ignore ()
308 {
309 this->reset ();
310 m_kind = TARGET_WAITKIND_IGNORE;
311 return *this;
312 }
313
314 target_waitstatus &set_no_history ()
315 {
316 this->reset ();
317 m_kind = TARGET_WAITKIND_NO_HISTORY;
318 return *this;
319 }
320
321 target_waitstatus &set_no_resumed ()
322 {
323 this->reset ();
324 m_kind = TARGET_WAITKIND_NO_RESUMED;
325 return *this;
326 }
327
328 target_waitstatus &set_thread_created ()
329 {
330 this->reset ();
331 m_kind = TARGET_WAITKIND_THREAD_CREATED;
332 return *this;
333 }
334
335 target_waitstatus &set_thread_exited (int exit_status)
336 {
337 this->reset ();
338 m_kind = TARGET_WAITKIND_THREAD_EXITED;
339 m_value.exit_status = exit_status;
340 return *this;
341 }
342
343 /* Get the kind of this wait status. */
344
345 target_waitkind kind () const
346 {
347 return m_kind;
348 }
349
350 /* Getters for the associated data.
351
352 Getters can only be used if the wait status is of the appropriate kind.
353 See the setters above or the assertions below to know which data is
354 associated to which kind. */
355
356 int exit_status () const
357 {
358 gdb_assert (m_kind == TARGET_WAITKIND_EXITED
359 || m_kind == TARGET_WAITKIND_THREAD_EXITED);
360 return m_value.exit_status;
361 }
362
363 gdb_signal sig () const
364 {
365 gdb_assert (m_kind == TARGET_WAITKIND_STOPPED
366 || m_kind == TARGET_WAITKIND_SIGNALLED);
367 return m_value.sig;
368 }
369
370 ptid_t child_ptid () const
371 {
372 gdb_assert (m_kind == TARGET_WAITKIND_FORKED
373 || m_kind == TARGET_WAITKIND_VFORKED);
374 return m_value.child_ptid;
375 }
376
377 const char *execd_pathname () const
378 {
379 gdb_assert (m_kind == TARGET_WAITKIND_EXECD);
380 return m_value.execd_pathname;
381 }
382
383 int syscall_number () const
384 {
385 gdb_assert (m_kind == TARGET_WAITKIND_SYSCALL_ENTRY
386 || m_kind == TARGET_WAITKIND_SYSCALL_RETURN);
387 return m_value.syscall_number;
388 }
389
390 /* Return a pretty printed form of target_waitstatus.
391
392 This is only meant to be used in debug messages, not for user-visible
393 messages. */
394 std::string to_string () const;
395
396 private:
397 /* Reset the wait status to its original state. */
398 void reset ()
399 {
400 if (m_kind == TARGET_WAITKIND_EXECD)
401 xfree (m_value.execd_pathname);
402
403 m_kind = TARGET_WAITKIND_IGNORE;
404 }
405
406 target_waitkind m_kind = TARGET_WAITKIND_IGNORE;
407
408 /* Additional information about the event. */
409 union
410 {
411 /* Exit status */
412 int exit_status;
413 /* Signal number */
414 enum gdb_signal sig;
415 /* Forked child pid */
416 ptid_t child_ptid;
417 /* execd pathname */
418 char *execd_pathname;
419 /* Syscall number */
420 int syscall_number;
421 } m_value {};
422 };
423
424 /* Extended reasons that can explain why a target/thread stopped for a
425 trap signal. */
426
427 enum target_stop_reason
428 {
429 /* Either not stopped, or stopped for a reason that doesn't require
430 special tracking. */
431 TARGET_STOPPED_BY_NO_REASON,
432
433 /* Stopped by a software breakpoint. */
434 TARGET_STOPPED_BY_SW_BREAKPOINT,
435
436 /* Stopped by a hardware breakpoint. */
437 TARGET_STOPPED_BY_HW_BREAKPOINT,
438
439 /* Stopped by a watchpoint. */
440 TARGET_STOPPED_BY_WATCHPOINT,
441
442 /* Stopped by a single step finishing. */
443 TARGET_STOPPED_BY_SINGLE_STEP
444 };
445
446 #endif /* TARGET_WAITSTATUS_H */