svn commit: r291211 - in head/sys/powerpc: include powerpc

Nathan Whitehorn nwhitehorn at FreeBSD.org
Mon Nov 23 17:07:53 UTC 2015


Author: nwhitehorn
Date: Mon Nov 23 17:07:51 2015
New Revision: 291211
URL: https://svnweb.freebsd.org/changeset/base/291211

Log:
  Provide support for userland binaries using the new ELFv2 ABI. This is a
  new, simplified, ELF ABI that avoids some of the stranger aspects of the
  existing 64-bit PowerPC ABI (function descriptors, in particular). Actually
  generating such executables requires a new version of binutils and a newer
  compiler (either GCC or clang) than GCC 4.2.1.

Modified:
  head/sys/powerpc/include/asm.h
  head/sys/powerpc/include/md_var.h
  head/sys/powerpc/include/profile.h
  head/sys/powerpc/powerpc/elf64_machdep.c
  head/sys/powerpc/powerpc/exec_machdep.c
  head/sys/powerpc/powerpc/sigcode64.S

Modified: head/sys/powerpc/include/asm.h
==============================================================================
--- head/sys/powerpc/include/asm.h	Mon Nov 23 17:05:28 2015	(r291210)
+++ head/sys/powerpc/include/asm.h	Mon Nov 23 17:07:51 2015	(r291211)
@@ -85,7 +85,9 @@
 	.section ".toc","aw"; \
 	TOC_REF(name): \
         .tc name[TC],name
+#endif
 
+#if defined(__powerpc64__) && (!defined(_CALL_ELF) || _CALL_ELF == 1)
 #define	_ENTRY(name) \
 	.section ".text"; \
 	.p2align 2; \

Modified: head/sys/powerpc/include/md_var.h
==============================================================================
--- head/sys/powerpc/include/md_var.h	Mon Nov 23 17:05:28 2015	(r291210)
+++ head/sys/powerpc/include/md_var.h	Mon Nov 23 17:07:51 2015	(r291211)
@@ -37,8 +37,8 @@ extern	char	sigcode32[];
 extern	int	szsigcode32;
 
 #ifdef __powerpc64__
-extern	char	sigcode64[];
-extern	int	szsigcode64;
+extern	char	sigcode64[], sigcode64_elfv2[];
+extern	int	szsigcode64, szsigcode64_elfv2;
 #endif
 
 extern	long	Maxmem;

Modified: head/sys/powerpc/include/profile.h
==============================================================================
--- head/sys/powerpc/include/profile.h	Mon Nov 23 17:05:28 2015	(r291210)
+++ head/sys/powerpc/include/profile.h	Mon Nov 23 17:07:51 2015	(r291211)
@@ -75,9 +75,10 @@ typedef __ptrdiff_t	fptrdiff_t;
  * to be restored to what it was on entry to the profiled routine.
  */
 
