syscall_emul.cc revision 10633:ae3b12c845b8
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 assert(fd >= 0); 232 Addr bufPtr = p->getSyscallArg(tc, index); 233 int nbytes = p->getSyscallArg(tc, index); 234 BufferArg bufArg(bufPtr, nbytes); 235 236 int bytes_read = read(fd, bufArg.bufferPtr(), nbytes); 237 238 if (bytes_read != -1) 239 bufArg.copyOut(tc->getMemProxy()); 240 241 return bytes_read; 242} 243 244SyscallReturn 245writeFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 246{ 247 int index = 0; 248 int fd = p->sim_fd(p->getSyscallArg(tc, index)); 249 Addr bufPtr = p->getSyscallArg(tc, index); 250 int nbytes = p->getSyscallArg(tc, index); 251 BufferArg bufArg(bufPtr, nbytes); 252 253 bufArg.copyIn(tc->getMemProxy()); 254 255 int bytes_written = write(fd, bufArg.bufferPtr(), nbytes); 256 257 fsync(fd); 258 259 return bytes_written; 260} 261 262 263SyscallReturn 264lseekFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 265{ 266 int index = 0; 267 int fd = p->sim_fd(p->getSyscallArg(tc, index)); 268 assert(fd >= 0); 269 uint64_t offs = p->getSyscallArg(tc, index); 270 int whence = p->getSyscallArg(tc, index); 271 272 off_t result = lseek(fd, offs, whence); 273 274 return (result == (off_t)-1) ? -errno : result; 275} 276 277 278SyscallReturn 279_llseekFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 280{ 281 int index = 0; 282 int fd = p->sim_fd(p->getSyscallArg(tc, index)); 283 assert(fd >= 0); 284 uint64_t offset_high = p->getSyscallArg(tc, index); 285 uint32_t offset_low = p->getSyscallArg(tc, index); 286 Addr result_ptr = p->getSyscallArg(tc, index); 287 int whence = p->getSyscallArg(tc, index); 288 289 uint64_t offset = (offset_high << 32) | offset_low; 290 291 uint64_t result = lseek(fd, offset, whence); 292 result = TheISA::htog(result); 293 294 if (result == (off_t)-1) { 295 //The seek failed. 296 return -errno; 297 } else { 298 // The seek succeeded. 299 // Copy "result" to "result_ptr" 300 // XXX We'll assume that the size of loff_t is 64 bits on the 301 // target platform 302 BufferArg result_buf(result_ptr, sizeof(result)); 303 memcpy(result_buf.bufferPtr(), &result, sizeof(result)); 304 result_buf.copyOut(tc->getMemProxy()); 305 return 0; 306 } 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 return unlinkHelper(desc, num, p, tc, 0); 404} 405 406SyscallReturn 407unlinkHelper(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc, 408 int index) 409{ 410 string path; 411 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 int result = unlink(path.c_str()); 419 return (result == -1) ? -errno : result; 420} 421 422 423SyscallReturn 424mkdirFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 425{ 426 string path; 427 428 int index = 0; 429 if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index))) 430 return -EFAULT; 431 432 // Adjust path for current working directory 433 path = p->fullPath(path); 434 435 mode_t mode = p->getSyscallArg(tc, index); 436 437 int result = mkdir(path.c_str(), mode); 438 return (result == -1) ? -errno : result; 439} 440 441SyscallReturn 442renameFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 443{ 444 string old_name; 445 446 int index = 0; 447 if (!tc->getMemProxy().tryReadString(old_name, p->getSyscallArg(tc, index))) 448 return -EFAULT; 449 450 string new_name; 451 452 if (!tc->getMemProxy().tryReadString(new_name, p->getSyscallArg(tc, index))) 453 return -EFAULT; 454 455 // Adjust path for current working directory 456 old_name = p->fullPath(old_name); 457 new_name = p->fullPath(new_name); 458 459 int64_t result = rename(old_name.c_str(), new_name.c_str()); 460 return (result == -1) ? -errno : result; 461} 462 463SyscallReturn 464truncateFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 465{ 466 string path; 467 468 int index = 0; 469 if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index))) 470 return -EFAULT; 471 472 off_t length = p->getSyscallArg(tc, index); 473 474 // Adjust path for current working directory 475 path = p->fullPath(path); 476 477 int result = truncate(path.c_str(), length); 478 return (result == -1) ? -errno : result; 479} 480 481SyscallReturn 482ftruncateFunc(SyscallDesc *desc, int num, 483 LiveProcess *process, ThreadContext *tc) 484{ 485 int index = 0; 486 int fd = process->sim_fd(process->getSyscallArg(tc, index)); 487 488 if (fd < 0) 489 return -EBADF; 490 491 off_t length = process->getSyscallArg(tc, index); 492 493 int result = ftruncate(fd, length); 494 return (result == -1) ? -errno : result; 495} 496 497SyscallReturn 498truncate64Func(SyscallDesc *desc, int num, 499 LiveProcess *process, ThreadContext *tc) 500{ 501 int index = 0; 502 string path; 503 504 if (!tc->getMemProxy().tryReadString(path, process->getSyscallArg(tc, index))) 505 return -EFAULT; 506 507 int64_t length = process->getSyscallArg(tc, index, 64); 508 509 // Adjust path for current working directory 510 path = process->fullPath(path); 511 512#if NO_STAT64 513 int result = truncate(path.c_str(), length); 514#else 515 int result = truncate64(path.c_str(), length); 516#endif 517 return (result == -1) ? -errno : result; 518} 519 520SyscallReturn 521ftruncate64Func(SyscallDesc *desc, int num, 522 LiveProcess *process, ThreadContext *tc) 523{ 524 int index = 0; 525 int fd = process->sim_fd(process->getSyscallArg(tc, index)); 526 527 if (fd < 0) 528 return -EBADF; 529 530 int64_t length = process->getSyscallArg(tc, index, 64); 531 532#if NO_STAT64 533 int result = ftruncate(fd, length); 534#else 535 int result = ftruncate64(fd, length); 536#endif 537 return (result == -1) ? -errno : result; 538} 539 540SyscallReturn 541umaskFunc(SyscallDesc *desc, int num, LiveProcess *process, ThreadContext *tc) 542{ 543 // Letting the simulated program change the simulator's umask seems like 544 // a bad idea. Compromise by just returning the current umask but not 545 // changing anything. 546 mode_t oldMask = umask(0); 547 umask(oldMask); 548 return (int)oldMask; 549} 550 551SyscallReturn 552chownFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 553{ 554 string path; 555 556 int index = 0; 557 if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index))) 558 return -EFAULT; 559 560 /* XXX endianess */ 561 uint32_t owner = p->getSyscallArg(tc, index); 562 uid_t hostOwner = owner; 563 uint32_t group = p->getSyscallArg(tc, index); 564 gid_t hostGroup = group; 565 566 // Adjust path for current working directory 567 path = p->fullPath(path); 568 569 int result = chown(path.c_str(), hostOwner, hostGroup); 570 return (result == -1) ? -errno : result; 571} 572 573SyscallReturn 574fchownFunc(SyscallDesc *desc, int num, LiveProcess *process, ThreadContext *tc) 575{ 576 int index = 0; 577 int fd = process->sim_fd(process->getSyscallArg(tc, index)); 578 579 if (fd < 0) 580 return -EBADF; 581 582 /* XXX endianess */ 583 uint32_t owner = process->getSyscallArg(tc, index); 584 uid_t hostOwner = owner; 585 uint32_t group = process->getSyscallArg(tc, index); 586 gid_t hostGroup = group; 587 588 int result = fchown(fd, hostOwner, hostGroup); 589 return (result == -1) ? -errno : result; 590} 591 592 593SyscallReturn 594dupFunc(SyscallDesc *desc, int num, LiveProcess *process, ThreadContext *tc) 595{ 596 int index = 0; 597 int fd = process->sim_fd(process->getSyscallArg(tc, index)); 598 if (fd < 0) 599 return -EBADF; 600 601 Process::FdMap *fdo = process->sim_fd_obj(fd); 602 603 int result = dup(fd); 604 return (result == -1) ? -errno : 605 process->alloc_fd(result, fdo->filename, fdo->flags, fdo->mode, false); 606} 607 608 609SyscallReturn 610fcntlFunc(SyscallDesc *desc, int num, LiveProcess *process, 611 ThreadContext *tc) 612{ 613 int index = 0; 614 int fd = process->getSyscallArg(tc, index); 615 616 if (fd < 0 || process->sim_fd(fd) < 0) 617 return -EBADF; 618 619 int cmd = process->getSyscallArg(tc, index); 620 switch (cmd) { 621 case 0: // F_DUPFD 622 // if we really wanted to support this, we'd need to do it 623 // in the target fd space. 624 warn("fcntl(%d, F_DUPFD) not supported, error returned\n", fd); 625 return -EMFILE; 626 627 case 1: // F_GETFD (get close-on-exec flag) 628 case 2: // F_SETFD (set close-on-exec flag) 629 return 0; 630 631 case 3: // F_GETFL (get file flags) 632 case 4: // F_SETFL (set file flags) 633 // not sure if this is totally valid, but we'll pass it through 634 // to the underlying OS 635 warn("fcntl(%d, %d) passed through to host\n", fd, cmd); 636 return fcntl(process->sim_fd(fd), cmd); 637 // return 0; 638 639 case 7: // F_GETLK (get lock) 640 case 8: // F_SETLK (set lock) 641 case 9: // F_SETLKW (set lock and wait) 642 // don't mess with file locking... just act like it's OK 643 warn("File lock call (fcntl(%d, %d)) ignored.\n", fd, cmd); 644 return 0; 645 646 default: 647 warn("Unknown fcntl command %d\n", cmd); 648 return 0; 649 } 650} 651 652SyscallReturn 653fcntl64Func(SyscallDesc *desc, int num, LiveProcess *process, 654 ThreadContext *tc) 655{ 656 int index = 0; 657 int fd = process->getSyscallArg(tc, index); 658 659 if (fd < 0 || process->sim_fd(fd) < 0) 660 return -EBADF; 661 662 int cmd = process->getSyscallArg(tc, index); 663 switch (cmd) { 664 case 33: //F_GETLK64 665 warn("fcntl64(%d, F_GETLK64) not supported, error returned\n", fd); 666 return -EMFILE; 667 668 case 34: // F_SETLK64 669 case 35: // F_SETLKW64 670 warn("fcntl64(%d, F_SETLK(W)64) not supported, error returned\n", fd); 671 return -EMFILE; 672 673 default: 674 // not sure if this is totally valid, but we'll pass it through 675 // to the underlying OS 676 warn("fcntl64(%d, %d) passed through to host\n", fd, cmd); 677 return fcntl(process->sim_fd(fd), cmd); 678 // return 0; 679 } 680} 681 682SyscallReturn 683pipePseudoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 684 ThreadContext *tc) 685{ 686 int fds[2], sim_fds[2]; 687 int pipe_retval = pipe(fds); 688 689 if (pipe_retval < 0) { 690 // error 691 return pipe_retval; 692 } 693 694 sim_fds[0] = process->alloc_fd(fds[0], "PIPE-READ", O_WRONLY, -1, true); 695 sim_fds[1] = process->alloc_fd(fds[1], "PIPE-WRITE", O_RDONLY, -1, true); 696 697 process->setReadPipeSource(sim_fds[0], sim_fds[1]); 698 // Alpha Linux convention for pipe() is that fd[0] is returned as 699 // the return value of the function, and fd[1] is returned in r20. 700 tc->setIntReg(SyscallPseudoReturnReg, sim_fds[1]); 701 return sim_fds[0]; 702} 703 704 705SyscallReturn 706getpidPseudoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 707 ThreadContext *tc) 708{ 709 // Make up a PID. There's no interprocess communication in 710 // fake_syscall mode, so there's no way for a process to know it's 711 // not getting a unique value. 712 713 tc->setIntReg(SyscallPseudoReturnReg, process->ppid()); 714 return process->pid(); 715} 716 717 718SyscallReturn 719getuidPseudoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 720 ThreadContext *tc) 721{ 722 // Make up a UID and EUID... it shouldn't matter, and we want the 723 // simulation to be deterministic. 724 725 // EUID goes in r20. 726 tc->setIntReg(SyscallPseudoReturnReg, process->euid()); //EUID 727 return process->uid(); // UID 728} 729 730 731SyscallReturn 732getgidPseudoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 733 ThreadContext *tc) 734{ 735 // Get current group ID. EGID goes in r20. 736 tc->setIntReg(SyscallPseudoReturnReg, process->egid()); //EGID 737 return process->gid(); 738} 739 740 741SyscallReturn 742setuidFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 743 ThreadContext *tc) 744{ 745 // can't fathom why a benchmark would call this. 746 int index = 0; 747 warn("Ignoring call to setuid(%d)\n", process->getSyscallArg(tc, index)); 748 return 0; 749} 750 751SyscallReturn 752getpidFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 753 ThreadContext *tc) 754{ 755 // Make up a PID. There's no interprocess communication in 756 // fake_syscall mode, so there's no way for a process to know it's 757 // not getting a unique value. 758 759 tc->setIntReg(SyscallPseudoReturnReg, process->ppid()); //PID 760 return process->pid(); 761} 762 763SyscallReturn 764getppidFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 765 ThreadContext *tc) 766{ 767 return process->ppid(); 768} 769 770SyscallReturn 771getuidFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 772 ThreadContext *tc) 773{ 774 return process->uid(); // UID 775} 776 777SyscallReturn 778geteuidFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 779 ThreadContext *tc) 780{ 781 return process->euid(); // UID 782} 783 784SyscallReturn 785getgidFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 786 ThreadContext *tc) 787{ 788 return process->gid(); 789} 790 791SyscallReturn 792getegidFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 793 ThreadContext *tc) 794{ 795 return process->egid(); 796} 797 798 799SyscallReturn 800cloneFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 801 ThreadContext *tc) 802{ 803 int index = 0; 804 IntReg flags = process->getSyscallArg(tc, index); 805 IntReg newStack = process->getSyscallArg(tc, index); 806 807 DPRINTF(SyscallVerbose, "In sys_clone:\n"); 808 DPRINTF(SyscallVerbose, " Flags=%llx\n", flags); 809 DPRINTF(SyscallVerbose, " Child stack=%llx\n", newStack); 810 811 812 if (flags != 0x10f00) { 813 warn("This sys_clone implementation assumes flags " 814 "CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD " 815 "(0x10f00), and may not work correctly with given flags " 816 "0x%llx\n", flags); 817 } 818 819 ThreadContext* ctc; // child thread context 820 if ( ( ctc = process->findFreeContext() ) != NULL ) { 821 DPRINTF(SyscallVerbose, " Found unallocated thread context\n"); 822 823 ctc->clearArchRegs(); 824 825 // Arch-specific cloning code 826 #if THE_ISA == ALPHA_ISA or THE_ISA == X86_ISA 827 // Cloning the misc. regs for these archs is enough 828 TheISA::copyMiscRegs(tc, ctc); 829 #elif THE_ISA == SPARC_ISA 830 TheISA::copyRegs(tc, ctc); 831 832 // TODO: Explain what this code actually does :-) 833 ctc->setIntReg(NumIntArchRegs + 6, 0); 834 ctc->setIntReg(NumIntArchRegs + 4, 0); 835 ctc->setIntReg(NumIntArchRegs + 3, NWindows - 2); 836 ctc->setIntReg(NumIntArchRegs + 5, NWindows); 837 ctc->setMiscReg(MISCREG_CWP, 0); 838 ctc->setIntReg(NumIntArchRegs + 7, 0); 839 ctc->setMiscRegNoEffect(MISCREG_TL, 0); 840 ctc->setMiscReg(MISCREG_ASI, ASI_PRIMARY); 841 842 for (int y = 8; y < 32; y++) 843 ctc->setIntReg(y, tc->readIntReg(y)); 844 #elif THE_ISA == ARM_ISA 845 TheISA::copyRegs(tc, ctc); 846 #else 847 fatal("sys_clone is not implemented for this ISA\n"); 848 #endif 849 850 // Set up stack register 851 ctc->setIntReg(TheISA::StackPointerReg, newStack); 852 853 // Set up syscall return values in parent and child 854 ctc->setIntReg(ReturnValueReg, 0); // return value, child 855 856 // Alpha needs SyscallSuccessReg=0 in child 857 #if THE_ISA == ALPHA_ISA 858 ctc->setIntReg(TheISA::SyscallSuccessReg, 0); 859 #endif 860 861 // In SPARC/Linux, clone returns 0 on pseudo-return register if 862 // parent, non-zero if child 863 #if THE_ISA == SPARC_ISA 864 tc->setIntReg(TheISA::SyscallPseudoReturnReg, 0); 865 ctc->setIntReg(TheISA::SyscallPseudoReturnReg, 1); 866 #endif 867 868 ctc->pcState(tc->nextInstAddr()); 869 870 ctc->activate(); 871 872 // Should return nonzero child TID in parent's syscall return register, 873 // but for our pthread library any non-zero value will work 874 return 1; 875 } else { 876 fatal("Called sys_clone, but no unallocated thread contexts found!\n"); 877 return 0; 878 } 879} 880 881SyscallReturn 882accessFunc(SyscallDesc *desc, int callnum, LiveProcess *p, ThreadContext *tc, 883 int index) 884{ 885 string path; 886 if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index))) 887 return -EFAULT; 888 889 // Adjust path for current working directory 890 path = p->fullPath(path); 891 892 mode_t mode = p->getSyscallArg(tc, index); 893 894 int result = access(path.c_str(), mode); 895 return (result == -1) ? -errno : result; 896} 897 898SyscallReturn 899accessFunc(SyscallDesc *desc, int callnum, LiveProcess *p, ThreadContext *tc) 900{ 901 return accessFunc(desc, callnum, p, tc, 0); 902} 903 904