Statistics
| Branch: | Revision:

root / bsd-user / syscall.c @ 8167ee88

History | View | Annotate | Download (8 kB)

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, see <http://www.gnu.org/licenses/>.
18
 */
19
#include <stdlib.h>
20
#include <stdio.h>
21
#include <stdint.h>
22
#include <stdarg.h>
23
#include <string.h>
24
#include <errno.h>
25
#include <unistd.h>
26
#include <fcntl.h>
27
#include <time.h>
28
#include <limits.h>
29
#include <sys/types.h>
30
#include <sys/mman.h>
31
#include <sys/syscall.h>
32
#include <signal.h>
33
#include <utime.h>
34

    
35
#include "qemu.h"
36
#include "qemu-common.h"
37

    
38
//#define DEBUG
39

    
40
static abi_ulong target_brk;
41
static abi_ulong target_original_brk;
42

    
43
#define get_errno(x) (x)
44
#define target_to_host_bitmask(x, tbl) (x)
45

    
46
void target_set_brk(abi_ulong new_brk)
47
{
48
    target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
49
}
50

    
51
/* do_syscall() should always have a single exit point at the end so
52
   that actions, such as logging of syscall results, can be performed.
53
   All errnos that do_syscall() returns must be -TARGET_<errcode>. */
54
abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
55
                            abi_long arg2, abi_long arg3, abi_long arg4,
56
                            abi_long arg5, abi_long arg6)
57
{
58
    abi_long ret;
59
    void *p;
60

    
61
#ifdef DEBUG
62
    gemu_log("freebsd syscall %d\n", num);
63
#endif
64
    if(do_strace)
65
        print_freebsd_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
66

    
67
    switch(num) {
68
    case TARGET_FREEBSD_NR_exit:
69
#ifdef HAVE_GPROF
70
        _mcleanup();
71
#endif
72
        gdb_exit(cpu_env, arg1);
73
        /* XXX: should free thread stack and CPU env */
74
        _exit(arg1);
75
        ret = 0; /* avoid warning */
76
        break;
77
    case TARGET_FREEBSD_NR_read:
78
        if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
79
            goto efault;
80
        ret = get_errno(read(arg1, p, arg3));
81
        unlock_user(p, arg2, ret);
82
        break;
83
    case TARGET_FREEBSD_NR_write:
84
        if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
85
            goto efault;
86
        ret = get_errno(write(arg1, p, arg3));
87
        unlock_user(p, arg2, 0);
88
        break;
89
    case TARGET_FREEBSD_NR_open:
90
        if (!(p = lock_user_string(arg1)))
91
            goto efault;
92
        ret = get_errno(open(path(p),
93
                             target_to_host_bitmask(arg2, fcntl_flags_tbl),
94
                             arg3));
95
        unlock_user(p, arg1, 0);
96
        break;
97
    case TARGET_FREEBSD_NR_mmap:
98
        ret = get_errno(target_mmap(arg1, arg2, arg3,
99
                                    target_to_host_bitmask(arg4, mmap_flags_tbl),
100
                                    arg5,
101
                                    arg6));
102
        break;
103
    case TARGET_FREEBSD_NR_mprotect:
104
        ret = get_errno(target_mprotect(arg1, arg2, arg3));
105
        break;
106
    case TARGET_FREEBSD_NR_syscall:
107
    case TARGET_FREEBSD_NR___syscall:
108
        ret = do_freebsd_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
109
        break;
110
    default:
111
        ret = syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
112
        break;
113
    }
114
 fail:
115
#ifdef DEBUG
116
    gemu_log(" = %ld\n", ret);
117
#endif
118
    if (do_strace)
119
        print_freebsd_syscall_ret(num, ret);
120
    return ret;
121
 efault:
122
    ret = -TARGET_EFAULT;
123
    goto fail;
124
}
125

    
126
abi_long do_netbsd_syscall(void *cpu_env, int num, abi_long arg1,
127
                           abi_long arg2, abi_long arg3, abi_long arg4,
128
                           abi_long arg5, abi_long arg6)
