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