diff --git a/sys/modules/Makefile b/sys/modules/Makefile --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -526,7 +526,7 @@ .if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386" SUBDIR+= linux .endif -.if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_ARCH} == "powerpc64" +.if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_ARCH:Mpowerpc64*} SUBDIR+= linux64 SUBDIR+= linux_common .endif diff --git a/sys/powerpc/linux/linux_sysvec.c b/sys/powerpc/linux/linux_sysvec.c --- a/sys/powerpc/linux/linux_sysvec.c +++ b/sys/powerpc/linux/linux_sysvec.c @@ -200,134 +200,6 @@ //AUXARGS_ENTRY(pos, LINUX_AT_PLATFORM, PTROUT(linux_platform)); } -/* - * Copy strings out to the new process address space, constructing new arg - * and env vector tables. Return a pointer to the base so that it can be used - * as the initial stack pointer. - * LINUXTODO: deduplicate against other linuxulator archs - */ -static int -linux_copyout_strings(struct image_params *imgp, uintptr_t *stack_base) -{ - char **vectp; - char *stringp; - uintptr_t destp, ustringp; - struct ps_strings *arginfo; - char canary[LINUX_AT_RANDOM_LEN]; - size_t execpath_len; - struct proc *p; - int argc, envc, error; - - p = imgp->proc; - arginfo = (struct ps_strings *)PROC_PS_STRINGS(p); - destp = (uintptr_t)arginfo; - - if (imgp->execpath != NULL && imgp->auxargs != NULL) { - execpath_len = strlen(imgp->execpath) + 1; - destp -= execpath_len; - destp = rounddown2(destp, sizeof(void *)); - imgp->execpathp = (void *)destp; - error = copyout(imgp->execpath, imgp->execpathp, execpath_len); - if (error != 0) - return (error); - } - - /* Prepare the canary for SSP. */ - arc4rand(canary, sizeof(canary), 0); - destp -= roundup(sizeof(canary), sizeof(void *)); - imgp->canary = (void *)destp; - error = copyout(canary, imgp->canary, sizeof(canary)); - if (error != 0) - return (error); - - /* Allocate room for the argument and environment strings. */ - destp -= ARG_MAX - imgp->args->stringspace; - destp = rounddown2(destp, sizeof(void *)); - ustringp = destp; - - if (imgp->auxargs) { - /* - * Allocate room on the stack for the ELF auxargs - * array. It has up to LINUX_AT_COUNT entries. - */ - destp -= LINUX_AT_COUNT * sizeof(Elf64_Auxinfo); - destp = rounddown2(destp, sizeof(void *)); - } - - vectp = (char **)destp; - - /* - * Allocate room for argc and the argv[] and env vectors including the - * terminating NULL pointers. - */ - vectp -= imgp->args->argc + 1 + imgp->args->envc + 1; - - /* NOT SURE WITH THIS - * Starting with 2.24, glibc depends on a 16-byte stack alignment. - * One "long argc" will be prepended later. - */ - vectp = (char **)((((uintptr_t)vectp + 8) & ~0xF) - 8); - - /* vectp also becomes our initial stack base. */ - *stack_base = (uintptr_t)vectp; - - stringp = imgp->args->begin_argv; - argc = imgp->args->argc; - envc = imgp->args->envc; - - /* Copy out strings - arguments and environment. */ - error = copyout(stringp, (void *)ustringp, - ARG_MAX - imgp->args->stringspace); - if (error != 0) - return (error); - - /* Fill in "ps_strings" struct for ps, w, etc. */ - if (suword(&arginfo->ps_argvstr, (long)(intptr_t)vectp) != 0 || - suword(&arginfo->ps_nargvstr, argc) != 0) - return (EFAULT); - - /* Fill in argument portion of vector table. */ - for (; argc > 0; --argc) { - if (suword(vectp++, ustringp) != 0) - return (EFAULT); - while (*stringp++ != 0) - ustringp++; - ustringp++; - } - - /* A null vector table pointer separates the argp's from the envp's. */ - if (suword(vectp++, 0) != 0) - return (EFAULT); - - if (suword(&arginfo->ps_envstr, (long)(intptr_t)vectp) != 0 || - suword(&arginfo->ps_nenvstr, envc) != 0) - return (EFAULT); - - /* Fill in environment portion of vector table. */ - for (; envc > 0; --envc) { - if (suword(vectp++, ustringp) != 0) - return (EFAULT); - while (*stringp++ != 0) - ustringp++; - ustringp++; - } - - /* The end of the vector table is a null pointer. */ - if (suword(vectp, 0) != 0) - return (EFAULT); - - if (imgp->auxargs) { - vectp++; - aux_vec = (uintptr_t)vectp; - error = imgp->sysent->sv_copyout_auxargs(imgp, - (uintptr_t)vectp); - if (error != 0) - return (error); - } - - return (0); -} - static void cleanup_power_extras(struct thread *td) { @@ -411,9 +283,7 @@ tf->fixreg[8] = (register_t)imgp->ps_strings; /* NetBSD extension */ tf->srr0 = imgp->entry_addr; - #ifdef __powerpc64__ tf->fixreg[12] = imgp->entry_addr; - #endif tf->srr1 = psl_userset | PSL_FE_DFLT; cleanup_power_extras(td); td->td_pcb->pcb_flags = 0; @@ -584,7 +454,7 @@ .sv_psstringssz = sizeof(struct ps_strings), .sv_stackprot = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE, /* Enabling the execution of stack temporarily for signal trampoline. */ .sv_copyout_auxargs = linux64_copyout_auxargs, - .sv_copyout_strings = linux_copyout_strings, + .sv_copyout_strings = linux64_copyout_strings, //.sv_setregs = linux_exec_setregs, .sv_setregs = linux_exec_setregs_funcdesc, .sv_fixlimit = NULL, @@ -607,6 +477,47 @@ .sv_setid_allowed = &linux_setid_allowed_query, }; +struct sysentvec elf64_linux_sysvec_v2 = { + .sv_size = LINUX_SYS_MAXSYSCALL, + .sv_table = linux_sysent, + .sv_fixup = __elfN(freebsd_fixup), + .sv_sendsig = linux_rt_sendsig, + .sv_sigcode = &_binary_linux_vdso_so_o_start, + .sv_szsigcode = &linux_szsigcode, + .sv_name = "Linux ELF64 V2", + .sv_coredump = __elfN(coredump), + .sv_elf_core_osabi = ELFOSABI_NONE, + .sv_elf_core_abi_vendor = LINUX_ABI_VENDOR, + .sv_elf_core_prepare_notes = linux64_prepare_notes, + .sv_minsigstksz = MINSIGSTKSZ, + .sv_minuser = VM_MIN_ADDRESS, + .sv_maxuser = VM_MAXUSER_ADDRESS, + .sv_usrstack = LINUX_USRSTACK, + .sv_psstrings = LINUX_PS_STRINGS, + .sv_psstringssz = sizeof(struct ps_strings), + .sv_stackprot = VM_PROT_ALL, + .sv_copyout_auxargs = linux64_copyout_auxargs, + .sv_copyout_strings = linux64_copyout_strings, + .sv_setregs = linux_exec_setregs, + .sv_fixlimit = NULL, + .sv_maxssiz = NULL, + .sv_flags = SV_ABI_LINUX | SV_LP64 | SV_SHP | SV_SIG_DISCIGN | + SV_SIG_WAITNDQ, + .sv_set_syscall_retval = linux_set_syscall_retval, + .sv_fetch_syscall_args = linux_fetch_syscall_args, + .sv_syscallnames = NULL, + .sv_shared_page_base = LINUX_SHAREDPAGE, + .sv_shared_page_len = PAGE_SIZE, + .sv_schedtail = linux_schedtail, + .sv_thread_detach = linux_thread_detach, + .sv_trap = NULL, + .sv_hwcap = NULL, + .sv_hwcap2 = NULL, + .sv_onexec = linux_on_exec_vmspace, + .sv_onexit = linux_on_exit, + .sv_ontdexit = linux_thread_dtor, +}; + static int linux_on_exec_vmspace(struct proc *p, struct image_params *imgp) { @@ -725,6 +636,8 @@ } } +static bool linux64_elfv2_header_match(struct image_params *, int32_t *, uint32_t *); + static Elf_Brandnote linux64_brandnote = { .hdr.n_namesz = sizeof(GNU_ABI_VENDOR), .hdr.n_descsz = 16, @@ -745,11 +658,34 @@ .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE }; +static Elf64_Brandinfo linux_brand_info_elfv2 = { + .brand = ELFOSABI_LINUX, + .machine = EM_PPC64, + .compat_3_brand = "Linux", + .interp_path = "/lib64/ld-linux-x86-64.so.2", + .sysvec = &elf64_linux_sysvec_v2, + .interp_newpath = NULL, + .brand_note = &linux64_brandnote, + .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE, + .header_supported = &linux64_elfv2_header_match +}; + Elf64_Brandinfo *linux_brandlist[] = { &linux_glibc2brand, + &linux_brand_info_elfv2, NULL }; +static bool +linux64_elfv2_header_match(struct image_params *params, int32_t *osrel __unused, + uint32_t *fctl0 __unused) +{ + const Elf64_Ehdr *hdr = (const Elf64_Ehdr *)params->image_header; + int abi = (hdr->e_flags & 3); + + return (abi == 2); +} + static int linux64_elf_modevent(module_t mod, int type, void *data) {