syscall_emul.cc revision 2107
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; 43using namespace TheISA; 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 (int)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)) != NoFault) 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)) != NoFault) 208 return -EFAULT; 209 210 string new_name; 211 212 if (xc->mem->readString(new_name, xc->getSyscallArg(1)) != NoFault) 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)) != NoFault) 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)) != NoFault) 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