ce426f
# commit 5162e7dd96efcd9b45c1dc1471a964d45278b1e1
ce426f
# Author: Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
ce426f
# Date:   Wed Dec 4 06:41:52 2013 -0600
ce426f
# 
ce426f
#     PowerPC64: Fix incorrect CFI in *context routines
ce426f
#     
ce426f
#     The context established by "makecontext" has a link register pointing
ce426f
#     back to an error path within the makecontext routine.  This is currently
ce426f
#     covered by the CFI FDE for makecontext itself, which is simply wrong
ce426f
#     for the stack frame *inside* the context.  When trying to unwind (e.g.
ce426f
#     doing a backtrace) in a routine inside a context created by makecontext,
ce426f
#     this can lead to uninitialized stack slots being accessed, causing the
ce426f
#     unwinder to crash in the worst case.
ce426f
#     
ce426f
#     Similarly, during parts of the "setcontext" routine, when the stack
ce426f
#     pointer has already been switched to point to the new context, the
ce426f
#     address range is still covered by the CFI FDE for setcontext.  When
ce426f
#     trying to unwind in that situation (e.g. backtrace from an async
ce426f
#     signal handler for profiling), it is again possible that the unwinder
ce426f
#     crashes.
ce426f
#     
ce426f
#     Theses are all problems in existing code, but the changes in stack
ce426f
#     frame layout appear to make the "worst case" much more likely in
ce426f
#     the ELFv2 ABI context.  This causes regressions e.g. in the libgo
ce426f
#     testsuite on ELFv2.
ce426f
#     
ce426f
#     This patch fixes this by ending the makecontext/setcontext FDEs
ce426f
#     before those problematic parts of the assembler, similar to what
ce426f
#     is already done on other platforms.   This fixes the libgo
ce426f
#     regression on ELFv2.
ce426f
# 
ce426f
diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S
ce426f
--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S	2014-05-29 13:16:16.000000000 -0500
ce426f
+++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S	2014-05-29 13:16:17.000000000 -0500
ce426f
@@ -129,6 +129,10 @@
ce426f
      the cpu link stack used to predict blr return addresses.  */
ce426f
   bcl	20,31,L(gotexitcodeaddr);
ce426f
 
ce426f
+  /* End FDE now, because while executing on the context's stack
ce426f
+     the unwind info would be wrong otherwise.  */
ce426f
+  cfi_endproc
ce426f
+
ce426f
 	/* This is the helper code which gets called if a function which
ce426f
 	   is registered with 'makecontext' returns.  In this case we
ce426f
 	   have to install the context listed in the uc_link element of
ce426f
@@ -157,6 +161,11 @@
ce426f
 #endif
ce426f
 	b    L(do_exit)
ce426f
 
ce426f
+  /* Re-establish FDE for the rest of the actual makecontext routine.  */
ce426f
+  cfi_startproc
ce426f
+  cfi_offset (lr, FRAME_LR_SAVE)
ce426f
+  cfi_adjust_cfa_offset (128)
ce426f
+
ce426f
   /* The address of the exit code is in the link register.  Store the lr
ce426f
      in the ucontext as LNK so the target function will return to our
ce426f
      exit code.  */
ce426f
diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/setcontext.S glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/setcontext.S
ce426f
--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/setcontext.S	2014-05-29 13:16:16.000000000 -0500
ce426f
+++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/setcontext.S	2014-05-29 13:16:17.000000000 -0500
ce426f
@@ -129,6 +129,10 @@
ce426f
   lfd  fp1,(SIGCONTEXT_FP_REGS+(PT_R1*8))(r31)
ce426f
   lfd  fp0,(SIGCONTEXT_FP_REGS+(PT_R0*8))(r31)
ce426f
 
ce426f
+  /* End FDE now, because the unwind info would be wrong while
ce426f
+     we're reloading registers to switch to the new context.  */
ce426f
+  cfi_endproc
ce426f
+
ce426f
   ld   r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r31)
ce426f
   ld   r1,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r31)
ce426f
   mtlr r0
ce426f
@@ -177,6 +181,11 @@
ce426f
   ld   r31,(SIGCONTEXT_GP_REGS+(PT_R31*8))(r31)
ce426f
   bctr
ce426f
 
ce426f
+  /* Re-establish FDE for the rest of the actual setcontext routine.  */
ce426f
+  cfi_startproc
ce426f
+  cfi_offset (lr, FRAME_LR_SAVE)
ce426f
+  cfi_adjust_cfa_offset (128)
ce426f
+
ce426f
 L(nv_error_exit):
ce426f
   ld   r0,128+FRAME_LR_SAVE(r1)
ce426f
   addi r1,r1,128
ce426f
@@ -403,6 +412,10 @@
ce426f
   lfd  fp1,(SIGCONTEXT_FP_REGS+(PT_R1*8))(r31)
ce426f
   lfd  fp0,(SIGCONTEXT_FP_REGS+(PT_R0*8))(r31)
ce426f
 
ce426f
+  /* End FDE now, because the unwind info would be wrong while
ce426f
+     we're reloading registers to switch to the new context.  */
ce426f
+  cfi_endproc
ce426f
+
ce426f
   ld   r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r31)
ce426f
   ld   r1,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r31)
ce426f
   mtlr r0
ce426f
@@ -451,6 +464,11 @@
ce426f
   ld   r31,(SIGCONTEXT_GP_REGS+(PT_R31*8))(r31)
ce426f
   bctr
ce426f
 
ce426f
+  /* Re-establish FDE for the rest of the actual setcontext routine.  */
ce426f
+  cfi_startproc
ce426f
+  cfi_offset (lr, FRAME_LR_SAVE)
ce426f
+  cfi_adjust_cfa_offset (128)
ce426f
+
ce426f
 L(error_exit):
ce426f
   ld   r0,128+FRAME_LR_SAVE(r1)
ce426f
   addi r1,r1,128