linux mmap2
Patrick Bihan-Faou
bsdcvs-emul at mindstep.com
Thu Feb 26 00:07:40 PST 2004
Reid Linnemann wrote:
>Hey all, I've got a little dilemma I need some hints with...
>
>I am running FreeBSD 4.9-STABLE, and trying to get a linux binary operating
>that uses mmap2. I've read a conversation kenneth culver had about his efforts,
>and from what I can tell mmap2 is implemented in -CURRENT - but not in -STABLE.
>Is there any way I can grab the -CURRENT version of the linuxulator, or
>cut'n'paste the changes kenneth made, and get mmap2 working? I had found, and
>later lost, kenneths record of changes he made to the linuxulator - if anyone
>can point me to them I would appreciate that as well.
>
>
>
In addition to mmap2 you'll probably need the ftruncate64 call. Here is
a patch for FreeBSD 4.9 RELEASE that will add a few usefull syscalls.
The implementation usually comes from FreeBSD 5.x or other not yet
commited PRs. It has worked for me so far.
Patrick.
-------------- next part --------------
# This is a shell archive. Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file". Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
# .
# ./sys
# ./sys/compat
# ./sys/compat/linux
# ./sys/compat/linux/linux_file.c.patch
# ./sys/compat/linux/linux_ipc.c.patch
# ./sys/i386
# ./sys/i386/linux
# ./sys/i386/linux/linux.h.patch
# ./sys/i386/linux/linux_dummy.c.patch
# ./sys/i386/linux/linux_machdep.c.patch
# ./sys/i386/linux/linux_sysvec.c.patch
#
echo c - .
mkdir -p . > /dev/null 2>&1
echo c - ./sys
mkdir -p ./sys > /dev/null 2>&1
echo c - ./sys/compat
mkdir -p ./sys/compat > /dev/null 2>&1
echo c - ./sys/compat/linux
mkdir -p ./sys/compat/linux > /dev/null 2>&1
echo x - ./sys/compat/linux/linux_file.c.patch
sed 's/^X//' >./sys/compat/linux/linux_file.c.patch << 'SHAR-EOF-MARKER-73db4bcbd0dbd2530319f0beaf7528fd'
X--- linux_file.c.orig
X+++ linux_file.c
X@@ -654,6 +654,26 @@
X }
X
X int
X+linux_truncate64(struct proc *p, struct linux_truncate64_args *args)
X+{
X+ struct truncate_args bsd;
X+ caddr_t sg;
X+
X+ sg = stackgap_init();
X+ CHECKALTEXIST(p, &sg, args->path);
X+
X+#ifdef DEBUG
X+ if (ldebug(truncate))
X+ printf(ARGS(truncate, "%s, %ld"), args->path,
X+ (long)args->length);
X+#endif
X+ bsd.path = args->path;
X+ bsd.length = args->length;
X+
X+ return truncate(p, &bsd);
X+}
X+
X+int
X linux_link(struct proc *p, struct linux_link_args *args)
X {
X struct link_args bsd;
SHAR-EOF-MARKER-73db4bcbd0dbd2530319f0beaf7528fd
echo x - ./sys/compat/linux/linux_ipc.c.patch
sed 's/^X//' >./sys/compat/linux/linux_ipc.c.patch << 'SHAR-EOF-MARKER-567afdfde5ef3c7f68f72519ac8d7ca7'
X--- linux_ipc.c.orig
X+++ linux_ipc.c
X@@ -80,6 +80,20 @@
X l_ushort seq;
X };
X
X+struct l_ipc64_perm {
X+ l_key_t key;
X+ l_uid_t uid;
X+ l_gid_t gid;
X+ l_uid_t cuid;
X+ l_gid_t cgid;
X+ l_ushort mode;
X+ l_ushort __pad1;
X+ l_ushort seq;
X+ l_ushort __pad2;
X+ l_ulong __unused1;
X+ l_ulong __unused2;
X+};
X+
X static void
X linux_to_bsd_ipc_perm(struct l_ipc_perm *lpp, struct ipc_perm *bpp)
X {
X@@ -92,6 +106,18 @@
X bpp->seq = lpp->seq;
X }
X
X+static void
X+linux_to_bsd_ipc64_perm(struct l_ipc64_perm *lpp, struct ipc_perm *bpp)
X+{
X+ bpp->key = lpp->key;
X+ bpp->uid = lpp->uid;
X+ bpp->gid = lpp->gid;
X+ bpp->cuid = lpp->cuid;
X+ bpp->cgid = lpp->cgid;
X+ bpp->mode = lpp->mode;
X+ bpp->seq = lpp->seq;
X+}
X+
X
X static void
X bsd_to_linux_ipc_perm(struct ipc_perm *bpp, struct l_ipc_perm *lpp)
X@@ -105,6 +131,18 @@
X lpp->seq = bpp->seq;
X }
X
X+static void
X+bsd_to_linux_ipc64_perm(struct ipc_perm *bpp, struct l_ipc64_perm *lpp)
X+{
X+ lpp->key = bpp->key;
X+ lpp->uid = bpp->uid;
X+ lpp->gid = bpp->gid;
X+ lpp->cuid = bpp->cuid;
X+ lpp->cgid = bpp->cgid;
X+ lpp->mode = bpp->mode;
X+ lpp->seq = bpp->seq;
X+}
X+
X struct l_semid_ds {
X struct l_ipc_perm sem_perm;
X l_time_t sem_otime;
X@@ -116,6 +154,17 @@
X l_ushort sem_nsems;
X };
X
X+struct l_semid64_ds {
X+ struct l_ipc64_perm sem_perm;
X+ l_time_t sem_otime;
X+ l_time_t sem_ctime;
X+ void *sem_base;
X+ void *sem_pending;
X+ void *sem_pending_last;
X+ void *undo;
X+ l_ushort sem_nsems;
X+};
X+
X struct l_shmid_ds {
X struct l_ipc_perm shm_perm;
X l_int shm_segsz;
X@@ -130,6 +179,20 @@
X void *private3;
X };
X
X+struct l_shmid64_ds {
X+ struct l_ipc64_perm shm_perm;
X+ l_int shm_segsz;
X+ l_time_t shm_atime;
X+ l_time_t shm_dtime;
X+ l_time_t shm_ctime;
X+ l_ushort shm_cpid;
X+ l_ushort shm_lpid;
X+ l_short shm_nattch;
X+ l_ushort private1;
X+ void *private2;
X+ void *private3;
X+};
X+
X static void
X linux_to_bsd_semid_ds(struct l_semid_ds *lsp, struct semid_ds *bsp)
X {
X@@ -141,6 +204,16 @@
X }
X
X static void
X+linux_to_bsd_semid64_ds(struct l_semid64_ds *lsp, struct semid_ds *bsp)
X+{
X+ linux_to_bsd_ipc64_perm(&lsp->sem_perm, &bsp->sem_perm);
X+ bsp->sem_otime = lsp->sem_otime;
X+ bsp->sem_ctime = lsp->sem_ctime;
X+ bsp->sem_nsems = lsp->sem_nsems;
X+ bsp->sem_base = lsp->sem_base;
X+}
X+
X+static void
X bsd_to_linux_semid_ds(struct semid_ds *bsp, struct l_semid_ds *lsp)
X {
X bsd_to_linux_ipc_perm(&bsp->sem_perm, &lsp->sem_perm);
X@@ -151,6 +224,16 @@
X }
X
X static void
X+bsd_to_linux_semid64_ds(struct semid_ds *bsp, struct l_semid64_ds *lsp)
X+{
X+ bsd_to_linux_ipc64_perm(&bsp->sem_perm, &lsp->sem_perm);
X+ lsp->sem_otime = bsp->sem_otime;
X+ lsp->sem_ctime = bsp->sem_ctime;
X+ lsp->sem_nsems = bsp->sem_nsems;
X+ lsp->sem_base = bsp->sem_base;
X+}
X+
X+static void
X linux_to_bsd_shmid_ds(struct l_shmid_ds *lsp, struct shmid_ds *bsp)
X {
X linux_to_bsd_ipc_perm(&lsp->shm_perm, &bsp->shm_perm);
X@@ -163,6 +246,19 @@
X bsp->shm_ctime = lsp->shm_ctime;
X bsp->shm_internal = lsp->private3; /* this goes (yet) SOS */
X }
X+static void
X+linux_to_bsd_shmid64_ds(struct l_shmid64_ds *lsp, struct shmid_ds *bsp)
X+{
X+ linux_to_bsd_ipc64_perm(&lsp->shm_perm, &bsp->shm_perm);
X+ bsp->shm_segsz = lsp->shm_segsz;
X+ bsp->shm_lpid = lsp->shm_lpid;
X+ bsp->shm_cpid = lsp->shm_cpid;
X+ bsp->shm_nattch = lsp->shm_nattch;
X+ bsp->shm_atime = lsp->shm_atime;
X+ bsp->shm_dtime = lsp->shm_dtime;
X+ bsp->shm_ctime = lsp->shm_ctime;
X+ bsp->shm_internal = lsp->private3; /* this goes (yet) SOS */
X+}
X
X static void
X bsd_to_linux_shmid_ds(struct shmid_ds *bsp, struct l_shmid_ds *lsp)
X@@ -178,6 +274,20 @@
X lsp->private3 = bsp->shm_internal; /* this goes (yet) SOS */
X }
X
X+static void
X+bsd_to_linux_shmid64_ds(struct shmid_ds *bsp, struct l_shmid64_ds *lsp)
X+{
X+ bsd_to_linux_ipc64_perm(&bsp->shm_perm, &lsp->shm_perm);
X+ lsp->shm_segsz = bsp->shm_segsz;
X+ lsp->shm_lpid = bsp->shm_lpid;
X+ lsp->shm_cpid = bsp->shm_cpid;
X+ lsp->shm_nattch = bsp->shm_nattch;
X+ lsp->shm_atime = bsp->shm_atime;
X+ lsp->shm_dtime = bsp->shm_dtime;
X+ lsp->shm_ctime = bsp->shm_ctime;
X+ lsp->private3 = bsp->shm_internal; /* this goes (yet) SOS */
X+}
X+
X int
X linux_semop(struct proc *p, struct linux_semop_args *args)
X {
X@@ -212,6 +322,7 @@
X linux_semctl(struct proc *p, struct linux_semctl_args *args)
X {
X struct l_semid_ds linux_semid;
X+ struct l_semid64_ds linux_semid64;
X struct __semctl_args /* {
X int semid;
X int semnum;
X@@ -261,6 +372,15 @@
X unptr->buf = stackgap_alloc(&sg, sizeof(struct semid_ds));
X linux_to_bsd_semid_ds(&linux_semid, unptr->buf);
X return __semctl(p, &bsd_args);
X+ case LINUX_IPC_SET|LINUX_IPC_64:
X+ bsd_args.cmd = IPC_SET;
X+ error = copyin((caddr_t)args->arg.buf, &linux_semid64,
X+ sizeof(linux_semid64));
X+ if (error)
X+ return (error);
X+ unptr->buf = stackgap_alloc(&sg, sizeof(struct semid_ds));
X+ linux_to_bsd_semid64_ds(&linux_semid64, unptr->buf);
X+ return __semctl(p, &bsd_args);
X case LINUX_IPC_STAT:
X bsd_args.cmd = IPC_STAT;
X unptr->buf = stackgap_alloc(&sg, sizeof(struct semid_ds));
X@@ -272,6 +392,17 @@
X bsd_to_linux_semid_ds(unptr->buf, &linux_semid);
X return copyout(&linux_semid, (caddr_t)args->arg.buf,
X sizeof(linux_semid));
X+ case LINUX_IPC_STAT|LINUX_IPC_64:
X+ bsd_args.cmd = IPC_STAT;
X+ unptr->buf = stackgap_alloc(&sg, sizeof(struct semid_ds));
X+ error = __semctl(p, &bsd_args);
X+ if (error)
X+ return error;
X+ p->p_retval[0] = IXSEQ_TO_IPCID(bsd_args.semid,
X+ unptr->buf->sem_perm);
X+ bsd_to_linux_semid64_ds(unptr->buf, &linux_semid64);
X+ return copyout(&linux_semid64, (caddr_t)args->arg.buf,
X+ sizeof(linux_semid64));
X case LINUX_IPC_INFO:
X case LINUX_SEM_INFO:
X error = copyin((caddr_t)args->arg.buf, &linux_seminfo,
X@@ -421,6 +552,7 @@
X linux_shmctl(struct proc *p, struct linux_shmctl_args *args)
X {
X struct l_shmid_ds linux_shmid;
X+ struct l_shmid64_ds linux_shmid64;
X struct shmctl_args /* {
X int shmid;
X int cmd;
X@@ -439,6 +571,15 @@
X bsd_to_linux_shmid_ds(bsd_args.buf, &linux_shmid);
X return copyout(&linux_shmid, (caddr_t)args->buf, sizeof(linux_shmid));
X
X+ case LINUX_IPC_STAT|LINUX_IPC_64:
X+ bsd_args.shmid = args->shmid;
X+ bsd_args.cmd = IPC_STAT;
X+ bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
X+ if ((error = shmctl(p, &bsd_args)))
X+ return error;
X+ bsd_to_linux_shmid64_ds(bsd_args.buf, &linux_shmid64);
X+ return copyout(&linux_shmid64, (caddr_t)args->buf, sizeof(linux_shmid64));
X+
X case LINUX_IPC_SET:
X if ((error = copyin((caddr_t)args->buf, &linux_shmid,
X sizeof(linux_shmid))))
X@@ -449,6 +590,16 @@
X bsd_args.cmd = IPC_SET;
X return shmctl(p, &bsd_args);
X
X+ case LINUX_IPC_SET|LINUX_IPC_64:
X+ if ((error = copyin((caddr_t)args->buf, &linux_shmid64,
X+ sizeof(linux_shmid64))))
X+ return error;
X+ bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
X+ linux_to_bsd_shmid64_ds(&linux_shmid64, bsd_args.buf);
X+ bsd_args.shmid = args->shmid;
X+ bsd_args.cmd = IPC_SET;
X+ return shmctl(p, &bsd_args);
X+
X case LINUX_IPC_RMID:
X bsd_args.shmid = args->shmid;
X bsd_args.cmd = IPC_RMID;
X@@ -460,6 +611,20 @@
X return error;
X bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
X linux_to_bsd_shmid_ds(&linux_shmid, bsd_args.buf);
X+ }
X+ return shmctl(p, &bsd_args);
X+
X+ case LINUX_IPC_RMID|LINUX_IPC_64:
X+ bsd_args.shmid = args->shmid;
X+ bsd_args.cmd = IPC_RMID;
X+ if (args->buf == NULL)
X+ bsd_args.buf = NULL;
X+ else {
X+ if ((error = copyin((caddr_t)args->buf, &linux_shmid64,
X+ sizeof(linux_shmid64))))
X+ return error;
X+ bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
X+ linux_to_bsd_shmid64_ds(&linux_shmid64, bsd_args.buf);
X }
X return shmctl(p, &bsd_args);
X
SHAR-EOF-MARKER-567afdfde5ef3c7f68f72519ac8d7ca7
echo c - ./sys/i386
mkdir -p ./sys/i386 > /dev/null 2>&1
echo c - ./sys/i386/linux
mkdir -p ./sys/i386/linux > /dev/null 2>&1
echo x - ./sys/i386/linux/linux.h.patch
sed 's/^X//' >./sys/i386/linux/linux.h.patch << 'SHAR-EOF-MARKER-0e3d93c3f5eb4a3d5b1172cad960e4ba'
X--- linux.h.orig
X+++ linux.h
X@@ -532,6 +532,9 @@
X #define LINUX_IPC_STAT 2
X #define LINUX_IPC_INFO 3
X
X+#define LINUX_IPC_OLD 0
X+#define LINUX_IPC_64 0x0100
X+
X #define LINUX_SHM_LOCK 11
X #define LINUX_SHM_UNLOCK 12
X #define LINUX_SHM_STAT 13
SHAR-EOF-MARKER-0e3d93c3f5eb4a3d5b1172cad960e4ba
echo x - ./sys/i386/linux/linux_dummy.c.patch
sed 's/^X//' >./sys/i386/linux/linux_dummy.c.patch << 'SHAR-EOF-MARKER-1b3f6aae2a39aa5043a0bf5f1e7e0cb4'
X--- linux_dummy.c.orig
X+++ linux_dummy.c
X@@ -64,8 +64,8 @@
X DUMMY(capget);
X DUMMY(capset);
X DUMMY(sendfile);
X-DUMMY(mmap2);
X-DUMMY(truncate64);
X+/*DUMMY(mmap2);*/
X+/*DUMMY(truncate64);*/
X DUMMY(setfsuid);
X DUMMY(setfsgid);
X DUMMY(pivot_root);
SHAR-EOF-MARKER-1b3f6aae2a39aa5043a0bf5f1e7e0cb4
echo x - ./sys/i386/linux/linux_machdep.c.patch
sed 's/^X//' >./sys/i386/linux/linux_machdep.c.patch << 'SHAR-EOF-MARKER-013eaf3882bdcd8e8dd36a2101827a2e'
X--- linux_machdep.c.orig
X+++ linux_machdep.c
X@@ -381,6 +381,120 @@
X #define GUARD_SIZE (4 * PAGE_SIZE)
X
X int
X+linux_mmap2(struct proc *p, struct linux_mmap2_args *linux_args)
X+{
X+ struct mmap_args /* {
X+ caddr_t addr;
X+ size_t len;
X+ int prot;
X+ int flags;
X+ int fd;
X+ long pad;
X+ off_t pos;
X+ } */ bsd_args;
X+
X+#ifdef DEBUG
X+ if (ldebug(mmap2))
X+ printf(ARGS(mmap2, "%p, %d, %d, 0x%08x, %d, %d"),
X+ (void *)linux_args->addr, linux_args->len, linux_args->prot,
X+ linux_args->flags, linux_args->fd, linux_args->pos);
X+#endif
X+
X+ bsd_args.flags = 0;
X+ if (linux_args->flags & LINUX_MAP_SHARED)
X+ bsd_args.flags |= MAP_SHARED;
X+ if (linux_args->flags & LINUX_MAP_PRIVATE)
X+ bsd_args.flags |= MAP_PRIVATE;
X+ if (linux_args->flags & LINUX_MAP_FIXED)
X+ bsd_args.flags |= MAP_FIXED;
X+ if (linux_args->flags & LINUX_MAP_ANON)
X+ bsd_args.flags |= MAP_ANON;
X+ else
X+ bsd_args.flags |= MAP_NOSYNC;
X+ if (linux_args->flags & LINUX_MAP_GROWSDOWN) {
X+ bsd_args.flags |= MAP_STACK;
X+
X+ /* The linux MAP_GROWSDOWN option does not limit auto
X+ * growth of the region. Linux mmap with this option
X+ * takes as addr the inital BOS, and as len, the initial
X+ * region size. It can then grow down from addr without
X+ * limit. However, linux threads has an implicit internal
X+ * limit to stack size of STACK_SIZE. Its just not
X+ * enforced explicitly in linux. But, here we impose
X+ * a limit of (STACK_SIZE - GUARD_SIZE) on the stack
X+ * region, since we can do this with our mmap.
X+ *
X+ * Our mmap with MAP_STACK takes addr as the maximum
X+ * downsize limit on BOS, and as len the max size of
X+ * the region. It them maps the top SGROWSIZ bytes,
X+ * and autgrows the region down, up to the limit
X+ * in addr.
X+ *
X+ * If we don't use the MAP_STACK option, the effect
X+ * of this code is to allocate a stack region of a
X+ * fixed size of (STACK_SIZE - GUARD_SIZE).
X+ */
X+
X+ /* This gives us TOS */
X+ bsd_args.addr = (caddr_t)(linux_args->addr + linux_args->len);
X+
X+ if (bsd_args.addr > p->p_vmspace->vm_maxsaddr) {
X+ /* Some linux apps will attempt to mmap
X+ * thread stacks near the top of their
X+ * address space. If their TOS is greater
X+ * than vm_maxsaddr, vm_map_growstack()
X+ * will confuse the thread stack with the
X+ * process stack and deliver a SEGV if they
X+ * attempt to grow the thread stack past their
X+ * current stacksize rlimit. To avoid this,
X+ * adjust vm_maxsaddr upwards to reflect
X+ * the current stacksize rlimit rather
X+ * than the maximum possible stacksize.
X+ * It would be better to adjust the
X+ * mmap'ed region, but some apps do not check
X+ * mmap's return value.
X+ */
X+ p->p_vmspace->vm_maxsaddr = (char *)USRSTACK -
X+ p->p_rlimit[RLIMIT_STACK].rlim_cur;
X+ }
X+
X+ /* This gives us our maximum stack size */
X+ if (linux_args->len > STACK_SIZE - GUARD_SIZE)
X+ bsd_args.len = linux_args->len;
X+ else
X+ bsd_args.len = STACK_SIZE - GUARD_SIZE;
X+
X+ /* This gives us a new BOS. If we're using VM_STACK, then
X+ * mmap will just map the top SGROWSIZ bytes, and let
X+ * the stack grow down to the limit at BOS. If we're
X+ * not using VM_STACK we map the full stack, since we
X+ * don't have a way to autogrow it.
X+ */
X+ bsd_args.addr -= bsd_args.len;
X+ } else {
X+ bsd_args.addr = (caddr_t)linux_args->addr;
X+ bsd_args.len = linux_args->len;
X+ }
X+
X+ bsd_args.prot = linux_args->prot | PROT_READ; /* always required */
X+ if (linux_args->flags & LINUX_MAP_ANON)
X+ bsd_args.fd = -1;
X+ else
X+ bsd_args.fd = linux_args->fd;
X+ bsd_args.pos = ctob(linux_args->pgoff);
X+ bsd_args.pad = 0;
X+
X+#ifdef DEBUG
X+ if (ldebug(mmap2))
X+ printf("-> (%p, %d, %d, 0x%08x, %d, %d)\n",
X+ (void *)bsd_args.addr, bsd_args.len, bsd_args.prot,
X+ bsd_args.flags, bsd_args.fd, (int)bsd_args.pos);
X+#endif
X+
X+ return (mmap(p, &bsd_args));
X+}
X+
X+int
X linux_mmap(struct proc *p, struct linux_mmap_args *args)
X {
X struct mmap_args /* {
SHAR-EOF-MARKER-013eaf3882bdcd8e8dd36a2101827a2e
echo x - ./sys/i386/linux/linux_sysvec.c.patch
sed 's/^X//' >./sys/i386/linux/linux_sysvec.c.patch << 'SHAR-EOF-MARKER-5063296fed19fdb032d23975e4efcbfc'
X--- linux_sysvec.c.orig
X+++ linux_sysvec.c
X@@ -722,6 +722,7 @@
X args[2] = tf->tf_edx;
X args[3] = tf->tf_esi;
X args[4] = tf->tf_edi;
X+ args[5] = tf->tf_ebp; /* tf_ebp taken from linux glibc sources */
X *params = NULL; /* no copyin */
X }
X
SHAR-EOF-MARKER-5063296fed19fdb032d23975e4efcbfc
exit
More information about the freebsd-emulation
mailing list