arrfab / rpms / glibc

Forked from rpms/glibc 4 years ago
Clone

Blame SOURCES/glibc-ppc64le-39.patch

147e83
# commit 696caf1d002ff059ddd20fd5eaccd76229c14850
147e83
# Author: Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
147e83
# Date:   Wed Dec 4 06:51:11 2013 -0600
147e83
# 
147e83
#     PowerPC64 ELFv2 ABI 2/6: Remove function descriptors
147e83
#     
147e83
#     This patch adds support for the ELFv2 ABI feature to remove function
147e83
#     descriptors.  See this GCC patch for in-depth discussion:
147e83
#     http://gcc.gnu.org/ml/gcc-patches/2013-11/msg01141.html
147e83
#     
147e83
#     This mostly involves two types of changes: updating assembler source
147e83
#     files to the new logic, and updating the dynamic loader.
147e83
#     
147e83
#     After the refactoring in the previous patch, most of the assembler source
147e83
#     changes can be handled simply by providing ELFv2 versions of the
147e83
#     macros in sysdep.h.   One somewhat non-obvious change is in __GI__setjmp:
147e83
#     this used to "fall through" to the immediately following __setjmp ENTRY
147e83
#     point.  This is no longer safe in the ELFv2 since ENTRY defines both
147e83
#     a global and a local entry point, and you cannot simply fall through
147e83
#     to a global entry point as it requires r12 to be set up.
147e83
#     
147e83
#     Also, makecontext needs to be updated to set up registers according to
147e83
#     the new ABI for calling into the context's start routine.
147e83
#     
147e83
#     The dynamic linker changes mostly consist of removing special code
147e83
#     to handle function descriptors.  We also need to support the new PLT
147e83
#     and glink format used by the the ELFv2 linker, see:
147e83
#     https://sourceware.org/ml/binutils/2013-10/msg00376.html
147e83
#     
147e83
#     In addition, the dynamic linker now verifies that the dynamic libraries
147e83
#     it loads match its own ABI.
147e83
#     
147e83
#     The hack in VDSO_IFUNC_RET to "synthesize" a function descriptor
147e83
#     for vDSO routines is also no longer necessary for ELFv2.
147e83
# 
147e83
diff -urN glibc-2.17-c758a686/elf/elf.h glibc-2.17-c758a686/elf/elf.h
147e83
--- glibc-2.17-c758a686/elf/elf.h	2014-05-29 13:58:25.000000000 -0500
147e83
+++ glibc-2.17-c758a686/elf/elf.h	2014-05-29 13:58:25.000000000 -0500
147e83
@@ -2263,6 +2263,12 @@
147e83
 #define R_PPC64_REL16_HI	251	/* half16   (sym+add-.)@h */
147e83
 #define R_PPC64_REL16_HA	252	/* half16   (sym+add-.)@ha */
147e83
 
147e83
+/* e_flags bits specifying ABI.
147e83
+   1 for original function descriptor using ABI,
147e83
+   2 for revised ABI without function descriptors,
147e83
+   0 for unspecified or not using any features affected by the differences.  */
147e83
+#define EF_PPC64_ABI	3
147e83
+
147e83
 /* PowerPC64 specific values for the Dyn d_tag field.  */
147e83
 #define DT_PPC64_GLINK  (DT_LOPROC + 0)
147e83
 #define DT_PPC64_OPD	(DT_LOPROC + 1)
147e83
diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/crti.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/crti.S
147e83
--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/crti.S	2014-05-29 13:58:25.000000000 -0500
147e83
+++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/crti.S	2014-05-29 13:58:25.000000000 -0500
147e83
@@ -64,6 +64,7 @@
147e83
 	ENTRY_2(_init)
147e83
 	.align ALIGNARG (2)
147e83
 BODY_LABEL (_init):
147e83
+	LOCALENTRY(_init)
147e83
 	mflr 0
147e83
 	std 0, 16(r1)
147e83
 	stdu r1, -112(r1)
