bsd-user: FreeBSD update

basic FreeBSD sysarch(2) handling
fixed syscall errno return

Signed-off-by: Juergen Lock <nox@jelal.kn-bremen.de>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
master
Juergen Lock 2009-10-17 00:34:26 +02:00 committed by Blue Swirl
parent 976b2037e5
commit 78cfb07fe0
9 changed files with 462 additions and 31 deletions

View File

@ -126,6 +126,9 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
regs->rax = 0; regs->rax = 0;
regs->rsp = infop->start_stack; regs->rsp = infop->start_stack;
regs->rip = infop->entry; regs->rip = infop->entry;
if (bsd_type == target_freebsd) {
regs->rdi = infop->start_stack;
}
} }
#else #else
@ -249,8 +252,13 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
#else #else
if (personality(infop->personality) == PER_LINUX32) if (personality(infop->personality) == PER_LINUX32)
regs->u_regs[14] = infop->start_stack - 16 * 4; regs->u_regs[14] = infop->start_stack - 16 * 4;
else else {
regs->u_regs[14] = infop->start_stack - 16 * 8 - STACK_BIAS; regs->u_regs[14] = infop->start_stack - 16 * 8 - STACK_BIAS;
if (bsd_type == target_freebsd) {
regs->u_regs[8] = infop->start_stack;
regs->u_regs[11] = infop->start_stack;
}
}
#endif #endif
} }

View File

@ -39,6 +39,7 @@
{ TARGET_FREEBSD_NR_ftruncate, "ftruncate", NULL, NULL, NULL }, { TARGET_FREEBSD_NR_ftruncate, "ftruncate", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_futimes, "futimes", NULL, NULL, NULL }, { TARGET_FREEBSD_NR_futimes, "futimes", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_getdirentries, "getdirentries", NULL, NULL, NULL }, { TARGET_FREEBSD_NR_getdirentries, "getdirentries", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_freebsd6_mmap, "freebsd6_mmap", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_getegid, "getegid", "%s()", NULL, NULL }, { TARGET_FREEBSD_NR_getegid, "getegid", "%s()", NULL, NULL },
{ TARGET_FREEBSD_NR_geteuid, "geteuid", "%s()", NULL, NULL }, { TARGET_FREEBSD_NR_geteuid, "geteuid", "%s()", NULL, NULL },
{ TARGET_FREEBSD_NR_getfh, "getfh", NULL, NULL, NULL }, { TARGET_FREEBSD_NR_getfh, "getfh", NULL, NULL, NULL },

View File

@ -143,5 +143,19 @@ struct target_vm86plus_struct {
struct target_vm86plus_info_struct vm86plus; struct target_vm86plus_info_struct vm86plus;
}; };
/* FreeBSD sysarch(2) */
#define TARGET_FREEBSD_I386_GET_LDT 0
#define TARGET_FREEBSD_I386_SET_LDT 1
/* I386_IOPL */
#define TARGET_FREEBSD_I386_GET_IOPERM 3
#define TARGET_FREEBSD_I386_SET_IOPERM 4
/* xxxxx */
#define TARGET_FREEBSD_I386_VM86 6
#define TARGET_FREEBSD_I386_GET_FSBASE 7
#define TARGET_FREEBSD_I386_SET_FSBASE 8
#define TARGET_FREEBSD_I386_GET_GSBASE 9
#define TARGET_FREEBSD_I386_SET_GSBASE 10
#define UNAME_MACHINE "i386" #define UNAME_MACHINE "i386"

View File

