# commit 5162e7dd96efcd9b45c1dc1471a964d45278b1e1 # Author: Ulrich Weigand # Date: Wed Dec 4 06:41:52 2013 -0600 # # 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. # --- # sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S | 9 ++++++++ # sysdeps/unix/sysv/linux/powerpc/powerpc64/setcontext.S | 18 ++++++++++++++++ # 2 files changed, 27 insertions(+) # --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S @@ -129,6 +129,10 @@ 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 @@ #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. */ --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/setcontext.S +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/setcontext.S @@ -129,6 +129,10 @@ 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 @@ 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 @@ 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 @@ 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