-#ifdef __powerpc64__
-#define	MCOUNT					\
-__asm(	"	.text				\n" \
+#if defined(__powerpc64__)
+
+#if !defined(_CALL_ELF) || _CALL_ELF == 1
+#define MCOUNT_PREAMBLE \
 	"	.align	2			\n" \
 	"	.globl	_mcount			\n" \
 	"	.section \".opd\",\"aw\"	\n" \
@@ -88,7 +89,17 @@ __asm(	"	.text				\n" \
 	"	.size   _mcount,24		\n" \
 	"	.type	_mcount, at function	\n" \
 	"	.align	4			\n" \
-	".L._mcount:				\n" \
+	".L._mcount:				\n" 
+#else
+#define MCOUNT_PREAMBLE \
+	"	.globl	_mcount			\n" \
+	"	.type	_mcount, at function	\n" \
+	"	.align	4			\n" \
+	"_mcount:				\n"
+#endif
+
+#define	MCOUNT					\
+__asm(	MCOUNT_PREAMBLE \
 	"	stdu	%r1,-(288+128)(%r1)	\n" \
 	"	std	%r3,48(%r1)		\n" \
 	"	std	%r4,56(%r1)		\n" \

Modified: head/sys/powerpc/powerpc/elf64_machdep.c
==============================================================================
--- head/sys/powerpc/powerpc/elf64_machdep.c	Mon Nov 23 17:05:28 2015	(r291210)
+++ head/sys/powerpc/powerpc/elf64_machdep.c	Mon Nov 23 17:07:51 2015	(r291211)
@@ -49,7 +49,10 @@
 #include <machine/elf.h>
 #include <machine/md_var.h>
 
-struct sysentvec elf64_freebsd_sysvec = {
+static void exec_setregs_funcdesc(struct thread *td, struct image_params *imgp,
+    u_long stack);
+
+struct sysentvec elf64_freebsd_sysvec_v1 = {
 	.sv_size	= SYS_MAXSYSCALL,
 	.sv_table	= sysent,
 	.sv_mask	= 0,
@@ -74,6 +77,45 @@ struct sysentvec elf64_freebsd_sysvec = 
 	.sv_psstrings	= PS_STRINGS,
 	.sv_stackprot	= VM_PROT_ALL,
 	.sv_copyout_strings = exec_copyout_strings,
+	.sv_setregs	= exec_setregs_funcdesc,
+	.sv_fixlimit	= NULL,
+	.sv_maxssiz	= NULL,
+	.sv_flags	= SV_ABI_FREEBSD | SV_LP64 | SV_SHP,
+	.sv_set_syscall_retval = cpu_set_syscall_retval,
+	.sv_fetch_syscall_args = cpu_fetch_syscall_args,
+	.sv_syscallnames = syscallnames,
+	.sv_shared_page_base = SHAREDPAGE,
+	.sv_shared_page_len = PAGE_SIZE,
+	.sv_schedtail	= NULL,
+	.sv_thread_detach = NULL,
+};
+INIT_SYSENTVEC(elf64_sysvec_v1, &elf64_freebsd_sysvec_v1);
+
+struct sysentvec elf64_freebsd_sysvec_v2 = {
+	.sv_size	= SYS_MAXSYSCALL,
+	.sv_table	= sysent,
+	.sv_mask	= 0,
+	.sv_sigsize	= 0,
+	.sv_sigtbl	= NULL,
+	.sv_errsize	= 0,
+	.sv_errtbl	= NULL,
+	.sv_transtrap	= NULL,
+	.sv_fixup	= __elfN(freebsd_fixup),
+	.sv_sendsig	= sendsig,
+	.sv_sigcode	= sigcode64_elfv2,
+	.sv_szsigcode	= &szsigcode64_elfv2,
+	.sv_prepsyscall	= NULL,
+	.sv_name	= "FreeBSD ELF64 V2",
+	.sv_coredump	= __elfN(coredump),
+	.sv_imgact_try	= NULL,
+	.sv_minsigstksz	= MINSIGSTKSZ,
+	.sv_pagesize	= PAGE_SIZE,
+	.sv_minuser	= VM_MIN_ADDRESS,
+	.sv_maxuser	= VM_MAXUSER_ADDRESS,
+	.sv_usrstack	= USRSTACK,
+	.sv_psstrings	= PS_STRINGS,
+	.sv_stackprot	= VM_PROT_ALL,
+	.sv_copyout_strings = exec_copyout_strings,
 	.sv_setregs	= exec_setregs,
 	.sv_fixlimit	= NULL,
 	.sv_maxssiz	= NULL,
@@ -86,23 +128,44 @@ struct sysentvec elf64_freebsd_sysvec = 
 	.sv_schedtail	= NULL,
 	.sv_thread_detach = NULL,
 };
-INIT_SYSENTVEC(elf64_sysvec, &elf64_freebsd_sysvec);
+INIT_SYSENTVEC(elf64_sysvec_v2, &elf64_freebsd_sysvec_v2);
+
+static boolean_t ppc64_elfv1_header_match(struct image_params *params);
+static boolean_t ppc64_elfv2_header_match(struct image_params *params);
+
+static Elf64_Brandinfo freebsd_brand_info_elfv1 = {
+	.brand		= ELFOSABI_FREEBSD,
+	.machine	= EM_PPC64,
+	.compat_3_brand	= "FreeBSD",
+	.emul_path	= NULL,
+	.interp_path	= "/libexec/ld-elf.so.1",
+	.sysvec		= &elf64_freebsd_sysvec_v1,
+	.interp_newpath	= NULL,
+	.brand_note	= &elf64_freebsd_brandnote,
+	.flags		= BI_CAN_EXEC_DYN | BI_BRAND_NOTE,
+	.header_supported = &ppc64_elfv1_header_match
+};
+
+SYSINIT(elf64v1, SI_SUB_EXEC, SI_ORDER_ANY,
+    (sysinit_cfunc_t) elf64_insert_brand_entry,
+    &freebsd_brand_info_elfv1);
 
-static Elf64_Brandinfo freebsd_brand_info = {
+static Elf64_Brandinfo freebsd_brand_info_elfv2 = {
 	.brand		= ELFOSABI_FREEBSD,
 	.machine	= EM_PPC64,
 	.compat_3_brand	= "FreeBSD",
 	.emul_path	= NULL,
 	.interp_path	= "/libexec/ld-elf.so.1",
-	.sysvec		= &elf64_freebsd_sysvec,
+	.sysvec		= &elf64_freebsd_sysvec_v2,
 	.interp_newpath	= NULL,
 	.brand_note	= &elf64_freebsd_brandnote,
-	.flags		= BI_CAN_EXEC_DYN | BI_BRAND_NOTE
+	.flags		= BI_CAN_EXEC_DYN | BI_BRAND_NOTE,
+	.header_supported = &ppc64_elfv2_header_match
 };
 
-SYSINIT(elf64, SI_SUB_EXEC, SI_ORDER_ANY,
+SYSINIT(elf64v2, SI_SUB_EXEC, SI_ORDER_ANY,
     (sysinit_cfunc_t) elf64_insert_brand_entry,
-    &freebsd_brand_info);
+    &freebsd_brand_info_elfv2);
 
 static Elf64_Brandinfo freebsd_brand_oinfo = {
 	.brand		= ELFOSABI_FREEBSD,
@@ -110,10 +173,11 @@ static Elf64_Brandinfo freebsd_brand_oin
 	.compat_3_brand	= "FreeBSD",
 	.emul_path	= NULL,
 	.interp_path	= "/usr/libexec/ld-elf.so.1",
-	.sysvec		= &elf64_freebsd_sysvec,
+	.sysvec		= &elf64_freebsd_sysvec_v1,
 	.interp_newpath	= NULL,
 	.brand_note	= &elf64_freebsd_brandnote,
-	.flags		= BI_CAN_EXEC_DYN | BI_BRAND_NOTE
+	.flags		= BI_CAN_EXEC_DYN | BI_BRAND_NOTE,
+	.header_supported = &ppc64_elfv1_header_match
 };
 
 SYSINIT(oelf64, SI_SUB_EXEC, SI_ORDER_ANY,
@@ -122,6 +186,50 @@ SYSINIT(oelf64, SI_SUB_EXEC, SI_ORDER_AN
 
 void elf_reloc_self(Elf_Dyn *dynp, Elf_Addr relocbase);
 
+static boolean_t
+ppc64_elfv1_header_match(struct image_params *params)
+{
+	const Elf64_Ehdr *hdr = (const Elf64_Ehdr *)params->image_header;
+	int abi = (hdr->e_flags & 3);
+
+	return (abi == 0 || abi == 1);
+}
+
+static boolean_t
+ppc64_elfv2_header_match(struct image_params *params)
+{
+	const Elf64_Ehdr *hdr = (const Elf64_Ehdr *)params->image_header;
+	int abi = (hdr->e_flags & 3);
+
+	return (abi == 2);
+}
+
+static void  
+exec_setregs_funcdesc(struct thread *td, struct image_params *imgp,
+    u_long stack)
+{
+	struct trapframe *tf;
+	register_t entry_desc[3];
+
+	tf = trapframe(td);
+	exec_setregs(td, imgp, stack);
+
+	/*
+	 * For 64-bit ELFv1, we need to disentangle the function
+	 * descriptor
+	 *
+	 * 0. entry point
+	 * 1. TOC value (r2)
+	 * 2. Environment pointer (r11)
+	 */
+
+	(void)copyin((void *)imgp->entry_addr, entry_desc,
+	    sizeof(entry_desc));
+	tf->srr0 = entry_desc[0] + imgp->reloc_base;
+	tf->fixreg[2] = entry_desc[1] + imgp->reloc_base;
+	tf->fixreg[11] = entry_desc[2] + imgp->reloc_base;
+}
+
 void
 elf64_dump_thread(struct thread *td, void *dst, size_t *off)
 {
@@ -190,7 +298,11 @@ elf_reloc_internal(linker_file_t lf, Elf
 
 	case R_PPC_JMP_SLOT:	/* function descriptor copy */
 		lookup(lf, symidx, 1, &addr);
+#if !defined(_CALL_ELF) || _CALL_ELF == 1
 		memcpy(where, (Elf_Addr *)addr, 3*sizeof(Elf_Addr));
+#else
+		memcpy(where, (Elf_Addr *)addr, sizeof(Elf_Addr));
+#endif
 		__asm __volatile("dcbst 0,%0; sync" :: "r"(where) : "memory");
 		break;
 

Modified: head/sys/powerpc/powerpc/exec_machdep.c
==============================================================================
--- head/sys/powerpc/powerpc/exec_machdep.c	Mon Nov 23 17:05:28 2015	(r291210)
+++ head/sys/powerpc/powerpc/exec_machdep.c	Mon Nov 23 17:07:51 2015	(r291211)
@@ -501,9 +501,6 @@ exec_setregs(struct thread *td, struct i
 {
 	struct trapframe	*tf;
 	register_t		argc;
-	#ifdef __powerpc64__
-	register_t		entry_desc[3];
-	#endif
 
 	tf = trapframe(td);
 	bzero(tf, sizeof *tf);
@@ -546,24 +543,13 @@ exec_setregs(struct thread *td, struct i
 	tf->fixreg[7] = 0;				/* termination vector */
 	tf->fixreg[8] = (register_t)imgp->ps_strings;	/* NetBSD extension */
 
+	tf->srr0 = imgp->entry_addr;
 	#ifdef __powerpc64__
-	/*
-	 * For 64-bit, we need to disentangle the function descriptor
-	 * 
-	 * 0. entry point
-	 * 1. TOC value (r2)
-	 * 2. Environment pointer (r11)
-	 */
-
-	(void)copyin((void *)imgp->entry_addr, entry_desc, sizeof(entry_desc));
-	tf->srr0 = entry_desc[0] + imgp->reloc_base;
-	tf->fixreg[2] = entry_desc[1] + imgp->reloc_base;
-	tf->fixreg[11] = entry_desc[2] + imgp->reloc_base;
+	tf->fixreg[12] = imgp->entry_addr;
 	tf->srr1 = PSL_SF | PSL_USERSET | PSL_FE_DFLT;
 	if (mfmsr() & PSL_HV)
 		tf->srr1 |= PSL_HV;
 	#else
-	tf->srr0 = imgp->entry_addr;
 	tf->srr1 = PSL_USERSET | PSL_FE_DFLT;
 	#endif
 	td->td_pcb->pcb_flags = 0;

Modified: head/sys/powerpc/powerpc/sigcode64.S
==============================================================================
--- head/sys/powerpc/powerpc/sigcode64.S	Mon Nov 23 17:05:28 2015	(r291210)
+++ head/sys/powerpc/powerpc/sigcode64.S	Mon Nov 23 17:07:51 2015	(r291211)
@@ -42,15 +42,21 @@
  *
  * On entry r1 points to a struct sigframe at bottom of current stack.
  * All other registers are unchanged.
+ *
+ * Entered midway through for v2 ELF binaries that don't need to deal with
+ * function descriptors.
+ *
  */
 	.globl	CNAME(sigcode64),CNAME(szsigcode64)
+	.globl	CNAME(sigcode64_elfv2),CNAME(szsigcode64_elfv2)
 CNAME(sigcode64):
-	addi	1,1,-112		/* reserved space for callee */
 	mflr	2			/* resolve function descriptor */
 	ld	0,0(2)			
 	ld	2,8(2)
 	mtlr	0
 
+CNAME(sigcode64_elfv2):
+	addi	1,1,-112		/* reserved space for callee */
 	blrl
 
 	addi	3,1,112+SF_UC		/* restore sp, and get &frame->sf_uc */
@@ -64,3 +70,6 @@ endsigcode64:
 	.data
 CNAME(szsigcode64):
 	.long	endsigcode64 - CNAME(sigcode64)
+CNAME(szsigcode64_elfv2):
+	.long	endsigcode64 - CNAME(sigcode64_elfv2)
+


More information about the svn-src-head mailing list