From patchwork Thu Jun 24 19:44:09 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Lance Taylor X-Patchwork-Id: 56826 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 11E7BB70A1 for ; Fri, 25 Jun 2010 05:44:23 +1000 (EST) Received: (qmail 1039 invoked by alias); 24 Jun 2010 19:44:21 -0000 Received: (qmail 1031 invoked by uid 22791); 24 Jun 2010 19:44:21 -0000 X-SWARE-Spam-Status: No, hits=-2.3 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, SPF_HELO_PASS, TW_CC, T_RP_MATCHES_RCVD, T_TVD_MIME_NO_HEADERS X-Spam-Check-By: sourceware.org Received: from smtp-out.google.com (HELO smtp-out.google.com) (216.239.44.51) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 24 Jun 2010 19:44:16 +0000 Received: from kpbe17.cbf.corp.google.com (kpbe17.cbf.corp.google.com [172.25.105.81]) by smtp-out.google.com with ESMTP id o5OJiEHN015654 for ; Thu, 24 Jun 2010 12:44:14 -0700 Received: from pzk28 (pzk28.prod.google.com [10.243.19.156]) by kpbe17.cbf.corp.google.com with ESMTP id o5OJi7ZE016923 for ; Thu, 24 Jun 2010 12:44:13 -0700 Received: by pzk28 with SMTP id 28so425219pzk.36 for ; Thu, 24 Jun 2010 12:44:13 -0700 (PDT) Received: by 10.142.202.4 with SMTP id z4mr9676037wff.294.1277408653283; Thu, 24 Jun 2010 12:44:13 -0700 (PDT) Received: from coign.google.com ([216.239.45.130]) by mx.google.com with ESMTPS id u34sm3097414wfh.20.2010.06.24.12.44.11 (version=TLSv1/SSLv3 cipher=RC4-MD5); Thu, 24 Jun 2010 12:44:12 -0700 (PDT) To: gcc-patches@gcc.gnu.org Subject: [gccgo] Fixes for stack unwinding From: Ian Lance Taylor Date: Thu, 24 Jun 2010 12:44:09 -0700 Message-ID: User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.1 (gnu/linux) MIME-Version: 1.0 X-System-Of-Record: true 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 This patch includes some fixes for stack unwinding in Go. 1) Don't let the unwind code split the stack. 2) Exiting a thread causes a stack unwind. Don't allocate memory during this unwind. 3) Treat cleanups correctly--not as an exception handler. Committed to gccgo branch. Ian diff -r c066a9b9c7bb libgo/runtime/go-unwind.c --- a/libgo/runtime/go-unwind.c Thu Jun 24 12:36:37 2010 -0700 +++ b/libgo/runtime/go-unwind.c Thu Jun 24 12:37:40 2010 -0700 @@ -47,7 +47,12 @@ { struct _Unwind_Exception *hdr; - if (__go_panic_defer->__is_foreign) + if (__go_panic_defer == NULL) + { + /* Some other language has thrown an exception. We know there + are no defer handlers, so there is nothing to do. */ + } + else if (__go_panic_defer->__is_foreign) { struct __go_panic_stack *n; _Bool was_recovered; @@ -210,6 +215,11 @@ return p; } +/* The personality function is invoked when unwinding the stack due to + a panic. Its job is to find the cleanup and exception handlers to + run. We can't split the stack here, because we won't be able to + unwind from that split. */ + #ifdef __ARM_EABI_UNWINDER__ /* ARM EABI personality routines must also unwind the stack. */ #define CONTINUE_UNWINDING \ @@ -234,7 +244,8 @@ #ifdef __ARM_EABI_UNWINDER__ _Unwind_Reason_Code PERSONALITY_FUNCTION (_Unwind_State, struct _Unwind_Exception *, - struct _Unwind_Context *); + struct _Unwind_Context *) + __attribute__ ((no_split_stack, flatten)); _Unwind_Reason_Code PERSONALITY_FUNCTION (_Unwind_State state, @@ -243,7 +254,8 @@ #else _Unwind_Reason_Code PERSONALITY_FUNCTION (int, _Unwind_Action, _Unwind_Exception_Class, - struct _Unwind_Exception *, struct _Unwind_Context *); + struct _Unwind_Exception *, struct _Unwind_Context *) + __attribute__ ((no_split_stack, flatten)); _Unwind_Reason_Code PERSONALITY_FUNCTION (int version, @@ -316,6 +328,7 @@ if (! ip_before_insn) --ip; landing_pad = 0; + action_record = NULL; #ifdef __USING_SJLJ_EXCEPTIONS__ /* The given "IP" is an index into the call-site table, with two @@ -380,18 +393,29 @@ } if (actions & _UA_SEARCH_PHASE) - return _URC_HANDLER_FOUND; + { + if (action_record == 0) + { + /* This indicates a cleanup rather than an exception + handler. */ + CONTINUE_UNWINDING; + } + return _URC_HANDLER_FOUND; + } + + /* It's possible for __go_panic_defer to be NULL here for an + exception thrown by a language other than Go. */ if (__go_panic_defer == NULL) { if (!is_foreign) - abort(); - __go_panic_defer = ((struct __go_panic_defer_struct *) - __go_alloc (sizeof (struct __go_panic_defer_struct))); + abort (); } - - __go_panic_defer->__exception = ue_header; - __go_panic_defer->__is_foreign = is_foreign; + else + { + __go_panic_defer->__exception = ue_header; + __go_panic_defer->__is_foreign = is_foreign; + } _Unwind_SetGR (context, __builtin_eh_return_data_regno (0), (_Unwind_Ptr) ue_header);