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