@ -46,6 +46,7 @@ int have_guest_base;
static const char *interp_prefix = CONFIG_QEMU_PREFIX; static const char *interp_prefix = CONFIG_QEMU_PREFIX;
const char *qemu_uname_release = CONFIG_UNAME_RELEASE; const char *qemu_uname_release = CONFIG_UNAME_RELEASE;
extern char **environ; extern char **environ;
enum BSDType bsd_type;
/* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
we allocate a bigger stack. Need a better solution, for example we allocate a bigger stack. Need a better solution, for example
@ -168,7 +169,7 @@ static void set_idt(int n, unsigned int dpl)
} }
#endif #endif
void cpu_loop(CPUX86State *env, enum BSDType bsd_type) void cpu_loop(CPUX86State *env)
{ {
int trapnr; int trapnr;
abi_ulong pc; abi_ulong pc;
@ -179,6 +180,45 @@ void cpu_loop(CPUX86State *env, enum BSDType bsd_type)
switch(trapnr) { switch(trapnr) {
case 0x80: case 0x80:
/* syscall from int $0x80 */ /* syscall from int $0x80 */
if (bsd_type == target_freebsd) {
abi_ulong params = (abi_ulong) env->regs[R_ESP] +
sizeof(int32_t);
int32_t syscall_nr = env->regs[R_EAX];
int32_t arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8;
if (syscall_nr == TARGET_FREEBSD_NR_syscall) {
get_user_s32(syscall_nr, params);
params += sizeof(int32_t);
} else if (syscall_nr == TARGET_FREEBSD_NR___syscall) {
get_user_s32(syscall_nr, params);
params += sizeof(int64_t);
}
get_user_s32(arg1, params);
params += sizeof(int32_t);
get_user_s32(arg2, params);
params += sizeof(int32_t);
get_user_s32(arg3, params);
params += sizeof(int32_t);
get_user_s32(arg4, params);
params += sizeof(int32_t);
get_user_s32(arg5, params);
params += sizeof(int32_t);
get_user_s32(arg6, params);
params += sizeof(int32_t);
get_user_s32(arg7, params);
params += sizeof(int32_t);
get_user_s32(arg8, params);
env->regs[R_EAX] = do_freebsd_syscall(env,
syscall_nr,
arg1,
arg2,
arg3,
arg4,
arg5,
arg6,
arg7,
arg8);
} else { //if (bsd_type == target_openbsd)
env->regs[R_EAX] = do_openbsd_syscall(env, env->regs[R_EAX] = do_openbsd_syscall(env,
env->regs[R_EAX], env->regs[R_EAX],
env->regs[R_EBX], env->regs[R_EBX],
@ -187,10 +227,27 @@ void cpu_loop(CPUX86State *env, enum BSDType bsd_type)
env->regs[R_ESI], env->regs[R_ESI],
env->regs[R_EDI], env->regs[R_EDI],
env->regs[R_EBP]); env->regs[R_EBP]);
}
if (((abi_ulong)env->regs[R_EAX]) >= (abi_ulong)(-515)) {
env->regs[R_EAX] = -env->regs[R_EAX];
env->eflags |= CC_C;
} else {
env->eflags &= ~CC_C;
}
break; break;
#ifndef TARGET_ABI32 #ifndef TARGET_ABI32
case EXCP_SYSCALL: case EXCP_SYSCALL:
/* linux syscall from syscall intruction */ /* syscall from syscall intruction */
if (bsd_type == target_freebsd)
env->regs[R_EAX] = do_freebsd_syscall(env,
env->regs[R_EAX],
env->regs[R_EDI],
env->regs[R_ESI],
env->regs[R_EDX],
env->regs[R_ECX],
env->regs[8],
env->regs[9], 0, 0);
else { //if (bsd_type == target_openbsd)
env->regs[R_EAX] = do_openbsd_syscall(env, env->regs[R_EAX] = do_openbsd_syscall(env,
env->regs[R_EAX], env->regs[R_EAX],
env->regs[R_EDI], env->regs[R_EDI],
@ -199,7 +256,14 @@ void cpu_loop(CPUX86State *env, enum BSDType bsd_type)
env->regs[10], env->regs[10],
env->regs[8], env->regs[8],
env->regs[9]); env->regs[9]);
}
env->eip = env->exception_next_eip; env->eip = env->exception_next_eip;
if (((abi_ulong)env->regs[R_EAX]) >= (abi_ulong)(-515)) {
env->regs[R_EAX] = -env->regs[R_EAX];
env->eflags |= CC_C;
} else {
env->eflags &= ~CC_C;
}
break; break;
#endif #endif
#if 0 #if 0
@ -446,7 +510,7 @@ static void flush_windows(CPUSPARCState *env)
#endif #endif
} }
void cpu_loop(CPUSPARCState *env, enum BSDType bsd_type) void cpu_loop(CPUSPARCState *env)
{ {
int trapnr, ret, syscall_nr; int trapnr, ret, syscall_nr;
//target_siginfo_t info; //target_siginfo_t info;
@ -458,6 +522,10 @@ void cpu_loop(CPUSPARCState *env, enum BSDType bsd_type)
#ifndef TARGET_SPARC64 #ifndef TARGET_SPARC64
case 0x80: case 0x80:
#else #else
/* FreeBSD uses 0x141 for syscalls too */
case 0x141:
if (bsd_type != target_freebsd)
goto badtrap;
case 0x100: case 0x100:
#endif #endif
syscall_nr = env->gregs[1]; syscall_nr = env->gregs[1];
@ -465,7 +533,7 @@ void cpu_loop(CPUSPARCState *env, enum BSDType bsd_type)
ret = do_freebsd_syscall(env, syscall_nr, ret = do_freebsd_syscall(env, syscall_nr,
env->regwptr[0], env->regwptr[1], env->regwptr[0], env->regwptr[1],
env->regwptr[2], env->regwptr[3], env->regwptr[2], env->regwptr[3],
env->regwptr[4], env->regwptr[5]); env->regwptr[4], env->regwptr[5], 0, 0);
else if (bsd_type == target_netbsd) else if (bsd_type == target_netbsd)
ret = do_netbsd_syscall(env, syscall_nr, ret = do_netbsd_syscall(env, syscall_nr,
env->regwptr[0], env->regwptr[1], env->regwptr[0], env->regwptr[1],
@ -482,6 +550,7 @@ void cpu_loop(CPUSPARCState *env, enum BSDType bsd_type)
env->regwptr[4], env->regwptr[5]); env->regwptr[4], env->regwptr[5]);
} }
if ((unsigned int)ret >= (unsigned int)(-515)) { if ((unsigned int)ret >= (unsigned int)(-515)) {
ret = -ret;
#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
env->xcc |= PSR_CARRY; env->xcc |= PSR_CARRY;
#else #else
@ -587,6 +656,9 @@ void cpu_loop(CPUSPARCState *env, enum BSDType bsd_type)
} }
break; break;
default: default:
#ifdef TARGET_SPARC64
badtrap:
#endif
printf ("Unhandled trap: 0x%x\n", trapnr); printf ("Unhandled trap: 0x%x\n", trapnr);
cpu_dump_state(env, stderr, fprintf, 0); cpu_dump_state(env, stderr, fprintf, 0);
exit (1); exit (1);
@ -668,7 +740,7 @@ int main(int argc, char **argv)
int gdbstub_port = 0; int gdbstub_port = 0;
char **target_environ, **wrk; char **target_environ, **wrk;
envlist_t *envlist = NULL; envlist_t *envlist = NULL;
enum BSDType bsd_type = target_openbsd; bsd_type = target_openbsd;
if (argc <= 1) if (argc <= 1)
usage(); usage();
@ -1033,7 +1105,7 @@ int main(int argc, char **argv)
gdbserver_start (gdbstub_port); gdbserver_start (gdbstub_port);
gdb_handlesig(env, 0); gdb_handlesig(env, 0);
} }
cpu_loop(env, bsd_type); cpu_loop(env);
/* never exits */ /* never exits */
return 0; return 0;
} }

