syscall_emul.cc revision 2093
1/*
2 * Copyright (c) 2003-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <fcntl.h>
30#include <unistd.h>
31
32#include <string>
33#include <iostream>
34
35#include "sim/syscall_emul.hh"
36#include "base/trace.hh"
37#include "cpu/exec_context.hh"
38#include "cpu/base.hh"
39#include "sim/process.hh"
40
41#include "sim/sim_events.hh"
42
43using namespace std;
44
45void
46SyscallDesc::doSyscall(int callnum, Process *process, ExecContext *xc)
47{
48    DPRINTFR(SyscallVerbose, "%s: syscall %s called\n",
49             xc->cpu->name(), name);
50
51    SyscallReturn retval = (*funcPtr)(this, callnum, process, xc);
52
53    DPRINTFR(SyscallVerbose, "%s: syscall %s returns %d\n",
54             xc->cpu->name(), name, retval.value());
55
56    if (!(flags & SyscallDesc::SuppressReturnValue))
57        xc->setSyscallReturn(retval);
58}
59
60
61SyscallReturn
62unimplementedFunc(SyscallDesc *desc, int callnum, Process *process,
63                  ExecContext *xc)
64{
65    fatal("syscall %s (#%d) unimplemented.", desc->name, callnum);
66}
67
68
69SyscallReturn
70ignoreFunc(SyscallDesc *desc, int callnum, Process *process,
71           ExecContext *xc)
72{
73    warn("ignoring syscall %s(%d, %d, ...)", desc->name,
74         xc->getSyscallArg(0), xc->getSyscallArg(1));
75
76    return 0;
77}
78
79
80SyscallReturn
81exitFunc(SyscallDesc *desc, int callnum, Process *process,
82         ExecContext *xc)
83{
84    new SimExitEvent("syscall caused exit", xc->getSyscallArg(0) & 0xff);
85
86    return 1;
87}
88
89
90SyscallReturn
91getpagesizeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
92{
93    return VMPageSize;
94}
95
96
97SyscallReturn
98obreakFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
99{
100    // change brk addr to first arg
101    Addr new_brk = xc->getSyscallArg(0);
102    if (new_brk != 0)
103    {
104        p->brk_point = xc->getSyscallArg(0);
105    }
106    DPRINTF(SyscallVerbose, "Break Point changed to: %#X\n", p->brk_point);
107    return p->brk_point;
108}
109
110
111SyscallReturn
112closeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
113{
114    int target_fd = xc->getSyscallArg(0);
115    int status = close(p->sim_fd(target_fd));
116    if (status >= 0)
117        p->free_fd(target_fd);
118    return status;
119}
120
121
122SyscallReturn
123readFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
124{
125    int fd = p->sim_fd(xc->getSyscallArg(0));
126    int nbytes = xc->getSyscallArg(2);
127    BufferArg bufArg(xc->getSyscallArg(1), nbytes);
128
129    int bytes_read = read(fd, bufArg.bufferPtr(), nbytes);
130
131    if (bytes_read != -1)
132        bufArg.copyOut(xc->mem);
133
134    return bytes_read;
135}
136
137SyscallReturn
138writeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
139{
140    int fd = p->sim_fd(xc->getSyscallArg(0));
141    int nbytes = xc->getSyscallArg(2);
142    BufferArg bufArg(xc->getSyscallArg(1), nbytes);
143
144    bufArg.copyIn(xc->mem);
145
146    int bytes_written = write(fd, bufArg.bufferPtr(), nbytes);
147
148    fsync(fd);
149
150    return bytes_written;
151}
152
153
154SyscallReturn
155lseekFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
156{
157    int fd = p->sim_fd(xc->getSyscallArg(0));
158    uint64_t offs = xc->getSyscallArg(1);
159    int whence = xc->getSyscallArg(2);
160
161    off_t result = lseek(fd, offs, whence);
162
163    return (result == (off_t)-1) ? -errno : result;
164}
165
166
167SyscallReturn
168munmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
169{
170    // given that we don't really implement mmap, munmap is really easy
171    return 0;
172}
173
174
175const char *hostname = "m5.eecs.umich.edu";
176
177SyscallReturn
178gethostnameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
179{
180    int name_len = xc->getSyscallArg(1);
181    BufferArg name(xc->getSyscallArg(0), name_len);
182
183    strncpy((char *)name.bufferPtr(), hostname, name_len);
184
185    name.copyOut(xc->mem);
186
187    return 0;
188}
189
190SyscallReturn
191unlinkFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
192{
193    string path;
194
195    if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
196        return (TheISA::IntReg)-EFAULT;
197
198    int result = unlink(path.c_str());
199    return (result == -1) ? -errno : result;
200}
201
202SyscallReturn
203renameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
204{
205    string old_name;
206
207    if (xc->mem->readString(old_name, xc->getSyscallArg(0)) != No_Fault)
208        return -EFAULT;
209
210    string new_name;
211
212    if (xc->mem->readString(new_name, xc->getSyscallArg(1)) != No_Fault)
213        return -EFAULT;
214
215    int64_t result = rename(old_name.c_str(), new_name.c_str());
216    return (result == -1) ? -errno : result;
217}
218
219SyscallReturn
220truncateFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
221{
222    string path;
223
224    if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
225        return -EFAULT;
226
227    off_t length = xc->getSyscallArg(1);
228
229    int result = truncate(path.c_str(), length);
230    return (result == -1) ? -errno : result;
231}
232
233SyscallReturn
234ftruncateFunc(SyscallDesc *desc, int num, Process *process, ExecContext *xc)
235{
236    int fd = process->sim_fd(xc->getSyscallArg(0));
237
238    if (fd < 0)
239        return -EBADF;
240
241    off_t length = xc->getSyscallArg(1);
242
243    int result = ftruncate(fd, length);
244    return (result == -1) ? -errno : result;
245}
246
247SyscallReturn
248chownFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
249{
250    string path;
251
252    if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
253        return -EFAULT;
254
255    /* XXX endianess */
256    uint32_t owner = xc->getSyscallArg(1);
257    uid_t hostOwner = owner;
258    uint32_t group = xc->getSyscallArg(2);
259    gid_t hostGroup = group;
260
261    int result = chown(path.c_str(), hostOwner, hostGroup);
262    return (result == -1) ? -errno : result;
263}
264
265SyscallReturn
266fchownFunc(SyscallDesc *desc, int num, Process *process, ExecContext *xc)
267{
268    int fd = process->sim_fd(xc->getSyscallArg(0));
269
270    if (fd < 0)
271        return -EBADF;
272
273    /* XXX endianess */
274    uint32_t owner = xc->getSyscallArg(1);
275    uid_t hostOwner = owner;
276    uint32_t group = xc->getSyscallArg(2);
277    gid_t hostGroup = group;
278
279    int result = fchown(fd, hostOwner, hostGroup);
280    return (result == -1) ? -errno : result;
281}
282
283
284SyscallReturn
285fcntlFunc(SyscallDesc *desc, int num, Process *process,
286          ExecContext *xc)
287{
288    int fd = xc->getSyscallArg(0);
289
290    if (fd < 0 || process->sim_fd(fd) < 0)
291        return -EBADF;
292
293    int cmd = xc->getSyscallArg(1);
294    switch (cmd) {
295      case 0: // F_DUPFD
296        // if we really wanted to support this, we'd need to do it
297        // in the target fd space.
298        warn("fcntl(%d, F_DUPFD) not supported, error returned\n", fd);
299        return -EMFILE;
300
301      case 1: // F_GETFD (get close-on-exec flag)
302      case 2: // F_SETFD (set close-on-exec flag)
303        return 0;
304
305      case 3: // F_GETFL (get file flags)
306      case 4: // F_SETFL (set file flags)
307        // not sure if this is totally valid, but we'll pass it through
308        // to the underlying OS
309        warn("fcntl(%d, %d) passed through to host\n", fd, cmd);
310        return fcntl(process->sim_fd(fd), cmd);
311        // return 0;
312
313      case 7: // F_GETLK  (get lock)
314      case 8: // F_SETLK  (set lock)
315      case 9: // F_SETLKW (set lock and wait)
316        // don't mess with file locking... just act like it's OK
317        warn("File lock call (fcntl(%d, %d)) ignored.\n", fd, cmd);
318        return 0;
319
320      default:
321        warn("Unknown fcntl command %d\n", cmd);
322        return 0;
323    }
324}
325
326
327