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