View File

@ -18,6 +18,7 @@ enum BSDType {
target_netbsd, target_netbsd,
target_openbsd, target_openbsd,
}; };
extern enum BSDType bsd_type;
#include "syscall_defs.h" #include "syscall_defs.h"
#include "syscall.h" #include "syscall.h"
@ -130,7 +131,8 @@ abi_long do_brk(abi_ulong new_brk);
void syscall_init(void); void syscall_init(void);
abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1, abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg2, abi_long arg3, abi_long arg4,
abi_long arg5, abi_long arg6); abi_long arg5, abi_long arg6, abi_long arg7,
abi_long arg8);
abi_long do_netbsd_syscall(void *cpu_env, int num, abi_long arg1, abi_long do_netbsd_syscall(void *cpu_env, int num, abi_long arg1,
abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg2, abi_long arg3, abi_long arg4,
abi_long arg5, abi_long arg6); abi_long arg5, abi_long arg6);
@ -139,7 +141,7 @@ abi_long do_openbsd_syscall(void *cpu_env, int num, abi_long arg1,
abi_long arg5, abi_long arg6); abi_long arg5, abi_long arg6);
void gemu_log(const char *fmt, ...) __attribute__((format(printf,1,2))); void gemu_log(const char *fmt, ...) __attribute__((format(printf,1,2)));
extern THREAD CPUState *thread_env; extern THREAD CPUState *thread_env;
void cpu_loop(CPUState *env, enum BSDType bsd_type); void cpu_loop(CPUState *env);
char *target_strerror(int err); char *target_strerror(int err);
int get_osversion(void); int get_osversion(void);
void fork_start(void); void fork_start(void);

