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.
This commit is contained in:
parent
c2c58185e5
commit
fd6820bbc8
@ -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; \
|
||||
|
@ -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;
|
||||
|
@ -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,@function \n" \
|
||||
" .align 4 \n" \
|
||||
".L._mcount: \n" \
|
||||
".L._mcount: \n"
|
||||
#else
|
||||
#define MCOUNT_PREAMBLE \
|
||||
" .globl _mcount \n" \
|
||||
" .type _mcount,@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" \
|
||||
|
@ -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 Elf64_Brandinfo freebsd_brand_info = {
|
||||
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,
|
||||
.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(elf64, SI_SUB_EXEC, SI_ORDER_ANY,
|
||||
SYSINIT(elf64v1, SI_SUB_EXEC, SI_ORDER_ANY,
|
||||
(sysinit_cfunc_t) elf64_insert_brand_entry,
|
||||
&freebsd_brand_info);
|
||||
&freebsd_brand_info_elfv1);
|
||||
|
||||
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_v2,
|
||||
.interp_newpath = NULL,
|
||||
.brand_note = &elf64_freebsd_brandnote,
|
||||
.flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE,
|
||||
.header_supported = &ppc64_elfv2_header_match
|
||||
};
|
||||
|
||||
SYSINIT(elf64v2, SI_SUB_EXEC, SI_ORDER_ANY,
|
||||
(sysinit_cfunc_t) elf64_insert_brand_entry,
|
||||
&freebsd_brand_info_elfv2);
|
||||
|
||||
static Elf64_Brandinfo freebsd_brand_oinfo = {
|
||||
.brand = ELFOSABI_FREEBSD,
|
||||
@ -110,10 +173,11 @@ static Elf64_Brandinfo freebsd_brand_oinfo = {
|
||||
.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_ANY,
|
||||
|
||||
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_Addr relocbase, const void *data,
|
||||
|
||||
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;
|
||||
|
||||
|
@ -501,9 +501,6 @@ exec_setregs(struct thread *td, struct image_params *imgp, u_long stack)
|
||||
{
|
||||
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 image_params *imgp, u_long stack)
|
||||
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;
|
||||
|
@ -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)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user