[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
- [Qemu-devel] [PATCH v3 00/19] bsd-user: Add system call and mips/arm support., Stacey Son, 2013/12/17
- Message not available
- Message not available
- [Qemu-devel] [PATCH v3 05/19] bsd-user: move arch/OS dependent code out of syscall.c,
Stacey Son <=
- Message not available
- Message not available
- Message not available
- Message not available
- Message not available
- Message not available
- Message not available
- Message not available
- Message not available
- Message not available