aboutsummaryrefslogtreecommitdiff
path: root/libgcc
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2011-10-28 22:03:56 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2011-10-28 22:03:56 +0000
commit18b4bd7b6cd8dabb4598c97c2e030032738ee112 (patch)
treeb087dac48b5582e2d244b01939bb8dae93938c86 /libgcc
parent4356b75d984e19b079b04a1e737271734a95a4b2 (diff)
downloadgcc-18b4bd7b6cd8dabb4598c97c2e030032738ee112.zip
gcc-18b4bd7b6cd8dabb4598c97c2e030032738ee112.tar.gz
gcc-18b4bd7b6cd8dabb4598c97c2e030032738ee112.tar.bz2
morestack.S: Correct CFI information to do proper returns throughout function.
* 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. From-SVN: r180633
Diffstat (limited to 'libgcc')
-rw-r--r--libgcc/ChangeLog6
-rw-r--r--libgcc/config/i386/morestack.S88
2 files changed, 64 insertions, 30 deletions
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index 2ceb192..a261e75 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -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
diff --git a/libgcc/config/i386/morestack.S b/libgcc/config/i386/morestack.S
index b09ac76..85c20ed 100644
--- a/libgcc/config/i386/morestack.S
+++ b/libgcc/config/i386/morestack.S
@@ -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.