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 * Authors: Steve Reinhardt 29 * Kevin Lim 30 */ 31 32#ifndef __SIM_SYSCALL_EMUL_HH__ 33#define __SIM_SYSCALL_EMUL_HH__ 34 35#define NO_STAT64 (defined(__APPLE__) || defined(__OpenBSD__) || \ 36 defined(__FreeBSD__) || defined(__CYGWIN__)) 37 38/// 39/// @file syscall_emul.hh 40/// 41/// This file defines objects used to emulate syscalls from the target 42/// application on the host machine. 43 44#ifdef __CYGWIN32__ 45#include <sys/fcntl.h> // for O_BINARY 46#endif 47#include <sys/stat.h> 48#include <sys/time.h> 49#include <sys/uio.h> 50#include <fcntl.h> 51 52#include <cerrno> 53#include <string> 54 55#include "base/chunk_generator.hh" 56#include "base/intmath.hh" // for RoundUp 57#include "base/misc.hh" 58#include "base/trace.hh" 59#include "base/types.hh" 60#include "config/the_isa.hh" 61#include "cpu/base.hh" 62#include "cpu/thread_context.hh" 63#include "debug/SyscallVerbose.hh" 64#include "mem/page_table.hh"
| 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 * Authors: Steve Reinhardt 29 * Kevin Lim 30 */ 31 32#ifndef __SIM_SYSCALL_EMUL_HH__ 33#define __SIM_SYSCALL_EMUL_HH__ 34 35#define NO_STAT64 (defined(__APPLE__) || defined(__OpenBSD__) || \ 36 defined(__FreeBSD__) || defined(__CYGWIN__)) 37 38/// 39/// @file syscall_emul.hh 40/// 41/// This file defines objects used to emulate syscalls from the target 42/// application on the host machine. 43 44#ifdef __CYGWIN32__ 45#include <sys/fcntl.h> // for O_BINARY 46#endif 47#include <sys/stat.h> 48#include <sys/time.h> 49#include <sys/uio.h> 50#include <fcntl.h> 51 52#include <cerrno> 53#include <string> 54 55#include "base/chunk_generator.hh" 56#include "base/intmath.hh" // for RoundUp 57#include "base/misc.hh" 58#include "base/trace.hh" 59#include "base/types.hh" 60#include "config/the_isa.hh" 61#include "cpu/base.hh" 62#include "cpu/thread_context.hh" 63#include "debug/SyscallVerbose.hh" 64#include "mem/page_table.hh"
|
65#include "mem/se_translating_port_proxy.hh"
| 65#include "mem/translating_port.hh"
|
66#include "sim/byteswap.hh" 67#include "sim/process.hh"
| 66#include "sim/byteswap.hh" 67#include "sim/process.hh"
|
| 68#include "sim/syscallreturn.hh"
|
68#include "sim/system.hh" 69 70/// 71/// System call descriptor. 72/// 73class SyscallDesc { 74 75 public: 76 77 /// Typedef for target syscall handler functions. 78 typedef SyscallReturn (*FuncPtr)(SyscallDesc *, int num, 79 LiveProcess *, ThreadContext *); 80 81 const char *name; //!< Syscall name (e.g., "open"). 82 FuncPtr funcPtr; //!< Pointer to emulation function. 83 int flags; //!< Flags (see Flags enum). 84 85 /// Flag values for controlling syscall behavior. 86 enum Flags { 87 /// Don't set return regs according to funcPtr return value. 88 /// Used for syscalls with non-standard return conventions 89 /// that explicitly set the ThreadContext regs (e.g., 90 /// sigreturn). 91 SuppressReturnValue = 1 92 }; 93 94 /// Constructor. 95 SyscallDesc(const char *_name, FuncPtr _funcPtr, int _flags = 0) 96 : name(_name), funcPtr(_funcPtr), flags(_flags) 97 { 98 } 99 100 /// Emulate the syscall. Public interface for calling through funcPtr. 101 void doSyscall(int callnum, LiveProcess *proc, ThreadContext *tc); 102}; 103 104 105class BaseBufferArg { 106 107 public: 108 109 BaseBufferArg(Addr _addr, int _size) : addr(_addr), size(_size) 110 { 111 bufPtr = new uint8_t[size]; 112 // clear out buffer: in case we only partially populate this, 113 // and then do a copyOut(), we want to make sure we don't 114 // introduce any random junk into the simulated address space 115 memset(bufPtr, 0, size); 116 } 117 118 virtual ~BaseBufferArg() { delete [] bufPtr; } 119 120 // 121 // copy data into simulator space (read from target memory) 122 //
| 69#include "sim/system.hh" 70 71/// 72/// System call descriptor. 73/// 74class SyscallDesc { 75 76 public: 77 78 /// Typedef for target syscall handler functions. 79 typedef SyscallReturn (*FuncPtr)(SyscallDesc *, int num, 80 LiveProcess *, ThreadContext *); 81 82 const char *name; //!< Syscall name (e.g., "open"). 83 FuncPtr funcPtr; //!< Pointer to emulation function. 84 int flags; //!< Flags (see Flags enum). 85 86 /// Flag values for controlling syscall behavior. 87 enum Flags { 88 /// Don't set return regs according to funcPtr return value. 89 /// Used for syscalls with non-standard return conventions 90 /// that explicitly set the ThreadContext regs (e.g., 91 /// sigreturn). 92 SuppressReturnValue = 1 93 }; 94 95 /// Constructor. 96 SyscallDesc(const char *_name, FuncPtr _funcPtr, int _flags = 0) 97 : name(_name), funcPtr(_funcPtr), flags(_flags) 98 { 99 } 100 101 /// Emulate the syscall. Public interface for calling through funcPtr. 102 void doSyscall(int callnum, LiveProcess *proc, ThreadContext *tc); 103}; 104 105 106class BaseBufferArg { 107 108 public: 109 110 BaseBufferArg(Addr _addr, int _size) : addr(_addr), size(_size) 111 { 112 bufPtr = new uint8_t[size]; 113 // clear out buffer: in case we only partially populate this, 114 // and then do a copyOut(), we want to make sure we don't 115 // introduce any random junk into the simulated address space 116 memset(bufPtr, 0, size); 117 } 118 119 virtual ~BaseBufferArg() { delete [] bufPtr; } 120 121 // 122 // copy data into simulator space (read from target memory) 123 //
|
123 virtual bool copyIn(SETranslatingPortProxy* memproxy)
| 124 virtual bool copyIn(TranslatingPort *memport)
|
124 {
| 125 {
|
125 memproxy->readBlob(addr, bufPtr, size);
| 126 memport->readBlob(addr, bufPtr, size);
|
126 return true; // no EFAULT detection for now 127 } 128 129 // 130 // copy data out of simulator space (write to target memory) 131 //
| 127 return true; // no EFAULT detection for now 128 } 129 130 // 131 // copy data out of simulator space (write to target memory) 132 //
|
132 virtual bool copyOut(SETranslatingPortProxy* memproxy)
| 133 virtual bool copyOut(TranslatingPort *memport)
|
133 {
| 134 {
|
134 memproxy->writeBlob(addr, bufPtr, size);
| 135 memport->writeBlob(addr, bufPtr, size);
|
135 return true; // no EFAULT detection for now 136 } 137 138 protected: 139 Addr addr; 140 int size; 141 uint8_t *bufPtr; 142}; 143 144 145class BufferArg : public BaseBufferArg 146{ 147 public: 148 BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { } 149 void *bufferPtr() { return bufPtr; } 150}; 151 152template <class T> 153class TypedBufferArg : public BaseBufferArg 154{ 155 public: 156 // user can optionally specify a specific number of bytes to 157 // allocate to deal with those structs that have variable-size 158 // arrays at the end 159 TypedBufferArg(Addr _addr, int _size = sizeof(T)) 160 : BaseBufferArg(_addr, _size) 161 { } 162 163 // type case 164 operator T*() { return (T *)bufPtr; } 165 166 // dereference operators 167 T &operator*() { return *((T *)bufPtr); } 168 T* operator->() { return (T *)bufPtr; } 169 T &operator[](int i) { return ((T *)bufPtr)[i]; } 170}; 171 172////////////////////////////////////////////////////////////////////// 173// 174// The following emulation functions are generic enough that they 175// don't need to be recompiled for different emulated OS's. They are 176// defined in sim/syscall_emul.cc. 177// 178////////////////////////////////////////////////////////////////////// 179 180 181/// Handler for unimplemented syscalls that we haven't thought about. 182SyscallReturn unimplementedFunc(SyscallDesc *desc, int num, 183 LiveProcess *p, ThreadContext *tc); 184 185/// Handler for unimplemented syscalls that we never intend to 186/// implement (signal handling, etc.) and should not affect the correct 187/// behavior of the program. Print a warning only if the appropriate 188/// trace flag is enabled. Return success to the target program. 189SyscallReturn ignoreFunc(SyscallDesc *desc, int num, 190 LiveProcess *p, ThreadContext *tc); 191SyscallReturn ignoreWarnOnceFunc(SyscallDesc *desc, int num, 192 LiveProcess *p, ThreadContext *tc); 193 194/// Target exit() handler: terminate current context. 195SyscallReturn exitFunc(SyscallDesc *desc, int num, 196 LiveProcess *p, ThreadContext *tc); 197 198/// Target exit_group() handler: terminate simulation. (exit all threads) 199SyscallReturn exitGroupFunc(SyscallDesc *desc, int num, 200 LiveProcess *p, ThreadContext *tc); 201 202/// Target getpagesize() handler. 203SyscallReturn getpagesizeFunc(SyscallDesc *desc, int num, 204 LiveProcess *p, ThreadContext *tc); 205 206/// Target brk() handler: set brk address. 207SyscallReturn brkFunc(SyscallDesc *desc, int num, 208 LiveProcess *p, ThreadContext *tc); 209 210/// Target close() handler. 211SyscallReturn closeFunc(SyscallDesc *desc, int num, 212 LiveProcess *p, ThreadContext *tc); 213 214/// Target read() handler. 215SyscallReturn readFunc(SyscallDesc *desc, int num, 216 LiveProcess *p, ThreadContext *tc); 217 218/// Target write() handler. 219SyscallReturn writeFunc(SyscallDesc *desc, int num, 220 LiveProcess *p, ThreadContext *tc); 221 222/// Target lseek() handler. 223SyscallReturn lseekFunc(SyscallDesc *desc, int num, 224 LiveProcess *p, ThreadContext *tc); 225 226/// Target _llseek() handler. 227SyscallReturn _llseekFunc(SyscallDesc *desc, int num, 228 LiveProcess *p, ThreadContext *tc); 229 230/// Target munmap() handler. 231SyscallReturn munmapFunc(SyscallDesc *desc, int num, 232 LiveProcess *p, ThreadContext *tc); 233 234/// Target gethostname() handler. 235SyscallReturn gethostnameFunc(SyscallDesc *desc, int num, 236 LiveProcess *p, ThreadContext *tc); 237 238/// Target getcwd() handler. 239SyscallReturn getcwdFunc(SyscallDesc *desc, int num, 240 LiveProcess *p, ThreadContext *tc); 241 242/// Target unlink() handler. 243SyscallReturn readlinkFunc(SyscallDesc *desc, int num, 244 LiveProcess *p, ThreadContext *tc); 245 246/// Target unlink() handler. 247SyscallReturn unlinkFunc(SyscallDesc *desc, int num, 248 LiveProcess *p, ThreadContext *tc); 249 250/// Target mkdir() handler. 251SyscallReturn mkdirFunc(SyscallDesc *desc, int num, 252 LiveProcess *p, ThreadContext *tc); 253 254/// Target rename() handler. 255SyscallReturn renameFunc(SyscallDesc *desc, int num, 256 LiveProcess *p, ThreadContext *tc); 257 258 259/// Target truncate() handler. 260SyscallReturn truncateFunc(SyscallDesc *desc, int num, 261 LiveProcess *p, ThreadContext *tc); 262 263 264/// Target ftruncate() handler. 265SyscallReturn ftruncateFunc(SyscallDesc *desc, int num, 266 LiveProcess *p, ThreadContext *tc); 267 268 269/// Target truncate64() handler. 270SyscallReturn truncate64Func(SyscallDesc *desc, int num, 271 LiveProcess *p, ThreadContext *tc); 272 273/// Target ftruncate64() handler. 274SyscallReturn ftruncate64Func(SyscallDesc *desc, int num, 275 LiveProcess *p, ThreadContext *tc); 276 277 278/// Target umask() handler. 279SyscallReturn umaskFunc(SyscallDesc *desc, int num, 280 LiveProcess *p, ThreadContext *tc); 281 282 283/// Target chown() handler. 284SyscallReturn chownFunc(SyscallDesc *desc, int num, 285 LiveProcess *p, ThreadContext *tc); 286 287 288/// Target fchown() handler. 289SyscallReturn fchownFunc(SyscallDesc *desc, int num, 290 LiveProcess *p, ThreadContext *tc); 291 292/// Target dup() handler. 293SyscallReturn dupFunc(SyscallDesc *desc, int num, 294 LiveProcess *process, ThreadContext *tc); 295 296/// Target fnctl() handler. 297SyscallReturn fcntlFunc(SyscallDesc *desc, int num, 298 LiveProcess *process, ThreadContext *tc); 299 300/// Target fcntl64() handler. 301SyscallReturn fcntl64Func(SyscallDesc *desc, int num, 302 LiveProcess *process, ThreadContext *tc); 303 304/// Target setuid() handler. 305SyscallReturn setuidFunc(SyscallDesc *desc, int num, 306 LiveProcess *p, ThreadContext *tc); 307 308/// Target getpid() handler. 309SyscallReturn getpidFunc(SyscallDesc *desc, int num, 310 LiveProcess *p, ThreadContext *tc); 311 312/// Target getuid() handler. 313SyscallReturn getuidFunc(SyscallDesc *desc, int num, 314 LiveProcess *p, ThreadContext *tc); 315 316/// Target getgid() handler. 317SyscallReturn getgidFunc(SyscallDesc *desc, int num, 318 LiveProcess *p, ThreadContext *tc); 319 320/// Target getppid() handler. 321SyscallReturn getppidFunc(SyscallDesc *desc, int num, 322 LiveProcess *p, ThreadContext *tc); 323 324/// Target geteuid() handler. 325SyscallReturn geteuidFunc(SyscallDesc *desc, int num, 326 LiveProcess *p, ThreadContext *tc); 327 328/// Target getegid() handler. 329SyscallReturn getegidFunc(SyscallDesc *desc, int num, 330 LiveProcess *p, ThreadContext *tc); 331 332/// Target clone() handler. 333SyscallReturn cloneFunc(SyscallDesc *desc, int num, 334 LiveProcess *p, ThreadContext *tc); 335 336 337/// Pseudo Funcs - These functions use a different return convension, 338/// returning a second value in a register other than the normal return register 339SyscallReturn pipePseudoFunc(SyscallDesc *desc, int num, 340 LiveProcess *process, ThreadContext *tc); 341 342/// Target getpidPseudo() handler. 343SyscallReturn getpidPseudoFunc(SyscallDesc *desc, int num, 344 LiveProcess *p, ThreadContext *tc); 345 346/// Target getuidPseudo() handler. 347SyscallReturn getuidPseudoFunc(SyscallDesc *desc, int num, 348 LiveProcess *p, ThreadContext *tc); 349 350/// Target getgidPseudo() handler. 351SyscallReturn getgidPseudoFunc(SyscallDesc *desc, int num, 352 LiveProcess *p, ThreadContext *tc); 353 354 355/// A readable name for 1,000,000, for converting microseconds to seconds. 356const int one_million = 1000000; 357 358/// Approximate seconds since the epoch (1/1/1970). About a billion, 359/// by my reckoning. We want to keep this a constant (not use the 360/// real-world time) to keep simulations repeatable. 361const unsigned seconds_since_epoch = 1000000000; 362 363/// Helper function to convert current elapsed time to seconds and 364/// microseconds. 365template <class T1, class T2> 366void 367getElapsedTime(T1 &sec, T2 &usec) 368{ 369 int elapsed_usecs = curTick() / SimClock::Int::us; 370 sec = elapsed_usecs / one_million; 371 usec = elapsed_usecs % one_million; 372} 373 374////////////////////////////////////////////////////////////////////// 375// 376// The following emulation functions are generic, but need to be 377// templated to account for differences in types, constants, etc. 378// 379////////////////////////////////////////////////////////////////////// 380 381#if NO_STAT64 382 typedef struct stat hst_stat; 383 typedef struct stat hst_stat64; 384#else 385 typedef struct stat hst_stat; 386 typedef struct stat64 hst_stat64; 387#endif 388 389//// Helper function to convert a host stat buffer to a target stat 390//// buffer. Also copies the target buffer out to the simulated 391//// memory space. Used by stat(), fstat(), and lstat(). 392 393template <typename target_stat, typename host_stat> 394static void 395convertStatBuf(target_stat &tgt, host_stat *host, bool fakeTTY = false) 396{ 397 using namespace TheISA; 398 399 if (fakeTTY) 400 tgt->st_dev = 0xA; 401 else 402 tgt->st_dev = host->st_dev;
| 136 return true; // no EFAULT detection for now 137 } 138 139 protected: 140 Addr addr; 141 int size; 142 uint8_t *bufPtr; 143}; 144 145 146class BufferArg : public BaseBufferArg 147{ 148 public: 149 BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { } 150 void *bufferPtr() { return bufPtr; } 151}; 152 153template <class T> 154class TypedBufferArg : public BaseBufferArg 155{ 156 public: 157 // user can optionally specify a specific number of bytes to 158 // allocate to deal with those structs that have variable-size 159 // arrays at the end 160 TypedBufferArg(Addr _addr, int _size = sizeof(T)) 161 : BaseBufferArg(_addr, _size) 162 { } 163 164 // type case 165 operator T*() { return (T *)bufPtr; } 166 167 // dereference operators 168 T &operator*() { return *((T *)bufPtr); } 169 T* operator->() { return (T *)bufPtr; } 170 T &operator[](int i) { return ((T *)bufPtr)[i]; } 171}; 172 173////////////////////////////////////////////////////////////////////// 174// 175// The following emulation functions are generic enough that they 176// don't need to be recompiled for different emulated OS's. They are 177// defined in sim/syscall_emul.cc. 178// 179////////////////////////////////////////////////////////////////////// 180 181 182/// Handler for unimplemented syscalls that we haven't thought about. 183SyscallReturn unimplementedFunc(SyscallDesc *desc, int num, 184 LiveProcess *p, ThreadContext *tc); 185 186/// Handler for unimplemented syscalls that we never intend to 187/// implement (signal handling, etc.) and should not affect the correct 188/// behavior of the program. Print a warning only if the appropriate 189/// trace flag is enabled. Return success to the target program. 190SyscallReturn ignoreFunc(SyscallDesc *desc, int num, 191 LiveProcess *p, ThreadContext *tc); 192SyscallReturn ignoreWarnOnceFunc(SyscallDesc *desc, int num, 193 LiveProcess *p, ThreadContext *tc); 194 195/// Target exit() handler: terminate current context. 196SyscallReturn exitFunc(SyscallDesc *desc, int num, 197 LiveProcess *p, ThreadContext *tc); 198 199/// Target exit_group() handler: terminate simulation. (exit all threads) 200SyscallReturn exitGroupFunc(SyscallDesc *desc, int num, 201 LiveProcess *p, ThreadContext *tc); 202 203/// Target getpagesize() handler. 204SyscallReturn getpagesizeFunc(SyscallDesc *desc, int num, 205 LiveProcess *p, ThreadContext *tc); 206 207/// Target brk() handler: set brk address. 208SyscallReturn brkFunc(SyscallDesc *desc, int num, 209 LiveProcess *p, ThreadContext *tc); 210 211/// Target close() handler. 212SyscallReturn closeFunc(SyscallDesc *desc, int num, 213 LiveProcess *p, ThreadContext *tc); 214 215/// Target read() handler. 216SyscallReturn readFunc(SyscallDesc *desc, int num, 217 LiveProcess *p, ThreadContext *tc); 218 219/// Target write() handler. 220SyscallReturn writeFunc(SyscallDesc *desc, int num, 221 LiveProcess *p, ThreadContext *tc); 222 223/// Target lseek() handler. 224SyscallReturn lseekFunc(SyscallDesc *desc, int num, 225 LiveProcess *p, ThreadContext *tc); 226 227/// Target _llseek() handler. 228SyscallReturn _llseekFunc(SyscallDesc *desc, int num, 229 LiveProcess *p, ThreadContext *tc); 230 231/// Target munmap() handler. 232SyscallReturn munmapFunc(SyscallDesc *desc, int num, 233 LiveProcess *p, ThreadContext *tc); 234 235/// Target gethostname() handler. 236SyscallReturn gethostnameFunc(SyscallDesc *desc, int num, 237 LiveProcess *p, ThreadContext *tc); 238 239/// Target getcwd() handler. 240SyscallReturn getcwdFunc(SyscallDesc *desc, int num, 241 LiveProcess *p, ThreadContext *tc); 242 243/// Target unlink() handler. 244SyscallReturn readlinkFunc(SyscallDesc *desc, int num, 245 LiveProcess *p, ThreadContext *tc); 246 247/// Target unlink() handler. 248SyscallReturn unlinkFunc(SyscallDesc *desc, int num, 249 LiveProcess *p, ThreadContext *tc); 250 251/// Target mkdir() handler. 252SyscallReturn mkdirFunc(SyscallDesc *desc, int num, 253 LiveProcess *p, ThreadContext *tc); 254 255/// Target rename() handler. 256SyscallReturn renameFunc(SyscallDesc *desc, int num, 257 LiveProcess *p, ThreadContext *tc); 258 259 260/// Target truncate() handler. 261SyscallReturn truncateFunc(SyscallDesc *desc, int num, 262 LiveProcess *p, ThreadContext *tc); 263 264 265/// Target ftruncate() handler. 266SyscallReturn ftruncateFunc(SyscallDesc *desc, int num, 267 LiveProcess *p, ThreadContext *tc); 268 269 270/// Target truncate64() handler. 271SyscallReturn truncate64Func(SyscallDesc *desc, int num, 272 LiveProcess *p, ThreadContext *tc); 273 274/// Target ftruncate64() handler. 275SyscallReturn ftruncate64Func(SyscallDesc *desc, int num, 276 LiveProcess *p, ThreadContext *tc); 277 278 279/// Target umask() handler. 280SyscallReturn umaskFunc(SyscallDesc *desc, int num, 281 LiveProcess *p, ThreadContext *tc); 282 283 284/// Target chown() handler. 285SyscallReturn chownFunc(SyscallDesc *desc, int num, 286 LiveProcess *p, ThreadContext *tc); 287 288 289/// Target fchown() handler. 290SyscallReturn fchownFunc(SyscallDesc *desc, int num, 291 LiveProcess *p, ThreadContext *tc); 292 293/// Target dup() handler. 294SyscallReturn dupFunc(SyscallDesc *desc, int num, 295 LiveProcess *process, ThreadContext *tc); 296 297/// Target fnctl() handler. 298SyscallReturn fcntlFunc(SyscallDesc *desc, int num, 299 LiveProcess *process, ThreadContext *tc); 300 301/// Target fcntl64() handler. 302SyscallReturn fcntl64Func(SyscallDesc *desc, int num, 303 LiveProcess *process, ThreadContext *tc); 304 305/// Target setuid() handler. 306SyscallReturn setuidFunc(SyscallDesc *desc, int num, 307 LiveProcess *p, ThreadContext *tc); 308 309/// Target getpid() handler. 310SyscallReturn getpidFunc(SyscallDesc *desc, int num, 311 LiveProcess *p, ThreadContext *tc); 312 313/// Target getuid() handler. 314SyscallReturn getuidFunc(SyscallDesc *desc, int num, 315 LiveProcess *p, ThreadContext *tc); 316 317/// Target getgid() handler. 318SyscallReturn getgidFunc(SyscallDesc *desc, int num, 319 LiveProcess *p, ThreadContext *tc); 320 321/// Target getppid() handler. 322SyscallReturn getppidFunc(SyscallDesc *desc, int num, 323 LiveProcess *p, ThreadContext *tc); 324 325/// Target geteuid() handler. 326SyscallReturn geteuidFunc(SyscallDesc *desc, int num, 327 LiveProcess *p, ThreadContext *tc); 328 329/// Target getegid() handler. 330SyscallReturn getegidFunc(SyscallDesc *desc, int num, 331 LiveProcess *p, ThreadContext *tc); 332 333/// Target clone() handler. 334SyscallReturn cloneFunc(SyscallDesc *desc, int num, 335 LiveProcess *p, ThreadContext *tc); 336 337 338/// Pseudo Funcs - These functions use a different return convension, 339/// returning a second value in a register other than the normal return register 340SyscallReturn pipePseudoFunc(SyscallDesc *desc, int num, 341 LiveProcess *process, ThreadContext *tc); 342 343/// Target getpidPseudo() handler. 344SyscallReturn getpidPseudoFunc(SyscallDesc *desc, int num, 345 LiveProcess *p, ThreadContext *tc); 346 347/// Target getuidPseudo() handler. 348SyscallReturn getuidPseudoFunc(SyscallDesc *desc, int num, 349 LiveProcess *p, ThreadContext *tc); 350 351/// Target getgidPseudo() handler. 352SyscallReturn getgidPseudoFunc(SyscallDesc *desc, int num, 353 LiveProcess *p, ThreadContext *tc); 354 355 356/// A readable name for 1,000,000, for converting microseconds to seconds. 357const int one_million = 1000000; 358 359/// Approximate seconds since the epoch (1/1/1970). About a billion, 360/// by my reckoning. We want to keep this a constant (not use the 361/// real-world time) to keep simulations repeatable. 362const unsigned seconds_since_epoch = 1000000000; 363 364/// Helper function to convert current elapsed time to seconds and 365/// microseconds. 366template <class T1, class T2> 367void 368getElapsedTime(T1 &sec, T2 &usec) 369{ 370 int elapsed_usecs = curTick() / SimClock::Int::us; 371 sec = elapsed_usecs / one_million; 372 usec = elapsed_usecs % one_million; 373} 374 375////////////////////////////////////////////////////////////////////// 376// 377// The following emulation functions are generic, but need to be 378// templated to account for differences in types, constants, etc. 379// 380////////////////////////////////////////////////////////////////////// 381 382#if NO_STAT64 383 typedef struct stat hst_stat; 384 typedef struct stat hst_stat64; 385#else 386 typedef struct stat hst_stat; 387 typedef struct stat64 hst_stat64; 388#endif 389 390//// Helper function to convert a host stat buffer to a target stat 391//// buffer. Also copies the target buffer out to the simulated 392//// memory space. Used by stat(), fstat(), and lstat(). 393 394template <typename target_stat, typename host_stat> 395static void 396convertStatBuf(target_stat &tgt, host_stat *host, bool fakeTTY = false) 397{ 398 using namespace TheISA; 399 400 if (fakeTTY) 401 tgt->st_dev = 0xA; 402 else 403 tgt->st_dev = host->st_dev;
|
403 tgt->st_dev = TheISA::htog(tgt->st_dev);
| 404 tgt->st_dev = htog(tgt->st_dev);
|
404 tgt->st_ino = host->st_ino;
| 405 tgt->st_ino = host->st_ino;
|
405 tgt->st_ino = TheISA::htog(tgt->st_ino);
| 406 tgt->st_ino = htog(tgt->st_ino);
|
406 tgt->st_mode = host->st_mode; 407 if (fakeTTY) { 408 // Claim to be a character device 409 tgt->st_mode &= ~S_IFMT; // Clear S_IFMT 410 tgt->st_mode |= S_IFCHR; // Set S_IFCHR 411 }
| 407 tgt->st_mode = host->st_mode; 408 if (fakeTTY) { 409 // Claim to be a character device 410 tgt->st_mode &= ~S_IFMT; // Clear S_IFMT 411 tgt->st_mode |= S_IFCHR; // Set S_IFCHR 412 }
|
412 tgt->st_mode = TheISA::htog(tgt->st_mode);
| 413 tgt->st_mode = htog(tgt->st_mode);
|
413 tgt->st_nlink = host->st_nlink;
| 414 tgt->st_nlink = host->st_nlink;
|
414 tgt->st_nlink = TheISA::htog(tgt->st_nlink);
| 415 tgt->st_nlink = htog(tgt->st_nlink);
|
415 tgt->st_uid = host->st_uid;
| 416 tgt->st_uid = host->st_uid;
|
416 tgt->st_uid = TheISA::htog(tgt->st_uid);
| 417 tgt->st_uid = htog(tgt->st_uid);
|
417 tgt->st_gid = host->st_gid;
| 418 tgt->st_gid = host->st_gid;
|
418 tgt->st_gid = TheISA::htog(tgt->st_gid);
| 419 tgt->st_gid = htog(tgt->st_gid);
|
419 if (fakeTTY) 420 tgt->st_rdev = 0x880d; 421 else 422 tgt->st_rdev = host->st_rdev;
| 420 if (fakeTTY) 421 tgt->st_rdev = 0x880d; 422 else 423 tgt->st_rdev = host->st_rdev;
|
423 tgt->st_rdev = TheISA::htog(tgt->st_rdev);
| 424 tgt->st_rdev = htog(tgt->st_rdev);
|
424 tgt->st_size = host->st_size;
| 425 tgt->st_size = host->st_size;
|
425 tgt->st_size = TheISA::htog(tgt->st_size);
| 426 tgt->st_size = htog(tgt->st_size);
|
426 tgt->st_atimeX = host->st_atime;
| 427 tgt->st_atimeX = host->st_atime;
|
427 tgt->st_atimeX = TheISA::htog(tgt->st_atimeX);
| 428 tgt->st_atimeX = htog(tgt->st_atimeX);
|
428 tgt->st_mtimeX = host->st_mtime;
| 429 tgt->st_mtimeX = host->st_mtime;
|
429 tgt->st_mtimeX = TheISA::htog(tgt->st_mtimeX);
| 430 tgt->st_mtimeX = htog(tgt->st_mtimeX);
|
430 tgt->st_ctimeX = host->st_ctime;
| 431 tgt->st_ctimeX = host->st_ctime;
|
431 tgt->st_ctimeX = TheISA::htog(tgt->st_ctimeX);
| 432 tgt->st_ctimeX = htog(tgt->st_ctimeX);
|
432 // Force the block size to be 8k. This helps to ensure buffered io works 433 // consistently across different hosts. 434 tgt->st_blksize = 0x2000;
| 433 // Force the block size to be 8k. This helps to ensure buffered io works 434 // consistently across different hosts. 435 tgt->st_blksize = 0x2000;
|
435 tgt->st_blksize = TheISA::htog(tgt->st_blksize);
| 436 tgt->st_blksize = htog(tgt->st_blksize);
|
436 tgt->st_blocks = host->st_blocks;
| 437 tgt->st_blocks = host->st_blocks;
|
437 tgt->st_blocks = TheISA::htog(tgt->st_blocks);
| 438 tgt->st_blocks = htog(tgt->st_blocks);
|
438} 439 440// Same for stat64 441 442template <typename target_stat, typename host_stat64> 443static void 444convertStat64Buf(target_stat &tgt, host_stat64 *host, bool fakeTTY = false) 445{ 446 using namespace TheISA; 447 448 convertStatBuf<target_stat, host_stat64>(tgt, host, fakeTTY); 449#if defined(STAT_HAVE_NSEC) 450 tgt->st_atime_nsec = host->st_atime_nsec;
| 439} 440 441// Same for stat64 442 443template <typename target_stat, typename host_stat64> 444static void 445convertStat64Buf(target_stat &tgt, host_stat64 *host, bool fakeTTY = false) 446{ 447 using namespace TheISA; 448 449 convertStatBuf<target_stat, host_stat64>(tgt, host, fakeTTY); 450#if defined(STAT_HAVE_NSEC) 451 tgt->st_atime_nsec = host->st_atime_nsec;
|
451 tgt->st_atime_nsec = TheISA::htog(tgt->st_atime_nsec);
| 452 tgt->st_atime_nsec = htog(tgt->st_atime_nsec);
|
452 tgt->st_mtime_nsec = host->st_mtime_nsec;
| 453 tgt->st_mtime_nsec = host->st_mtime_nsec;
|
453 tgt->st_mtime_nsec = TheISA::htog(tgt->st_mtime_nsec);
| 454 tgt->st_mtime_nsec = htog(tgt->st_mtime_nsec);
|
454 tgt->st_ctime_nsec = host->st_ctime_nsec;
| 455 tgt->st_ctime_nsec = host->st_ctime_nsec;
|
455 tgt->st_ctime_nsec = TheISA::htog(tgt->st_ctime_nsec);
| 456 tgt->st_ctime_nsec = htog(tgt->st_ctime_nsec);
|
456#else 457 tgt->st_atime_nsec = 0; 458 tgt->st_mtime_nsec = 0; 459 tgt->st_ctime_nsec = 0; 460#endif 461} 462 463//Here are a couple convenience functions 464template<class OS> 465static void
| 457#else 458 tgt->st_atime_nsec = 0; 459 tgt->st_mtime_nsec = 0; 460 tgt->st_ctime_nsec = 0; 461#endif 462} 463 464//Here are a couple convenience functions 465template<class OS> 466static void
|
466copyOutStatBuf(SETranslatingPortProxy* mem, Addr addr,
| 467copyOutStatBuf(TranslatingPort * mem, Addr addr,
|
467 hst_stat *host, bool fakeTTY = false) 468{ 469 typedef TypedBufferArg<typename OS::tgt_stat> tgt_stat_buf; 470 tgt_stat_buf tgt(addr); 471 convertStatBuf<tgt_stat_buf, hst_stat>(tgt, host, fakeTTY); 472 tgt.copyOut(mem); 473} 474 475template<class OS> 476static void
| 468 hst_stat *host, bool fakeTTY = false) 469{ 470 typedef TypedBufferArg<typename OS::tgt_stat> tgt_stat_buf; 471 tgt_stat_buf tgt(addr); 472 convertStatBuf<tgt_stat_buf, hst_stat>(tgt, host, fakeTTY); 473 tgt.copyOut(mem); 474} 475 476template<class OS> 477static void
|
477copyOutStat64Buf(SETranslatingPortProxy* mem, Addr addr,
| 478copyOutStat64Buf(TranslatingPort * mem, Addr addr,
|
478 hst_stat64 *host, bool fakeTTY = false) 479{ 480 typedef TypedBufferArg<typename OS::tgt_stat64> tgt_stat_buf; 481 tgt_stat_buf tgt(addr); 482 convertStat64Buf<tgt_stat_buf, hst_stat64>(tgt, host, fakeTTY); 483 tgt.copyOut(mem); 484} 485 486/// Target ioctl() handler. For the most part, programs call ioctl() 487/// only to find out if their stdout is a tty, to determine whether to 488/// do line or block buffering. 489template <class OS> 490SyscallReturn 491ioctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 492 ThreadContext *tc) 493{ 494 int index = 0; 495 int fd = process->getSyscallArg(tc, index); 496 unsigned req = process->getSyscallArg(tc, index); 497 498 DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req); 499 500 if (fd < 0 || process->sim_fd(fd) < 0) { 501 // doesn't map to any simulator fd: not a valid target fd 502 return -EBADF; 503 } 504 505 switch (req) { 506 case OS::TIOCISATTY_: 507 case OS::TIOCGETP_: 508 case OS::TIOCSETP_: 509 case OS::TIOCSETN_: 510 case OS::TIOCSETC_: 511 case OS::TIOCGETC_: 512 case OS::TIOCGETS_: 513 case OS::TIOCGETA_: 514 case OS::TCSETAW_: 515 return -ENOTTY; 516 517 default: 518 fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ \n", 519 fd, req, tc->pcState()); 520 } 521} 522 523/// Target open() handler. 524template <class OS> 525SyscallReturn 526openFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 527 ThreadContext *tc) 528{ 529 std::string path; 530 531 int index = 0;
| 479 hst_stat64 *host, bool fakeTTY = false) 480{ 481 typedef TypedBufferArg<typename OS::tgt_stat64> tgt_stat_buf; 482 tgt_stat_buf tgt(addr); 483 convertStat64Buf<tgt_stat_buf, hst_stat64>(tgt, host, fakeTTY); 484 tgt.copyOut(mem); 485} 486 487/// Target ioctl() handler. For the most part, programs call ioctl() 488/// only to find out if their stdout is a tty, to determine whether to 489/// do line or block buffering. 490template <class OS> 491SyscallReturn 492ioctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 493 ThreadContext *tc) 494{ 495 int index = 0; 496 int fd = process->getSyscallArg(tc, index); 497 unsigned req = process->getSyscallArg(tc, index); 498 499 DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req); 500 501 if (fd < 0 || process->sim_fd(fd) < 0) { 502 // doesn't map to any simulator fd: not a valid target fd 503 return -EBADF; 504 } 505 506 switch (req) { 507 case OS::TIOCISATTY_: 508 case OS::TIOCGETP_: 509 case OS::TIOCSETP_: 510 case OS::TIOCSETN_: 511 case OS::TIOCSETC_: 512 case OS::TIOCGETC_: 513 case OS::TIOCGETS_: 514 case OS::TIOCGETA_: 515 case OS::TCSETAW_: 516 return -ENOTTY; 517 518 default: 519 fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ \n", 520 fd, req, tc->pcState()); 521 } 522} 523 524/// Target open() handler. 525template <class OS> 526SyscallReturn 527openFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 528 ThreadContext *tc) 529{ 530 std::string path; 531 532 int index = 0;
|
532 if (!tc->getMemProxy()->tryReadString(path,
| 533 if (!tc->getMemPort()->tryReadString(path,
|
533 process->getSyscallArg(tc, index))) 534 return -EFAULT; 535 536 if (path == "/dev/sysdev0") { 537 // This is a memory-mapped high-resolution timer device on Alpha. 538 // We don't support it, so just punt. 539 warn("Ignoring open(%s, ...)\n", path); 540 return -ENOENT; 541 } 542 543 int tgtFlags = process->getSyscallArg(tc, index); 544 int mode = process->getSyscallArg(tc, index); 545 int hostFlags = 0; 546 547 // translate open flags 548 for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) { 549 if (tgtFlags & OS::openFlagTable[i].tgtFlag) { 550 tgtFlags &= ~OS::openFlagTable[i].tgtFlag; 551 hostFlags |= OS::openFlagTable[i].hostFlag; 552 } 553 } 554 555 // any target flags left? 556 if (tgtFlags != 0) 557 warn("Syscall: open: cannot decode flags 0x%x", tgtFlags); 558 559#ifdef __CYGWIN32__ 560 hostFlags |= O_BINARY; 561#endif 562 563 // Adjust path for current working directory 564 path = process->fullPath(path); 565 566 DPRINTF(SyscallVerbose, "opening file %s\n", path.c_str()); 567 568 int fd; 569 if (!path.compare(0, 6, "/proc/") || !path.compare(0, 8, "/system/") || 570 !path.compare(0, 10, "/platform/") || !path.compare(0, 5, "/sys/")) { 571 // It's a proc/sys entery and requires special handling 572 fd = OS::openSpecialFile(path, process, tc); 573 return (fd == -1) ? -1 : process->alloc_fd(fd,path.c_str(),hostFlags,mode, false); 574 } else { 575 // open the file 576 fd = open(path.c_str(), hostFlags, mode); 577 return (fd == -1) ? -errno : process->alloc_fd(fd,path.c_str(),hostFlags,mode, false); 578 } 579 580} 581 582/// Target sysinfo() handler. 583template <class OS> 584SyscallReturn 585sysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 586 ThreadContext *tc) 587{ 588 589 int index = 0; 590 TypedBufferArg<typename OS::tgt_sysinfo> 591 sysinfo(process->getSyscallArg(tc, index)); 592 593 sysinfo->uptime=seconds_since_epoch; 594 sysinfo->totalram=process->system->memSize(); 595
| 534 process->getSyscallArg(tc, index))) 535 return -EFAULT; 536 537 if (path == "/dev/sysdev0") { 538 // This is a memory-mapped high-resolution timer device on Alpha. 539 // We don't support it, so just punt. 540 warn("Ignoring open(%s, ...)\n", path); 541 return -ENOENT; 542 } 543 544 int tgtFlags = process->getSyscallArg(tc, index); 545 int mode = process->getSyscallArg(tc, index); 546 int hostFlags = 0; 547 548 // translate open flags 549 for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) { 550 if (tgtFlags & OS::openFlagTable[i].tgtFlag) { 551 tgtFlags &= ~OS::openFlagTable[i].tgtFlag; 552 hostFlags |= OS::openFlagTable[i].hostFlag; 553 } 554 } 555 556 // any target flags left? 557 if (tgtFlags != 0) 558 warn("Syscall: open: cannot decode flags 0x%x", tgtFlags); 559 560#ifdef __CYGWIN32__ 561 hostFlags |= O_BINARY; 562#endif 563 564 // Adjust path for current working directory 565 path = process->fullPath(path); 566 567 DPRINTF(SyscallVerbose, "opening file %s\n", path.c_str()); 568 569 int fd; 570 if (!path.compare(0, 6, "/proc/") || !path.compare(0, 8, "/system/") || 571 !path.compare(0, 10, "/platform/") || !path.compare(0, 5, "/sys/")) { 572 // It's a proc/sys entery and requires special handling 573 fd = OS::openSpecialFile(path, process, tc); 574 return (fd == -1) ? -1 : process->alloc_fd(fd,path.c_str(),hostFlags,mode, false); 575 } else { 576 // open the file 577 fd = open(path.c_str(), hostFlags, mode); 578 return (fd == -1) ? -errno : process->alloc_fd(fd,path.c_str(),hostFlags,mode, false); 579 } 580 581} 582 583/// Target sysinfo() handler. 584template <class OS> 585SyscallReturn 586sysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 587 ThreadContext *tc) 588{ 589 590 int index = 0; 591 TypedBufferArg<typename OS::tgt_sysinfo> 592 sysinfo(process->getSyscallArg(tc, index)); 593 594 sysinfo->uptime=seconds_since_epoch; 595 sysinfo->totalram=process->system->memSize(); 596
|
596 sysinfo.copyOut(tc->getMemProxy());
| 597 sysinfo.copyOut(tc->getMemPort());
|
597 598 return 0; 599} 600 601/// Target chmod() handler. 602template <class OS> 603SyscallReturn 604chmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 605 ThreadContext *tc) 606{ 607 std::string path; 608 609 int index = 0;
| 598 599 return 0; 600} 601 602/// Target chmod() handler. 603template <class OS> 604SyscallReturn 605chmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 606 ThreadContext *tc) 607{ 608 std::string path; 609 610 int index = 0;
|
610 if (!tc->getMemProxy()->tryReadString(path,
| 611 if (!tc->getMemPort()->tryReadString(path,
|
611 process->getSyscallArg(tc, index))) { 612 return -EFAULT; 613 } 614 615 uint32_t mode = process->getSyscallArg(tc, index); 616 mode_t hostMode = 0; 617 618 // XXX translate mode flags via OS::something??? 619 hostMode = mode; 620 621 // Adjust path for current working directory 622 path = process->fullPath(path); 623 624 // do the chmod 625 int result = chmod(path.c_str(), hostMode); 626 if (result < 0) 627 return -errno; 628 629 return 0; 630} 631 632 633/// Target fchmod() handler. 634template <class OS> 635SyscallReturn 636fchmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 637 ThreadContext *tc) 638{ 639 int index = 0; 640 int fd = process->getSyscallArg(tc, index); 641 if (fd < 0 || process->sim_fd(fd) < 0) { 642 // doesn't map to any simulator fd: not a valid target fd 643 return -EBADF; 644 } 645 646 uint32_t mode = process->getSyscallArg(tc, index); 647 mode_t hostMode = 0; 648 649 // XXX translate mode flags via OS::someting??? 650 hostMode = mode; 651 652 // do the fchmod 653 int result = fchmod(process->sim_fd(fd), hostMode); 654 if (result < 0) 655 return -errno; 656 657 return 0; 658} 659 660/// Target mremap() handler. 661template <class OS> 662SyscallReturn 663mremapFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) 664{ 665 int index = 0; 666 Addr start = process->getSyscallArg(tc, index); 667 uint64_t old_length = process->getSyscallArg(tc, index); 668 uint64_t new_length = process->getSyscallArg(tc, index); 669 uint64_t flags = process->getSyscallArg(tc, index); 670 671 if ((start % TheISA::VMPageSize != 0) || 672 (new_length % TheISA::VMPageSize != 0)) { 673 warn("mremap failing: arguments not page aligned"); 674 return -EINVAL; 675 } 676 677 if (new_length > old_length) { 678 if ((start + old_length) == process->mmap_end) { 679 uint64_t diff = new_length - old_length;
| 612 process->getSyscallArg(tc, index))) { 613 return -EFAULT; 614 } 615 616 uint32_t mode = process->getSyscallArg(tc, index); 617 mode_t hostMode = 0; 618 619 // XXX translate mode flags via OS::something??? 620 hostMode = mode; 621 622 // Adjust path for current working directory 623 path = process->fullPath(path); 624 625 // do the chmod 626 int result = chmod(path.c_str(), hostMode); 627 if (result < 0) 628 return -errno; 629 630 return 0; 631} 632 633 634/// Target fchmod() handler. 635template <class OS> 636SyscallReturn 637fchmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 638 ThreadContext *tc) 639{ 640 int index = 0; 641 int fd = process->getSyscallArg(tc, index); 642 if (fd < 0 || process->sim_fd(fd) < 0) { 643 // doesn't map to any simulator fd: not a valid target fd 644 return -EBADF; 645 } 646 647 uint32_t mode = process->getSyscallArg(tc, index); 648 mode_t hostMode = 0; 649 650 // XXX translate mode flags via OS::someting??? 651 hostMode = mode; 652 653 // do the fchmod 654 int result = fchmod(process->sim_fd(fd), hostMode); 655 if (result < 0) 656 return -errno; 657 658 return 0; 659} 660 661/// Target mremap() handler. 662template <class OS> 663SyscallReturn 664mremapFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) 665{ 666 int index = 0; 667 Addr start = process->getSyscallArg(tc, index); 668 uint64_t old_length = process->getSyscallArg(tc, index); 669 uint64_t new_length = process->getSyscallArg(tc, index); 670 uint64_t flags = process->getSyscallArg(tc, index); 671 672 if ((start % TheISA::VMPageSize != 0) || 673 (new_length % TheISA::VMPageSize != 0)) { 674 warn("mremap failing: arguments not page aligned"); 675 return -EINVAL; 676 } 677 678 if (new_length > old_length) { 679 if ((start + old_length) == process->mmap_end) { 680 uint64_t diff = new_length - old_length;
|
680 process->allocateMem(process->mmap_end, diff);
| 681 process->pTable->allocate(process->mmap_end, diff);
|
681 process->mmap_end += diff; 682 return start; 683 } else { 684 // sys/mman.h defined MREMAP_MAYMOVE 685 if (!(flags & 1)) { 686 warn("can't remap here and MREMAP_MAYMOVE flag not set\n"); 687 return -ENOMEM; 688 } else { 689 process->pTable->remap(start, old_length, process->mmap_end); 690 warn("mremapping to totally new vaddr %08p-%08p, adding %d\n", 691 process->mmap_end, process->mmap_end + new_length, new_length); 692 start = process->mmap_end; 693 // add on the remaining unallocated pages
| 682 process->mmap_end += diff; 683 return start; 684 } else { 685 // sys/mman.h defined MREMAP_MAYMOVE 686 if (!(flags & 1)) { 687 warn("can't remap here and MREMAP_MAYMOVE flag not set\n"); 688 return -ENOMEM; 689 } else { 690 process->pTable->remap(start, old_length, process->mmap_end); 691 warn("mremapping to totally new vaddr %08p-%08p, adding %d\n", 692 process->mmap_end, process->mmap_end + new_length, new_length); 693 start = process->mmap_end; 694 // add on the remaining unallocated pages
|
694 process->allocateMem(start + old_length, 695 new_length - old_length);
| 695 process->pTable->allocate(start + old_length, new_length - old_length);
|
696 process->mmap_end += new_length; 697 warn("returning %08p as start\n", start); 698 return start; 699 } 700 } 701 } else {
| 696 process->mmap_end += new_length; 697 warn("returning %08p as start\n", start); 698 return start; 699 } 700 } 701 } else {
|
702 process->pTable->unmap(start + new_length, old_length - new_length);
| 702 process->pTable->deallocate(start + new_length, old_length - 703 new_length);
|
703 return start; 704 } 705} 706 707/// Target stat() handler. 708template <class OS> 709SyscallReturn 710statFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 711 ThreadContext *tc) 712{ 713 std::string path; 714 715 int index = 0;
| 704 return start; 705 } 706} 707 708/// Target stat() handler. 709template <class OS> 710SyscallReturn 711statFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 712 ThreadContext *tc) 713{ 714 std::string path; 715 716 int index = 0;
|
716 if (!tc->getMemProxy()->tryReadString(path,
| 717 if (!tc->getMemPort()->tryReadString(path,
|
717 process->getSyscallArg(tc, index))) { 718 return -EFAULT; 719 } 720 Addr bufPtr = process->getSyscallArg(tc, index); 721 722 // Adjust path for current working directory 723 path = process->fullPath(path); 724 725 struct stat hostBuf; 726 int result = stat(path.c_str(), &hostBuf); 727 728 if (result < 0) 729 return -errno; 730
| 718 process->getSyscallArg(tc, index))) { 719 return -EFAULT; 720 } 721 Addr bufPtr = process->getSyscallArg(tc, index); 722 723 // Adjust path for current working directory 724 path = process->fullPath(path); 725 726 struct stat hostBuf; 727 int result = stat(path.c_str(), &hostBuf); 728 729 if (result < 0) 730 return -errno; 731
|
731 copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf);
| 732 copyOutStatBuf<OS>(tc->getMemPort(), bufPtr, &hostBuf);
|
732 733 return 0; 734} 735 736 737/// Target stat64() handler. 738template <class OS> 739SyscallReturn 740stat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 741 ThreadContext *tc) 742{ 743 std::string path; 744 745 int index = 0;
| 733 734 return 0; 735} 736 737 738/// Target stat64() handler. 739template <class OS> 740SyscallReturn 741stat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 742 ThreadContext *tc) 743{ 744 std::string path; 745 746 int index = 0;
|
746 if (!tc->getMemProxy()->tryReadString(path,
| 747 if (!tc->getMemPort()->tryReadString(path,
|
747 process->getSyscallArg(tc, index))) 748 return -EFAULT; 749 Addr bufPtr = process->getSyscallArg(tc, index); 750 751 // Adjust path for current working directory 752 path = process->fullPath(path); 753 754#if NO_STAT64 755 struct stat hostBuf; 756 int result = stat(path.c_str(), &hostBuf); 757#else 758 struct stat64 hostBuf; 759 int result = stat64(path.c_str(), &hostBuf); 760#endif 761 762 if (result < 0) 763 return -errno; 764
| 748 process->getSyscallArg(tc, index))) 749 return -EFAULT; 750 Addr bufPtr = process->getSyscallArg(tc, index); 751 752 // Adjust path for current working directory 753 path = process->fullPath(path); 754 755#if NO_STAT64 756 struct stat hostBuf; 757 int result = stat(path.c_str(), &hostBuf); 758#else 759 struct stat64 hostBuf; 760 int result = stat64(path.c_str(), &hostBuf); 761#endif 762 763 if (result < 0) 764 return -errno; 765
|
765 copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf);
| 766 copyOutStat64Buf<OS>(tc->getMemPort(), bufPtr, &hostBuf);
|
766 767 return 0; 768} 769 770 771/// Target fstat64() handler. 772template <class OS> 773SyscallReturn 774fstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 775 ThreadContext *tc) 776{ 777 int index = 0; 778 int fd = process->getSyscallArg(tc, index); 779 Addr bufPtr = process->getSyscallArg(tc, index); 780 if (fd < 0 || process->sim_fd(fd) < 0) { 781 // doesn't map to any simulator fd: not a valid target fd 782 return -EBADF; 783 } 784 785#if NO_STAT64 786 struct stat hostBuf; 787 int result = fstat(process->sim_fd(fd), &hostBuf); 788#else 789 struct stat64 hostBuf; 790 int result = fstat64(process->sim_fd(fd), &hostBuf); 791#endif 792 793 if (result < 0) 794 return -errno; 795
| 767 768 return 0; 769} 770 771 772/// Target fstat64() handler. 773template <class OS> 774SyscallReturn 775fstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 776 ThreadContext *tc) 777{ 778 int index = 0; 779 int fd = process->getSyscallArg(tc, index); 780 Addr bufPtr = process->getSyscallArg(tc, index); 781 if (fd < 0 || process->sim_fd(fd) < 0) { 782 // doesn't map to any simulator fd: not a valid target fd 783 return -EBADF; 784 } 785 786#if NO_STAT64 787 struct stat hostBuf; 788 int result = fstat(process->sim_fd(fd), &hostBuf); 789#else 790 struct stat64 hostBuf; 791 int result = fstat64(process->sim_fd(fd), &hostBuf); 792#endif 793 794 if (result < 0) 795 return -errno; 796
|
796 copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf, (fd == 1));
| 797 copyOutStat64Buf<OS>(tc->getMemPort(), bufPtr, &hostBuf, (fd == 1));
|
797 798 return 0; 799} 800 801 802/// Target lstat() handler. 803template <class OS> 804SyscallReturn 805lstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 806 ThreadContext *tc) 807{ 808 std::string path; 809 810 int index = 0;
| 798 799 return 0; 800} 801 802 803/// Target lstat() handler. 804template <class OS> 805SyscallReturn 806lstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 807 ThreadContext *tc) 808{ 809 std::string path; 810 811 int index = 0;
|
811 if (!tc->getMemProxy()->tryReadString(path,
| 812 if (!tc->getMemPort()->tryReadString(path,
|
812 process->getSyscallArg(tc, index))) { 813 return -EFAULT; 814 } 815 Addr bufPtr = process->getSyscallArg(tc, index); 816 817 // Adjust path for current working directory 818 path = process->fullPath(path); 819 820 struct stat hostBuf; 821 int result = lstat(path.c_str(), &hostBuf); 822 823 if (result < 0) 824 return -errno; 825
| 813 process->getSyscallArg(tc, index))) { 814 return -EFAULT; 815 } 816 Addr bufPtr = process->getSyscallArg(tc, index); 817 818 // Adjust path for current working directory 819 path = process->fullPath(path); 820 821 struct stat hostBuf; 822 int result = lstat(path.c_str(), &hostBuf); 823 824 if (result < 0) 825 return -errno; 826
|
826 copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf);
| 827 copyOutStatBuf<OS>(tc->getMemPort(), bufPtr, &hostBuf);
|
827 828 return 0; 829} 830 831/// Target lstat64() handler. 832template <class OS> 833SyscallReturn 834lstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 835 ThreadContext *tc) 836{ 837 std::string path; 838 839 int index = 0;
| 828 829 return 0; 830} 831 832/// Target lstat64() handler. 833template <class OS> 834SyscallReturn 835lstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 836 ThreadContext *tc) 837{ 838 std::string path; 839 840 int index = 0;
|
840 if (!tc->getMemProxy()->tryReadString(path,
| 841 if (!tc->getMemPort()->tryReadString(path,
|
841 process->getSyscallArg(tc, index))) { 842 return -EFAULT; 843 } 844 Addr bufPtr = process->getSyscallArg(tc, index); 845 846 // Adjust path for current working directory 847 path = process->fullPath(path); 848 849#if NO_STAT64 850 struct stat hostBuf; 851 int result = lstat(path.c_str(), &hostBuf); 852#else 853 struct stat64 hostBuf; 854 int result = lstat64(path.c_str(), &hostBuf); 855#endif 856 857 if (result < 0) 858 return -errno; 859
| 842 process->getSyscallArg(tc, index))) { 843 return -EFAULT; 844 } 845 Addr bufPtr = process->getSyscallArg(tc, index); 846 847 // Adjust path for current working directory 848 path = process->fullPath(path); 849 850#if NO_STAT64 851 struct stat hostBuf; 852 int result = lstat(path.c_str(), &hostBuf); 853#else 854 struct stat64 hostBuf; 855 int result = lstat64(path.c_str(), &hostBuf); 856#endif 857 858 if (result < 0) 859 return -errno; 860
|
860 copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf);
| 861 copyOutStat64Buf<OS>(tc->getMemPort(), bufPtr, &hostBuf);
|
861 862 return 0; 863} 864 865/// Target fstat() handler. 866template <class OS> 867SyscallReturn 868fstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 869 ThreadContext *tc) 870{ 871 int index = 0; 872 int fd = process->sim_fd(process->getSyscallArg(tc, index)); 873 Addr bufPtr = process->getSyscallArg(tc, index); 874 875 DPRINTF(SyscallVerbose, "fstat(%d, ...)\n", fd); 876 877 if (fd < 0) 878 return -EBADF; 879 880 struct stat hostBuf; 881 int result = fstat(fd, &hostBuf); 882 883 if (result < 0) 884 return -errno; 885
| 862 863 return 0; 864} 865 866/// Target fstat() handler. 867template <class OS> 868SyscallReturn 869fstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 870 ThreadContext *tc) 871{ 872 int index = 0; 873 int fd = process->sim_fd(process->getSyscallArg(tc, index)); 874 Addr bufPtr = process->getSyscallArg(tc, index); 875 876 DPRINTF(SyscallVerbose, "fstat(%d, ...)\n", fd); 877 878 if (fd < 0) 879 return -EBADF; 880 881 struct stat hostBuf; 882 int result = fstat(fd, &hostBuf); 883 884 if (result < 0) 885 return -errno; 886
|
886 copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf, (fd == 1));
| 887 copyOutStatBuf<OS>(tc->getMemPort(), bufPtr, &hostBuf, (fd == 1));
|
887 888 return 0; 889} 890 891 892/// Target statfs() handler. 893template <class OS> 894SyscallReturn 895statfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 896 ThreadContext *tc) 897{ 898 std::string path; 899 900 int index = 0;
| 888 889 return 0; 890} 891 892 893/// Target statfs() handler. 894template <class OS> 895SyscallReturn 896statfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 897 ThreadContext *tc) 898{ 899 std::string path; 900 901 int index = 0;
|
901 if (!tc->getMemProxy()->tryReadString(path,
| 902 if (!tc->getMemPort()->tryReadString(path,
|
902 process->getSyscallArg(tc, index))) { 903 return -EFAULT; 904 } 905 Addr bufPtr = process->getSyscallArg(tc, index); 906 907 // Adjust path for current working directory 908 path = process->fullPath(path); 909 910 struct statfs hostBuf; 911 int result = statfs(path.c_str(), &hostBuf); 912 913 if (result < 0) 914 return -errno; 915
| 903 process->getSyscallArg(tc, index))) { 904 return -EFAULT; 905 } 906 Addr bufPtr = process->getSyscallArg(tc, index); 907 908 // Adjust path for current working directory 909 path = process->fullPath(path); 910 911 struct statfs hostBuf; 912 int result = statfs(path.c_str(), &hostBuf); 913 914 if (result < 0) 915 return -errno; 916
|
916 OS::copyOutStatfsBuf(tc->getMemProxy(), bufPtr, &hostBuf);
| 917 OS::copyOutStatfsBuf(tc->getMemPort(), bufPtr, &hostBuf);
|
917 918 return 0; 919} 920 921 922/// Target fstatfs() handler. 923template <class OS> 924SyscallReturn 925fstatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 926 ThreadContext *tc) 927{ 928 int index = 0; 929 int fd = process->sim_fd(process->getSyscallArg(tc, index)); 930 Addr bufPtr = process->getSyscallArg(tc, index); 931 932 if (fd < 0) 933 return -EBADF; 934 935 struct statfs hostBuf; 936 int result = fstatfs(fd, &hostBuf); 937 938 if (result < 0) 939 return -errno; 940
| 918 919 return 0; 920} 921 922 923/// Target fstatfs() handler. 924template <class OS> 925SyscallReturn 926fstatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 927 ThreadContext *tc) 928{ 929 int index = 0; 930 int fd = process->sim_fd(process->getSyscallArg(tc, index)); 931 Addr bufPtr = process->getSyscallArg(tc, index); 932 933 if (fd < 0) 934 return -EBADF; 935 936 struct statfs hostBuf; 937 int result = fstatfs(fd, &hostBuf); 938 939 if (result < 0) 940 return -errno; 941
|
941 OS::copyOutStatfsBuf(tc->getMemProxy(), bufPtr, &hostBuf);
| 942 OS::copyOutStatfsBuf(tc->getMemPort(), bufPtr, &hostBuf);
|
942 943 return 0; 944} 945 946 947/// Target writev() handler. 948template <class OS> 949SyscallReturn 950writevFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 951 ThreadContext *tc) 952{ 953 int index = 0; 954 int fd = process->getSyscallArg(tc, index); 955 if (fd < 0 || process->sim_fd(fd) < 0) { 956 // doesn't map to any simulator fd: not a valid target fd 957 return -EBADF; 958 } 959
| 943 944 return 0; 945} 946 947 948/// Target writev() handler. 949template <class OS> 950SyscallReturn 951writevFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 952 ThreadContext *tc) 953{ 954 int index = 0; 955 int fd = process->getSyscallArg(tc, index); 956 if (fd < 0 || process->sim_fd(fd) < 0) { 957 // doesn't map to any simulator fd: not a valid target fd 958 return -EBADF; 959 } 960
|
960 SETranslatingPortProxy *p = tc->getMemProxy();
| 961 TranslatingPort *p = tc->getMemPort();
|
961 uint64_t tiov_base = process->getSyscallArg(tc, index); 962 size_t count = process->getSyscallArg(tc, index); 963 struct iovec hiov[count]; 964 for (size_t i = 0; i < count; ++i) { 965 typename OS::tgt_iovec tiov; 966 967 p->readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec), 968 (uint8_t*)&tiov, sizeof(typename OS::tgt_iovec));
| 962 uint64_t tiov_base = process->getSyscallArg(tc, index); 963 size_t count = process->getSyscallArg(tc, index); 964 struct iovec hiov[count]; 965 for (size_t i = 0; i < count; ++i) { 966 typename OS::tgt_iovec tiov; 967 968 p->readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec), 969 (uint8_t*)&tiov, sizeof(typename OS::tgt_iovec));
|
969 hiov[i].iov_len = TheISA::gtoh(tiov.iov_len);
| 970 hiov[i].iov_len = gtoh(tiov.iov_len);
|
970 hiov[i].iov_base = new char [hiov[i].iov_len];
| 971 hiov[i].iov_base = new char [hiov[i].iov_len];
|
971 p->readBlob(TheISA::gtoh(tiov.iov_base), (uint8_t *)hiov[i].iov_base,
| 972 p->readBlob(gtoh(tiov.iov_base), (uint8_t *)hiov[i].iov_base,
|
972 hiov[i].iov_len); 973 } 974 975 int result = writev(process->sim_fd(fd), hiov, count); 976 977 for (size_t i = 0; i < count; ++i) 978 delete [] (char *)hiov[i].iov_base; 979 980 if (result < 0) 981 return -errno; 982 983 return 0; 984} 985 986 987/// Target mmap() handler. 988/// 989/// We don't really handle mmap(). If the target is mmaping an 990/// anonymous region or /dev/zero, we can get away with doing basically 991/// nothing (since memory is initialized to zero and the simulator 992/// doesn't really check addresses anyway). 993/// 994template <class OS> 995SyscallReturn 996mmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 997{ 998 int index = 0; 999 Addr start = p->getSyscallArg(tc, index); 1000 uint64_t length = p->getSyscallArg(tc, index); 1001 index++; // int prot = p->getSyscallArg(tc, index); 1002 int flags = p->getSyscallArg(tc, index); 1003 int tgt_fd = p->getSyscallArg(tc, index); 1004 // int offset = p->getSyscallArg(tc, index); 1005 1006 if (!(flags & OS::TGT_MAP_ANONYMOUS)) { 1007 Process::FdMap *fd_map = p->sim_fd_obj(tgt_fd); 1008 if (!fd_map || fd_map->fd < 0) { 1009 warn("mmap failing: target fd %d is not valid\n", tgt_fd); 1010 return -EBADF; 1011 } 1012 1013 if (fd_map->filename != "/dev/zero") { 1014 // This is very likely broken, but leave a warning here 1015 // (rather than panic) in case /dev/zero is known by 1016 // another name on some platform 1017 warn("allowing mmap of file %s; mmap not supported on files" 1018 " other than /dev/zero\n", fd_map->filename); 1019 } 1020 } 1021 1022 if ((start % TheISA::VMPageSize) != 0 || 1023 (length % TheISA::VMPageSize) != 0) { 1024 warn("mmap failing: arguments not page-aligned: " 1025 "start 0x%x length 0x%x", 1026 start, length); 1027 return -EINVAL; 1028 } 1029
| 973 hiov[i].iov_len); 974 } 975 976 int result = writev(process->sim_fd(fd), hiov, count); 977 978 for (size_t i = 0; i < count; ++i) 979 delete [] (char *)hiov[i].iov_base; 980 981 if (result < 0) 982 return -errno; 983 984 return 0; 985} 986 987 988/// Target mmap() handler. 989/// 990/// We don't really handle mmap(). If the target is mmaping an 991/// anonymous region or /dev/zero, we can get away with doing basically 992/// nothing (since memory is initialized to zero and the simulator 993/// doesn't really check addresses anyway). 994/// 995template <class OS> 996SyscallReturn 997mmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 998{ 999 int index = 0; 1000 Addr start = p->getSyscallArg(tc, index); 1001 uint64_t length = p->getSyscallArg(tc, index); 1002 index++; // int prot = p->getSyscallArg(tc, index); 1003 int flags = p->getSyscallArg(tc, index); 1004 int tgt_fd = p->getSyscallArg(tc, index); 1005 // int offset = p->getSyscallArg(tc, index); 1006 1007 if (!(flags & OS::TGT_MAP_ANONYMOUS)) { 1008 Process::FdMap *fd_map = p->sim_fd_obj(tgt_fd); 1009 if (!fd_map || fd_map->fd < 0) { 1010 warn("mmap failing: target fd %d is not valid\n", tgt_fd); 1011 return -EBADF; 1012 } 1013 1014 if (fd_map->filename != "/dev/zero") { 1015 // This is very likely broken, but leave a warning here 1016 // (rather than panic) in case /dev/zero is known by 1017 // another name on some platform 1018 warn("allowing mmap of file %s; mmap not supported on files" 1019 " other than /dev/zero\n", fd_map->filename); 1020 } 1021 } 1022 1023 if ((start % TheISA::VMPageSize) != 0 || 1024 (length % TheISA::VMPageSize) != 0) { 1025 warn("mmap failing: arguments not page-aligned: " 1026 "start 0x%x length 0x%x", 1027 start, length); 1028 return -EINVAL; 1029 } 1030
|
1030 // are we ok with clobbering existing mappings? only set this to 1031 // true if the user has been warned. 1032 bool clobber = false; 1033 1034 // try to use the caller-provided address if there is one 1035 bool use_provided_address = (start != 0); 1036 1037 if (use_provided_address) { 1038 // check to see if the desired address is already in use 1039 if (!p->pTable->isUnmapped(start, length)) { 1040 // there are existing mappings in the desired range 1041 // whether we clobber them or not depends on whether the caller 1042 // specified MAP_FIXED 1043 if (flags & OS::TGT_MAP_FIXED) { 1044 // MAP_FIXED specified: clobber existing mappings 1045 warn("mmap: MAP_FIXED at 0x%x overwrites existing mappings\n", 1046 start); 1047 clobber = true; 1048 } else { 1049 // MAP_FIXED not specified: ignore suggested start address 1050 warn("mmap: ignoring suggested map address 0x%x\n", start); 1051 use_provided_address = false; 1052 } 1053 }
| 1031 if (start != 0) { 1032 warn("mmap: ignoring suggested map address 0x%x, using 0x%x", 1033 start, p->mmap_end);
|
1054 } 1055
| 1034 } 1035
|
1056 if (!use_provided_address) { 1057 // no address provided, or provided address unusable: 1058 // pick next address from our "mmap region" 1059 if (OS::mmapGrowsDown()) { 1060 start = p->mmap_end - length; 1061 p->mmap_end = start; 1062 } else { 1063 start = p->mmap_end; 1064 p->mmap_end += length; 1065 }
| 1036 // pick next address from our "mmap region" 1037 if (OS::mmapGrowsDown()) { 1038 start = p->mmap_end - length; 1039 p->mmap_end = start; 1040 } else { 1041 start = p->mmap_end; 1042 p->mmap_end += length;
|
1066 }
| 1043 }
|
| 1044 p->pTable->allocate(start, length);
|
1067
| 1045
|
1068 p->allocateMem(start, length, clobber); 1069
| |
1070 return start; 1071} 1072 1073/// Target getrlimit() handler. 1074template <class OS> 1075SyscallReturn 1076getrlimitFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 1077 ThreadContext *tc) 1078{ 1079 int index = 0; 1080 unsigned resource = process->getSyscallArg(tc, index); 1081 TypedBufferArg<typename OS::rlimit> rlp(process->getSyscallArg(tc, index)); 1082 1083 switch (resource) { 1084 case OS::TGT_RLIMIT_STACK: 1085 // max stack size in bytes: make up a number (8MB for now) 1086 rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
| 1046 return start; 1047} 1048 1049/// Target getrlimit() handler. 1050template <class OS> 1051SyscallReturn 1052getrlimitFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 1053 ThreadContext *tc) 1054{ 1055 int index = 0; 1056 unsigned resource = process->getSyscallArg(tc, index); 1057 TypedBufferArg<typename OS::rlimit> rlp(process->getSyscallArg(tc, index)); 1058 1059 switch (resource) { 1060 case OS::TGT_RLIMIT_STACK: 1061 // max stack size in bytes: make up a number (8MB for now) 1062 rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
|
1087 rlp->rlim_cur = TheISA::htog(rlp->rlim_cur); 1088 rlp->rlim_max = TheISA::htog(rlp->rlim_max);
| 1063 rlp->rlim_cur = htog(rlp->rlim_cur); 1064 rlp->rlim_max = htog(rlp->rlim_max);
|
1089 break; 1090 1091 case OS::TGT_RLIMIT_DATA: 1092 // max data segment size in bytes: make up a number 1093 rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024;
| 1065 break; 1066 1067 case OS::TGT_RLIMIT_DATA: 1068 // max data segment size in bytes: make up a number 1069 rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024;
|
1094 rlp->rlim_cur = TheISA::htog(rlp->rlim_cur); 1095 rlp->rlim_max = TheISA::htog(rlp->rlim_max);
| 1070 rlp->rlim_cur = htog(rlp->rlim_cur); 1071 rlp->rlim_max = htog(rlp->rlim_max);
|
1096 break; 1097 1098 default: 1099 std::cerr << "getrlimitFunc: unimplemented resource " << resource 1100 << std::endl; 1101 abort(); 1102 break; 1103 } 1104
| 1072 break; 1073 1074 default: 1075 std::cerr << "getrlimitFunc: unimplemented resource " << resource 1076 << std::endl; 1077 abort(); 1078 break; 1079 } 1080
|
1105 rlp.copyOut(tc->getMemProxy());
| 1081 rlp.copyOut(tc->getMemPort());
|
1106 return 0; 1107} 1108 1109/// Target gettimeofday() handler. 1110template <class OS> 1111SyscallReturn 1112gettimeofdayFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 1113 ThreadContext *tc) 1114{ 1115 int index = 0; 1116 TypedBufferArg<typename OS::timeval> tp(process->getSyscallArg(tc, index)); 1117 1118 getElapsedTime(tp->tv_sec, tp->tv_usec); 1119 tp->tv_sec += seconds_since_epoch; 1120 tp->tv_sec = TheISA::htog(tp->tv_sec); 1121 tp->tv_usec = TheISA::htog(tp->tv_usec); 1122
| 1082 return 0; 1083} 1084 1085/// Target gettimeofday() handler. 1086template <class OS> 1087SyscallReturn 1088gettimeofdayFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 1089 ThreadContext *tc) 1090{ 1091 int index = 0; 1092 TypedBufferArg<typename OS::timeval> tp(process->getSyscallArg(tc, index)); 1093 1094 getElapsedTime(tp->tv_sec, tp->tv_usec); 1095 tp->tv_sec += seconds_since_epoch; 1096 tp->tv_sec = TheISA::htog(tp->tv_sec); 1097 tp->tv_usec = TheISA::htog(tp->tv_usec); 1098
|
1123 tp.copyOut(tc->getMemProxy());
| 1099 tp.copyOut(tc->getMemPort());
|
1124 1125 return 0; 1126} 1127 1128 1129/// Target utimes() handler. 1130template <class OS> 1131SyscallReturn 1132utimesFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 1133 ThreadContext *tc) 1134{ 1135 std::string path; 1136 1137 int index = 0;
| 1100 1101 return 0; 1102} 1103 1104 1105/// Target utimes() handler. 1106template <class OS> 1107SyscallReturn 1108utimesFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 1109 ThreadContext *tc) 1110{ 1111 std::string path; 1112 1113 int index = 0;
|
1138 if (!tc->getMemProxy()->tryReadString(path,
| 1114 if (!tc->getMemPort()->tryReadString(path,
|
1139 process->getSyscallArg(tc, index))) { 1140 return -EFAULT; 1141 } 1142 1143 TypedBufferArg<typename OS::timeval [2]> 1144 tp(process->getSyscallArg(tc, index));
| 1115 process->getSyscallArg(tc, index))) { 1116 return -EFAULT; 1117 } 1118 1119 TypedBufferArg<typename OS::timeval [2]> 1120 tp(process->getSyscallArg(tc, index));
|
1145 tp.copyIn(tc->getMemProxy());
| 1121 tp.copyIn(tc->getMemPort());
|
1146 1147 struct timeval hostTimeval[2]; 1148 for (int i = 0; i < 2; ++i) 1149 {
| 1122 1123 struct timeval hostTimeval[2]; 1124 for (int i = 0; i < 2; ++i) 1125 {
|
1150 hostTimeval[i].tv_sec = TheISA::gtoh((*tp)[i].tv_sec); 1151 hostTimeval[i].tv_usec = TheISA::gtoh((*tp)[i].tv_usec);
| 1126 hostTimeval[i].tv_sec = gtoh((*tp)[i].tv_sec); 1127 hostTimeval[i].tv_usec = gtoh((*tp)[i].tv_usec);
|
1152 } 1153 1154 // Adjust path for current working directory 1155 path = process->fullPath(path); 1156 1157 int result = utimes(path.c_str(), hostTimeval); 1158 1159 if (result < 0) 1160 return -errno; 1161 1162 return 0; 1163} 1164/// Target getrusage() function. 1165template <class OS> 1166SyscallReturn 1167getrusageFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 1168 ThreadContext *tc) 1169{ 1170 int index = 0; 1171 int who = process->getSyscallArg(tc, index); // THREAD, SELF, or CHILDREN 1172 TypedBufferArg<typename OS::rusage> rup(process->getSyscallArg(tc, index)); 1173 1174 rup->ru_utime.tv_sec = 0; 1175 rup->ru_utime.tv_usec = 0; 1176 rup->ru_stime.tv_sec = 0; 1177 rup->ru_stime.tv_usec = 0; 1178 rup->ru_maxrss = 0; 1179 rup->ru_ixrss = 0; 1180 rup->ru_idrss = 0; 1181 rup->ru_isrss = 0; 1182 rup->ru_minflt = 0; 1183 rup->ru_majflt = 0; 1184 rup->ru_nswap = 0; 1185 rup->ru_inblock = 0; 1186 rup->ru_oublock = 0; 1187 rup->ru_msgsnd = 0; 1188 rup->ru_msgrcv = 0; 1189 rup->ru_nsignals = 0; 1190 rup->ru_nvcsw = 0; 1191 rup->ru_nivcsw = 0; 1192 1193 switch (who) { 1194 case OS::TGT_RUSAGE_SELF: 1195 getElapsedTime(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec);
| 1128 } 1129 1130 // Adjust path for current working directory 1131 path = process->fullPath(path); 1132 1133 int result = utimes(path.c_str(), hostTimeval); 1134 1135 if (result < 0) 1136 return -errno; 1137 1138 return 0; 1139} 1140/// Target getrusage() function. 1141template <class OS> 1142SyscallReturn 1143getrusageFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 1144 ThreadContext *tc) 1145{ 1146 int index = 0; 1147 int who = process->getSyscallArg(tc, index); // THREAD, SELF, or CHILDREN 1148 TypedBufferArg<typename OS::rusage> rup(process->getSyscallArg(tc, index)); 1149 1150 rup->ru_utime.tv_sec = 0; 1151 rup->ru_utime.tv_usec = 0; 1152 rup->ru_stime.tv_sec = 0; 1153 rup->ru_stime.tv_usec = 0; 1154 rup->ru_maxrss = 0; 1155 rup->ru_ixrss = 0; 1156 rup->ru_idrss = 0; 1157 rup->ru_isrss = 0; 1158 rup->ru_minflt = 0; 1159 rup->ru_majflt = 0; 1160 rup->ru_nswap = 0; 1161 rup->ru_inblock = 0; 1162 rup->ru_oublock = 0; 1163 rup->ru_msgsnd = 0; 1164 rup->ru_msgrcv = 0; 1165 rup->ru_nsignals = 0; 1166 rup->ru_nvcsw = 0; 1167 rup->ru_nivcsw = 0; 1168 1169 switch (who) { 1170 case OS::TGT_RUSAGE_SELF: 1171 getElapsedTime(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec);
|
1196 rup->ru_utime.tv_sec = TheISA::htog(rup->ru_utime.tv_sec); 1197 rup->ru_utime.tv_usec = TheISA::htog(rup->ru_utime.tv_usec);
| 1172 rup->ru_utime.tv_sec = htog(rup->ru_utime.tv_sec); 1173 rup->ru_utime.tv_usec = htog(rup->ru_utime.tv_usec);
|
1198 break; 1199 1200 case OS::TGT_RUSAGE_CHILDREN: 1201 // do nothing. We have no child processes, so they take no time. 1202 break; 1203 1204 default: 1205 // don't really handle THREAD or CHILDREN, but just warn and 1206 // plow ahead 1207 warn("getrusage() only supports RUSAGE_SELF. Parameter %d ignored.", 1208 who); 1209 } 1210
| 1174 break; 1175 1176 case OS::TGT_RUSAGE_CHILDREN: 1177 // do nothing. We have no child processes, so they take no time. 1178 break; 1179 1180 default: 1181 // don't really handle THREAD or CHILDREN, but just warn and 1182 // plow ahead 1183 warn("getrusage() only supports RUSAGE_SELF. Parameter %d ignored.", 1184 who); 1185 } 1186
|
1211 rup.copyOut(tc->getMemProxy());
| 1187 rup.copyOut(tc->getMemPort());
|
1212 1213 return 0; 1214} 1215 1216/// Target times() function. 1217template <class OS> 1218SyscallReturn 1219timesFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 1220 ThreadContext *tc) 1221{ 1222 int index = 0; 1223 TypedBufferArg<typename OS::tms> bufp(process->getSyscallArg(tc, index)); 1224 1225 // Fill in the time structure (in clocks) 1226 int64_t clocks = curTick() * OS::M5_SC_CLK_TCK / SimClock::Int::s; 1227 bufp->tms_utime = clocks; 1228 bufp->tms_stime = 0; 1229 bufp->tms_cutime = 0; 1230 bufp->tms_cstime = 0; 1231 1232 // Convert to host endianness
| 1188 1189 return 0; 1190} 1191 1192/// Target times() function. 1193template <class OS> 1194SyscallReturn 1195timesFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 1196 ThreadContext *tc) 1197{ 1198 int index = 0; 1199 TypedBufferArg<typename OS::tms> bufp(process->getSyscallArg(tc, index)); 1200 1201 // Fill in the time structure (in clocks) 1202 int64_t clocks = curTick() * OS::M5_SC_CLK_TCK / SimClock::Int::s; 1203 bufp->tms_utime = clocks; 1204 bufp->tms_stime = 0; 1205 bufp->tms_cutime = 0; 1206 bufp->tms_cstime = 0; 1207 1208 // Convert to host endianness
|
1233 bufp->tms_utime = TheISA::htog(bufp->tms_utime);
| 1209 bufp->tms_utime = htog(bufp->tms_utime);
|
1234 1235 // Write back
| 1210 1211 // Write back
|
1236 bufp.copyOut(tc->getMemProxy());
| 1212 bufp.copyOut(tc->getMemPort());
|
1237 1238 // Return clock ticks since system boot 1239 return clocks; 1240} 1241 1242/// Target time() function. 1243template <class OS> 1244SyscallReturn 1245timeFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 1246 ThreadContext *tc) 1247{ 1248 typename OS::time_t sec, usec; 1249 getElapsedTime(sec, usec); 1250 sec += seconds_since_epoch; 1251 1252 int index = 0; 1253 Addr taddr = (Addr)process->getSyscallArg(tc, index); 1254 if(taddr != 0) { 1255 typename OS::time_t t = sec;
| 1213 1214 // Return clock ticks since system boot 1215 return clocks; 1216} 1217 1218/// Target time() function. 1219template <class OS> 1220SyscallReturn 1221timeFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 1222 ThreadContext *tc) 1223{ 1224 typename OS::time_t sec, usec; 1225 getElapsedTime(sec, usec); 1226 sec += seconds_since_epoch; 1227 1228 int index = 0; 1229 Addr taddr = (Addr)process->getSyscallArg(tc, index); 1230 if(taddr != 0) { 1231 typename OS::time_t t = sec;
|
1256 t = TheISA::htog(t); 1257 SETranslatingPortProxy *p = tc->getMemProxy();
| 1232 t = htog(t); 1233 TranslatingPort *p = tc->getMemPort();
|
1258 p->writeBlob(taddr, (uint8_t*)&t, (int)sizeof(typename OS::time_t)); 1259 } 1260 return sec; 1261} 1262 1263 1264#endif // __SIM_SYSCALL_EMUL_HH__
| 1234 p->writeBlob(taddr, (uint8_t*)&t, (int)sizeof(typename OS::time_t)); 1235 } 1236 return sec; 1237} 1238 1239 1240#endif // __SIM_SYSCALL_EMUL_HH__
|