diff options
Diffstat (limited to 'bsd-user/syscall.c')
-rw-r--r-- | bsd-user/syscall.c | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c new file mode 100644 index 000000000..45fb5e4c7 --- /dev/null +++ b/bsd-user/syscall.c @@ -0,0 +1,273 @@ +/* + * BSD syscalls + * + * Copyright (c) 2003 - 2008 Fabrice Bellard + * + * 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <stdlib.h> +#include <stdio.h> +#include <stdint.h> +#include <stdarg.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <fcntl.h> +#include <time.h> +#include <limits.h> +#include <sys/types.h> +#include <sys/mman.h> +#include <sys/syscall.h> +#include <signal.h> +#include <utime.h> + +#include "qemu.h" +#include "qemu-common.h" + +//#define DEBUG + +static abi_ulong target_brk; +static abi_ulong target_original_brk; + +#define get_errno(x) (x) +#define target_to_host_bitmask(x, tbl) (x) + +void target_set_brk(abi_ulong new_brk) +{ + target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk); +} + +/* do_syscall() should always have a single exit point at the end so + that actions, such as logging of syscall results, can be performed. + 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 arg2, abi_long arg3, abi_long arg4, + abi_long arg5, abi_long arg6) +{ + abi_long ret; + void *p; + +#ifdef DEBUG + gemu_log("freebsd syscall %d\n", num); +#endif + if(do_strace) + print_freebsd_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6); + + switch(num) { + case TARGET_FREEBSD_NR_exit: +#ifdef HAVE_GPROF + _mcleanup(); +#endif + gdb_exit(cpu_env, arg1); + /* XXX: should free thread stack and CPU env */ + _exit(arg1); + ret = 0; /* avoid warning */ + break; + case TARGET_FREEBSD_NR_read: + if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0))) + goto efault; + ret = get_errno(read(arg1, p, arg3)); + unlock_user(p, arg2, ret); + break; + case TARGET_FREEBSD_NR_write: + if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1))) + goto efault; + ret = get_errno(write(arg1, p, arg3)); + unlock_user(p, arg2, 0); + break; + case TARGET_FREEBSD_NR_open: + if (!(p = lock_user_string(arg1))) + goto efault; + ret = get_errno(open(path(p), + target_to_host_bitmask(arg2, fcntl_flags_tbl), + arg3)); + unlock_user(p, arg1, 0); + break; + case TARGET_FREEBSD_NR_mmap: + ret = get_errno(target_mmap(arg1, arg2, arg3, + target_to_host_bitmask(arg4, mmap_flags_tbl), + arg5, + arg6)); + break; + case TARGET_FREEBSD_NR_mprotect: + ret = get_errno(target_mprotect(arg1, arg2, arg3)); + break; + case TARGET_FREEBSD_NR_syscall: + case TARGET_FREEBSD_NR___syscall: + ret = do_freebsd_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0); + break; + default: + ret = syscall(num, arg1, arg2, arg3, arg4, arg5, arg6); + break; + } + fail: +#ifdef DEBUG + gemu_log(" = %ld\n", ret); +#endif + if (do_strace) + print_freebsd_syscall_ret(num, ret); + return ret; + efault: + ret = -TARGET_EFAULT; + goto fail; +} + +abi_long do_netbsd_syscall(void *cpu_env, int num, abi_long arg1, + abi_long arg2, abi_long arg3, abi_long arg4, + abi_long arg5, abi_long arg6) +{ + abi_long ret; + void *p; + +#ifdef DEBUG + gemu_log("netbsd syscall %d\n", num); +#endif + if(do_strace) + print_netbsd_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6); + + switch(num) { + case TARGET_NETBSD_NR_exit: +#ifdef HAVE_GPROF + _mcleanup(); +#endif + gdb_exit(cpu_env, arg1); + /* XXX: should free thread stack and CPU env */ + _exit(arg1); + ret = 0; /* avoid warning */ + break; + case TARGET_NETBSD_NR_read: + if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0))) + goto efault; + ret = get_errno(read(arg1, p, arg3)); + unlock_user(p, arg2, ret); + break; + case TARGET_NETBSD_NR_write: + if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1))) + goto efault; + ret = get_errno(write(arg1, p, arg3)); + unlock_user(p, arg2, 0); + break; + case TARGET_NETBSD_NR_open: + if (!(p = lock_user_string(arg1))) + goto efault; + ret = get_errno(open(path(p), + target_to_host_bitmask(arg2, fcntl_flags_tbl), + arg3)); + unlock_user(p, arg1, 0); + break; + case TARGET_NETBSD_NR_mmap: + ret = get_errno(target_mmap(arg1, arg2, arg3, + target_to_host_bitmask(arg4, mmap_flags_tbl), + arg5, + arg6)); + break; + 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); + break; + default: + ret = syscall(num, arg1, arg2, arg3, arg4, arg5, arg6); + break; + } + fail: +#ifdef DEBUG + gemu_log(" = %ld\n", ret); +#endif + if (do_strace) + print_netbsd_syscall_ret(num, ret); + return ret; + efault: + ret = -TARGET_EFAULT; + goto fail; +} + +abi_long do_openbsd_syscall(void *cpu_env, int num, abi_long arg1, + abi_long arg2, abi_long arg3, abi_long arg4, + abi_long arg5, abi_long arg6) +{ + abi_long ret; + void *p; + +#ifdef DEBUG + gemu_log("openbsd syscall %d\n", num); +#endif + if(do_strace) + print_openbsd_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6); + + switch(num) { + case TARGET_OPENBSD_NR_exit: +#ifdef HAVE_GPROF + _mcleanup(); +#endif + gdb_exit(cpu_env, arg1); + /* XXX: should free thread stack and CPU env */ + _exit(arg1); + ret = 0; /* avoid warning */ + break; + case TARGET_OPENBSD_NR_read: + if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0))) + goto efault; + ret = get_errno(read(arg1, p, arg3)); + unlock_user(p, arg2, ret); + break; + case TARGET_OPENBSD_NR_write: + if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1))) + goto efault; + ret = get_errno(write(arg1, p, arg3)); + unlock_user(p, arg2, 0); + break; + case TARGET_OPENBSD_NR_open: + if (!(p = lock_user_string(arg1))) + goto efault; + ret = get_errno(open(path(p), + target_to_host_bitmask(arg2, fcntl_flags_tbl), + arg3)); + unlock_user(p, arg1, 0); + break; + case TARGET_OPENBSD_NR_mmap: + ret = get_errno(target_mmap(arg1, arg2, arg3, + target_to_host_bitmask(arg4, mmap_flags_tbl), + arg5, + arg6)); + break; + 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); + break; + default: + ret = syscall(num, arg1, arg2, arg3, arg4, arg5, arg6); + break; + } + fail: +#ifdef DEBUG + gemu_log(" = %ld\n", ret); +#endif + if (do_strace) + print_openbsd_syscall_ret(num, ret); + return ret; + efault: + ret = -TARGET_EFAULT; + goto fail; +} + +void syscall_init(void) +{ +} |