From patchwork Mon Jul 30 14:18:40 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julian Brown X-Patchwork-Id: 174026 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id B95A02C008C for ; Tue, 31 Jul 2012 00:19:14 +1000 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1344262756; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Received: Received:Date:From:To:CC:Subject:Message-ID:MIME-Version: Content-Type:Mailing-List:Precedence:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:Sender:Delivered-To; bh=4UOJ0aw iZL66tjo1uCKPOU0Y21M=; b=CecLV4vtMd6dU642ts+ev9m++sRc15SY9pDNltQ OunaoYX+NduNvO0xign8Xsby5USoCpkbpK3N9URAK1U/lWpLcwmQzX3cr/vMUvva 9uRsPDXBaOhoXkuuNx750hPYBm/7KZlYzpQ8+5kttr/ZAk1Ehp/yWc6iV361m+rU xeMA= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:Received:Received:Date:From:To:CC:Subject:Message-ID:MIME-Version:Content-Type:X-IsSubscribed:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=p3MvM8YSNUbORbU415dZ9mWbBQPZFxsMGV5Wwy+m1TQR//sjVQ5VzBVHt7Vkp4 g65gWQ5Wsz9E9Gl6Dnlg+RmhGwztZzmO4Z97Po2PcqXolxbK4kc7MNEIv235sqg3 WK2x1/x8GM+AxEESRerrmb9GCeTfurYSgjKLSvNGdxrEs=; Received: (qmail 29694 invoked by alias); 30 Jul 2012 14:19:10 -0000 Received: (qmail 29683 invoked by uid 22791); 30 Jul 2012 14:19:08 -0000 X-SWARE-Spam-Status: No, hits=-3.2 required=5.0 tests=AWL, BAYES_00, KHOP_RCVD_UNTRUST, RCVD_IN_HOSTKARMA_W, RCVD_IN_HOSTKARMA_WL, TW_CX, TW_TB X-Spam-Check-By: sourceware.org Received: from relay1.mentorg.com (HELO relay1.mentorg.com) (192.94.38.131) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 30 Jul 2012 14:18:54 +0000 Received: from svr-orw-fem-01.mgc.mentorg.com ([147.34.98.93]) by relay1.mentorg.com with esmtp id 1Svqo9-0003gN-46 from Julian_Brown@mentor.com ; Mon, 30 Jul 2012 07:18:53 -0700 Received: from SVR-IES-FEM-01.mgc.mentorg.com ([137.202.0.104]) by svr-orw-fem-01.mgc.mentorg.com over TLS secured channel with Microsoft SMTPSVC(6.0.3790.4675); Mon, 30 Jul 2012 07:18:53 -0700 Received: from octopus (137.202.0.76) by SVR-IES-FEM-01.mgc.mentorg.com (137.202.0.104) with Microsoft SMTP Server id 14.1.289.1; Mon, 30 Jul 2012 15:18:47 +0100 Date: Mon, 30 Jul 2012 15:18:40 +0100 From: Julian Brown To: CC: , Subject: [PATCH, ARM] RFC: Backtracing through C++ exception-handling constructs Message-ID: <20120730151840.0bf5eb81@octopus> MIME-Version: 1.0 X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Hi, I've been investigating a patch which we've been using locally to fix an issue with backtraces (using, e.g., glibc's backtrace() function) through C++ exception-handling constructs on ARM. The original author of the patch was Daniel Jacobowitz (please correct me if my understanding is wrong!). There are two issues in play here: 1. Exception-handling is handled in a target-specific way for ARM, defined in the EHABI document ("Exception handling ABI for the ARM architecture", IHI 0038A). However, no mention of "forced unwinding" is made in this document. 2. Backtracing in particular isn't even the "normal" use case for forced unwinding: e.g., http://www.ucw.cz/~hubicka/papers/abi/node25.html#SECTION00923200000000000000 suggests that forced unwinding is "a single-phase process (phase 2 of the normal exception-handling process)", whereas for producing a backtrace, something more like a phase 1 lookup is done (no cleanup handlers are called -- we're merely observing the state of the stack). So, to be clear, we're definitely dealing with a corner case here. The problem is that _Unwind_Backtrace in libgcc will fail to make progress in some cases if it hits a frame with a cleanup associated with it, leading to unhelpful behaviour like (for the attached program): bar calling abort abort handler invoked, depth 25 ./test() [0x8968] ../install/arm-none-linux-gnueabi/libc/lib/libc.so.6(__default_rt_sa_restorer_v2+0) [0x401cf860] ../install/arm-none-linux-gnueabi/libc/lib/libc.so.6(gsignal+0x40) [0x401ce5e0] ./test() [0x8a4c] ./test() [0x8a4c] ./test() [0x8a4c] ./test() [0x8a4c] ./test() [0x8a4c] ./test() [0x8a4c] ./test() [0x8a4c] ./test() [0x8a4c] ./test() [0x8a4c] ./test() [0x8a4c] ./test() [0x8a4c] ./test() [0x8a4c] ./test() [0x8a4c] ./test() [0x8a4c] ./test() [0x8a4c] ./test() [0x8a4c] ./test() [0x8a4c] ./test() [0x8a4c] ./test() [0x8a4c] ./test() [0x8a4c] ./test() [0x8a4c] ./test() [0x8a4c] which is clearly wrong, no matter how you look at it. I'll defer to Dan for a better description of the problem/fix (on a private branch, circa February 2010): "This bug was a failure of backtrace() when presented with a C++ abort - in particular, one which inherited throw() but called cout, so needed its own call to __cxa_call_unexpected. We'd get stuck in a loop in _Unwind_Backtrace because the code was not prepared for the handler to return _URC_HANDLER_FOUND. "The GCC ARM unwinders already have _US_FORCED_UNWIND passed to the personality routine. ISTM that forced unwinding when doing essentially a 'phase 1' lookup has no other useful meaning, and this is a useful meaning to assign to it: skip handlers, keep unwinding." The patch still seems to produce a reasonable improvement in behaviour, giving: build$ arm-none-linux-gnueabi-g++ test.cc -o test -g $ ./test bar calling abort abort handler invoked, depth 5 ./test() [0x8968] ../install/arm-none-linux-gnueabi/libc/lib/libc.so.6(__default_rt_sa_restorer_v2+0) [0x401cf860] ../install/arm-none-linux-gnueabi/libc/lib/libc.so.6(gsignal+0x40) [0x401ce5e0] ./test() [0x8a4c] ./test() [0x8a4c] although tbh I'd hope for backtrace_symbols to produce something a little more useful than that (unrelated to this patch), and I'd also expect identical results from the test whether the "throw ()" is present on the declaration of "bar", or not -- which unfortunately isn't the case. Without throw (), we get: bar calling abort abort handler invoked, depth 8 ./test() [0x897c] ../install/arm-none-linux-gnueabi/libc/lib/libc.so.6(__default_rt_sa_restorer_v2+0) [0x401cf860] ../install/arm-none-linux-gnueabi/libc/lib/libc.so.6(gsignal+0x40) [0x401ce5e0] ./test() [0x8a60] ./test() [0x8a60] ./test() [0x8a7c] ./test() [0x8acc] ../install/arm-none-linux-gnueabi/libc/lib/libc.so.6(__libc_start_main+0x114) [0x401b8e44] I.e., it looks like the backtrace progresses all the way to the outermost frame -- which IIUC, was the intended resulting behaviour for the attached patch to start with. So: does anyone have an opinion about whether the attached is a correct fix, or if the spinning-during-backtrace problem might have a better solution? (I'm a little fuzzy on the intricate details of all this stuff!). Thanks, Julian ChangeLog Daniel Jacobowitz libstdc++-v3/ * libsupc++/eh_personality.cc (PERSONALITY_FUNCTION): For ARM EABI, skip handlers for _US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND. commit eafec6ead2e5a5a5a1b6504311a6a7ec6f0420af Author: Julian Brown Date: Wed Jul 25 11:43:08 2012 -0700 Backtrace through throw. diff --git a/libstdc++-v3/libsupc++/eh_personality.cc b/libstdc++-v3/libsupc++/eh_personality.cc index 72f596e..3322b6c 100644 --- a/libstdc++-v3/libsupc++/eh_personality.cc +++ b/libstdc++-v3/libsupc++/eh_personality.cc @@ -380,6 +380,8 @@ PERSONALITY_FUNCTION (int version, switch (state & _US_ACTION_MASK) { case _US_VIRTUAL_UNWIND_FRAME: + if (state & _US_FORCE_UNWIND) + CONTINUE_UNWINDING; actions = _UA_SEARCH_PHASE; break;