129
{
130
    abi_long ret;
131
    void *p;
132

    
133
#ifdef DEBUG
134
    gemu_log("netbsd syscall %d\n", num);
135
#endif
136
    if(do_strace)
137
        print_netbsd_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
138

    
139
    switch(num) {
140
    case TARGET_NETBSD_NR_exit:
141
#ifdef HAVE_GPROF
142
        _mcleanup();
143
#endif
144
        gdb_exit(cpu_env, arg1);
145
        /* XXX: should free thread stack and CPU env */
146
        _exit(arg1);
147
        ret = 0; /* avoid warning */
148
        break;
149
    case TARGET_NETBSD_NR_read:
150
        if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
151
            goto efault;
152
        ret = get_errno(read(arg1, p, arg3));
153
        unlock_user(p, arg2, ret);
154
        break;
155
    case TARGET_NETBSD_NR_write:
156
        if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
157
            goto efault;
158
        ret = get_errno(write(arg1, p, arg3));
159
        unlock_user(p, arg2, 0);
160
        break;
161
    case TARGET_NETBSD_NR_open:
162
        if (!(p = lock_user_string(arg1)))
163
            goto efault;
164
        ret = get_errno(open(path(p),
165
                             target_to_host_bitmask(arg2, fcntl_flags_tbl),
166
                             arg3));
167
        unlock_user(p, arg1, 0);
168
        break;
169
    case TARGET_NETBSD_NR_mmap:
170
        ret = get_errno(target_mmap(arg1, arg2, arg3,
171
                                    target_to_host_bitmask(arg4, mmap_flags_tbl),
172
                                    arg5,
173
                                    arg6));
174
        break;
175
    case TARGET_NETBSD_NR_mprotect:
176
        ret = get_errno(target_mprotect(arg1, arg2, arg3));
177
        break;
178
    case TARGET_NETBSD_NR_syscall:
179
    case TARGET_NETBSD_NR___syscall:
180
        ret = do_netbsd_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
181
        break;
182
    default:
183
        ret = syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
184
        break;
185
    }
186
 fail:
187
#ifdef DEBUG
188
    gemu_log(" = %ld\n", ret);
189
#endif
190
    if (do_strace)
191
        print_netbsd_syscall_ret(num, ret);
192
    return ret;
193
 efault:
194
    ret = -TARGET_EFAULT;
195
    goto fail;
196
}
197

    
198
abi_long do_openbsd_syscall(void *cpu_env, int num, abi_long arg1,
199
                            abi_long arg2, abi_long arg3, abi_long arg4,
200
                            abi_long arg5, abi_long arg6)
201
{
202
    abi_long ret;
203
    void *p;
204

    
205
#ifdef DEBUG
206
    gemu_log("openbsd syscall %d\n", num);
207
#endif
208
    if(do_strace)
209
        print_openbsd_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
210

    
211
    switch(num) {
212
    case TARGET_OPENBSD_NR_exit:
213
#ifdef HAVE_GPROF
214
        _mcleanup();
215
#endif
216
        gdb_exit(cpu_env, arg1);
217
        /* XXX: should free thread stack and CPU env */
218
        _exit(arg1);
219
        ret = 0; /* avoid warning */
220
        break;
221
    case TARGET_OPENBSD_NR_read:
222
        if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
223
            goto efault;
224
        ret = get_errno(read(arg1, p, arg3));
225
        unlock_user(p, arg2, ret);
226
        break;
227
    case TARGET_OPENBSD_NR_write:
228
        if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
229
            goto efault;
230
        ret = get_errno(write(arg1, p, arg3));
231
        unlock_user(p, arg2, 0);
232
        break;
233
    case TARGET_OPENBSD_NR_open:
234
        if (!(p = lock_user_string(arg1)))
235
            goto efault;
236
        ret = get_errno(open(path(p),
237
                             target_to_host_bitmask(arg2, fcntl_flags_tbl),
238
                             arg3));
239
        unlock_user(p, arg1, 0);
240
        break;
241
    case TARGET_OPENBSD_NR_mmap:
242
        ret = get_errno(target_mmap(arg1, arg2, arg3,
243
                                    target_to_host_bitmask(arg4, mmap_flags_tbl),
244
                                    arg5,
245
                                    arg6));
246
        break;
247
    case TARGET_OPENBSD_NR_mprotect:
248
        ret = get_errno(target_mprotect(arg1, arg2, arg3));
249
        break;
250
    case TARGET_OPENBSD_NR_syscall:
251
    case TARGET_OPENBSD_NR___syscall:
252
        ret = do_openbsd_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
253
        break;
254
    default:
255
        ret = syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
256
        break;
257
    }
258
 fail:
259
#ifdef DEBUG
260
    gemu_log(" = %ld\n", ret);
261
#endif
262
    if (do_strace)
263
        print_openbsd_syscall_ret(num, ret);
264
    return ret;
265
 efault:
266
    ret = -TARGET_EFAULT;
267
    goto fail;
268
}
269

    
270
void syscall_init(void)
271
{
272
}