Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 3 Dec 2015 00:10:57 +0000 (UTC)
From:      Nathan Whitehorn <nwhitehorn@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r291668 - in head: lib/csu/powerpc64 libexec/rtld-elf libexec/rtld-elf/powerpc64 sys/powerpc/include sys/powerpc/powerpc
Message-ID:  <201512030010.tB30AvNc077043@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: nwhitehorn
Date: Thu Dec  3 00:10:57 2015
New Revision: 291668
URL: https://svnweb.freebsd.org/changeset/base/291668

Log:
  Provide support for ELFv2 userland if using a newer compiler (recent clang
  or gcc) and binutils >= 2.24. Not enabled by default.

Modified:
  head/lib/csu/powerpc64/crti.S
  head/libexec/rtld-elf/powerpc64/reloc.c
  head/libexec/rtld-elf/powerpc64/rtld_start.S
  head/libexec/rtld-elf/rtld.c
  head/libexec/rtld-elf/rtld.h
  head/sys/powerpc/include/asm.h
  head/sys/powerpc/powerpc/sigcode64.S

Modified: head/lib/csu/powerpc64/crti.S
==============================================================================
--- head/lib/csu/powerpc64/crti.S	Thu Dec  3 00:08:50 2015	(r291667)
+++ head/lib/csu/powerpc64/crti.S	Thu Dec  3 00:10:57 2015	(r291668)
@@ -26,34 +26,59 @@
 #include <machine/asm.h>
 __FBSDID("$FreeBSD$");
 
+#ifdef _CALL_ELF
+.abiversion _CALL_ELF
+#endif
+
 	.section .init,"ax",@progbits
-	.align	2
+	.p2align	2
 	.globl	_init
+#if !defined(_CALL_ELF) || _CALL_ELF == 1
 	.section ".opd","aw"
-	.align	3
+	.p2align	3
 _init:
 	.quad	.L._init,.TOC.@tocbase,0
 	.previous
 	.type	_init,@function
 
-	.align 4
+	.p2align 4
 .L._init:
+#else
+	.p2align 4
+	.globl	_init
+	.type	_init,@function
+_init:
+	addis	%r2, %r12, (.TOC.-_init)@ha
+	addi	%r2, %r2, (.TOC.-_init)@l
+	.localentry _init, .-_init
+#endif
 	stdu 1,-48(1)
 	mflr 0
 	std 0,64(1)
 
+/* Fini */
 	.section .fini,"ax",@progbits
-	.align	2
+	.p2align	2
 	.globl	_fini
+#if !defined(_CALL_ELF) || _CALL_ELF == 1
 	.section ".opd","aw"
-	.align	3
+	.p2align	3
 _fini:
 	.quad	.L._fini,.TOC.@tocbase,0
 	.previous
 	.type	_fini,@function
 
-	.align 4
+	.p2align 4
 .L._fini:
+#else
+	.p2align 4
+	.globl	_fini
+	.type	_fini,@function
+_fini:
+	addis	%r2, %r12, (.TOC.-_fini)@ha
+	addi	%r2, %r2, (.TOC.-_fini)@l
+	.localentry _fini, .-_fini
+#endif
 	stdu 1,-48(1)
 	mflr 0
 	std 0,64(1)

Modified: head/libexec/rtld-elf/powerpc64/reloc.c
==============================================================================
--- head/libexec/rtld-elf/powerpc64/reloc.c	Thu Dec  3 00:08:50 2015	(r291667)
+++ head/libexec/rtld-elf/powerpc64/reloc.c	Thu Dec  3 00:10:57 2015	(r291668)
@@ -43,11 +43,13 @@
 #include "debug.h"
 #include "rtld.h"
 
+#if !defined(_CALL_ELF) || _CALL_ELF == 1
 struct funcdesc {
 	Elf_Addr addr;
 	Elf_Addr toc;
 	Elf_Addr env;
 };
