Say we simulate a bad alloc in exceptions_state_mc_init:
...
jmp_buf *
exceptions_state_mc_init ()
{
+ {
+ static bool throw_bad_alloc = true;
+ if (throw_bad_alloc)
+ {
+ throw_bad_alloc = false;
+
+ va_list dummy;
+ throw gdb_quit_bad_alloc (gdb_exception_quit ("bad alloc", dummy));
+ }
+ }
catchers.emplace_front ();
return &catchers.front ().buf;
}
...
After starting gdb and typing "q", gdb terminates:
...
$ gdb -q
(gdb) terminate called after throwing an instance of 'gdb_quit_bad_alloc'
what(): std::bad_alloc
...
because the bad alloc (thrown in TRY_SJLJ) is caught by the noexcept on
gdb_rl_callback_read_char_wrapper_noexcept:
...
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
...
Fix this by renaming gdb_rl_callback_read_char_wrapper_noexcept to
gdb_rl_callback_read_char_wrapper_sjlj and calling it from a wrapper function
that catches the bad alloc expection:
...
static struct gdb_exception
gdb_rl_callback_read_char_wrapper_noexcept () noexcept
{
try
{
return gdb_rl_callback_read_char_wrapper_sjlj ();
}
catch (gdb_exception &ex)
{
return std::move (ex);
}
}
...
getting us instead:
...
$ gdb -q
(gdb) bad alloc
(gdb) q
...
Tested on aarch64-linux.
(sjlj-based) C++ exceptions. */
static struct gdb_exception
-gdb_rl_callback_read_char_wrapper_noexcept () noexcept
+gdb_rl_callback_read_char_wrapper_sjlj ()
{
struct gdb_exception gdb_expt;
return gdb_expt;
}
+/* Wrapper around gdb_rl_callback_read_char_wrapper_sjlj to ensure
+ noexcept. */
+
+static struct gdb_exception
+gdb_rl_callback_read_char_wrapper_noexcept () noexcept
+{
+ try
+ {
+ return gdb_rl_callback_read_char_wrapper_sjlj ();
+ }
+ catch (gdb_exception &ex)
+ {
+ return std::move (ex);
+ }
+}
+
static void
gdb_rl_callback_read_char_wrapper (gdb_client_data client_data)
{