View File

@ -29,6 +29,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/syscall.h> #include <sys/syscall.h>
#include <sys/sysctl.h>
#include <signal.h> #include <signal.h>
#include <utime.h> #include <utime.h>
@ -40,20 +41,283 @@
static abi_ulong target_brk; static abi_ulong target_brk;
static abi_ulong target_original_brk; static abi_ulong target_original_brk;
#define get_errno(x) (x) static inline abi_long get_errno(abi_long ret)
{
if (ret == -1)
/* XXX need to translate host -> target errnos here */
return -(errno);
else
return ret;
}
#define target_to_host_bitmask(x, tbl) (x) #define target_to_host_bitmask(x, tbl) (x)
static inline int is_error(abi_long ret)
{
return (abi_ulong)ret >= (abi_ulong)(-4096);
}
void target_set_brk(abi_ulong new_brk) void target_set_brk(abi_ulong new_brk)
{ {
target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk); target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
} }
/* do_obreak() must return target errnos. */
static abi_long do_obreak(abi_ulong new_brk)
{
abi_ulong brk_page;
abi_long mapped_addr;
int new_alloc_size;
if (!new_brk)
return 0;
if (new_brk < target_original_brk)
return -TARGET_EINVAL;
brk_page = HOST_PAGE_ALIGN(target_brk);
/* If the new brk is less than this, set it and we're done... */
if (new_brk < brk_page) {
target_brk = new_brk;
return 0;
}
/* We need to allocate more memory after the brk... */
new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1);
mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
PROT_READ|PROT_WRITE,
MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0));
if (!is_error(mapped_addr))
target_brk = new_brk;
else
return mapped_addr;
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
case CTLTYPE_QUAD:
*(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 = qemu_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);
qemu_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.
*/
static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr,
int count, int copy)
{
struct target_iovec *target_vec;
abi_ulong base;
int i;
target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
if (!target_vec)
return -TARGET_EFAULT;
for(i = 0;i < count; i++) {
base = tswapl(target_vec[i].iov_base);
vec[i].iov_len = tswapl(target_vec[i].iov_len);
if (vec[i].iov_len != 0) {
vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy);
/* Don't check lock_user return value. We must call writev even
if a element has invalid base address. */
} else {
/* zero length pointer is ignored */
vec[i].iov_base = NULL;
}
}
unlock_user (target_vec, target_addr, 0);
return 0;
}
static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
int count, int copy)
{
struct target_iovec *target_vec;
abi_ulong base;
int i;
target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
if (!target_vec)
return -TARGET_EFAULT;
for(i = 0;i < count; i++) {
if (target_vec[i].iov_base) {
base = tswapl(target_vec[i].iov_base);
unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
}
}
unlock_user (target_vec, target_addr, 0);
return 0;
}
/* do_syscall() should always have a single exit point at the end so /* do_syscall() should always have a single exit point at the end so
that actions, such as logging of syscall results, can be performed. that actions, such as logging of syscall results, can be performed.
All errnos that do_syscall() returns must be -TARGET_<errcode>. */ All errnos that do_syscall() returns must be -TARGET_<errcode>. */
abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1, abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg2, abi_long arg3, abi_long arg4,
abi_long arg5, abi_long arg6) abi_long arg5, abi_long arg6, abi_long arg7,
abi_long arg8)
{ {
abi_long ret; abi_long ret;
void *p; void *p;
@ -86,6 +350,18 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(write(arg1, p, arg3)); ret = get_errno(write(arg1, p, arg3));
unlock_user(p, arg2, 0); unlock_user(p, arg2, 0);
break; break;
case TARGET_FREEBSD_NR_writev:
{
int count = arg3;
struct iovec *vec;
vec = alloca(count * sizeof(struct iovec));
if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
goto efault;
ret = get_errno(writev(arg1, vec, count));
unlock_iovec(vec, arg2, count, 0);
}
break;
case TARGET_FREEBSD_NR_open: case TARGET_FREEBSD_NR_open:
if (!(p = lock_user_string(arg1))) if (!(p = lock_user_string(arg1)))
goto efault; goto efault;
@ -103,12 +379,23 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
case TARGET_FREEBSD_NR_mprotect: case TARGET_FREEBSD_NR_mprotect:
ret = get_errno(target_mprotect(arg1, arg2, arg3)); ret = get_errno(target_mprotect(arg1, arg2, arg3));
break; break;
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);
break;
#endif
case TARGET_FREEBSD_NR_sysarch:
ret = do_freebsd_sysarch(cpu_env, arg1, arg2);
break;
case TARGET_FREEBSD_NR_syscall: case TARGET_FREEBSD_NR_syscall:
case TARGET_FREEBSD_NR___syscall: case TARGET_FREEBSD_NR___syscall:
ret = do_freebsd_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0); ret = do_freebsd_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,arg7,arg8,0);
break; break;
default: default:
ret = syscall(num, arg1, arg2, arg3, arg4, arg5, arg6); ret = get_errno(syscall(num, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8));
break; break;
} }
fail: fail:

