Add support for executing the FreeBSD 1/i386 a.out binaries on amd64.
In particular: - implement compat shims for old stat(2) variants and ogetdirentries(2); - implement delivery of signals with ancient stack frame layout and corresponding sigreturn(2); - implement old getpagesize(2); - provide a user-mode trampoline and LDT call gate for lcall $7,$0; - port a.out image activator and connect it to the build as a module on amd64. The changes are hidden under COMPAT_43. MFC after: 1 month
This commit is contained in:
parent
17f0fc566e
commit
7332c129e0
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=220238
@ -69,3 +69,14 @@ freebsd32_sysarch(struct thread *td, struct freebsd32_sysarch_args *uap)
|
||||
return (sysarch(td, &uap1));
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef COMPAT_43
|
||||
int
|
||||
ofreebsd32_getpagesize(struct thread *td,
|
||||
struct ofreebsd32_getpagesize_args *uap)
|
||||
{
|
||||
|
||||
td->td_retval[0] = IA32_PAGE_SIZE;
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
@ -300,6 +300,109 @@ freebsd32_swapcontext(struct thread *td, struct freebsd32_swapcontext_args *uap)
|
||||
* frame pointer, it returns to the user
|
||||
* specified pc, psl.
|
||||
*/
|
||||
|
||||
#ifdef COMPAT_43
|
||||
static void
|
||||
ia32_osendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
|
||||
{
|
||||
struct ia32_sigframe3 sf, *fp;
|
||||
struct proc *p;
|
||||
struct thread *td;
|
||||
struct sigacts *psp;
|
||||
struct trapframe *regs;
|
||||
int sig;
|
||||
int oonstack;
|
||||
|
||||
td = curthread;
|
||||
p = td->td_proc;
|
||||
PROC_LOCK_ASSERT(p, MA_OWNED);
|
||||
sig = ksi->ksi_signo;
|
||||
psp = p->p_sigacts;
|
||||
mtx_assert(&psp->ps_mtx, MA_OWNED);
|
||||
regs = td->td_frame;
|
||||
oonstack = sigonstack(regs->tf_rsp);
|
||||
|
||||
/* Allocate space for the signal handler context. */
|
||||
if ((td->td_pflags & TDP_ALTSTACK) && !oonstack &&
|
||||
SIGISMEMBER(psp->ps_sigonstack, sig)) {
|
||||
fp = (struct ia32_sigframe3 *)(td->td_sigstk.ss_sp +
|
||||
td->td_sigstk.ss_size - sizeof(sf));
|
||||
td->td_sigstk.ss_flags |= SS_ONSTACK;
|
||||
} else
|
||||
fp = (struct ia32_sigframe3 *)regs->tf_rsp - 1;
|
||||
|
||||
/* Translate the signal if appropriate. */
|
||||
if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
|
||||
sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)];
|
||||
|
||||
/* Build the argument list for the signal handler. */
|
||||
sf.sf_signum = sig;
|
||||
sf.sf_scp = (register_t)&fp->sf_siginfo.si_sc;
|
||||
if (SIGISMEMBER(psp->ps_siginfo, sig)) {
|
||||
/* Signal handler installed with SA_SIGINFO. */
|
||||
sf.sf_arg2 = (register_t)&fp->sf_siginfo;
|
||||
sf.sf_siginfo.si_signo = sig;
|
||||
sf.sf_siginfo.si_code = ksi->ksi_code;
|
||||
sf.sf_ah = (uintptr_t)catcher;
|
||||
} else {
|
||||
/* Old FreeBSD-style arguments. */
|
||||
sf.sf_arg2 = ksi->ksi_code;
|
||||
sf.sf_addr = (register_t)ksi->ksi_addr;
|
||||
sf.sf_ah = (uintptr_t)catcher;
|
||||
}
|
||||
mtx_unlock(&psp->ps_mtx);
|
||||
PROC_UNLOCK(p);
|
||||
|
||||
/* Save most if not all of trap frame. */
|
||||
sf.sf_siginfo.si_sc.sc_eax = regs->tf_rax;
|
||||
sf.sf_siginfo.si_sc.sc_ebx = regs->tf_rbx;
|
||||
sf.sf_siginfo.si_sc.sc_ecx = regs->tf_rcx;
|
||||
sf.sf_siginfo.si_sc.sc_edx = regs->tf_rdx;
|
||||
sf.sf_siginfo.si_sc.sc_esi = regs->tf_rsi;
|
||||
sf.sf_siginfo.si_sc.sc_edi = regs->tf_rdi;
|
||||
sf.sf_siginfo.si_sc.sc_cs = regs->tf_cs;
|
||||
sf.sf_siginfo.si_sc.sc_ds = regs->tf_ds;
|
||||
sf.sf_siginfo.si_sc.sc_ss = regs->tf_ss;
|
||||
sf.sf_siginfo.si_sc.sc_es = regs->tf_es;
|
||||
sf.sf_siginfo.si_sc.sc_fs = regs->tf_fs;
|
||||
sf.sf_siginfo.si_sc.sc_gs = regs->tf_gs;
|
||||
sf.sf_siginfo.si_sc.sc_isp = regs->tf_rsp;
|
||||
|
||||
/* Build the signal context to be used by osigreturn(). */
|
||||
sf.sf_siginfo.si_sc.sc_onstack = (oonstack) ? 1 : 0;
|
||||
SIG2OSIG(*mask, sf.sf_siginfo.si_sc.sc_mask);
|
||||
sf.sf_siginfo.si_sc.sc_esp = regs->tf_rsp;
|
||||
sf.sf_siginfo.si_sc.sc_ebp = regs->tf_rbp;
|
||||
sf.sf_siginfo.si_sc.sc_eip = regs->tf_rip;
|
||||
sf.sf_siginfo.si_sc.sc_eflags = regs->tf_rflags;
|
||||
sf.sf_siginfo.si_sc.sc_trapno = regs->tf_trapno;
|
||||
sf.sf_siginfo.si_sc.sc_err = regs->tf_err;
|
||||
|
||||
/*
|
||||
* Copy the sigframe out to the user's stack.
|
||||
*/
|
||||
if (copyout(&sf, fp, sizeof(*fp)) != 0) {
|
||||
#ifdef DEBUG
|
||||
printf("process %ld has trashed its stack\n", (long)p->p_pid);
|
||||
#endif
|
||||
PROC_LOCK(p);
|
||||
sigexit(td, SIGILL);
|
||||
}
|
||||
|
||||
regs->tf_rsp = (uintptr_t)fp;
|
||||
regs->tf_rip = p->p_sysent->sv_psstrings - sz_ia32_osigcode;
|
||||
regs->tf_rflags &= ~(PSL_T | PSL_D);
|
||||
regs->tf_cs = _ucode32sel;
|
||||
regs->tf_ds = _udatasel;
|
||||
regs->tf_es = _udatasel;
|
||||
regs->tf_fs = _udatasel;
|
||||
regs->tf_ss = _udatasel;
|
||||
set_pcb_flags(td->td_pcb, PCB_FULL_IRET);
|
||||
PROC_LOCK(p);
|
||||
mtx_lock(&psp->ps_mtx);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef COMPAT_FREEBSD4
|
||||
static void
|
||||
freebsd4_ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
|
||||
@ -440,6 +543,12 @@ ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
|
||||
freebsd4_ia32_sendsig(catcher, ksi, mask);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#ifdef COMPAT_43
|
||||
if (SIGISMEMBER(psp->ps_osigset, sig)) {
|
||||
ia32_osendsig(catcher, ksi, mask);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
mtx_assert(&psp->ps_mtx, MA_OWNED);
|
||||
regs = td->td_frame;
|
||||
@ -547,6 +656,64 @@ ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
|
||||
* make sure that the user has not modified the
|
||||
* state to gain improper privileges.
|
||||
*/
|
||||
|
||||
#ifdef COMPAT_43
|
||||
int
|
||||
ofreebsd32_sigreturn(struct thread *td, struct ofreebsd32_sigreturn_args *uap)
|
||||
{
|
||||
struct ia32_sigcontext3 sc, *scp;
|
||||
struct trapframe *regs;
|
||||
int eflags, error;
|
||||
ksiginfo_t ksi;
|
||||
|
||||
regs = td->td_frame;
|
||||
error = copyin(uap->sigcntxp, &sc, sizeof(sc));
|
||||
if (error != 0)
|
||||
return (error);
|
||||
scp = ≻
|
||||
eflags = scp->sc_eflags;
|
||||
if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF)) {
|
||||
return (EINVAL);
|
||||
}
|
||||
if (!CS_SECURE(scp->sc_cs)) {
|
||||
ksiginfo_init_trap(&ksi);
|
||||
ksi.ksi_signo = SIGBUS;
|
||||
ksi.ksi_code = BUS_OBJERR;
|
||||
ksi.ksi_trapno = T_PROTFLT;
|
||||
ksi.ksi_addr = (void *)regs->tf_rip;
|
||||
trapsignal(td, &ksi);
|
||||
return (EINVAL);
|
||||
}
|
||||
regs->tf_ds = scp->sc_ds;
|
||||
regs->tf_es = scp->sc_es;
|
||||
regs->tf_fs = scp->sc_fs;
|
||||
regs->tf_gs = scp->sc_gs;
|
||||
|
||||
regs->tf_rax = scp->sc_eax;
|
||||
regs->tf_rbx = scp->sc_ebx;
|
||||
regs->tf_rcx = scp->sc_ecx;
|
||||
regs->tf_rdx = scp->sc_edx;
|
||||
regs->tf_rsi = scp->sc_esi;
|
||||
regs->tf_rdi = scp->sc_edi;
|
||||
regs->tf_cs = scp->sc_cs;
|
||||
regs->tf_ss = scp->sc_ss;
|
||||
regs->tf_rbp = scp->sc_ebp;
|
||||
regs->tf_rsp = scp->sc_esp;
|
||||
regs->tf_rip = scp->sc_eip;
|
||||
regs->tf_rflags = eflags;
|
||||
|
||||
if (scp->sc_onstack & 1)
|
||||
td->td_sigstk.ss_flags |= SS_ONSTACK;
|
||||
else
|
||||
td->td_sigstk.ss_flags &= ~SS_ONSTACK;
|
||||
|
||||
kern_sigprocmask(td, SIG_SETMASK, (sigset_t *)&scp->sc_mask, NULL,
|
||||
SIGPROCMASK_OLD);
|
||||
set_pcb_flags(td->td_pcb, PCB_FULL_IRET);
|
||||
return (EJUSTRETURN);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef COMPAT_FREEBSD4
|
||||
/*
|
||||
* MPSAFE
|
||||
@ -734,6 +901,9 @@ ia32_setregs(struct thread *td, struct image_params *imgp, u_long stack)
|
||||
user_ldt_free(td);
|
||||
else
|
||||
mtx_unlock(&dt_lock);
|
||||
#ifdef COMPAT_43
|
||||
setup_lcall_gate();
|
||||
#endif
|
||||
|
||||
pcb->pcb_fsbase = 0;
|
||||
pcb->pcb_gsbase = 0;
|
||||
|
@ -66,6 +66,35 @@ freebsd4_ia32_sigcode:
|
||||
jmp 1b
|
||||
#endif
|
||||
|
||||
#ifdef COMPAT_43
|
||||
ALIGN_TEXT
|
||||
ia32_osigcode:
|
||||
calll *IA32_SIGF_HANDLER(%esp)/* call signal handler */
|
||||
leal IA32_SIGF_SC(%esp),%eax /* get sigcontext */
|
||||
pushl %eax
|
||||
movl $103,%eax /* 3.x SYS_sigreturn */
|
||||
pushl %eax /* junk to fake return addr. */
|
||||
int $0x80 /* enter kernel with args */
|
||||
1:
|
||||
jmp 1b
|
||||
|
||||
|
||||
ALIGN_TEXT
|
||||
lcall_tramp:
|
||||
pushl %ebp
|
||||
movl %esp,%ebp
|
||||
pushl 0x24(%ebp) /* arg 6 */
|
||||
pushl 0x20(%ebp)
|
||||
pushl 0x1c(%ebp)
|
||||
pushl 0x18(%ebp)
|
||||
pushl 0x14(%ebp)
|
||||
pushl 0x10(%ebp) /* arg 1 */
|
||||
pushl 0xc(%ebp) /* gap */
|
||||
int $0x80
|
||||
leave
|
||||
lretl
|
||||
#endif
|
||||
|
||||
ALIGN_TEXT
|
||||
esigcode:
|
||||
|
||||
@ -78,3 +107,11 @@ sz_ia32_sigcode:
|
||||
sz_freebsd4_ia32_sigcode:
|
||||
.long esigcode-freebsd4_ia32_sigcode
|
||||
#endif
|
||||
#ifdef COMPAT_43
|
||||
.globl sz_ia32_osigcode
|
||||
sz_ia32_osigcode:
|
||||
.long esigcode-ia32_osigcode
|
||||
.globl sz_lcall_tramp
|
||||
sz_lcall_tramp:
|
||||
.long esigcode-lcall_tramp
|
||||
#endif
|
||||
|
@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$");
|
||||
*/
|
||||
|
||||
#include "opt_clock.h"
|
||||
#include "opt_compat.h"
|
||||
#include "opt_cpu.h"
|
||||
#include "opt_isa.h"
|
||||
|
||||
@ -78,7 +79,17 @@ __FBSDID("$FreeBSD$");
|
||||
#include <machine/intr_machdep.h>
|
||||
#include <machine/md_var.h>
|
||||
|
||||
#include <compat/freebsd32/freebsd32_signal.h>
|
||||
#include <compat/freebsd32/freebsd32_util.h>
|
||||
#include <compat/ia32/ia32_signal.h>
|
||||
#include <machine/psl.h>
|
||||
#include <machine/segments.h>
|
||||
#include <machine/specialreg.h>
|
||||
#include <machine/sysarch.h>
|
||||
#include <machine/frame.h>
|
||||
#include <machine/md_var.h>
|
||||
#include <machine/pcb.h>
|
||||
#include <machine/cpufunc.h>
|
||||
|
||||
#define IDTVEC(name) __CONCAT(X,name)
|
||||
|
||||
@ -198,3 +209,45 @@ ia32_syscall_disable(void *dummy)
|
||||
|
||||
SYSINIT(ia32_syscall, SI_SUB_EXEC, SI_ORDER_ANY, ia32_syscall_enable, NULL);
|
||||
SYSUNINIT(ia32_syscall, SI_SUB_EXEC, SI_ORDER_ANY, ia32_syscall_disable, NULL);
|
||||
|
||||
#ifdef COMPAT_43
|
||||
int
|
||||
setup_lcall_gate(void)
|
||||
{
|
||||
struct i386_ldt_args uap;
|
||||
struct user_segment_descriptor descs[2];
|
||||
struct gate_descriptor *ssd;
|
||||
uint32_t lcall_addr;
|
||||
int error;
|
||||
|
||||
bzero(&uap, sizeof(uap));
|
||||
uap.start = 0;
|
||||
uap.num = 2;
|
||||
|
||||
/*
|
||||
* This is the easiest way to cut the space for system
|
||||
* descriptor in ldt. Manually adjust the descriptor type to
|
||||
* the call gate later.
|
||||
*/
|
||||
bzero(&descs[0], sizeof(descs));
|
||||
descs[0].sd_type = SDT_SYSNULL;
|
||||
descs[1].sd_type = SDT_SYSNULL;
|
||||
error = amd64_set_ldt(curthread, &uap, descs);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
lcall_addr = curproc->p_sysent->sv_psstrings - sz_lcall_tramp;
|
||||
mtx_lock(&dt_lock);
|
||||
ssd = (struct gate_descriptor *)(curproc->p_md.md_ldt->ldt_base);
|
||||
bzero(ssd, sizeof(*ssd));
|
||||
ssd->gd_looffset = lcall_addr;
|
||||
ssd->gd_hioffset = lcall_addr >> 16;
|
||||
ssd->gd_selector = _ucode32sel;
|
||||
ssd->gd_type = SDT_SYSCGT;
|
||||
ssd->gd_dpl = SEL_UPL;
|
||||
ssd->gd_p = 1;
|
||||
mtx_unlock(&dt_lock);
|
||||
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
@ -1454,6 +1454,29 @@ freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
|
||||
return (ftruncate(td, &ap));
|
||||
}
|
||||
|
||||
#ifdef COMPAT_43
|
||||
int
|
||||
ofreebsd32_getdirentries(struct thread *td,
|
||||
struct ofreebsd32_getdirentries_args *uap)
|
||||
{
|
||||
struct ogetdirentries_args ap;
|
||||
int error;
|
||||
long loff;
|
||||
int32_t loff_cut;
|
||||
|
||||
ap.fd = uap->fd;
|
||||
ap.buf = uap->buf;
|
||||
ap.count = uap->count;
|
||||
ap.basep = NULL;
|
||||
error = kern_ogetdirentries(td, &ap, &loff);
|
||||
if (error == 0) {
|
||||
loff_cut = loff;
|
||||
error = copyout(&loff_cut, uap->basep, sizeof(int32_t));
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
freebsd32_getdirentries(struct thread *td,
|
||||
struct freebsd32_getdirentries_args *uap)
|
||||
@ -1638,6 +1661,29 @@ copy_stat(struct stat *in, struct stat32 *out)
|
||||
TS_CP(*in, *out, st_birthtim);
|
||||
}
|
||||
|
||||
#ifdef COMPAT_43
|
||||
static void
|
||||
copy_ostat(struct stat *in, struct ostat32 *out)
|
||||
{
|
||||
|
||||
CP(*in, *out, st_dev);
|
||||
CP(*in, *out, st_ino);
|
||||
CP(*in, *out, st_mode);
|
||||
CP(*in, *out, st_nlink);
|
||||
CP(*in, *out, st_uid);
|
||||
CP(*in, *out, st_gid);
|
||||
CP(*in, *out, st_rdev);
|
||||
CP(*in, *out, st_size);
|
||||
TS_CP(*in, *out, st_atim);
|
||||
TS_CP(*in, *out, st_mtim);
|
||||
TS_CP(*in, *out, st_ctim);
|
||||
CP(*in, *out, st_blksize);
|
||||
CP(*in, *out, st_blocks);
|
||||
CP(*in, *out, st_flags);
|
||||
CP(*in, *out, st_gen);
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
|
||||
{
|
||||
@ -1653,6 +1699,23 @@ freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
|
||||
return (error);
|
||||
}
|
||||
|
||||
#ifdef COMPAT_43
|
||||
int
|
||||
ofreebsd32_stat(struct thread *td, struct ofreebsd32_stat_args *uap)
|
||||
{
|
||||
struct stat sb;
|
||||
struct ostat32 sb32;
|
||||
int error;
|
||||
|
||||
error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
|
||||
if (error)
|
||||
return (error);
|
||||
copy_ostat(&sb, &sb32);
|
||||
error = copyout(&sb32, uap->ub, sizeof (sb32));
|
||||
return (error);
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
|
||||
{
|
||||
@ -1668,6 +1731,23 @@ freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
|
||||
return (error);
|
||||
}
|
||||
|
||||
#ifdef COMPAT_43
|
||||
int
|
||||
ofreebsd32_fstat(struct thread *td, struct ofreebsd32_fstat_args *uap)
|
||||
{
|
||||
struct stat ub;
|
||||
struct ostat32 ub32;
|
||||
int error;
|
||||
|
||||
error = kern_fstat(td, uap->fd, &ub);
|
||||
if (error)
|
||||
return (error);
|
||||
copy_ostat(&ub, &ub32);
|
||||
error = copyout(&ub32, uap->ub, sizeof(ub32));
|
||||
return (error);
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
freebsd32_fstatat(struct thread *td, struct freebsd32_fstatat_args *uap)
|
||||
{
|
||||
@ -1698,9 +1778,23 @@ freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* MPSAFE
|
||||
*/
|
||||
#ifdef COMPAT_43
|
||||
int
|
||||
ofreebsd32_lstat(struct thread *td, struct ofreebsd32_lstat_args *uap)
|
||||
{
|
||||
struct stat sb;
|
||||
struct ostat32 sb32;
|
||||
int error;
|
||||
|
||||
error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
|
||||
if (error)
|
||||
return (error);
|
||||
copy_ostat(&sb, &sb32);
|
||||
error = copyout(&sb32, uap->ub, sizeof (sb32));
|
||||
return (error);
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
|
||||
{
|
||||
|
@ -117,9 +117,11 @@
|
||||
35 AUE_FCHFLAGS NOPROTO { int fchflags(int fd, int flags); }
|
||||
36 AUE_SYNC NOPROTO { int sync(void); }
|
||||
37 AUE_KILL NOPROTO { int kill(int pid, int signum); }
|
||||
38 AUE_STAT UNIMPL ostat
|
||||
38 AUE_STAT COMPAT { int freebsd32_stat(char *path, \
|
||||
struct ostat32 *ub); }
|
||||
39 AUE_GETPPID NOPROTO { pid_t getppid(void); }
|
||||
40 AUE_LSTAT UNIMPL olstat
|
||||
40 AUE_LSTAT COMPAT { int freebsd32_lstat(char *path, \
|
||||
struct ostat *ub); }
|
||||
41 AUE_DUP NOPROTO { int dup(u_int fd); }
|
||||
42 AUE_PIPE NOPROTO { int pipe(void); }
|
||||
43 AUE_GETEGID NOPROTO { gid_t getegid(void); }
|
||||
@ -153,9 +155,11 @@
|
||||
60 AUE_UMASK NOPROTO { int umask(int newmask); } umask \
|
||||
umask_args int
|
||||
61 AUE_CHROOT NOPROTO { int chroot(char *path); }
|
||||
62 AUE_FSTAT OBSOL ofstat
|
||||
62 AUE_FSTAT COMPAT { int freebsd32_fstat(int fd, \
|
||||
struct ostat32 *ub); }
|
||||
63 AUE_NULL OBSOL ogetkerninfo
|
||||
64 AUE_NULL OBSOL ogetpagesize
|
||||
64 AUE_NULL COMPAT { int freebsd32_getpagesize( \
|
||||
int32_t dummy); }
|
||||
65 AUE_MSYNC NOPROTO { int msync(void *addr, size_t len, \
|
||||
int flags); }
|
||||
66 AUE_VFORK NOPROTO { int vfork(void); }
|
||||
@ -210,7 +214,8 @@
|
||||
100 AUE_GETPRIORITY NOPROTO { int getpriority(int which, int who); }
|
||||
101 AUE_NULL OBSOL osend
|
||||
102 AUE_NULL OBSOL orecv
|
||||
103 AUE_NULL OBSOL osigreturn
|
||||
103 AUE_NULL COMPAT { int freebsd32_sigreturn( \
|
||||
struct ia32_sigcontext3 *sigcntxp); }
|
||||
104 AUE_BIND NOPROTO { int bind(int s, caddr_t name, \
|
||||
int namelen); }
|
||||
105 AUE_SETSOCKOPT NOPROTO { int setsockopt(int s, int level, \
|
||||
@ -292,7 +297,8 @@
|
||||
; 155 is initialized by the NFS code, if present.
|
||||
; XXX this is a problem!!!
|
||||
155 AUE_NFS_SVC UNIMPL nfssvc
|
||||
156 AUE_GETDIRENTRIES OBSOL ogetdirentries
|
||||
156 AUE_GETDIRENTRIES COMPAT { int freebsd32_getdirentries(int fd, \
|
||||
char *buf, u_int count, uint32_t *basep); }
|
||||
157 AUE_STATFS COMPAT4 { int freebsd32_statfs(char *path, \
|
||||
struct statfs32 *buf); }
|
||||
158 AUE_FSTATFS COMPAT4 { int freebsd32_fstatfs(int fd, \
|
||||
|
@ -13,6 +13,9 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
ASSYM(IA32_SIGF_HANDLER, offsetof(struct ia32_sigframe, sf_ah));
|
||||
ASSYM(IA32_SIGF_UC, offsetof(struct ia32_sigframe, sf_uc));
|
||||
#ifdef COMPAT_43
|
||||
ASSYM(IA32_SIGF_SC, offsetof(struct ia32_sigframe3, sf_siginfo.si_sc));
|
||||
#endif
|
||||
ASSYM(IA32_UC_GS, offsetof(struct ia32_ucontext, uc_mcontext.mc_gs));
|
||||
ASSYM(IA32_UC_FS, offsetof(struct ia32_ucontext, uc_mcontext.mc_fs));
|
||||
ASSYM(IA32_UC_ES, offsetof(struct ia32_ucontext, uc_mcontext.mc_es));
|
||||
|
@ -112,7 +112,7 @@ struct ia32_ucontext4 {
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef COMPAT_FREEBSD3
|
||||
#ifdef COMPAT_43
|
||||
struct ia32_sigcontext3 {
|
||||
u_int32_t sc_onstack;
|
||||
u_int32_t sc_mask;
|
||||
@ -165,7 +165,7 @@ struct ia32_sigframe {
|
||||
struct siginfo32 sf_si; /* = *sf_siginfo (SA_SIGINFO case) */
|
||||
};
|
||||
|
||||
#ifdef COMPAT_FREEBSD3
|
||||
#ifdef COMPAT_43
|
||||
struct ia32_siginfo3 {
|
||||
struct ia32_sigcontext3 si_sc;
|
||||
int si_signo;
|
||||
@ -186,10 +186,15 @@ struct ksiginfo;
|
||||
struct image_params;
|
||||
extern char ia32_sigcode[];
|
||||
extern char freebsd4_ia32_sigcode[];
|
||||
extern char ia32_osigcode[];
|
||||
extern char lcall_tramp;
|
||||
extern int sz_ia32_sigcode;
|
||||
extern int sz_freebsd4_ia32_sigcode;
|
||||
extern void ia32_sendsig(sig_t, struct ksiginfo *, sigset_t *);
|
||||
extern void ia32_setregs(struct thread *td, struct image_params *imgp,
|
||||
extern int sz_ia32_osigcode;
|
||||
extern int sz_lcall_tramp;
|
||||
void ia32_sendsig(sig_t, struct ksiginfo *, sigset_t *);
|
||||
void ia32_setregs(struct thread *td, struct image_params *imgp,
|
||||
u_long stack);
|
||||
int setup_lcall_gate(void);
|
||||
|
||||
#endif
|
||||
|
@ -95,14 +95,12 @@ CTASSERT(sizeof(struct ia32_sigframe4) == 408);
|
||||
|
||||
extern const char *freebsd32_syscallnames[];
|
||||
|
||||
static void ia32_fixlimit(struct rlimit *rl, int which);
|
||||
|
||||
SYSCTL_NODE(_compat, OID_AUTO, ia32, CTLFLAG_RW, 0, "ia32 mode");
|
||||
|
||||
static u_long ia32_maxdsiz = IA32_MAXDSIZ;
|
||||
SYSCTL_ULONG(_compat_ia32, OID_AUTO, maxdsiz, CTLFLAG_RW, &ia32_maxdsiz, 0, "");
|
||||
TUNABLE_ULONG("compat.ia32.maxdsiz", &ia32_maxdsiz);
|
||||
static u_long ia32_maxssiz = IA32_MAXSSIZ;
|
||||
u_long ia32_maxssiz = IA32_MAXSSIZ;
|
||||
SYSCTL_ULONG(_compat_ia32, OID_AUTO, maxssiz, CTLFLAG_RW, &ia32_maxssiz, 0, "");
|
||||
TUNABLE_ULONG("compat.ia32.maxssiz", &ia32_maxssiz);
|
||||
static u_long ia32_maxvmem = IA32_MAXVMEM;
|
||||
@ -206,7 +204,7 @@ elf32_dump_thread(struct thread *td __unused, void *dst __unused,
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
ia32_fixlimit(struct rlimit *rl, int which)
|
||||
{
|
||||
|
||||
|
@ -58,5 +58,6 @@
|
||||
struct syscall_args;
|
||||
int ia32_fetch_syscall_args(struct thread *td, struct syscall_args *sa);
|
||||
void ia32_set_syscall_retval(struct thread *, int);
|
||||
void ia32_fixlimit(struct rlimit *rl, int which);
|
||||
|
||||
#endif
|
||||
|
@ -48,3 +48,14 @@ freebsd32_sysarch(struct thread *td, struct freebsd32_sysarch_args *uap)
|
||||
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
#ifdef COMPAT_43
|
||||
int
|
||||
ofreebsd32_getpagesize(struct thread *td,
|
||||
struct ofreebsd32_getpagesize_args *uap)
|
||||
{
|
||||
|
||||
td->td_retval[0] = IA32_PAGE_SIZE;
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
@ -92,6 +92,15 @@ x) */
|
||||
};
|
||||
int sz_ia32_sigcode = sizeof(ia32_sigcode);
|
||||
|
||||
#ifdef COMPAT_43
|
||||
int
|
||||
ofreebsd32_sigreturn(struct thread *td, struct ofreebsd32_sigreturn_args *uap)
|
||||
{
|
||||
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Signal sending has not been implemented on ia64. This causes
|
||||
* the sigtramp code to not understand the arguments and the application
|
||||
|
@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/imgact.h>
|
||||
#include <sys/imgact_aout.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/limits.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mutex.h>
|
||||
@ -52,9 +53,18 @@ __FBSDID("$FreeBSD$");
|
||||
#include <vm/vm_object.h>
|
||||
#include <vm/vm_param.h>
|
||||
|
||||
#ifdef __amd64__
|
||||
#include <compat/freebsd32/freebsd32_signal.h>
|
||||
#include <compat/freebsd32/freebsd32_util.h>
|
||||
#include <compat/freebsd32/freebsd32_proto.h>
|
||||
#include <compat/freebsd32/freebsd32_syscall.h>
|
||||
#include <compat/ia32/ia32_signal.h>
|
||||
#endif
|
||||
|
||||
static int exec_aout_imgact(struct image_params *imgp);
|
||||
static int aout_fixup(register_t **stack_base, struct image_params *imgp);
|
||||
|
||||
#if defined(__i386__)
|
||||
struct sysentvec aout_sysvec = {
|
||||
.sv_size = SYS_MAXSYSCALL,
|
||||
.sv_table = sysent,
|
||||
@ -83,31 +93,69 @@ struct sysentvec aout_sysvec = {
|
||||
.sv_setregs = exec_setregs,
|
||||
.sv_fixlimit = NULL,
|
||||
.sv_maxssiz = NULL,
|
||||
.sv_flags = SV_ABI_FREEBSD | SV_AOUT |
|
||||
#if defined(__i386__)
|
||||
SV_IA32 | SV_ILP32
|
||||
#else
|
||||
#error Choose SV_XXX flags for the platform
|
||||
#endif
|
||||
,
|
||||
.sv_flags = SV_ABI_FREEBSD | SV_AOUT | SV_IA32 | SV_ILP32,
|
||||
.sv_set_syscall_retval = cpu_set_syscall_retval,
|
||||
.sv_fetch_syscall_args = cpu_fetch_syscall_args,
|
||||
.sv_syscallnames = syscallnames,
|
||||
.sv_schedtail = NULL,
|
||||
};
|
||||
|
||||
#elif defined(__amd64__)
|
||||
|
||||
#define AOUT32_USRSTACK 0xbfc0000
|
||||
#define AOUT32_PS_STRINGS \
|
||||
(AOUT32_USRSTACK - sizeof(struct freebsd32_ps_strings))
|
||||
|
||||
extern const char *freebsd32_syscallnames[];
|
||||
extern u_long ia32_maxssiz;
|
||||
|
||||
struct sysentvec aout_sysvec = {
|
||||
.sv_size = FREEBSD32_SYS_MAXSYSCALL,
|
||||
.sv_table = freebsd32_sysent,
|
||||
.sv_mask = 0,
|
||||
.sv_sigsize = 0,
|
||||
.sv_sigtbl = NULL,
|
||||
.sv_errsize = 0,
|
||||
.sv_errtbl = NULL,
|
||||
.sv_transtrap = NULL,
|
||||
.sv_fixup = aout_fixup,
|
||||
.sv_sendsig = ia32_sendsig,
|
||||
.sv_sigcode = ia32_sigcode,
|
||||
.sv_szsigcode = &sz_ia32_sigcode,
|
||||
.sv_prepsyscall = NULL,
|
||||
.sv_name = "FreeBSD a.out",
|
||||
.sv_coredump = NULL,
|
||||
.sv_imgact_try = NULL,
|
||||
.sv_minsigstksz = MINSIGSTKSZ,
|
||||
.sv_pagesize = IA32_PAGE_SIZE,
|
||||
.sv_minuser = 0,
|
||||
.sv_maxuser = AOUT32_USRSTACK,
|
||||
.sv_usrstack = AOUT32_USRSTACK,
|
||||
.sv_psstrings = AOUT32_PS_STRINGS,
|
||||
.sv_stackprot = VM_PROT_ALL,
|
||||
.sv_copyout_strings = freebsd32_copyout_strings,
|
||||
.sv_setregs = ia32_setregs,
|
||||
.sv_fixlimit = ia32_fixlimit,
|
||||
.sv_maxssiz = &ia32_maxssiz,
|
||||
.sv_flags = SV_ABI_FREEBSD | SV_AOUT | SV_IA32 | SV_ILP32,
|
||||
.sv_set_syscall_retval = ia32_set_syscall_retval,
|
||||
.sv_fetch_syscall_args = ia32_fetch_syscall_args,
|
||||
.sv_syscallnames = freebsd32_syscallnames,
|
||||
};
|
||||
#else
|
||||
#error "Port me"
|
||||
#endif
|
||||
|
||||
static int
|
||||
aout_fixup(stack_base, imgp)
|
||||
register_t **stack_base;
|
||||
struct image_params *imgp;
|
||||
aout_fixup(register_t **stack_base, struct image_params *imgp)
|
||||
{
|
||||
|
||||
return (suword(--(*stack_base), imgp->args->argc));
|
||||
*(char **)stack_base -= sizeof(uint32_t);
|
||||
return (suword(*stack_base, imgp->args->argc));
|
||||
}
|
||||
|
||||
static int
|
||||
exec_aout_imgact(imgp)
|
||||
struct image_params *imgp;
|
||||
exec_aout_imgact(struct image_params *imgp)
|
||||
{
|
||||
const struct exec *a_out = (const struct exec *) imgp->image_header;
|
||||
struct vmspace *vmspace;
|
||||
@ -175,7 +223,14 @@ exec_aout_imgact(imgp)
|
||||
a_out->a_entry >= virtual_offset + a_out->a_text ||
|
||||
|
||||
/* text and data size must each be page rounded */
|
||||
a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK)
|
||||
a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK
|
||||
|
||||
#ifdef __amd64__
|
||||
||
|
||||
/* overflows */
|
||||
virtual_offset + a_out->a_text + a_out->a_data + bss_size > UINT_MAX
|
||||
#endif
|
||||
)
|
||||
return (-1);
|
||||
|
||||
/* text + data can't exceed file size */
|
||||
|
@ -3898,14 +3898,20 @@ struct ogetdirentries_args {
|
||||
};
|
||||
#endif
|
||||
int
|
||||
ogetdirentries(td, uap)
|
||||
struct thread *td;
|
||||
register struct ogetdirentries_args /* {
|
||||
int fd;
|
||||
char *buf;
|
||||
u_int count;
|
||||
long *basep;
|
||||
} */ *uap;
|
||||
ogetdirentries(struct thread *td, struct ogetdirentries_args *uap)
|
||||
{
|
||||
long loff;
|
||||
int error;
|
||||
|
||||
error = kern_ogetdirentries(td, uap, &loff);
|
||||
if (error == 0)
|
||||
error = copyout(&loff, uap->basep, sizeof(long));
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
kern_ogetdirentries(struct thread *td, struct ogetdirentries_args *uap,
|
||||
long *ploff)
|
||||
{
|
||||
struct vnode *vp;
|
||||
struct file *fp;
|
||||
@ -4024,9 +4030,10 @@ ogetdirentries(td, uap)
|
||||
}
|
||||
VOP_UNLOCK(vp, 0);
|
||||
VFS_UNLOCK_GIANT(vfslocked);
|
||||
error = copyout(&loff, uap->basep, sizeof(long));
|
||||
fdrop(fp, td);
|
||||
td->td_retval[0] = uap->count - auio.uio_resid;
|
||||
if (error == 0)
|
||||
*ploff = loff;
|
||||
return (error);
|
||||
}
|
||||
#endif /* COMPAT_43 */
|
||||
|
@ -518,6 +518,7 @@ _snc= snc
|
||||
|
||||
.if ${MACHINE_CPUARCH} == "amd64"
|
||||
_aac= aac
|
||||
_aout= aout
|
||||
_acpi= acpi
|
||||
.if ${MK_CRYPT} != "no" || defined(ALL_MODULES)
|
||||
_aesni= aesni
|
||||
|
@ -52,6 +52,7 @@ struct kld_file_stat;
|
||||
struct ksiginfo;
|
||||
struct sendfile_args;
|
||||
struct thr_param;
|
||||
struct ogetdirentries_args;
|
||||
|
||||
int kern___getcwd(struct thread *td, u_char *buf, enum uio_seg bufseg,
|
||||
u_int buflen);
|
||||
@ -143,6 +144,8 @@ int kern_msgsnd(struct thread *, int, const void *, size_t, int, long);
|
||||
int kern_msgrcv(struct thread *, int, void *, size_t, long, int, long *);
|
||||
int kern_nanosleep(struct thread *td, struct timespec *rqt,
|
||||
struct timespec *rmt);
|
||||
int kern_ogetdirentries(struct thread *td, struct ogetdirentries_args *uap,
|
||||
long *ploff);
|
||||
int kern_open(struct thread *td, char *path, enum uio_seg pathseg,
|
||||
int flags, int mode);
|
||||
int kern_openat(struct thread *td, int fd, char *path,
|
||||
|
Loading…
Reference in New Issue
Block a user