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