From 2693a26216c329bd7ec2aae7743409f572de4fa5 Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Tue, 20 Dec 2016 15:46:44 +0000 Subject: [PATCH] Fix longjmp across readline w/ --enable-sjlj-exceptions toolchains Nowadays, GDB propagates C++ exceptions across readline using setjmp/longjmp 89525768cd08 ("Propagate GDB/C++ exceptions across readline using sj/lj-based TRY/CATCH") because DWARF-based unwinding can't cross C functions compiled without -fexceptions (see details from the commit above). Unfortunately, toolchains that use SjLj-based C++ exceptions got broken with that fix, because _Unwind_SjLj_Unregister, which is put at the exit of a function, is not executed due to the longjmp added by that commit. (gdb) [New Thread 2936.0xb80] kill Thread 1 received signal SIGSEGV, Segmentation fault. 0x03ff662b in ?? () top?bt 15 #0 0x03ff662b in ?? () #1 0x00526b92 in stdin_event_handler (error=0, client_data=0x172ed8) at ../../binutils-gdb/gdb/event-top.c:555 #2 0x00525a94 in handle_file_event (ready_mask=, file_ptr=0x3ff5cb8) at ../../binutils-gdb/gdb/event-loop.c:733 #3 gdb_wait_for_event (block=block@entry=1) at ../../binutils-gdb/gdb/event-loop.c:884 #4 0x00525bfb in gdb_do_one_event () at ../../binutils-gdb/gdb/event-loop.c:347 #5 0x00525ce5 in start_event_loop () at ../../binutils-gdb/gdb/event-loop.c:371 #6 0x0051fada in captured_command_loop (data=0x0) at ../../binutils-gdb/gdb/main.c:324 #7 0x0051cf5d in catch_errors ( func=func@entry=0x51fab0 , func_args=func_args@entry=0x0, errstring=errstring@entry=0x7922bf "", mask=mask@entry=RETURN_MASK_ALL) at ../../binutils-gdb/gdb/exceptions.c:236 #8 0x00520f0c in captured_main (data=0x328feb4) at ../../binutils-gdb/gdb/main.c:1149 #9 gdb_main (args=args@entry=0x328feb4) at ../../binutils-gdb/gdb/main.c:1159 #10 0x0071e400 in main (argc=1, argv=0x171220) at ../../binutils-gdb/gdb/gdb.c:32 Fix this by making the functions involved in setjmp/longjmp as noexcept, so that the compiler knows it doesn't need to emit the _Unwind_SjLj_Register / _Unwind_SjLj_Unregister calls for C++ exceptions. Tested on x86_64 Fedora 23 with: - GCC 5.3.1 w/ DWARF-based exceptions. - GCC 7 built with --enable-sjlj-exceptions. gdb/ChangeLog: 2016-12-20 Pedro Alves Yao Qi PR gdb/20977 * event-top.c (gdb_rl_callback_read_char_wrapper_noexcept): New noexcept function, factored out from ... (gdb_rl_callback_read_char_wrapper): ... this. (gdb_rl_callback_handler): Mark noexcept. --- gdb/ChangeLog | 9 +++++++++ gdb/event-top.c | 23 ++++++++++++++++++----- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 233a43c3755..5f0e6fec263 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,12 @@ +2016-12-20 Pedro Alves + Yao Qi + + PR gdb/20977 + * event-top.c (gdb_rl_callback_read_char_wrapper_noexcept): New + noexcept function, factored out from ... + (gdb_rl_callback_read_char_wrapper): ... this. + (gdb_rl_callback_handler): Mark noexcept. + 2016-12-20 Antoine Tremblay * .dir-locals.el: Set c++ mode for the directory and set indent diff --git a/gdb/event-top.c b/gdb/event-top.c index acf84747289..fa58def6da3 100644 --- a/gdb/event-top.c +++ b/gdb/event-top.c @@ -157,10 +157,12 @@ void (*after_char_processing_hook) (void); 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. */ + prompts / queries, through gdb_readline_wrapper. This must be + noexcept in order to avoid problems with mixing sjlj and + (sjlj-based) C++ exceptions. */ -static void -gdb_rl_callback_read_char_wrapper (gdb_client_data client_data) +static struct gdb_exception +gdb_rl_callback_read_char_wrapper_noexcept () noexcept { struct gdb_exception gdb_expt = exception_none; @@ -180,6 +182,15 @@ gdb_rl_callback_read_char_wrapper (gdb_client_data client_data) } END_CATCH_SJLJ + return gdb_expt; +} + +static void +gdb_rl_callback_read_char_wrapper (gdb_client_data client_data) +{ + struct gdb_exception gdb_expt + = gdb_rl_callback_read_char_wrapper_noexcept (); + /* Rethrow using the normal EH mechanism. */ if (gdb_expt.reason < 0) throw_exception (gdb_expt); @@ -187,10 +198,12 @@ gdb_rl_callback_read_char_wrapper (gdb_client_data client_data) /* GDB's readline callback handler. Calls the current INPUT_HANDLER, and propagates GDB exceptions/errors thrown from INPUT_HANDLER back - across readline. See gdb_rl_callback_read_char_wrapper. */ + across readline. See gdb_rl_callback_read_char_wrapper. This must + be noexcept in order to avoid problems with mixing sjlj and + (sjlj-based) C++ exceptions. */ static void -gdb_rl_callback_handler (char *rl) +gdb_rl_callback_handler (char *rl) noexcept { struct gdb_exception gdb_rl_expt = exception_none; struct ui *ui = current_ui; -- 2.30.2