5de29b
# commit 61cd8fe4017c251617dd300818917e61a12ab48e
5de29b
# Author: Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
5de29b
# Date:   Wed Dec 4 06:59:37 2013 -0600
5de29b
# 
5de29b
#     PowerPC64 ELFv2 ABI 5/6: LD_AUDIT interface changes
5de29b
#     
5de29b
#     The ELFv2 ABI changes the calling convention by passing and returning
5de29b
#     structures in registers in more cases than the old ABI:
5de29b
#     http://gcc.gnu.org/ml/gcc-patches/2013-11/msg01145.html
5de29b
#     http://gcc.gnu.org/ml/gcc-patches/2013-11/msg01147.html
5de29b
#     
5de29b
#     For the most part, this does not affect glibc, since glibc assembler
5de29b
#     files do not use structure parameters / return values.  However, one
5de29b
#     place is affected: the LD_AUDIT interface provides a structure to
5de29b
#     the audit routine that contains all registers holding function
5de29b
#     argument and return values for the intercepted PLT call.
5de29b
#     
5de29b
#     Since the new ABI now sometimes uses registers to return values
5de29b
#     that were never used for this purpose in the old ABI, this structure
5de29b
#     has to be extended.  To force audit routines to be modified for the
5de29b
#     new ABI if necessary, the patch defines v2 variants of the la_ppc64
5de29b
#     types and routines.
5de29b
#     
5de29b
#     In addition, the patch contains two unrelated changes to the
5de29b
#     PLT trampoline routines: it fixes a bug where FPR return values
5de29b
#     were stored in the wrong place, and it removes the unnecessary
5de29b
#     save/restore of CR.
5de29b
# 
12745e
diff -urN glibc-2.17-c758a686/sysdeps/powerpc/bits/link.h glibc-2.17-c758a686/sysdeps/powerpc/bits/link.h
12745e
--- glibc-2.17-c758a686/sysdeps/powerpc/bits/link.h	2014-05-29 14:11:12.000000000 -0500
12745e
+++ glibc-2.17-c758a686/sysdeps/powerpc/bits/link.h	2014-05-29 14:11:20.000000000 -0500
5de29b
@@ -63,7 +63,7 @@
5de29b
 
5de29b
 __END_DECLS
5de29b
 
5de29b
-#else
5de29b
+#elif _CALL_ELF != 2
5de29b
 
5de29b
 /* Registers for entry into PLT on PPC64.  */
5de29b
 typedef struct La_ppc64_regs
5de29b
@@ -107,4 +107,48 @@
5de29b
 
5de29b
 __END_DECLS
5de29b
 
5de29b
+#else
5de29b
+
5de29b
+/* Registers for entry into PLT on PPC64 in the ELFv2 ABI.  */
5de29b
+typedef struct La_ppc64v2_regs
5de29b
+{
5de29b
+  uint64_t lr_reg[8];
5de29b
+  double lr_fp[13];
5de29b
+  uint32_t __padding;
5de29b
+  uint32_t lr_vrsave;
5de29b
+  uint32_t lr_vreg[12][4] __attribute__ ((aligned (16)));
5de29b
+  uint64_t lr_r1;
5de29b
+  uint64_t lr_lr;
5de29b
+} La_ppc64v2_regs;
5de29b
+
5de29b
+/* Return values for calls from PLT on PPC64 in the ELFv2 ABI.  */
5de29b
+typedef struct La_ppc64v2_retval
5de29b
+{
5de29b
+  uint64_t lrv_r3;
5de29b
+  uint64_t lrv_r4;
5de29b
+  double lrv_fp[10];
5de29b
+  uint32_t lrv_vreg[8][4] __attribute__ ((aligned (16)));
5de29b
+} La_ppc64v2_retval;
5de29b
+
5de29b
+
5de29b
+__BEGIN_DECLS
5de29b
+
5de29b
+extern Elf64_Addr la_ppc64v2_gnu_pltenter (Elf64_Sym *__sym,
5de29b
+					   unsigned int __ndx,
5de29b
+					   uintptr_t *__refcook,
5de29b
+					   uintptr_t *__defcook,
5de29b
+					   La_ppc64v2_regs *__regs,
5de29b
+					   unsigned int *__flags,
5de29b
+					   const char *__symname,
5de29b
+					   long int *__framesizep);
5de29b
+extern unsigned int la_ppc64v2_gnu_pltexit (Elf64_Sym *__sym,
5de29b
+					    unsigned int __ndx,
5de29b
+					    uintptr_t *__refcook,
5de29b
+					    uintptr_t *__defcook,
5de29b
+					    const La_ppc64v2_regs *__inregs,
5de29b
+					    La_ppc64v2_retval *__outregs,
5de29b
+					    const char *__symname);
5de29b
+
5de29b
+__END_DECLS
5de29b
+
5de29b
 #endif