147e83
@@ -81,6 +82,7 @@
147e83
 	ENTRY_2(_fini)
147e83
 	.align ALIGNARG (2)
147e83
 BODY_LABEL (_fini):
147e83
+	LOCALENTRY(_fini)
147e83
 	mflr 0
147e83
 	std 0, 16(r1)
147e83
 	stdu r1, -112(r1)
147e83
diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-irel.h glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-irel.h
147e83
--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-irel.h	2014-05-29 13:58:25.000000000 -0500
147e83
+++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-irel.h	2014-05-29 13:58:25.000000000 -0500
147e83
@@ -50,7 +50,11 @@
147e83
     {
147e83
       Elf64_Addr *const reloc_addr = (void *) reloc->r_offset;
147e83
       Elf64_Addr value = elf_ifunc_invoke(reloc->r_addend);
147e83
+#if _CALL_ELF != 2
147e83
       *(Elf64_FuncDesc *) reloc_addr = *(Elf64_FuncDesc *) value;
147e83
+#else
147e83
+      *reloc_addr = value;
147e83
+#endif
147e83
     }
147e83
   else
147e83
     __libc_fatal ("unexpected reloc type in static binary");
147e83
diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-machine.h glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-machine.h
147e83
--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-machine.h	2014-05-29 13:58:25.000000000 -0500
147e83
+++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-machine.h	2014-05-29 14:05:46.000000000 -0500
147e83
@@ -31,6 +31,7 @@
147e83
    in l_info array.  */
147e83
 #define DT_PPC64(x) (DT_PPC64_##x - DT_LOPROC + DT_NUM)
147e83
 
147e83
+#if _CALL_ELF != 2
147e83
 /* A PowerPC64 function descriptor.  The .plt (procedure linkage
147e83
    table) and .opd (official procedure descriptor) sections are
147e83
    arrays of these.  */
147e83
@@ -40,6 +41,7 @@
147e83
   Elf64_Addr fd_toc;
147e83
   Elf64_Addr fd_aux;
147e83
 } Elf64_FuncDesc;
147e83
+#endif
147e83
 
147e83
 #define ELF_MULT_MACHINES_SUPPORTED
147e83
 
147e83
@@ -47,6 +49,18 @@
147e83
 static inline int
147e83
 elf_machine_matches_host (const Elf64_Ehdr *ehdr)
147e83
 {
147e83
+  /* Verify that the binary matches our ABI version.  */
147e83
+  if ((ehdr->e_flags & EF_PPC64_ABI) != 0)
147e83
+    {
147e83
+#if _CALL_ELF != 2
147e83
+      if ((ehdr->e_flags & EF_PPC64_ABI) != 1)
147e83
+        return 0;
147e83
+#else
147e83
+      if ((ehdr->e_flags & EF_PPC64_ABI) != 2)
147e83
+        return 0;
147e83
+#endif
147e83
+    }
147e83
+
147e83
   return ehdr->e_machine == EM_PPC64;
147e83
 }
147e83
 
147e83
@@ -124,6 +138,7 @@
147e83
 "	.align	2\n"							\
147e83
 "	" ENTRY_2(_start) "\n"						\
147e83
 BODY_PREFIX "_start:\n"							\
147e83
+"	" LOCALENTRY(_start) "\n"						\
147e83
 /* We start with the following on the stack, from top:			\
147e83
    argc (4 bytes);							\
147e83
    arguments for program (terminated by NULL);				\
147e83
@@ -165,6 +180,7 @@
147e83
    Changing these is strongly discouraged (not least because argc is	\
147e83
    passed by value!).  */						\
147e83
 BODY_PREFIX "_dl_start_user:\n"						\
147e83
+"	" LOCALENTRY(_dl_start_user) "\n"				\
147e83
 /* the address of _start in r30.  */					\
147e83
 "	mr	30,3\n"							\
147e83
 /* &_dl_argc in 29, &_dl_argv in 27, and _dl_loaded in 28.  */		\