+#endif
 
 /*
  * Process the R_PPC_COPY relocations
@@ -336,11 +338,14 @@ static int
 reloc_plt_object(Obj_Entry *obj, const Elf_Rela *rela)
 {
 	Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+#if !defined(_CALL_ELF) || _CALL_ELF == 1
 	Elf_Addr *glink;
+#endif
 	long reloff;
 
 	reloff = rela - obj->pltrela;
 
+#if !defined(_CALL_ELF) || _CALL_ELF == 1
 	if (obj->priv == NULL)
 		obj->priv = xmalloc(obj->pltrelasize);
 	glink = obj->priv + reloff*sizeof(Elf_Addr)*2;
@@ -351,6 +356,10 @@ reloc_plt_object(Obj_Entry *obj, const E
 	((struct funcdesc *)(where))->env = (Elf_Addr)glink;
 	*(glink++) = (Elf_Addr)obj;
 	*(glink++) = reloff*sizeof(Elf_Rela);
+#else
+	dbg(" reloc_plt_object: where=%p,reloff=%lx,glink=%#lx", (void *)where, reloff, obj->glink);
+	*where = (Elf_Addr)obj->glink + 4*reloff + 32;
+#endif
 
 	return (0);
 }
@@ -416,7 +425,11 @@ reloc_jmpslots(Obj_Entry *obj, int flags
 
 		if (def == &sym_zero) {
 			/* Zero undefined weak symbols */
+#if !defined(_CALL_ELF) || _CALL_ELF == 1
 			bzero(where, sizeof(struct funcdesc));
