summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2016-09-21 16:31:30 +0100
committerPedro Alves <palves@redhat.com>2016-09-23 17:34:28 +0100
commit3ec66096627bb23fcbca943b1788456bd61092d9 (patch)
tree390439780ca7248fb256bd7ddcdc6d0ca0ca25f5
parent97e64e5ab19dbf6a9babd711e8deec5545520954 (diff)
downloadbinutils-gdb-3ec66096627bb23fcbca943b1788456bd61092d9.tar.gz
CATCH(e, RETURN_MASK_ERROR) -> CATCH(const gdb_error &e): core bits
This changes GDB's TRY/CATCH macros in a way that allowing changing the CATCH sites to look a lot more like normal C++ catch blocks. I.e., do: - CATCH (e, RETURN_MASK_ERROR) + CATCH (const gdb_error &e) And: - CATCH (ex, RETURN_MASK_ALL) + CATCH (const gdb_exception &ex) Note this simplifies the TRY_SJLJ/CATCH_SJLJ implementation, by no longer supporting filter masks. The places where we need this will always want to catch all exceptions, so nothing is missed. Since the exception types used to filter errors vs QUITs are exposed to current code, and, we no longer need to play macro tricks, we rename them to something more sensible: -struct gdb_exception_RETURN_MASK_ERROR : public gdb_exception_RETURN_MASK_ALL +struct gdb_error : public gdb_exception -struct gdb_exception_RETURN_MASK_QUIT : public gdb_exception_RETURN_MASK_ALL +struct gdb_quit : public gdb_exception and "struct gdb_exception_RETURN_MASK_ALL" is gone. The logic is now: - Code that wants to catch Ctrl-C as well as gdb errors can can simply catch gdb_exception, the root exception type. - Code that wants to only intercept errors while ignoring Ctrl-C catches gdb_error instead. Adding more exception types that inherit gdb_error so that catching code wouldn't have to rethrow if it catches a gdb_error of the "wrong" error type would be possible, though not done here. The next patch adjusts the whole codebase to use the new CATCH form.
-rw-r--r--gdb/common/common-exceptions.c76
-rw-r--r--gdb/common/common-exceptions.h86
-rw-r--r--gdb/event-top.c11
3 files changed, 41 insertions, 132 deletions
diff --git a/gdb/common/common-exceptions.c b/gdb/common/common-exceptions.c
index 33fff21609b..4ceca45628a 100644
--- a/gdb/common/common-exceptions.c
+++ b/gdb/common/common-exceptions.c
@@ -55,26 +55,6 @@ struct catcher
/* Where to go for throw_exception(). */
static struct catcher *current_catcher;
-#if GDB_XCPT == GDB_XCPT_SJMP
-
-/* Return length of current_catcher list. */
-
-static int
-catcher_list_size (void)
-{
- int size;
- struct catcher *catcher;
-
- for (size = 0, catcher = current_catcher;
- catcher != NULL;
- catcher = catcher->prev)
- ++size;
-
- return size;
-}
-
-#endif
-
jmp_buf *
exceptions_state_mc_init (void)
{
@@ -178,29 +158,13 @@ exceptions_state_mc (enum catcher_action action)
}
}
-int
-exceptions_state_mc_catch (struct gdb_exception *exception,
- int mask)
+struct gdb_exception
+exceptions_state_mc_catch ()
{
- *exception = current_catcher->exception;
- catcher_pop ();
+ struct gdb_exception res = current_catcher->exception;
- if (exception->reason < 0)
- {
- if (mask & RETURN_MASK (exception->reason))
- {
- /* Exit normally and let the caller handle the
- exception. */
- return 1;
- }
-
- /* The caller didn't request that the event be caught, relay the
- event to the next exception_catch/CATCH_SJLJ. */
- throw_exception_sjlj (*exception);
- }
-
- /* No exception was thrown. */
- return 0;
+ catcher_pop ();
+ return res;
}
int
@@ -215,8 +179,6 @@ exceptions_state_mc_action_iter_1 (void)
return exceptions_state_mc (CATCH_ITER_1);
}
-#if GDB_XCPT != GDB_XCPT_SJMP
-
/* How many nested TRY blocks we have. See exception_messages and
throw_it. */
@@ -262,8 +224,6 @@ gdb_exception_sliced_copy (struct gdb_exception *to, const struct gdb_exception
*to = *from;
}
-#endif /* !GDB_XCPT_SJMP */
-
/* Return EXCEPTION to the nearest containing catch_errors(). */
void
@@ -279,25 +239,23 @@ throw_exception_sjlj (struct gdb_exception exception)
longjmp (current_catcher->buf, exception.reason);
}
-#if GDB_XCPT != GDB_XCPT_SJMP
-
/* Implementation of throw_exception that uses C++ try/catch. */
-static ATTRIBUTE_NORETURN void
-throw_exception_cxx (struct gdb_exception exception)
+ATTRIBUTE_NORETURN void
+throw_exception (struct gdb_exception exception)
{
do_cleanups (all_cleanups ());
if (exception.reason == RETURN_QUIT)
{
- gdb_exception_RETURN_MASK_QUIT ex;
+ gdb_quit ex;
gdb_exception_sliced_copy (&ex, &exception);
throw ex;
}
else if (exception.reason == RETURN_ERROR)
{
- gdb_exception_RETURN_MASK_ERROR ex;
+ gdb_error ex;
gdb_exception_sliced_copy (&ex, &exception);
throw ex;
@@ -306,18 +264,6 @@ throw_exception_cxx (struct gdb_exception exception)
gdb_assert_not_reached ("invalid return reason");
}
-#endif
-
-void
-throw_exception (struct gdb_exception exception)
-{
-#if GDB_XCPT == GDB_XCPT_SJMP
- throw_exception_sjlj (exception);
-#else
- throw_exception_cxx (exception);
-#endif
-}
-
/* A stack of exception messages.
This is needed to handle nested calls to throw_it: we don't want to
xfree space for a message before it's used.
@@ -339,11 +285,7 @@ throw_it (enum return_reason reason, enum errors error, const char *fmt,
{
struct gdb_exception e;
char *new_message;
-#if GDB_XCPT == GDB_XCPT_SJMP
- int depth = catcher_list_size ();
-#else
int depth = try_scope_depth;
-#endif
gdb_assert (depth > 0);
diff --git a/gdb/common/common-exceptions.h b/gdb/common/common-exceptions.h
index 6bf7e400ada..69a2b16f453 100644
--- a/gdb/common/common-exceptions.h
+++ b/gdb/common/common-exceptions.h
@@ -119,10 +119,6 @@ struct gdb_exception
/* The different exception mechanisms that TRY/CATCH can map to. */
-/* Make GDB exceptions use setjmp/longjmp behind the scenes. This is
- the only mode supported when GDB is built as a C program. */
-#define GDB_XCPT_SJMP 1
-
/* Make GDB exceptions use try/catch behind the scenes. */
#define GDB_XCPT_TRY 2
@@ -132,11 +128,7 @@ struct gdb_exception
spurious code between the TRY and the CATCH block. */
#define GDB_XCPT_RAW_TRY 3
-#ifdef __cplusplus
-# define GDB_XCPT GDB_XCPT_TRY
-#else
-# define GDB_XCPT GDB_XCPT_SJMP
-#endif
+#define GDB_XCPT GDB_XCPT_TRY
/* Functions to drive the sjlj-based exceptions state machine. Though
declared here by necessity, these functions should be considered
@@ -146,15 +138,13 @@ struct gdb_exception
extern jmp_buf *exceptions_state_mc_init (void);
extern int exceptions_state_mc_action_iter (void);
extern int exceptions_state_mc_action_iter_1 (void);
-extern int exceptions_state_mc_catch (struct gdb_exception *, int);
+extern struct gdb_exception exceptions_state_mc_catch ();
/* Same, but for the C++ try/catch-based TRY/CATCH mechanism. */
-#if GDB_XCPT != GDB_XCPT_SJMP
extern void *exception_try_scope_entry (void);
extern void exception_try_scope_exit (void *saved_state);
extern void exception_rethrow (void);
-#endif
/* Macro to wrap up standard try/catch behavior.
@@ -184,7 +174,7 @@ extern void exception_rethrow (void);
when TRY/CATCH are mapped to C++ try/catch. The SJLJ variants are
needed in some cases where gdb exceptions need to cross third-party
library code compiled without exceptions support (e.g.,
- readline). */
+ readline). Also, the SJLJ versions don't support a mask */
#define TRY_SJLJ \
{ \
@@ -195,27 +185,21 @@ extern void exception_rethrow (void);
while (exceptions_state_mc_action_iter ()) \
while (exceptions_state_mc_action_iter_1 ())
-#define CATCH_SJLJ(EXCEPTION, MASK) \
- { \
- struct gdb_exception EXCEPTION; \
- if (exceptions_state_mc_catch (&(EXCEPTION), MASK))
+/* Note: we create a local named temporary object instead of assigning
+ EXCEPTION directly to the result of exceptions_state_mc_catch()
+ directly, in order to allow catching by non-const reference, just
+ like C++ try/catch. */
+#define CATCH_SJLJ(EXCEPTION) \
+ { \
+ gdb_exception sjlj_exception_object = exceptions_state_mc_catch (); \
+ if (sjlj_exception_object.reason < 0) \
+ { \
+ EXCEPTION = sjlj_exception_object;
#define END_CATCH_SJLJ \
+ } \
}
-#if GDB_XCPT == GDB_XCPT_SJMP
-
-/* If using SJLJ-based exceptions for all exceptions, then provide
- standard aliases. */
-
-#define TRY TRY_SJLJ
-#define CATCH CATCH_SJLJ
-#define END_CATCH END_CATCH_SJLJ
-
-#endif /* GDB_XCPT_SJMP */
-
-#if GDB_XCPT == GDB_XCPT_TRY || GDB_XCPT == GDB_XCPT_RAW_TRY
-
/* Prevent error/quit during TRY from calling cleanups established
prior to here. This pops out the scope in either case of normal
exit or exception exit. */
@@ -236,54 +220,42 @@ struct exception_try_scope
#if GDB_XCPT == GDB_XCPT_TRY
/* We still need to wrap TRY/CATCH in C++ so that cleanups and C++
- exceptions can coexist. The TRY blocked is wrapped in a
- do/while(0) so that break/continue within the block works the same
- as in C. */
+ exceptions can coexist. */
#define TRY \
try \
{ \
- exception_try_scope exception_try_scope_instance; \
- do \
- {
+ exception_try_scope exception_try_scope_instance;
-#define CATCH(EXCEPTION, MASK) \
- } while (0); \
+#define CATCH(EXCEPTION) \
} \
- catch (struct gdb_exception ## _ ## MASK &EXCEPTION)
+ catch (EXCEPTION)
-#define END_CATCH \
- catch (...) \
- { \
- exception_rethrow (); \
- }
+#define END_CATCH \
+ catch (...) \
+ { \
+ exception_rethrow (); \
+ }
#else
#define TRY try
-#define CATCH(EXCEPTION, MASK) \
- catch (struct gdb_exception ## _ ## MASK &EXCEPTION)
+#define CATCH(EXCEPTION) \
+ catch (EXCEPTION)
#define END_CATCH
#endif
/* The exception types client code may catch. They're just shims
- around gdb_exception that add nothing but type info. Which is used
- is selected depending on the MASK argument passed to CATCH. */
+ around gdb_exception that add nothing but type info. */
-struct gdb_exception_RETURN_MASK_ALL : public gdb_exception
+struct gdb_error : public gdb_exception
{
};
-struct gdb_exception_RETURN_MASK_ERROR : public gdb_exception_RETURN_MASK_ALL
+struct gdb_quit : public gdb_exception
{
};
-struct gdb_exception_RETURN_MASK_QUIT : public gdb_exception_RETURN_MASK_ALL
-{
-};
-
-#endif /* GDB_XCPT_TRY || GDB_XCPT_RAW_TRY */
-
/* An exception type that inherits from both std::bad_alloc and a gdb
exception. This is necessary because operator new can only throw
std::bad_alloc, and OTOH, we want exceptions thrown due to memory
@@ -291,7 +263,7 @@ struct gdb_exception_RETURN_MASK_QUIT : public gdb_exception_RETURN_MASK_ALL
spread around the codebase. */
struct gdb_quit_bad_alloc
- : public gdb_exception_RETURN_MASK_QUIT,
+ : public gdb_quit,
public std::bad_alloc
{
explicit gdb_quit_bad_alloc (gdb_exception ex)
diff --git a/gdb/event-top.c b/gdb/event-top.c
index 576eded22c2..e990f782340 100644
--- a/gdb/event-top.c
+++ b/gdb/event-top.c
@@ -162,8 +162,6 @@ void (*after_char_processing_hook) (void);
static void
gdb_rl_callback_read_char_wrapper (gdb_client_data client_data)
{
- struct gdb_exception gdb_expt = exception_none;
-
/* C++ exceptions can't normally be thrown across readline (unless
it is built with -fexceptions, but it won't by default on many
ABIs). So we instead wrap the readline call with a sjlj-based
@@ -174,15 +172,12 @@ gdb_rl_callback_read_char_wrapper (gdb_client_data client_data)
if (after_char_processing_hook)
(*after_char_processing_hook) ();
}
- CATCH_SJLJ (ex, RETURN_MASK_ALL)
+ CATCH_SJLJ (const gdb_exception &ex)
{
- gdb_expt = ex;
+ /* Rethrow using the normal EH mechanism. */
+ throw_exception (ex);
}
END_CATCH_SJLJ
-
- /* Rethrow using the normal EH mechanism. */
- if (gdb_expt.reason < 0)
- throw_exception (gdb_expt);
}
/* GDB's readline callback handler. Calls the current INPUT_HANDLER,