qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 09/18] bsd-user: add support for freebsd process rel


From: Stacey Son
Subject: [Qemu-devel] [PATCH 09/18] bsd-user: add support for freebsd process related system calls
Date: Wed, 16 Oct 2013 09:37:03 -0500

This change add support or stubs for process related system calls including
fork(2), vfork(2), rfork(2), pdfork(2), execve(2), fexecve(2), wait4(2), 
exit(2),
getgroups(2), setgroups(2), umask(2), setlogin(2), getlogin(2), getrusage(2),
getrlimit(2), setrlimit(2), getpid(2), getppid(2), getuid(2), geteuid(2),
getgid(2), getegid(2), setuid(2), seteuid(2), setgid(2), setegid(2), getpgrp(2),
setreuid(2), setregid(2), getresuid(2), getresgid(2), getsid(2), setsid(2),
issetugid(2), profil(2), ktrace(2), setloginclass(2), getloginclass(2),
pdgetpid(2), jail*(2), cap_*(2), *audit*(2), utrace(2), ptrace(2), 
getpriority(2),
and setpriority(2).

Signed-off-by: Stacey Son <address@hidden>
---
 bsd-user/Makefile.objs     |    4 +-
 bsd-user/bsd-proc.c        |  160 ++++++++++++++++
 bsd-user/bsd-proc.h        |  434 ++++++++++++++++++++++++++++++++++++++++++++
 bsd-user/freebsd/os-proc.c |  234 ++++++++++++++++++++++++
 bsd-user/freebsd/os-proc.h |  428 +++++++++++++++++++++++++++++++++++++++++++
 bsd-user/netbsd/os-proc.c  |   11 +
 bsd-user/netbsd/os-proc.h  |  243 +++++++++++++++++++++++++
 bsd-user/openbsd/os-proc.c |   11 +
 bsd-user/openbsd/os-proc.h |  243 +++++++++++++++++++++++++
 bsd-user/qemu-bsd.h        |   43 +++++
 bsd-user/qemu.h            |    4 +
 bsd-user/syscall.c         |  262 ++++++++++++++++++++++++++-
 12 files changed, 2069 insertions(+), 8 deletions(-)
 create mode 100644 bsd-user/bsd-proc.c
 create mode 100644 bsd-user/bsd-proc.h
 create mode 100644 bsd-user/freebsd/os-proc.c
 create mode 100644 bsd-user/freebsd/os-proc.h
 create mode 100644 bsd-user/netbsd/os-proc.c
 create mode 100644 bsd-user/netbsd/os-proc.h
 create mode 100644 bsd-user/openbsd/os-proc.c
 create mode 100644 bsd-user/openbsd/os-proc.h
 create mode 100644 bsd-user/qemu-bsd.h

diff --git a/bsd-user/Makefile.objs b/bsd-user/Makefile.objs
index d92961a..6a2fc37 100644
--- a/bsd-user/Makefile.objs
+++ b/bsd-user/Makefile.objs
@@ -1,3 +1,5 @@
 obj-y = main.o bsdload.o elfload.o mmap.o signal.o strace.o syscall.o \
-               uaccess.o $(HOST_ABI_DIR)/os-sys.o \
+               uaccess.o bsd-proc.o \
+                       $(HOST_ABI_DIR)/os-proc.o \
+                       $(HOST_ABI_DIR)/os-sys.o \
                        $(HOST_ABI_DIR)/os-time.o 