12745e
diff -urN glibc-2.17-c758a686/sysdeps/powerpc/ldsodefs.h glibc-2.17-c758a686/sysdeps/powerpc/ldsodefs.h
12745e
--- glibc-2.17-c758a686/sysdeps/powerpc/ldsodefs.h	2014-05-29 14:11:12.000000000 -0500
12745e
+++ glibc-2.17-c758a686/sysdeps/powerpc/ldsodefs.h	2014-05-29 14:11:20.000000000 -0500
5de29b
@@ -25,6 +25,8 @@
5de29b
 struct La_ppc32_retval;
5de29b
 struct La_ppc64_regs;
5de29b
 struct La_ppc64_retval;
5de29b
+struct La_ppc64v2_regs;
5de29b
+struct La_ppc64v2_retval;
5de29b
 
5de29b
 #define ARCH_PLTENTER_MEMBERS						\
5de29b
     Elf32_Addr (*ppc32_gnu_pltenter) (Elf32_Sym *, unsigned int, uintptr_t *, \
5de29b
@@ -34,7 +36,12 @@
5de29b
     Elf64_Addr (*ppc64_gnu_pltenter) (Elf64_Sym *, unsigned int, uintptr_t *, \
5de29b
 				      uintptr_t *, struct La_ppc64_regs *, \
5de29b
 				      unsigned int *, const char *name,	\
5de29b
-				      long int *framesizep)
5de29b
+				      long int *framesizep);		\
5de29b
+    Elf64_Addr (*ppc64v2_gnu_pltenter) (Elf64_Sym *, unsigned int,	\
5de29b
+					uintptr_t *,  uintptr_t *,	\
5de29b
+					struct La_ppc64v2_regs *,	\
5de29b
+					unsigned int *, const char *name, \
5de29b
+					long int *framesizep)
5de29b
 
5de29b
 #define ARCH_PLTEXIT_MEMBERS						\
5de29b
     unsigned int (*ppc32_gnu_pltexit) (Elf32_Sym *, unsigned int,	\
5de29b
@@ -47,7 +54,14 @@
5de29b
 				       uintptr_t *,			\
5de29b
 				       uintptr_t *,			\
5de29b
 				       const struct La_ppc64_regs *,	\
5de29b
-				       struct La_ppc64_retval *, const char *)
5de29b
+				       struct La_ppc64_retval *,	\
5de29b
+				       const char *);			\
5de29b
+    unsigned int (*ppc64v2_gnu_pltexit) (Elf64_Sym *, unsigned int,	\
5de29b
+					 uintptr_t *,			\
5de29b
+					 uintptr_t *,			\
5de29b
+					 const struct La_ppc64v2_regs *,\
5de29b
+					 struct La_ppc64v2_retval *,	\
5de29b
+					 const char *)
5de29b
 
5de29b
 #include_next <ldsodefs.h>
5de29b
 
12745e
diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-machine.h glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-machine.h
12745e
--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-machine.h	2014-05-29 14:11:12.000000000 -0500
12745e
+++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-machine.h	2014-05-29 14:11:20.000000000 -0500
5de29b
@@ -546,8 +546,13 @@
5de29b
 
5de29b
 
5de29b
 /* Names of the architecture-specific auditing callback functions.  */
5de29b
+#if _CALL_ELF != 2
5de29b
 #define ARCH_LA_PLTENTER ppc64_gnu_pltenter
5de29b
 #define ARCH_LA_PLTEXIT ppc64_gnu_pltexit
5de29b
+#else
5de29b
+#define ARCH_LA_PLTENTER ppc64v2_gnu_pltenter
5de29b
+#define ARCH_LA_PLTEXIT ppc64v2_gnu_pltexit
5de29b
+#endif
5de29b
 
5de29b
 #endif /* dl_machine_h */
5de29b
 
12745e
diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-trampoline.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-trampoline.S
12745e
--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-trampoline.S	2014-05-29 14:11:12.000000000 -0500
12745e
+++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-trampoline.S	2014-05-29 14:11:20.000000000 -0500
5de29b
@@ -50,11 +50,8 @@
5de29b
 /* Store the LR in the LR Save area.  */
5de29b
 	std	r0,FRAME_SIZE+FRAME_LR_SAVE(r1)
5de29b
 	cfi_offset (lr, FRAME_LR_SAVE)
5de29b
-	mfcr	r0
5de29b
 	std	r9,INT_PARMS+48(r1)
