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