aboutsummaryrefslogtreecommitdiff
path: root/sys/amd64/linux32/linux32_sysvec.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/amd64/linux32/linux32_sysvec.c')
-rw-r--r--sys/amd64/linux32/linux32_sysvec.c149
1 files changed, 21 insertions, 128 deletions
diff --git a/sys/amd64/linux32/linux32_sysvec.c b/sys/amd64/linux32/linux32_sysvec.c
index e9162f04d3f7..19b4af7661f0 100644
--- a/sys/amd64/linux32/linux32_sysvec.c
+++ b/sys/amd64/linux32/linux32_sysvec.c
@@ -32,11 +32,6 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "opt_compat.h"
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#ifndef COMPAT_FREEBSD32
#error "Unable to compile Linux-emulator due to missing COMPAT_FREEBSD32 option!"
#endif
@@ -44,44 +39,31 @@ __FBSDID("$FreeBSD$");
#define __ELF_WORD_SIZE 32
#include <sys/param.h>
-#include <sys/systm.h>
#include <sys/exec.h>
-#include <sys/fcntl.h>
#include <sys/imgact.h>
#include <sys/imgact_elf.h>
#include <sys/kernel.h>
#include <sys/lock.h>
-#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/mutex.h>
#include <sys/proc.h>
-#include <sys/resourcevar.h>
#include <sys/stddef.h>
-#include <sys/signalvar.h>
#include <sys/syscallsubr.h>
#include <sys/sysctl.h>
#include <sys/sysent.h>
-#include <sys/sysproto.h>
-#include <sys/vnode.h>
-#include <sys/eventhandler.h>
-#include <vm/vm.h>
#include <vm/pmap.h>
-#include <vm/vm_extern.h>
+#include <vm/vm.h>
#include <vm/vm_map.h>
-#include <vm/vm_object.h>
-#include <vm/vm_page.h>
#include <vm/vm_param.h>
-#include <machine/cpu.h>
#include <machine/md_var.h>
-#include <machine/pcb.h>
-#include <machine/specialreg.h>
#include <machine/trap.h>
#include <x86/linux/linux_x86.h>
#include <amd64/linux32/linux.h>
#include <amd64/linux32/linux32_proto.h>
+#include <compat/linux/linux_elf.h>
#include <compat/linux/linux_emul.h>
#include <compat/linux/linux_fork.h>
#include <compat/linux/linux_ioctl.h>
@@ -113,11 +95,10 @@ extern char _binary_linux32_vdso_so_o_end;
static vm_offset_t linux_vdso_base;
extern struct sysent linux32_sysent[LINUX32_SYS_MAXSYSCALL];
+extern const char *linux32_syscallnames[];
SET_DECLARE(linux_ioctl_handler_set, struct linux_ioctl_handler);
-static int linux_fixup_elf(uintptr_t *stack_base,
- struct image_params *iparams);
static int linux_copyout_strings(struct image_params *imgp,
uintptr_t *stack_base);
static void linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask);
@@ -127,7 +108,6 @@ static void linux_exec_sysvec_init(void *param);
static int linux_on_exec_vmspace(struct proc *p,
struct image_params *imgp);
static void linux32_fixlimit(struct rlimit *rl, int which);
-static bool linux32_trans_osrel(const Elf_Note *note, int32_t *osrel);
static void linux_vdso_install(const void *param);
static void linux_vdso_deinstall(const void *param);
static void linux_vdso_reloc(char *mapping, Elf_Addr offset);
@@ -151,74 +131,15 @@ LINUX_VDSO_SYM_INTPTR(kern_tsc_selector);
LINUX_VDSO_SYM_INTPTR(kern_cpu_selector);
LINUX_VDSO_SYM_CHAR(linux_platform);
-static int
-linux_copyout_auxargs(struct image_params *imgp, uintptr_t base)
+void
+linux32_arch_copyout_auxargs(struct image_params *imgp, Elf_Auxinfo **pos)
{
- Elf32_Auxargs *args;
- Elf32_Auxinfo *argarray, *pos;
- int error, issetugid;
-
- args = (Elf32_Auxargs *)imgp->auxargs;
- argarray = pos = malloc(LINUX_AT_COUNT * sizeof(*pos), M_TEMP,
- M_WAITOK | M_ZERO);
-
- issetugid = imgp->proc->p_flag & P_SUGID ? 1 : 0;
- AUXARGS_ENTRY(pos, LINUX_AT_SYSINFO, __kernel_vsyscall);
- AUXARGS_ENTRY(pos, LINUX_AT_SYSINFO_EHDR, linux_vdso_base);
- AUXARGS_ENTRY(pos, LINUX_AT_HWCAP, cpu_feature);
- AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz);
- /*
- * Do not export AT_CLKTCK when emulating Linux kernel prior to 2.4.0,
- * as it has appeared in the 2.4.0-rc7 first time.
- * Being exported, AT_CLKTCK is returned by sysconf(_SC_CLK_TCK),
- * glibc falls back to the hard-coded CLK_TCK value when aux entry
- * is not present.
- * Also see linux_times() implementation.
- */
- if (linux_kernver(curthread) >= LINUX_KERNVER_2004000)
- AUXARGS_ENTRY(pos, LINUX_AT_CLKTCK, stclohz);
- AUXARGS_ENTRY(pos, AT_PHDR, args->phdr);
- AUXARGS_ENTRY(pos, AT_PHENT, args->phent);
- AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum);
- AUXARGS_ENTRY(pos, AT_BASE, args->base);
- AUXARGS_ENTRY(pos, AT_FLAGS, args->flags);
- AUXARGS_ENTRY(pos, AT_ENTRY, args->entry);
- AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_ucred->cr_ruid);
- AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid);
- AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_ucred->cr_rgid);
- AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_ucred->cr_svgid);
- AUXARGS_ENTRY(pos, LINUX_AT_SECURE, issetugid);
- AUXARGS_ENTRY(pos, LINUX_AT_RANDOM, PTROUT(imgp->canary));
- AUXARGS_ENTRY(pos, LINUX_AT_HWCAP2, 0);
- if (imgp->execpathp != 0)
- AUXARGS_ENTRY(pos, LINUX_AT_EXECFN, PTROUT(imgp->execpathp));
- if (args->execfd != -1)
- AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
- AUXARGS_ENTRY(pos, LINUX_AT_PLATFORM, PTROUT(linux_platform));
- AUXARGS_ENTRY(pos, AT_NULL, 0);
-
- free(imgp->auxargs, M_TEMP);
- imgp->auxargs = NULL;
- KASSERT(pos - argarray <= LINUX_AT_COUNT, ("Too many auxargs"));
-
- error = copyout(argarray, (void *)base,
- sizeof(*argarray) * LINUX_AT_COUNT);
- free(argarray, M_TEMP);
- return (error);
-}
-
-static int
-linux_fixup_elf(uintptr_t *stack_base, struct image_params *imgp)
-{
- Elf32_Addr *base;
-
- base = (Elf32_Addr *)*stack_base;
- base--;
- if (suword32(base, (uint32_t)imgp->args->argc) == -1)
- return (EFAULT);
- *stack_base = (uintptr_t)base;
- return (0);
+ AUXARGS_ENTRY((*pos), LINUX_AT_SYSINFO, __kernel_vsyscall);
+ AUXARGS_ENTRY((*pos), LINUX_AT_SYSINFO_EHDR, linux_vdso_base);
+ AUXARGS_ENTRY((*pos), LINUX_AT_HWCAP, cpu_feature);
+ AUXARGS_ENTRY((*pos), LINUX_AT_HWCAP2, linux_x86_elf_hwcap2());
+ AUXARGS_ENTRY((*pos), LINUX_AT_PLATFORM, PTROUT(linux_platform));
}
static void
@@ -604,13 +525,13 @@ linux32_fetch_syscall_args(struct thread *td)
sa->args[2] = frame->tf_rdx;
sa->args[3] = frame->tf_rsi;
sa->args[4] = frame->tf_rdi;
- sa->args[5] = frame->tf_rbp; /* Unconfirmed */
+ sa->args[5] = frame->tf_rbp;
sa->code = frame->tf_rax;
sa->original_code = sa->code;
if (sa->code >= p->p_sysent->sv_size)
/* nosys */
- sa->callp = &p->p_sysent->sv_table[p->p_sysent->sv_size - 1];
+ sa->callp = &nosys_sysent;
else
sa->callp = &p->p_sysent->sv_table[sa->code];
@@ -856,7 +777,7 @@ linux32_fixlimit(struct rlimit *rl, int which)
struct sysentvec elf_linux_sysvec = {
.sv_size = LINUX32_SYS_MAXSYSCALL,
.sv_table = linux32_sysent,
- .sv_fixup = linux_fixup_elf,
+ .sv_fixup = elf32_freebsd_fixup,
.sv_sendsig = linux_sendsig,
.sv_sigcode = &_binary_linux32_vdso_so_o_start,
.sv_szsigcode = &linux_szsigcode,
@@ -865,7 +786,6 @@ struct sysentvec elf_linux_sysvec = {
.sv_elf_core_osabi = ELFOSABI_NONE,
.sv_elf_core_abi_vendor = LINUX_ABI_VENDOR,
.sv_elf_core_prepare_notes = linux32_prepare_notes,
- .sv_imgact_try = linux_exec_imgact_try,
.sv_minsigstksz = LINUX_MINSIGSTKSZ,
.sv_minuser = VM_MIN_ADDRESS,
.sv_maxuser = LINUX32_MAXUSER,
@@ -873,7 +793,7 @@ struct sysentvec elf_linux_sysvec = {
.sv_psstrings = LINUX32_PS_STRINGS,
.sv_psstringssz = sizeof(struct linux32_ps_strings),
.sv_stackprot = VM_PROT_ALL,
- .sv_copyout_auxargs = linux_copyout_auxargs,
+ .sv_copyout_auxargs = __linuxN(copyout_auxargs),
.sv_copyout_strings = linux_copyout_strings,
.sv_setregs = linux_exec_setregs,
.sv_fixlimit = linux32_fixlimit,
@@ -882,12 +802,14 @@ struct sysentvec elf_linux_sysvec = {
SV_SIG_DISCIGN | SV_SIG_WAITNDQ | SV_TIMEKEEP,
.sv_set_syscall_retval = linux32_set_syscall_retval,
.sv_fetch_syscall_args = linux32_fetch_syscall_args,
- .sv_syscallnames = NULL,
+ .sv_syscallnames = linux32_syscallnames,
.sv_shared_page_base = LINUX32_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,
@@ -903,7 +825,7 @@ linux_on_exec_vmspace(struct proc *p, struct image_params *imgp)
error = linux_map_vdso(p, linux_vdso_obj, linux_vdso_base,
LINUX32_VDSOPAGE_SIZE, imgp);
if (error == 0)
- linux_on_exec(p, imgp);
+ error = linux_on_exec(p, imgp);
return (error);
}
@@ -924,7 +846,7 @@ linux_exec_sysvec_init(void *param)
tkoff = kern_timekeep_base - linux_vdso_base;
ktimekeep_base = (l_uintptr_t *)(linux_vdso_mapping + tkoff);
- *ktimekeep_base = sv->sv_timekeep_base;
+ *ktimekeep_base = sv->sv_shared_page_base + sv->sv_timekeep_offset;
tkoff = kern_tsc_selector - linux_vdso_base;
ktsc_selector = (l_uintptr_t *)(linux_vdso_mapping + tkoff);
@@ -1029,46 +951,19 @@ linux_vdso_reloc(char *mapping, Elf_Addr offset)
}
}
-static char GNU_ABI_VENDOR[] = "GNU";
-static int GNULINUX_ABI_DESC = 0;
-
-static bool
-linux32_trans_osrel(const Elf_Note *note, int32_t *osrel)
-{
- const Elf32_Word *desc;
- uintptr_t p;
-
- p = (uintptr_t)(note + 1);
- p += roundup2(note->n_namesz, sizeof(Elf32_Addr));
-
- desc = (const Elf32_Word *)p;
- if (desc[0] != GNULINUX_ABI_DESC)
- return (false);
-
- /*
- * For Linux we encode osrel using the Linux convention of
- * (version << 16) | (major << 8) | (minor)
- * See macro in linux_mib.h
- */
- *osrel = LINUX_KERNVER(desc[1], desc[2], desc[3]);
-
- return (true);
-}
-
static Elf_Brandnote linux32_brandnote = {
.hdr.n_namesz = sizeof(GNU_ABI_VENDOR),
.hdr.n_descsz = 16, /* XXX at least 16 */
.hdr.n_type = 1,
.vendor = GNU_ABI_VENDOR,
.flags = BN_TRANSLATE_OSREL,
- .trans_osrel = linux32_trans_osrel
+ .trans_osrel = linux_trans_osrel
};
static Elf32_Brandinfo linux_brand = {
.brand = ELFOSABI_LINUX,
.machine = EM_386,
.compat_3_brand = "Linux",
- .emul_path = linux_emul_path,
.interp_path = "/lib/ld-linux.so.1",
.sysvec = &elf_linux_sysvec,
.interp_newpath = NULL,
@@ -1080,7 +975,6 @@ static Elf32_Brandinfo linux_glibc2brand = {
.brand = ELFOSABI_LINUX,
.machine = EM_386,
.compat_3_brand = "Linux",
- .emul_path = linux_emul_path,
.interp_path = "/lib/ld-linux.so.2",
.sysvec = &elf_linux_sysvec,
.interp_newpath = NULL,
@@ -1092,7 +986,6 @@ static Elf32_Brandinfo linux_muslbrand = {
.brand = ELFOSABI_LINUX,
.machine = EM_386,
.compat_3_brand = "Linux",
- .emul_path = linux_emul_path,
.interp_path = "/lib/ld-musl-i386.so.1",
.sysvec = &elf_linux_sysvec,
.interp_newpath = NULL,
@@ -1101,7 +994,7 @@ static Elf32_Brandinfo linux_muslbrand = {
LINUX_BI_FUTEX_REQUEUE
};
-Elf32_Brandinfo *linux_brandlist[] = {
+static Elf32_Brandinfo *linux_brandlist[] = {
&linux_brand,
&linux_glibc2brand,
&linux_muslbrand,