View File

@ -106,3 +106,9 @@
#include "freebsd/syscall_nr.h" #include "freebsd/syscall_nr.h"
#include "netbsd/syscall_nr.h" #include "netbsd/syscall_nr.h"
#include "openbsd/syscall_nr.h" #include "openbsd/syscall_nr.h"
struct target_iovec {
abi_long iov_base; /* Starting address */
abi_long iov_len; /* Number of bytes */
};

View File

@ -90,6 +90,24 @@ struct target_msqid64_ds {
abi_ulong __unused5; abi_ulong __unused5;
}; };
/* FreeBSD sysarch(2) */
#define TARGET_FREEBSD_I386_GET_LDT 0
#define TARGET_FREEBSD_I386_SET_LDT 1
/* I386_IOPL */
#define TARGET_FREEBSD_I386_GET_IOPERM 3
#define TARGET_FREEBSD_I386_SET_IOPERM 4
/* xxxxx */
#define TARGET_FREEBSD_I386_GET_FSBASE 7
#define TARGET_FREEBSD_I386_SET_FSBASE 8
#define TARGET_FREEBSD_I386_GET_GSBASE 9
#define TARGET_FREEBSD_I386_SET_GSBASE 10
#define TARGET_FREEBSD_AMD64_GET_FSBASE 128
#define TARGET_FREEBSD_AMD64_SET_FSBASE 129
#define TARGET_FREEBSD_AMD64_GET_GSBASE 130
#define TARGET_FREEBSD_AMD64_SET_GSBASE 131
#define UNAME_MACHINE "x86_64" #define UNAME_MACHINE "x86_64"
#define TARGET_ARCH_SET_GS 0x1001 #define TARGET_ARCH_SET_GS 0x1001

