qemu/bsd-user/syscall.c
<<
>>
Prefs
   1/*
   2 *  BSD syscalls
   3 *
   4 *  Copyright (c) 2003 - 2008 Fabrice Bellard
   5 *
   6 *  This program is free software; you can redistribute it and/or modify
   7 *  it under the terms of the GNU General Public License as published by
   8 *  the Free Software Foundation; either version 2 of the License, or
   9 *  (at your option) any later version.
  10 *
  11 *  This program is distributed in the hope that it will be useful,
  12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 *  GNU General Public License for more details.
  15 *
  16 *  You should have received a copy of the GNU General Public License
  17 *  along with this program; if not, write to the Free Software
  18 *  Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
  19 *  MA 02110-1301, USA.
  20 */
  21#include <stdlib.h>
  22#include <stdio.h>
  23#include <stdint.h>
  24#include <stdarg.h>
  25#include <string.h>
  26#include <errno.h>
  27#include <unistd.h>
  28#include <fcntl.h>
  29#include <time.h>
  30#include <limits.h>
  31#include <sys/types.h>
  32#include <sys/mman.h>
  33#include <sys/syscall.h>
  34#include <signal.h>
  35#include <utime.h>
  36
  37#include "qemu.h"
  38#include "qemu-common.h"
  39
  40//#define DEBUG
  41
  42static abi_ulong target_brk;
  43static abi_ulong target_original_brk;
  44
  45#define get_errno(x) (x)
  46#define target_to_host_bitmask(x, tbl) (x)
  47
  48void target_set_brk(abi_ulong new_brk)
  49{
  50    target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
  51}
  52
  53/* do_syscall() should always have a single exit point at the end so
  54   that actions, such as logging of syscall results, can be performed.
  55   All errnos that do_syscall() returns must be -TARGET_<errcode>. */
  56abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
  57                            abi_long arg2, abi_long arg3, abi_long arg4,
  58                            abi_long arg5, abi_long arg6)
  59{
  60    abi_long ret;
  61    void *p;
  62
  63#ifdef DEBUG
  64    gemu_log("freebsd syscall %d\n", num);
  65#endif
  66    if(do_strace)
  67        print_freebsd_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
  68
  69    switch(num) {
  70    case TARGET_FREEBSD_NR_exit:
  71#ifdef HAVE_GPROF
  72        _mcleanup();
  73#endif
  74        gdb_exit(cpu_env, arg1);
  75        /* XXX: should free thread stack and CPU env */
  76        _exit(arg1);
  77        ret = 0; /* avoid warning */
  78        break;
  79    case TARGET_FREEBSD_NR_read:
  80        if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
  81            goto efault;
  82        ret = get_errno(read(arg1, p, arg3));
  83        unlock_user(p, arg2, ret);
  84        break;
  85    case TARGET_FREEBSD_NR_write:
  86        if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
  87            goto efault;
  88        ret = get_errno(write(arg1, p, arg3));
  89        unlock_user(p, arg2, 0);
  90        break;
  91    case TARGET_FREEBSD_NR_open:
  92        if (!(p = lock_user_string(arg1)))
  93            goto efault;
  94        ret = get_errno(open(path(p),
  95                             target_to_host_bitmask(arg2, fcntl_flags_tbl),
  96                             arg3));
  97        unlock_user(p, arg1, 0);
  98        break;
  99    case TARGET_FREEBSD_NR_mmap:
 100        ret = get_errno(target_mmap(arg1, arg2, arg3,
 101                                    target_to_host_bitmask(arg4, mmap_flags_tbl),
 102                                    arg5,
 103                                    arg6));
 104        break;
 105    case TARGET_FREEBSD_NR_mprotect:
 106        ret = get_errno(target_mprotect(arg1, arg2, arg3));
 107        break;
 108    case TARGET_FREEBSD_NR_syscall:
 109    case TARGET_FREEBSD_NR___syscall:
 110        ret = do_freebsd_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
 111        break;
 112    default:
 113        ret = syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
 114        break;
 115    }
 116 fail:
 117#ifdef DEBUG
 118    gemu_log(" = %ld\n", ret);
 119#endif
 120    if (do_strace)
 121        print_freebsd_syscall_ret(num, ret);
 122    return ret;
 123 efault:
 124    ret = -TARGET_EFAULT;
 125    goto fail;
 126}
 127
 128abi_long do_netbsd_syscall(void *cpu_env, int num, abi_long arg1,
 129                           abi_long arg2, abi_long arg3, abi_long arg4,
 130                           abi_long arg5, abi_long arg6)
 131{
 132    abi_long ret;
 133    void *p;
 134
 135#ifdef DEBUG
 136    gemu_log("netbsd syscall %d\n", num);
 137#endif
 138    if(do_strace)
 139        print_netbsd_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
 140
 141    switch(num) {
 142    case TARGET_NETBSD_NR_exit:
 143#ifdef HAVE_GPROF
 144        _mcleanup();
 145#endif
 146        gdb_exit(cpu_env, arg1);
 147        /* XXX: should free thread stack and CPU env */
 148        _exit(arg1);
 149        ret = 0; /* avoid warning */
 150        break;
 151    case TARGET_NETBSD_NR_read:
 152        if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
 153            goto efault;
 154        ret = get_errno(read(arg1, p, arg3));
 155        unlock_user(p, arg2, ret);
 156        break;
 157    case TARGET_NETBSD_NR_write:
 158        if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
 159            goto efault;
 160        ret = get_errno(write(arg1, p, arg3));
 161        unlock_user(p, arg2, 0);
 162        break;
 163    case TARGET_NETBSD_NR_open:
 164        if (!(p = lock_user_string(arg1)))
 165            goto efault;
 166        ret = get_errno(open(path(p),
 167                             target_to_host_bitmask(arg2, fcntl_flags_tbl),
 168                             arg3));
 169        unlock_user(p, arg1, 0);
 170        break;
 171    case TARGET_NETBSD_NR_mmap:
 172        ret = get_errno(target_mmap(arg1, arg2, arg3,
 173                                    target_to_host_bitmask(arg4, mmap_flags_tbl),
 174                                    arg5,
 175                                    arg6));
 176        break;
 177    case TARGET_NETBSD_NR_mprotect:
 178        ret = get_errno(target_mprotect(arg1, arg2, arg3));
 179        break;
 180    case TARGET_NETBSD_NR_syscall:
 181    case TARGET_NETBSD_NR___syscall:
 182        ret = do_netbsd_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
 183        break;
 184    default:
 185        ret = syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
 186        break;
 187    }
 188 fail:
 189#ifdef DEBUG
 190    gemu_log(" = %ld\n", ret);
 191#endif
 192    if (do_strace)
 193        print_netbsd_syscall_ret(num, ret);
 194    return ret;
 195 efault:
 196    ret = -TARGET_EFAULT;
 197    goto fail;
 198}
 199
 200abi_long do_openbsd_syscall(void *cpu_env, int num, abi_long arg1,
 201                            abi_long arg2, abi_long arg3, abi_long arg4,
 202                            abi_long arg5, abi_long arg6)
 203{
 204    abi_long ret;
 205    void *p;
 206
 207#ifdef DEBUG
 208    gemu_log("openbsd syscall %d\n", num);
 209#endif
 210    if(do_strace)
 211        print_openbsd_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
 212
 213    switch(num) {
 214    case TARGET_OPENBSD_NR_exit:
 215#ifdef HAVE_GPROF
 216        _mcleanup();
 217#endif
 218        gdb_exit(cpu_env, arg1);
 219        /* XXX: should free thread stack and CPU env */
 220        _exit(arg1);
 221        ret = 0; /* avoid warning */
 222        break;
 223    case TARGET_OPENBSD_NR_read:
 224        if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
 225            goto efault;
 226        ret = get_errno(read(arg1, p, arg3));
 227        unlock_user(p, arg2, ret);
 228        break;
 229    case TARGET_OPENBSD_NR_write:
 230        if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
 231            goto efault;
 232        ret = get_errno(write(arg1, p, arg3));
 233        unlock_user(p, arg2, 0);
 234        break;
 235    case TARGET_OPENBSD_NR_open:
 236        if (!(p = lock_user_string(arg1)))
 237            goto efault;
 238        ret = get_errno(open(path(p),
 239                             target_to_host_bitmask(arg2, fcntl_flags_tbl),
 240                             arg3));
 241        unlock_user(p, arg1, 0);
 242        break;
 243    case TARGET_OPENBSD_NR_mmap:
 244        ret = get_errno(target_mmap(arg1, arg2, arg3,
 245                                    target_to_host_bitmask(arg4, mmap_flags_tbl),
 246                                    arg5,
 247                                    arg6));
 248        break;
 249    case TARGET_OPENBSD_NR_mprotect:
 250        ret = get_errno(target_mprotect(arg1, arg2, arg3));
 251        break;
 252    case TARGET_OPENBSD_NR_syscall:
 253    case TARGET_OPENBSD_NR___syscall:
 254        ret = do_openbsd_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
 255        break;
 256    default:
 257        ret = syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
 258        break;
 259    }
 260 fail:
 261#ifdef DEBUG
 262    gemu_log(" = %ld\n", ret);
 263#endif
 264    if (do_strace)
 265        print_openbsd_syscall_ret(num, ret);
 266    return ret;
 267 efault:
 268    ret = -TARGET_EFAULT;
 269    goto fail;
 270}
 271
 272void syscall_init(void)
 273{
 274}
 275