* config/i386/morestack.S: Correct CFI information to do proper
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 28 Oct 2011 22:03:56 +0000 (22:03 +0000)
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 28 Oct 2011 22:03:56 +0000 (22:03 +0000)
returns throughout function.  In 32-bit mode, save %ebx so that it
is restored on unwind.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@180633 138bc75d-0d04-0410-961f-82ee72b054a4

libgcc/ChangeLog
libgcc/config/i386/morestack.S

index 2ceb192..a261e75 100644 (file)
@@ -1,3 +1,9 @@
+2011-10-28  Ian Lance Taylor  <iant@google.com>
+
+       * config/i386/morestack.S: Correct CFI information to do proper
+       returns throughout function.  In 32-bit mode, save %ebx so that it
+       is restored on unwind.
+
 2011-10-25  Bernd Schmidt  <bernds@codesourcery.com>
 
        * config/c6x/pr-support.c (__gnu_unwind_24bit): Correct logic for the
index b09ac76..85c20ed 100644 (file)
@@ -139,44 +139,68 @@ __morestack:
        .cfi_lsda 0x1b,.LLSDA1
 #endif
 
-       # Set up a normal backtrace.
-       pushl   %ebp
-       .cfi_def_cfa_offset 8
-       .cfi_offset %ebp, -8
-       movl    %esp, %ebp
-       .cfi_def_cfa_register %ebp
-
        # We return below with a ret $8.  We will return to a single
        # return instruction, which will return to the caller of our
        # caller.  We let the unwinder skip that single return
        # instruction, and just return to the real caller.
-       .cfi_offset 8, 8
+
+       # Here CFA points just past the return address on the stack,
+       # e.g., on function entry it is %esp + 4.  Later we will
+       # change it to %ebp + 8, as set by .cfi_def_cfa_register and
+       # .cfi_def_cfa_offset above.  The stack looks like this:
+       #       CFA + 12:       stack pointer after two returns
+       #       CFA + 8:        return address of morestack caller's caller
+       #       CFA + 4:        size of parameters
+       #       CFA:            new stack frame size
+       #       CFA - 4:        return address of this function
+       #       CFA - 8:        previous value of %ebp; %ebp points here
+       # We want to set %esp to the stack pointer after the double
+       # return, which is CFA + 12.
+       .cfi_offset 8, 8                # New PC stored at CFA + 8
        .cfi_escape 0x15, 4, 0x7d       # DW_CFA_val_offset_sf, %esp, 12/-4
+                                       # i.e., next %esp is CFA + 12
+
+       # Set up a normal backtrace.
+       pushl   %ebp
+       .cfi_def_cfa_offset 8
+       .cfi_offset %ebp, -8
+       movl    %esp,%ebp
+       .cfi_def_cfa_register %ebp
 
        # In 32-bit mode the parameters are pushed on the stack.  The
        # argument size is pushed then the new stack frame size is
        # pushed.
 
+       # Align stack to 16-byte boundary with enough space for saving
+       # registers and passing parameters to functions we call.
+       subl    $40,%esp
+
+       # Because our cleanup code may need to clobber %ebx, we need
+       # to save it here so the unwinder can restore the value used
+       # by the caller.  Note that we don't have to restore the
+       # register, since we don't change it, we just have to save it
+       # for the unwinder.
+       movl    %ebx,-4(%ebp)
+       .cfi_offset %ebx, -12
+
        # In 32-bit mode the registers %eax, %edx, and %ecx may be
        # used for parameters, depending on the regparm and fastcall
        # attributes.
 
-       pushl   %eax
-       pushl   %edx
-       pushl   %ecx
+       movl    %eax,-8(%ebp)
+       movl    %edx,-12(%ebp)
+       movl    %ecx,-16(%ebp)
 
        call    __morestack_block_signals
 
-       pushl   12(%ebp)                # The size of the parameters.
+       movl    12(%ebp),%eax           # The size of the parameters.
+       movl    %eax,8(%esp)
        leal    20(%ebp),%eax           # Address of caller's parameters.
-       pushl   %eax
+       movl    %eax,4(%esp)
        addl    $BACKOFF,8(%ebp)        # Ask for backoff bytes.
        leal    8(%ebp),%eax            # The address of the new frame size.
-       pushl   %eax
+       movl    %eax,(%esp)
 
-       # Note that %esp is exactly 32 bytes below the CFA -- perfect for
-       # a 16-byte aligned stack.  That said, we still ought to compile
-       # generic-morestack.c with -mpreferred-stack-boundary=2.  FIXME.
        call    __generic_morestack
 
        movl    %eax,%esp               # Switch to the new stack.
@@ -191,8 +215,8 @@ __morestack:
 
        call    __morestack_unblock_signals
 
-       movl    -8(%ebp),%edx           # Restore registers.
-       movl    -12(%ebp),%ecx
+       movl    -12(%ebp),%edx          # Restore registers.
+       movl    -16(%ebp),%ecx
 
        movl    4(%ebp),%eax            # Increment the return address
        cmpb    $0xc3,(%eax)            # to skip the ret instruction;
@@ -200,12 +224,12 @@ __morestack:
        addl    $2,%eax
 1:     inc     %eax
 
-       movl    %eax,-8(%ebp)           # Store return address in an
+       movl    %eax,-12(%ebp)          # Store return address in an
                                        # unused slot.
 
-       movl    -4(%ebp),%eax           # Restore the last register.
+       movl    -8(%ebp),%eax           # Restore the last register.
 
-       call    *-8(%ebp)               # Call our caller!
+       call    *-12(%ebp)              # Call our caller!
 
        # The caller will return here, as predicted.
 
@@ -255,9 +279,13 @@ __morestack:
        popl    %eax
 
        .cfi_remember_state
+
+       # We never changed %ebx, so we don't have to actually restore it.
+       .cfi_restore %ebx
+
        popl    %ebp
        .cfi_restore %ebp
-       .cfi_def_cfa %esp, 12
+       .cfi_def_cfa %esp, 4
        ret     $8                      # Return to caller, which will
                                        # immediately return.  Pop
                                        # arguments as we go.
@@ -300,13 +328,6 @@ __morestack:
        .cfi_lsda 0x1b,.LLSDA1
 #endif
 
-       # Set up a normal backtrace.
-       pushq   %rbp
-       .cfi_def_cfa_offset 16
-       .cfi_offset %rbp, -16
-       movq    %rsp, %rbp
-       .cfi_def_cfa_register %rbp
-
        # We will return a single return instruction, which will
        # return to the caller of our caller.  Let the unwinder skip
        # that single return instruction, and just return to the real
@@ -314,6 +335,13 @@ __morestack:
        .cfi_offset 16, 0
        .cfi_escape 0x15, 7, 0x7f       # DW_CFA_val_offset_sf, %esp, 8/-8
 
+       # Set up a normal backtrace.
+       pushq   %rbp
+       .cfi_def_cfa_offset 16
+       .cfi_offset %rbp, -16
+       movq    %rsp, %rbp
+       .cfi_def_cfa_register %rbp
+
        # In 64-bit mode the new stack frame size is passed in r10
         # and the argument size is passed in r11.