+/* Wrapper function for calling into the readline library. This takes
+ care of a couple things:
+
+ - The event loop expects the callback function to have a parameter,
+ while readline expects none.
+
+ - Propagation of GDB exceptions/errors thrown from INPUT_HANDLER
+ across readline requires special handling.
+
+ On the exceptions issue:
+
+ DWARF-based unwinding cannot cross code built without -fexceptions.
+ Any exception that tries to propagate through such code will fail
+ and the result is a call to std::terminate. While some ABIs, such
+ as x86-64, require all code to be built with exception tables,
+ others don't.
+
+ This is a problem when GDB calls some non-EH-aware C library code,
+ that calls into GDB again through a callback, and that GDB callback
+ code throws a C++ exception. Turns out this is exactly what
+ happens with GDB's readline callback.
+
+ In such cases, we must catch and save any C++ exception that might
+ be thrown from the GDB callback before returning to the
+ non-EH-aware code. When the non-EH-aware function itself returns
+ back to GDB, we then rethrow the original C++ exception.
+
+ In the readline case however, the right thing to do is to longjmp
+ out of the callback, rather than do a normal return -- there's no
+ way for the callback to return to readline an indication that an
+ error happened, so a normal return would have rl_callback_read_char
+ potentially continue processing further input, redisplay the
+ prompt, etc. Instead of raw setjmp/longjmp however, we use our
+ sjlj-based TRY/CATCH mechanism, which knows to handle multiple
+ levels of active setjmp/longjmp frames, needed in order to handle
+ the readline callback recursing, as happens with e.g., secondary
+ prompts / queries, through gdb_readline_wrapper. This must be
+ noexcept in order to avoid problems with mixing sjlj and
+ (sjlj-based) C++ exceptions. */
+
+static struct gdb_exception
+gdb_rl_callback_read_char_wrapper_noexcept () noexcept
+{
+ struct gdb_exception gdb_expt;
+
+ /* 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
+ TRY/CATCH, and rethrow the GDB exception once back in GDB. */
+ TRY_SJLJ
+ {
+ rl_callback_read_char ();
+ if (after_char_processing_hook)
+ (*after_char_processing_hook) ();
+ }
+ CATCH_SJLJ (ex, RETURN_MASK_ALL)
+ {
+ gdb_expt = std::move (ex);
+ }
+ END_CATCH_SJLJ
+
+ return gdb_expt;
+}
+