52#include "sim/system.hh" 53 54using namespace std; 55using namespace TheISA; 56 57void 58SyscallDesc::doSyscall(int callnum, LiveProcess *process, ThreadContext *tc) 59{ 60 if (DTRACE(SyscallBase)) { 61 int index = 0; 62 IntReg arg[6] M5_VAR_USED; 63 64 // we can't just put the calls to getSyscallArg() in the 65 // DPRINTF arg list, because C++ doesn't guarantee their order 66 for (int i = 0; i < 6; ++i) 67 arg[i] = process->getSyscallArg(tc, index); 68 69 // Linux supports up to six system call arguments through registers 70 // so we want to print all six. Check to the relevant man page to 71 // verify how many are actually used by a given system call. 72 DPRINTF_SYSCALL(Base, 73 "%s called w/arguments %d, %d, %d, %d, %d, %d\n", 74 name, arg[0], arg[1], arg[2], arg[3], arg[4], 75 arg[5]); 76 } 77 78 SyscallReturn retval = (*funcPtr)(this, callnum, process, tc); 79 80 if (retval.needsRetry()) { 81 DPRINTF_SYSCALL(Base, "%s needs retry\n", name); 82 } else { 83 DPRINTF_SYSCALL(Base, "%s returns %d\n", name, 84 retval.encodedValue()); 85 } 86 87 if (!(flags & SyscallDesc::SuppressReturnValue) && !retval.needsRetry()) 88 process->setSyscallReturn(tc, retval); 89} 90 91 92SyscallReturn 93unimplementedFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 94 ThreadContext *tc) 95{ 96 fatal("syscall %s (#%d) unimplemented.", desc->name, callnum); 97 98 return 1; 99} 100 101 102SyscallReturn 103ignoreFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 104 ThreadContext *tc) 105{ 106 int index = 0; 107 const char *extra_text = ""; 108 109 if (desc->warnOnce()) { 110 if (desc->warned) 111 return 0; 112 113 desc->warned = true; 114 extra_text = "\n (further warnings will be suppressed)"; 115 } 116 117 warn("ignoring syscall %s(%d, ...)%s", desc->name, 118 process->getSyscallArg(tc, index), extra_text); 119 120 return 0; 121} 122 123 124SyscallReturn 125exitFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 126 ThreadContext *tc) 127{ 128 if (process->system->numRunningContexts() == 1) { 129 // Last running context... exit simulator 130 int index = 0; 131 exitSimLoop("target called exit()", 132 process->getSyscallArg(tc, index) & 0xff); 133 } else { 134 // other running threads... just halt this one 135 tc->halt(); 136 } 137 138 return 1; 139} 140 141 142SyscallReturn 143exitGroupFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 144 ThreadContext *tc) 145{ 146 // halt all threads belonging to this process 147 for (auto i: process->contextIds) { 148 process->system->getThreadContext(i)->halt(); 149 } 150 151 if (!process->system->numRunningContexts()) { 152 // all threads belonged to this process... exit simulator 153 int index = 0; 154 exitSimLoop("target called exit()", 155 process->getSyscallArg(tc, index) & 0xff); 156 } 157 158 return 1; 159} 160 161 162SyscallReturn 163getpagesizeFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 164{ 165 return (int)PageBytes; 166} 167 168 169SyscallReturn 170brkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 171{ 172 // change brk addr to first arg 173 int index = 0; 174 Addr new_brk = p->getSyscallArg(tc, index); 175 176 // in Linux at least, brk(0) returns the current break value 177 // (note that the syscall and the glibc function have different behavior) 178 if (new_brk == 0) 179 return p->brk_point; 180 181 if (new_brk > p->brk_point) { 182 // might need to allocate some new pages 183 for (ChunkGenerator gen(p->brk_point, new_brk - p->brk_point, 184 PageBytes); !gen.done(); gen.next()) { 185 if (!p->pTable->translate(gen.addr())) 186 p->allocateMem(roundDown(gen.addr(), PageBytes), PageBytes); 187 188 // if the address is already there, zero it out 189 else { 190 uint8_t zero = 0; 191 SETranslatingPortProxy &tp = tc->getMemProxy(); 192 193 // split non-page aligned accesses 194 Addr next_page = roundUp(gen.addr(), PageBytes); 195 uint32_t size_needed = next_page - gen.addr(); 196 tp.memsetBlob(gen.addr(), zero, size_needed); 197 if (gen.addr() + PageBytes > next_page && 198 next_page < new_brk && 199 p->pTable->translate(next_page)) 200 { 201 size_needed = PageBytes - size_needed; 202 tp.memsetBlob(next_page, zero, size_needed); 203 } 204 } 205 } 206 } 207 208 p->brk_point = new_brk; 209 DPRINTF_SYSCALL(Verbose, "brk: break point changed to: %#X\n", 210 p->brk_point); 211 return p->brk_point; 212} 213 214 215SyscallReturn 216closeFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 217{ 218 int index = 0; 219 int tgt_fd = p->getSyscallArg(tc, index); 220 221 int sim_fd = p->getSimFD(tgt_fd); 222 if (sim_fd < 0) 223 return -EBADF; 224 225 int status = 0; 226 if (sim_fd > 2) 227 status = close(sim_fd); 228 if (status >= 0) 229 p->resetFDEntry(tgt_fd); 230 return status; 231} 232 233 234SyscallReturn 235readFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 236{ 237 int index = 0; 238 int tgt_fd = p->getSyscallArg(tc, index); 239 Addr bufPtr = p->getSyscallArg(tc, index); 240 int nbytes = p->getSyscallArg(tc, index); 241 BufferArg bufArg(bufPtr, nbytes); 242 243 int sim_fd = p->getSimFD(tgt_fd); 244 if (sim_fd < 0) 245 return -EBADF; 246 247 int bytes_read = read(sim_fd, bufArg.bufferPtr(), nbytes); 248 249 if (bytes_read > 0) 250 bufArg.copyOut(tc->getMemProxy()); 251 252 return bytes_read; 253} 254 255SyscallReturn 256writeFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 257{ 258 int index = 0; 259 int tgt_fd = p->getSyscallArg(tc, index); 260 Addr bufPtr = p->getSyscallArg(tc, index); 261 int nbytes = p->getSyscallArg(tc, index); 262 BufferArg bufArg(bufPtr, nbytes); 263 264 int sim_fd = p->getSimFD(tgt_fd); 265 if (sim_fd < 0) 266 return -EBADF; 267 268 bufArg.copyIn(tc->getMemProxy()); 269 270 int bytes_written = write(sim_fd, bufArg.bufferPtr(), nbytes); 271 272 fsync(sim_fd); 273 274 return bytes_written; 275} 276 277 278SyscallReturn 279lseekFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 280{ 281 int index = 0; 282 int tgt_fd = p->getSyscallArg(tc, index); 283 uint64_t offs = p->getSyscallArg(tc, index); 284 int whence = p->getSyscallArg(tc, index); 285 286 int sim_fd = p->getSimFD(tgt_fd); 287 if (sim_fd < 0) 288 return -EBADF; 289 290 off_t result = lseek(sim_fd, offs, whence); 291 292 return (result == (off_t)-1) ? -errno : result; 293} 294 295 296SyscallReturn 297_llseekFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 298{ 299 int index = 0; 300 int tgt_fd = p->getSyscallArg(tc, index); 301 uint64_t offset_high = p->getSyscallArg(tc, index); 302 uint32_t offset_low = p->getSyscallArg(tc, index); 303 Addr result_ptr = p->getSyscallArg(tc, index); 304 int whence = p->getSyscallArg(tc, index); 305 306 int sim_fd = p->getSimFD(tgt_fd); 307 if (sim_fd < 0) 308 return -EBADF; 309 310 uint64_t offset = (offset_high << 32) | offset_low; 311 312 uint64_t result = lseek(sim_fd, offset, whence); 313 result = TheISA::htog(result); 314 315 if (result == (off_t)-1) 316 return -errno; 317 // Assuming that the size of loff_t is 64 bits on the target platform 318 BufferArg result_buf(result_ptr, sizeof(result)); 319 memcpy(result_buf.bufferPtr(), &result, sizeof(result)); 320 result_buf.copyOut(tc->getMemProxy()); 321 return 0; 322} 323 324 325SyscallReturn 326munmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 327{ 328 // With mmap more fully implemented, it might be worthwhile to bite 329 // the bullet and implement munmap. Should allow us to reuse simulated 330 // memory. 331 return 0; 332} 333 334 335const char *hostname = "m5.eecs.umich.edu"; 336 337SyscallReturn 338gethostnameFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 339{ 340 int index = 0; 341 Addr bufPtr = p->getSyscallArg(tc, index); 342 int name_len = p->getSyscallArg(tc, index); 343 BufferArg name(bufPtr, name_len); 344 345 strncpy((char *)name.bufferPtr(), hostname, name_len); 346 347 name.copyOut(tc->getMemProxy()); 348 349 return 0; 350} 351 352SyscallReturn 353getcwdFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 354{ 355 int result = 0; 356 int index = 0; 357 Addr bufPtr = p->getSyscallArg(tc, index); 358 unsigned long size = p->getSyscallArg(tc, index); 359 BufferArg buf(bufPtr, size); 360 361 // Is current working directory defined? 362 string cwd = p->getcwd(); 363 if (!cwd.empty()) { 364 if (cwd.length() >= size) { 365 // Buffer too small 366 return -ERANGE; 367 } 368 strncpy((char *)buf.bufferPtr(), cwd.c_str(), size); 369 result = cwd.length(); 370 } else { 371 if (getcwd((char *)buf.bufferPtr(), size) != NULL) { 372 result = strlen((char *)buf.bufferPtr()); 373 } else { 374 result = -1; 375 } 376 } 377 378 buf.copyOut(tc->getMemProxy()); 379 380 return (result == -1) ? -errno : result; 381} 382 383/// Target open() handler. 384SyscallReturn 385readlinkFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 386 ThreadContext *tc) 387{ 388 return readlinkFunc(desc, callnum, process, tc, 0); 389} 390 391SyscallReturn 392readlinkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc, 393 int index) 394{ 395 string path; 396 397 if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index))) 398 return -EFAULT; 399 400 // Adjust path for current working directory 401 path = p->fullPath(path); 402 403 Addr bufPtr = p->getSyscallArg(tc, index); 404 size_t bufsiz = p->getSyscallArg(tc, index); 405 406 BufferArg buf(bufPtr, bufsiz); 407 408 int result = -1; 409 if (path != "/proc/self/exe") { 410 result = readlink(path.c_str(), (char *)buf.bufferPtr(), bufsiz); 411 } else { 412 // Emulate readlink() called on '/proc/self/exe' should return the 413 // absolute path of the binary running in the simulated system (the 414 // LiveProcess' executable). It is possible that using this path in 415 // the simulated system will result in unexpected behavior if: 416 // 1) One binary runs another (e.g., -c time -o "my_binary"), and 417 // called binary calls readlink(). 418 // 2) The host's full path to the running benchmark changes from one 419 // simulation to another. This can result in different simulated 420 // performance since the simulated system will process the binary 421 // path differently, even if the binary itself does not change. 422 423 // Get the absolute canonical path to the running application 424 char real_path[PATH_MAX]; 425 char *check_real_path = realpath(p->progName(), real_path); 426 if (!check_real_path) { 427 fatal("readlink('/proc/self/exe') unable to resolve path to " 428 "executable: %s", p->progName()); 429 } 430 strncpy((char*)buf.bufferPtr(), real_path, bufsiz); 431 size_t real_path_len = strlen(real_path); 432 if (real_path_len > bufsiz) { 433 // readlink will truncate the contents of the 434 // path to ensure it is no more than bufsiz 435 result = bufsiz; 436 } else { 437 result = real_path_len; 438 } 439 440 // Issue a warning about potential unexpected results 441 warn_once("readlink() called on '/proc/self/exe' may yield unexpected " 442 "results in various settings.\n Returning '%s'\n", 443 (char*)buf.bufferPtr()); 444 } 445 446 buf.copyOut(tc->getMemProxy()); 447 448 return (result == -1) ? -errno : result; 449} 450 451SyscallReturn 452unlinkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 453{ 454 return unlinkHelper(desc, num, p, tc, 0); 455} 456 457SyscallReturn 458unlinkHelper(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc, 459 int index) 460{ 461 string path; 462 463 if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index))) 464 return -EFAULT; 465 466 // Adjust path for current working directory 467 path = p->fullPath(path); 468 469 int result = unlink(path.c_str()); 470 return (result == -1) ? -errno : result; 471} 472 473 474SyscallReturn 475mkdirFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 476{ 477 string path; 478 479 int index = 0; 480 if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index))) 481 return -EFAULT; 482 483 // Adjust path for current working directory 484 path = p->fullPath(path); 485 486 mode_t mode = p->getSyscallArg(tc, index); 487 488 int result = mkdir(path.c_str(), mode); 489 return (result == -1) ? -errno : result; 490} 491 492SyscallReturn 493renameFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 494{ 495 string old_name; 496 497 int index = 0; 498 if (!tc->getMemProxy().tryReadString(old_name, p->getSyscallArg(tc, index))) 499 return -EFAULT; 500 501 string new_name; 502 503 if (!tc->getMemProxy().tryReadString(new_name, p->getSyscallArg(tc, index))) 504 return -EFAULT; 505 506 // Adjust path for current working directory 507 old_name = p->fullPath(old_name); 508 new_name = p->fullPath(new_name); 509 510 int64_t result = rename(old_name.c_str(), new_name.c_str()); 511 return (result == -1) ? -errno : result; 512} 513 514SyscallReturn 515truncateFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 516{ 517 string path; 518 519 int index = 0; 520 if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index))) 521 return -EFAULT; 522 523 off_t length = p->getSyscallArg(tc, index); 524 525 // Adjust path for current working directory 526 path = p->fullPath(path); 527 528 int result = truncate(path.c_str(), length); 529 return (result == -1) ? -errno : result; 530} 531 532SyscallReturn 533ftruncateFunc(SyscallDesc *desc, int num, 534 LiveProcess *process, ThreadContext *tc) 535{ 536 int index = 0; 537 int tgt_fd = process->getSyscallArg(tc, index); 538 off_t length = process->getSyscallArg(tc, index); 539 540 int sim_fd = process->getSimFD(tgt_fd); 541 if (sim_fd < 0) 542 return -EBADF; 543 544 int result = ftruncate(sim_fd, length); 545 return (result == -1) ? -errno : result; 546} 547 548SyscallReturn 549truncate64Func(SyscallDesc *desc, int num, 550 LiveProcess *process, ThreadContext *tc) 551{ 552 int index = 0; 553 string path; 554 555 if (!tc->getMemProxy().tryReadString(path, process->getSyscallArg(tc, index))) 556 return -EFAULT; 557 558 int64_t length = process->getSyscallArg(tc, index, 64); 559 560 // Adjust path for current working directory 561 path = process->fullPath(path); 562 563#if NO_STAT64 564 int result = truncate(path.c_str(), length); 565#else 566 int result = truncate64(path.c_str(), length); 567#endif 568 return (result == -1) ? -errno : result; 569} 570 571SyscallReturn 572ftruncate64Func(SyscallDesc *desc, int num, 573 LiveProcess *process, ThreadContext *tc) 574{ 575 int index = 0; 576 int tgt_fd = process->getSyscallArg(tc, index); 577 int64_t length = process->getSyscallArg(tc, index, 64); 578 579 int sim_fd = process->getSimFD(tgt_fd); 580 if (sim_fd < 0) 581 return -EBADF; 582 583#if NO_STAT64 584 int result = ftruncate(sim_fd, length); 585#else 586 int result = ftruncate64(sim_fd, length); 587#endif 588 return (result == -1) ? -errno : result; 589} 590 591SyscallReturn 592umaskFunc(SyscallDesc *desc, int num, LiveProcess *process, ThreadContext *tc) 593{ 594 // Letting the simulated program change the simulator's umask seems like 595 // a bad idea. Compromise by just returning the current umask but not 596 // changing anything. 597 mode_t oldMask = umask(0); 598 umask(oldMask); 599 return (int)oldMask; 600} 601 602SyscallReturn 603chownFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 604{ 605 string path; 606 607 int index = 0; 608 if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index))) 609 return -EFAULT; 610 611 /* XXX endianess */ 612 uint32_t owner = p->getSyscallArg(tc, index); 613 uid_t hostOwner = owner; 614 uint32_t group = p->getSyscallArg(tc, index); 615 gid_t hostGroup = group; 616 617 // Adjust path for current working directory 618 path = p->fullPath(path); 619 620 int result = chown(path.c_str(), hostOwner, hostGroup); 621 return (result == -1) ? -errno : result; 622} 623 624SyscallReturn 625fchownFunc(SyscallDesc *desc, int num, LiveProcess *process, ThreadContext *tc) 626{ 627 int index = 0; 628 int tgt_fd = process->getSyscallArg(tc, index); 629 630 int sim_fd = process->getSimFD(tgt_fd); 631 if (sim_fd < 0) 632 return -EBADF; 633 634 /* XXX endianess */ 635 uint32_t owner = process->getSyscallArg(tc, index); 636 uid_t hostOwner = owner; 637 uint32_t group = process->getSyscallArg(tc, index); 638 gid_t hostGroup = group; 639 640 int result = fchown(sim_fd, hostOwner, hostGroup); 641 return (result == -1) ? -errno : result; 642} 643 644 645SyscallReturn 646dupFunc(SyscallDesc *desc, int num, LiveProcess *process, ThreadContext *tc) 647{ 648 int index = 0; 649 int tgt_fd = process->getSyscallArg(tc, index); 650 651 int sim_fd = process->getSimFD(tgt_fd); 652 if (sim_fd < 0) 653 return -EBADF; 654 655 FDEntry *fde = process->getFDEntry(tgt_fd); 656 657 int result = dup(sim_fd); 658 return (result == -1) ? -errno : 659 process->allocFD(result, fde->filename, fde->flags, fde->mode, false); 660} 661 662 663SyscallReturn 664fcntlFunc(SyscallDesc *desc, int num, LiveProcess *process, 665 ThreadContext *tc) 666{ 667 int index = 0; 668 int tgt_fd = process->getSyscallArg(tc, index); 669 670 int sim_fd = process->getSimFD(tgt_fd); 671 if (sim_fd < 0) 672 return -EBADF; 673 674 int cmd = process->getSyscallArg(tc, index); 675 switch (cmd) { 676 case 0: // F_DUPFD 677 // if we really wanted to support this, we'd need to do it 678 // in the target fd space. 679 warn("fcntl(%d, F_DUPFD) not supported, error returned\n", tgt_fd); 680 return -EMFILE; 681 682 case 1: // F_GETFD (get close-on-exec flag) 683 case 2: // F_SETFD (set close-on-exec flag) 684 return 0; 685 686 case 3: // F_GETFL (get file flags) 687 case 4: // F_SETFL (set file flags) 688 // not sure if this is totally valid, but we'll pass it through 689 // to the underlying OS 690 warn("fcntl(%d, %d) passed through to host\n", tgt_fd, cmd); 691 return fcntl(sim_fd, cmd); 692 // return 0; 693 694 case 7: // F_GETLK (get lock) 695 case 8: // F_SETLK (set lock) 696 case 9: // F_SETLKW (set lock and wait) 697 // don't mess with file locking... just act like it's OK 698 warn("File lock call (fcntl(%d, %d)) ignored.\n", tgt_fd, cmd); 699 return 0; 700 701 default: 702 warn("Unknown fcntl command %d\n", cmd); 703 return 0; 704 } 705} 706 707SyscallReturn 708fcntl64Func(SyscallDesc *desc, int num, LiveProcess *process, 709 ThreadContext *tc) 710{ 711 int index = 0; 712 int tgt_fd = process->getSyscallArg(tc, index); 713 714 int sim_fd = process->getSimFD(tgt_fd); 715 if (sim_fd < 0) 716 return -EBADF; 717 718 int cmd = process->getSyscallArg(tc, index); 719 switch (cmd) { 720 case 33: //F_GETLK64 721 warn("fcntl64(%d, F_GETLK64) not supported, error returned\n", tgt_fd); 722 return -EMFILE; 723 724 case 34: // F_SETLK64 725 case 35: // F_SETLKW64 726 warn("fcntl64(%d, F_SETLK(W)64) not supported, error returned\n", 727 tgt_fd); 728 return -EMFILE; 729 730 default: 731 // not sure if this is totally valid, but we'll pass it through 732 // to the underlying OS 733 warn("fcntl64(%d, %d) passed through to host\n", tgt_fd, cmd); 734 return fcntl(sim_fd, cmd); 735 // return 0; 736 } 737} 738 739SyscallReturn 740pipePseudoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 741 ThreadContext *tc) 742{ 743 int fds[2], sim_fds[2]; 744 int pipe_retval = pipe(fds); 745 746 if (pipe_retval < 0) { 747 // error 748 return pipe_retval; 749 } 750 751 sim_fds[0] = process->allocFD(fds[0], "PIPE-READ", O_WRONLY, -1, true); 752 sim_fds[1] = process->allocFD(fds[1], "PIPE-WRITE", O_RDONLY, -1, true); 753 754 process->setReadPipeSource(sim_fds[0], sim_fds[1]); 755 // Alpha Linux convention for pipe() is that fd[0] is returned as 756 // the return value of the function, and fd[1] is returned in r20. 757 tc->setIntReg(SyscallPseudoReturnReg, sim_fds[1]); 758 return sim_fds[0]; 759} 760 761 762SyscallReturn 763getpidPseudoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 764 ThreadContext *tc) 765{ 766 // Make up a PID. There's no interprocess communication in 767 // fake_syscall mode, so there's no way for a process to know it's 768 // not getting a unique value. 769 770 tc->setIntReg(SyscallPseudoReturnReg, process->ppid()); 771 return process->pid(); 772} 773 774 775SyscallReturn 776getuidPseudoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 777 ThreadContext *tc) 778{ 779 // Make up a UID and EUID... it shouldn't matter, and we want the 780 // simulation to be deterministic. 781 782 // EUID goes in r20. 783 tc->setIntReg(SyscallPseudoReturnReg, process->euid()); //EUID 784 return process->uid(); // UID 785} 786 787 788SyscallReturn 789getgidPseudoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 790 ThreadContext *tc) 791{ 792 // Get current group ID. EGID goes in r20. 793 tc->setIntReg(SyscallPseudoReturnReg, process->egid()); //EGID 794 return process->gid(); 795} 796 797 798SyscallReturn 799setuidFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 800 ThreadContext *tc) 801{ 802 // can't fathom why a benchmark would call this. 803 int index = 0; 804 warn("Ignoring call to setuid(%d)\n", process->getSyscallArg(tc, index)); 805 return 0; 806} 807 808SyscallReturn 809getpidFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 810 ThreadContext *tc) 811{ 812 // Make up a PID. There's no interprocess communication in 813 // fake_syscall mode, so there's no way for a process to know it's 814 // not getting a unique value. 815 816 tc->setIntReg(SyscallPseudoReturnReg, process->ppid()); //PID 817 return process->pid(); 818} 819 820SyscallReturn 821getppidFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 822 ThreadContext *tc) 823{ 824 return process->ppid(); 825} 826 827SyscallReturn 828getuidFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 829 ThreadContext *tc) 830{ 831 return process->uid(); // UID 832} 833 834SyscallReturn 835geteuidFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 836 ThreadContext *tc) 837{ 838 return process->euid(); // UID 839} 840 841SyscallReturn 842getgidFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 843 ThreadContext *tc) 844{ 845 return process->gid(); 846} 847 848SyscallReturn 849getegidFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 850 ThreadContext *tc) 851{ 852 return process->egid(); 853} 854 855 856SyscallReturn 857cloneFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 858 ThreadContext *tc) 859{ 860 int index = 0; 861 IntReg flags = process->getSyscallArg(tc, index); 862 IntReg newStack = process->getSyscallArg(tc, index); 863 864 DPRINTF(SyscallVerbose, "In sys_clone:\n"); 865 DPRINTF(SyscallVerbose, " Flags=%llx\n", flags); 866 DPRINTF(SyscallVerbose, " Child stack=%llx\n", newStack); 867 868 869 if (flags != 0x10f00) { 870 warn("This sys_clone implementation assumes flags " 871 "CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD " 872 "(0x10f00), and may not work correctly with given flags " 873 "0x%llx\n", flags); 874 } 875 876 ThreadContext* ctc; // child thread context 877 if ( ( ctc = process->findFreeContext() ) != NULL ) { 878 DPRINTF(SyscallVerbose, " Found unallocated thread context\n"); 879 880 ctc->clearArchRegs(); 881 882 // Arch-specific cloning code 883 #if THE_ISA == ALPHA_ISA or THE_ISA == X86_ISA 884 // Cloning the misc. regs for these archs is enough 885 TheISA::copyMiscRegs(tc, ctc); 886 #elif THE_ISA == SPARC_ISA 887 TheISA::copyRegs(tc, ctc); 888 889 // TODO: Explain what this code actually does :-) 890 ctc->setIntReg(NumIntArchRegs + 6, 0); 891 ctc->setIntReg(NumIntArchRegs + 4, 0); 892 ctc->setIntReg(NumIntArchRegs + 3, NWindows - 2); 893 ctc->setIntReg(NumIntArchRegs + 5, NWindows); 894 ctc->setMiscReg(MISCREG_CWP, 0); 895 ctc->setIntReg(NumIntArchRegs + 7, 0); 896 ctc->setMiscRegNoEffect(MISCREG_TL, 0); 897 ctc->setMiscReg(MISCREG_ASI, ASI_PRIMARY); 898 899 for (int y = 8; y < 32; y++) 900 ctc->setIntReg(y, tc->readIntReg(y)); 901 #elif THE_ISA == ARM_ISA 902 TheISA::copyRegs(tc, ctc); 903 #else 904 fatal("sys_clone is not implemented for this ISA\n"); 905 #endif 906 907 // Set up stack register 908 ctc->setIntReg(TheISA::StackPointerReg, newStack); 909 910 // Set up syscall return values in parent and child 911 ctc->setIntReg(ReturnValueReg, 0); // return value, child 912 913 // Alpha needs SyscallSuccessReg=0 in child 914 #if THE_ISA == ALPHA_ISA 915 ctc->setIntReg(TheISA::SyscallSuccessReg, 0); 916 #endif 917 918 // In SPARC/Linux, clone returns 0 on pseudo-return register if 919 // parent, non-zero if child 920 #if THE_ISA == SPARC_ISA 921 tc->setIntReg(TheISA::SyscallPseudoReturnReg, 0); 922 ctc->setIntReg(TheISA::SyscallPseudoReturnReg, 1); 923 #endif 924 925 ctc->pcState(tc->nextInstAddr()); 926 927 ctc->activate(); 928 929 // Should return nonzero child TID in parent's syscall return register, 930 // but for our pthread library any non-zero value will work 931 return 1; 932 } else { 933 fatal("Called sys_clone, but no unallocated thread contexts found!\n"); 934 return 0; 935 } 936} 937 938SyscallReturn 939fallocateFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 940 ThreadContext *tc) 941{ 942 int index = 0; 943 int tgt_fd = process->getSyscallArg(tc, index); 944 int mode = process->getSyscallArg(tc, index); 945 off_t offset = process->getSyscallArg(tc, index); 946 off_t len = process->getSyscallArg(tc, index); 947 948 int sim_fd = process->getSimFD(tgt_fd); 949 if (sim_fd < 0) 950 return -EBADF; 951 952 int result = fallocate(sim_fd, mode, offset, len); 953 if (result < 0) 954 return -errno; 955 956 return 0; 957} 958 959SyscallReturn 960accessFunc(SyscallDesc *desc, int callnum, LiveProcess *p, ThreadContext *tc, 961 int index) 962{ 963 string path; 964 if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index))) 965 return -EFAULT; 966 967 // Adjust path for current working directory 968 path = p->fullPath(path); 969 970 mode_t mode = p->getSyscallArg(tc, index); 971 972 int result = access(path.c_str(), mode); 973 return (result == -1) ? -errno : result; 974} 975 976SyscallReturn 977accessFunc(SyscallDesc *desc, int callnum, LiveProcess *p, ThreadContext *tc) 978{ 979 return accessFunc(desc, callnum, p, tc, 0); 980} 981
|