From patchwork Mon Dec 19 14:42:17 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yao Qi X-Patchwork-Id: 18580 Received: (qmail 9108 invoked by alias); 19 Dec 2016 14:42:50 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 9089 invoked by uid 89); 19 Dec 2016 14:42:49 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.5 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE, RCVD_IN_SORBS_SPAM, SPF_PASS autolearn=no version=3.3.2 spammy=D*entry X-HELO: mail-pg0-f65.google.com Received: from mail-pg0-f65.google.com (HELO mail-pg0-f65.google.com) (74.125.83.65) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 19 Dec 2016 14:42:39 +0000 Received: by mail-pg0-f65.google.com with SMTP id g1so6884130pgn.0 for ; Mon, 19 Dec 2016 06:42:39 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id; bh=WHuaF62zjoMwobUW2aZJxaDoCFaS6ov4QgTMabbq7tM=; b=gnkA4k3x+T+suNbXPX1PGhDHlclbuI4l/514Dssr61MIVJOv1TJYSnoAa06lZ+ovtU qNgUBw+WYWFqrZrzRpIczpffcPZdDxrXyYNF6DdTB+WCNQ4Zj5Rjw2pd3W/lrX53mCaO Ji3CkjL5wfICspg/xEkcxyxqbihFh5QBPHwDxpzIFGTtT2a3B8KZu3N+SjSxibwjb798 fZirg67ADwTqyUlz/Vu8d819OeU1rxNIjwe2a2oQ6kczDVWvHItiHaw/x0tDvqBDvTrR rE0D06hYmJg90/OPJ6gfzhbpGJSHydmCoa+iOSKXwwrJondUGD91eIy9C5KzE6PhVlt+ 27+g== X-Gm-Message-State: AKaTC01K41Qtb+ksP2IeHB+JZ1Ck0CPg4Pt2sDMwGU555Ycff/kqC3nQIB7mzQJa9JSHvw== X-Received: by 10.84.193.129 with SMTP id f1mr35256551pld.129.1482158557744; Mon, 19 Dec 2016 06:42:37 -0800 (PST) Received: from E107787-LIN.cambridge.arm.com (gcc1-power7.osuosl.org. [140.211.15.137]) by smtp.gmail.com with ESMTPSA id h7sm32361338pgn.13.2016.12.19.06.42.36 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 19 Dec 2016 06:42:37 -0800 (PST) From: Yao Qi X-Google-Original-From: Yao Qi To: gdb-patches@sourceware.org Subject: [RFC master/7.12.1] Don't propagate C++ exceptions across readline using SjLj on SjLj-based exception unwinding Date: Mon, 19 Dec 2016 14:42:17 +0000 Message-Id: <1482158537-17839-1-git-send-email-yao.qi@linaro.org> X-IsSubscribed: yes Nowadays, we propagate C++ exceptions across readline using setjmp/longjmp 89525768cd086a0798a504c81fdf7ebcd4c904e1 (Propagate GDB/C++ exceptions across readline using sj/lj-based TRY/CATCH) because DWARF-based unwinding can't cross C function (see details from the commit above). However, SjLj-based exception unwinding doesn't have such issue. What is more, looks longjmp may break the SjLj-based exception handling, because _Unwind_SjLj_Unregister, which is put the exit of function, is not executed due to longjmp. (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 I dig into libcc/unwind-sjlj.c and gcc/except.c, but I still don't find much clue. This patch fixes this issue by not propagating the exception via setjmp/longjmp if __USING_SJLJ_EXCEPTIONS__. gdb: 2016-12-19 Yao Qi PR gdb/20977 * event-top.c (gdb_rl_callback_read_char_wrapper): New function. (gdb_rl_callback_read_char_wrapper): Call gdb_rl_callback_read_char_wrapper. (gdb_rl_callback_handler_1): New function. (gdb_rl_callback_handler): Call gdb_rl_callback_handler_1. --- gdb/event-top.c | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/gdb/event-top.c b/gdb/event-top.c index acf8474..db3a18f 100644 --- a/gdb/event-top.c +++ b/gdb/event-top.c @@ -121,6 +121,14 @@ static struct async_signal_handler *async_sigterm_token; void (*after_char_processing_hook) (void); +static void +gdb_rl_callback_read_char_wrapper (void) +{ + rl_callback_read_char (); + if (after_char_processing_hook) + (*after_char_processing_hook) (); +} + /* Wrapper function for calling into the readline library. This takes care of a couple things: @@ -136,7 +144,8 @@ void (*after_char_processing_hook) (void); 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. + others don't. However SJLJ-based unwinding doesn't have such + problem. 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 @@ -162,6 +171,9 @@ void (*after_char_processing_hook) (void); static void gdb_rl_callback_read_char_wrapper (gdb_client_data client_data) { +#ifdef __USING_SJLJ_EXCEPTIONS__ + gdb_rl_callback_read_char_wrapper(); +#else struct gdb_exception gdb_expt = exception_none; /* C++ exceptions can't normally be thrown across readline (unless @@ -170,9 +182,7 @@ gdb_rl_callback_read_char_wrapper (gdb_client_data client_data) 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) (); + gdb_rl_callback_read_char_wrapper(); } CATCH_SJLJ (ex, RETURN_MASK_ALL) { @@ -183,6 +193,15 @@ gdb_rl_callback_read_char_wrapper (gdb_client_data client_data) /* Rethrow using the normal EH mechanism. */ if (gdb_expt.reason < 0) throw_exception (gdb_expt); +#endif +} + +static void +gdb_rl_callback_handler_1 (char *rl) +{ + struct ui *ui = current_ui; + + ui->input_handler (rl); } /* GDB's readline callback handler. Calls the current INPUT_HANDLER, @@ -192,12 +211,14 @@ gdb_rl_callback_read_char_wrapper (gdb_client_data client_data) static void gdb_rl_callback_handler (char *rl) { +#ifdef __USING_SJLJ_EXCEPTIONS__ + gdb_rl_callback_handler_1 (rl); +#else struct gdb_exception gdb_rl_expt = exception_none; - struct ui *ui = current_ui; TRY { - ui->input_handler (rl); + gdb_rl_callback_handler_1 (rl); } CATCH (ex, RETURN_MASK_ALL) { @@ -214,6 +235,7 @@ gdb_rl_callback_handler (char *rl) dtors are NOT run automatically. */ if (gdb_rl_expt.reason < 0) throw_exception_sjlj (gdb_rl_expt); +#endif } /* Change the function to be invoked every time there is a character