5de29b
 	std	r10,INT_PARMS+56(r1)
5de29b
-/* I'm almost certain we don't have to save cr...  be safe.  */
5de29b
-	std	r0,FRAME_SIZE+FRAME_CR_SAVE(r1)
5de29b
 	bl	JUMPTARGET(_dl_fixup)
5de29b
 #ifndef SHARED
5de29b
 	nop
5de29b
@@ -66,11 +63,9 @@
5de29b
 	ld	r8,INT_PARMS+40(r1)
5de29b
 	ld	r7,INT_PARMS+32(r1)
5de29b
 	mtlr	r0
5de29b
-	ld	r0,FRAME_SIZE+FRAME_CR_SAVE(r1)
5de29b
 	ld	r6,INT_PARMS+24(r1)
5de29b
 	ld	r5,INT_PARMS+16(r1)
5de29b
 	ld	r4,INT_PARMS+8(r1)
5de29b
-	mtcrf	0xFF,r0
5de29b
 /* Prepare for calling the function returned by fixup.  */
5de29b
 	PPC64_LOAD_FUNCPTR r3
5de29b
 	ld	r3,INT_PARMS+0(r1)
5de29b
@@ -85,18 +80,30 @@
5de29b
 #undef FRAME_SIZE
5de29b
 #undef INT_PARMS
5de29b
 
5de29b
-	/* Stack layout:
5de29b
-	   (Note: some of these are not required for the ELFv2 ABI.)
5de29b
-	  +592   previous backchain
5de29b
-	  +584   spill_r31
5de29b
-	  +576   spill_r30
5de29b
-	  +560   v1
5de29b
-	  +552   fp4
5de29b
-	  +544   fp3
5de29b
-	  +536   fp2
5de29b
-	  +528   fp1
5de29b
-	  +520   r4
5de29b
-	  +512   r3
5de29b
+	/* Stack layout:		ELFv2 ABI.
5de29b
+					+752   previous backchain
5de29b
+					+744   spill_r31
5de29b
+					+736   spill_r30
5de29b
+					+720   v8
5de29b
+					+704   v7
5de29b
+					+688   v6
5de29b
+					+672   v5
5de29b
+					+656   v4
5de29b
+					+640   v3
5de29b
+					+624   v2
5de29b
+					+608   v1
5de29b
+					+600   fp10
5de29b
+	  ELFv1 ABI			+592   fp9
5de29b
+	  +592   previous backchain	+584   fp8
5de29b
+	  +584   spill_r31		+576   fp7
5de29b
+	  +576   spill_r30		+568   fp6
5de29b
+	  +560   v1			+560   fp5
5de29b
+	  +552   fp4			+552   fp4
5de29b
+	  +544   fp3			+544   fp3
5de29b
+	  +536   fp2			+536   fp2
5de29b
+	  +528   fp1			+528   fp1
5de29b
+	  +520   r4			+520   r4
5de29b
+	  +512   r3			+512   r3
5de29b
 	   return values
5de29b
           +504   free
5de29b
 	  +496   stackframe
5de29b
@@ -157,10 +164,15 @@
5de29b
 	  +8     CR save area
5de29b
 	r1+0     stack back chain
5de29b
 	*/
5de29b
-#define FRAME_SIZE 592
5de29b
+#if _CALL_ELF == 2
5de29b
+# define FRAME_SIZE 752
5de29b
+# define VR_RTN 608
5de29b
+#else
5de29b
+# define FRAME_SIZE 592
5de29b
+# define VR_RTN 560
5de29b
+#endif
5de29b
 #define INT_RTN 512
5de29b
 #define FPR_RTN 528
5de29b
-#define VR_RTN 560
5de29b
 #define STACK_FRAME 496
5de29b
 #define CALLING_LR 488
5de29b
 #define CALLING_SP 480
5de29b
@@ -205,18 +217,14 @@
5de29b
 	mflr	r5
5de29b
 	std	r7,INT_PARMS+32(r1)
5de29b
 	std	r8,INT_PARMS+40(r1)
5de29b
-/* Store the LR in the LR Save area of the previous frame.  */
5de29b
-/* XXX Do we have to do this?  */
5de29b
+/* Store the LR in the LR Save area.  */
5de29b
 	la	r8,FRAME_SIZE(r1)
5de29b
 	std	r5,FRAME_SIZE+FRAME_LR_SAVE(r1)
5de29b
 	cfi_offset (lr, FRAME_LR_SAVE)
5de29b
 	std	r5,CALLING_LR(r1)
5de29b
-	mfcr	r0
5de29b
 	std	r9,INT_PARMS+48(r1)