View File

@ -805,6 +805,20 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
# define TRAP_sig(context) ((context)->uc_mcontext->es.trapno) # define TRAP_sig(context) ((context)->uc_mcontext->es.trapno)
# define ERROR_sig(context) ((context)->uc_mcontext->es.err) # define ERROR_sig(context) ((context)->uc_mcontext->es.err)
# define MASK_sig(context) ((context)->uc_sigmask) # define MASK_sig(context) ((context)->uc_sigmask)
#elif defined (__NetBSD__)
# include <ucontext.h>
# define EIP_sig(context) ((context)->uc_mcontext.__gregs[_REG_EIP])
# define TRAP_sig(context) ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
# define ERROR_sig(context) ((context)->uc_mcontext.__gregs[_REG_ERR])
# define MASK_sig(context) ((context)->uc_sigmask)
#elif defined (__FreeBSD__) || defined(__DragonFly__)
# include <ucontext.h>
# define EIP_sig(context) (*((unsigned long*)&(context)->uc_mcontext.mc_eip))
# define TRAP_sig(context) ((context)->uc_mcontext.mc_trapno)
# define ERROR_sig(context) ((context)->uc_mcontext.mc_err)
# define MASK_sig(context) ((context)->uc_sigmask)
#elif defined(__OpenBSD__) #elif defined(__OpenBSD__)
# define EIP_sig(context) ((context)->sc_eip) # define EIP_sig(context) ((context)->sc_eip)
# define TRAP_sig(context) ((context)->sc_trapno) # define TRAP_sig(context) ((context)->sc_trapno)
@ -821,7 +835,9 @@ int cpu_signal_handler(int host_signum, void *pinfo,
void *puc) void *puc)
{ {
siginfo_t *info = pinfo; siginfo_t *info = pinfo;
#if defined(__OpenBSD__) #if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__)
ucontext_t *uc = puc;
#elif defined(__OpenBSD__)
struct sigcontext *uc = puc; struct sigcontext *uc = puc;
#else #else
struct ucontext *uc = puc; struct ucontext *uc = puc;
@ -855,6 +871,13 @@ int cpu_signal_handler(int host_signum, void *pinfo,
#define TRAP_sig(context) ((context)->sc_trapno) #define TRAP_sig(context) ((context)->sc_trapno)
#define ERROR_sig(context) ((context)->sc_err) #define ERROR_sig(context) ((context)->sc_err)
#define MASK_sig(context) ((context)->sc_mask) #define MASK_sig(context) ((context)->sc_mask)
#elif defined (__FreeBSD__) || defined(__DragonFly__)
#include <ucontext.h>
#define PC_sig(context) (*((unsigned long*)&(context)->uc_mcontext.mc_rip))
#define TRAP_sig(context) ((context)->uc_mcontext.mc_trapno)
#define ERROR_sig(context) ((context)->uc_mcontext.mc_err)
#define MASK_sig(context) ((context)->uc_sigmask)
#else #else
#define PC_sig(context) ((context)->uc_mcontext.gregs[REG_RIP]) #define PC_sig(context) ((context)->uc_mcontext.gregs[REG_RIP])
#define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO]) #define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO])
@ -867,7 +890,7 @@ int cpu_signal_handler(int host_signum, void *pinfo,
{ {
siginfo_t *info = pinfo; siginfo_t *info = pinfo;
unsigned long pc; unsigned long pc;
#ifdef __NetBSD__ #if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__)
ucontext_t *uc = puc; ucontext_t *uc = puc;
#elif defined(__OpenBSD__) #elif defined(__OpenBSD__)
struct sigcontext *uc = puc; struct sigcontext *uc = puc;