]> Git Repo - binutils.git/blob - gdb/target/waitstatus.h
Automatic date update in version.in
[binutils.git] / gdb / target / waitstatus.h
1 /* Target waitstatus definitions and prototypes.
2
3    Copyright (C) 1990-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 #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 occured, 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 */
This page took 0.047087 seconds and 4 git commands to generate.