5de29b
 	std	r10,INT_PARMS+56(r1)
5de29b
 	std	r8,CALLING_SP(r1)
5de29b
-/* I'm almost certain we don't have to save cr...  be safe.  */
5de29b
-	std	r0,FRAME_SIZE+FRAME_CR_SAVE(r1)
5de29b
 	ld	r12,.LC__dl_hwcap@toc(r2)
5de29b
 #ifdef SHARED
5de29b
 	/* Load _rtld_local_ro._dl_hwcap.  */
5de29b
@@ -319,11 +327,9 @@
5de29b
 	ld	r8,INT_PARMS+40(r1)
5de29b
 	ld	r7,INT_PARMS+32(r1)
5de29b
 	mtlr	r0
5de29b
-	ld	r0,FRAME_SIZE+FRAME_CR_SAVE(r1)
5de29b
 	ld	r6,INT_PARMS+24(r1)
5de29b
 	ld	r5,INT_PARMS+16(r1)
5de29b
 	ld	r4,INT_PARMS+8(r1)
5de29b
-	mtcrf	0xFF,r0
5de29b
 /* Prepare for calling the function returned by fixup.  */
5de29b
 	PPC64_LOAD_FUNCPTR r3
5de29b
 	ld	r3,INT_PARMS+0(r1)
5de29b
@@ -346,10 +352,11 @@
5de29b
 	lfd	fp12,FPR_PARMS+88(r1)
5de29b
 	lfd	fp13,FPR_PARMS+96(r1)
5de29b
 /* Unwind the stack frame, and jump.  */
5de29b
-	ld	r31,584(r1)
5de29b
-	ld	r30,576(r1)
5de29b
+	ld	r31,FRAME_SIZE-8(r1)
5de29b
+	ld	r30,FRAME_SIZE-16(r1)
5de29b
 	addi	r1,r1,FRAME_SIZE
5de29b
 	bctr
5de29b
+
5de29b
 L(do_pltexit):
5de29b
 	la	r10,(VR_PARMS+0)(r1)
5de29b
 	la	r9,(VR_PARMS+16)(r1)
5de29b
@@ -383,11 +390,9 @@
5de29b
 	ld	r8,INT_PARMS+40(r1)
5de29b
 	ld	r7,INT_PARMS+32(r1)
5de29b
 	mtlr	r0
5de29b
-	ld	r0,FRAME_SIZE+FRAME_CR_SAVE(r1)
5de29b
 	ld	r6,INT_PARMS+24(r1)
5de29b
 	ld	r5,INT_PARMS+16(r1)
5de29b
 	ld	r4,INT_PARMS+8(r1)
5de29b
-	mtcrf	0xFF,r0
5de29b
 /* Prepare for calling the function returned by fixup.  */
5de29b
 	std	r2,FRAME_TOC_SAVE(r1)
5de29b
 	PPC64_LOAD_FUNCPTR r3
5de29b
@@ -413,16 +418,37 @@
5de29b
 /* But return here and store the return values.  */
5de29b
 	std	r3,INT_RTN(r1)
5de29b
 	std	r4,INT_RTN+8(r1)
5de29b
-	stfd	fp1,FPR_PARMS+0(r1)
5de29b
-	stfd	fp2,FPR_PARMS+8(r1)
5de29b
+	stfd	fp1,FPR_RTN+0(r1)
5de29b
+	stfd	fp2,FPR_RTN+8(r1)
5de29b
 	cmpdi	cr0,r12,0
5de29b
 	la	r10,VR_RTN(r1)
5de29b
-	stfd	fp3,FPR_PARMS+16(r1)
5de29b
-	stfd	fp4,FPR_PARMS+24(r1)
5de29b
+	stfd	fp3,FPR_RTN+16(r1)
5de29b
+	stfd	fp4,FPR_RTN+24(r1)
5de29b
+#if _CALL_ELF == 2
5de29b
+	la	r12,VR_RTN+16(r1)
5de29b
+	stfd	fp5,FPR_RTN+32(r1)
5de29b
+	stfd	fp6,FPR_RTN+40(r1)
5de29b
+	li	r5,32
5de29b
+	li	r6,64
5de29b
+	stfd	fp7,FPR_RTN+48(r1)
5de29b
+	stfd	fp8,FPR_RTN+56(r1)
5de29b
+	stfd	fp9,FPR_RTN+64(r1)
5de29b
+	stfd	fp10,FPR_RTN+72(r1)
5de29b
+#endif
5de29b
 	mr	r3,r31
5de29b
 	mr	r4,r30
5de29b
 	beq	L(callpltexit)
