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