gem5  v20.1.0.0
syscall_emul.hh
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012-2013, 2015, 2019-2020 ARM Limited
3  * Copyright (c) 2015 Advanced Micro Devices, Inc.
4  * All rights reserved
5  *
6  * The license below extends only to copyright in the software and shall
7  * not be construed as granting a license to any other intellectual
8  * property including but not limited to intellectual property relating
9  * to a hardware implementation of the functionality of the software
10  * licensed hereunder. You may use the software subject to the license
11  * terms below provided that you ensure that this notice is replicated
12  * unmodified and in its entirety in all distributions of the software,
13  * modified or unmodified, in source code or in binary form.
14  *
15  * Copyright (c) 2003-2005 The Regents of The University of Michigan
16  * All rights reserved.
17  *
18  * Redistribution and use in source and binary forms, with or without
19  * modification, are permitted provided that the following conditions are
20  * met: redistributions of source code must retain the above copyright
21  * notice, this list of conditions and the following disclaimer;
22  * redistributions in binary form must reproduce the above copyright
23  * notice, this list of conditions and the following disclaimer in the
24  * documentation and/or other materials provided with the distribution;
25  * neither the name of the copyright holders nor the names of its
26  * contributors may be used to endorse or promote products derived from
27  * this software without specific prior written permission.
28  *
29  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40  */
41 
42 #ifndef __SIM_SYSCALL_EMUL_HH__
43 #define __SIM_SYSCALL_EMUL_HH__
44 
45 #if (defined(__APPLE__) || defined(__OpenBSD__) || \
46  defined(__FreeBSD__) || defined(__CYGWIN__) || \
47  defined(__NetBSD__))
48 #define NO_STAT64 1
49 #else
50 #define NO_STAT64 0
51 #endif
52 
58 
59 #if defined(__linux__)
60 #include <sys/eventfd.h>
61 #include <sys/statfs.h>
62 
63 #else
64 #include <sys/mount.h>
65 
66 #endif
67 
68 #ifdef __CYGWIN32__
69 #include <sys/fcntl.h>
70 
71 #endif
72 #include <fcntl.h>
73 #include <net/if.h>
74 #include <poll.h>
75 #include <sys/ioctl.h>
76 #include <sys/mman.h>
77 #include <sys/socket.h>
78 #include <sys/stat.h>
79 #include <sys/time.h>
80 #include <sys/types.h>
81 #include <sys/uio.h>
82 #include <unistd.h>
83 
84 #include <cerrno>
85 #include <memory>
86 #include <string>
87 
88 #include "arch/generic/tlb.hh"
89 #include "arch/utility.hh"
90 #include "base/intmath.hh"
92 #include "base/logging.hh"
93 #include "base/trace.hh"
94 #include "base/types.hh"
95 #include "config/the_isa.hh"
96 #include "cpu/base.hh"
97 #include "cpu/thread_context.hh"
98 #include "kern/linux/linux.hh"
99 #include "mem/page_table.hh"
100 #include "params/Process.hh"
101 #include "sim/emul_driver.hh"
102 #include "sim/futex_map.hh"
103 #include "sim/guest_abi.hh"
104 #include "sim/process.hh"
105 #include "sim/proxy_ptr.hh"
107 #include "sim/syscall_desc.hh"
108 #include "sim/syscall_emul_buf.hh"
109 #include "sim/syscall_return.hh"
110 
111 #if defined(__APPLE__) && defined(__MACH__) && !defined(CMSG_ALIGN)
112 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
113 #endif
114 
116 //
117 // The following emulation functions are generic enough that they
118 // don't need to be recompiled for different emulated OS's. They are
119 // defined in sim/syscall_emul.cc.
120 //
122 
123 void warnUnsupportedOS(std::string syscall_name);
124 
127 
136 
137 // Target fallocateFunc() handler.
139  int tgt_fd, int mode, off_t offset, off_t len);
140 
143 
146 
149  uint64_t tidPtr);
150 
153 
155 SyscallReturn brkFunc(SyscallDesc *desc, ThreadContext *tc, Addr new_brk);
156 
158 SyscallReturn closeFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd);
159 
162  int tgt_fd, uint64_t offs, int whence);
163 
166  int tgt_fd, uint64_t offset_high,
167  uint32_t offset_low, Addr result_ptr, int whence);
168 
171  size_t length);
172 
175  int tgt_fd, int how);
176 
179  Addr buf_ptr, int name_len);
180 
183  Addr buf_ptr, unsigned long size);
184 
187  Addr pathname, Addr buf, size_t bufsiz);
188 
191 
194  Addr pathname, Addr new_pathname);
195 
198  Addr pathname, Addr new_pathname);
199 
202  Addr pathname, mode_t mode);
203 
206  Addr pathname, mode_t mode, dev_t dev);
207 
210 
211 // Target rmdir() handler.
213 
216  Addr oldpath, Addr newpath);
217 
218 
221  Addr pathname, off_t length);
222 
223 
226  int tgt_fd, off_t length);
227 
228 
231  Addr pathname, int64_t length);
232 
235  int tgt_fd, int64_t length);
236 
239 
242 
245  Addr pathname, uint32_t owner, uint32_t group);
246 
249 
252  int pid, int pgid);
253 
256  int tgt_fd, uint32_t owner, uint32_t group);
257 
260  int tgt_fd);
261 
264  int old_tgt_fd, int new_tgt_fd);
265 
268  int tgt_fd, int cmd, GuestABI::VarArgs<int> varargs);
269 
272  int tgt_fd, int cmd);
273 
275 SyscallReturn pipeFunc(SyscallDesc *desc, ThreadContext *tc, Addr tgt_addr);
276 
279  Addr tgt_addr, int flags);
280 
283 
284 // Target getpeername() handler.
286  int tgt_fd, Addr sockAddrPtr, Addr addrlenPtr);
287 
288 // Target bind() handler.
290  int tgt_fd, Addr buf_ptr, int addrlen);
291 
292 // Target listen() handler.
294  int tgt_fd, int backlog);
295 
296 // Target connect() handler.
298  int tgt_fd, Addr buf_ptr, int addrlen);
299 
300 #if defined(SYS_getdents)
301 // Target getdents() handler.
302 SyscallReturn getdentsFunc(SyscallDesc *desc, ThreadContext *tc,
303  int tgt_fd, Addr buf_ptr, unsigned count);
304 #endif
305 
306 #if defined(SYS_getdents64)
307 // Target getdents() handler.
308 SyscallReturn getdents64Func(SyscallDesc *desc, ThreadContext *tc,
309  int tgt_fd, Addr buf_ptr, unsigned count);
310 #endif
311 
312 // Target sendto() handler.
314  int tgt_fd, Addr bufrPtr, size_t bufrLen, int flags,
315  Addr addrPtr, socklen_t addrLen);
316 
317 // Target recvfrom() handler.
319  int tgt_fd, Addr bufrPtr, size_t bufrLen,
320  int flags, Addr addrPtr, Addr addrlenPtr);
321 
322 // Target recvmsg() handler.
324  int tgt_fd, Addr msgPtr, int flags);
325 
326 // Target sendmsg() handler.
328  int tgt_fd, Addr msgPtr, int flags);
329 
330 // Target getuid() handler.
332 
335 
338 
341 
344 
347  Addr pathname, mode_t mode);
348 
349 // Target getsockopt() handler.
351  int tgt_fd, int level, int optname,
352  Addr valPtr, Addr lenPtr);
353 
354 // Target setsockopt() handler.
356  int tgt_fd, int level, int optname,
357  Addr valPtr, socklen_t len);
358 
360  VPtr<uint32_t> cpu, VPtr<uint32_t> node,
361  VPtr<uint32_t> tcache);
362 
363 // Target getsockname() handler.
365  int tgt_fd, Addr addrPtr, Addr lenPtr);
366 
370 template <class OS>
373  Addr uaddr, int op, int val, int timeout, Addr uaddr2, int val3)
374 {
375  using namespace std;
376 
377  auto process = tc->getProcessPtr();
378 
379  /*
380  * Unsupported option that does not affect the correctness of the
381  * application. This is a performance optimization utilized by Linux.
382  */
383  op &= ~OS::TGT_FUTEX_PRIVATE_FLAG;
384  op &= ~OS::TGT_FUTEX_CLOCK_REALTIME_FLAG;
385 
386  FutexMap &futex_map = tc->getSystemPtr()->futexMap;
387 
388  if (OS::TGT_FUTEX_WAIT == op || OS::TGT_FUTEX_WAIT_BITSET == op) {
389  // Ensure futex system call accessed atomically.
390  BufferArg buf(uaddr, sizeof(int));
391  buf.copyIn(tc->getVirtProxy());
392  int mem_val = *(int*)buf.bufferPtr();
393 
394  /*
395  * The value in memory at uaddr is not equal with the expected val
396  * (a different thread must have changed it before the system call was
397  * invoked). In this case, we need to throw an error.
398  */
399  if (val != mem_val)
400  return -OS::TGT_EWOULDBLOCK;
401 
402  if (OS::TGT_FUTEX_WAIT == op) {
403  futex_map.suspend(uaddr, process->tgid(), tc);
404  } else {
405  futex_map.suspend_bitset(uaddr, process->tgid(), tc, val3);
406  }
407 
408  return 0;
409  } else if (OS::TGT_FUTEX_WAKE == op) {
410  return futex_map.wakeup(uaddr, process->tgid(), val);
411  } else if (OS::TGT_FUTEX_WAKE_BITSET == op) {
412  return futex_map.wakeup_bitset(uaddr, process->tgid(), val3);
413  } else if (OS::TGT_FUTEX_REQUEUE == op ||
414  OS::TGT_FUTEX_CMP_REQUEUE == op) {
415 
416  // Ensure futex system call accessed atomically.
417  BufferArg buf(uaddr, sizeof(int));
418  buf.copyIn(tc->getVirtProxy());
419  int mem_val = *(int*)buf.bufferPtr();
420  /*
421  * For CMP_REQUEUE, the whole operation is only started only if
422  * val3 is still the value of the futex pointed to by uaddr.
423  */
424  if (OS::TGT_FUTEX_CMP_REQUEUE && val3 != mem_val)
425  return -OS::TGT_EWOULDBLOCK;
426  return futex_map.requeue(uaddr, process->tgid(), val, timeout, uaddr2);
427  } else if (OS::TGT_FUTEX_WAKE_OP == op) {
428  /*
429  * The FUTEX_WAKE_OP operation is equivalent to executing the
430  * following code atomically and totally ordered with respect to
431  * other futex operations on any of the two supplied futex words:
432  *
433  * int oldval = *(int *) addr2;
434  * *(int *) addr2 = oldval op oparg;
435  * futex(addr1, FUTEX_WAKE, val, 0, 0, 0);
436  * if (oldval cmp cmparg)
437  * futex(addr2, FUTEX_WAKE, val2, 0, 0, 0);
438  *
439  * (op, oparg, cmp, cmparg are encoded in val3)
440  *
441  * +---+---+-----------+-----------+
442  * |op |cmp| oparg | cmparg |
443  * +---+---+-----------+-----------+
444  * 4 4 12 12 <== # of bits
445  *
446  * reference: http://man7.org/linux/man-pages/man2/futex.2.html
447  *
448  */
449  // get value from simulated-space
450  BufferArg buf(uaddr2, sizeof(int));
451  buf.copyIn(tc->getVirtProxy());
452  int oldval = *(int*)buf.bufferPtr();
453  int newval = oldval;
454  // extract op, oparg, cmp, cmparg from val3
455  int wake_cmparg = val3 & 0xfff;
456  int wake_oparg = (val3 & 0xfff000) >> 12;
457  int wake_cmp = (val3 & 0xf000000) >> 24;
458  int wake_op = (val3 & 0xf0000000) >> 28;
459  if ((wake_op & OS::TGT_FUTEX_OP_ARG_SHIFT) >> 3 == 1)
460  wake_oparg = (1 << wake_oparg);
461  wake_op &= ~OS::TGT_FUTEX_OP_ARG_SHIFT;
462  // perform operation on the value of the second futex
463  if (wake_op == OS::TGT_FUTEX_OP_SET)
464  newval = wake_oparg;
465  else if (wake_op == OS::TGT_FUTEX_OP_ADD)
466  newval += wake_oparg;
467  else if (wake_op == OS::TGT_FUTEX_OP_OR)
468  newval |= wake_oparg;
469  else if (wake_op == OS::TGT_FUTEX_OP_ANDN)
470  newval &= ~wake_oparg;
471  else if (wake_op == OS::TGT_FUTEX_OP_XOR)
472  newval ^= wake_oparg;
473  // copy updated value back to simulated-space
474  *(int*)buf.bufferPtr() = newval;
475  buf.copyOut(tc->getVirtProxy());
476  // perform the first wake-up
477  int woken1 = futex_map.wakeup(uaddr, process->tgid(), val);
478  int woken2 = 0;
479  // calculate the condition of the second wake-up
480  bool is_wake2 = false;
481  if (wake_cmp == OS::TGT_FUTEX_OP_CMP_EQ)
482  is_wake2 = oldval == wake_cmparg;
483  else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_NE)
484  is_wake2 = oldval != wake_cmparg;
485  else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_LT)
486  is_wake2 = oldval < wake_cmparg;
487  else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_LE)
488  is_wake2 = oldval <= wake_cmparg;
489  else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_GT)
490  is_wake2 = oldval > wake_cmparg;
491  else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_GE)
492  is_wake2 = oldval >= wake_cmparg;
493  // perform the second wake-up
494  if (is_wake2)
495  woken2 = futex_map.wakeup(uaddr2, process->tgid(), timeout);
496 
497  return woken1 + woken2;
498  }
499  warn("futex: op %d not implemented; ignoring.", op);
500  return -ENOSYS;
501 }
502 
506 
507 
511 const unsigned seconds_since_epoch = 1000 * 1000 * 1000;
512 
515 template <class T1, class T2>
516 void
517 getElapsedTimeMicro(T1 &sec, T2 &usec)
518 {
519  static const int OneMillion = 1000 * 1000;
520 
521  uint64_t elapsed_usecs = curTick() / SimClock::Int::us;
522  sec = elapsed_usecs / OneMillion;
523  usec = elapsed_usecs % OneMillion;
524 }
525 
528 template <class T1, class T2>
529 void
530 getElapsedTimeNano(T1 &sec, T2 &nsec)
531 {
532  static const int OneBillion = 1000 * 1000 * 1000;
533 
534  uint64_t elapsed_nsecs = curTick() / SimClock::Int::ns;
535  sec = elapsed_nsecs / OneBillion;
536  nsec = elapsed_nsecs % OneBillion;
537 }
538 
540 //
541 // The following emulation functions are generic, but need to be
542 // templated to account for differences in types, constants, etc.
543 //
545 
546  typedef struct statfs hst_statfs;
547 #if NO_STAT64
548  typedef struct stat hst_stat;
549  typedef struct stat hst_stat64;
550 #else
551  typedef struct stat hst_stat;
552  typedef struct stat64 hst_stat64;
553 #endif
554 
558 
559 template <typename OS, typename TgtStatPtr, typename HostStatPtr>
560 void
561 copyOutStatBuf(TgtStatPtr tgt, HostStatPtr host, bool fakeTTY=false)
562 {
563  constexpr ByteOrder bo = OS::byteOrder;
564 
565  if (fakeTTY)
566  tgt->st_dev = 0xA;
567  else
568  tgt->st_dev = host->st_dev;
569  tgt->st_dev = htog(tgt->st_dev, bo);
570  tgt->st_ino = host->st_ino;
571  tgt->st_ino = htog(tgt->st_ino, bo);
572  tgt->st_mode = host->st_mode;
573  if (fakeTTY) {
574  // Claim to be a character device
575  tgt->st_mode &= ~S_IFMT; // Clear S_IFMT
576  tgt->st_mode |= S_IFCHR; // Set S_IFCHR
577  }
578  tgt->st_mode = htog(tgt->st_mode, bo);
579  tgt->st_nlink = host->st_nlink;
580  tgt->st_nlink = htog(tgt->st_nlink, bo);
581  tgt->st_uid = host->st_uid;
582  tgt->st_uid = htog(tgt->st_uid, bo);
583  tgt->st_gid = host->st_gid;
584  tgt->st_gid = htog(tgt->st_gid, bo);
585  if (fakeTTY)
586  tgt->st_rdev = 0x880d;
587  else
588  tgt->st_rdev = host->st_rdev;
589  tgt->st_rdev = htog(tgt->st_rdev, bo);
590  tgt->st_size = host->st_size;
591  tgt->st_size = htog(tgt->st_size, bo);
592  tgt->st_atimeX = host->st_atime;
593  tgt->st_atimeX = htog(tgt->st_atimeX, bo);
594  tgt->st_mtimeX = host->st_mtime;
595  tgt->st_mtimeX = htog(tgt->st_mtimeX, bo);
596  tgt->st_ctimeX = host->st_ctime;
597  tgt->st_ctimeX = htog(tgt->st_ctimeX, bo);
598  // Force the block size to be 8KB. This helps to ensure buffered io works
599  // consistently across different hosts.
600  tgt->st_blksize = 0x2000;
601  tgt->st_blksize = htog(tgt->st_blksize, bo);
602  tgt->st_blocks = host->st_blocks;
603  tgt->st_blocks = htog(tgt->st_blocks, bo);
604 }
605 
606 // Same for stat64
607 
608 template <typename OS, typename TgtStatPtr, typename HostStatPtr>
609 void
610 copyOutStat64Buf(TgtStatPtr tgt, HostStatPtr host,
611  bool fakeTTY=false)
612 {
613  copyOutStatBuf<OS>(tgt, host, fakeTTY);
614 #if defined(STAT_HAVE_NSEC)
615  constexpr ByteOrder bo = OS::byteOrder;
616 
617  tgt->st_atime_nsec = host->st_atime_nsec;
618  tgt->st_atime_nsec = htog(tgt->st_atime_nsec, bo);
619  tgt->st_mtime_nsec = host->st_mtime_nsec;
620  tgt->st_mtime_nsec = htog(tgt->st_mtime_nsec, bo);
621  tgt->st_ctime_nsec = host->st_ctime_nsec;
622  tgt->st_ctime_nsec = htog(tgt->st_ctime_nsec, bo);
623 #else
624  tgt->st_atime_nsec = 0;
625  tgt->st_mtime_nsec = 0;
626  tgt->st_ctime_nsec = 0;
627 #endif
628 }
629 
630 template <class OS, typename TgtStatPtr, typename HostStatPtr>
631 void
632 copyOutStatfsBuf(TgtStatPtr tgt, HostStatPtr host)
633 {
634  constexpr ByteOrder bo = OS::byteOrder;
635 
636  tgt->f_type = htog(host->f_type, bo);
637 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
638  tgt->f_bsize = htog(host->f_iosize, bo);
639 #else
640  tgt->f_bsize = htog(host->f_bsize, bo);
641 #endif
642  tgt->f_blocks = htog(host->f_blocks, bo);
643  tgt->f_bfree = htog(host->f_bfree, bo);
644  tgt->f_bavail = htog(host->f_bavail, bo);
645  tgt->f_files = htog(host->f_files, bo);
646  tgt->f_ffree = htog(host->f_ffree, bo);
647  memcpy(&tgt->f_fsid, &host->f_fsid, sizeof(host->f_fsid));
648 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
649  tgt->f_namelen = htog(host->f_namemax, bo);
650  tgt->f_frsize = htog(host->f_bsize, bo);
651 #elif defined(__APPLE__)
652  tgt->f_namelen = 0;
653  tgt->f_frsize = 0;
654 #else
655  tgt->f_namelen = htog(host->f_namelen, bo);
656  tgt->f_frsize = htog(host->f_frsize, bo);
657 #endif
658 #if defined(__linux__)
659  memcpy(&tgt->f_spare, &host->f_spare,
660  std::min(sizeof(host->f_spare), sizeof(tgt->f_spare)));
661 #else
662  /*
663  * The fields are different sizes per OS. Don't bother with
664  * f_spare or f_reserved on non-Linux for now.
665  */
666  memset(&tgt->f_spare, 0, sizeof(tgt->f_spare));
667 #endif
668 }
669 
674 template <class OS>
677  int tgt_fd, unsigned req, Addr addr)
678 {
679  auto p = tc->getProcessPtr();
680 
681  DPRINTF_SYSCALL(Verbose, "ioctl(%d, 0x%x, ...)\n", tgt_fd, req);
682 
683  if (OS::isTtyReq(req))
684  return -ENOTTY;
685 
686  auto dfdp = std::dynamic_pointer_cast<DeviceFDEntry>((*p->fds)[tgt_fd]);
687  if (dfdp) {
688  EmulatedDriver *emul_driver = dfdp->getDriver();
689  if (emul_driver)
690  return emul_driver->ioctl(tc, req, addr);
691  }
692 
693  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
694  if (sfdp) {
695  int status;
696 
697  switch (req) {
698  case SIOCGIFCONF: {
699  BufferArg conf_arg(addr, sizeof(ifconf));
700  conf_arg.copyIn(tc->getVirtProxy());
701 
702  ifconf *conf = (ifconf*)conf_arg.bufferPtr();
703  Addr ifc_buf_addr = (Addr)conf->ifc_buf;
704  BufferArg ifc_buf_arg(ifc_buf_addr, conf->ifc_len);
705  ifc_buf_arg.copyIn(tc->getVirtProxy());
706 
707  conf->ifc_buf = (char*)ifc_buf_arg.bufferPtr();
708 
709  status = ioctl(sfdp->getSimFD(), req, conf_arg.bufferPtr());
710  if (status != -1) {
711  conf->ifc_buf = (char*)ifc_buf_addr;
712  ifc_buf_arg.copyOut(tc->getVirtProxy());
713  conf_arg.copyOut(tc->getVirtProxy());
714  }
715 
716  return status;
717  }
718  case SIOCGIFFLAGS:
719 #if defined(__linux__)
720  case SIOCGIFINDEX:
721 #endif
722  case SIOCGIFNETMASK:
723  case SIOCGIFADDR:
724 #if defined(__linux__)
725  case SIOCGIFHWADDR:
726 #endif
727  case SIOCGIFMTU: {
728  BufferArg req_arg(addr, sizeof(ifreq));
729  req_arg.copyIn(tc->getVirtProxy());
730 
731  status = ioctl(sfdp->getSimFD(), req, req_arg.bufferPtr());
732  if (status != -1)
733  req_arg.copyOut(tc->getVirtProxy());
734  return status;
735  }
736  }
737  }
738 
743  warn("Unsupported ioctl call (return ENOTTY): ioctl(%d, 0x%x, ...) @ \n",
744  tgt_fd, req, tc->pcState());
745  return -ENOTTY;
746 }
747 
749 template <class OS>
752  int tgt_dirfd, Addr pathname, int tgt_flags, int mode)
753 {
754  auto p = tc->getProcessPtr();
755 
760  std::string path;
761  if (!tc->getVirtProxy().tryReadString(path, pathname))
762  return -EFAULT;
763 
764 #ifdef __CYGWIN32__
765  int host_flags = O_BINARY;
766 #else
767  int host_flags = 0;
768 #endif
769 
773  for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) {
774  if (tgt_flags & OS::openFlagTable[i].tgtFlag) {
775  tgt_flags &= ~OS::openFlagTable[i].tgtFlag;
776  host_flags |= OS::openFlagTable[i].hostFlag;
777  }
778  }
779  if (tgt_flags)
780  warn("%s: cannot decode flags %#x", desc->name(), tgt_flags);
781 
782 #ifdef __CYGWIN32__
783  host_flags |= O_BINARY;
784 #endif
785 
798  std::string redir_path = path;
799  std::string abs_path = path;
800  if (tgt_dirfd == OS::TGT_AT_FDCWD) {
801  abs_path = p->absolutePath(path, true);
802  redir_path = p->checkPathRedirect(path);
803  } else if (!startswith(path, "/")) {
804  std::shared_ptr<FDEntry> fdep = ((*p->fds)[tgt_dirfd]);
805  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
806  if (!ffdp)
807  return -EBADF;
808  abs_path = ffdp->getFileName() + path;
809  redir_path = p->checkPathRedirect(abs_path);
810  }
811 
818  if (startswith(abs_path, "/dev/")) {
819  std::string filename = abs_path.substr(strlen("/dev/"));
820  EmulatedDriver *drv = p->findDriver(filename);
821  if (drv) {
822  DPRINTF_SYSCALL(Verbose, "%s: passing call to "
823  "driver open with path[%s]\n",
824  desc->name(), abs_path.c_str());
825  return drv->open(tc, mode, host_flags);
826  }
831  }
832 
857  int sim_fd = -1;
858  std::string used_path;
859  std::vector<std::string> special_paths =
860  { "/proc/meminfo/", "/system/", "/platform/", "/etc/passwd",
861  "/proc/self/maps", "/dev/urandom",
862  "/sys/devices/system/cpu/online" };
863  for (auto entry : special_paths) {
864  if (startswith(path, entry)) {
865  sim_fd = OS::openSpecialFile(abs_path, p, tc);
866  used_path = abs_path;
867  }
868  }
869  if (sim_fd == -1) {
870  sim_fd = open(redir_path.c_str(), host_flags, mode);
871  used_path = redir_path;
872  }
873  if (sim_fd == -1) {
874  int local = -errno;
875  DPRINTF_SYSCALL(Verbose, "%s: failed -> path:%s "
876  "(inferred from:%s)\n", desc->name(),
877  used_path.c_str(), path.c_str());
878  return local;
879  }
880 
889  auto ffdp = std::make_shared<FileFDEntry>(sim_fd, host_flags, path, 0);
890  int tgt_fd = p->fds->allocFD(ffdp);
891  DPRINTF_SYSCALL(Verbose, "%s: sim_fd[%d], target_fd[%d] -> path:%s\n"
892  "(inferred from:%s)\n", desc->name(),
893  sim_fd, tgt_fd, used_path.c_str(), path.c_str());
894  return tgt_fd;
895 }
896 
898 template <class OS>
901  Addr pathname, int tgt_flags, int mode)
902 {
903  return openatFunc<OS>(
904  desc, tc, OS::TGT_AT_FDCWD, pathname, tgt_flags, mode);
905 }
906 
908 template <class OS>
910 unlinkatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, Addr pathname)
911 {
912  if (dirfd != OS::TGT_AT_FDCWD)
913  warn("unlinkat: first argument not AT_FDCWD; unlikely to work");
914 
915  return unlinkFunc(desc, tc, pathname);
916 }
917 
919 template <class OS>
922  int dirfd, Addr pathname, int mode)
923 {
924  if (dirfd != OS::TGT_AT_FDCWD)
925  warn("faccessat: first argument not AT_FDCWD; unlikely to work");
926  return accessFunc(desc, tc, pathname, mode);
927 }
928 
930 template <class OS>
933  int dirfd, Addr pathname, Addr buf, size_t bufsiz)
934 {
935  if (dirfd != OS::TGT_AT_FDCWD)
936  warn("openat: first argument not AT_FDCWD; unlikely to work");
937  return readlinkFunc(desc, tc, pathname, buf, bufsiz);
938 }
939 
941 template <class OS>
944  int olddirfd, Addr oldpath, int newdirfd, Addr newpath)
945 {
946  if (olddirfd != OS::TGT_AT_FDCWD)
947  warn("renameat: first argument not AT_FDCWD; unlikely to work");
948 
949  if (newdirfd != OS::TGT_AT_FDCWD)
950  warn("renameat: third argument not AT_FDCWD; unlikely to work");
951 
952  return renameFunc(desc, tc, oldpath, newpath);
953 }
954 
956 template <class OS>
960 {
961  auto process = tc->getProcessPtr();
962 
963  sysinfo->uptime = seconds_since_epoch;
964  sysinfo->totalram = process->system->memSize();
965  sysinfo->mem_unit = 1;
966 
967  return 0;
968 }
969 
971 template <class OS>
973 chmodFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, mode_t mode)
974 {
975  std::string path;
976  auto process = tc->getProcessPtr();
977 
978  if (!tc->getVirtProxy().tryReadString(path, pathname))
979  return -EFAULT;
980 
981  mode_t hostMode = 0;
982 
983  // XXX translate mode flags via OS::something???
984  hostMode = mode;
985 
986  // Adjust path for cwd and redirection
987  path = process->checkPathRedirect(path);
988 
989  // do the chmod
990  int result = chmod(path.c_str(), hostMode);
991  if (result < 0)
992  return -errno;
993 
994  return 0;
995 }
996 
997 template <class OS>
1000  Addr fdsPtr, int nfds, int tmout)
1001 {
1002  auto p = tc->getProcessPtr();
1003 
1004  BufferArg fdsBuf(fdsPtr, sizeof(struct pollfd) * nfds);
1005  fdsBuf.copyIn(tc->getVirtProxy());
1006 
1013  int temp_tgt_fds[nfds];
1014  for (int index = 0; index < nfds; index++) {
1015  temp_tgt_fds[index] = ((struct pollfd *)fdsBuf.bufferPtr())[index].fd;
1016  auto tgt_fd = temp_tgt_fds[index];
1017  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
1018  if (!hbfdp)
1019  return -EBADF;
1020  auto host_fd = hbfdp->getSimFD();
1021  ((struct pollfd *)fdsBuf.bufferPtr())[index].fd = host_fd;
1022  }
1023 
1030  int status;
1031  if (tmout < 0) {
1032  status = poll((struct pollfd *)fdsBuf.bufferPtr(), nfds, 0);
1033  if (status == 0) {
1039  System *sysh = tc->getSystemPtr();
1041  for (it=sysh->signalList.begin(); it!=sysh->signalList.end(); it++)
1042  if (it->receiver == p)
1043  return -EINTR;
1044  return SyscallReturn::retry();
1045  }
1046  } else
1047  status = poll((struct pollfd *)fdsBuf.bufferPtr(), nfds, 0);
1048 
1049  if (status == -1)
1050  return -errno;
1051 
1056  for (int index = 0; index < nfds; index++) {
1057  auto tgt_fd = temp_tgt_fds[index];
1058  ((struct pollfd *)fdsBuf.bufferPtr())[index].fd = tgt_fd;
1059  }
1060 
1065  fdsBuf.copyOut(tc->getVirtProxy());
1066 
1067  return status;
1068 }
1069 
1071 template <class OS>
1073 fchmodFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint32_t mode)
1074 {
1075  auto p = tc->getProcessPtr();
1076 
1077  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1078  if (!ffdp)
1079  return -EBADF;
1080  int sim_fd = ffdp->getSimFD();
1081 
1082  mode_t hostMode = mode;
1083 
1084  int result = fchmod(sim_fd, hostMode);
1085 
1086  return (result < 0) ? -errno : 0;
1087 }
1088 
1090 template <class OS>
1093  Addr start, uint64_t old_length, uint64_t new_length, uint64_t flags,
1095 {
1096  auto p = tc->getProcessPtr();
1097  Addr page_bytes = tc->getSystemPtr()->getPageBytes();
1098  uint64_t provided_address = 0;
1099  bool use_provided_address = flags & OS::TGT_MREMAP_FIXED;
1100 
1101  if (use_provided_address)
1102  provided_address = varargs.get<uint64_t>();
1103 
1104  if ((start % page_bytes != 0) ||
1105  (provided_address % page_bytes != 0)) {
1106  warn("mremap failing: arguments not page aligned");
1107  return -EINVAL;
1108  }
1109 
1110  new_length = roundUp(new_length, page_bytes);
1111 
1112  if (new_length > old_length) {
1113  Addr mmap_end = p->memState->getMmapEnd();
1114 
1115  if ((start + old_length) == mmap_end &&
1116  (!use_provided_address || provided_address == start)) {
1117  // This case cannot occur when growing downward, as
1118  // start is greater than or equal to mmap_end.
1119  uint64_t diff = new_length - old_length;
1120  p->memState->mapRegion(mmap_end, diff, "remapped");
1121  p->memState->setMmapEnd(mmap_end + diff);
1122  return start;
1123  } else {
1124  if (!use_provided_address && !(flags & OS::TGT_MREMAP_MAYMOVE)) {
1125  warn("can't remap here and MREMAP_MAYMOVE flag not set\n");
1126  return -ENOMEM;
1127  } else {
1128  uint64_t new_start = provided_address;
1129  if (!use_provided_address) {
1130  new_start = p->mmapGrowsDown() ?
1131  mmap_end - new_length : mmap_end;
1132  mmap_end = p->mmapGrowsDown() ?
1133  new_start : mmap_end + new_length;
1134  p->memState->setMmapEnd(mmap_end);
1135  }
1136 
1137  warn("mremapping to new vaddr %08p-%08p, adding %d\n",
1138  new_start, new_start + new_length,
1139  new_length - old_length);
1140 
1141  // add on the remaining unallocated pages
1142  p->allocateMem(new_start + old_length,
1143  new_length - old_length,
1144  use_provided_address /* clobber */);
1145 
1146  if (use_provided_address &&
1147  ((new_start + new_length > p->memState->getMmapEnd() &&
1148  !p->mmapGrowsDown()) ||
1149  (new_start < p->memState->getMmapEnd() &&
1150  p->mmapGrowsDown()))) {
1151  // something fishy going on here, at least notify the user
1152  // @todo: increase mmap_end?
1153  warn("mmap region limit exceeded with MREMAP_FIXED\n");
1154  }
1155 
1156  warn("returning %08p as start\n", new_start);
1157  p->memState->remapRegion(start, new_start, old_length);
1158  return new_start;
1159  }
1160  }
1161  } else {
1162  // Shrink a region
1163  if (use_provided_address && provided_address != start)
1164  p->memState->remapRegion(start, provided_address, new_length);
1165  if (new_length != old_length)
1166  p->memState->unmapRegion(start + new_length,
1167  old_length - new_length);
1168  return use_provided_address ? provided_address : start;
1169  }
1170 }
1171 
1173 template <class OS>
1176  Addr pathname, VPtr<typename OS::tgt_stat> tgt_stat)
1177 {
1178  std::string path;
1179  auto process = tc->getProcessPtr();
1180 
1181  if (!tc->getVirtProxy().tryReadString(path, pathname))
1182  return -EFAULT;
1183 
1184  // Adjust path for cwd and redirection
1185  path = process->checkPathRedirect(path);
1186 
1187  struct stat hostBuf;
1188  int result = stat(path.c_str(), &hostBuf);
1189 
1190  if (result < 0)
1191  return -errno;
1192 
1193  copyOutStatBuf<OS>(tgt_stat, &hostBuf);
1194 
1195  return 0;
1196 }
1197 
1198 
1200 template <class OS>
1203  Addr pathname, VPtr<typename OS::tgt_stat64> tgt_stat)
1204 {
1205  std::string path;
1206  auto process = tc->getProcessPtr();
1207 
1208  if (!tc->getVirtProxy().tryReadString(path, pathname))
1209  return -EFAULT;
1210 
1211  // Adjust path for cwd and redirection
1212  path = process->checkPathRedirect(path);
1213 
1214 #if NO_STAT64
1215  struct stat hostBuf;
1216  int result = stat(path.c_str(), &hostBuf);
1217 #else
1218  struct stat64 hostBuf;
1219  int result = stat64(path.c_str(), &hostBuf);
1220 #endif
1221 
1222  if (result < 0)
1223  return -errno;
1224 
1225  copyOutStat64Buf<OS>(tgt_stat, &hostBuf);
1226 
1227  return 0;
1228 }
1229 
1230 
1232 template <class OS>
1235  int dirfd, Addr pathname, VPtr<typename OS::tgt_stat64> tgt_stat)
1236 {
1237  auto process = tc->getProcessPtr();
1238  if (dirfd != OS::TGT_AT_FDCWD)
1239  warn("fstatat64: first argument not AT_FDCWD; unlikely to work");
1240 
1241  std::string path;
1242  if (!tc->getVirtProxy().tryReadString(path, pathname))
1243  return -EFAULT;
1244 
1245  // Adjust path for cwd and redirection
1246  path = process->checkPathRedirect(path);
1247 
1248 #if NO_STAT64
1249  struct stat hostBuf;
1250  int result = stat(path.c_str(), &hostBuf);
1251 #else
1252  struct stat64 hostBuf;
1253  int result = stat64(path.c_str(), &hostBuf);
1254 #endif
1255 
1256  if (result < 0)
1257  return -errno;
1258 
1259  copyOutStat64Buf<OS>(tgt_stat, &hostBuf);
1260 
1261  return 0;
1262 }
1263 
1264 
1266 template <class OS>
1269  int tgt_fd, VPtr<typename OS::tgt_stat64> tgt_stat)
1270 {
1271  auto p = tc->getProcessPtr();
1272 
1273  auto ffdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
1274  if (!ffdp)
1275  return -EBADF;
1276  int sim_fd = ffdp->getSimFD();
1277 
1278 #if NO_STAT64
1279  struct stat hostBuf;
1280  int result = fstat(sim_fd, &hostBuf);
1281 #else
1282  struct stat64 hostBuf;
1283  int result = fstat64(sim_fd, &hostBuf);
1284 #endif
1285 
1286  if (result < 0)
1287  return -errno;
1288 
1289  copyOutStat64Buf<OS>(tgt_stat, &hostBuf, (sim_fd == 1));
1290 
1291  return 0;
1292 }
1293 
1294 
1296 template <class OS>
1299  Addr pathname, VPtr<typename OS::tgt_stat> tgt_stat)
1300 {
1301  std::string path;
1302  auto process = tc->getProcessPtr();
1303 
1304  if (!tc->getVirtProxy().tryReadString(path, pathname))
1305  return -EFAULT;
1306 
1307  // Adjust path for cwd and redirection
1308  path = process->checkPathRedirect(path);
1309 
1310  struct stat hostBuf;
1311  int result = lstat(path.c_str(), &hostBuf);
1312 
1313  if (result < 0)
1314  return -errno;
1315 
1316  copyOutStatBuf<OS>(tgt_stat, &hostBuf);
1317 
1318  return 0;
1319 }
1320 
1322 template <class OS>
1325  Addr pathname, VPtr<typename OS::tgt_stat64> tgt_stat)
1326 {
1327  std::string path;
1328  auto process = tc->getProcessPtr();
1329 
1330  if (!tc->getVirtProxy().tryReadString(path, pathname))
1331  return -EFAULT;
1332 
1333  // Adjust path for cwd and redirection
1334  path = process->checkPathRedirect(path);
1335 
1336 #if NO_STAT64
1337  struct stat hostBuf;
1338  int result = lstat(path.c_str(), &hostBuf);
1339 #else
1340  struct stat64 hostBuf;
1341  int result = lstat64(path.c_str(), &hostBuf);
1342 #endif
1343 
1344  if (result < 0)
1345  return -errno;
1346 
1347  copyOutStat64Buf<OS>(tgt_stat, &hostBuf);
1348 
1349  return 0;
1350 }
1351 
1353 template <class OS>
1356  int tgt_fd, VPtr<typename OS::tgt_stat> tgt_stat)
1357 {
1358  auto p = tc->getProcessPtr();
1359 
1360  DPRINTF_SYSCALL(Verbose, "fstat(%d, ...)\n", tgt_fd);
1361 
1362  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1363  if (!ffdp)
1364  return -EBADF;
1365  int sim_fd = ffdp->getSimFD();
1366 
1367  struct stat hostBuf;
1368  int result = fstat(sim_fd, &hostBuf);
1369 
1370  if (result < 0)
1371  return -errno;
1372 
1373  copyOutStatBuf<OS>(tgt_stat, &hostBuf, (sim_fd == 1));
1374 
1375  return 0;
1376 }
1377 
1379 template <class OS>
1382  Addr pathname, VPtr<typename OS::tgt_statfs> tgt_stat)
1383 {
1384 #if defined(__linux__)
1385  std::string path;
1386  auto process = tc->getProcessPtr();
1387 
1388  if (!tc->getVirtProxy().tryReadString(path, pathname))
1389  return -EFAULT;
1390 
1391  // Adjust path for cwd and redirection
1392  path = process->checkPathRedirect(path);
1393 
1394  struct statfs hostBuf;
1395  int result = statfs(path.c_str(), &hostBuf);
1396 
1397  if (result < 0)
1398  return -errno;
1399 
1400  copyOutStatfsBuf<OS>(tgt_stat, &hostBuf);
1401  return 0;
1402 #else
1403  warnUnsupportedOS("statfs");
1404  return -1;
1405 #endif
1406 }
1407 
1408 template <class OS>
1410 cloneFunc(SyscallDesc *desc, ThreadContext *tc, RegVal flags, RegVal newStack,
1411  Addr ptidPtr, Addr ctidPtr, Addr tlsPtr)
1412 {
1413  auto p = tc->getProcessPtr();
1414 
1415  if (((flags & OS::TGT_CLONE_SIGHAND)&& !(flags & OS::TGT_CLONE_VM)) ||
1416  ((flags & OS::TGT_CLONE_THREAD) && !(flags & OS::TGT_CLONE_SIGHAND)) ||
1417  ((flags & OS::TGT_CLONE_FS) && (flags & OS::TGT_CLONE_NEWNS)) ||
1418  ((flags & OS::TGT_CLONE_NEWIPC) && (flags & OS::TGT_CLONE_SYSVSEM)) ||
1419  ((flags & OS::TGT_CLONE_NEWPID) && (flags & OS::TGT_CLONE_THREAD)) ||
1420  ((flags & OS::TGT_CLONE_VM) && !(newStack)))
1421  return -EINVAL;
1422 
1423  ThreadContext *ctc;
1424  if (!(ctc = tc->getSystemPtr()->threads.findFree())) {
1425  DPRINTF_SYSCALL(Verbose, "clone: no spare thread context in system"
1426  "[cpu %d, thread %d]", tc->cpuId(), tc->threadId());
1427  return -EAGAIN;
1428  }
1429 
1436  ProcessParams *pp = new ProcessParams();
1437  pp->executable.assign(*(new std::string(p->progName())));
1438  pp->cmd.push_back(*(new std::string(p->progName())));
1439  pp->system = p->system;
1440  pp->cwd.assign(p->tgtCwd);
1441  pp->input.assign("stdin");
1442  pp->output.assign("stdout");
1443  pp->errout.assign("stderr");
1444  pp->uid = p->uid();
1445  pp->euid = p->euid();
1446  pp->gid = p->gid();
1447  pp->egid = p->egid();
1448 
1449  /* Find the first free PID that's less than the maximum */
1450  std::set<int> const& pids = p->system->PIDs;
1451  int temp_pid = *pids.begin();
1452  do {
1453  temp_pid++;
1454  } while (pids.find(temp_pid) != pids.end());
1455  if (temp_pid >= System::maxPID)
1456  fatal("temp_pid is too large: %d", temp_pid);
1457 
1458  pp->pid = temp_pid;
1459  pp->ppid = (flags & OS::TGT_CLONE_THREAD) ? p->ppid() : p->pid();
1460  pp->useArchPT = p->useArchPT;
1461  pp->kvmInSE = p->kvmInSE;
1462  Process *cp = pp->create();
1463  // TODO: there is no way to know when the Process SimObject is done with
1464  // the params pointer. Both the params pointer (pp) and the process
1465  // pointer (cp) are normally managed in python and are never cleaned up.
1466 
1467  Process *owner = ctc->getProcessPtr();
1468  ctc->setProcessPtr(cp);
1469  cp->assignThreadContext(ctc->contextId());
1470  owner->revokeThreadContext(ctc->contextId());
1471 
1472  if (flags & OS::TGT_CLONE_PARENT_SETTID) {
1473  BufferArg ptidBuf(ptidPtr, sizeof(long));
1474  long *ptid = (long *)ptidBuf.bufferPtr();
1475  *ptid = cp->pid();
1476  ptidBuf.copyOut(tc->getVirtProxy());
1477  }
1478 
1479  if (flags & OS::TGT_CLONE_THREAD) {
1480  cp->pTable->shared = true;
1481  cp->useForClone = true;
1482  }
1483  cp->initState();
1484  p->clone(tc, ctc, cp, flags);
1485 
1486  if (flags & OS::TGT_CLONE_THREAD) {
1487  delete cp->sigchld;
1488  cp->sigchld = p->sigchld;
1489  } else if (flags & OS::TGT_SIGCHLD) {
1490  *cp->sigchld = true;
1491  }
1492 
1493  if (flags & OS::TGT_CLONE_CHILD_SETTID) {
1494  BufferArg ctidBuf(ctidPtr, sizeof(long));
1495  long *ctid = (long *)ctidBuf.bufferPtr();
1496  *ctid = cp->pid();
1497  ctidBuf.copyOut(ctc->getVirtProxy());
1498  }
1499 
1500  if (flags & OS::TGT_CLONE_CHILD_CLEARTID)
1501  cp->childClearTID = (uint64_t)ctidPtr;
1502 
1503  ctc->clearArchRegs();
1504 
1505  OS::archClone(flags, p, cp, tc, ctc, newStack, tlsPtr);
1506 
1507  desc->returnInto(ctc, 0);
1508 
1509 #if THE_ISA == SPARC_ISA
1512 #endif
1513 
1514  TheISA::PCState cpc = tc->pcState();
1515  if (!p->kvmInSE)
1516  cpc.advance();
1517  ctc->pcState(cpc);
1518  ctc->activate();
1519 
1520  return cp->pid();
1521 }
1522 
1523 template <class OS>
1526  RegVal newStack, Addr ptidPtr, Addr tlsPtr, Addr ctidPtr)
1527 {
1528  return cloneFunc<OS>(desc, tc, flags, newStack, ptidPtr, ctidPtr, tlsPtr);
1529 }
1530 
1532 template <class OS>
1535  int tgt_fd, VPtr<typename OS::tgt_statfs> tgt_stat)
1536 {
1537  auto p = tc->getProcessPtr();
1538 
1539  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1540  if (!ffdp)
1541  return -EBADF;
1542  int sim_fd = ffdp->getSimFD();
1543 
1544  struct statfs hostBuf;
1545  int result = fstatfs(sim_fd, &hostBuf);
1546 
1547  if (result < 0)
1548  return -errno;
1549 
1550  copyOutStatfsBuf<OS>(tgt_stat, &hostBuf);
1551 
1552  return 0;
1553 }
1554 
1556 template <class OS>
1559  int tgt_fd, uint64_t tiov_base, size_t count)
1560 {
1561  auto p = tc->getProcessPtr();
1562 
1563  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1564  if (!ffdp)
1565  return -EBADF;
1566  int sim_fd = ffdp->getSimFD();
1567 
1568  PortProxy &prox = tc->getVirtProxy();
1569  typename OS::tgt_iovec tiov[count];
1570  struct iovec hiov[count];
1571  for (size_t i = 0; i < count; ++i) {
1572  prox.readBlob(tiov_base + (i * sizeof(typename OS::tgt_iovec)),
1573  &tiov[i], sizeof(typename OS::tgt_iovec));
1574  hiov[i].iov_len = gtoh(tiov[i].iov_len, OS::byteOrder);
1575  hiov[i].iov_base = new char [hiov[i].iov_len];
1576  }
1577 
1578  int result = readv(sim_fd, hiov, count);
1579  int local_errno = errno;
1580 
1581  for (size_t i = 0; i < count; ++i) {
1582  if (result != -1) {
1583  prox.writeBlob(htog(tiov[i].iov_base, OS::byteOrder),
1584  hiov[i].iov_base, hiov[i].iov_len);
1585  }
1586  delete [] (char *)hiov[i].iov_base;
1587  }
1588 
1589  return (result == -1) ? -local_errno : result;
1590 }
1591 
1593 template <class OS>
1596  int tgt_fd, uint64_t tiov_base, size_t count)
1597 {
1598  auto p = tc->getProcessPtr();
1599 
1600  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
1601  if (!hbfdp)
1602  return -EBADF;
1603  int sim_fd = hbfdp->getSimFD();
1604 
1605  PortProxy &prox = tc->getVirtProxy();
1606  struct iovec hiov[count];
1607  for (size_t i = 0; i < count; ++i) {
1608  typename OS::tgt_iovec tiov;
1609 
1610  prox.readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec),
1611  &tiov, sizeof(typename OS::tgt_iovec));
1612  hiov[i].iov_len = gtoh(tiov.iov_len, OS::byteOrder);
1613  hiov[i].iov_base = new char [hiov[i].iov_len];
1614  prox.readBlob(gtoh(tiov.iov_base, OS::byteOrder), hiov[i].iov_base,
1615  hiov[i].iov_len);
1616  }
1617 
1618  int result = writev(sim_fd, hiov, count);
1619 
1620  for (size_t i = 0; i < count; ++i)
1621  delete [] (char *)hiov[i].iov_base;
1622 
1623  return (result == -1) ? -errno : result;
1624 }
1625 
1627 template <class OS>
1630  Addr start, typename OS::size_t length, int prot,
1631  int tgt_flags, int tgt_fd, typename OS::off_t offset)
1632 {
1633  auto p = tc->getProcessPtr();
1634  Addr page_bytes = tc->getSystemPtr()->getPageBytes();
1635 
1636  if (start & (page_bytes - 1) ||
1637  offset & (page_bytes - 1) ||
1638  (tgt_flags & OS::TGT_MAP_PRIVATE &&
1639  tgt_flags & OS::TGT_MAP_SHARED) ||
1640  (!(tgt_flags & OS::TGT_MAP_PRIVATE) &&
1641  !(tgt_flags & OS::TGT_MAP_SHARED)) ||
1642  !length) {
1643  return -EINVAL;
1644  }
1645 
1646  if ((prot & PROT_WRITE) && (tgt_flags & OS::TGT_MAP_SHARED)) {
1647  // With shared mmaps, there are two cases to consider:
1648  // 1) anonymous: writes should modify the mapping and this should be
1649  // visible to observers who share the mapping. Currently, it's
1650  // difficult to update the shared mapping because there's no
1651  // structure which maintains information about the which virtual
1652  // memory areas are shared. If that structure existed, it would be
1653  // possible to make the translations point to the same frames.
1654  // 2) file-backed: writes should modify the mapping and the file
1655  // which is backed by the mapping. The shared mapping problem is the
1656  // same as what was mentioned about the anonymous mappings. For
1657  // file-backed mappings, the writes to the file are difficult
1658  // because it requires syncing what the mapping holds with the file
1659  // that resides on the host system. So, any write on a real system
1660  // would cause the change to be propagated to the file mapping at
1661  // some point in the future (the inode is tracked along with the
1662  // mapping). This isn't guaranteed to always happen, but it usually
1663  // works well enough. The guarantee is provided by the msync system
1664  // call. We could force the change through with shared mappings with
1665  // a call to msync, but that again would require more information
1666  // than we currently maintain.
1667  warn_once("mmap: writing to shared mmap region is currently "
1668  "unsupported. The write succeeds on the target, but it "
1669  "will not be propagated to the host or shared mappings");
1670  }
1671 
1672  length = roundUp(length, page_bytes);
1673 
1674  int sim_fd = -1;
1675  if (!(tgt_flags & OS::TGT_MAP_ANONYMOUS)) {
1676  std::shared_ptr<FDEntry> fdep = (*p->fds)[tgt_fd];
1677 
1678  auto dfdp = std::dynamic_pointer_cast<DeviceFDEntry>(fdep);
1679  if (dfdp) {
1680  EmulatedDriver *emul_driver = dfdp->getDriver();
1681  return emul_driver->mmap(tc, start, length, prot, tgt_flags,
1682  tgt_fd, offset);
1683  }
1684 
1685  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
1686  if (!ffdp)
1687  return -EBADF;
1688  sim_fd = ffdp->getSimFD();
1689 
1698  if (p->interpImage.contains(tc->pcState().instAddr())) {
1699  std::shared_ptr<FDEntry> fdep = (*p->fds)[tgt_fd];
1700  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
1701  auto *lib = Loader::createObjectFile(p->checkPathRedirect(
1702  ffdp->getFileName()));
1703  DPRINTF_SYSCALL(Verbose, "Loading symbols from %s\n",
1704  ffdp->getFileName());
1705 
1706  if (lib) {
1707  Addr offset = lib->buildImage().minAddr() + start;
1708  Loader::debugSymbolTable.insert(*lib->symtab().offset(offset));
1709  }
1710  }
1711  }
1712 
1716  if (!(tgt_flags & OS::TGT_MAP_FIXED)) {
1724  if (!(start && p->memState->isUnmapped(start, length))) {
1728  start = p->memState->extendMmap(length);
1729  }
1730  }
1731 
1732  DPRINTF_SYSCALL(Verbose, " mmap range is 0x%x - 0x%x\n",
1733  start, start + length - 1);
1734 
1740  if (tgt_flags & OS::TGT_MAP_FIXED) {
1745  p->memState->unmapRegion(start, length);
1746  }
1747 
1751  std::string region_name;
1752  if (tgt_flags & OS::TGT_MAP_ANONYMOUS) {
1753  region_name = "anon";
1754  } else {
1755  std::shared_ptr<FDEntry> fdep = (*p->fds)[tgt_fd];
1756  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
1757  region_name = ffdp->getFileName();
1758  }
1759 
1764  p->memState->mapRegion(start, length, region_name, sim_fd, offset);
1765 
1766  return start;
1767 }
1768 
1769 template <class OS>
1772  int tgt_fd, Addr bufPtr, int nbytes, int offset)
1773 {
1774  auto p = tc->getProcessPtr();
1775 
1776  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1777  if (!ffdp)
1778  return -EBADF;
1779  int sim_fd = ffdp->getSimFD();
1780 
1781  BufferArg bufArg(bufPtr, nbytes);
1782 
1783  int bytes_read = pread(sim_fd, bufArg.bufferPtr(), nbytes, offset);
1784 
1785  bufArg.copyOut(tc->getVirtProxy());
1786 
1787  return (bytes_read == -1) ? -errno : bytes_read;
1788 }
1789 
1790 template <class OS>
1793  int tgt_fd, Addr bufPtr, int nbytes, int offset)
1794 {
1795  auto p = tc->getProcessPtr();
1796 
1797  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1798  if (!ffdp)
1799  return -EBADF;
1800  int sim_fd = ffdp->getSimFD();
1801 
1802  BufferArg bufArg(bufPtr, nbytes);
1803  bufArg.copyIn(tc->getVirtProxy());
1804 
1805  int bytes_written = pwrite(sim_fd, bufArg.bufferPtr(), nbytes, offset);
1806 
1807  return (bytes_written == -1) ? -errno : bytes_written;
1808 }
1809 
1811 template <class OS>
1814  Addr start, typename OS::size_t length, int prot,
1815  int tgt_flags, int tgt_fd, typename OS::off_t offset)
1816 {
1817  return mmapFunc<OS>(desc, tc, start, length, prot, tgt_flags,
1818  tgt_fd, offset * tc->getSystemPtr()->getPageBytes());
1819 }
1820 
1822 template <class OS>
1825  unsigned resource, VPtr<typename OS::rlimit> rlp)
1826 {
1827  const ByteOrder bo = OS::byteOrder;
1828  switch (resource) {
1829  case OS::TGT_RLIMIT_STACK:
1830  // max stack size in bytes: make up a number (8MB for now)
1831  rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
1832  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
1833  rlp->rlim_max = htog(rlp->rlim_max, bo);
1834  break;
1835 
1836  case OS::TGT_RLIMIT_DATA:
1837  // max data segment size in bytes: make up a number
1838  rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024;
1839  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
1840  rlp->rlim_max = htog(rlp->rlim_max, bo);
1841  break;
1842 
1843  case OS::TGT_RLIMIT_NPROC:
1844  rlp->rlim_cur = rlp->rlim_max = tc->getSystemPtr()->threads.size();
1845  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
1846  rlp->rlim_max = htog(rlp->rlim_max, bo);
1847  break;
1848 
1849  default:
1850  warn("getrlimit: unimplemented resource %d", resource);
1851  return -EINVAL;
1852  break;
1853  }
1854 
1855  return 0;
1856 }
1857 
1858 template <class OS>
1861  int pid, int resource, Addr n, VPtr<typename OS::rlimit> rlp)
1862 {
1863  if (pid != 0) {
1864  warn("prlimit: ignoring rlimits for nonzero pid");
1865  return -EPERM;
1866  }
1867  if (n)
1868  warn("prlimit: ignoring new rlimit");
1869  if (rlp) {
1870  const ByteOrder bo = OS::byteOrder;
1871  switch (resource) {
1872  case OS::TGT_RLIMIT_STACK:
1873  // max stack size in bytes: make up a number (8MB for now)
1874  rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
1875  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
1876  rlp->rlim_max = htog(rlp->rlim_max, bo);
1877  break;
1878  case OS::TGT_RLIMIT_DATA:
1879  // max data segment size in bytes: make up a number
1880  rlp->rlim_cur = rlp->rlim_max = 256*1024*1024;
1881  rlp->rlim_cur = htog(rlp->rlim_cur, bo);
1882  rlp->rlim_max = htog(rlp->rlim_max, bo);
1883  break;
1884  default:
1885  warn("prlimit: unimplemented resource %d", resource);
1886  return -EINVAL;
1887  break;
1888  }
1889  }
1890  return 0;
1891 }
1892 
1894 template <class OS>
1897  int clk_id, VPtr<typename OS::timespec> tp)
1898 {
1899  getElapsedTimeNano(tp->tv_sec, tp->tv_nsec);
1900  tp->tv_sec += seconds_since_epoch;
1901  tp->tv_sec = htog(tp->tv_sec, OS::byteOrder);
1902  tp->tv_nsec = htog(tp->tv_nsec, OS::byteOrder);
1903 
1904  return 0;
1905 }
1906 
1908 template <class OS>
1912 {
1913  // Set resolution at ns, which is what clock_gettime() returns
1914  tp->tv_sec = 0;
1915  tp->tv_nsec = 1;
1916 
1917  return 0;
1918 }
1919 
1921 template <class OS>
1924  VPtr<typename OS::timeval> tp, Addr tz_ptr)
1925 {
1926  getElapsedTimeMicro(tp->tv_sec, tp->tv_usec);
1927  tp->tv_sec += seconds_since_epoch;
1928  tp->tv_sec = htog(tp->tv_sec, OS::byteOrder);
1929  tp->tv_usec = htog(tp->tv_usec, OS::byteOrder);
1930 
1931  return 0;
1932 }
1933 
1934 
1936 template <class OS>
1939  VPtr<typename OS::timeval [2]> tp)
1940 {
1941  std::string path;
1942  auto process = tc->getProcessPtr();
1943 
1944  if (!tc->getVirtProxy().tryReadString(path, pathname))
1945  return -EFAULT;
1946 
1947  struct timeval hostTimeval[2];
1948  for (int i = 0; i < 2; ++i) {
1949  hostTimeval[i].tv_sec = gtoh((*tp)[i].tv_sec, OS::byteOrder);
1950  hostTimeval[i].tv_usec = gtoh((*tp)[i].tv_usec, OS::byteOrder);
1951  }
1952 
1953  // Adjust path for cwd and redirection
1954  path = process->checkPathRedirect(path);
1955 
1956  int result = utimes(path.c_str(), hostTimeval);
1957 
1958  if (result < 0)
1959  return -errno;
1960 
1961  return 0;
1962 }
1963 
1964 template <class OS>
1967  Addr pathname, Addr argv_mem_loc, Addr envp_mem_loc)
1968 {
1969  auto p = tc->getProcessPtr();
1970 
1971  std::string path;
1972  PortProxy & mem_proxy = tc->getVirtProxy();
1973  if (!mem_proxy.tryReadString(path, pathname))
1974  return -EFAULT;
1975 
1976  if (access(path.c_str(), F_OK) == -1)
1977  return -EACCES;
1978 
1979  auto read_in = [](std::vector<std::string> &vect,
1980  PortProxy &mem_proxy, Addr mem_loc)
1981  {
1982  for (int inc = 0; ; inc++) {
1983  BufferArg b((mem_loc + sizeof(Addr) * inc), sizeof(Addr));
1984  b.copyIn(mem_proxy);
1985 
1986  if (!*(Addr*)b.bufferPtr())
1987  break;
1988 
1989  vect.push_back(std::string());
1990  mem_proxy.tryReadString(vect[inc], *(Addr*)b.bufferPtr());
1991  }
1992  };
1993 
2000  ProcessParams *pp = new ProcessParams();
2001  pp->executable = path;
2002  read_in(pp->cmd, mem_proxy, argv_mem_loc);
2003  read_in(pp->env, mem_proxy, envp_mem_loc);
2004  pp->uid = p->uid();
2005  pp->egid = p->egid();
2006  pp->euid = p->euid();
2007  pp->gid = p->gid();
2008  pp->ppid = p->ppid();
2009  pp->pid = p->pid();
2010  pp->input.assign("cin");
2011  pp->output.assign("cout");
2012  pp->errout.assign("cerr");
2013  pp->cwd.assign(p->tgtCwd);
2014  pp->system = p->system;
2023  p->system->PIDs.erase(p->pid());
2024  Process *new_p = pp->create();
2025  delete pp;
2026 
2031  new_p->fds = p->fds;
2032  for (int i = 0; i < new_p->fds->getSize(); i++) {
2033  std::shared_ptr<FDEntry> fdep = (*new_p->fds)[i];
2034  if (fdep && fdep->getCOE())
2035  new_p->fds->closeFDEntry(i);
2036  }
2037 
2038  *new_p->sigchld = true;
2039 
2040  delete p;
2041  tc->clearArchRegs();
2042  tc->setProcessPtr(new_p);
2043  new_p->assignThreadContext(tc->contextId());
2044  new_p->initState();
2045  tc->activate();
2046  TheISA::PCState pcState = tc->pcState();
2047  tc->setNPC(pcState.instAddr());
2048 
2049  return SyscallReturn();
2050 }
2051 
2053 template <class OS>
2056  int who /* THREAD, SELF, or CHILDREN */,
2058 {
2059  rup->ru_utime.tv_sec = 0;
2060  rup->ru_utime.tv_usec = 0;
2061  rup->ru_stime.tv_sec = 0;
2062  rup->ru_stime.tv_usec = 0;
2063  rup->ru_maxrss = 0;
2064  rup->ru_ixrss = 0;
2065  rup->ru_idrss = 0;
2066  rup->ru_isrss = 0;
2067  rup->ru_minflt = 0;
2068  rup->ru_majflt = 0;
2069  rup->ru_nswap = 0;
2070  rup->ru_inblock = 0;
2071  rup->ru_oublock = 0;
2072  rup->ru_msgsnd = 0;
2073  rup->ru_msgrcv = 0;
2074  rup->ru_nsignals = 0;
2075  rup->ru_nvcsw = 0;
2076  rup->ru_nivcsw = 0;
2077 
2078  switch (who) {
2079  case OS::TGT_RUSAGE_SELF:
2080  getElapsedTimeMicro(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec);
2081  rup->ru_utime.tv_sec = htog(rup->ru_utime.tv_sec, OS::byteOrder);
2082  rup->ru_utime.tv_usec = htog(rup->ru_utime.tv_usec, OS::byteOrder);
2083  break;
2084 
2085  case OS::TGT_RUSAGE_CHILDREN:
2086  // do nothing. We have no child processes, so they take no time.
2087  break;
2088 
2089  default:
2090  // don't really handle THREAD or CHILDREN, but just warn and
2091  // plow ahead
2092  warn("getrusage() only supports RUSAGE_SELF. Parameter %d ignored.",
2093  who);
2094  }
2095 
2096  return 0;
2097 }
2098 
2100 template <class OS>
2103 {
2104  // Fill in the time structure (in clocks)
2105  int64_t clocks = curTick() * OS::M5_SC_CLK_TCK / SimClock::Int::s;
2106  bufp->tms_utime = clocks;
2107  bufp->tms_stime = 0;
2108  bufp->tms_cutime = 0;
2109  bufp->tms_cstime = 0;
2110 
2111  // Convert to host endianness
2112  bufp->tms_utime = htog(bufp->tms_utime, OS::byteOrder);
2113 
2114  // Return clock ticks since system boot
2115  return clocks;
2116 }
2117 
2119 template <class OS>
2122 {
2123  typename OS::time_t sec, usec;
2124  getElapsedTimeMicro(sec, usec);
2125  sec += seconds_since_epoch;
2126 
2127  if (taddr != 0) {
2128  typename OS::time_t t = sec;
2129  t = htog(t, OS::byteOrder);
2130  PortProxy &p = tc->getVirtProxy();
2131  p.writeBlob(taddr, &t, (int)sizeof(typename OS::time_t));
2132  }
2133  return sec;
2134 }
2135 
2136 template <class OS>
2138 tgkillFunc(SyscallDesc *desc, ThreadContext *tc, int tgid, int tid, int sig)
2139 {
2155  System *sys = tc->getSystemPtr();
2156  Process *tgt_proc = nullptr;
2157  for (auto *tc: sys->threads) {
2158  Process *temp = tc->getProcessPtr();
2159  if (temp->pid() == tid) {
2160  tgt_proc = temp;
2161  break;
2162  }
2163  }
2164 
2165  if (sig != 0 || sig != OS::TGT_SIGABRT)
2166  return -EINVAL;
2167 
2168  if (tgt_proc == nullptr)
2169  return -ESRCH;
2170 
2171  if (tgid != -1 && tgt_proc->tgid() != tgid)
2172  return -ESRCH;
2173 
2174  if (sig == OS::TGT_SIGABRT)
2175  exitGroupFunc(desc, tc, 0);
2176 
2177  return 0;
2178 }
2179 
2180 template <class OS>
2183  int domain, int type, int prot)
2184 {
2185  auto p = tc->getProcessPtr();
2186 
2187  int sim_fd = socket(domain, type, prot);
2188  if (sim_fd == -1)
2189  return -errno;
2190 
2191  auto sfdp = std::make_shared<SocketFDEntry>(sim_fd, domain, type, prot);
2192  int tgt_fd = p->fds->allocFD(sfdp);
2193 
2194  return tgt_fd;
2195 }
2196 
2197 template <class OS>
2200  int domain, int type, int prot, Addr svPtr)
2201 {
2202  auto p = tc->getProcessPtr();
2203 
2204  BufferArg svBuf((Addr)svPtr, 2 * sizeof(int));
2205  int status = socketpair(domain, type, prot, (int *)svBuf.bufferPtr());
2206  if (status == -1)
2207  return -errno;
2208 
2209  int *fds = (int *)svBuf.bufferPtr();
2210 
2211  auto sfdp1 = std::make_shared<SocketFDEntry>(fds[0], domain, type, prot);
2212  fds[0] = p->fds->allocFD(sfdp1);
2213  auto sfdp2 = std::make_shared<SocketFDEntry>(fds[1], domain, type, prot);
2214  fds[1] = p->fds->allocFD(sfdp2);
2215  svBuf.copyOut(tc->getVirtProxy());
2216 
2217  return status;
2218 }
2219 
2220 template <class OS>
2222 selectFunc(SyscallDesc *desc, ThreadContext *tc, int nfds,
2223  VPtr<typename OS::fd_set> readfds,
2224  VPtr<typename OS::fd_set> writefds,
2225  VPtr<typename OS::fd_set> errorfds,
2227 {
2228  int retval;
2229 
2230  auto p = tc->getProcessPtr();
2231 
2237  fd_set readfds_h;
2238  FD_ZERO(&readfds_h);
2239  fd_set writefds_h;
2240  FD_ZERO(&writefds_h);
2241  fd_set errorfds_h;
2242  FD_ZERO(&errorfds_h);
2243 
2253  int nfds_h = 0;
2254  std::map<int, int> trans_map;
2255  auto try_add_host_set = [&](typename OS::fd_set *tgt_set_entry,
2256  fd_set *hst_set_entry,
2257  int iter) -> bool
2258  {
2264  if (FD_ISSET(iter, (fd_set *)tgt_set_entry)) {
2270  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[iter]);
2271  if (!hbfdp)
2272  return true;
2273  auto sim_fd = hbfdp->getSimFD();
2274 
2280  trans_map[sim_fd] = iter;
2281 
2287  nfds_h = std::max(nfds_h - 1, sim_fd + 1);
2288 
2293  FD_SET(sim_fd, hst_set_entry);
2294  }
2295  return false;
2296  };
2297 
2298  for (int i = 0; i < nfds; i++) {
2299  if (readfds) {
2300  bool ebadf = try_add_host_set(readfds, &readfds_h, i);
2301  if (ebadf)
2302  return -EBADF;
2303  }
2304  if (writefds) {
2305  bool ebadf = try_add_host_set(writefds, &writefds_h, i);
2306  if (ebadf)
2307  return -EBADF;
2308  }
2309  if (errorfds) {
2310  bool ebadf = try_add_host_set(errorfds, &errorfds_h, i);
2311  if (ebadf)
2312  return -EBADF;
2313  }
2314  }
2315 
2316  if (timeout) {
2324  timeout->tv_sec = 0;
2325  timeout->tv_usec = 0;
2326 
2327  retval = select(nfds_h,
2328  readfds ? &readfds_h : nullptr,
2329  writefds ? &writefds_h : nullptr,
2330  errorfds ? &errorfds_h : nullptr,
2331  (timeval *)(typename OS::timeval *)timeout);
2332  } else {
2340  struct timeval tv = { 0, 0 };
2341 
2342  retval = select(nfds_h,
2343  readfds ? &readfds_h : nullptr,
2344  readfds ? &writefds_h : nullptr,
2345  readfds ? &errorfds_h : nullptr,
2346  &tv);
2347 
2348  if (retval == 0) {
2354  for (auto sig : tc->getSystemPtr()->signalList)
2355  if (sig.receiver == p)
2356  return -EINTR;
2357  return SyscallReturn::retry();
2358  }
2359  }
2360 
2361  if (retval == -1)
2362  return -errno;
2363 
2364  FD_ZERO(reinterpret_cast<fd_set *>((typename OS::fd_set *)readfds));
2365  FD_ZERO(reinterpret_cast<fd_set *>((typename OS::fd_set *)writefds));
2366  FD_ZERO(reinterpret_cast<fd_set *>((typename OS::fd_set *)errorfds));
2367 
2373  for (int i = 0; i < nfds_h; i++) {
2374  if (readfds && FD_ISSET(i, &readfds_h))
2375  FD_SET(trans_map[i], readfds);
2376 
2377  if (writefds && FD_ISSET(i, &writefds_h))
2378  FD_SET(trans_map[i], writefds);
2379 
2380  if (errorfds && FD_ISSET(i, &errorfds_h))
2381  FD_SET(trans_map[i], errorfds);
2382  }
2383 
2384  return retval;
2385 }
2386 
2387 template <class OS>
2390  int tgt_fd, Addr buf_ptr, int nbytes)
2391 {
2392  auto p = tc->getProcessPtr();
2393 
2394  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
2395  if (!hbfdp)
2396  return -EBADF;
2397  int sim_fd = hbfdp->getSimFD();
2398 
2399  struct pollfd pfd;
2400  pfd.fd = sim_fd;
2401  pfd.events = POLLIN | POLLPRI;
2402  if ((poll(&pfd, 1, 0) == 0)
2403  && !(hbfdp->getFlags() & OS::TGT_O_NONBLOCK))
2404  return SyscallReturn::retry();
2405 
2406  BufferArg buf_arg(buf_ptr, nbytes);
2407  int bytes_read = read(sim_fd, buf_arg.bufferPtr(), nbytes);
2408 
2409  if (bytes_read > 0)
2410  buf_arg.copyOut(tc->getVirtProxy());
2411 
2412  return (bytes_read == -1) ? -errno : bytes_read;
2413 }
2414 
2415 template <class OS>
2418  int tgt_fd, Addr buf_ptr, int nbytes)
2419 {
2420  auto p = tc->getProcessPtr();
2421 
2422  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
2423  if (!hbfdp)
2424  return -EBADF;
2425  int sim_fd = hbfdp->getSimFD();
2426 
2427  BufferArg buf_arg(buf_ptr, nbytes);
2428  buf_arg.copyIn(tc->getVirtProxy());
2429 
2430  struct pollfd pfd;
2431  pfd.fd = sim_fd;
2432  pfd.events = POLLOUT;
2433 
2440  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(hbfdp);
2441  if (ffdp && (ffdp->getFileName() != "/dev/random")) {
2442  if (!poll(&pfd, 1, 0) && !(ffdp->getFlags() & OS::TGT_O_NONBLOCK))
2443  return SyscallReturn::retry();
2444  }
2445 
2446  int bytes_written = write(sim_fd, buf_arg.bufferPtr(), nbytes);
2447 
2448  if (bytes_written != -1)
2449  fsync(sim_fd);
2450 
2451  return (bytes_written == -1) ? -errno : bytes_written;
2452 }
2453 
2454 template <class OS>
2457  pid_t pid, Addr statPtr, int options, Addr rusagePtr)
2458 {
2459  auto p = tc->getProcessPtr();
2460 
2461  if (rusagePtr)
2462  DPRINTF_SYSCALL(Verbose, "wait4: rusage pointer provided %lx, however "
2463  "functionality not supported. Ignoring rusage pointer.\n",
2464  rusagePtr);
2465 
2474  System *sysh = tc->getSystemPtr();
2476  for (iter=sysh->signalList.begin(); iter!=sysh->signalList.end(); iter++) {
2477  if (iter->receiver == p) {
2478  if (pid < -1) {
2479  if ((iter->sender->pgid() == -pid)
2480  && (iter->signalValue == OS::TGT_SIGCHLD))
2481  goto success;
2482  } else if (pid == -1) {
2483  if (iter->signalValue == OS::TGT_SIGCHLD)
2484  goto success;
2485  } else if (pid == 0) {
2486  if ((iter->sender->pgid() == p->pgid())
2487  && (iter->signalValue == OS::TGT_SIGCHLD))
2488  goto success;
2489  } else {
2490  if ((iter->sender->pid() == pid)
2491  && (iter->signalValue == OS::TGT_SIGCHLD))
2492  goto success;
2493  }
2494  }
2495  }
2496 
2497  return (options & OS::TGT_WNOHANG) ? 0 : SyscallReturn::retry();
2498 
2499 success:
2500  // Set status to EXITED for WIFEXITED evaluations.
2501  const int EXITED = 0;
2502  BufferArg statusBuf(statPtr, sizeof(int));
2503  *(int *)statusBuf.bufferPtr() = EXITED;
2504  statusBuf.copyOut(tc->getVirtProxy());
2505 
2506  // Return the child PID.
2507  pid_t retval = iter->sender->pid();
2508  sysh->signalList.erase(iter);
2509  return retval;
2510 }
2511 
2512 template <class OS>
2515  int tgt_fd, Addr addrPtr, Addr lenPtr)
2516 {
2517  struct sockaddr sa;
2518  socklen_t addrLen;
2519  int host_fd;
2520  auto p = tc->getProcessPtr();
2521 
2522  BufferArg *lenBufPtr = nullptr;
2523  BufferArg *addrBufPtr = nullptr;
2524 
2525  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
2526  if (!sfdp)
2527  return -EBADF;
2528  int sim_fd = sfdp->getSimFD();
2529 
2536  struct pollfd pfd;
2537  pfd.fd = sim_fd;
2538  pfd.events = POLLIN | POLLPRI;
2539  if ((poll(&pfd, 1, 0) == 0) && !(sfdp->getFlags() & OS::TGT_O_NONBLOCK))
2540  return SyscallReturn::retry();
2541 
2542  if (lenPtr) {
2543  lenBufPtr = new BufferArg(lenPtr, sizeof(socklen_t));
2544  lenBufPtr->copyIn(tc->getVirtProxy());
2545  memcpy(&addrLen, (socklen_t *)lenBufPtr->bufferPtr(),
2546  sizeof(socklen_t));
2547  }
2548 
2549  if (addrPtr) {
2550  addrBufPtr = new BufferArg(addrPtr, sizeof(struct sockaddr));
2551  addrBufPtr->copyIn(tc->getVirtProxy());
2552  memcpy(&sa, (struct sockaddr *)addrBufPtr->bufferPtr(),
2553  sizeof(struct sockaddr));
2554  }
2555 
2556  host_fd = accept(sim_fd, &sa, &addrLen);
2557 
2558  if (host_fd == -1)
2559  return -errno;
2560 
2561  if (addrPtr) {
2562  memcpy(addrBufPtr->bufferPtr(), &sa, sizeof(sa));
2563  addrBufPtr->copyOut(tc->getVirtProxy());
2564  delete(addrBufPtr);
2565  }
2566 
2567  if (lenPtr) {
2568  *(socklen_t *)lenBufPtr->bufferPtr() = addrLen;
2569  lenBufPtr->copyOut(tc->getVirtProxy());
2570  delete(lenBufPtr);
2571  }
2572 
2573  auto afdp = std::make_shared<SocketFDEntry>(host_fd, sfdp->_domain,
2574  sfdp->_type, sfdp->_protocol);
2575  return p->fds->allocFD(afdp);
2576 }
2577 
2579 template <class OS>
2582  unsigned initval, int in_flags)
2583 {
2584 #if defined(__linux__)
2585  auto p = tc->getProcessPtr();
2586 
2587  int sim_fd = eventfd(initval, in_flags);
2588  if (sim_fd == -1)
2589  return -errno;
2590 
2591  bool cloexec = in_flags & OS::TGT_O_CLOEXEC;
2592 
2593  int flags = cloexec ? OS::TGT_O_CLOEXEC : 0;
2594  flags |= (in_flags & OS::TGT_O_NONBLOCK) ? OS::TGT_O_NONBLOCK : 0;
2595 
2596  auto hbfdp = std::make_shared<HBFDEntry>(flags, sim_fd, cloexec);
2597  int tgt_fd = p->fds->allocFD(hbfdp);
2598  return tgt_fd;
2599 #else
2600  warnUnsupportedOS("eventfd");
2601  return -1;
2602 #endif
2603 }
2604 
2605 #endif // __SIM_SYSCALL_EMUL_HH__
System::signalList
std::list< BasicSignal > signalList
Definition: system.hh:627
syscall_debug_macros.hh
fatal
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:183
FutexMap::suspend
void suspend(Addr addr, uint64_t tgid, ThreadContext *tc)
Inserts a futex into the map with one waiting TC.
Definition: futex_map.cc:62
ArmISA::status
Bitfield< 5, 0 > status
Definition: miscregs_types.hh:417
dup2Func
SyscallReturn dup2Func(SyscallDesc *desc, ThreadContext *tc, int old_tgt_fd, int new_tgt_fd)
Target dup2() handler.
Definition: syscall_emul.cc:691
EmulatedDriver::open
virtual int open(ThreadContext *tc, int mode, int flags)=0
Abstract method, invoked when the user program calls open() on the device driver.
SimClock::Int::ns
Tick ns
nanosecond
Definition: core.cc:65
getrusageFunc
SyscallReturn getrusageFunc(SyscallDesc *desc, ThreadContext *tc, int who, VPtr< typename OS::rusage > rup)
Target getrusage() function.
Definition: syscall_emul.hh:2055
warn
#define warn(...)
Definition: logging.hh:239
length
uint8_t length
Definition: inet.hh:422
linux.hh
fstatat64Func
SyscallReturn fstatat64Func(SyscallDesc *desc, ThreadContext *tc, int dirfd, Addr pathname, VPtr< typename OS::tgt_stat64 > tgt_stat)
Target fstatat64() handler.
Definition: syscall_emul.hh:1234
mmap2Func
SyscallReturn mmap2Func(SyscallDesc *desc, ThreadContext *tc, Addr start, typename OS::size_t length, int prot, int tgt_flags, int tgt_fd, typename OS::off_t offset)
Target mmap2() handler.
Definition: syscall_emul.hh:1813
renameFunc
SyscallReturn renameFunc(SyscallDesc *desc, ThreadContext *tc, Addr oldpath, Addr newpath)
Target rename() handler.
Definition: syscall_emul.cc:523
ioctlFunc
SyscallReturn ioctlFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, unsigned req, Addr addr)
Target ioctl() handler.
Definition: syscall_emul.hh:676
tgkillFunc
SyscallReturn tgkillFunc(SyscallDesc *desc, ThreadContext *tc, int tgid, int tid, int sig)
Definition: syscall_emul.hh:2138
FutexMap::wakeup
int wakeup(Addr addr, uint64_t tgid, int count)
Wakes up at most count waiting threads on a futex.
Definition: futex_map.cc:68
gethostnameFunc
SyscallReturn gethostnameFunc(SyscallDesc *desc, ThreadContext *tc, Addr buf_ptr, int name_len)
Target gethostname() handler.
Definition: syscall_emul.cc:354
readvFunc
SyscallReturn readvFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint64_t tiov_base, size_t count)
Target readv() handler.
Definition: syscall_emul.hh:1558
ThreadContext::activate
virtual void activate()=0
Set the status to Active.
fstatfsFunc
SyscallReturn fstatfsFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr< typename OS::tgt_statfs > tgt_stat)
Target fstatfs() handler.
Definition: syscall_emul.hh:1534
warnUnsupportedOS
void warnUnsupportedOS(std::string syscall_name)
Definition: syscall_emul.cc:60
MipsISA::index
Bitfield< 30, 0 > index
Definition: pra_constants.hh:44
lstat64Func
SyscallReturn lstat64Func(SyscallDesc *desc, ThreadContext *tc, Addr pathname, VPtr< typename OS::tgt_stat64 > tgt_stat)
Target lstat64() handler.
Definition: syscall_emul.hh:1324
ArmISA::byteOrder
ByteOrder byteOrder(const ThreadContext *tc)
Definition: utility.hh:449
Process::fds
std::shared_ptr< FDArray > fds
Definition: process.hh:276
Process::assignThreadContext
void assignThreadContext(ContextID context_id)
Definition: process.hh:120
warn_once
#define warn_once(...)
Definition: logging.hh:243
ArmISA::i
Bitfield< 7 > i
Definition: miscregs_types.hh:63
System::getPageBytes
Addr getPageBytes() const
Get the page bytes for the ISA.
Definition: system.hh:396
Process
Definition: process.hh:65
pipe2Func
SyscallReturn pipe2Func(SyscallDesc *desc, ThreadContext *tc, Addr tgt_addr, int flags)
Target pipe() handler.
Definition: syscall_emul.cc:802
ProxyPtr
Definition: proxy_ptr.hh:236
cloneFunc
SyscallReturn cloneFunc(SyscallDesc *desc, ThreadContext *tc, RegVal flags, RegVal newStack, Addr ptidPtr, Addr ctidPtr, Addr tlsPtr)
Definition: syscall_emul.hh:1410
symlinkFunc
SyscallReturn symlinkFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, Addr new_pathname)
Target symlink() handler.
Definition: syscall_emul.cc:488
FutexMap::suspend_bitset
void suspend_bitset(Addr addr, uint64_t tgid, ThreadContext *tc, int bitmask)
Definition: futex_map.cc:98
ArmISA::fd
Bitfield< 14, 12 > fd
Definition: types.hh:159
truncateFunc
SyscallReturn truncateFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, off_t length)
Target truncate() handler.
Definition: syscall_emul.cc:544
getpgrpFunc
SyscallReturn getpgrpFunc(SyscallDesc *desc, ThreadContext *tc)
Target getpgrpFunc() handler.
Definition: syscall_emul.cc:887
ignoreFunc
SyscallReturn ignoreFunc(SyscallDesc *desc, ThreadContext *tc)
Handler for unimplemented syscalls that we never intend to implement (signal handling,...
Definition: syscall_emul.cc:73
type
uint8_t type
Definition: inet.hh:421
tlb.hh
ThreadContext::setIntReg
virtual void setIntReg(RegIndex reg_idx, RegVal val)=0
chownFunc
SyscallReturn chownFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, uint32_t owner, uint32_t group)
Target chown() handler.
Definition: syscall_emul.cc:625
statfsFunc
SyscallReturn statfsFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, VPtr< typename OS::tgt_statfs > tgt_stat)
Target statfs() handler.
Definition: syscall_emul.hh:1381
Loader::createObjectFile
ObjectFile * createObjectFile(const std::string &fname, bool raw)
Definition: object_file.cc:61
SimClock::Int::us
Tick us
microsecond
Definition: core.cc:64
futex_map.hh
recvfromFunc
SyscallReturn recvfromFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr bufrPtr, size_t bufrLen, int flags, Addr addrPtr, Addr addrlenPtr)
Definition: syscall_emul.cc:1220
prlimitFunc
SyscallReturn prlimitFunc(SyscallDesc *desc, ThreadContext *tc, int pid, int resource, Addr n, VPtr< typename OS::rlimit > rlp)
Definition: syscall_emul.hh:1860
FutexMap
FutexMap class holds a map of all futexes used in the system.
Definition: futex_map.hh:90
PowerISA::bo
Bitfield< 25, 21 > bo
Definition: types.hh:62
System::maxPID
static const int maxPID
Definition: system.hh:620
X86ISA::op
Bitfield< 4 > op
Definition: types.hh:78
utimesFunc
SyscallReturn utimesFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, VPtr< typename OS::timeval[2]> tp)
Target utimes() handler.
Definition: syscall_emul.hh:1938
mremapFunc
SyscallReturn mremapFunc(SyscallDesc *desc, ThreadContext *tc, Addr start, uint64_t old_length, uint64_t new_length, uint64_t flags, GuestABI::VarArgs< uint64_t > varargs)
Target mremap() handler.
Definition: syscall_emul.hh:1092
munmapFunc
SyscallReturn munmapFunc(SyscallDesc *desc, ThreadContext *tc, Addr start, size_t length)
Target munmap() handler.
Definition: syscall_emul.cc:331
std::vector< std::string >
brkFunc
SyscallReturn brkFunc(SyscallDesc *desc, ThreadContext *tc, Addr new_brk)
Target brk() handler: set brk address.
Definition: syscall_emul.cc:249
proxy_ptr.hh
ThreadContext::getProcessPtr
virtual Process * getProcessPtr()=0
X86ISA::count
count
Definition: misc.hh:703
syscall_emul_buf.hh
copyOutStatBuf
void copyOutStatBuf(TgtStatPtr tgt, HostStatPtr host, bool fakeTTY=false)
Definition: syscall_emul.hh:561
gettimeofdayFunc
SyscallReturn gettimeofdayFunc(SyscallDesc *desc, ThreadContext *tc, VPtr< typename OS::timeval > tp, Addr tz_ptr)
Target gettimeofday() handler.
Definition: syscall_emul.hh:1923
setpgidFunc
SyscallReturn setpgidFunc(SyscallDesc *desc, ThreadContext *tc, int pid, int pgid)
Target setpgid() handler.
Definition: syscall_emul.cc:894
hst_stat64
struct stat64 hst_stat64
Definition: syscall_emul.hh:552
getsockoptFunc
SyscallReturn getsockoptFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int level, int optname, Addr valPtr, Addr lenPtr)
Definition: syscall_emul.cc:1517
copyOutStatfsBuf
void copyOutStatfsBuf(TgtStatPtr tgt, HostStatPtr host)
Definition: syscall_emul.hh:632
writeFunc
SyscallReturn writeFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr buf_ptr, int nbytes)
Definition: syscall_emul.hh:2417
getppidFunc
SyscallReturn getppidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getppid() handler.
Definition: syscall_emul.cc:942
getsocknameFunc
SyscallReturn getsocknameFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr addrPtr, Addr lenPtr)
Definition: syscall_emul.cc:1555
ThreadContext::threadId
virtual int threadId() const =0
System::Threads::findFree
ThreadContext * findFree()
Definition: system.cc:155
sc_dt::inc
void inc(scfx_mant &mant)
Definition: scfx_mant.hh:341
connectFunc
SyscallReturn connectFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr buf_ptr, int addrlen)
Definition: syscall_emul.cc:1199
acceptFunc
SyscallReturn acceptFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr addrPtr, Addr lenPtr)
Definition: syscall_emul.hh:2514
fallocateFunc
SyscallReturn fallocateFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int mode, off_t offset, off_t len)
Definition: syscall_emul.cc:977
socketFunc
SyscallReturn socketFunc(SyscallDesc *desc, ThreadContext *tc, int domain, int type, int prot)
Definition: syscall_emul.hh:2182
timesFunc
SyscallReturn timesFunc(SyscallDesc *desc, ThreadContext *tc, VPtr< typename OS::tms > bufp)
Target times() function.
Definition: syscall_emul.hh:2102
PortProxy::writeBlob
void writeBlob(Addr addr, const void *p, int size) const
Same as tryWriteBlob, but insists on success.
Definition: port_proxy.hh:187
execveFunc
SyscallReturn execveFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, Addr argv_mem_loc, Addr envp_mem_loc)
Definition: syscall_emul.hh:1966
GuestABI::VarArgs::get
Arg get()
Definition: varargs.hh:161
openatFunc
SyscallReturn openatFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_dirfd, Addr pathname, int tgt_flags, int mode)
Target open() handler.
Definition: syscall_emul.hh:751
ArmISA::SyscallPseudoReturnReg
const int SyscallPseudoReturnReg
Definition: registers.hh:131
ArmISA::n
Bitfield< 31 > n
Definition: miscregs_types.hh:450
mmapFunc
SyscallReturn mmapFunc(SyscallDesc *desc, ThreadContext *tc, Addr start, typename OS::size_t length, int prot, int tgt_flags, int tgt_fd, typename OS::off_t offset)
Target mmap() handler.
Definition: syscall_emul.hh:1629
Process::revokeThreadContext
void revokeThreadContext(int context_id)
After delegating a thread context to a child process no longer should relate to the ThreadContext.
Definition: process.cc:267
Process::tgid
uint64_t tgid()
Definition: process.hh:88
EmulatedDriver
EmulatedDriver is an abstract base class for fake SE-mode device drivers.
Definition: emul_driver.hh:52
Loader::debugSymbolTable
SymbolTable debugSymbolTable
Global unified debugging symbol table (for target).
Definition: symtab.cc:47
cp
Definition: cprintf.cc:40
ThreadContext::clearArchRegs
virtual void clearArchRegs()=0
getElapsedTimeNano
void getElapsedTimeNano(T1 &sec, T2 &nsec)
Helper function to convert current elapsed time to seconds and nanoseconds.
Definition: syscall_emul.hh:530
pollFunc
SyscallReturn pollFunc(SyscallDesc *desc, ThreadContext *tc, Addr fdsPtr, int nfds, int tmout)
Definition: syscall_emul.hh:999
ftruncateFunc
SyscallReturn ftruncateFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, off_t length)
Target ftruncate() handler.
Definition: syscall_emul.cc:560
syscall_return.hh
socketpairFunc
SyscallReturn socketpairFunc(SyscallDesc *desc, ThreadContext *tc, int domain, int type, int prot, Addr svPtr)
Definition: syscall_emul.hh:2199
ThreadContext
ThreadContext is the external interface to all thread state for anything outside of the CPU.
Definition: thread_context.hh:88
SyscallDesc::name
std::string name() const
Definition: syscall_desc.hh:76
GuestABI::VarArgs
Definition: varargs.hh:146
lstatFunc
SyscallReturn lstatFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, VPtr< typename OS::tgt_stat > tgt_stat)
Target lstat() handler.
Definition: syscall_emul.hh:1298
System
Definition: system.hh:73
exitGroupFunc
SyscallReturn exitGroupFunc(SyscallDesc *desc, ThreadContext *tc, int status)
Target exit_group() handler: terminate simulation. (exit all threads)
Definition: syscall_emul.cc:236
Process::checkPathRedirect
std::string checkPathRedirect(const std::string &filename)
Redirect file path if it matches any keys initialized by system object.
Definition: process.cc:403
lseekFunc
SyscallReturn lseekFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint64_t offs, int whence)
Target lseek() handler.
Definition: syscall_emul.cc:287
getegidFunc
SyscallReturn getegidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getegid() handler.
Definition: syscall_emul.cc:970
System::futexMap
FutexMap futexMap
Definition: system.hh:618
DPRINTF_SYSCALL
#define DPRINTF_SYSCALL(FLAGEXT, FMT,...)
This macro is intended to help with readability.
Definition: syscall_debug_macros.hh:57
exitFunc
SyscallReturn exitFunc(SyscallDesc *desc, ThreadContext *tc, int status)
Target exit() handler: terminate current context.
Definition: syscall_emul.cc:230
htog
T htog(T value, ByteOrder guest_byte_order)
Definition: byteswap.hh:155
ArmISA::sa
Bitfield< 3 > sa
Definition: miscregs_types.hh:386
listenFunc
SyscallReturn listenFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int backlog)
Definition: syscall_emul.cc:1184
Process::sigchld
bool * sigchld
Definition: process.hh:288
setTidAddressFunc
SyscallReturn setTidAddressFunc(SyscallDesc *desc, ThreadContext *tc, uint64_t tidPtr)
Target set_tid_address() handler.
Definition: syscall_emul.cc:271
setsockoptFunc
SyscallReturn setsockoptFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int level, int optname, Addr valPtr, socklen_t len)
Definition: syscall_emul.cc:1619
SimClock::Int::s
Tick s
second
Definition: core.cc:62
process.hh
ArmISA::mode
Bitfield< 4, 0 > mode
Definition: miscregs_types.hh:70
unlinkFunc
SyscallReturn unlinkFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname)
Target unlink() handler.
Definition: syscall_emul.cc:452
unlinkatFunc
SyscallReturn unlinkatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, Addr pathname)
Target unlinkat() handler.
Definition: syscall_emul.hh:910
getpidFunc
SyscallReturn getpidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getpid() handler.
Definition: syscall_emul.cc:928
selectFunc
SyscallReturn selectFunc(SyscallDesc *desc, ThreadContext *tc, int nfds, VPtr< typename OS::fd_set > readfds, VPtr< typename OS::fd_set > writefds, VPtr< typename OS::fd_set > errorfds, VPtr< typename OS::timeval > timeout)
Definition: syscall_emul.hh:2222
ThreadContext::cpuId
virtual int cpuId() const =0
X86ISA::prot
Bitfield< 7 > prot
Definition: misc.hh:582
sysinfoFunc
SyscallReturn sysinfoFunc(SyscallDesc *desc, ThreadContext *tc, VPtr< typename OS::tgt_sysinfo > sysinfo)
Target sysinfo() handler.
Definition: syscall_emul.hh:958
System::Threads::size
int size() const
Definition: system.hh:204
openFunc
SyscallReturn openFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, int tgt_flags, int mode)
Target open() handler.
Definition: syscall_emul.hh:900
ThreadContext::contextId
virtual ContextID contextId() const =0
clock_gettimeFunc
SyscallReturn clock_gettimeFunc(SyscallDesc *desc, ThreadContext *tc, int clk_id, VPtr< typename OS::timespec > tp)
Target clock_gettime() function.
Definition: syscall_emul.hh:1896
fchownFunc
SyscallReturn fchownFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint32_t owner, uint32_t group)
Target fchown() handler.
Definition: syscall_emul.cc:646
bindFunc
SyscallReturn bindFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr buf_ptr, int addrlen)
Definition: syscall_emul.cc:1163
getgidFunc
SyscallReturn getgidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getgid() handler.
Definition: syscall_emul.cc:963
EmulatedDriver::mmap
virtual Addr mmap(ThreadContext *tc, Addr start, uint64_t length, int prot, int tgtFlags, int tgtFd, int offset)
Virtual method, invoked when the user program calls mmap() on the file descriptor returned by a previ...
Definition: emul_driver.hh:95
ThreadContext::setNPC
void setNPC(Addr val)
Definition: thread_context.hh:263
X86ISA::val
Bitfield< 63 > val
Definition: misc.hh:769
umaskFunc
SyscallReturn umaskFunc(SyscallDesc *desc, ThreadContext *tc)
Target umask() handler.
Definition: syscall_emul.cc:614
rmdirFunc
SyscallReturn rmdirFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname)
Definition: syscall_emul.cc:1057
ftruncate64Func
SyscallReturn ftruncate64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int64_t length)
Target ftruncate64() handler.
Definition: syscall_emul.cc:595
Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
statFunc
SyscallReturn statFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, VPtr< typename OS::tgt_stat > tgt_stat)
Target stat() handler.
Definition: syscall_emul.hh:1175
SyscallReturn
This class represents the return value from an emulated system call, including any errno setting.
Definition: syscall_return.hh:52
eventfdFunc
SyscallReturn eventfdFunc(SyscallDesc *desc, ThreadContext *tc, unsigned initval, int in_flags)
Target eventfd() function.
Definition: syscall_emul.hh:2581
clock_getresFunc
SyscallReturn clock_getresFunc(SyscallDesc *desc, ThreadContext *tc, int clk_id, VPtr< typename OS::timespec > tp)
Target clock_getres() function.
Definition: syscall_emul.hh:1910
BaseBufferArg::copyIn
bool copyIn(PortProxy &memproxy)
copy data into simulator space (read from target memory)
Definition: syscall_emul_buf.hh:77
readlinkFunc
SyscallReturn readlinkFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, Addr buf, size_t bufsiz)
Target readlink() handler.
Definition: syscall_emul.cc:394
BufferArg::bufferPtr
void * bufferPtr()
Return a pointer to the internal simulator-space buffer.
Definition: syscall_emul_buf.hh:115
getrlimitFunc
SyscallReturn getrlimitFunc(SyscallDesc *desc, ThreadContext *tc, unsigned resource, VPtr< typename OS::rlimit > rlp)
Target getrlimit() handler.
Definition: syscall_emul.hh:1824
ThreadContext::pcState
virtual TheISA::PCState pcState() const =0
pipePseudoFunc
SyscallReturn pipePseudoFunc(SyscallDesc *desc, ThreadContext *tc)
Pseudo Funcs - These functions use a different return convension, returning a second value in a regis...
Definition: syscall_emul.cc:790
mknodFunc
SyscallReturn mknodFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, mode_t mode, dev_t dev)
Target mknod() handler.
Definition: syscall_emul.cc:1015
ThreadContext::getVirtProxy
virtual PortProxy & getVirtProxy()=0
FutexMap::requeue
int requeue(Addr addr1, uint64_t tgid, int count, int count2, Addr addr2)
This operation wakes a given number (val) of waiters.
Definition: futex_map.cc:150
readFunc
SyscallReturn readFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr buf_ptr, int nbytes)
Definition: syscall_emul.hh:2389
X86ISA::level
Bitfield< 20 > level
Definition: intmessage.hh:47
copyOutStat64Buf
void copyOutStat64Buf(TgtStatPtr tgt, HostStatPtr host, bool fakeTTY=false)
Definition: syscall_emul.hh:610
System::threads
Threads threads
Definition: system.hh:309
pread64Func
SyscallReturn pread64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr bufPtr, int nbytes, int offset)
Definition: syscall_emul.hh:1771
chdirFunc
SyscallReturn chdirFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname)
Target chdir() handler.
Definition: syscall_emul.cc:1030
hst_statfs
struct statfs hst_statfs
Definition: syscall_emul.hh:546
faccessatFunc
SyscallReturn faccessatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, Addr pathname, int mode)
Target facessat() handler.
Definition: syscall_emul.hh:921
recvmsgFunc
SyscallReturn recvmsgFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr msgPtr, int flags)
Definition: syscall_emul.cc:1312
PortProxy
This object is a proxy for a port or other object which implements the functional response protocol,...
Definition: port_proxy.hh:80
ArmISA::b
Bitfield< 7 > b
Definition: miscregs_types.hh:376
fcntlFunc
SyscallReturn fcntlFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int cmd, GuestABI::VarArgs< int > varargs)
Target fcntl() handler.
Definition: syscall_emul.cc:719
EmulatedDriver::ioctl
virtual int ioctl(ThreadContext *tc, unsigned req, Addr buf)=0
Abstract method, invoked when the user program calls ioctl() on the file descriptor returned by a pre...
base.hh
getcwdFunc
SyscallReturn getcwdFunc(SyscallDesc *desc, ThreadContext *tc, Addr buf_ptr, unsigned long size)
Target getcwd() handler.
Definition: syscall_emul.cc:364
fstatFunc
SyscallReturn fstatFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr< typename OS::tgt_stat > tgt_stat)
Target fstat() handler.
Definition: syscall_emul.hh:1355
std
Overload hash function for BasicBlockRange type.
Definition: vec_reg.hh:587
getcpuFunc
SyscallReturn getcpuFunc(SyscallDesc *desc, ThreadContext *tc, VPtr< uint32_t > cpu, VPtr< uint32_t > node, VPtr< uint32_t > tcache)
Definition: syscall_emul.cc:1639
MipsISA::PCState
GenericISA::DelaySlotPCState< MachInst > PCState
Definition: types.hh:41
types.hh
ArmISA::t
Bitfield< 5 > t
Definition: miscregs_types.hh:67
startswith
bool startswith(const char *s, const char *prefix)
Return true if 's' starts with the prefix string 'prefix'.
Definition: str.hh:224
_llseekFunc
SyscallReturn _llseekFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint64_t offset_high, uint32_t offset_low, Addr result_ptr, int whence)
Target _llseek() handler.
Definition: syscall_emul.cc:304
ArmISA::domain
Bitfield< 7, 4 > domain
Definition: miscregs_types.hh:418
sendtoFunc
SyscallReturn sendtoFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr bufrPtr, size_t bufrLen, int flags, Addr addrPtr, socklen_t addrLen)
Definition: syscall_emul.cc:1280
futexFunc
SyscallReturn futexFunc(SyscallDesc *desc, ThreadContext *tc, Addr uaddr, int op, int val, int timeout, Addr uaddr2, int val3)
Futex system call Implemented by Daniel Sanchez Used by printf's in multi-threaded apps.
Definition: syscall_emul.hh:372
Process::initState
void initState() override
initState() is called on each SimObject when not restoring from a checkpoint.
Definition: process.cc:290
roundUp
T roundUp(const T &val, const U &align)
This function is used to align addresses in memory.
Definition: intmath.hh:131
ignoreWarnOnceFunc
SyscallReturn ignoreWarnOnceFunc(SyscallDesc *desc, ThreadContext *tc)
Like above, but only prints a warning once per syscall desc it's used with.
Definition: syscall_emul.cc:80
truncate64Func
SyscallReturn truncate64Func(SyscallDesc *desc, ThreadContext *tc, Addr pathname, int64_t length)
Target truncate64() handler.
Definition: syscall_emul.cc:574
FutexMap::wakeup_bitset
int wakeup_bitset(Addr addr, uint64_t tgid, int bitmask)
Definition: futex_map.cc:117
pipeFunc
SyscallReturn pipeFunc(SyscallDesc *desc, ThreadContext *tc, Addr tgt_addr)
Target pipe() handler.
Definition: syscall_emul.cc:796
getpagesizeFunc
SyscallReturn getpagesizeFunc(SyscallDesc *desc, ThreadContext *tc)
Target getpagesize() handler.
Definition: syscall_emul.cc:242
ArmISA::len
Bitfield< 18, 16 > len
Definition: miscregs_types.hh:439
guest_abi.hh
SyscallDesc::returnInto
virtual void returnInto(ThreadContext *tc, const SyscallReturn &ret)=0
For use within the system call executor if new threads are created and need something returned into t...
readlinkatFunc
SyscallReturn readlinkatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, Addr pathname, Addr buf, size_t bufsiz)
Target readlinkat() handler.
Definition: syscall_emul.hh:932
addr
ip6_addr_t addr
Definition: inet.hh:423
geteuidFunc
SyscallReturn geteuidFunc(SyscallDesc *desc, ThreadContext *tc)
Target geteuid() handler.
Definition: syscall_emul.cc:956
logging.hh
getElapsedTimeMicro
void getElapsedTimeMicro(T1 &sec, T2 &usec)
Helper function to convert current elapsed time to seconds and microseconds.
Definition: syscall_emul.hh:517
emul_driver.hh
writevFunc
SyscallReturn writevFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint64_t tiov_base, size_t count)
Target writev() handler.
Definition: syscall_emul.hh:1595
chmodFunc
SyscallReturn chmodFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, mode_t mode)
Target chmod() handler.
Definition: syscall_emul.hh:973
renameatFunc
SyscallReturn renameatFunc(SyscallDesc *desc, ThreadContext *tc, int olddirfd, Addr oldpath, int newdirfd, Addr newpath)
Target renameat() handler.
Definition: syscall_emul.hh:943
hst_stat
struct stat hst_stat
Definition: syscall_emul.hh:551
getpeernameFunc
SyscallReturn getpeernameFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr sockAddrPtr, Addr addrlenPtr)
Definition: syscall_emul.cc:1592
trace.hh
gettidFunc
SyscallReturn gettidFunc(SyscallDesc *desc, ThreadContext *tc)
Target gettid() handler.
Definition: syscall_emul.cc:935
gtoh
T gtoh(T value, ByteOrder guest_byte_order)
Definition: byteswap.hh:162
Loader::SymbolTable::insert
bool insert(const Symbol &symbol)
Definition: symtab.cc:58
getuidFunc
SyscallReturn getuidFunc(SyscallDesc *desc, ThreadContext *tc)
Definition: syscall_emul.cc:949
fcntl64Func
SyscallReturn fcntl64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int cmd)
Target fcntl64() handler.
Definition: syscall_emul.cc:761
fchmodFunc
SyscallReturn fchmodFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint32_t mode)
Target fchmod() handler.
Definition: syscall_emul.hh:1073
SyscallReturn::retry
static SyscallReturn retry()
Pseudo-constructor to create an instance with the retry flag set.
Definition: syscall_return.hh:77
shutdownFunc
SyscallReturn shutdownFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int how)
Target shutdown() handler.
Definition: syscall_emul.cc:1148
MipsISA::p
Bitfield< 0 > p
Definition: pra_constants.hh:323
std::list
STL list class.
Definition: stl.hh:51
intmath.hh
BufferArg
BufferArg represents an untyped buffer in target user space that is passed by reference to an (emulat...
Definition: syscall_emul_buf.hh:103
closeFunc
SyscallReturn closeFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd)
Target close() handler.
Definition: syscall_emul.cc:280
fstat64Func
SyscallReturn fstat64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr< typename OS::tgt_stat64 > tgt_stat)
Target fstat64() handler.
Definition: syscall_emul.hh:1268
page_table.hh
seconds_since_epoch
const unsigned seconds_since_epoch
Approximate seconds since the epoch (1/1/1970).
Definition: syscall_emul.hh:511
cloneBackwardsFunc
SyscallReturn cloneBackwardsFunc(SyscallDesc *desc, ThreadContext *tc, RegVal flags, RegVal newStack, Addr ptidPtr, Addr tlsPtr, Addr ctidPtr)
Definition: syscall_emul.hh:1525
PortProxy::readBlob
void readBlob(Addr addr, void *p, int size) const
Higher level interfaces based on the above.
Definition: port_proxy.hh:177
PortProxy::tryReadString
bool tryReadString(std::string &str, Addr addr) const
Reads the string at guest address addr into the std::string str.
Definition: port_proxy.cc:100
stat64Func
SyscallReturn stat64Func(SyscallDesc *desc, ThreadContext *tc, Addr pathname, VPtr< typename OS::tgt_stat64 > tgt_stat)
Target stat64() handler.
Definition: syscall_emul.hh:1202
object_file.hh
linkFunc
SyscallReturn linkFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, Addr new_pathname)
Target link() handler.
Definition: syscall_emul.cc:467
pwrite64Func
SyscallReturn pwrite64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr bufPtr, int nbytes, int offset)
Definition: syscall_emul.hh:1792
unimplementedFunc
SyscallReturn unimplementedFunc(SyscallDesc *desc, ThreadContext *tc)
Handler for unimplemented syscalls that we haven't thought about.
Definition: syscall_emul.cc:66
thread_context.hh
sendmsgFunc
SyscallReturn sendmsgFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr msgPtr, int flags)
Definition: syscall_emul.cc:1450
RegVal
uint64_t RegVal
Definition: types.hh:168
Process::pid
uint64_t pid()
Definition: process.hh:84
SyscallDesc
This class provides the wrapper interface for the system call implementations which are defined in th...
Definition: syscall_desc.hh:66
syscall_desc.hh
ThreadContext::setProcessPtr
virtual void setProcessPtr(Process *p)=0
ThreadContext::getSystemPtr
virtual System * getSystemPtr()=0
mkdirFunc
SyscallReturn mkdirFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, mode_t mode)
Target mkdir() handler.
Definition: syscall_emul.cc:509
BaseBufferArg::copyOut
bool copyOut(PortProxy &memproxy)
copy data out of simulator space (write to target memory)
Definition: syscall_emul_buf.hh:87
accessFunc
SyscallReturn accessFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, mode_t mode)
Target access() handler.
Definition: syscall_emul.cc:999
timeFunc
SyscallReturn timeFunc(SyscallDesc *desc, ThreadContext *tc, Addr taddr)
Target time() function.
Definition: syscall_emul.hh:2121
curTick
Tick curTick()
The current simulated tick.
Definition: core.hh:45
ArmISA::offset
Bitfield< 23, 0 > offset
Definition: types.hh:153
wait4Func
SyscallReturn wait4Func(SyscallDesc *desc, ThreadContext *tc, pid_t pid, Addr statPtr, int options, Addr rusagePtr)
Definition: syscall_emul.hh:2456
dupFunc
SyscallReturn dupFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd)
Target dup() handler.
Definition: syscall_emul.cc:671

Generated on Wed Sep 30 2020 14:02:14 for gem5 by doxygen 1.8.17