From: Tom de Vries Date: Fri, 25 Oct 2024 10:48:18 +0000 (+0200) Subject: [gdb] Handle bad alloc in gdb_rl_callback_read_char_wrapper_noexcept X-Git-Tag: gdb-16-branchpoint~596 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3d17c8817216343179f64d1a682311a70774ccb4;p=thirdparty%2Fbinutils-gdb.git [gdb] Handle bad alloc in gdb_rl_callback_read_char_wrapper_noexcept 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. --- diff --git a/gdb/event-top.c b/gdb/event-top.c index cdc7874b7fa..d3cf144958a 100644 --- a/gdb/event-top.c +++ b/gdb/event-top.c @@ -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) {