GDB (xrefs)
common-exceptions.h
Go to the documentation of this file.
1 /* Exception (throw catch) mechanism, for GDB, the GNU debugger.
2 
3  Copyright (C) 1986-2018 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 COMMON_EXCEPTIONS_H
21 #define COMMON_EXCEPTIONS_H
22 
23 #include <setjmp.h>
24 #include <new>
25 
26 /* Reasons for calling throw_exceptions(). NOTE: all reason values
27  must be different from zero. enum value 0 is reserved for internal
28  use as the return value from an initial setjmp(). */
29 
31  {
32  /* User interrupt. */
34  /* Any other error. */
36  };
37 
38 #define RETURN_MASK(reason) (1 << (int)(-reason))
39 
40 typedef enum
41 {
45 } return_mask;
46 
47 /* Describe all exceptions. */
48 
49 enum errors {
51 
52  /* Any generic error, the corresponding text is in
53  exception.message. */
55 
56  /* Something requested was not found. */
58 
59  /* Thread library lacks support necessary for finding thread local
60  storage. */
62 
63  /* Load module not found while attempting to find thread local storage. */
65 
66  /* Thread local storage has not been allocated yet. */
68 
69  /* Something else went wrong while attempting to find thread local
70  storage. The ``struct gdb_exception'' message field provides
71  more detail. */
73 
74  /* Problem parsing an XML document. */
76 
77  /* Error accessing memory. */
79 
80  /* Value not available. E.g., a register was not collected in a
81  traceframe. */
83 
84  /* Value was optimized out. Note: if the value was a register, this
85  means the register was not saved in the frame. */
87 
88  /* DW_OP_entry_value resolving failed. */
90 
91  /* Target throwing an error has been closed. Current command should be
92  aborted as the inferior state is no longer valid. */
94 
95  /* An undefined command was executed. */
97 
98  /* Requested feature, method, mechanism, etc. is not supported. */
100 
101  /* The number of candidates generated during line completion has
102  reached the user's specified limit. This isn't an error, this exception
103  is used to halt searching for more completions, but for consistency
104  "_ERROR" is appended to the name. */
106 
107  /* Add more errors here. */
109 };
110 
112 {
114  enum errors error;
115  const char *message;
116 };
117 
118 /* The different exception mechanisms that TRY/CATCH can map to. */
119 
120 /* Make GDB exceptions use setjmp/longjmp behind the scenes. */
121 #define GDB_XCPT_SJMP 1
122 
123 /* Make GDB exceptions use try/catch behind the scenes. */
124 #define GDB_XCPT_TRY 2
125 
126 /* Specify this mode to build with TRY/CATCH mapped directly to raw
127  try/catch. GDB won't work correctly, but building that way catches
128  code tryin to break/continue out of the try block, along with
129  spurious code between the TRY and the CATCH block. */
130 #define GDB_XCPT_RAW_TRY 3
131 
132 #define GDB_XCPT GDB_XCPT_TRY
133 
134 /* Functions to drive the sjlj-based exceptions state machine. Though
135  declared here by necessity, these functions should be considered
136  internal to the exceptions subsystem and not used other than via
137  the TRY/CATCH (or TRY_SJLJ/CATCH_SJLJ) macros defined below. */
138 
139 extern jmp_buf *exceptions_state_mc_init (void);
140 extern int exceptions_state_mc_action_iter (void);
141 extern int exceptions_state_mc_action_iter_1 (void);
142 extern int exceptions_state_mc_catch (struct gdb_exception *, int);
143 
144 /* Same, but for the C++ try/catch-based TRY/CATCH mechanism. */
145 
146 #if GDB_XCPT != GDB_XCPT_SJMP
147 extern void *exception_try_scope_entry (void);
148 extern void exception_try_scope_exit (void *saved_state);
149 extern void exception_rethrow (void);
150 #endif
151 
152 /* Macro to wrap up standard try/catch behavior.
153 
154  The double loop lets us correctly handle code "break"ing out of the
155  try catch block. (It works as the "break" only exits the inner
156  "while" loop, the outer for loop detects this handling it
157  correctly.) Of course "return" and "goto" are not so lucky.
158 
159  For instance:
160 
161  *INDENT-OFF*
162 
163  TRY
164  {
165  }
166  CATCH (e, RETURN_MASK_ERROR)
167  {
168  switch (e.reason)
169  {
170  case RETURN_ERROR: ...
171  }
172  }
173  END_CATCH
174 
175  Note that the SJLJ version of the macros are actually named
176  TRY_SJLJ/CATCH_SJLJ in order to make it possible to call them even
177  when TRY/CATCH are mapped to C++ try/catch. The SJLJ variants are
178  needed in some cases where gdb exceptions need to cross third-party
179  library code compiled without exceptions support (e.g.,
180  readline). */
181 
182 #define TRY_SJLJ \
183  { \
184  jmp_buf *buf = \
185  exceptions_state_mc_init (); \
186  setjmp (*buf); \
187  } \
188  while (exceptions_state_mc_action_iter ()) \
189  while (exceptions_state_mc_action_iter_1 ())
190 
191 #define CATCH_SJLJ(EXCEPTION, MASK) \
192  { \
193  struct gdb_exception EXCEPTION; \
194  if (exceptions_state_mc_catch (&(EXCEPTION), MASK))
195 
196 #define END_CATCH_SJLJ \
197  }
198 
199 #if GDB_XCPT == GDB_XCPT_SJMP
200 
201 /* If using SJLJ-based exceptions for all exceptions, then provide
202  standard aliases. */
203 
204 #define TRY TRY_SJLJ
205 #define CATCH CATCH_SJLJ
206 #define END_CATCH END_CATCH_SJLJ
207 
208 #endif /* GDB_XCPT_SJMP */
209 
210 #if GDB_XCPT == GDB_XCPT_TRY || GDB_XCPT == GDB_XCPT_RAW_TRY
211 
212 /* Prevent error/quit during TRY from calling cleanups established
213  prior to here. This pops out the scope in either case of normal
214  exit or exception exit. */
216 {
218  {
220  }
222  {
224  }
225 
226  void *saved_state;
227 };
228 
229 #if GDB_XCPT == GDB_XCPT_TRY
230 
231 /* We still need to wrap TRY/CATCH in C++ so that cleanups and C++
232  exceptions can coexist.
233 
234  The TRY blocked is wrapped in a do/while(0) so that break/continue
235  within the block works the same as in C.
236 
237  END_CATCH makes sure that even if the CATCH block doesn't want to
238  catch the exception, we stop at every frame in the unwind chain to
239  run its cleanups, which may e.g., have pointers to stack variables
240  that are going to be destroyed.
241 
242  There's an outer scope around the whole TRY/END_CATCH in order to
243  cause a compilation error if you forget to add the END_CATCH at the
244  end a TRY/CATCH construct. */
245 
246 #define TRY \
247  { \
248  try \
249  { \
250  exception_try_scope exception_try_scope_instance; \
251  do \
252  {
253 
254 #define CATCH(EXCEPTION, MASK) \
255  } while (0); \
256  } \
257  catch (struct gdb_exception ## _ ## MASK &EXCEPTION)
258 
259 #define END_CATCH \
260  catch (...) \
261  { \
262  exception_rethrow (); \
263  } \
264  }
265 
266 #else
267 
268 #define TRY try
269 #define CATCH(EXCEPTION, MASK) \
270  catch (struct gdb_exception ## _ ## MASK &EXCEPTION)
271 #define END_CATCH
272 
273 #endif
274 
275 /* The exception types client code may catch. They're just shims
276  around gdb_exception that add nothing but type info. Which is used
277  is selected depending on the MASK argument passed to CATCH. */
278 
280 {
281 };
282 
284 {
285 };
286 
288 {
289 };
290 
291 #endif /* GDB_XCPT_TRY || GDB_XCPT_RAW_TRY */
292 
293 /* An exception type that inherits from both std::bad_alloc and a gdb
294  exception. This is necessary because operator new can only throw
295  std::bad_alloc, and OTOH, we want exceptions thrown due to memory
296  allocation error to be caught by all the CATCH/RETURN_MASK_ALL
297  spread around the codebase. */
298 
301  public std::bad_alloc
302 {
304  : std::bad_alloc ()
305  {
306  gdb_exception *self = this;
307 
308  *self = ex;
309  }
310 };
311 
312 /* *INDENT-ON* */
313 
314 /* Throw an exception (as described by "struct gdb_exception"),
315  landing in the inner most containing exception handler established
316  using TRY/CATCH. */
317 extern void throw_exception (struct gdb_exception exception)
318  ATTRIBUTE_NORETURN;
319 
320 /* Throw an exception by executing a LONG JUMP to the inner most
321  containing exception handler established using TRY_SJLJ. Necessary
322  in some cases where we need to throw GDB exceptions across
323  third-party library code (e.g., readline). */
324 extern void throw_exception_sjlj (struct gdb_exception exception)
325  ATTRIBUTE_NORETURN;
326 
327 /* Convenience wrappers around throw_exception that throw GDB
328  errors. */
329 extern void throw_verror (enum errors, const char *fmt, va_list ap)
330  ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (2, 0);
331 extern void throw_vquit (const char *fmt, va_list ap)
332  ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (1, 0);
333 extern void throw_error (enum errors error, const char *fmt, ...)
334  ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (2, 3);
335 extern void throw_quit (const char *fmt, ...)
336  ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (1, 2);
337 
338 /* A pre-defined non-exception. */
339 extern const struct gdb_exception exception_none;
340 
341 #endif /* COMMON_EXCEPTIONS_H */
int exceptions_state_mc_catch(struct gdb_exception *, int)
return_reason
void void void void const struct gdb_exception exception_none
#define RETURN_MASK(reason)
enum errors error
void exception_try_scope_exit(void *saved_state)
void void void void throw_quit(const char *fmt,...) ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF(1
void throw_exception_sjlj(struct gdb_exception exception) ATTRIBUTE_NORETURN
void void throw_vquit(const char *fmt, va_list ap) ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF(1
gdb_quit_bad_alloc(gdb_exception ex)
#define ATTRIBUTE_PRINTF
Definition: common-defs.h:70
void throw_exception(struct gdb_exception exception) ATTRIBUTE_NORETURN
return_mask
int exceptions_state_mc_action_iter(void)
jmp_buf * exceptions_state_mc_init(void)
void exception_rethrow(void)
void throw_verror(enum errors, const char *fmt, va_list ap) ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF(2
void void void throw_error(enum errors error, const char *fmt,...) ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF(2
int exceptions_state_mc_action_iter_1(void)
const char * message
void * exception_try_scope_entry(void)
void error(const char *fmt,...)
Definition: errors.c:38
enum return_reason reason