syscall_emul.cc revision 1999
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 <unistd.h>
30
31#include <string>
32#include <iostream>
33
34#include "sim/syscall_emul.hh"
35#include "base/trace.hh"
36#include "cpu/exec_context.hh"
37#include "cpu/base.hh"
38#include "sim/process.hh"
39
40#include "sim/sim_events.hh"
41
42using namespace std;
43
44void
45SyscallDesc::doSyscall(int callnum, Process *process, ExecContext *xc)
46{
47    DPRINTFR(SyscallVerbose, "%s: syscall %s called\n",
48             xc->cpu->name(), name);
49
50    SyscallReturn retval = (*funcPtr)(this, callnum, process, xc);
51
52    DPRINTFR(SyscallVerbose, "%s: syscall %s returns %d\n",
53             xc->cpu->name(), name, retval.value());
54
55    if (!(flags & SyscallDesc::SuppressReturnValue))
56        xc->setSyscallReturn(retval);
57}
58
59
60SyscallReturn
61unimplementedFunc(SyscallDesc *desc, int callnum, Process *process,
62                  ExecContext *xc)
63{
64    fatal("syscall %s (#%d) unimplemented.", desc->name, callnum);
65}
66
67
68SyscallReturn
69ignoreFunc(SyscallDesc *desc, int callnum, Process *process,
70           ExecContext *xc)
71{
72    warn("ignoring syscall %s(%d, %d, ...)", desc->name,
73         xc->getSyscallArg(0), xc->getSyscallArg(1));
74
75    return 0;
76}
77
78
79SyscallReturn
80exitFunc(SyscallDesc *desc, int callnum, Process *process,
81         ExecContext *xc)
82{
83    new SimExitEvent("syscall caused exit", xc->getSyscallArg(0) & 0xff);
84
85    return 1;
86}
87
88
89SyscallReturn
90getpagesizeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
91{
92    return VMPageSize;
93}
94
95
96SyscallReturn
97obreakFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
98{
99    // change brk addr to first arg
100    Addr new_brk = xc->getSyscallArg(0);
101    if (new_brk != 0)
102    {
103        p->brk_point = xc->getSyscallArg(0);
104    }
105    DPRINTF(SyscallVerbose, "Break Point changed to: %#X\n", p->brk_point);
106    return p->brk_point;
107}
108
109
110SyscallReturn
111closeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
112{
113    int target_fd = xc->getSyscallArg(0);
114    int status = close(p->sim_fd(target_fd));
115    if (status >= 0)
116        p->free_fd(target_fd);
117    return status;
118}
119
120
121SyscallReturn
122readFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
123{
124    int fd = p->sim_fd(xc->getSyscallArg(0));
125    int nbytes = xc->getSyscallArg(2);
126    BufferArg bufArg(xc->getSyscallArg(1), nbytes);
127
128    int bytes_read = read(fd, bufArg.bufferPtr(), nbytes);
129
130    if (bytes_read != -1)
131        bufArg.copyOut(xc->mem);
132
133    return bytes_read;
134}
135
136SyscallReturn
137writeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
138{
139    int fd = p->sim_fd(xc->getSyscallArg(0));
140    int nbytes = xc->getSyscallArg(2);
141    BufferArg bufArg(xc->getSyscallArg(1), nbytes);
142
143    bufArg.copyIn(xc->mem);
144
145    int bytes_written = write(fd, bufArg.bufferPtr(), nbytes);
146
147    fsync(fd);
148
149    return bytes_written;
150}
151
152
153SyscallReturn
154lseekFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
155{
156    int fd = p->sim_fd(xc->getSyscallArg(0));
157    uint64_t offs = xc->getSyscallArg(1);
158    int whence = xc->getSyscallArg(2);
159
160    off_t result = lseek(fd, offs, whence);
161
162    return (result == (off_t)-1) ? -errno : result;
163}
164
165
166SyscallReturn
167munmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
168{
169    // given that we don't really implement mmap, munmap is really easy
170    return 0;
171}
172
173
174const char *hostname = "m5.eecs.umich.edu";
175
176SyscallReturn
177gethostnameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
178{
179    int name_len = xc->getSyscallArg(1);
180    BufferArg name(xc->getSyscallArg(0), name_len);
181
182    strncpy((char *)name.bufferPtr(), hostname, name_len);
183
184    name.copyOut(xc->mem);
185
186    return 0;
187}
188
189SyscallReturn
190unlinkFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
191{
192    string path;
193
194    if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
195        return (TheISA::IntReg)-EFAULT;
196
197    int result = unlink(path.c_str());
198    return (result == -1) ? -errno : result;
199}
200
201SyscallReturn
202renameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
203{
204    string old_name;
205
206    if (xc->mem->readString(old_name, xc->getSyscallArg(0)) != No_Fault)
207        return -EFAULT;
208
209    string new_name;
210
211    if (xc->mem->readString(new_name, xc->getSyscallArg(1)) != No_Fault)
212        return -EFAULT;
213
214    int64_t result = rename(old_name.c_str(), new_name.c_str());
215    return (result == -1) ? -errno : result;
216}
217
218SyscallReturn
219truncateFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
220{
221    string path;
222
223    if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
224        return -EFAULT;
225
226    off_t length = xc->getSyscallArg(1);
227
228    int result = truncate(path.c_str(), length);
229    return (result == -1) ? -errno : result;
230}
231
232SyscallReturn
233ftruncateFunc(SyscallDesc *desc, int num, Process *process, ExecContext *xc)
234{
235    int fd = process->sim_fd(xc->getSyscallArg(0));
236
237    if (fd < 0)
238        return -EBADF;
239
240    off_t length = xc->getSyscallArg(1);
241
242    int result = ftruncate(fd, length);
243    return (result == -1) ? -errno : result;
244}
245
246SyscallReturn
247chownFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
248{
249    string path;
250
251    if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
252        return -EFAULT;
253
254    /* XXX endianess */
255    uint32_t owner = xc->getSyscallArg(1);
256    uid_t hostOwner = owner;
257    uint32_t group = xc->getSyscallArg(2);
258    gid_t hostGroup = group;
259
260    int result = chown(path.c_str(), hostOwner, hostGroup);
261    return (result == -1) ? -errno : result;
262}
263
264SyscallReturn
265fchownFunc(SyscallDesc *desc, int num, Process *process, ExecContext *xc)
266{
267    int fd = process->sim_fd(xc->getSyscallArg(0));
268
269    if (fd < 0)
270        return -EBADF;
271
272    /* XXX endianess */
273    uint32_t owner = xc->getSyscallArg(1);
274    uid_t hostOwner = owner;
275    uint32_t group = xc->getSyscallArg(2);
276    gid_t hostGroup = group;
277
278    int result = fchown(fd, hostOwner, hostGroup);
279    return (result == -1) ? -errno : result;
280}
281