From patchwork Thu Jun 24 19:47:14 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: 56828 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 85549B6F16 for ; Fri, 25 Jun 2010 05:47:30 +1000 (EST) Received: (qmail 3188 invoked by alias); 24 Jun 2010 19:47:29 -0000 Received: (qmail 3179 invoked by uid 22791); 24 Jun 2010 19:47:28 -0000 X-SWARE-Spam-Status: No, hits=-2.1 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, SPF_HELO_PASS, TW_CC, TW_DD, TW_OV, TW_SL, TW_XF, 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) (74.125.121.35) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 24 Jun 2010 19:47:22 +0000 Received: from kpbe12.cbf.corp.google.com (kpbe12.cbf.corp.google.com [172.25.105.76]) by smtp-out.google.com with ESMTP id o5OJlJHV024276 for ; Thu, 24 Jun 2010 12:47:19 -0700 Received: from pxi20 (pxi20.prod.google.com [10.243.27.20]) by kpbe12.cbf.corp.google.com with ESMTP id o5OJklMe010358 for ; Thu, 24 Jun 2010 12:47:18 -0700 Received: by pxi20 with SMTP id 20so1748295pxi.39 for ; Thu, 24 Jun 2010 12:47:18 -0700 (PDT) Received: by 10.142.209.8 with SMTP id h8mr3782611wfg.155.1277408837975; Thu, 24 Jun 2010 12:47:17 -0700 (PDT) Received: from coign.google.com ([216.239.45.130]) by mx.google.com with ESMTPS id d14sm6212849rva.18.2010.06.24.12.47.16 (version=TLSv1/SSLv3 cipher=RC4-MD5); Thu, 24 Jun 2010 12:47:17 -0700 (PDT) To: gcc-patches@gcc.gnu.org Subject: [gccgo] Use a cleanup to restore the stack guard when unwinding From: Ian Lance Taylor Date: Thu, 24 Jun 2010 12:47:14 -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 When using split stacks, and unwinding the stack due to an exception, we need to not only restore the stack pointer across a stack split, we need to also restore the stack guard. This patch implements that by using a cleanup in the split stack code. Committed to gccgo branch. Ian Index: generic-morestack.c =================================================================== --- generic-morestack.c (revision 161235) +++ generic-morestack.c (working copy) @@ -62,6 +62,10 @@ extern void * __generic_releasestack (size_t *pavailable) __attribute__ ((no_split_stack, flatten, visibility ("hidden"))); +extern size_t +__generic_findstack (void *stack) + __attribute__ ((no_split_stack, flatten, visibility ("hidden"))); + extern void __morestack_load_mmap (void) __attribute__ ((no_split_stack)); @@ -362,6 +366,33 @@ __generic_releasestack (size_t *pavailab return old_stack; } +/* Find the stack segment for STACK and return the amount of space + available. This is used when unwinding the stack because of an + exception, in order to reset the stack guard correctly. */ + +size_t +__generic_findstack (void *stack) +{ + struct stack_segment *pss; + + for (pss = __morestack_current_segment; pss != NULL; pss = pss->prev) + { + if ((char *) pss < (char *) stack + && (char *) pss + pss->size > (char *) stack) + { + __morestack_current_segment = pss; +#ifdef STACK_GROWS_DOWNWARD + return (char *) stack - (char *) (pss + 1); +#else + return (char *) (pss + 1) + pss->size - (char *) stack; +#endif + } + } + + // We don't know where we are on the stack. + return 512; +} + /* This function is called at program startup time to make sure that mmap and munmap are resolved if linking dynamically. We want to resolve them while we have enough stack for them, rather than Index: config/i386/morestack.S =================================================================== --- config/i386/morestack.S (revision 161235) +++ config/i386/morestack.S (working copy) @@ -103,10 +103,21 @@ __morestack_non_split: #endif __morestack: +.LFB1: .cfi_startproc #ifndef __x86_64__ + # We use a cleanup to restore the stack guard if an exception + # is thrown through this code. +#ifndef __PIC__ + .cfi_personality 0,__gcc_personality_v0 + .cfi_lsda 0,.LLSDA1 +#else + .cfi_personality 0x9b,DW.ref.__gcc_personality_v0 + .cfi_lsda 0x1b,.LLSDA1 +#endif + # Set up a normal backtrace. pushl %ebp .cfi_def_cfa_offset 8 @@ -152,6 +163,7 @@ __morestack: # FIXME: The offset must match # TARGET_THREAD_SPLIT_STACK_OFFSET in # gcc/config/i386/linux.h. +.LEHB0: movl %eax,%gs:0x30 # Save the new stack boundary. movl -8(%ebp),%edx # Restore registers. @@ -186,6 +198,7 @@ __morestack: subl 4(%esp),%eax # Subtract available space. addl $512,%eax # Back off 512 bytes. +.LEHE0: movl %eax,%gs:0x30 # Save the new stack boundary. addl $8,%esp # Remove values from stack. @@ -195,14 +208,42 @@ __morestack: # Switch back to the old stack via copy back from %ebp. leave + .cfi_remember_state .cfi_restore %ebp .cfi_def_cfa %esp, 12 ret $8 # Return to caller, which will # immediately return. Pop # arguments as we go. +# This is the cleanup code called by the stack unwinder when unwinding +# through the code between .LEHB0 and .LEHE0 above. + +.L1: + .cfi_restore_state + subl $16,%esp # Maintain 16 byte alignment. + movl %eax,4(%esp) # Save exception header. + movl %ebp,(%esp) # Stack pointer after resume. + call __generic_findstack + movl %esp,%ecx # Get the stack pointer. + subl %eax,%ecx # Subtract available space. + addl $512,%ecx # Back off 512 bytes. + movl %ecx,%gs:0x30 # Save new stack boundary. + movl 4(%esp),%eax # Function argument. + movl %eax,(%esp) + call _Unwind_Resume # Resume unwinding. + #else /* defined(__x86_64__) */ + # We use a cleanup to restore the stack guard if an exception + # is thrown through this code. +#ifndef __PIC__ + .cfi_personality 0x3,__gcc_personality_v0 + .cfi_lsda 0x3,.LLSDA1 +#else + .cfi_personality 0x9b,DW.ref.__gcc_personality_v0 + .cfi_lsda 0x1b,.LLSDA1 +#endif + # Set up a normal backtrace. pushq %rbp .cfi_def_cfa_offset 16 @@ -251,6 +292,7 @@ __morestack: # FIXME: The offset must match # TARGET_THREAD_SPLIT_STACK_OFFSET in # gcc/config/i386/linux64.h. +.LEHB0: movq %rax,%fs:0x70 # Save the new stack boundary. movq 8(%rbp),%r10 # Increment the return address @@ -276,6 +318,7 @@ __morestack: subq 0(%rsp),%rax # Subtract available space. addq $512,%rax # Back off 512 bytes. +.LEHE0: movq %rax,%fs:0x70 # Save the new stack boundary. addq $8,%rsp # Remove value from stack. @@ -284,12 +327,30 @@ __morestack: popq %rax # Switch back to the old stack via copy back from %rbp. + .cfi_remember_state leave .cfi_restore %rbp .cfi_def_cfa %rsp, 8 ret # Return to caller, which will # immediately return. +# This is the cleanup code called by the stack unwinder when unwinding +# through the code between .LEHB0 and .LEHE0 above. + +.L1: + .cfi_restore_state + movl %edx,%ebx # Save exception data + movq %rax,%r12 + movl %rbp,%rdi # Stack pointer after resume. + call __generic_findstack + movq %rsp,%rcx # Get the stack pointer. + subq %rax,%rcx # Subtract available space. + addq $512,%rcx # Back off 512 bytes. + movq %rcx,%fs:0x70 # Save new stack boundary. + movq %r12,%rdi # Restore exception data for call. + movslq %ebx,%rdx + call _Unwind_Resume # Resume unwinding. + #endif /* defined(__x86_64__) */ .cfi_endproc @@ -297,6 +358,40 @@ __morestack: .size __morestack, . - __morestack #endif + .globl __gcc_personality_v0 + .section .gcc_except_table,"a",@progbits + .align 4 +.LLSDA1: + .byte 0xff # @LPStart format (omit) + .byte 0xff # @TType format (omit) + .byte 0x1 # call-site format (uleb128) + .uleb128 .LLSDACSE1-.LLSDACSB1 # Call-site table length +.LLSDACSB1: + .uleb128 .LEHB0-.LFB1 # region 0 start + .uleb128 .LEHE0-.LEHB0 # length + .uleb128 .L1-.LFB1 # landing pad + .uleb128 0 # action +.LLSDACSE1: + +#ifdef __PIC__ + # Build a position independent reference to the basic + # personality function. + .hidden DW.ref.__gcc_personality_v0 + .weak DW.ref.__gcc_personality_v0 + .section .data.DW.ref.__gcc_personality_v0,"awG",@progbits,DW.ref.__gcc_personality_v0,comdat + .type DW.ref.__gcc_personality_v0, @object +DW.ref.__gcc_personality_v0: +#ifndef __x86_64 + .align 4 + .size DW.ref.__gcc_personality_v0, 4 + .long __gcc_personality_v0 +#else + .align 8 + .size DW.ref.__gcc_personality_v0, 8 + .quad __gcc_personality_v0 +#endif +#endif + # Initialize the stack test value when the program starts or when a # new thread starts. We don't know how large the main stack is, so we # guess conservatively. We might be able to use getrlimit here.