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