summaryrefslogtreecommitdiffstats
path: root/sys/compat
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2011-04-01 11:16:29 +0000
committerkib <kib@FreeBSD.org>2011-04-01 11:16:29 +0000
commit7c2eaa21fe792c26e223a2f36a4f5c00fdaf52d8 (patch)
tree601aa0131bd58a0facc71b1b7c7b138597686fbe /sys/compat
parent6d6007bc145d7665435f03f2ff2043e14240d09e (diff)
downloadFreeBSD-src-7c2eaa21fe792c26e223a2f36a4f5c00fdaf52d8.zip
FreeBSD-src-7c2eaa21fe792c26e223a2f36a4f5c00fdaf52d8.tar.gz
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
Diffstat (limited to 'sys/compat')
-rw-r--r--sys/compat/freebsd32/freebsd32_misc.c100
-rw-r--r--sys/compat/freebsd32/syscalls.master18
-rw-r--r--sys/compat/ia32/ia32_genassym.c3
-rw-r--r--sys/compat/ia32/ia32_signal.h13
-rw-r--r--sys/compat/ia32/ia32_sysvec.c6
-rw-r--r--sys/compat/ia32/ia32_util.h1
6 files changed, 124 insertions, 17 deletions
diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c
index e751147..5772c0e 100644
--- a/sys/compat/freebsd32/freebsd32_misc.c
+++ b/sys/compat/freebsd32/freebsd32_misc.c
@@ -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)
{
diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master
index 8a4cadf..da42133 100644
--- a/sys/compat/freebsd32/syscalls.master
+++ b/sys/compat/freebsd32/syscalls.master
@@ -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, \
diff --git a/sys/compat/ia32/ia32_genassym.c b/sys/compat/ia32/ia32_genassym.c
index 84fb648..5462a8b 100644
--- a/sys/compat/ia32/ia32_genassym.c
+++ b/sys/compat/ia32/ia32_genassym.c
@@ -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));
diff --git a/sys/compat/ia32/ia32_signal.h b/sys/compat/ia32/ia32_signal.h
index 757e384..0c54caf 100644
--- a/sys/compat/ia32/ia32_signal.h
+++ b/sys/compat/ia32/ia32_signal.h
@@ -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
diff --git a/sys/compat/ia32/ia32_sysvec.c b/sys/compat/ia32/ia32_sysvec.c
index a7790ef..c7edac4 100644
--- a/sys/compat/ia32/ia32_sysvec.c
+++ b/sys/compat/ia32/ia32_sysvec.c
@@ -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)
{
diff --git a/sys/compat/ia32/ia32_util.h b/sys/compat/ia32/ia32_util.h
index 4355daa..f153492 100644
--- a/sys/compat/ia32/ia32_util.h
+++ b/sys/compat/ia32/ia32_util.h
@@ -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
OpenPOWER on IntegriCloud