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