147e83
@@ -256,8 +272,22 @@
147e83
    relocations behave "normally", ie. always use the real address
147e83
    like PLT relocations.  So always set ELF_RTYPE_CLASS_PLT.  */
147e83
 
147e83
+#if _CALL_ELF != 2
147e83
 #define elf_machine_type_class(type) \
147e83
   (ELF_RTYPE_CLASS_PLT | (((type) == R_PPC64_COPY) * ELF_RTYPE_CLASS_COPY))
147e83
+#else
147e83
+/* And now that you have read that large comment, you can disregard it
147e83
+   all for ELFv2.  ELFv2 does need the special SHN_UNDEF treatment.  */
147e83
+#define IS_PPC64_TLS_RELOC(R)						\
147e83
+  (((R) >= R_PPC64_TLS && (R) <= R_PPC64_DTPREL16_HIGHESTA)		\
147e83
+   || ((R) >= R_PPC64_TPREL16_HIGH && (R) <= R_PPC64_DTPREL16_HIGHA))
147e83
+
147e83
+#define elf_machine_type_class(type) \
147e83
+  ((((type) == R_PPC64_JMP_SLOT					\
147e83
+     || (type) == R_PPC64_ADDR24				\
147e83
+     || IS_PPC64_TLS_RELOC (type)) * ELF_RTYPE_CLASS_PLT)	\
147e83
+   | (((type) == R_PPC64_COPY) * ELF_RTYPE_CLASS_COPY))
147e83
+#endif
147e83
 
147e83
 /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries.  */
147e83
 #define ELF_MACHINE_JMP_SLOT	R_PPC64_JMP_SLOT
147e83
@@ -266,8 +296,19 @@
147e83
 #define ELF_MACHINE_NO_REL 1
147e83
 
147e83
 /* Stuff for the PLT.  */
147e83
+#if _CALL_ELF != 2
147e83
 #define PLT_INITIAL_ENTRY_WORDS 3
147e83
+#define PLT_ENTRY_WORDS 3
147e83
 #define GLINK_INITIAL_ENTRY_WORDS 8
147e83
+/* The first 32k entries of glink can set an index and branch using two
147e83
+   instructions; past that point, glink uses three instructions.  */
147e83
+#define GLINK_ENTRY_WORDS(I) (((I) < 0x8000)? 2 : 3)
147e83
+#else
147e83
+#define PLT_INITIAL_ENTRY_WORDS 2
147e83
+#define PLT_ENTRY_WORDS 1
147e83
+#define GLINK_INITIAL_ENTRY_WORDS 8
147e83
+#define GLINK_ENTRY_WORDS(I) 1
147e83
+#endif
147e83
 
147e83
 #define PPC_DCBST(where) asm volatile ("dcbst 0,%0" : : "r"(where) : "memory")
147e83
 #define PPC_DCBT(where) asm volatile ("dcbt 0,%0" : : "r"(where) : "memory")
147e83
@@ -312,17 +353,12 @@
147e83
 
147e83
       if (lazy)
