syscall_emul.hh revision 2238
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#ifndef __SIM_SYSCALL_EMUL_HH__ 30#define __SIM_SYSCALL_EMUL_HH__ 31 32#define BSD_HOST (defined(__APPLE__) || defined(__OpenBSD__) || \ 33 defined(__FreeBSD__)) 34 35/// 36/// @file syscall_emul.hh 37/// 38/// This file defines objects used to emulate syscalls from the target 39/// application on the host machine. 40 41#include <errno.h> 42#include <string> 43#ifdef __CYGWIN32__ 44#include <sys/fcntl.h> // for O_BINARY 45#endif 46#include <sys/uio.h> 47 48#include "base/intmath.hh" // for RoundUp 49#include "mem/functional/functional.hh" 50#include "arch/isa_traits.hh" // for Addr 51 52#include "base/trace.hh" 53#include "cpu/exec_context.hh" 54#include "sim/process.hh" 55 56/// 57/// System call descriptor. 58/// 59class SyscallDesc { 60 61 public: 62 63 /// Typedef for target syscall handler functions. 64 typedef SyscallReturn (*FuncPtr)(SyscallDesc *, int num, 65 Process *, ExecContext *); 66 67 const char *name; //!< Syscall name (e.g., "open"). 68 FuncPtr funcPtr; //!< Pointer to emulation function. 69 int flags; //!< Flags (see Flags enum). 70 71 /// Flag values for controlling syscall behavior. 72 enum Flags { 73 /// Don't set return regs according to funcPtr return value. 74 /// Used for syscalls with non-standard return conventions 75 /// that explicitly set the ExecContext regs (e.g., 76 /// sigreturn). 77 SuppressReturnValue = 1 78 }; 79 80 /// Constructor. 81 SyscallDesc(const char *_name, FuncPtr _funcPtr, int _flags = 0) 82 : name(_name), funcPtr(_funcPtr), flags(_flags) 83 { 84 } 85 86 /// Emulate the syscall. Public interface for calling through funcPtr. 87 void doSyscall(int callnum, Process *proc, ExecContext *xc); 88}; 89 90 91class BaseBufferArg { 92 93 public: 94 95 BaseBufferArg(Addr _addr, int _size) : addr(_addr), size(_size) 96 { 97 bufPtr = new uint8_t[size]; 98 // clear out buffer: in case we only partially populate this, 99 // and then do a copyOut(), we want to make sure we don't 100 // introduce any random junk into the simulated address space 101 memset(bufPtr, 0, size); 102 } 103 104 virtual ~BaseBufferArg() { delete [] bufPtr; } 105 106 // 107 // copy data into simulator space (read from target memory) 108 // 109 virtual bool copyIn(FunctionalMemory *mem) 110 { 111 mem->access(Read, addr, bufPtr, size); 112 return true; // no EFAULT detection for now 113 } 114 115 // 116 // copy data out of simulator space (write to target memory) 117 // 118 virtual bool copyOut(FunctionalMemory *mem) 119 { 120 mem->access(Write, addr, bufPtr, size); 121 return true; // no EFAULT detection for now 122 } 123 124 protected: 125 Addr addr; 126 int size; 127 uint8_t *bufPtr; 128}; 129 130 131class BufferArg : public BaseBufferArg 132{ 133 public: 134 BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { } 135 void *bufferPtr() { return bufPtr; } 136}; 137 138template <class T> 139class TypedBufferArg : public BaseBufferArg 140{ 141 public: 142 // user can optionally specify a specific number of bytes to 143 // allocate to deal with those structs that have variable-size 144 // arrays at the end 145 TypedBufferArg(Addr _addr, int _size = sizeof(T)) 146 : BaseBufferArg(_addr, _size) 147 { } 148 149 // type case 150 operator T*() { return (T *)bufPtr; } 151 152 // dereference operators 153 T &operator*() { return *((T *)bufPtr); } 154 T* operator->() { return (T *)bufPtr; } 155 T &operator[](int i) { return ((T *)bufPtr)[i]; } 156}; 157 158////////////////////////////////////////////////////////////////////// 159// 160// The following emulation functions are generic enough that they 161// don't need to be recompiled for different emulated OS's. They are 162// defined in sim/syscall_emul.cc. 163// 164////////////////////////////////////////////////////////////////////// 165 166 167/// Handler for unimplemented syscalls that we haven't thought about. 168SyscallReturn unimplementedFunc(SyscallDesc *desc, int num, 169 Process *p, ExecContext *xc); 170 171/// Handler for unimplemented syscalls that we never intend to 172/// implement (signal handling, etc.) and should not affect the correct 173/// behavior of the program. Print a warning only if the appropriate 174/// trace flag is enabled. Return success to the target program. 175SyscallReturn ignoreFunc(SyscallDesc *desc, int num, 176 Process *p, ExecContext *xc); 177 178/// Target exit() handler: terminate simulation. 179SyscallReturn exitFunc(SyscallDesc *desc, int num, 180 Process *p, ExecContext *xc); 181 182/// Target getpagesize() handler. 183SyscallReturn getpagesizeFunc(SyscallDesc *desc, int num, 184 Process *p, ExecContext *xc); 185 186/// Target obreak() handler: set brk address. 187SyscallReturn obreakFunc(SyscallDesc *desc, int num, 188 Process *p, ExecContext *xc); 189 190/// Target close() handler. 191SyscallReturn closeFunc(SyscallDesc *desc, int num, 192 Process *p, ExecContext *xc); 193 194/// Target read() handler. 195SyscallReturn readFunc(SyscallDesc *desc, int num, 196 Process *p, ExecContext *xc); 197 198/// Target write() handler. 199SyscallReturn writeFunc(SyscallDesc *desc, int num, 200 Process *p, ExecContext *xc); 201 202/// Target lseek() handler. 203SyscallReturn lseekFunc(SyscallDesc *desc, int num, 204 Process *p, ExecContext *xc); 205 206/// Target munmap() handler. 207SyscallReturn munmapFunc(SyscallDesc *desc, int num, 208 Process *p, ExecContext *xc); 209 210/// Target gethostname() handler. 211SyscallReturn gethostnameFunc(SyscallDesc *desc, int num, 212 Process *p, ExecContext *xc); 213 214/// Target unlink() handler. 215SyscallReturn unlinkFunc(SyscallDesc *desc, int num, 216 Process *p, ExecContext *xc); 217 218/// Target rename() handler. 219SyscallReturn renameFunc(SyscallDesc *desc, int num, 220 Process *p, ExecContext *xc); 221 222 223/// Target truncate() handler. 224SyscallReturn truncateFunc(SyscallDesc *desc, int num, 225 Process *p, ExecContext *xc); 226 227 228/// Target ftruncate() handler. 229SyscallReturn ftruncateFunc(SyscallDesc *desc, int num, 230 Process *p, ExecContext *xc); 231 232 233/// Target chown() handler. 234SyscallReturn chownFunc(SyscallDesc *desc, int num, 235 Process *p, ExecContext *xc); 236 237 238/// Target fchown() handler. 239SyscallReturn fchownFunc(SyscallDesc *desc, int num, 240 Process *p, ExecContext *xc); 241 242/// Target fnctl() handler. 243SyscallReturn fcntlFunc(SyscallDesc *desc, int num, 244 Process *process, ExecContext *xc); 245 246/// Target setuid() handler. 247SyscallReturn setuidFunc(SyscallDesc *desc, int num, 248 Process *p, ExecContext *xc); 249 250/// Target getpid() handler. 251SyscallReturn getpidFunc(SyscallDesc *desc, int num, 252 Process *p, ExecContext *xc); 253 254/// Target getuid() handler. 255SyscallReturn getuidFunc(SyscallDesc *desc, int num, 256 Process *p, ExecContext *xc); 257 258/// Target getgid() handler. 259SyscallReturn getgidFunc(SyscallDesc *desc, int num, 260 Process *p, ExecContext *xc); 261 262/// Target getppid() handler. 263SyscallReturn getppidFunc(SyscallDesc *desc, int num, 264 Process *p, ExecContext *xc); 265 266/// Target geteuid() handler. 267SyscallReturn geteuidFunc(SyscallDesc *desc, int num, 268 Process *p, ExecContext *xc); 269 270/// Target getegid() handler. 271SyscallReturn getegidFunc(SyscallDesc *desc, int num, 272 Process *p, ExecContext *xc); 273 274 275 276/// Pseudo Funcs - These functions use a different return convension, 277/// returning a second value in a register other than the normal return register 278SyscallReturn pipePseudoFunc(SyscallDesc *desc, int num, 279 Process *process, ExecContext *xc); 280 281/// Target getpidPseudo() handler. 282SyscallReturn getpidPseudoFunc(SyscallDesc *desc, int num, 283 Process *p, ExecContext *xc); 284 285/// Target getuidPseudo() handler. 286SyscallReturn getuidPseudoFunc(SyscallDesc *desc, int num, 287 Process *p, ExecContext *xc); 288 289/// Target getgidPseudo() handler. 290SyscallReturn getgidPseudoFunc(SyscallDesc *desc, int num, 291 Process *p, ExecContext *xc); 292 293 294/// This struct is used to build an target-OS-dependent table that 295/// maps the target's open() flags to the host open() flags. 296struct OpenFlagTransTable { 297 int tgtFlag; //!< Target system flag value. 298 int hostFlag; //!< Corresponding host system flag value. 299}; 300 301 302 303/// A readable name for 1,000,000, for converting microseconds to seconds. 304const int one_million = 1000000; 305 306/// Approximate seconds since the epoch (1/1/1970). About a billion, 307/// by my reckoning. We want to keep this a constant (not use the 308/// real-world time) to keep simulations repeatable. 309const unsigned seconds_since_epoch = 1000000000; 310 311/// Helper function to convert current elapsed time to seconds and 312/// microseconds. 313template <class T1, class T2> 314void 315getElapsedTime(T1 &sec, T2 &usec) 316{ 317 int elapsed_usecs = curTick / Clock::Int::us; 318 sec = elapsed_usecs / one_million; 319 usec = elapsed_usecs % one_million; 320} 321 322////////////////////////////////////////////////////////////////////// 323// 324// The following emulation functions are generic, but need to be 325// templated to account for differences in types, constants, etc. 326// 327////////////////////////////////////////////////////////////////////// 328 329/// Target ioctl() handler. For the most part, programs call ioctl() 330/// only to find out if their stdout is a tty, to determine whether to 331/// do line or block buffering. 332template <class OS> 333SyscallReturn 334ioctlFunc(SyscallDesc *desc, int callnum, Process *process, 335 ExecContext *xc) 336{ 337 int fd = xc->getSyscallArg(0); 338 unsigned req = xc->getSyscallArg(1); 339 340 DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req); 341 342 if (fd < 0 || process->sim_fd(fd) < 0) { 343 // doesn't map to any simulator fd: not a valid target fd 344 return -EBADF; 345 } 346 347 switch (req) { 348 case OS::TIOCISATTY: 349 case OS::TIOCGETP: 350 case OS::TIOCSETP: 351 case OS::TIOCSETN: 352 case OS::TIOCSETC: 353 case OS::TIOCGETC: 354 case OS::TIOCGETS: 355 case OS::TIOCGETA: 356 return -ENOTTY; 357 358 default: 359 fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ 0x%llx\n", 360 fd, req, xc->readPC()); 361 } 362} 363 364/// Target open() handler. 365template <class OS> 366SyscallReturn 367openFunc(SyscallDesc *desc, int callnum, Process *process, 368 ExecContext *xc) 369{ 370 std::string path; 371 372 if (xc->mem->readString(path, xc->getSyscallArg(0)) != NoFault) 373 return -EFAULT; 374 375 if (path == "/dev/sysdev0") { 376 // This is a memory-mapped high-resolution timer device on Alpha. 377 // We don't support it, so just punt. 378 warn("Ignoring open(%s, ...)\n", path); 379 return -ENOENT; 380 } 381 382 int tgtFlags = xc->getSyscallArg(1); 383 int mode = xc->getSyscallArg(2); 384 int hostFlags = 0; 385 386 // translate open flags 387 for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) { 388 if (tgtFlags & OS::openFlagTable[i].tgtFlag) { 389 tgtFlags &= ~OS::openFlagTable[i].tgtFlag; 390 hostFlags |= OS::openFlagTable[i].hostFlag; 391 } 392 } 393 394 // any target flags left? 395 if (tgtFlags != 0) 396 warn("Syscall: open: cannot decode flags 0x%x", tgtFlags); 397 398#ifdef __CYGWIN32__ 399 hostFlags |= O_BINARY; 400#endif 401 402 DPRINTF(SyscallVerbose, "opening file %s\n", path.c_str()); 403 404 // open the file 405 int fd = open(path.c_str(), hostFlags, mode); 406 407 return (fd == -1) ? -errno : process->alloc_fd(fd); 408} 409 410 411/// Target chmod() handler. 412template <class OS> 413SyscallReturn 414chmodFunc(SyscallDesc *desc, int callnum, Process *process, 415 ExecContext *xc) 416{ 417 std::string path; 418 419 if (xc->mem->readString(path, xc->getSyscallArg(0)) != NoFault) 420 return -EFAULT; 421 422 uint32_t mode = xc->getSyscallArg(1); 423 mode_t hostMode = 0; 424 425 // XXX translate mode flags via OS::something??? 426 hostMode = mode; 427 428 // do the chmod 429 int result = chmod(path.c_str(), hostMode); 430 if (result < 0) 431 return -errno; 432 433 return 0; 434} 435 436 437/// Target fchmod() handler. 438template <class OS> 439SyscallReturn 440fchmodFunc(SyscallDesc *desc, int callnum, Process *process, 441 ExecContext *xc) 442{ 443 int fd = xc->getSyscallArg(0); 444 if (fd < 0 || process->sim_fd(fd) < 0) { 445 // doesn't map to any simulator fd: not a valid target fd 446 return -EBADF; 447 } 448 449 uint32_t mode = xc->getSyscallArg(1); 450 mode_t hostMode = 0; 451 452 // XXX translate mode flags via OS::someting??? 453 hostMode = mode; 454 455 // do the fchmod 456 int result = fchmod(process->sim_fd(fd), hostMode); 457 if (result < 0) 458 return -errno; 459 460 return 0; 461} 462 463 464/// Target stat() handler. 465template <class OS> 466SyscallReturn 467statFunc(SyscallDesc *desc, int callnum, Process *process, 468 ExecContext *xc) 469{ 470 std::string path; 471 472 if (xc->mem->readString(path, xc->getSyscallArg(0)) != NoFault) 473 return -EFAULT; 474 475 struct stat hostBuf; 476 int result = stat(path.c_str(), &hostBuf); 477 478 if (result < 0) 479 return -errno; 480 481 OS::copyOutStatBuf(xc->mem, xc->getSyscallArg(1), &hostBuf); 482 483 return 0; 484} 485 486 487/// Target fstat64() handler. 488template <class OS> 489SyscallReturn 490fstat64Func(SyscallDesc *desc, int callnum, Process *process, 491 ExecContext *xc) 492{ 493 int fd = xc->getSyscallArg(0); 494 if (fd < 0 || process->sim_fd(fd) < 0) { 495 // doesn't map to any simulator fd: not a valid target fd 496 return -EBADF; 497 } 498 499#if BSD_HOST 500 struct stat hostBuf; 501 int result = fstat(process->sim_fd(fd), &hostBuf); 502#else 503 struct stat64 hostBuf; 504 int result = fstat64(process->sim_fd(fd), &hostBuf); 505#endif 506 507 if (result < 0) 508 return -errno; 509 510 OS::copyOutStat64Buf(xc->mem, fd, xc->getSyscallArg(1), &hostBuf); 511 512 return 0; 513} 514 515 516/// Target lstat() handler. 517template <class OS> 518SyscallReturn 519lstatFunc(SyscallDesc *desc, int callnum, Process *process, 520 ExecContext *xc) 521{ 522 std::string path; 523 524 if (xc->mem->readString(path, xc->getSyscallArg(0)) != NoFault) 525 return -EFAULT; 526 527 struct stat hostBuf; 528 int result = lstat(path.c_str(), &hostBuf); 529 530 if (result < 0) 531 return -errno; 532 533 OS::copyOutStatBuf(xc->mem, xc->getSyscallArg(1), &hostBuf); 534 535 return 0; 536} 537 538/// Target lstat64() handler. 539template <class OS> 540SyscallReturn 541lstat64Func(SyscallDesc *desc, int callnum, Process *process, 542 ExecContext *xc) 543{ 544 std::string path; 545 546 if (xc->mem->readString(path, xc->getSyscallArg(0)) != NoFault) 547 return -EFAULT; 548 549#if BSD_HOST 550 struct stat hostBuf; 551 int result = lstat(path.c_str(), &hostBuf); 552#else 553 struct stat64 hostBuf; 554 int result = lstat64(path.c_str(), &hostBuf); 555#endif 556 557 if (result < 0) 558 return -errno; 559 560 OS::copyOutStat64Buf(xc->mem, -1, xc->getSyscallArg(1), &hostBuf); 561 562 return 0; 563} 564 565/// Target fstat() handler. 566template <class OS> 567SyscallReturn 568fstatFunc(SyscallDesc *desc, int callnum, Process *process, 569 ExecContext *xc) 570{ 571 int fd = process->sim_fd(xc->getSyscallArg(0)); 572 573 DPRINTF(SyscallVerbose, "fstat(%d, ...)\n", fd); 574 575 if (fd < 0) 576 return -EBADF; 577 578 struct stat hostBuf; 579 int result = fstat(fd, &hostBuf); 580 581 if (result < 0) 582 return -errno; 583 584 OS::copyOutStatBuf(xc->mem, xc->getSyscallArg(1), &hostBuf); 585 return 0; 586} 587 588 589/// Target statfs() handler. 590template <class OS> 591SyscallReturn 592statfsFunc(SyscallDesc *desc, int callnum, Process *process, 593 ExecContext *xc) 594{ 595 std::string path; 596 597 if (xc->mem->readString(path, xc->getSyscallArg(0)) != NoFault) 598 return -EFAULT; 599 600 struct statfs hostBuf; 601 int result = statfs(path.c_str(), &hostBuf); 602 603 if (result < 0) 604 return -errno; 605 606 OS::copyOutStatfsBuf(xc->mem, xc->getSyscallArg(1), &hostBuf); 607 608 return 0; 609} 610 611 612/// Target fstatfs() handler. 613template <class OS> 614SyscallReturn 615fstatfsFunc(SyscallDesc *desc, int callnum, Process *process, 616 ExecContext *xc) 617{ 618 int fd = process->sim_fd(xc->getSyscallArg(0)); 619 620 if (fd < 0) 621 return -EBADF; 622 623 struct statfs hostBuf; 624 int result = fstatfs(fd, &hostBuf); 625 626 if (result < 0) 627 return -errno; 628 629 OS::copyOutStatfsBuf(xc->mem, xc->getSyscallArg(1), &hostBuf); 630 631 return 0; 632} 633 634 635/// Target writev() handler. 636template <class OS> 637SyscallReturn 638writevFunc(SyscallDesc *desc, int callnum, Process *process, 639 ExecContext *xc) 640{ 641 int fd = xc->getSyscallArg(0); 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 uint64_t tiov_base = xc->getSyscallArg(1); 648 size_t count = xc->getSyscallArg(2); 649 struct iovec hiov[count]; 650 for (int i = 0; i < count; ++i) 651 { 652 typename OS::tgt_iovec tiov; 653 xc->mem->access(Read, tiov_base + i*sizeof(typename OS::tgt_iovec), 654 &tiov, sizeof(typename OS::tgt_iovec)); 655 hiov[i].iov_len = gtoh(tiov.iov_len); 656 hiov[i].iov_base = new char [hiov[i].iov_len]; 657 xc->mem->access(Read, gtoh(tiov.iov_base), 658 hiov[i].iov_base, hiov[i].iov_len); 659 } 660 661 int result = writev(process->sim_fd(fd), hiov, count); 662 663 for (int i = 0; i < count; ++i) 664 { 665 delete [] (char *)hiov[i].iov_base; 666 } 667 668 if (result < 0) 669 return -errno; 670 671 return 0; 672} 673 674 675/// Target mmap() handler. 676/// 677/// We don't really handle mmap(). If the target is mmaping an 678/// anonymous region or /dev/zero, we can get away with doing basically 679/// nothing (since memory is initialized to zero and the simulator 680/// doesn't really check addresses anyway). Always print a warning, 681/// since this could be seriously broken if we're not mapping 682/// /dev/zero. 683// 684/// Someday we should explicitly check for /dev/zero in open, flag the 685/// file descriptor, and fail (or implement!) a non-anonymous mmap to 686/// anything else. 687template <class OS> 688SyscallReturn 689mmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) 690{ 691 Addr start = xc->getSyscallArg(0); 692 uint64_t length = xc->getSyscallArg(1); 693 // int prot = xc->getSyscallArg(2); 694 int flags = xc->getSyscallArg(3); 695 // int fd = p->sim_fd(xc->getSyscallArg(4)); 696 // int offset = xc->getSyscallArg(5); 697 698 if (start == 0) { 699 // user didn't give an address... pick one from our "mmap region" 700 start = p->mmap_end; 701 p->mmap_end += roundUp(length, TheISA::VMPageSize); 702 if (p->nxm_start != 0) { 703 //If we have an nxm space, make sure we haven't colided 704 assert(p->mmap_end < p->nxm_start); 705 } 706 } 707 708 if (!(flags & OS::TGT_MAP_ANONYMOUS)) { 709 warn("allowing mmap of file @ fd %d. " 710 "This will break if not /dev/zero.", xc->getSyscallArg(4)); 711 } 712 713 return start; 714} 715 716/// Target getrlimit() handler. 717template <class OS> 718SyscallReturn 719getrlimitFunc(SyscallDesc *desc, int callnum, Process *process, 720 ExecContext *xc) 721{ 722 unsigned resource = xc->getSyscallArg(0); 723 TypedBufferArg<typename OS::rlimit> rlp(xc->getSyscallArg(1)); 724 725 switch (resource) { 726 case OS::TGT_RLIMIT_STACK: 727 // max stack size in bytes: make up a number (2MB for now) 728 rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024; 729 rlp->rlim_cur = htog(rlp->rlim_cur); 730 rlp->rlim_max = htog(rlp->rlim_max); 731 break; 732 733 default: 734 std::cerr << "getrlimitFunc: unimplemented resource " << resource 735 << std::endl; 736 abort(); 737 break; 738 } 739 740 rlp.copyOut(xc->mem); 741 return 0; 742} 743 744/// Target gettimeofday() handler. 745template <class OS> 746SyscallReturn 747gettimeofdayFunc(SyscallDesc *desc, int callnum, Process *process, 748 ExecContext *xc) 749{ 750 TypedBufferArg<typename OS::timeval> tp(xc->getSyscallArg(0)); 751 752 getElapsedTime(tp->tv_sec, tp->tv_usec); 753 tp->tv_sec += seconds_since_epoch; 754 tp->tv_sec = htog(tp->tv_sec); 755 tp->tv_usec = htog(tp->tv_usec); 756 757 tp.copyOut(xc->mem); 758 759 return 0; 760} 761 762 763/// Target utimes() handler. 764template <class OS> 765SyscallReturn 766utimesFunc(SyscallDesc *desc, int callnum, Process *process, 767 ExecContext *xc) 768{ 769 std::string path; 770 771 if (xc->mem->readString(path, xc->getSyscallArg(0)) != NoFault) 772 return -EFAULT; 773 774 TypedBufferArg<typename OS::timeval [2]> tp(xc->getSyscallArg(1)); 775 tp.copyIn(xc->mem); 776 777 struct timeval hostTimeval[2]; 778 for (int i = 0; i < 2; ++i) 779 { 780 hostTimeval[i].tv_sec = gtoh((*tp)[i].tv_sec); 781 hostTimeval[i].tv_usec = gtoh((*tp)[i].tv_usec); 782 } 783 int result = utimes(path.c_str(), hostTimeval); 784 785 if (result < 0) 786 return -errno; 787 788 return 0; 789} 790/// Target getrusage() function. 791template <class OS> 792SyscallReturn 793getrusageFunc(SyscallDesc *desc, int callnum, Process *process, 794 ExecContext *xc) 795{ 796 int who = xc->getSyscallArg(0); // THREAD, SELF, or CHILDREN 797 TypedBufferArg<typename OS::rusage> rup(xc->getSyscallArg(1)); 798 799 if (who != OS::TGT_RUSAGE_SELF) { 800 // don't really handle THREAD or CHILDREN, but just warn and 801 // plow ahead 802 warn("getrusage() only supports RUSAGE_SELF. Parameter %d ignored.", 803 who); 804 } 805 806 getElapsedTime(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec); 807 rup->ru_utime.tv_sec = htog(rup->ru_utime.tv_sec); 808 rup->ru_utime.tv_usec = htog(rup->ru_utime.tv_usec); 809 810 rup->ru_stime.tv_sec = 0; 811 rup->ru_stime.tv_usec = 0; 812 rup->ru_maxrss = 0; 813 rup->ru_ixrss = 0; 814 rup->ru_idrss = 0; 815 rup->ru_isrss = 0; 816 rup->ru_minflt = 0; 817 rup->ru_majflt = 0; 818 rup->ru_nswap = 0; 819 rup->ru_inblock = 0; 820 rup->ru_oublock = 0; 821 rup->ru_msgsnd = 0; 822 rup->ru_msgrcv = 0; 823 rup->ru_nsignals = 0; 824 rup->ru_nvcsw = 0; 825 rup->ru_nivcsw = 0; 826 827 rup.copyOut(xc->mem); 828 829 return 0; 830} 831 832#endif // __SIM_SYSCALL_EMUL_HH__ 833