5de29b
 	stvx	v2,0,r10
5de29b
+#if _CALL_ELF == 2
5de29b
+	stvx	v3,0,r12
5de29b
+	stvx	v4,r5,r10
5de29b
+	stvx	v5,r5,r12
5de29b
+	addi	r5,r5,64
5de29b
+	stvx	v6,r6,r10
5de29b
+	stvx	v7,r6,r12
5de29b
+	stvx	v8,r5,r10
5de29b
+	stvx	v9,r5,r12
5de29b
+#endif
5de29b
 L(callpltexit):
5de29b
 	addi	r5,r1,INT_PARMS
5de29b
 	addi	r6,r1,INT_RTN
5de29b
@@ -434,18 +460,39 @@
5de29b
 	lwz	r12,VR_VRSAVE(r1)
5de29b
 	ld	r3,INT_RTN(r1)
5de29b
 	ld	r4,INT_RTN+8(r1)
5de29b
-	lfd	fp1,FPR_PARMS+0(r1)
5de29b
-	lfd	fp2,FPR_PARMS+8(r1)
5de29b
+	lfd	fp1,FPR_RTN+0(r1)
5de29b
+	lfd	fp2,FPR_RTN+8(r1)
5de29b
 	cmpdi	cr0,r12,0
5de29b
-	la	r10,VR_RTN(r1)
5de29b
-	lfd	fp3,FPR_PARMS+16(r1)
5de29b
-	lfd	fp4,FPR_PARMS+24(r1)
5de29b
+	la	r11,VR_RTN(r1)
5de29b
+	lfd	fp3,FPR_RTN+16(r1)
5de29b
+	lfd	fp4,FPR_RTN+24(r1)
5de29b
+#if _CALL_ELF == 2
5de29b
+	la	r12,VR_RTN+16(r1)
5de29b
+	lfd	fp5,FPR_RTN+32(r1)
5de29b
+	lfd	fp6,FPR_RTN+40(r1)
5de29b
+	li	r30,32
5de29b
+	li	r31,64
5de29b
+	lfd	fp7,FPR_RTN+48(r1)
5de29b
+	lfd	fp8,FPR_RTN+56(r1)
5de29b
+	lfd	fp9,FPR_RTN+64(r1)
5de29b
+	lfd	fp10,FPR_RTN+72(r1)
5de29b
+#endif
5de29b
 	beq	L(pltexitreturn)
5de29b
-	lvx	v2,0,r10
5de29b
+	lvx	v2,0,r11
5de29b
+#if _CALL_ELF == 2
5de29b
+	lvx	v3,0,r12
5de29b
+	lvx	v4,r30,r11
5de29b
+	lvx	v5,r30,r12
5de29b
+	addi	r30,r30,64
5de29b
+	lvx	v6,r31,r11
5de29b
+	lvx	v7,r31,r12
5de29b
+	lvx	v8,r30,r11
5de29b
+	lvx	v9,r30,r12
5de29b
+#endif
5de29b
 L(pltexitreturn):
5de29b
 	ld	r0,FRAME_SIZE+FRAME_LR_SAVE(r1)
5de29b
-	ld	r31,584(r1)
5de29b
-	ld	r30,576(r1)
5de29b
+	ld	r31,FRAME_SIZE-8(r1)
5de29b
+	ld	r30,FRAME_SIZE-16(r1)
5de29b
 	mtlr	r0
5de29b
 	ld	r1,0(r1)
5de29b
 	blr
12745e
diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/tst-audit.h glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/tst-audit.h
12745e
--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/tst-audit.h	2014-05-29 14:11:12.000000000 -0500
12745e
+++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/tst-audit.h	2014-05-29 14:11:20.000000000 -0500
5de29b
@@ -18,8 +18,16 @@
5de29b
    License along with the GNU C Library.  If not, see
5de29b
    <http://www.gnu.org/licenses/>.  */
5de29b
 
5de29b
+#if _CALL_ELF != 2
5de29b
 #define pltenter la_ppc64_gnu_pltenter
5de29b
 #define pltexit la_ppc64_gnu_pltexit
5de29b
 #define La_regs La_ppc64_regs
5de29b
 #define La_retval La_ppc64_retval
5de29b
 #define int_retval lrv_r3
5de29b
+#else
5de29b
+#define pltenter la_ppc64v2_gnu_pltenter
5de29b
+#define pltexit la_ppc64v2_gnu_pltexit
5de29b
+#define La_regs La_ppc64v2_regs
5de29b
+#define La_retval La_ppc64v2_retval
5de29b
+#define int_retval lrv_r3
5de29b
+#endif