gdb: Don't skip prologue for explicit line breakpoints in assembler
[deliverable/binutils-gdb.git] / gdb / common / common-exceptions.h
index c4a2f59f9041a993cc6fc18295b5ca789f6af805..ebcaf031354336ae733fe6cc0f28228fa386e3db 100644 (file)
@@ -1,6 +1,6 @@
 /* Exception (throw catch) mechanism, for GDB, the GNU debugger.
 
-   Copyright (C) 1986-2017 Free Software Foundation, Inc.
+   Copyright (C) 1986-2019 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
-#ifndef COMMON_EXCEPTIONS_H
-#define COMMON_EXCEPTIONS_H
+#ifndef COMMON_COMMON_EXCEPTIONS_H
+#define COMMON_COMMON_EXCEPTIONS_H
 
 #include <setjmp.h>
 #include <new>
+#include <memory>
+#include <string>
 
 /* Reasons for calling throw_exceptions().  NOTE: all reason values
-   must be less than zero.  enum value 0 is reserved for internal use
-   as the return value from an initial setjmp().  The function
-   catch_exceptions() reserves values >= 0 as legal results from its
-   wrapped function.  */
+   must be different from zero.  enum value 0 is reserved for internal
+   use as the return value from an initial setjmp().  */
 
 enum return_reason
   {
@@ -87,7 +87,7 @@ enum errors {
      means the register was not saved in the frame.  */
   OPTIMIZED_OUT_ERROR,
 
-  /* DW_OP_GNU_entry_value resolving failed.  */
+  /* DW_OP_entry_value resolving failed.  */
   NO_ENTRY_VALUE_ERROR,
 
   /* Target throwing an error has been closed.  Current command should be
@@ -112,26 +112,63 @@ enum errors {
 
 struct gdb_exception
 {
-  enum return_reason reason;
-  enum errors error;
-  const char *message;
-};
+  gdb_exception ()
+    : reason ((enum return_reason) 0),
+      error (GDB_NO_ERROR)
+  {
+  }
+
+  gdb_exception (enum return_reason r, enum errors e)
+    : reason (r),
+      error (e)
+  {
+  }
 
-/* The different exception mechanisms that TRY/CATCH can map to.  */
+  gdb_exception (enum return_reason r, enum errors e,
+                const char *fmt, va_list ap)
+    ATTRIBUTE_PRINTF (4, 0)
+    : reason (r),
+      error (e),
+      message (std::make_shared<std::string> (string_vprintf (fmt, ap)))
+  {
+  }
 
-/* Make GDB exceptions use setjmp/longjmp behind the scenes.  */
-#define GDB_XCPT_SJMP 1
+  /* The move constructor exists so that we can mark it "noexcept",
+     which is a good practice for any sort of exception object.  */
+  explicit gdb_exception (gdb_exception &&other) noexcept = default;
 
-/* Make GDB exceptions use try/catch behind the scenes.  */
-#define GDB_XCPT_TRY 2
+  /* The copy constructor exists so that we can mark it "noexcept",
+     which is a good practice for any sort of exception object.  */
+  gdb_exception (const gdb_exception &other) noexcept
+    : reason (other.reason),
+      error (other.error),
+      message (other.message)
+  {
+  }
 
-/* Specify this mode to build with TRY/CATCH mapped directly to raw
-   try/catch.  GDB won't work correctly, but building that way catches
-   code tryin to break/continue out of the try block, along with
-   spurious code between the TRY and the CATCH block.  */
-#define GDB_XCPT_RAW_TRY 3
+  /* The assignment operator exists so that we can mark it "noexcept",
+     which is a good practice for any sort of exception object.  */
+  gdb_exception &operator= (const gdb_exception &other) noexcept
+  {
+    reason = other.reason;
+    error = other.error;
+    message = other.message;
+    return *this;
+  }
 
-#define GDB_XCPT GDB_XCPT_TRY
+  gdb_exception &operator= (gdb_exception &&other) noexcept = default;
+
+  /* Return the contents of the exception message, as a C string.  The
+     string remains owned by the exception object.  */
+  const char *what () const noexcept
+  {
+    return message->c_str ();
+  }
+
+  enum return_reason reason;
+  enum errors error;
+  std::shared_ptr<std::string> message;
+};
 
 /* Functions to drive the sjlj-based exceptions state machine.  Though
    declared here by necessity, these functions should be considered
@@ -143,14 +180,6 @@ 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);
 
-/* 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.
 
    The double loop lets us correctly handle code "break"ing out of the
@@ -162,24 +191,21 @@ extern void exception_rethrow (void);
 
    *INDENT-OFF*
 
-   TRY
+   TRY_SJLJ
      {
      }
-   CATCH (e, RETURN_MASK_ERROR)
+   CATCH_SJLJ (e, RETURN_MASK_ERROR)
      {
        switch (e.reason)
          {
            case RETURN_ERROR: ...
          }
      }
-   END_CATCH
+   END_CATCH_SJLJ
 
-  Note that the SJLJ version of the macros are actually named
-  TRY_SJLJ/CATCH_SJLJ in order to make it possible to call them even
-  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).  */
+   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).  */
 
 #define TRY_SJLJ \
      { \
@@ -198,87 +224,40 @@ extern void exception_rethrow (void);
 #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
+/* 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.  */
 
-/* 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.  */
-struct exception_try_scope
+struct gdb_exception_error : public gdb_exception
 {
-  exception_try_scope ()
+  gdb_exception_error (enum errors e, const char *fmt, va_list ap)
+    ATTRIBUTE_PRINTF (3, 0)
+    : gdb_exception (RETURN_ERROR, e, fmt, ap)
   {
-    saved_state = exception_try_scope_entry ();
   }
-  ~exception_try_scope ()
-  {
-    exception_try_scope_exit (saved_state);
-  }
-
-  void *saved_state;
-};
 
-#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.  */
-#define TRY                                                            \
-  try                                                                  \
-    {                                                                  \
-      exception_try_scope exception_try_scope_instance;                        \
-      do                                                               \
-       {
-
-#define CATCH(EXCEPTION, MASK)                                         \
-       } while (0);                                                    \
-    }                                                                  \
-  catch (struct gdb_exception ## _ ## MASK &EXCEPTION)
-
-#define END_CATCH                              \
-  catch (...)                                  \
-  {                                            \
-    exception_rethrow ();                      \
+  explicit gdb_exception_error (gdb_exception &&ex) noexcept
+    : gdb_exception (std::move (ex))
+  {
+    gdb_assert (ex.reason == RETURN_ERROR);
   }
-
-#else
-
-#define TRY try
-#define CATCH(EXCEPTION, MASK) \
-  catch (struct gdb_exception ## _ ## MASK &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.  */
-
-struct gdb_exception_RETURN_MASK_ALL : public gdb_exception
-{
 };
 
-struct gdb_exception_RETURN_MASK_ERROR : public gdb_exception_RETURN_MASK_ALL
+struct gdb_exception_quit : public gdb_exception
 {
-};
+  gdb_exception_quit (const char *fmt, va_list ap)
+    ATTRIBUTE_PRINTF (2, 0)
+    : gdb_exception (RETURN_QUIT, GDB_NO_ERROR, fmt, ap)
+  {
+  }
 
-struct gdb_exception_RETURN_MASK_QUIT : public gdb_exception_RETURN_MASK_ALL
-{
+  explicit gdb_exception_quit (gdb_exception &&ex) noexcept
+    : gdb_exception (std::move (ex))
+  {
+    gdb_assert (ex.reason == RETURN_QUIT);
+  }
 };
 
-#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
@@ -286,15 +265,13 @@ 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_exception_quit,
     public std::bad_alloc
 {
-  explicit gdb_quit_bad_alloc (gdb_exception ex)
-    : std::bad_alloc ()
+  explicit gdb_quit_bad_alloc (gdb_exception &&ex) noexcept
+    : gdb_exception_quit (std::move (ex)),
+      std::bad_alloc ()
   {
-    gdb_exception *self = this;
-
-    *self = ex;
   }
 };
 
@@ -303,14 +280,14 @@ struct gdb_quit_bad_alloc
 /* Throw an exception (as described by "struct gdb_exception"),
    landing in the inner most containing exception handler established
    using TRY/CATCH.  */
-extern void throw_exception (struct gdb_exception exception)
+extern void throw_exception (gdb_exception &&exception)
      ATTRIBUTE_NORETURN;
 
 /* Throw an exception by executing a LONG JUMP to the inner most
    containing exception handler established using TRY_SJLJ.  Necessary
    in some cases where we need to throw GDB exceptions across
    third-party library code (e.g., readline).  */
-extern void throw_exception_sjlj (struct gdb_exception exception)
+extern void throw_exception_sjlj (const struct gdb_exception &exception)
      ATTRIBUTE_NORETURN;
 
 /* Convenience wrappers around throw_exception that throw GDB
@@ -324,7 +301,4 @@ extern void throw_error (enum errors error, const char *fmt, ...)
 extern void throw_quit (const char *fmt, ...)
      ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (1, 2);
 
-/* A pre-defined non-exception.  */
-extern const struct gdb_exception exception_none;
-
-#endif /* COMMON_EXCEPTIONS_H */
+#endif /* COMMON_COMMON_EXCEPTIONS_H */
This page took 0.027904 seconds and 4 git commands to generate.