qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH v3 05/19] bsd-user: move arch/OS dependent code out


From: Stacey Son
Subject: [Qemu-devel] [PATCH v3 05/19] bsd-user: move arch/OS dependent code out of syscall.c
Date: Tue, 17 Dec 2013 05:52:24 -0600

This change moves the system call handler for sysctl(2) and
sysarch(2) from syscall.c to the OS and arch dependent directories.
This eliminates many of the #ifdef's in syscall.c.  These system
call handlers are now located in the host os and target arch
directories.
---
 bsd-user/Makefile.objs                  |    2 +-
 bsd-user/arm/target_arch_sigtramp.h     |   33 ++++
 bsd-user/bsdload.c                      |  170 +++++++++++++-----
 bsd-user/elfload.c                      |    9 +-
 bsd-user/freebsd/os-sys.c               |  284 +++++++++++++++++++++++++++++++
 bsd-user/freebsd/target_os_stack.h      |  157 +++++++++++++++++
 bsd-user/i386/target_arch_sigtramp.h    |   11 ++
 bsd-user/mips/target_arch_sigtramp.h    |   23 +++
 bsd-user/mips64/target_arch_sigtramp.h  |   23 +++
 bsd-user/netbsd/os-sys.c                |   46 +++++
 bsd-user/netbsd/target_os_stack.h       |   33 ++++
 bsd-user/openbsd/os-sys.c               |   46 +++++
 bsd-user/openbsd/target_os_stack.h      |   33 ++++
 bsd-user/qemu.h                         |   30 +++-
 bsd-user/sparc/target_arch_sigtramp.h   |   11 ++
 bsd-user/sparc64/target_arch_sigtramp.h |   11 ++
 bsd-user/syscall.c                      |  210 +++--------------------
 bsd-user/x86_64/target_arch_sigtramp.h  |   11 ++
 18 files changed, 900 insertions(+), 243 deletions(-)
 create mode 100644 bsd-user/arm/target_arch_sigtramp.h
 create mode 100644 bsd-user/freebsd/os-sys.c
 create mode 100644 bsd-user/freebsd/target_os_stack.h
 create mode 100644 bsd-user/i386/target_arch_sigtramp.h
 create mode 100644 bsd-user/mips/target_arch_sigtramp.h
 create mode 100644 bsd-user/mips64/target_arch_sigtramp.h
 create mode 100644 bsd-user/netbsd/os-sys.c
 create mode 100644 bsd-user/netbsd/target_os_stack.h
 create mode 100644 bsd-user/openbsd/os-sys.c
 create mode 100644 bsd-user/openbsd/target_os_stack.h
 create mode 100644 bsd-user/sparc/target_arch_sigtramp.h
 create mode 100644 bsd-user/sparc64/target_arch_sigtramp.h
 create mode 100644 bsd-user/x86_64/target_arch_sigtramp.h

diff --git a/bsd-user/Makefile.objs b/bsd-user/Makefile.objs
index 41e8dce..a4dca8e 100644
--- a/bsd-user/Makefile.objs
+++ b/bsd-user/Makefile.objs
@@ -1,2 +1,2 @@
 obj-y = main.o bsdload.o elfload.o mmap.o signal.o strace.o syscall.o \
