diff options
author | Ulrich Weigand <Ulrich.Weigand@de.ibm.com> | 2013-12-04 06:41:52 -0600 |
---|---|---|
committer | Adhemerval Zanella <azanella@linux.vnet.ibm.com> | 2013-12-04 07:41:37 -0600 |
commit | 5162e7dd96efcd9b45c1dc1471a964d45278b1e1 (patch) | |
tree | 82cf3f29b872248b8ca7d82e5706c70aaaf64da3 /sysdeps/unix | |
parent | 19e3372ba4538f85b6c73361feaf408ae0e65ebe (diff) | |
download | glibc-5162e7dd96efcd9b45c1dc1471a964d45278b1e1.tar.gz glibc-5162e7dd96efcd9b45c1dc1471a964d45278b1e1.tar.xz glibc-5162e7dd96efcd9b45c1dc1471a964d45278b1e1.zip |
PowerPC64: Fix incorrect CFI in *context routines
The context established by "makecontext" has a link register pointing back to an error path within the makecontext routine. This is currently covered by the CFI FDE for makecontext itself, which is simply wrong for the stack frame *inside* the context. When trying to unwind (e.g. doing a backtrace) in a routine inside a context created by makecontext, this can lead to uninitialized stack slots being accessed, causing the unwinder to crash in the worst case. Similarly, during parts of the "setcontext" routine, when the stack pointer has already been switched to point to the new context, the address range is still covered by the CFI FDE for setcontext. When trying to unwind in that situation (e.g. backtrace from an async signal handler for profiling), it is again possible that the unwinder crashes. Theses are all problems in existing code, but the changes in stack frame layout appear to make the "worst case" much more likely in the ELFv2 ABI context. This causes regressions e.g. in the libgo testsuite on ELFv2. This patch fixes this by ending the makecontext/setcontext FDEs before those problematic parts of the assembler, similar to what is already done on other platforms. This fixes the libgo regression on ELFv2.
Diffstat (limited to 'sysdeps/unix')
-rw-r--r-- | sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S | 9 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/powerpc/powerpc64/setcontext.S | 18 |
2 files changed, 27 insertions, 0 deletions
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S b/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S index 32fc47c3f3..a7b0a18108 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S @@ -129,6 +129,10 @@ L(noparms): the cpu link stack used to predict blr return addresses. */ bcl 20,31,L(gotexitcodeaddr); + /* End FDE now, because while executing on the context's stack + the unwind info would be wrong otherwise. */ + cfi_endproc + /* This is the helper code which gets called if a function which is registered with 'makecontext' returns. In this case we have to install the context listed in the uc_link element of @@ -157,6 +161,11 @@ L(do_exit): #endif b L(do_exit) + /* Re-establish FDE for the rest of the actual makecontext routine. */ + cfi_startproc + cfi_offset (lr, FRAME_LR_SAVE) + cfi_adjust_cfa_offset (128) + /* The address of the exit code is in the link register. Store the lr in the ucontext as LNK so the target function will return to our exit code. */ diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/setcontext.S b/sysdeps/unix/sysv/linux/powerpc/powerpc64/setcontext.S index e1f0b8624c..5ec19ba561 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/setcontext.S +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/setcontext.S @@ -129,6 +129,10 @@ ENTRY(__novec_setcontext) lfd fp1,(SIGCONTEXT_FP_REGS+(PT_R1*8))(r31) lfd fp0,(SIGCONTEXT_FP_REGS+(PT_R0*8))(r31) + /* End FDE now, because the unwind info would be wrong while + we're reloading registers to switch to the new context. */ + cfi_endproc + ld r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r31) ld r1,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r31) mtlr r0 @@ -177,6 +181,11 @@ ENTRY(__novec_setcontext) ld r31,(SIGCONTEXT_GP_REGS+(PT_R31*8))(r31) bctr + /* Re-establish FDE for the rest of the actual setcontext routine. */ + cfi_startproc + cfi_offset (lr, FRAME_LR_SAVE) + cfi_adjust_cfa_offset (128) + L(nv_error_exit): ld r0,128+FRAME_LR_SAVE(r1) addi r1,r1,128 @@ -403,6 +412,10 @@ L(has_no_vec): lfd fp1,(SIGCONTEXT_FP_REGS+(PT_R1*8))(r31) lfd fp0,(SIGCONTEXT_FP_REGS+(PT_R0*8))(r31) + /* End FDE now, because the unwind info would be wrong while + we're reloading registers to switch to the new context. */ + cfi_endproc + ld r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r31) ld r1,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r31) mtlr r0 @@ -451,6 +464,11 @@ L(has_no_vec): ld r31,(SIGCONTEXT_GP_REGS+(PT_R31*8))(r31) bctr + /* Re-establish FDE for the rest of the actual setcontext routine. */ + cfi_startproc + cfi_offset (lr, FRAME_LR_SAVE) + cfi_adjust_cfa_offset (128) + L(error_exit): ld r0,128+FRAME_LR_SAVE(r1) addi r1,r1,128 |