+#else
+			*where = 0;
+#endif
 		} else {
 			reloc_jmpslot(where, target, defobj, obj,
 			    (const Elf_Rel *) rela);
@@ -436,9 +449,6 @@ Elf_Addr
 reloc_jmpslot(Elf_Addr *wherep, Elf_Addr target, const Obj_Entry *defobj,
 	      const Obj_Entry *obj, const Elf_Rel *rel)
 {
-	dbg(" reloc_jmpslot: where=%p, target=%p (%#lx + %#lx)",
-	    (void *)wherep, (void *)target, *(Elf_Addr *)target,
-	    (Elf_Addr)defobj->relocbase);
 
 	/*
 	 * At the PLT entry pointed at by `wherep', construct
@@ -446,6 +456,11 @@ reloc_jmpslot(Elf_Addr *wherep, Elf_Addr
 	 * address.
 	 */
 
+#if !defined(_CALL_ELF) || _CALL_ELF == 1
+	dbg(" reloc_jmpslot: where=%p, target=%p (%#lx + %#lx)",
+	    (void *)wherep, (void *)target, *(Elf_Addr *)target,
+	    (Elf_Addr)defobj->relocbase);
+
 	memcpy(wherep, (void *)target, sizeof(struct funcdesc));
 	if (((struct funcdesc *)(wherep))->addr < (Elf_Addr)defobj->relocbase) {
 		/*
@@ -459,8 +474,14 @@ reloc_jmpslot(Elf_Addr *wherep, Elf_Addr
 		((struct funcdesc *)(wherep))->toc +=
 		    (Elf_Addr)defobj->relocbase;
 	}
+#else
+	dbg(" reloc_jmpslot: where=%p, target=%p", (void *)wherep,
+	    (void *)target);
+
+	*wherep = target;
+#endif
 
-	__asm __volatile("dcbst 0,%0; sync" :: "r"(wherep) : "memory");
+	__asm __volatile("sync" ::: "memory");
 
 	return (target);
 }
@@ -485,6 +506,20 @@ reloc_gnu_ifunc(Obj_Entry *obj, int flag
 void
 init_pltgot(Obj_Entry *obj)
 {
+#if defined(_CALL_ELF) && _CALL_ELF == 2
+	Elf_Addr *pltcall;
+
+	pltcall = obj->pltgot;
+
+	if (pltcall == NULL) {
+		return;
+	}
+
+	pltcall[0] = (Elf_Addr)&_rtld_bind_start; 
+	pltcall[1] = (Elf_Addr)obj;
+
+	__asm __volatile("sync" ::: "memory");
+#endif
 }
 
 void

Modified: head/libexec/rtld-elf/powerpc64/rtld_start.S
==============================================================================
--- head/libexec/rtld-elf/powerpc64/rtld_start.S	Thu Dec  3 00:08:50 2015	(r291667)
+++ head/libexec/rtld-elf/powerpc64/rtld_start.S	Thu Dec  3 00:10:57 2015	(r291668)
@@ -82,9 +82,13 @@ _ENTRY(_rtld_start)
 
 	bl      _rtld		/* &_start = _rtld(sp, &exit_proc, &obj_main)*/
 	nop
+#if !defined(_CALL_ELF) || _CALL_ELF == 1
 	ld	%r2,8(%r3)
 	ld	%r11,16(%r3)
 	ld	%r3,0(%r3)
+#else
+	mr	%r12,%r3
+#endif
 	mtlr    %r3
 
 	/*
@@ -106,7 +110,11 @@ _ENTRY(_rtld_start)
  * _rtld_bind_start()
  *
  * Call into the MI binder. This routine is reached via the PLT call cell
- * On entry, %r11 contains a pointer to the (object, relocation) tuple.
+ *
+ * For ELFv1, on entry, %r11 contains a pointer to the (object, relocation)
+ * tuple.
+ *
+ * For ELFv2, %r11 contains an object pointer and %r0 contains the PLT index.
  *
  * Save all registers, call into the binder to resolve and fixup the external
  * routine, and then transfer to the external routine on return.
@@ -114,6 +122,7 @@ _ENTRY(_rtld_start)
 	.globl  _rtld_bind
 
 _ENTRY(_rtld_bind_start)
+	mr	%r12,%r0		# shunt r0 immediately to r12 for ELFv2
 	mflr    %r0
 	std     %r0,16(%r1)		# save lr
 	mfcr    %r0
@@ -121,7 +130,7 @@ _ENTRY(_rtld_bind_start)
 
 	stdu    %r1,-48-12*8(%r1)	# stack space for 8 regs + header
 					#   + 2 save regs
-	std	%r3,64+0*8(%r1)		# save r3-r31
+	std	%r3,64+0*8(%r1)		# save r3-r10 (arguments)
 	std	%r4,64+1*8(%r1)
 	std	%r5,64+2*8(%r1)
 	std	%r6,64+3*8(%r1)
@@ -129,19 +138,27 @@ _ENTRY(_rtld_bind_start)
 	std	%r8,64+5*8(%r1)
 	std	%r9,64+6*8(%r1)
 	std	%r10,64+7*8(%r1)
-	std	%r12,64+8*8(%r1)
 
+#if !defined(_CALL_ELF) || _CALL_ELF == 1
 	ld	%r3,0(%r11)
 	ld	%r4,8(%r11)
+#else
+	mr	%r3,%r11
+	mulli	%r4,%r12,24		/* Multiply index by sizeof(Elf_Rela) */
+#endif
 	bl      _rtld_bind		# target addr = _rtld_bind(obj, reloff)
 	nop
 
+#if !defined(_CALL_ELF) || _CALL_ELF == 1
 	ld	%r2,8(%r3)
 	ld	%r11,16(%r3)
 	ld	%r3,0(%r3)
+#else 
+	mr	%r12,%r3
+#endif
 	mtctr   %r3			# move absolute target addr into ctr
 
-	ld	%r3,64+0*8(%r1)		# restore r3-r31
+	ld	%r3,64+0*8(%r1)		# restore r3-r10
 	ld	%r4,64+1*8(%r1)
 	ld	%r5,64+2*8(%r1)
 	ld	%r6,64+3*8(%r1)
@@ -149,7 +166,6 @@ _ENTRY(_rtld_bind_start)
 	ld	%r8,64+5*8(%r1)
 	ld	%r9,64+6*8(%r1)
 	ld	%r10,64+7*8(%r1)
-	ld	%r12,64+8*8(%r1)
 
 	ld	%r1,0(%r1)		# restore stack
 	ld	%r0,8(%r1)		# restore cr

Modified: head/libexec/rtld-elf/rtld.c
==============================================================================
--- head/libexec/rtld-elf/rtld.c	Thu Dec  3 00:08:50 2015	(r291667)
+++ head/libexec/rtld-elf/rtld.c	Thu Dec  3 00:10:57 2015	(r291668)
@@ -1148,7 +1148,7 @@ digest_dynamic1(Obj_Entry *obj, int earl
 #ifdef __mips__
 	case DT_MIPS_LOCAL_GOTNO:
 		obj->local_gotno = dynp->d_un.d_val;
-	    break;
+		break;
 
 	case DT_MIPS_SYMTABNO:
 		obj->symtabno = dynp->d_un.d_val;
@@ -1163,6 +1163,12 @@ digest_dynamic1(Obj_Entry *obj, int earl
 		break;
 #endif
 
+#ifdef __powerpc64__
+	case DT_PPC64_GLINK:
+		obj->glink = (Elf_Addr) (obj->relocbase + dynp->d_un.d_ptr);
+		break;
+#endif
+
 	case DT_FLAGS_1:
 		if (dynp->d_un.d_val & DF_1_NOOPEN)
 		    obj->z_noopen = true;

Modified: head/libexec/rtld-elf/rtld.h
==============================================================================
--- head/libexec/rtld-elf/rtld.h	Thu Dec  3 00:08:50 2015	(r291667)
+++ head/libexec/rtld-elf/rtld.h	Thu Dec  3 00:10:57 2015	(r291668)
@@ -187,6 +187,9 @@ typedef struct Struct_Obj_Entry {
     Elf_Word symtabno;		/* Number of dynamic symbols */
     Elf_Word gotsym;		/* First dynamic symbol in GOT */
 #endif
+#ifdef __powerpc64__
+    Elf_Addr glink;		/* GLINK PLT call stub section */
+#endif
 
     const Elf_Verneed *verneed; /* Required versions. */
     Elf_Word verneednum;	/* Number of entries in verneed table */

Modified: head/sys/powerpc/include/asm.h
==============================================================================
--- head/sys/powerpc/include/asm.h	Thu Dec  3 00:08:50 2015	(r291667)
+++ head/sys/powerpc/include/asm.h	Thu Dec  3 00:10:57 2015	(r291668)
@@ -61,17 +61,26 @@
 #define	HIDENAME(asmsym)	__CONCAT(.,asmsym)
 #endif
 
+#if !defined(_CALL_ELF) || _CALL_ELF == 1
 #ifdef _KERNEL
+/* ELFv1 kernel uses global dot symbols */
 #define	DOT_LABEL(name)		__CONCAT(.,name)
 #define	TYPE_ENTRY(name)	.size	name,24; \
 				.type	DOT_LABEL(name),@function; \
 				.globl	DOT_LABEL(name);
 #define	END_SIZE(name)		.size	DOT_LABEL(name),.-DOT_LABEL(name);
 #else /* !_KERNEL */
+/* ELFv1 user code uses local function entry points */
 #define	DOT_LABEL(name)		__CONCAT(.L.,name)
 #define	TYPE_ENTRY(name)	.type	name,@function;
 #define	END_SIZE(name)		.size	name,.-DOT_LABEL(name);
 #endif /* _KERNEL */
+#else
+/* ELFv2 doesn't have any of this complication */
+#define	DOT_LABEL(name)		name
+#define	TYPE_ENTRY(name)	.type	name,@function;
+#define	END_SIZE(name)		.size	name,.-DOT_LABEL(name);
+#endif
 
 #define	_GLOBAL(name) \
 	.data; \

Modified: head/sys/powerpc/powerpc/sigcode64.S
==============================================================================
--- head/sys/powerpc/powerpc/sigcode64.S	Thu Dec  3 00:08:50 2015	(r291667)
+++ head/sys/powerpc/powerpc/sigcode64.S	Thu Dec  3 00:10:57 2015	(r291668)
@@ -57,6 +57,7 @@ CNAME(sigcode64):
 
 CNAME(sigcode64_elfv2):
 	addi	1,1,-112		/* reserved space for callee */
+	mflr	12			/* ELFv2 wants the address in r12 */
 	blrl
 
 	addi	3,1,112+SF_UC		/* restore sp, and get &frame->sf_uc */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201512030010.tB30AvNc077043>