]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
[gdb] Handle bad alloc in gdb_rl_callback_read_char_wrapper_noexcept
authorTom de Vries <tdevries@suse.de>
Fri, 25 Oct 2024 10:48:18 +0000 (12:48 +0200)
committerTom de Vries <tdevries@suse.de>
Fri, 25 Oct 2024 10:48:18 +0000 (12:48 +0200)
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.

gdb/event-top.c

index cdc7874b7fad8435d10eb553e74ef410d8642979..d3cf144958a8ca867dc5e22eb030800cf5443a2a 100644 (file)
@@ -184,7 +184,7 @@ extern "C" void _rl_signal_handler (int);
    (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;
 
@@ -229,6 +229,22 @@ gdb_rl_callback_read_char_wrapper_noexcept () noexcept
   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)
 {