$(TARGET_ABI_DIR)/target_arch_cpu.o
diff --git a/bsd-user/bsd-proc.c b/bsd-user/bsd-proc.c
new file mode 100644
index 0000000..a4bcdc8
--- /dev/null
+++ b/bsd-user/bsd-proc.c
@@ -0,0 +1,160 @@
+/*
+ *  BSD process related system call helpers
+ *
+ *  Copyright (c) 2013 Stacey D. Son
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+
+#include "qemu.h"
+#include "qemu-bsd.h"
+
+/*
+ * resource/rusage conversion
+ */
+int target_to_host_resource(int code)
+{
+
+    switch (code) {
+    case TARGET_RLIMIT_AS:
+        return RLIMIT_AS;
+
+    case TARGET_RLIMIT_CORE:
+        return RLIMIT_CORE;
+
+    case TARGET_RLIMIT_CPU:
+        return RLIMIT_CPU;
+
+    case TARGET_RLIMIT_DATA:
+        return RLIMIT_DATA;
+
+    case TARGET_RLIMIT_FSIZE:
+        return RLIMIT_FSIZE;
+
+    case TARGET_RLIMIT_MEMLOCK:
+        return RLIMIT_MEMLOCK;
+
+    case TARGET_RLIMIT_NOFILE:
+        return RLIMIT_NOFILE;
+
+    case TARGET_RLIMIT_NPROC:
+        return RLIMIT_NPROC;
+
+    case TARGET_RLIMIT_RSS:
+        return RLIMIT_RSS;
+
+    case TARGET_RLIMIT_SBSIZE:
+        return RLIMIT_SBSIZE;
+
+    case TARGET_RLIMIT_STACK:
+        return RLIMIT_STACK;
+
+    case TARGET_RLIMIT_SWAP:
+        return RLIMIT_SWAP;
+
+    case TARGET_RLIMIT_NPTS:
+        return RLIMIT_NPTS;
+
+    default:
+        return code;
+    }
+}
+
+rlim_t target_to_host_rlim(abi_ulong target_rlim)
+{
+    abi_ulong target_rlim_swap;
+    rlim_t result;
+
+    target_rlim_swap = tswapal(target_rlim);
+    if (target_rlim_swap == TARGET_RLIM_INFINITY) {
+        return RLIM_INFINITY;
+    }
+
+    result = target_rlim_swap;
+    if (target_rlim_swap != (rlim_t)result) {
+        return RLIM_INFINITY;
+    }
+
+    return result;
+}
+
+abi_ulong host_to_target_rlim(rlim_t rlim)
+{
+    abi_ulong target_rlim_swap;
+    abi_ulong result;
+
+    if (rlim == RLIM_INFINITY || rlim != (abi_long)rlim) {
+        target_rlim_swap = TARGET_RLIM_INFINITY;
+    } else {
+        target_rlim_swap = rlim;
+    }
+    result = tswapal(target_rlim_swap);
+
+    return result;
+}
+
+abi_long host_to_target_rusage(abi_ulong target_addr,
+        const struct rusage *rusage)
+{
+    struct target_freebsd_rusage *target_rusage;
+
+    if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0)) {
+        return -TARGET_EFAULT;
+    }
+    __put_user(rusage->ru_utime.tv_sec, &target_rusage->ru_utime.tv_sec);
+    __put_user(rusage->ru_utime.tv_usec, &target_rusage->ru_utime.tv_usec);
+
+    __put_user(rusage->ru_stime.tv_sec, &target_rusage->ru_stime.tv_sec);
+    __put_user(rusage->ru_stime.tv_usec, &target_rusage->ru_stime.tv_usec);
+
+    __put_user(rusage->ru_maxrss, &target_rusage->ru_maxrss);
+    __put_user(rusage->ru_idrss, &target_rusage->ru_idrss);
+    __put_user(rusage->ru_idrss, &target_rusage->ru_idrss);
+    __put_user(rusage->ru_isrss, &target_rusage->ru_isrss);
+    __put_user(rusage->ru_minflt, &target_rusage->ru_minflt);
+    __put_user(rusage->ru_majflt, &target_rusage->ru_majflt);
+    __put_user(rusage->ru_nswap, &target_rusage->ru_nswap);
+    __put_user(rusage->ru_inblock, &target_rusage->ru_inblock);
+    __put_user(rusage->ru_oublock, &target_rusage->ru_oublock);
+    __put_user(rusage->ru_msgsnd, &target_rusage->ru_msgsnd);
+    __put_user(rusage->ru_msgrcv, &target_rusage->ru_msgrcv);
+    __put_user(rusage->ru_nsignals, &target_rusage->ru_nsignals);
+    __put_user(rusage->ru_nvcsw, &target_rusage->ru_nvcsw);
+    __put_user(rusage->ru_nivcsw, &target_rusage->ru_nivcsw);
+    unlock_user_struct(target_rusage, target_addr, 1);
+
+    return 0;
+}
+
+/*
+ * wait status conversion.
+ *
+ * Map host to target signal numbers for the wait family of syscalls.
+ * Assume all other status bits are the same.
+ */
+int host_to_target_waitstatus(int status)
+{
+    if (WIFSIGNALED(status)) {
+        return host_to_target_signal(WTERMSIG(status)) | (status & ~0x7f);
+    }
+    if (WIFSTOPPED(status)) {
+        return (host_to_target_signal(WSTOPSIG(status)) << 8) | (status & 
0xff);
+    }
+    return status;
+}
+
diff --git a/bsd-user/bsd-proc.h b/bsd-user/bsd-proc.h
new file mode 100644
index 0000000..d1c732a
--- /dev/null
+++ b/bsd-user/bsd-proc.h
@@ -0,0 +1,434 @@
+/*
+ *  process related system call shims and definitions
+ *
+ *  Copyright (c) 2013 Stacey D. Son
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __BSD_PROC_H_
+#define __BSD_PROC_H_
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <unistd.h>
+
+#include "qemu-bsd.h"
+
+extern int _getlogin(char*, int);
+
+/* exit(2) */
+static inline abi_long do_bsd_exit(void *cpu_env, abi_long arg1)
+{
+#ifdef TARGET_GPROF
+    _mcleanup();
+#endif
+    gdb_exit(cpu_env, arg1);
+    /* XXX: should free thread stack and CPU env here  */
+    _exit(arg1);
+
+    return 0;
+}
+
+/* getgroups(2) */
+static inline abi_long do_bsd_getgroups(abi_long gidsetsize, abi_long arg2)
+{
+    abi_long ret;
+    uint32_t *target_grouplist;
+    gid_t *grouplist;
+    int i;
+
+    grouplist = alloca(gidsetsize * sizeof(gid_t));
+    ret = get_errno(getgroups(gidsetsize, grouplist));
+    if (gidsetsize != 0) {
+        if (!is_error(ret)) {
+            target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 2, 
0);
+            if (!target_grouplist) {
+                return -TARGET_EFAULT;
+            }
+            for (i = 0; i < ret; i++) {
+                target_grouplist[i] = tswap32(grouplist[i]);
+            }
+            unlock_user(target_grouplist, arg2, gidsetsize * 2);
+        }
+    }
+    return ret;
+}
+
+/* setgroups(2) */
+static inline abi_long do_bsd_setgroups(abi_long gidsetsize, abi_long arg2)
+{
+    uint32_t *target_grouplist;
+    gid_t *grouplist;
+    int i;
+
+    grouplist = alloca(gidsetsize * sizeof(gid_t));
+    target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 2, 1);
+    if (!target_grouplist) {
+        return -TARGET_EFAULT;
+    }
+    for (i = 0; i < gidsetsize; i++) {
+        grouplist[i] = tswap32(target_grouplist[i]);
+    }
+    unlock_user(target_grouplist, arg2, 0);
+    return get_errno(setgroups(gidsetsize, grouplist));
+}
+
+/* umask(2) */
+static inline abi_long do_bsd_umask(abi_long arg1)
+{
+
+    return get_errno(umask(arg1));
+}
+
+/* setlogin(2) */
+static inline abi_long do_bsd_setlogin(abi_long arg1)
+{
+    abi_long ret;
+    void *p;
+
+    p = lock_user_string(arg1);
+    if (p == NULL) {
+        return -TARGET_EFAULT;
+    }
+    ret = get_errno(setlogin(p));
+    unlock_user(p, arg1, 0);
+
+    return ret;
+}
+
+/* getlogin(2) */
+static inline abi_long do_bsd_getlogin(abi_long arg1, abi_long arg2)
+{
+    abi_long ret;
+    void *p;
+
+    p = lock_user_string(arg1);
+    if (p == NULL) {
+        return -TARGET_EFAULT;
+    }
+    ret = get_errno(_getlogin(p, arg2));
+    unlock_user(p, arg1, 0);
+
+    return ret;
+}
+
+/* getrusage(2) */
+static inline abi_long do_bsd_getrusage(abi_long who, abi_ulong target_addr)
+{
+    abi_long ret;
+    struct rusage rusage;
+
+    ret = get_errno(getrusage(who, &rusage));
+    if (!is_error(ret)) {
+        host_to_target_rusage(target_addr, &rusage);
+    }
+    return ret;
+}
+
+/* getrlimit(2) */
+static inline abi_long do_bsd_getrlimit(abi_long arg1, abi_ulong arg2)
+{
+    abi_long ret;
+    int resource = target_to_host_resource(arg1);
+    struct target_rlimit *target_rlim;
+    struct rlimit rlim;
+
+    switch (resource) {
+    case RLIMIT_STACK:
+        rlim.rlim_cur = target_dflssiz;
+        rlim.rlim_max = target_maxssiz;
+        ret = 0;
+        break;
+
+    case RLIMIT_DATA:
+        rlim.rlim_cur = target_dfldsiz;
+        rlim.rlim_max = target_maxdsiz;
+        ret = 0;
+        break;
+
+    default:
+        ret = get_errno(getrlimit(resource, &rlim));
+        break;
+    }
+    if (!is_error(ret)) {
+        if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0)) {
+            return -TARGET_EFAULT;
+        }
+        target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
+        target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
+        unlock_user_struct(target_rlim, arg2, 1);
+    }
+    return ret;
+}
+
+/* setrlimit(2) */
+static inline abi_long do_bsd_setrlimit(abi_long arg1, abi_ulong arg2)
+{
+    abi_long ret;
+    int resource = target_to_host_resource(arg1);
+    struct target_rlimit *target_rlim;
+    struct rlimit rlim;
+
+    if (RLIMIT_STACK == resource) {
+        /* XXX We should, maybe, allow the stack size to shrink */
+        ret = -TARGET_EPERM;
+    } else {
+        if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1)) {
+            return -TARGET_EFAULT;
+        }
+        rlim.rlim_cur = target_to_host_rlim(target_rlim->rlim_cur);
+        rlim.rlim_max = target_to_host_rlim(target_rlim->rlim_max);
+        unlock_user_struct(target_rlim, arg2, 0);
+        ret = get_errno(setrlimit(resource, &rlim));
+    }
+    return ret;
+}
+
+/* getpid(2) */
+static inline abi_long do_bsd_getpid(void)
+{
+
+    return get_errno(getpid());
+}
+
+/* getppid(2) */
+static inline abi_long do_bsd_getppid(void)
+{
+
+    return get_errno(getppid());
+}
+
+/* getuid(2) */
+static inline abi_long do_bsd_getuid(void)
+{
+
+    return get_errno(getuid());
+}
+
+/* geteuid(2) */
+static inline abi_long do_bsd_geteuid(void)
+{
+
+    return get_errno(geteuid());
+}
+
+/* getgid(2) */
+static inline abi_long do_bsd_getgid(void)
+{
+
+    return get_errno(getgid());
+}
+
+/* getegid(2) */
+static inline abi_long do_bsd_getegid(void)
+{
+
+    return get_errno(getegid());
+}
+
+/* setuid(2) */
+static inline abi_long do_bsd_setuid(abi_long arg1)
+{
+
+    return get_errno(setuid(arg1));
+}
+
+/* seteuid(2) */
+static inline abi_long do_bsd_seteuid(abi_long arg1)
+{
+
+    return get_errno(seteuid(arg1));
+}
+
+/* setgid(2) */
+static inline abi_long do_bsd_setgid(abi_long arg1)
+{
+
+    return get_errno(setgid(arg1));
+}
+
+/* setegid(2) */
+static inline abi_long do_bsd_setegid(abi_long arg1)
+{
+
+    return get_errno(setegid(arg1));
+}
+
+/* getpgrp(2) */
+static inline abi_long do_bsd_getpgrp(void)
+{
+
+    return get_errno(getpgrp());
+}
+
+/* setreuid(2) */
+static inline abi_long do_bsd_setreuid(abi_long arg1, abi_long arg2)
+{
+
+    return get_errno(setreuid(arg1, arg2));
+}
+
+/* setregid(2) */
+static inline abi_long do_bsd_setregid(abi_long arg1, abi_long arg2)
+{
+
+    return get_errno(setregid(arg1, arg2));
+}
+
+/* setresuid(2) */
+static inline abi_long do_bsd_setresuid(abi_long arg1, abi_long arg2,
+        abi_long arg3)
+{
+
+    return get_errno(setresuid(arg1, arg2, arg3));
+}
+
+/* getresuid(2) */
+static inline abi_long do_bsd_getresuid(abi_ulong arg1, abi_ulong arg2,
+        abi_ulong arg3)
+{
+    abi_long ret;
+    uid_t ruid, euid, suid;
+
+    ret = get_errno(getresuid(&ruid, &euid, &suid));
+    if (is_error(ret)) {
+            return ret;
+    }
+    if (put_user_s32(ruid, arg1)) {
+        return -TARGET_EFAULT;
+    }
+    if (put_user_s32(euid, arg2)) {
+        return -TARGET_EFAULT;
+    }
+    if (put_user_s32(suid, arg3)) {
+        return -TARGET_EFAULT;
+    }
+    return ret;
+}
+
+/* getresgid(2) */
+static inline abi_long do_bsd_getresgid(abi_ulong arg1, abi_ulong arg2,
+        abi_ulong arg3)
+{
+    abi_long ret;
+    uid_t ruid, euid, suid;
+
+    ret = get_errno(getresgid(&ruid, &euid, &suid));
+    if (is_error(ret)) {
+            return ret;
+    }
+    if (put_user_s32(ruid, arg1)) {
+        return -TARGET_EFAULT;
+    }
+    if (put_user_s32(euid, arg2)) {
+        return -TARGET_EFAULT;
+    }
+    if (put_user_s32(suid, arg3)) {
+        return -TARGET_EFAULT;
+    }
+    return ret;
+}
+
+/* getsid(2) */
+static inline abi_long do_bsd_getsid(abi_long arg1)
+{
+
+    return get_errno(getsid(arg1));
+}
+
+/* setsid(2) */
+static inline abi_long do_bsd_setsid(void)
+{
+
+    return get_errno(setsid());
+}
+
+/* issetugid(2) */
+static inline abi_long do_bsd_issetugid(void)
+{
+
+    return get_errno(issetugid());
+}
+
+/* profil(2) */
+static inline abi_long do_bsd_profil(abi_long arg1, abi_long arg2,
+        abi_long arg3, abi_long arg4)
+{
+
+    qemu_log("qemu: Unsupported syscall profil()\n");
+    return -TARGET_ENOSYS;
+}
+
+
+/* ktrace(2) */
+static inline abi_long do_bsd_ktrace(abi_long arg1, abi_long arg2,
+        abi_long arg3, abi_long arg4)
+{
+
+    qemu_log("qemu: Unsupported syscall ktrace()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* utrace(2) */
+static inline abi_long do_bsd_utrace(abi_long arg1, abi_long arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall ptrace()\n");
+    return -TARGET_ENOSYS;
+}
+
+
+/* ptrace(2) */
+static inline abi_long do_bsd_ptrace(abi_long arg1, abi_long arg2,
+        abi_long arg3, abi_long arg4)
+{
+
+    qemu_log("qemu: Unsupported syscall ptrace()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* getpriority(2) */
+static inline abi_long do_bsd_getpriority(abi_long which, abi_long who)
+{
+    abi_long ret;
+    /*
+     * Note that negative values are valid for getpriority, so we must
+     * differentiate based on errno settings.
+     */
+    errno = 0;
+    ret = getpriority(which, who);
+    if (ret == -1 && errno != 0) {
+        ret = -host_to_target_errno(errno);
+        return ret;
+    }
+    /* Return value is a biased priority to avoid negative numbers. */
+    ret = 20 - ret;
+
+    return ret;
+}
+
+/* setpriority(2) */
+static inline abi_long do_bsd_setpriority(abi_long which, abi_long who,
+        abi_long prio)
+{
+
+    return get_errno(setpriority(which, who, prio));
+}
+
+
+#endif /* !__BSD_PROC_H_ */
+
diff --git a/bsd-user/freebsd/os-proc.c b/bsd-user/freebsd/os-proc.c
new file mode 100644
index 0000000..b696222
--- /dev/null
+++ b/bsd-user/freebsd/os-proc.c
@@ -0,0 +1,234 @@
+/*
+ *  FreeBSD process related emulation code
+ *
+ *  Copyright (c) 2013 Stacey D. Son
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/sysctl.h>
+#include <sys/unistd.h>
+#if defined(__FreeBSD_version) && __FreeBSD_version > 900000
+#include <libprocstat.h>
+#endif
+
+#include "qemu.h"
+
+/*
+ * Get the filename for the given file descriptor.
+ * Note that this may return NULL (fail) if no longer cached in the kernel.
+ */
+static char *
+get_filename_from_fd(pid_t pid, int fd, char *filename, size_t len)
+{
+    char *ret = NULL;
+#if defined(__FreeBSD_version) && __FreeBSD_version > 900000
+    unsigned int cnt;
+    struct procstat *procstat = NULL;
+    struct kinfo_proc *kipp = NULL;
+    struct filestat_list *head = NULL;
+    struct filestat *fst;
+
+    procstat = procstat_open_sysctl();
+    if (NULL == procstat) {
+        goto out;
+    }
+
+    kipp = procstat_getprocs(procstat, KERN_PROC_PID, pid, &cnt);
+    if (NULL == kipp) {
+        goto out;
+    }
+
+    head = procstat_getfiles(procstat, kipp, 0);
+    if (NULL == head) {
+        goto out;
+    }
+
+    STAILQ_FOREACH(fst, head, next) {
+        if (fd == fst->fs_fd) {
+            if (fst->fs_path != NULL) {
+                (void)strlcpy(filename, fst->fs_path, len);
+                ret = filename;
+            }
+            break;
+        }
+    }
+
+out:
+    if (head != NULL) {
+        procstat_freefiles(procstat, head);
+    }
+    if (kipp != NULL) {
+        procstat_freeprocs(procstat, kipp);
+    }
+    if (procstat != NULL) {
+        procstat_close(procstat);
+    }
+#endif
+    return ret;
+}
+
+/*
+ * execve/fexecve
+ */
+abi_long freebsd_exec_common(abi_ulong path_or_fd, abi_ulong guest_argp,
+        abi_ulong guest_envp, int do_fexec)
+{
+    char **argp, **envp, **qargp, **qarg1;
+    int argc, envc;
+    abi_ulong gp;
+    abi_ulong addr;
+    char **q;
+    int total_size = 0;
+    void *p;
+    abi_long ret;
+
+    argc = 0;
+    for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
+        if (get_user_ual(addr, gp)) {
+            return -TARGET_EFAULT;
+        }
+        if (!addr) {
+            break;
+        }
+        argc++;
+    }
+    envc = 0;
+    for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
+        if (get_user_ual(addr, gp)) {
+            return -TARGET_EFAULT;
+        }
+        if (!addr) {
+            break;
+        }
+        envc++;
+    }
+
+    qargp = argp =  alloca((argc + 3) * sizeof(void *));
+    /* save the first agrument for the emulator */
+    *argp++ = (char *)getprogname();
+    qarg1 = argp;
+    envp = alloca((envc + 1) * sizeof(void *));
+    for (gp = guest_argp, q = argp; gp; gp += sizeof(abi_ulong), q++) {
+        if (get_user_ual(addr, gp)) {
+            ret = -TARGET_EFAULT;
+            goto execve_end;
+        }
+        if (!addr) {
+            break;
+        }
+        *q = lock_user_string(addr);
+        if (*q == NULL) {
+            ret = -TARGET_EFAULT;
+            goto execve_end;
+        }
+        total_size += strlen(*q) + 1;
+    }
+    *q = NULL;
+
+    for (gp = guest_envp, q = envp; gp; gp += sizeof(abi_ulong), q++) {
+        if (get_user_ual(addr, gp)) {
+            ret = -TARGET_EFAULT;
+            goto execve_end;
+        }
+        if (!addr) {
+            break;
+        }
+        *q = lock_user_string(addr);
+        if (*q == NULL) {
+            ret = -TARGET_EFAULT;
+            goto execve_end;
+        }
+        total_size += strlen(*q) + 1;
+    }
+    *q = NULL;
+
+    /*
+     * This case will not be caught by the host's execve() if its
+     * page size is bigger than the target's.
+     */
+    if (total_size > MAX_ARG_PAGES * TARGET_PAGE_SIZE) {
+        ret = -TARGET_E2BIG;
+        goto execve_end;
+    }
+
+    if (do_fexec) {
+        if (((int)path_or_fd > 0 &&
+            is_target_elf_binary((int)path_or_fd)) == 1) {
+            char execpath[PATH_MAX];
+
+            /*
+             * The executable is an elf binary for the target
+             * arch.  execve() it using the emulator if we can
+             * determine the filename path from the fd.
+             */
+            if (get_filename_from_fd(getpid(), (int)path_or_fd, execpath,
+                        sizeof(execpath)) != NULL) {
+                *qarg1 = execpath;
+                ret = get_errno(execve(qemu_proc_pathname, qargp, envp));
+            } else {
+                /* Getting the filename path failed. */
+                ret = -TARGET_EBADF;
+                goto execve_end;
+            }
+        } else {
+            ret = get_errno(fexecve((int)path_or_fd, argp, envp));
+        }
+    } else {
+        int fd;
+
+        p = lock_user_string(path_or_fd);
+        if (p == NULL) {
+            ret = -TARGET_EFAULT;
+            goto execve_end;
+        }
+
+        /*
+         * Check the header and see if it a target elf binary.  If so
+         * then execute using qemu user mode emulator.
+         */
+        fd = open(p, O_RDONLY | O_CLOEXEC);
+        if (fd > 0 && is_target_elf_binary(fd) == 1) {
+            close(fd);
+            /* Execve() as a target binary using emulator. */
+            *qarg1 = (char *)p;
+            ret = get_errno(execve(qemu_proc_pathname, qargp, envp));
+        } else {
+            close(fd);
+            /* Execve() as a host native binary. */
+            ret = get_errno(execve(p, argp, envp));
+        }
+        unlock_user(p, path_or_fd, 0);
+    }
+
+execve_end:
+    for (gp = guest_argp, q = argp; *q; gp += sizeof(abi_ulong), q++) {
+        if (get_user_ual(addr, gp) || !addr) {
+            break;
+        }
+        unlock_user(*q, addr, 0);
+    }
+
+    for (gp = guest_envp, q = envp; *q; gp += sizeof(abi_ulong), q++) {
+        if (get_user_ual(addr, gp) || !addr) {
+            break;
+        }
+        unlock_user(*q, addr, 0);
+    }
+    return ret;
+}
+
+
diff --git a/bsd-user/freebsd/os-proc.h b/bsd-user/freebsd/os-proc.h
new file mode 100644
index 0000000..b31f7c4
--- /dev/null
+++ b/bsd-user/freebsd/os-proc.h
@@ -0,0 +1,428 @@
+/*
+ *  process related system call shims and definitions
+ *
+ *  Copyright (c) 2013 Stacey D. Son
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __FREEBSD_PROC_H_
+#define __FREEBSD_PROC_H_
+
+#include <sys/types.h>
+#if defined(__FreeBSD_version) && __FreeBSD_version > 900000
+#include <sys/procdesc.h>
+#endif
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "target_arch_cpu.h"
+
+extern int __setugid(int flag);
+extern int pdwait4(int fd, int *status, int options, struct rusage *rusage);
+
+/* execve(2) */
+static inline abi_long do_freebsd_execve(abi_ulong path_or_fd, abi_ulong argp,
+        abi_ulong envp)
+{
+
+    return freebsd_exec_common(path_or_fd, argp, envp, 0);
+}
+
+/* fexecve(2) */
+static inline abi_long do_freebsd_fexecve(abi_ulong path_or_fd, abi_ulong argp,
+        abi_ulong envp)
+{
+
+    return freebsd_exec_common(path_or_fd, argp, envp, 1);
+}
+
+/* wait4(2) */
+static inline abi_long do_freebsd_wait4(abi_long arg1, abi_ulong target_status,
+        abi_long arg3, abi_ulong target_rusage)
+{
+    abi_long ret;
+    int status;
+    struct rusage rusage, *rusage_ptr = NULL;
+
+    if (target_rusage) {
+        rusage_ptr = &rusage;
+    }
+    ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr));
+    if (!is_error(ret)) {
+        status = host_to_target_waitstatus(status);
+        if (put_user_s32(status, target_status) != 0) {
+            return -TARGET_EFAULT;
+        }
+        if (target_rusage != 0) {
+            host_to_target_rusage(target_rusage, &rusage);
+        }
+    }
+    return ret;
+}
+
+#if defined(__FreeBSD_version) && __FreeBSD_version > 900000
+/* setloginclass(2) */
+static inline abi_long do_freebsd_setloginclass(abi_ulong arg1)
+{
+    abi_long ret;
+    void *p;
+
+    p = lock_user_string(arg1);
+    if (p == NULL) {
+        return -TARGET_EFAULT;
+    }
+    ret = get_errno(setloginclass(p));
+    unlock_user(p, arg1, 0);
+
+    return ret;
+}
+
+/* getloginclass(2) */
+static inline abi_long do_freebsd_getloginclass(abi_ulong arg1, abi_ulong arg2)
+{
+    abi_long ret;
+    void *p;
+
+    p = lock_user_string(arg1);
+    if (p == NULL) {
+        return -TARGET_EFAULT;
+    }
+    ret = get_errno(getloginclass(p, arg2));
+    unlock_user(p, arg1, 0);
+
+    return ret;
+}
+
+/* pdwait4(2) */
+static inline abi_long do_freebsd_pdwait4(abi_long arg1,
+        abi_ulong target_status, abi_long arg3, abi_ulong target_rusage)
+{
+    abi_long ret;
+    int status;
+    struct rusage rusage, *rusage_ptr = NULL;
+
+    if (target_rusage) {
+        rusage_ptr = &rusage;
+    }
+    ret = get_errno(pdwait4(arg1, &status, arg3, rusage_ptr));
+    if (!is_error(ret)) {
+        status = host_to_target_waitstatus(status);
+        if (put_user_s32(status, target_status) != 0) {
+            return -TARGET_EFAULT;
+        }
+        if (target_rusage != 0) {
+            host_to_target_rusage(target_rusage, &rusage);
+        }
+    }
+    return ret;
+}
+
+/* pdgetpid(2) */
+static inline abi_long do_freebsd_pdgetpid(abi_long fd, abi_ulong target_pidp)
+{
+    abi_long ret;
+    pid_t pid;
+
+    ret = get_errno(pdgetpid(fd, &pid));
+    if (!is_error(ret)) {
+        if (put_user_u32(pid, target_pidp)) {
+            return -TARGET_EFAULT;
+        }
+    }
+    return ret;
+}
+
+#else
+
+/* setloginclass(2) */
+static inline abi_long do_freebsd_setloginclass(abi_ulong arg1)
+{
+
+    qemu_log("qemu: Unsupported syscall setloginclass()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* getloginclass(2) */
+static inline abi_long do_freebsd_getloginclass(abi_ulong arg1, abi_ulong arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall getloginclass()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* pdwait4(2) */
+static inline abi_long do_freebsd_pdwait4(abi_long arg1,
+        abi_ulong target_status, abi_long arg3, abi_ulong target_rusage)
+{
+
+    qemu_log("qemu: Unsupported syscall pdwait4()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* pdgetpid(2) */
+static inline abi_long do_freebsd_pdgetpid(abi_long fd, abi_ulong target_pidp)
+{
+
+    qemu_log("qemu: Unsupported syscall pdgetpid()\n");
+    return -TARGET_ENOSYS;
+}
+#endif /* !  __FreeBSD_version > 900000 */
+
+/* undocumented __setugid */
+static inline abi_long do_freebsd___setugid(abi_long arg1)
+{
+
+    return get_errno(__setugid(arg1));
+}
+
+/* fork(2) */
+static inline abi_long do_freebsd_fork(void *cpu_env)
+{
+    abi_long ret;
+    abi_ulong child_flag = 0;
+
+    fork_start();
+    ret = fork();
+    if (ret == 0) {
+        /* child */
+        child_flag = 1;
+        target_cpu_clone_regs(cpu_env, 0);
+    } else {
+        /* parent */
+        fork_end(0);
+    }
+
+    /*
+     * The fork system call sets a child flag in the second return
+     * value: 0 for parent process, 1 for child process.
+     */
+    set_second_rval(cpu_env, child_flag);
+
+    return ret;
+}
+
+/* vfork(2) */
+static inline abi_long do_freebsd_vfork(void *cpu_env)
+{
+
+    return do_freebsd_fork(cpu_env);
+}
+
+/* rfork(2) */
+static inline abi_long do_freebsd_rfork(void *cpu_env, abi_long flags)
+{
+    abi_long ret;
+    abi_ulong child_flag = 0;
+
+    fork_start();
+    ret = rfork(flags);
+    if (ret == 0) {
+        /* child */
+        child_flag = 1;
+        target_cpu_clone_regs(cpu_env, 0);
+    } else {
+        /* parent */
+        fork_end(0);
+    }
+
+    /*
+     * The fork system call sets a child flag in the second return
+     * value: 0 for parent process, 1 for child process.
+     */
+    set_second_rval(cpu_env, child_flag);
+
+    return ret;
+
+}
+
+#if defined(__FreeBSD_version) && __FreeBSD_version > 900000
+/* pdfork(2) */
+static inline abi_long do_freebsd_pdfork(void *cpu_env, abi_ulong target_fdp,
+        abi_long flags)
+{
+    abi_long ret;
+    abi_ulong child_flag = 0;
+    int fd;
+
+    fork_start();
+    ret = pdfork(&fd, flags);
+    if (ret == 0) {
+        /* child */
+        child_flag = 1;
+        target_cpu_clone_regs(cpu_env, 0);
+    } else {
+        /* parent */
+        fork_end(0);
+    }
+    if (put_user_s32(fd, target_fdp)) {
+        return -TARGET_EFAULT;
+    }
+
+    /*
+     * The fork system call sets a child flag in the second return
+     * value: 0 for parent process, 1 for child process.
+     */
+    set_second_rval(cpu_env, child_flag);
+
+    return ret;
+}
+
+#else
+
+/* pdfork(2) */
+static inline abi_long do_freebsd_pdfork(void *cpu_env, abi_ulong arg1,
+        abi_long arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall pdfork()\n");
+    return -TARGET_ENOSYS;
+}
+
+#endif /* __FreeBSD_version > 900000 */
+
+/* jail(2) */
+static inline abi_long do_freebsd_jail(abi_ulong arg1)
+{
+
+    qemu_log("qemu: Unsupported syscall jail()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* jail_attach(2) */
+static inline abi_long do_freebsd_jail_attach(abi_long arg1)
+{
+
+    qemu_log("qemu: Unsupported syscall jail_attach()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* jail_remove(2) */
+static inline abi_long do_freebsd_jail_remove(abi_long arg1)
+{
+
+    qemu_log("qemu: Unsupported syscall jail_remove()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* jail_get(2) */
+static inline abi_long do_freebsd_jail_get(abi_ulong arg1, abi_long arg2,
+        abi_long arg3)
+{
+
+    qemu_log("qemu: Unsupported syscall jail_get()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* jail_set(2) */
+static inline abi_long do_freebsd_jail_set(abi_ulong arg1, abi_long arg2,
+        abi_long arg3)
+{
+
+    qemu_log("qemu: Unsupported syscall jail_set()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* cap_enter(2) */
+static inline abi_long do_freebsd_cap_enter(void)
+{
+
+    qemu_log("qemu: Unsupported syscall cap_enter()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* cap_new(2) */
+static inline abi_long do_freebsd_cap_new(abi_long arg1, abi_ulong arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall cap_new()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* cap_getrights(2) */
+static inline abi_long do_freebsd_cap_getrights(abi_long arg1, abi_ulong arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall cap_getrights()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* cap_getmode(2) */
+static inline abi_long do_freebsd_cap_getmode(abi_ulong arg1)
+{
+
+    qemu_log("qemu: Unsupported syscall cap_getmode()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* audit(2) */
+static inline abi_long do_freebsd_audit(abi_ulong arg1, abi_ulong arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall audit()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* auditon(2) */
+static inline abi_long do_freebsd_auditon(abi_long arg1, abi_ulong arg2,
+        abi_ulong arg3)
+{
+
+    qemu_log("qemu: Unsupported syscall auditon()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* getaudit(2) */
+static inline abi_long do_freebsd_getaudit(abi_ulong arg1)
+{
+
+    qemu_log("qemu: Unsupported syscall getaudit()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* setaudit(2) */
+static inline abi_long do_freebsd_setaudit(abi_ulong arg1)
+{
+
+    qemu_log("qemu: Unsupported syscall setaudit()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* getaudit_addr(2) */
+static inline abi_long do_freebsd_getaudit_addr(abi_ulong arg1,
+        abi_ulong arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall getaudit_addr()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* setaudit_addr(2) */
+static inline abi_long do_freebsd_setaudit_addr(abi_ulong arg1,
+        abi_ulong arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall setaudit_addr()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* auditctl(2) */
+static inline abi_long do_freebsd_auditctl(abi_ulong arg1)
+{
+
+    qemu_log("qemu: Unsupported syscall auditctl()\n");
+    return -TARGET_ENOSYS;
+}
+
+#endif /* ! __FREEBSD_PROC_H_ */
diff --git a/bsd-user/netbsd/os-proc.c b/bsd-user/netbsd/os-proc.c
new file mode 100644
index 0000000..bc11d29
--- /dev/null
+++ b/bsd-user/netbsd/os-proc.c
@@ -0,0 +1,11 @@
+/*
+ * XXX To support FreeBSD binaries on NetBSD the following will need to be
+ * emulated.
+ */
+abi_long freebsd_exec_common(abi_ulong path_or_fd, abi_ulong guest_argp,
+        abi_ulong guest_envp, int do_fexec)
+{
+
+    qemu_log("qemu: Unsupported %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
diff --git a/bsd-user/netbsd/os-proc.h b/bsd-user/netbsd/os-proc.h
new file mode 100644
index 0000000..f34d616
--- /dev/null
+++ b/bsd-user/netbsd/os-proc.h
@@ -0,0 +1,243 @@
+#ifndef __NETBSD_PROC_H_
+#define __NETBSD_PROC_H_
+
+/*
+ * XXX To support FreeBSD binaries on NetBSD these syscalls will need
+ * to be emulated.
+ */
+
+/* execve(2) */
+static inline abi_long do_freebsd_execve(abi_ulong path_or_fd, abi_ulong argp,
+        abi_ulong envp)
+{
+
+    qemu_log("qemu: Unsupported syscall execve()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* fexecve(2) */
+static inline abi_long do_freebsd_fexecve(abi_ulong path_or_fd, abi_ulong argp,
+        abi_ulong envp)
+{
+
+    qemu_log("qemu: Unsupported syscall fexecve()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* wait4(2) */
+static inline abi_long do_freebsd_wait4(abi_long arg1, abi_ulong target_status,
+        abi_long arg3, abi_ulong target_rusage)
+{
+
+    qemu_log("qemu: Unsupported syscall wait4()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* setloginclass(2) */
+static inline abi_long do_freebsd_setloginclass(abi_ulong arg1)
+{
+
+    qemu_log("qemu: Unsupported syscall setloginclass()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* getloginclass(2) */
+static inline abi_long do_freebsd_getloginclass(abi_ulong arg1, abi_ulong arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall getloginclass()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* pdwait4(2) */
+static inline abi_long do_freebsd_pdwait4(abi_long arg1,
+        abi_ulong target_status, abi_long arg3, abi_ulong target_rusage)
+{
+
+    qemu_log("qemu: Unsupported syscall pdwait4()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* pdgetpid(2) */
+static inline abi_long do_freebsd_pdgetpid(abi_long fd, abi_ulong target_pidp)
+{
+
+    qemu_log("qemu: Unsupported syscall pdgetpid()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* undocumented __setugid */
+static inline abi_long do_freebsd___setugid(abi_long arg1)
+{
+
+    qemu_log("qemu: Unsupported syscall __setugid()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* fork(2) */
+static inline abi_long do_freebsd_fork(void *cpu_env)
+{
+
+    qemu_log("qemu: Unsupported syscall fork()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* vfork(2) */
+static inline abi_long do_freebsd_vfork(void *cpu_env)
+{
+
+    qemu_log("qemu: Unsupported syscall vfork()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* rfork(2) */
+static inline abi_long do_freebsd_rfork(void *cpu_env, abi_long flags)
+{
+
+    qemu_log("qemu: Unsupported syscall rfork()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* pdfork(2) */
+static inline abi_long do_freebsd_pdfork(void *cpu_env, abi_ulong arg1,
+        abi_long arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall pdfork()\n");
+    return -TARGET_ENOSYS
+}
+
+/* jail(2) */
+static inline abi_long do_freebsd_jail(abi_ulong arg1)
+{
+
+    qemu_log("qemu: Unsupported syscall jail()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* jail_attach(2) */
+static inline abi_long do_freebsd_jail_attach(abi_long arg1)
+{
+
+    qemu_log("qemu: Unsupported syscall jail_attach()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* jail_remove(2) */
+static inline abi_long do_freebsd_jail_remove(abi_long arg1)
+{
+
+    qemu_log("qemu: Unsupported syscall jail_remove()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* jail_get(2) */
+static inline abi_long do_freebsd_jail_get(abi_ulong arg1, abi_long arg2,
+        abi_long arg3)
+{
+
+    qemu_log("qemu: Unsupported syscall jail_get()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* jail_set(2) */
+static inline abi_long do_freebsd_jail_set(abi_ulong arg1, abi_long arg2,
+        abi_long arg3)
+{
+
+    qemu_log("qemu: Unsupported syscall jail_set()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* cap_enter(2) */
+static inline abi_long do_freebsd_cap_enter(void)
+{
+
+    qemu_log("qemu: Unsupported syscall cap_enter()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* cap_new(2) */
+static inline abi_long do_freebsd_cap_new(abi_long arg1, abi_ulong arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall cap_new()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* cap_getrights(2) */
+static inline abi_long do_freebsd_cap_getrights(abi_long arg1, abi_ulong arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall cap_getrights()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* cap_getmode(2) */
+static inline abi_long do_freebsd_cap_getmode(abi_ulong arg1)
+{
+
+    qemu_log("qemu: Unsupported syscall cap_getmode()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* audit(2) */
+static inline abi_long do_freebsd_audit(abi_ulong arg1, abi_ulong arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall audit()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* auditon(2) */
+static inline abi_long do_freebsd_auditon(abi_long arg1, abi_ulong arg2,
+        abi_ulong arg3)
+{
+
+    qemu_log("qemu: Unsupported syscall auditon()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* getaudit(2) */
+static inline abi_long do_freebsd_getaudit(abi_ulong arg1)
+{
+
+    qemu_log("qemu: Unsupported syscall getaudit()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* setaudit(2) */
+static inline abi_long do_freebsd_setaudit(abi_ulong arg1)
+{
+
+    qemu_log("qemu: Unsupported syscall setaudit()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* getaudit_addr(2) */
+static inline abi_long do_freebsd_getaudit_addr(abi_ulong arg1,
+        abi_ulong arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall getaudit_addr()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* setaudit_addr(2) */
+static inline abi_long do_freebsd_setaudit_addr(abi_ulong arg1,
+        abi_ulong arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall setaudit_addr()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* auditctl(2) */
+static inline abi_long do_freebsd_auditctl(abi_ulong arg1)
+{
+
+    qemu_log("qemu: Unsupported syscall auditctl()\n");
+    return -TARGET_ENOSYS;
+}
+
+#endif /* ! __NETBSD_PROC_H_ */
diff --git a/bsd-user/openbsd/os-proc.c b/bsd-user/openbsd/os-proc.c
new file mode 100644
index 0000000..bc11d29
--- /dev/null
+++ b/bsd-user/openbsd/os-proc.c
@@ -0,0 +1,11 @@
+/*
+ * XXX To support FreeBSD binaries on NetBSD the following will need to be
+ * emulated.
+ */
+abi_long freebsd_exec_common(abi_ulong path_or_fd, abi_ulong guest_argp,
+        abi_ulong guest_envp, int do_fexec)
+{
+
+    qemu_log("qemu: Unsupported %s\n", __func__);
+    return -TARGET_ENOSYS;
+}
diff --git a/bsd-user/openbsd/os-proc.h b/bsd-user/openbsd/os-proc.h
new file mode 100644
index 0000000..9cce719
--- /dev/null
+++ b/bsd-user/openbsd/os-proc.h
@@ -0,0 +1,243 @@
+#ifndef __OPENBSD_PROC_H_
+#define __OPENBSD_PROC_H_
+
+/*
+ * XXX To support FreeBSD binaries on OpenBSD these syscalls will need
+ * to be emulated.
+ */
+
+/* execve(2) */
+static inline abi_long do_freebsd_execve(abi_ulong path_or_fd, abi_ulong argp,
+        abi_ulong envp)
+{
+
+    qemu_log("qemu: Unsupported syscall execve()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* fexecve(2) */
+static inline abi_long do_freebsd_fexecve(abi_ulong path_or_fd, abi_ulong argp,
+        abi_ulong envp)
+{
+
+    qemu_log("qemu: Unsupported syscall fexecve()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* wait4(2) */
+static inline abi_long do_freebsd_wait4(abi_long arg1, abi_ulong target_status,
+        abi_long arg3, abi_ulong target_rusage)
+{
+
+    qemu_log("qemu: Unsupported syscall wait4()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* setloginclass(2) */
+static inline abi_long do_freebsd_setloginclass(abi_ulong arg1)
+{
+
+    qemu_log("qemu: Unsupported syscall setloginclass()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* getloginclass(2) */
+static inline abi_long do_freebsd_getloginclass(abi_ulong arg1, abi_ulong arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall getloginclass()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* pdwait4(2) */
+static inline abi_long do_freebsd_pdwait4(abi_long arg1,
+        abi_ulong target_status, abi_long arg3, abi_ulong target_rusage)
+{
+
+    qemu_log("qemu: Unsupported syscall pdwait4()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* pdgetpid(2) */
+static inline abi_long do_freebsd_pdgetpid(abi_long fd, abi_ulong target_pidp)
+{
+
+    qemu_log("qemu: Unsupported syscall pdgetpid()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* undocumented __setugid */
+static inline abi_long do_freebsd___setugid(abi_long arg1)
+{
+
+    qemu_log("qemu: Unsupported syscall __setugid()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* fork(2) */
+static inline abi_long do_freebsd_fork(void *cpu_env)
+{
+
+    qemu_log("qemu: Unsupported syscall fork()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* vfork(2) */
+static inline abi_long do_freebsd_vfork(void *cpu_env)
+{
+
+    qemu_log("qemu: Unsupported syscall vfork()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* rfork(2) */
+static inline abi_long do_freebsd_rfork(void *cpu_env, abi_long flags)
+{
+
+    qemu_log("qemu: Unsupported syscall rfork()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* pdfork(2) */
+static inline abi_long do_freebsd_pdfork(void *cpu_env, abi_ulong arg1,
+        abi_long arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall pdfork()\n");
+    return -TARGET_ENOSYS
+}
+
+/* jail(2) */
+static inline abi_long do_freebsd_jail(abi_ulong arg1)
+{
+
+    qemu_log("qemu: Unsupported syscall jail()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* jail_attach(2) */
+static inline abi_long do_freebsd_jail_attach(abi_long arg1)
+{
+
+    qemu_log("qemu: Unsupported syscall jail_attach()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* jail_remove(2) */
+static inline abi_long do_freebsd_jail_remove(abi_long arg1)
+{
+
+    qemu_log("qemu: Unsupported syscall jail_remove()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* jail_get(2) */
+static inline abi_long do_freebsd_jail_get(abi_ulong arg1, abi_long arg2,
+        abi_long arg3)
+{
+
+    qemu_log("qemu: Unsupported syscall jail_get()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* jail_set(2) */
+static inline abi_long do_freebsd_jail_set(abi_ulong arg1, abi_long arg2,
+        abi_long arg3)
+{
+
+    qemu_log("qemu: Unsupported syscall jail_set()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* cap_enter(2) */
+static inline abi_long do_freebsd_cap_enter(void)
+{
+
+    qemu_log("qemu: Unsupported syscall cap_enter()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* cap_new(2) */
+static inline abi_long do_freebsd_cap_new(abi_long arg1, abi_ulong arg2)
+{
+
+        qemu_log("qemu: Unsupported syscall cap_new()\n");
+            return -TARGET_ENOSYS;
+}
+
+/* cap_getrights(2) */
+static inline abi_long do_freebsd_cap_getrights(abi_long arg1, abi_ulong arg2)
+{
+
+        qemu_log("qemu: Unsupported syscall cap_getrights()\n");
+            return -TARGET_ENOSYS;
+}
+
+/* cap_getmode(2) */
+static inline abi_long do_freebsd_cap_getmode(abi_ulong arg1)
+{
+
+    qemu_log("qemu: Unsupported syscall cap_getmode()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* audit(2) */
+static inline abi_long do_freebsd_audit(abi_ulong arg1, abi_ulong arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall audit()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* auditon(2) */
+static inline abi_long do_freebsd_auditon(abi_long arg1, abi_ulong arg2,
+        abi_ulong arg3)
+{
+
+    qemu_log("qemu: Unsupported syscall auditon()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* getaudit(2) */
+static inline abi_long do_freebsd_getaudit(abi_ulong arg1)
+{
+
+    qemu_log("qemu: Unsupported syscall getaudit()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* setaudit(2) */
+static inline abi_long do_freebsd_setaudit(abi_ulong arg1)
+{
+
+    qemu_log("qemu: Unsupported syscall setaudit()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* getaudit_addr(2) */
+static inline abi_long do_freebsd_getaudit_addr(abi_ulong arg1,
+        abi_ulong arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall getaudit_addr()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* setaudit_addr(2) */
+static inline abi_long do_freebsd_setaudit_addr(abi_ulong arg1,
+        abi_ulong arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall setaudit_addr()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* auditctl(2) */
+static inline abi_long do_freebsd_auditctl(abi_ulong arg1)
+{
+
+    qemu_log("qemu: Unsupported syscall auditctl()\n");
+    return -TARGET_ENOSYS;
+}
+
+#endif /* ! __OPENBSD_PROC_H_ */
diff --git a/bsd-user/qemu-bsd.h b/bsd-user/qemu-bsd.h
new file mode 100644
index 0000000..590c36b
--- /dev/null
+++ b/bsd-user/qemu-bsd.h
@@ -0,0 +1,43 @@
+/*
+ *  BSD conversion extern declarations
+ *
+ *  Copyright (c) 2013 Stacey D. Son
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _QEMU_BSD_H_
+#define _QEMU_BSD_H_
+
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+#include <sys/resource.h>
+#include <sys/sem.h>
+#include <sys/shm.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/uuid.h>
+#include <sys/wait.h>
+#include <netinet/in.h>
+
+/* bsd-proc.c */
+int target_to_host_resource(int code);
+rlim_t target_to_host_rlim(abi_ulong target_rlim);
+abi_ulong host_to_target_rlim(rlim_t rlim);
+abi_long host_to_target_rusage(abi_ulong target_addr,
+        const struct rusage *rusage);
+int host_to_target_waitstatus(int status);
+
+#endif /* !_QEMU_BSD_H_ */
diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
index 0e332af..a9f5666 100644
--- a/bsd-user/qemu.h
+++ b/bsd-user/qemu.h
@@ -248,6 +248,10 @@ extern char qemu_proc_pathname[];
 abi_long get_errno(abi_long ret);
 int is_error(abi_long ret);
 
+/* os-proc.c */
+abi_long freebsd_exec_common(abi_ulong path_or_fd, abi_ulong guest_argp,
+        abi_ulong guest_envp, int do_fexec);
+
 /* os-sys.c */
 abi_long do_freebsd_sysctl(CPUArchState *env, abi_ulong namep, int32_t namelen,
         abi_ulong oldp, abi_ulong oldlenp, abi_ulong newp, abi_ulong newlen);
diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c
index bc4a7e4..f8a40f0 100644
--- a/bsd-user/syscall.c
+++ b/bsd-user/syscall.c
@@ -38,12 +38,15 @@
 #include "qemu-common.h"
 
 #define target_to_host_bitmask(x, tbl) (x)
+static int host_to_target_errno(int err);
 
 /* BSD independent syscall shims */
+#include "bsd-proc.h"
 #include "bsd-signal.h"
 
 /* *BSD dependent syscall shims */
 #include "os-time.h"
+#include "os-proc.h"
 #include "os-signal.h"
 
 /* #define DEBUG */
@@ -63,6 +66,12 @@ abi_long get_errno(abi_long ret)
         return ret;
 }
 
+static int host_to_target_errno(int err)
+{
+    /* XXX need to translate host errnos here */
+    return err;
+}
+
 int is_error(abi_long ret)
 {
     return (abi_ulong)ret >= (abi_ulong)(-4096);
@@ -176,15 +185,254 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, 
abi_long arg1,
         print_freebsd_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
 
     switch(num) {
-    case TARGET_FREEBSD_NR_exit:
-#ifdef TARGET_GPROF
-        _mcleanup();
+        /*
+         * process system calls
+         */
+    case TARGET_FREEBSD_NR_fork: /* fork(2) */
+        ret = do_freebsd_fork(cpu_env);
+        break;
+
+    case TARGET_FREEBSD_NR_vfork: /* vfork(2) */
+        ret = do_freebsd_vfork(cpu_env);
+        break;
+
+    case TARGET_FREEBSD_NR_rfork: /* rfork(2) */
+        ret = do_freebsd_rfork(cpu_env, arg1);
+        break;
+
+    case TARGET_FREEBSD_NR_pdfork: /* pdfork(2) */
+        ret = do_freebsd_pdfork(cpu_env, arg1, arg2);
+        break;
+
+    case TARGET_FREEBSD_NR_execve: /* execve(2) */
+        ret = do_freebsd_execve(arg1, arg2, arg3);
+        break;
+
+    case TARGET_FREEBSD_NR_fexecve: /* fexecve(2) */
+        ret = do_freebsd_fexecve(arg1, arg2, arg3);
+        break;
+
+    case TARGET_FREEBSD_NR_wait4: /* wait4(2) */
+        ret = do_freebsd_wait4(arg1, arg2, arg3, arg4);
+        break;
+
+    case TARGET_FREEBSD_NR_exit: /* exit(2) */
+        ret = do_bsd_exit(cpu_env, arg1);
+        break;
+
+    case TARGET_FREEBSD_NR_getgroups: /* getgroups(2) */
+        ret = do_bsd_getgroups(arg1, arg2);
+        break;
+
+    case TARGET_FREEBSD_NR_setgroups: /* setgroups(2) */
+        ret = do_bsd_setgroups(arg1, arg2);
+        break;
+
+    case TARGET_FREEBSD_NR_umask: /* umask(2) */
+        ret = do_bsd_umask(arg1);
+        break;
+
+    case TARGET_FREEBSD_NR_setlogin: /* setlogin(2) */
+        ret = do_bsd_setlogin(arg1);
+        break;
+
+    case TARGET_FREEBSD_NR_getlogin: /* getlogin(2) */
+        ret = do_bsd_getlogin(arg1, arg2);
+        break;
+
+    case TARGET_FREEBSD_NR_getrusage: /* getrusage(2) */
+        ret = do_bsd_getrusage(arg1, arg2);
+        break;
+
+    case TARGET_FREEBSD_NR_getrlimit: /* getrlimit(2) */
+        ret = do_bsd_getrlimit(arg1, arg2);
+        break;
+
+    case TARGET_FREEBSD_NR_setrlimit: /* setrlimit(2) */
+        ret = do_bsd_setrlimit(arg1, arg2);
+        break;
+
+    case TARGET_FREEBSD_NR_getpid: /* getpid(2) */
+        ret = do_bsd_getpid();
+        break;
+
+    case TARGET_FREEBSD_NR_getppid: /* getppid(2) */
+        ret = do_bsd_getppid();
+        break;
+
+    case TARGET_FREEBSD_NR_getuid: /* getuid(2) */
+        ret = do_bsd_getuid();
+        break;
+
+    case TARGET_FREEBSD_NR_geteuid: /* geteuid(2) */
+        ret = do_bsd_geteuid();
+        break;
+
+    case TARGET_FREEBSD_NR_getgid: /* getgid(2) */
+        ret = do_bsd_getgid();
+        break;
+
+    case TARGET_FREEBSD_NR_getegid: /* getegid(2) */
+        ret = do_bsd_getegid();
+        break;
+
+    case TARGET_FREEBSD_NR_setuid: /* setuid(2) */
+        ret = do_bsd_setuid(arg1);
+        break;
+
+    case TARGET_FREEBSD_NR_seteuid: /* seteuid(2) */
+        ret = do_bsd_seteuid(arg1);
+        break;
+
+    case TARGET_FREEBSD_NR_setgid: /* setgid(2) */
+        ret = do_bsd_setgid(arg1);
+        break;
+
+    case TARGET_FREEBSD_NR_setegid: /* setegid(2) */
+        ret = do_bsd_setegid(arg1);
+        break;
+
+    case TARGET_FREEBSD_NR_getpgrp: /* getpgrp(2) */
+        ret = do_bsd_getpgrp();
+        break;
+
+    case TARGET_FREEBSD_NR_setreuid: /* setreuid(2) */
+        ret = do_bsd_setreuid(arg1, arg2);
+        break;
+
+    case TARGET_FREEBSD_NR_setregid: /* setregid(2) */
+        ret = do_bsd_setregid(arg1, arg2);
+        break;
+
+    case TARGET_FREEBSD_NR_getresuid: /* getresuid(2) */
+        ret = do_bsd_getresuid(arg1, arg2, arg3);
+        break;
+
+    case TARGET_FREEBSD_NR_getresgid: /* getresgid(2) */
+        ret = do_bsd_getresgid(arg1, arg2, arg3);
+        break;
+
+    case TARGET_FREEBSD_NR_getsid: /* getsid(2) */
+        ret = do_bsd_getsid(arg1);
+        break;
+
+    case TARGET_FREEBSD_NR_setsid: /* setsid(2) */
+        ret = do_bsd_setsid();
+        break;
+
+    case TARGET_FREEBSD_NR_issetugid: /* issetugid(2) */
+        ret = do_bsd_issetugid();
+        break;
+
+    case TARGET_FREEBSD_NR_profil: /* profil(2) */
+        ret = do_bsd_profil(arg1, arg2, arg3, arg4);
+        break;
+
+    case TARGET_FREEBSD_NR_ktrace: /* ktrace(2) */
+        ret = do_bsd_ktrace(arg1, arg2, arg3, arg4);
+        break;
+
+    case TARGET_FREEBSD_NR_setloginclass: /* setloginclass(2) */
+        ret = do_freebsd_setloginclass(arg1);
+        break;
+
+    case TARGET_FREEBSD_NR_getloginclass: /* getloginclass(2) */
+        ret = do_freebsd_getloginclass(arg1, arg2);
+        break;
+#if 0
+    case TARGET_FREEBSD_NR_pdwait4: /* pdwait4(2) */
+        ret = do_freebsd_pdwait4(arg1, arg2, arg3, arg4);
+        break;
 #endif
-        gdb_exit(cpu_env, arg1);
-        /* XXX: should free thread stack and CPU env */
-        _exit(arg1);
-        ret = 0; /* avoid warning */
+
+    case TARGET_FREEBSD_NR_pdgetpid: /* pdgetpid(2) */
+        ret = do_freebsd_pdgetpid(arg1, arg2);
+        break;
+
+    case TARGET_FREEBSD_NR___setugid: /* undocumented */
+        ret = do_freebsd___setugid(arg1);
+        break;
+
+    case TARGET_FREEBSD_NR_jail: /* jail(2) */
+        ret = do_freebsd_jail(arg1);
+        break;
+
+    case TARGET_FREEBSD_NR_jail_attach: /* jail_attach(2) */
+        ret = do_freebsd_jail_attach(arg1);
+        break;
+
+    case TARGET_FREEBSD_NR_jail_remove: /* jail_remove(2) */
+        ret = do_freebsd_jail_remove(arg1);
+        break;
+
+    case TARGET_FREEBSD_NR_jail_get: /* jail_get(2) */
+        ret = do_freebsd_jail_get(arg1, arg2, arg3);
         break;
+
+    case TARGET_FREEBSD_NR_jail_set: /* jail_set(2) */
+        ret = do_freebsd_jail_set(arg1, arg2, arg3);
+        break;
+
+    case TARGET_FREEBSD_NR_cap_enter: /* cap_enter(2) */
+        ret = do_freebsd_cap_enter();
+        break;
+
+    case TARGET_FREEBSD_NR_cap_new: /* cap_new(2) */
+        ret = do_freebsd_cap_new(arg1, arg2);
+        break;
+
+    case TARGET_FREEBSD_NR_cap_getrights: /* cap_getrights(2) */
+        ret = do_freebsd_cap_getrights(arg1, arg2);
+        break;
+
+    case TARGET_FREEBSD_NR_cap_getmode: /* cap_getmode(2) */
+        ret = do_freebsd_cap_getmode(arg1);
+        break;
+
+    case TARGET_FREEBSD_NR_audit: /* audit(2) */
+        ret = do_freebsd_audit(arg1, arg2);
+        break;
+
+    case TARGET_FREEBSD_NR_auditon: /* auditon(2) */
+        ret = do_freebsd_auditon(arg1, arg2, arg3);
+        break;
+
+    case TARGET_FREEBSD_NR_getaudit: /* getaudit(2) */
+        ret = do_freebsd_getaudit(arg1);
+        break;
+
+    case TARGET_FREEBSD_NR_setaudit: /* setaudit(2) */
+        ret = do_freebsd_setaudit(arg1);
+        break;
+
+    case TARGET_FREEBSD_NR_getaudit_addr: /* getaudit_addr(2) */
+        ret = do_freebsd_getaudit_addr(arg1, arg2);
+        break;
+
+    case TARGET_FREEBSD_NR_setaudit_addr: /* setaudit_addr(2) */
+        ret = do_freebsd_setaudit_addr(arg1, arg2);
+        break;
+
+    case TARGET_FREEBSD_NR_auditctl: /* auditctl(2) */
+        ret = do_freebsd_auditctl(arg1);
+        break;
+    case TARGET_FREEBSD_NR_utrace: /* utrace(2) */
+        ret = do_bsd_utrace(arg1, arg2);
+        break;
+
+    case TARGET_FREEBSD_NR_ptrace: /* ptrace(2) */
+        ret = do_bsd_ptrace(arg1, arg2, arg3, arg4);
+        break;
+
+    case TARGET_FREEBSD_NR_getpriority: /* getpriority(2) */
+        ret = do_bsd_getpriority(arg1, arg2);
+        break;
+
+    case TARGET_FREEBSD_NR_setpriority: /* setpriority(2) */
+        ret = do_bsd_setpriority(arg1, arg2, arg3);
+        break;
+
+
     case TARGET_FREEBSD_NR_read:
         if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
             goto efault;
-- 
1.7.8




reply via email to

[Prev in Thread] Current Thread [Next in Thread]