147e83
 	{
147e83
-	  /* The function descriptor of the appropriate trampline
147e83
-	     routine is used to set the 1st and 2nd doubleword of the
147e83
-	     plt_reserve.  */
147e83
-	  Elf64_FuncDesc *resolve_fd;
147e83
 	  Elf64_Word glink_offset;
147e83
-	  /* the plt_reserve area is the 1st 3 doublewords of the PLT */
147e83
-	  Elf64_FuncDesc *plt_reserve = (Elf64_FuncDesc *) plt;
147e83
 	  Elf64_Word offset;
147e83
+	  Elf64_Addr dlrr;
147e83
 
147e83
-	  resolve_fd = (Elf64_FuncDesc *) (profile ? _dl_profile_resolve
147e83
-					   : _dl_runtime_resolve);
147e83
+	  dlrr = (Elf64_Addr) (profile ? _dl_profile_resolve
147e83
+				       : _dl_runtime_resolve);
147e83
 	  if (profile && GLRO(dl_profile) != NULL
147e83
 	      && _dl_name_match_p (GLRO(dl_profile), map))
147e83
 	    /* This is the object we are looking for.  Say that we really
147e83
@@ -330,20 +366,33 @@
147e83
 	    GL(dl_profile_map) = map;
147e83
 
147e83
 
147e83
+#if _CALL_ELF != 2
147e83
 	  /* We need to stuff the address/TOC of _dl_runtime_resolve
147e83
 	     into doublewords 0 and 1 of plt_reserve.  Then we need to
147e83
 	     stuff the map address into doubleword 2 of plt_reserve.
147e83
 	     This allows the GLINK0 code to transfer control to the
147e83
 	     correct trampoline which will transfer control to fixup
147e83
 	     in dl-machine.c.  */
147e83
-	  plt_reserve->fd_func = resolve_fd->fd_func;
147e83
-	  plt_reserve->fd_toc  = resolve_fd->fd_toc;
147e83
-	  plt_reserve->fd_aux  = (Elf64_Addr) map;
147e83
+	  {
147e83
+	    /* The plt_reserve area is the 1st 3 doublewords of the PLT.  */
147e83
+	    Elf64_FuncDesc *plt_reserve = (Elf64_FuncDesc *) plt;
147e83
+	    Elf64_FuncDesc *resolve_fd = (Elf64_FuncDesc *) dlrr;
147e83
+	    plt_reserve->fd_func = resolve_fd->fd_func;
147e83
+	    plt_reserve->fd_toc  = resolve_fd->fd_toc;
147e83
+	    plt_reserve->fd_aux  = (Elf64_Addr) map;
147e83
 #ifdef RTLD_BOOTSTRAP
147e83
-	  /* When we're bootstrapping, the opd entry will not have
147e83
-	     been relocated yet.  */
147e83
-	  plt_reserve->fd_func += l_addr;
147e83
-	  plt_reserve->fd_toc  += l_addr;
147e83
+	    /* When we're bootstrapping, the opd entry will not have
147e83
+	       been relocated yet.  */
147e83
+	    plt_reserve->fd_func += l_addr;
147e83
+	    plt_reserve->fd_toc  += l_addr;
147e83
+#endif
147e83
+	  }
147e83
+#else
147e83
+	  /* When we don't have function descriptors, the first doubleword
147e83
+	     of the PLT holds the address of _dl_runtime_resolve, and the
147e83
+	     second doubleword holds the map address.  */
147e83
+	  plt[0] = dlrr;
147e83
+	  plt[1] = (Elf64_Addr) map;
147e83
 #endif
147e83
 
147e83
 	  /* Set up the lazy PLT entries.  */
147e83
@@ -354,14 +403,8 @@
147e83
 	    {
147e83
 
147e83
 	      plt[offset] = (Elf64_Xword) &glink[glink_offset];
147e83
-	      offset += 3;
147e83
-	      /* The first 32k entries of glink can set an index and
147e83
-		 branch using two instructions;  Past that point,
147e83
-		 glink uses three instructions.  */
147e83
-	      if (i < 0x8000)
147e83
-		glink_offset += 2;
147e83
-	      else
147e83
-		glink_offset += 3;
147e83
+	      offset += PLT_ENTRY_WORDS;
147e83
+	      glink_offset += GLINK_ENTRY_WORDS (i);
147e83
 	    }
147e83
 
147e83
 	  /* Now, we've modified data.  We need to write the changes from
147e83
@@ -389,6 +432,7 @@
147e83
 		       const Elf64_Rela *reloc,
147e83
 		       Elf64_Addr *reloc_addr, Elf64_Addr finaladdr)
147e83
 {
147e83
+#if _CALL_ELF != 2
147e83
   Elf64_FuncDesc *plt = (Elf64_FuncDesc *) reloc_addr;
147e83
   Elf64_FuncDesc *rel = (Elf64_FuncDesc *) finaladdr;
147e83
   Elf64_Addr offset = 0;
147e83
@@ -426,6 +470,9 @@
147e83
   plt->fd_func = rel->fd_func + offset;
147e83
   PPC_DCBST (&plt->fd_func);
147e83
   PPC_ISYNC;
147e83
+#else
147e83
+  *reloc_addr = finaladdr;
147e83
+#endif
147e83
 
147e83
   return finaladdr;
147e83
 }
147e83
@@ -433,6 +480,7 @@
147e83
 static inline void __attribute__ ((always_inline))
147e83
 elf_machine_plt_conflict (Elf64_Addr *reloc_addr, Elf64_Addr finaladdr)
147e83
 {
147e83
+#if _CALL_ELF != 2
147e83
   Elf64_FuncDesc *plt = (Elf64_FuncDesc *) reloc_addr;
147e83
   Elf64_FuncDesc *rel = (Elf64_FuncDesc *) finaladdr;
147e83
 
147e83
@@ -443,6 +491,9 @@
147e83
   PPC_DCBST (&plt->fd_aux);
147e83
   PPC_DCBST (&plt->fd_toc);
147e83
   PPC_SYNC;
147e83
+#else
147e83
+  *reloc_addr = finaladdr;
147e83
+#endif
147e83
 }
147e83
 
147e83
 /* Return the final value of a plt relocation.  */
147e83
@@ -512,6 +563,7 @@
147e83
 resolve_ifunc (Elf64_Addr value,
147e83
 	       const struct link_map *map, const struct link_map *sym_map)
147e83
 {
147e83
+#if _CALL_ELF != 2
147e83
 #ifndef RESOLVE_CONFLICT_FIND_MAP
147e83
   /* The function we are calling may not yet have its opd entry relocated.  */
147e83
   Elf64_FuncDesc opd;
147e83
@@ -529,6 +581,7 @@
147e83
       value = (Elf64_Addr) &opd;
147e83
     }
147e83
 #endif
147e83
+#endif
147e83
   return ((Elf64_Addr (*) (unsigned long int)) value) (GLRO(dl_hwcap));
147e83
 }
