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