From patchwork Thu Jun 24 19:44:09 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [gccgo] Fixes for stack unwinding Date: Thu, 24 Jun 2010 09:44:09 -0000 From: Ian Taylor X-Patchwork-Id: 56826 Message-Id: To: 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);