147e83
 
147e83
diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/setjmp-common.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/setjmp-common.S
147e83
--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/setjmp-common.S	2014-05-29 13:58:25.000000000 -0500
147e83
+++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/setjmp-common.S	2014-05-29 14:00:27.000000000 -0500
147e83
@@ -55,21 +55,22 @@
147e83
    that saves r2 since the call won't go via a plt call stub.  See
147e83
    bugz #269.  __GI__setjmp is used in csu/libc-start.c when
147e83
    HAVE_CLEANUP_JMP_BUF is defined.  */
147e83
-ENTRY (BP_SYM (__GI__setjmp))
147e83
+ENTRY (__GI__setjmp)
147e83
 	std r2,40(r1)		/* Save the callers TOC in the save area.  */
147e83
-	cfi_endproc
147e83
-END_2 (BP_SYM (__GI__setjmp))
147e83
-/* Fall thru. */
147e83
+	CALL_MCOUNT 1
147e83
+	li r4,0			/* Set second argument to 0.  */
147e83
+	b JUMPTARGET (GLUE(__sigsetjmp,_ent))
147e83
+END (__GI__setjmp)
147e83
 #endif
147e83
 
147e83
-ENTRY (BP_SYM (_setjmp))
147e83
+ENTRY (_setjmp)
147e83
 	CALL_MCOUNT 1
147e83
 	li r4,0			/* Set second argument to 0.  */
147e83
 	b JUMPTARGET (GLUE(__sigsetjmp,_ent))
147e83
-END (BP_SYM (_setjmp))
147e83
+END (_setjmp)
147e83
 libc_hidden_def (_setjmp)
147e83
 
147e83
-ENTRY (BP_SYM (__sigsetjmp))
147e83
+ENTRY (__sigsetjmp)
147e83
 	CALL_MCOUNT 2
147e83
 JUMPTARGET(GLUE(__sigsetjmp,_ent)):