-               uaccess.o $(TARGET_ABI_DIR)/target_arch_cpu.o
+               uaccess.o $(HOST_VARIANT_DIR)/os-sys.o 
$(TARGET_ABI_DIR)/target_arch_cpu.o
diff --git a/bsd-user/arm/target_arch_sigtramp.h 
b/bsd-user/arm/target_arch_sigtramp.h
new file mode 100644
index 0000000..98dc313
--- /dev/null
+++ b/bsd-user/arm/target_arch_sigtramp.h
@@ -0,0 +1,33 @@
+
+#ifndef _TARGET_ARCH_SIGTRAMP_H_
+#define _TARGET_ARCH_SIGTRAMP_H_
+
+/* Compare to arm/arm/locore.S ENTRY_NP(sigcode) */
+static inline abi_long setup_sigtramp(abi_ulong offset, unsigned sigf_uc,
+        unsigned sys_sigreturn)
+{
+    int i;
+    uint32_t sys_exit = TARGET_FREEBSD_NR_exit;
+    /*
+     * The code has to load r7 manually rather than using
+     * "ldr r7, =SYS_return to make sure the size of the
+     * code is correct.
+     */
+    uint32_t sigtramp_code[] = {
+    /* 1 */ 0xE1A0000D,         /* mov r0, sp */
+    /* 2 */ 0xE59F700C,         /* ldr r7, [pc, #12] */
+    /* 3 */ 0xEF000000 + sys_sigreturn, /* swi (SYS_sigreturn) */
+    /* 4 */ 0xE59F7008,         /* ldr r7, [pc, #8] */
+    /* 5 */ 0xEF000000 + sys_exit,      /* swi (SYS_exit)*/
+    /* 6 */ 0xEAFFFFFA,         /* b . -16 */
+    /* 7 */ sys_sigreturn,
+    /* 8 */ sys_exit
+    };
+
+    for (i = 0; i < 8; i++) {
+        tswap32s(&sigtramp_code[i]);
+    }
+
+    return memcpy_to_target(offset, sigtramp_code, TARGET_SZSIGCODE);
+}
+#endif /* _TARGET_ARCH_SIGTRAMP_H_ */
diff --git a/bsd-user/bsdload.c b/bsd-user/bsdload.c
index 2abc713..45fdcf8 100644
--- a/bsd-user/bsdload.c
+++ b/bsd-user/bsdload.c
@@ -1,4 +1,19 @@
-/* Code for loading BSD executables.  Mostly linux kernel code.  */
+/*
+ *  Load BSD executables.
+ *
+ *  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/stat.h>
@@ -26,38 +41,22 @@ abi_long memcpy_to_target(abi_ulong dest, const void *src,
     return 0;
 }
 
-static int in_group_p(gid_t g)
-{
-    /* return TRUE if we're in the specified group, FALSE otherwise */
-    int         ngroup;
-    int         i;
-    gid_t       grouplist[TARGET_NGROUPS];
-
-    ngroup = getgroups(TARGET_NGROUPS, grouplist);
-    for(i = 0; i < ngroup; i++) {
-        if(grouplist[i] == g) {
-            return 1;
-        }
-    }
-    return 0;
-}
-
 static int count(char ** vec)
 {
     int         i;
 
-    for(i = 0; *vec; i++) {
+    for (i = 0; *vec; i++) {
         vec++;
     }
 
     return(i);
 }
 
-static int prepare_binprm(struct linux_binprm *bprm)
+static int prepare_binprm(struct bsd_binprm *bprm)
 {
     struct stat         st;
     int mode;
-    int retval, id_change;
+    int retval;
 
     if(fstat(bprm->fd, &st) < 0) {
         return(-errno);
@@ -73,14 +72,10 @@ static int prepare_binprm(struct linux_binprm *bprm)
 
     bprm->e_uid = geteuid();
     bprm->e_gid = getegid();
-    id_change = 0;
 
     /* Set-uid? */
     if(mode & S_ISUID) {
         bprm->e_uid = st.st_uid;
-        if(bprm->e_uid != geteuid()) {
-            id_change = 1;
-        }
     }
 
     /* Set-gid? */
@@ -91,9 +86,6 @@ static int prepare_binprm(struct linux_binprm *bprm)
      */
     if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
         bprm->e_gid = st.st_gid;
-        if (!in_group_p(bprm->e_gid)) {
-                id_change = 1;
-        }
     }
 
     memset(bprm->buf, 0, sizeof(bprm->buf));
@@ -154,34 +146,116 @@ abi_ulong loader_build_argptr(int envc, int argc, 
abi_ulong sp,
     return sp;
 }
 
+static int is_there(const char *candidate)
+{
+    struct stat fin;
+
+    /* XXX work around access(2) false positives for superuser */
+    if (access(candidate, X_OK) == 0 && stat(candidate, &fin) == 0 &&
+            S_ISREG(fin.st_mode) && (getuid() != 0 ||
+                (fin.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0)) {
+        return 1;
+    }
+
+    return 0;
+}
+
+static int find_in_path(char *path, const char *filename, char *retpath,
+        size_t rpsize)
+{
+    const char *d;
+    int found;
+
+    if (strchr(filename, '/') != NULL) {
+        if (is_there(filename)) {
+                if (!realpath(filename, retpath)) {
+                    return -1;
+                }
+                return 0;
+        } else {
+            return -1;
+        }
+    }
+
+    found = 0;
+    while ((d = strsep(&path, ":")) != NULL) {
+        if (*d == '\0') {
+            d = ".";
+        }
+        if (snprintf(retpath, rpsize, "%s/%s", d, filename) >= (int)rpsize) {
+            continue;
+        }
+        if (is_there((const char *)retpath)) {
+            found = 1;
+            break;
+        }
+    }
+    return found;
+}
+
 int loader_exec(const char * filename, char ** argv, char ** envp,
-             struct target_pt_regs * regs, struct image_info *infop)
+             struct target_pt_regs *regs, struct image_info *infop,
+             struct bsd_binprm *bprm)
 {
-    struct linux_binprm bprm;
-    int retval;
-    int i;
+    char *p, *path = NULL, fullpath[PATH_MAX];
+    const char *execname = NULL;
+    int retval, i, found;
 
-    bprm.p = TARGET_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int);
+    bprm->p = TARGET_PAGE_SIZE * MAX_ARG_PAGES; /* -sizeof(unsigned int); */
     for (i=0 ; i<MAX_ARG_PAGES ; i++)       /* clear page-table */
-            bprm.page[i] = NULL;
-    retval = open(filename, O_RDONLY);
-    if (retval < 0)
+            bprm->page[i] = NULL;
+
+    /* Find target executable in path, if not already an absolute path. */
+    p = getenv("PATH");
+    if (p != NULL) {
+        path = g_strdup(p);
+        if (path == NULL) {
+            fprintf(stderr, "Out of memory\n");
+            return -1;
+        }
+        execname = realpath(filename, NULL);
+        if (execname == NULL) {
+            execname = g_strdup(filename);
+        }
+        found = find_in_path(path, execname, fullpath, sizeof(fullpath));
+        /* Absolute path specified but not found? */
+        if (found == -1) {
+            return -1;
+        }
+        if (found) {
+            retval = open(fullpath, O_RDONLY);
+            bprm->fullpath = g_strdup(fullpath);
+        } else {
+            retval = open(execname, O_RDONLY);
+            bprm->fullpath = NULL;
+        }
+        if (execname) {
+            g_free((void *)execname);
+        }
+        g_free(path);
+    } else {
+        retval = open(filename, O_RDONLY);
+        bprm->fullpath = NULL;
+    }
+    if (retval < 0) {
         return retval;
-    bprm.fd = retval;
-    bprm.filename = (char *)filename;
-    bprm.argc = count(argv);
-    bprm.argv = argv;
-    bprm.envc = count(envp);
-    bprm.envp = envp;
+    }
+
+    bprm->fd = retval;
+    bprm->filename = (char *)filename;
+    bprm->argc = count(argv);
+    bprm->argv = argv;
+    bprm->envc = count(envp);
+    bprm->envp = envp;
 
-    retval = prepare_binprm(&bprm);
+    retval = prepare_binprm(bprm);
 
     if(retval>=0) {
-        if (bprm.buf[0] == 0x7f
-                && bprm.buf[1] == 'E'
-                && bprm.buf[2] == 'L'
-                && bprm.buf[3] == 'F') {
-            retval = load_elf_binary(&bprm,regs,infop);
+        if (bprm->buf[0] == 0x7f
+                && bprm->buf[1] == 'E'
+                && bprm->buf[2] == 'L'
+                && bprm->buf[3] == 'F') {
+            retval = load_elf_binary(bprm, regs, infop);
         } else {
             fprintf(stderr, "Unknown binary format\n");
             return -1;
@@ -196,7 +270,7 @@ int loader_exec(const char * filename, char ** argv, char 
** envp,
 
     /* Something went wrong, return the inode and free the argument pages*/
     for (i=0 ; i<MAX_ARG_PAGES ; i++) {
-        g_free(bprm.page[i]);
+        g_free(bprm->page[i]);
     }
     return(retval);
 }
diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c
index ccf72d1..68d0209 100644
--- a/bsd-user/elfload.c
+++ b/bsd-user/elfload.c
@@ -91,6 +91,9 @@ enum {
 #define ELIBBAD 80
 #endif
 
+abi_ulong target_stksiz;
+abi_ulong target_stkbas;
+
 #ifdef TARGET_I386
 
 #define ELF_PLATFORM get_elf_platform()
@@ -665,7 +668,7 @@ static abi_ulong copy_elf_strings(int argc,char ** argv, 
void **page,
     return p;
 }
 
-static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm,
+static abi_ulong setup_arg_pages(abi_ulong p, struct bsd_binprm *bprm,
                                  struct image_info *info)
 {
     abi_ulong stack_base, size, error;
@@ -1147,8 +1150,8 @@ static void load_symbols(struct elfhdr *hdr, int fd)
     syminfos = s;
 }
 
-int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
-                    struct image_info * info)
+int load_elf_binary(struct bsd_binprm *bprm, struct target_pt_regs *regs,
+                    struct image_info *info)
 {
     struct elfhdr elf_ex;
     struct elfhdr interp_elf_ex;
diff --git a/bsd-user/freebsd/os-sys.c b/bsd-user/freebsd/os-sys.c
new file mode 100644
index 0000000..c8f999f
--- /dev/null
+++ b/bsd-user/freebsd/os-sys.c
@@ -0,0 +1,284 @@
+/*
+ *  FreeBSD sysctl() and sysarch() system call emulation
+ *
+ *  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/param.h>
+#include <sys/sysctl.h>
+#include <string.h>
+
+#include "qemu.h"
+
+#include "target_arch_sysarch.h"
+#include "target_os_vmparam.h"
+
+/*
+ * XXX this uses the undocumented oidfmt interface to find the kind of
+ * a requested sysctl, see /sys/kern/kern_sysctl.c:sysctl_sysctl_oidfmt()
+ * (compare to src/sbin/sysctl/sysctl.c)
+ */
+static int
+oidfmt(int *oid, int len, char *fmt, uint32_t *kind)
+{
+    int qoid[CTL_MAXNAME+2];
+    uint8_t buf[BUFSIZ];
+    int i;
+    size_t j;
+
+    qoid[0] = 0;
+    qoid[1] = 4;
+    memcpy(qoid + 2, oid, len * sizeof(int));
+
+    j = sizeof(buf);
+    i = sysctl(qoid, len + 2, buf, &j, 0, 0);
+    if (i) {
+        return i;
+    }
+
+    if (kind) {
+        *kind = *(uint32_t *)buf;
+    }
+
+    if (fmt) {
+        strcpy(fmt, (char *)(buf + sizeof(uint32_t)));
+    }
+    return 0;
+}
+
+/*
+ * try and convert sysctl return data for the target.
+ * XXX doesn't handle CTLTYPE_OPAQUE and CTLTYPE_STRUCT.
+ */
+static int sysctl_oldcvt(void *holdp, size_t holdlen, uint32_t kind)
+{
+    switch (kind & CTLTYPE) {
+    case CTLTYPE_INT:
+    case CTLTYPE_UINT:
+        *(uint32_t *)holdp = tswap32(*(uint32_t *)holdp);
+        break;
+
+#ifdef TARGET_ABI32
+    case CTLTYPE_LONG:
+    case CTLTYPE_ULONG:
+        *(uint32_t *)holdp = tswap32(*(long *)holdp);
+        break;
+#else
+    case CTLTYPE_LONG:
+        *(uint64_t *)holdp = tswap64(*(long *)holdp);
+    case CTLTYPE_ULONG:
+        *(uint64_t *)holdp = tswap64(*(unsigned long *)holdp);
+        break;
+#endif
+#if !defined(__FreeBSD_version) || __FreeBSD_version < 900031
+    case CTLTYPE_QUAD:
+#else
+    case CTLTYPE_U64:
+    case CTLTYPE_S64:
+#endif
+        *(uint64_t *)holdp = tswap64(*(uint64_t *)holdp);
+        break;
+
+    case CTLTYPE_STRING:
+        break;
+
+    default:
+        /* XXX unhandled */
+        return -1;
+    }
+    return 0;
+}
+
+/*
+ * Convert the undocmented name2oid sysctl data for the target.
+ */
+static inline void sysctl_name2oid(uint32_t *holdp, size_t holdlen)
+{
+    size_t i;
+
+    for (i = 0; i < holdlen; i++) {
+        holdp[i] = tswap32(holdp[i]);
+    }
+}
+
+static inline void sysctl_oidfmt(uint32_t *holdp)
+{
+    /* byte swap the kind */
+    holdp[0] = tswap32(holdp[0]);
+}
+
+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)
+{
+    abi_long ret;
+    void *hnamep, *holdp = NULL, *hnewp = NULL;
+    size_t holdlen;
+    abi_ulong oldlen = 0;
+    int32_t *snamep = g_malloc(sizeof(int32_t) * namelen), *p, *q, i;
+    uint32_t kind = 0;
+    TaskState *ts = (TaskState *)env->opaque;
+
+    if (oldlenp) {
+        if (get_user_ual(oldlen, oldlenp)) {
+            return -TARGET_EFAULT;
+        }
+    }
+    hnamep = lock_user(VERIFY_READ, namep, namelen, 1);
+    if (hnamep == NULL) {
+        return -TARGET_EFAULT;
+    }
+    if (newp) {
+        hnewp = lock_user(VERIFY_READ, newp, newlen, 1);
+        if (hnewp == NULL) {
+            return -TARGET_EFAULT;
+        }
+    }
+    if (oldp) {
+        holdp = lock_user(VERIFY_WRITE, oldp, oldlen, 0);
+        if (holdp == NULL) {
+            return -TARGET_EFAULT;
+        }
+    }
+    holdlen = oldlen;
+    for (p = hnamep, q = snamep, i = 0; i < namelen; p++, i++) {
+        *q++ = tswap32(*p);
+    }
+    oidfmt(snamep, namelen, NULL, &kind);
+
+    /* Handle some arch/emulator dependent sysctl()'s here. */
+    switch (snamep[0]) {
+    case CTL_KERN:
+        switch (snamep[1]) {
+        case KERN_USRSTACK:
+#if TARGET_USRSTACK != 0
+            (*(abi_ulong *)holdp) = tswapal(TARGET_USRSTACK);
+            holdlen = sizeof(abi_ulong);
+            ret = 0;
+#else
+            ret = -TARGET_ENOENT;
+#endif
+            goto out;
+
+        case KERN_PS_STRINGS:
+#if defined(TARGET_PS_STRINGS)
+            (*(abi_ulong *)holdp) = tswapal(TARGET_PS_STRINGS);
+            holdlen = sizeof(abi_ulong);
+            ret = 0;
+#else
+            ret = -TARGET_ENOENT;
+#endif
+            goto out;
+
+        case KERN_PROC:
+            switch (snamep[2]) {
+            case KERN_PROC_PATHNAME:
+                holdlen = strlen(ts->bprm->fullpath) + 1;
+                if (holdp) {
+                    if (oldlen < holdlen) {
+                        ret = -TARGET_EINVAL;
+                        goto out;
+                    }
+                    strlcpy(holdp, ts->bprm->fullpath, oldlen);
+                }
+                ret = 0;
+                goto out;
+
+            default:
+                break;
+            }
+            break;
+
+        default:
+            break;
+        }
+        break;
+
+    case CTL_HW:
+        switch (snamep[1]) {
+        case HW_MACHINE:
+            strlcpy(holdp, TARGET_HW_MACHINE, oldlen);
+            ret = 0;
+            goto out;
+
+        case HW_MACHINE_ARCH:
+            strlcpy(holdp, TARGET_HW_MACHINE_ARCH, oldlen);
+            ret = 0;
+            goto out;
+
+        case 851: /* hw.availpages */
+            {
+                long lvalue;
+                size_t len = sizeof(lvalue);
+
+                if (sysctlbyname("hw.availpages", &lvalue, &len, NULL, 0)
+                        == -1) {
+                    ret = -1;
+                } else {
+                    (*(abi_ulong *)holdp) = tswapal((abi_ulong)lvalue);
+                    holdlen = sizeof(abi_ulong);
+                    ret = 0;
+                }
+            }
+            goto out;
+
+        default:
+            break;
+        }
+    default:
+        break;
+    }
+
+    ret = get_errno(sysctl(snamep, namelen, holdp, &holdlen, hnewp, newlen));
+    if (!ret && (holdp != 0 && holdlen != 0)) {
+        if (0 == snamep[0] && (3 == snamep[1] || 4 == snamep[1])) {
+            if (3 == snamep[1]) {
+                /* Handle the undocumented name2oid special case. */
+                sysctl_name2oid(holdp, holdlen);
+            } else {
+                /* Handle oidfmt */
+                sysctl_oidfmt(holdp);
+            }
+        } else {
+            sysctl_oldcvt(holdp, holdlen, kind);
+        }
+    }
+#ifdef DEBUG
+    else {
+        printf("sysctl(mib[0]=%d, mib[1]=%d, mib[3]=%d...) returned %d\n",
+        snamep[0], snamep[1], snamep[2], (int)ret);
+    }
+#endif
+
+out:
+    if (oldlenp) {
+        put_user_ual(holdlen, oldlenp);
+    }
+    unlock_user(hnamep, namep, 0);
+    unlock_user(holdp, oldp, holdlen);
+    if (hnewp) {
+        unlock_user(hnewp, newp, 0);
+    }
+    g_free(snamep);
+    return ret;
+}
+
+/* sysarch() is architecture dependent. */
+abi_long do_freebsd_sysarch(void *cpu_env, abi_long arg1, abi_long arg2)
+{
+
+    return do_freebsd_arch_sysarch(cpu_env, arg1, arg2);
+}
diff --git a/bsd-user/freebsd/target_os_stack.h 
b/bsd-user/freebsd/target_os_stack.h
new file mode 100644
index 0000000..c84b69e
--- /dev/null
+++ b/bsd-user/freebsd/target_os_stack.h
@@ -0,0 +1,157 @@
+#ifndef _TARGET_OS_STACK_H_
+#define _TARGET_OS_STACK_H_
+
+#include <sys/param.h>
+#include "target_arch_sigtramp.h"
+
+/*
+ * The inital FreeBSD stack is as follows:
+ * (see kern/kern_exec.c exec_copyout_strings() )
+ *
+ *  Hi Address -> char **ps_argvstr  (struct ps_strings for ps, w, etc.)
+ *                unsigned ps_nargvstr
+ *                char **ps_envstr
+ *  PS_STRINGS -> unsigned ps_nenvstr
+ *
+ *                machine dependent sigcode (sv_sigcode of size
+ *                                           sv_szsigcode)
+ *
+ *                execpath          (absolute image path for rtld)
+ *
+ *                SSP Canary        (sizeof(long) * 8)
+ *
+ *                page sizes array  (usually sizeof(u_long) )
+ *
+ *  "destp" ->    argv, env strings (up to 262144 bytes)
+ */
+static inline int setup_initial_stack(struct bsd_binprm *bprm,
+        abi_ulong *ret_addr)
+{
+    int i;
+    abi_ulong stack_hi_addr;
+    size_t execpath_len, stringspace;
+    abi_ulong destp, argvp, envp, p;
+    struct target_ps_strings ps_strs;
+    char canary[sizeof(abi_long) * 8];
+
+    stack_hi_addr = p = target_stkbas + target_stksiz;
+
+    /* Save some space for ps_strings. */
+    p -= sizeof(struct target_ps_strings);
+
+#ifdef TARGET_SZSIGCODE
+    /* Add machine depedent sigcode. */
+    p -= TARGET_SZSIGCODE;
+    if (setup_sigtramp(p, (unsigned)offsetof(struct target_sigframe, sf_uc),
+            TARGET_FREEBSD_NR_sigreturn)) {
+        errno = EFAULT;
+        return -1;
+    }
+#endif
+    if (bprm->fullpath) {
+        execpath_len = strlen(bprm->fullpath) + 1;
+        p -= roundup(execpath_len, sizeof(abi_ulong));
+        if (memcpy_to_target(p, bprm->fullpath, execpath_len)) {
+            errno = EFAULT;
+            return -1;
+        }
+    }
+    /* Add canary for SSP. */
+    arc4random_buf(canary, sizeof(canary));
+    p -= roundup(sizeof(canary), sizeof(abi_ulong));
+    if (memcpy_to_target(p, canary, sizeof(canary))) {
+        errno = EFAULT;
+        return -1;
+    }
+    /* Add page sizes array. */
+    /* p -= sizeof(int); */
+    p -= sizeof(abi_ulong);
+    /* if (put_user_u32(TARGET_PAGE_SIZE, p)) { */
+    if (put_user_ual(TARGET_PAGE_SIZE, p)) {
+        errno = EFAULT;
+        return -1;
+    }
+    /* Calculate the string space needed */
+    stringspace = 0;
+    for (i = 0; i < bprm->argc; ++i) {
+        stringspace += strlen(bprm->argv[i]) + 1;
+    }
+    for (i = 0; i < bprm->envc; ++i) {
+        stringspace += strlen(bprm->envp[i]) + 1;
+    }
+    if (stringspace > TARGET_ARG_MAX) {
+       errno = ENOMEM;
+       return -1;
+    }
+
+    /* Make room for the argv and envp strings */
+    /* p = destp = roundup(p - TARGET_SPACE_USRSPACE - (TARGET_ARG_MAX - 
stringspace), sizeof(abi_ulong)); */
+    argvp = p - TARGET_SPACE_USRSPACE;
+    p = destp = roundup(p - TARGET_SPACE_USRSPACE - TARGET_ARG_MAX, 
sizeof(abi_ulong));
+
+    /*
+     * Add argv strings.  Note that the argv[] vectors are added by
+     * loader_build_argptr()
+     */
+    /* XXX need to make room for auxargs */
+    /* argvp = destp - ((bprm->argc + bprm->envc + 2) * sizeof(abi_ulong)); */
+    /* envp = argvp + (bprm->argc + 2) * sizeof(abi_ulong); */
+    envp = argvp + (bprm->argc + 1) * sizeof(abi_ulong);
+    ps_strs.ps_argvstr = tswapl(argvp);
+    ps_strs.ps_nargvstr = tswap32(bprm->argc);
+    for (i = 0; i < bprm->argc; ++i) {
+        size_t len = strlen(bprm->argv[i]) + 1;
+
+        if (memcpy_to_target(destp, bprm->argv[i], len)) {
+            errno = EFAULT;
+            return -1;
+        }
+        if (put_user_ual(destp, argvp)) {
+            errno = EFAULT;
+            return -1;
+        }
+        argvp += sizeof(abi_ulong);
+        destp += len;
+    }
+    if (put_user_ual(0, argvp)) {
+        errno = EFAULT;
+        return -1;
+    }
+    /*
+     * Add env strings. Note that the envp[] vectors are added by
+     * loader_build_argptr().
+     */
+    ps_strs.ps_envstr = tswapl(envp);
+    ps_strs.ps_nenvstr = tswap32(bprm->envc);
+    for (i = 0; i < bprm->envc; ++i) {
+        size_t len = strlen(bprm->envp[i]) + 1;
+
+        if (memcpy_to_target(destp, bprm->envp[i], len)) {
+            errno = EFAULT;
+            return -1;
+        }
+        if (put_user_ual(destp, envp)) {
+            errno = EFAULT;
+            return -1;
+        }
+        envp += sizeof(abi_ulong);
+        destp += len;
+    }
+    if (put_user_ual(0, envp)) {
+        errno = EFAULT;
+        return -1;
+    }
+    if (memcpy_to_target(stack_hi_addr - sizeof(ps_strs), &ps_strs,
+                sizeof(ps_strs))) {
+        errno = EFAULT;
+        return -1;
+    }
+
+    if (ret_addr) {
+       *ret_addr = p;
+    }
+
+    return 0;
+ }
+
+#endif /* !_TARGET_OS_STACK_H_ */
diff --git a/bsd-user/i386/target_arch_sigtramp.h 
b/bsd-user/i386/target_arch_sigtramp.h
new file mode 100644
index 0000000..f0f36d1
--- /dev/null
+++ b/bsd-user/i386/target_arch_sigtramp.h
@@ -0,0 +1,11 @@
+
+#ifndef _TARGET_ARCH_SIGTRAMP_H_
+#define _TARGET_ARCH_SIGTRAMP_H_
+
+static inline abi_long setup_sigtramp(abi_ulong offset, unsigned sigf_uc,
+        unsigned sys_sigreturn)
+{
+
+    return -TARGET_EOPNOTSUPP;
+}
+#endif /* _TARGET_ARCH_SIGTRAMP_H_ */
diff --git a/bsd-user/mips/target_arch_sigtramp.h 
b/bsd-user/mips/target_arch_sigtramp.h
new file mode 100644
index 0000000..5e3c69a
--- /dev/null
+++ b/bsd-user/mips/target_arch_sigtramp.h
@@ -0,0 +1,23 @@
+
+#ifndef _TARGET_ARCH_SIGTRAMP_H_
+#define _TARGET_ARCH_SIGTRAMP_H_
+
+/* Compare to mips/mips/locore.S sigcode() */
+static inline abi_long setup_sigtramp(abi_ulong offset, unsigned sigf_uc,
+        unsigned sys_sigreturn)
+{
+    int i;
+    uint32_t sigtramp_code[TARGET_SZSIGCODE/TARGET_INSN_SIZE] = {
+    /* 1 */ 0x67A40000 + sigf_uc,       /* daddu   $a0, $sp, (sigf_uc) */
+    /* 2 */ 0x24020000 + sys_sigreturn, /* li      $v0, (sys_sigreturn) */
+    /* 3 */ 0x0000000C,                 /* syscall */
+    /* 4 */ 0x0000000D                  /* break */
+    };
+
+    for (i = 0; i < 4; i++) {
+        tswap32s(&sigtramp_code[i]);
+    }
+
+    return memcpy_to_target(offset, sigtramp_code, TARGET_SZSIGCODE);
+}
+#endif /* _TARGET_ARCH_SIGTRAMP_H_ */
diff --git a/bsd-user/mips64/target_arch_sigtramp.h 
b/bsd-user/mips64/target_arch_sigtramp.h
new file mode 100644
index 0000000..5e3c69a
--- /dev/null
+++ b/bsd-user/mips64/target_arch_sigtramp.h
@@ -0,0 +1,23 @@
+
+#ifndef _TARGET_ARCH_SIGTRAMP_H_
+#define _TARGET_ARCH_SIGTRAMP_H_
+
+/* Compare to mips/mips/locore.S sigcode() */
+static inline abi_long setup_sigtramp(abi_ulong offset, unsigned sigf_uc,
+        unsigned sys_sigreturn)
+{
+    int i;
+    uint32_t sigtramp_code[TARGET_SZSIGCODE/TARGET_INSN_SIZE] = {
+    /* 1 */ 0x67A40000 + sigf_uc,       /* daddu   $a0, $sp, (sigf_uc) */
+    /* 2 */ 0x24020000 + sys_sigreturn, /* li      $v0, (sys_sigreturn) */
+    /* 3 */ 0x0000000C,                 /* syscall */
+    /* 4 */ 0x0000000D                  /* break */
+    };
+
+    for (i = 0; i < 4; i++) {
+        tswap32s(&sigtramp_code[i]);
+    }
+
+    return memcpy_to_target(offset, sigtramp_code, TARGET_SZSIGCODE);
+}
+#endif /* _TARGET_ARCH_SIGTRAMP_H_ */
diff --git a/bsd-user/netbsd/os-sys.c b/bsd-user/netbsd/os-sys.c
new file mode 100644
index 0000000..68ea0e1
--- /dev/null
+++ b/bsd-user/netbsd/os-sys.c
@@ -0,0 +1,46 @@
+/*
+ *  NetBSD sysctl() and sysarch() system call emulation
+ *
+ *
+ *  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/param.h>
+#include <sys/sysctl.h>
+#include <string.h>
+
+#include "qemu.h"
+
+#include "target_arch_sysarch.h"
+#include "target_os_vmparam.h"
+
+
+/* This must be emulated to support FreeBSD target binaries on NetBSD host. */
+
+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)
+{
+
+    qemu_log("qemu: Unsupported syscall __sysctl()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* sysarch() is architecture dependent. */
+abi_long do_freebsd_sysarch(void *cpu_env, abi_long arg1, abi_long arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall sysarch()\n");
+    return -TARGET_ENOSYS;
+}
diff --git a/bsd-user/netbsd/target_os_stack.h 
b/bsd-user/netbsd/target_os_stack.h
new file mode 100644
index 0000000..1a26c3f
--- /dev/null
+++ b/bsd-user/netbsd/target_os_stack.h
@@ -0,0 +1,33 @@
+#ifndef _TARGET_OS_STACK_H_
+#define _TARGET_OS_STACK_H_
+
+#include "target_arch_sigtramp.h"
+
+static inline int setup_initial_stack(struct bsd_binprm *bprm, abi_ulong *p)
+{
+    int i;
+    abi_ulong stack_base;
+
+    stack_base = (target_stkbas + target_stksiz) -
+                  MAX_ARG_PAGES * TARGET_PAGE_SIZE;
+    if (p) {
+        *p = stack_base;
+    }
+
+    for (i = 0; i < MAX_ARG_PAGES; i++) {
+        if (bprm->page[i]) {
+            info->rss++;
+            if (!memcpy_to_target(stack_base, bprm->page[i],
+                        TARGET_PAGE_SIZE)) {
+                errno = EFAULT;
+                return -1;
+            }
+            g_free(bprm->page[i]);
+        }
+        stack_base += TARGET_PAGE_SIZE;
+    }
+
+    return 0;
+}
+
+#endif /* !_TARGET_OS_STACK_H_ */
diff --git a/bsd-user/openbsd/os-sys.c b/bsd-user/openbsd/os-sys.c
new file mode 100644
index 0000000..30df472
--- /dev/null
+++ b/bsd-user/openbsd/os-sys.c
@@ -0,0 +1,46 @@
+/*
+ *  OpenBSD sysctl() and sysarch() system call emulation
+ *
+ *
+ *  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/param.h>
+#include <sys/sysctl.h>
+#include <string.h>
+
+#include "qemu.h"
+
+#include "target_arch_sysarch.h"
+#include "target_os_vmparam.h"
+
+
+/* This must be emulated to support FreeBSD target binaries on NetBSD host. */
+
+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)
+{
+
+    qemu_log("qemu: Unsupported syscall __sysctl()\n");
+    return -TARGET_ENOSYS;
+}
+
+/* sysarch() is architecture dependent. */
+abi_long do_freebsd_sysarch(void *cpu_env, abi_long arg1, abi_long arg2)
+{
+
+    qemu_log("qemu: Unsupported syscall sysarch()\n");
+    return -TARGET_ENOSYS;
+}
diff --git a/bsd-user/openbsd/target_os_stack.h 
b/bsd-user/openbsd/target_os_stack.h
new file mode 100644
index 0000000..1a26c3f
--- /dev/null
+++ b/bsd-user/openbsd/target_os_stack.h
@@ -0,0 +1,33 @@
+#ifndef _TARGET_OS_STACK_H_
+#define _TARGET_OS_STACK_H_
+
+#include "target_arch_sigtramp.h"
+
+static inline int setup_initial_stack(struct bsd_binprm *bprm, abi_ulong *p)
+{
+    int i;
+    abi_ulong stack_base;
+
+    stack_base = (target_stkbas + target_stksiz) -
+                  MAX_ARG_PAGES * TARGET_PAGE_SIZE;
+    if (p) {
+        *p = stack_base;
+    }
+
+    for (i = 0; i < MAX_ARG_PAGES; i++) {
+        if (bprm->page[i]) {
+            info->rss++;
+            if (!memcpy_to_target(stack_base, bprm->page[i],
+                        TARGET_PAGE_SIZE)) {
+                errno = EFAULT;
+                return -1;
+            }
+            g_free(bprm->page[i]);
+        }
+        stack_base += TARGET_PAGE_SIZE;
+    }
+
+    return 0;
+}
+
+#endif /* !_TARGET_OS_STACK_H_ */
diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
index cb77069..594de5c 100644
--- a/bsd-user/qemu.h
+++ b/bsd-user/qemu.h
@@ -90,6 +90,7 @@ typedef struct TaskState {
     struct TaskState *next;
     int used; /* non zero if used */
     struct image_info *info;
+    struct bsd_binprm *bprm;
 
     struct emulated_sigtable sigtab[TARGET_NSIG];
     struct sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */
@@ -118,7 +119,7 @@ extern unsigned long mmap_min_addr;
  * This structure is used to hold the arguments that are
  * used when loading binaries.
  */
-struct linux_binprm {
+struct bsd_binprm {
         char buf[128];
         void *page[MAX_ARG_PAGES];
         abi_ulong p;
@@ -127,19 +128,23 @@ struct linux_binprm {
         int argc, envc;
         char **argv;
         char **envp;
-        char * filename;        /* Name of binary */
+        char *filename;         /* (Given) Name of binary */
+        char *fullpath;         /* Full path of binary */
+        int (*core_dump)(int, const CPUArchState *);
 };
 
 void do_init_thread(struct target_pt_regs *regs, struct image_info *infop);
 abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
                               abi_ulong stringp, int push_ptr);
-int loader_exec(const char * filename, char ** argv, char ** envp,
-             struct target_pt_regs * regs, struct image_info *infop);
+int loader_exec(const char *filename, char **argv, char **envp,
+             struct target_pt_regs *regs, struct image_info *infop,
+             struct bsd_binprm *bprm);
 
-int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
-                    struct image_info * info);
-int load_flt_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
-                    struct image_info * info);
+int load_elf_binary(struct bsd_binprm *bprm, struct target_pt_regs *regs,
+                    struct image_info *info);
+int load_flt_binary(struct bsd_binprm *bprm, struct target_pt_regs *regs,
+                    struct image_info *info);
+int is_target_elf_binary(int fd);
 
 abi_long memcpy_to_target(abi_ulong dest, const void *src,
                           unsigned long len);
@@ -232,6 +237,15 @@ extern unsigned long target_maxssiz;
 extern unsigned long target_sgrowsiz;
 extern char qemu_proc_pathname[];
 
+/* syscall.c */
+abi_long get_errno(abi_long ret);
+int is_error(abi_long ret);
+
+/* 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);
+abi_long do_freebsd_sysarch(void *cpu_env, abi_long arg1, abi_long arg2);
+
 /* user access */
 
 #define VERIFY_READ 0
diff --git a/bsd-user/sparc/target_arch_sigtramp.h 
b/bsd-user/sparc/target_arch_sigtramp.h
new file mode 100644
index 0000000..f0f36d1
--- /dev/null
+++ b/bsd-user/sparc/target_arch_sigtramp.h
@@ -0,0 +1,11 @@
+
+#ifndef _TARGET_ARCH_SIGTRAMP_H_
+#define _TARGET_ARCH_SIGTRAMP_H_
+
+static inline abi_long setup_sigtramp(abi_ulong offset, unsigned sigf_uc,
+        unsigned sys_sigreturn)
+{
+
+    return -TARGET_EOPNOTSUPP;
+}
+#endif /* _TARGET_ARCH_SIGTRAMP_H_ */
diff --git a/bsd-user/sparc64/target_arch_sigtramp.h 
b/bsd-user/sparc64/target_arch_sigtramp.h
new file mode 100644
index 0000000..f0f36d1
--- /dev/null
+++ b/bsd-user/sparc64/target_arch_sigtramp.h
@@ -0,0 +1,11 @@
+
+#ifndef _TARGET_ARCH_SIGTRAMP_H_
+#define _TARGET_ARCH_SIGTRAMP_H_
+
+static inline abi_long setup_sigtramp(abi_ulong offset, unsigned sigf_uc,
+        unsigned sys_sigreturn)
+{
+
+    return -TARGET_EOPNOTSUPP;
+}
+#endif /* _TARGET_ARCH_SIGTRAMP_H_ */
diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c
index a4d1583..dbc212d 100644
--- a/bsd-user/syscall.c
+++ b/bsd-user/syscall.c
@@ -2,6 +2,7 @@
  *  BSD syscalls
  *
  *  Copyright (c) 2003 - 2008 Fabrice Bellard
+ *  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
@@ -36,12 +37,17 @@
 #include "qemu.h"
 #include "qemu-common.h"
 
-//#define DEBUG
+#define target_to_host_bitmask(x, tbl) (x)
+
+/* #define DEBUG */
 
 static abi_ulong target_brk;
 static abi_ulong target_original_brk;
 
-static inline abi_long get_errno(abi_long ret)
+/*
+ * errno conversion.
+ */
+abi_long get_errno(abi_long ret)
 {
     if (ret == -1)
         /* XXX need to translate host -> target errnos here */
@@ -50,9 +56,7 @@ static inline abi_long get_errno(abi_long ret)
         return ret;
 }
 
-#define target_to_host_bitmask(x, tbl) (x)
-
-static inline int is_error(abi_long ret)
+int is_error(abi_long ret)
 {
     return (abi_ulong)ret >= (abi_ulong)(-4096);
 }
@@ -96,175 +100,6 @@ static abi_long do_obreak(abi_ulong new_brk)
     return 0;
 }
 
-#if defined(TARGET_I386)
-static abi_long do_freebsd_sysarch(CPUX86State *env, int op, abi_ulong parms)
-{
-    abi_long ret = 0;
-    abi_ulong val;
-    int idx;
-
-    switch(op) {
-#ifdef TARGET_ABI32
-    case TARGET_FREEBSD_I386_SET_GSBASE:
-    case TARGET_FREEBSD_I386_SET_FSBASE:
-        if (op == TARGET_FREEBSD_I386_SET_GSBASE)
-#else
-    case TARGET_FREEBSD_AMD64_SET_GSBASE:
-    case TARGET_FREEBSD_AMD64_SET_FSBASE:
-        if (op == TARGET_FREEBSD_AMD64_SET_GSBASE)
-#endif
-            idx = R_GS;
-        else
-            idx = R_FS;
-        if (get_user(val, parms, abi_ulong))
-            return -TARGET_EFAULT;
-        cpu_x86_load_seg(env, idx, 0);
-        env->segs[idx].base = val;
-        break;
-#ifdef TARGET_ABI32
-    case TARGET_FREEBSD_I386_GET_GSBASE:
-    case TARGET_FREEBSD_I386_GET_FSBASE:
-        if (op == TARGET_FREEBSD_I386_GET_GSBASE)
-#else
-    case TARGET_FREEBSD_AMD64_GET_GSBASE:
-    case TARGET_FREEBSD_AMD64_GET_FSBASE:
-        if (op == TARGET_FREEBSD_AMD64_GET_GSBASE)
-#endif
-            idx = R_GS;
-        else
-            idx = R_FS;
-        val = env->segs[idx].base;
-        if (put_user(val, parms, abi_ulong))
-            return -TARGET_EFAULT;
-        break;
-    /* XXX handle the others... */
-    default:
-        ret = -TARGET_EINVAL;
-        break;
-    }
-    return ret;
-}
-#endif
-
-#ifdef TARGET_SPARC
-static abi_long do_freebsd_sysarch(void *env, int op, abi_ulong parms)
-{
-    /* XXX handle
-     * TARGET_FREEBSD_SPARC_UTRAP_INSTALL,
-     * TARGET_FREEBSD_SPARC_SIGTRAMP_INSTALL
-     */
-    return -TARGET_EINVAL;
-}
-#endif
-
-#ifdef __FreeBSD__
-/*
- * XXX this uses the undocumented oidfmt interface to find the kind of
- * a requested sysctl, see /sys/kern/kern_sysctl.c:sysctl_sysctl_oidfmt()
- * (this is mostly copied from src/sbin/sysctl/sysctl.c)
- */
-static int
-oidfmt(int *oid, int len, char *fmt, uint32_t *kind)
-{
-    int qoid[CTL_MAXNAME+2];
-    uint8_t buf[BUFSIZ];
-    int i;
-    size_t j;
-
-    qoid[0] = 0;
-    qoid[1] = 4;
-    memcpy(qoid + 2, oid, len * sizeof(int));
-
-    j = sizeof(buf);
-    i = sysctl(qoid, len + 2, buf, &j, 0, 0);
-    if (i)
-        return i;
-
-    if (kind)
-        *kind = *(uint32_t *)buf;
-
-    if (fmt)
-        strcpy(fmt, (char *)(buf + sizeof(uint32_t)));
-    return (0);
-}
-
-/*
- * try and convert sysctl return data for the target.
- * XXX doesn't handle CTLTYPE_OPAQUE and CTLTYPE_STRUCT.
- */
-static int sysctl_oldcvt(void *holdp, size_t holdlen, uint32_t kind)
-{
-    switch (kind & CTLTYPE) {
-    case CTLTYPE_INT:
-    case CTLTYPE_UINT:
-        *(uint32_t *)holdp = tswap32(*(uint32_t *)holdp);
-        break;
-#ifdef TARGET_ABI32
-    case CTLTYPE_LONG:
-    case CTLTYPE_ULONG:
-        *(uint32_t *)holdp = tswap32(*(long *)holdp);
-        break;
-#else
-    case CTLTYPE_LONG:
-        *(uint64_t *)holdp = tswap64(*(long *)holdp);
-    case CTLTYPE_ULONG:
-        *(uint64_t *)holdp = tswap64(*(unsigned long *)holdp);
-        break;
-#endif
-#ifdef CTLTYPE_U64
-    case CTLTYPE_S64:
-    case CTLTYPE_U64:
-#else
-    case CTLTYPE_QUAD:
-#endif
-        *(uint64_t *)holdp = tswap64(*(uint64_t *)holdp);
-        break;
-    case CTLTYPE_STRING:
-        break;
-    default:
-        /* XXX unhandled */
-        return -1;
-    }
-    return 0;
-}
-
-/* XXX this needs to be emulated on non-FreeBSD hosts... */
-static abi_long do_freebsd_sysctl(abi_ulong namep, int32_t namelen, abi_ulong 
oldp,
-                          abi_ulong oldlenp, abi_ulong newp, abi_ulong newlen)
-{
-    abi_long ret;
-    void *hnamep, *holdp, *hnewp = NULL;
-    size_t holdlen;
-    abi_ulong oldlen = 0;
-    int32_t *snamep = g_malloc(sizeof(int32_t) * namelen), *p, *q, i;
-    uint32_t kind = 0;
-
-    if (oldlenp)
-        get_user_ual(oldlen, oldlenp);
-    if (!(hnamep = lock_user(VERIFY_READ, namep, namelen, 1)))
-        return -TARGET_EFAULT;
-    if (newp && !(hnewp = lock_user(VERIFY_READ, newp, newlen, 1)))
-        return -TARGET_EFAULT;
-    if (!(holdp = lock_user(VERIFY_WRITE, oldp, oldlen, 0)))
-        return -TARGET_EFAULT;
-    holdlen = oldlen;
-    for (p = hnamep, q = snamep, i = 0; i < namelen; p++, i++)
-       *q++ = tswap32(*p);
-    oidfmt(snamep, namelen, NULL, &kind);
-    /* XXX swap hnewp */
-    ret = get_errno(sysctl(snamep, namelen, holdp, &holdlen, hnewp, newlen));
-    if (!ret)
-        sysctl_oldcvt(holdp, holdlen, kind);
-    put_user_ual(holdlen, oldlenp);
-    unlock_user(hnamep, namep, 0);
-    unlock_user(holdp, oldp, holdlen);
-    if (hnewp)
-        unlock_user(hnewp, newp, 0);
-    g_free(snamep);
-    return ret;
-}
-#endif
-
 /* FIXME
  * lock_iovec()/unlock_iovec() have a return code of 0 for success where
  * other lock functions have a return code of 0 for failure.
@@ -387,20 +222,27 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, 
abi_long arg1,
     case TARGET_FREEBSD_NR_break:
         ret = do_obreak(arg1);
         break;
-#ifdef __FreeBSD__
-    case TARGET_FREEBSD_NR___sysctl:
-        ret = do_freebsd_sysctl(arg1, arg2, arg3, arg4, arg5, arg6);
+
+        /*
+         * sys{ctl, arch, call}
+         */
+    case TARGET_FREEBSD_NR___sysctl: /* sysctl(3) */
+        ret = do_freebsd_sysctl(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6);
         break;
-#endif
-    case TARGET_FREEBSD_NR_sysarch:
+
+    case TARGET_FREEBSD_NR_sysarch: /* sysarch(2) */
         ret = do_freebsd_sysarch(cpu_env, arg1, arg2);
         break;
-    case TARGET_FREEBSD_NR_syscall:
-    case TARGET_FREEBSD_NR___syscall:
-        ret = do_freebsd_syscall(cpu_env,arg1 & 
0xffff,arg2,arg3,arg4,arg5,arg6,arg7,arg8,0);
+
+    case TARGET_FREEBSD_NR_syscall: /* syscall(2) */
+    case TARGET_FREEBSD_NR___syscall: /* __syscall(2) */
+        ret = do_freebsd_syscall(cpu_env, arg1 & 0xffff, arg2, arg3, arg4,
+                arg5, arg6, arg7, arg8, 0);
         break;
+
     default:
-        ret = get_errno(syscall(num, arg1, arg2, arg3, arg4, arg5, arg6, arg7, 
arg8));
+        ret = get_errno(syscall(num, arg1, arg2, arg3, arg4, arg5, arg6, arg7,
+                    arg8));
         break;
     }
  fail:
@@ -467,6 +309,7 @@ abi_long do_netbsd_syscall(void *cpu_env, int num, abi_long 
arg1,
     case TARGET_NETBSD_NR_mprotect:
         ret = get_errno(target_mprotect(arg1, arg2, arg3));
         break;
+
     case TARGET_NETBSD_NR_syscall:
     case TARGET_NETBSD_NR___syscall:
         ret = do_netbsd_syscall(cpu_env,arg1 & 
0xffff,arg2,arg3,arg4,arg5,arg6,0);
@@ -539,6 +382,7 @@ abi_long do_openbsd_syscall(void *cpu_env, int num, 
abi_long arg1,
     case TARGET_OPENBSD_NR_mprotect:
         ret = get_errno(target_mprotect(arg1, arg2, arg3));
         break;
+
     case TARGET_OPENBSD_NR_syscall:
     case TARGET_OPENBSD_NR___syscall:
         ret = do_openbsd_syscall(cpu_env,arg1 & 
0xffff,arg2,arg3,arg4,arg5,arg6,0);
diff --git a/bsd-user/x86_64/target_arch_sigtramp.h 
b/bsd-user/x86_64/target_arch_sigtramp.h
new file mode 100644
index 0000000..f0f36d1
--- /dev/null
+++ b/bsd-user/x86_64/target_arch_sigtramp.h
@@ -0,0 +1,11 @@
+
+#ifndef _TARGET_ARCH_SIGTRAMP_H_
+#define _TARGET_ARCH_SIGTRAMP_H_
+
+static inline abi_long setup_sigtramp(abi_ulong offset, unsigned sigf_uc,
+        unsigned sys_sigreturn)
+{
+
+    return -TARGET_EOPNOTSUPP;
+}
+#endif /* _TARGET_ARCH_SIGTRAMP_H_ */
-- 
1.7.8




reply via email to

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