147e83
 	CHECK_BOUNDS_BOTH_WIDE_LIT (r3, r8, r9, JB_SIZE)
147e83
@@ -215,18 +216,18 @@
147e83
 	li	r3,0
147e83
 	blr
147e83
 #elif defined SHARED
147e83
-	b	JUMPTARGET (BP_SYM (__sigjmp_save))
147e83
+	b	JUMPTARGET (__sigjmp_save)
147e83
 #else
147e83
 	mflr	r0
147e83
 	std	r0,16(r1)
147e83
 	stdu	r1,-112(r1)
147e83
 	cfi_adjust_cfa_offset(112)
147e83
 	cfi_offset(lr,16)
147e83
-	bl	JUMPTARGET (BP_SYM (__sigjmp_save))
147e83
+	bl	JUMPTARGET (__sigjmp_save)
147e83
 	nop
147e83
 	ld	r0,112+16(r1)
147e83
 	addi	r1,r1,112
147e83
 	mtlr	r0
147e83
 	blr
147e83
 #endif
147e83
-END (BP_SYM (__sigsetjmp))
147e83
+END (__sigsetjmp)
147e83
diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/sysdep.h glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/sysdep.h
147e83
--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/sysdep.h	2014-05-29 13:58:25.000000000 -0500
147e83
+++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/sysdep.h	2014-05-29 13:58:25.000000000 -0500
147e83
@@ -74,6 +74,8 @@
147e83
 #endif
147e83
 	.endm
147e83
 
147e83
+#if _CALL_ELF != 2
147e83
+
147e83
 /* Macro to prepare for calling via a function pointer.  */
147e83
 	.macro PPC64_LOAD_FUNCPTR PTR
147e83
 	ld      r12,0(\PTR)
147e83
@@ -115,13 +117,37 @@
147e83
 	.size name,.-BODY_LABEL(name);		\
147e83
 	.size BODY_LABEL(name),.-BODY_LABEL(name);
147e83
 #endif
147e83
+#define LOCALENTRY(name)
147e83
+
147e83
+#else /* _CALL_ELF */
147e83
+
147e83
+/* Macro to prepare for calling via a function pointer.  */
147e83
+	.macro PPC64_LOAD_FUNCPTR PTR
147e83
+	mr	r12,\PTR
147e83
+	mtctr   r12
147e83
+	.endm
147e83
+
147e83
+#define DOT_LABEL(X) X
147e83
+#define BODY_LABEL(X) X
147e83
+#define ENTRY_2(name)	\
147e83
+	.globl name;				\
147e83
+	.type name,@function;
147e83
+#define END_2(name)	\
147e83
+	.size name,.-name;
147e83
+#define LOCALENTRY(name)	\
147e83
+1:      addis	r2,r12,.TOC.-1b@ha; \
147e83
+        addi	r2,r2,.TOC.-1b@l; \
147e83
+	.localentry name,.-name;
147e83
+
147e83
+#endif /* _CALL_ELF */
147e83
 
147e83
 #define ENTRY(name)	\
147e83
 	.section	".text";		\
147e83
 	ENTRY_2(name)				\
147e83
 	.align ALIGNARG(2);			\
147e83
 BODY_LABEL(name):				\
147e83
-	cfi_startproc;
147e83
+	cfi_startproc;				\
147e83
+	LOCALENTRY(name)
147e83
 
147e83
 #define EALIGN_W_0  /* No words to insert.  */
147e83
 #define EALIGN_W_1  nop
147e83
@@ -140,7 +166,8 @@
147e83
 	.align ALIGNARG(alignt);		\
147e83
 	EALIGN_W_##words;			\
147e83
 BODY_LABEL(name):				\
147e83
-	cfi_startproc;
147e83
+	cfi_startproc;				\
147e83
+	LOCALENTRY(name)
147e83
 
147e83
 /* Local labels stripped out by the linker.  */
147e83
 #undef L
147e83
@@ -295,6 +322,8 @@
147e83
 
147e83
 #else /* !__ASSEMBLER__ */
147e83
 
147e83
+#if _CALL_ELF != 2
147e83
+
147e83
 #define PPC64_LOAD_FUNCPTR(ptr) \
147e83
 	"ld 	12,0(" #ptr ");\n"					\
147e83
 	"ld	2,8(" #ptr ");\n"					\
147e83
@@ -335,5 +364,26 @@
147e83
 	".size " #name ",.-" BODY_PREFIX #name ";\n"			\
147e83
 	".size " BODY_PREFIX #name ",.-" BODY_PREFIX #name ";"
147e83
 #endif
147e83
+#define LOCALENTRY(name)
147e83
+
147e83
+#else /* _CALL_ELF */
147e83
+
147e83
+#define PPC64_LOAD_FUNCPTR(ptr) \
147e83
+	"mr	12," #ptr ";\n"						\
147e83
+	"mtctr 	12;"
147e83
+
147e83
+#define DOT_PREFIX ""
147e83
+#define BODY_PREFIX ""
147e83
+#define ENTRY_2(name)	\
147e83
+	".type " #name ",@function;\n"					\
147e83
+	".globl " #name ";"
147e83
+#define END_2(name)	\
147e83
+	".size " #name ",.-" #name ";"
147e83
+#define LOCALENTRY(name)	\
147e83
+	"1: addis 2,12,.TOC.-1b@ha;\n"					\
147e83
+	"addi	2,2,.TOC.-1b@l;\n"					\
147e83
+	".localentry " #name ",.-" #name ";"
147e83
+
147e83
+#endif /* _CALL_ELF */
147e83
 
147e83
 #endif	/* __ASSEMBLER__ */
147e83
diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/ldsodefs.h glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/ldsodefs.h
147e83
--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/ldsodefs.h	2014-05-29 13:58:24.000000000 -0500
147e83
+++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/ldsodefs.h	2014-05-29 13:58:25.000000000 -0500
147e83
@@ -23,6 +23,8 @@
147e83
 
147e83
 /* Now define our stuff.  */
147e83
 
147e83
+#if _CALL_ELF != 2
147e83
+
147e83
 static __always_inline bool
147e83
 _dl_ppc64_is_opd_sym (const struct link_map *l, const ElfW(Sym) *sym)
147e83
 {
147e83
@@ -73,4 +75,6 @@
147e83
 #define DL_ADDR_SYM_MATCH(L, SYM, MATCHSYM, ADDR) \
147e83
   _dl_ppc64_addr_sym_match (L, SYM, MATCHSYM, ADDR)
147e83
 
147e83
+#endif
147e83
+
147e83
 #endif /* ldsodefs.h */
147e83
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
147e83
--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S	2014-05-29 13:58:24.000000000 -0500
147e83
+++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S	2014-05-29 13:58:25.000000000 -0500
147e83
@@ -111,6 +111,7 @@
147e83
 
147e83
 L(noparms):
147e83
 
147e83
+#if _CALL_ELF != 2
147e83
   /* Load the function address and TOC from the function descriptor
147e83
      and store them in the ucontext as NIP and r2.  Store the 3rd
147e83
      field of the function descriptor into the ucontext as r11 in case
147e83
@@ -121,6 +122,12 @@
147e83
   std   r0,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r3)
147e83
   std   r10,(SIGCONTEXT_GP_REGS+(PT_R2*8))(r3)
147e83
   std   r9,(SIGCONTEXT_GP_REGS+(PT_R11*8))(r3)
147e83
+#else
147e83
+  /* In the ELFv2 ABI, the function pointer is already the address.
147e83
+     Store it as NIP and r12 as required by the ABI.  */
147e83
+  std   r4,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r3)
147e83
+  std   r4,(SIGCONTEXT_GP_REGS+(PT_R12*8))(r3)
147e83
+#endif
147e83
 
147e83
   /* If the target function returns we need to do some cleanup.  We use a
147e83
      code trick to get the address of our cleanup function into the link