42#ifndef __SIM_SYSCALL_EMUL_HH__
43#define __SIM_SYSCALL_EMUL_HH__
45#if (defined(__APPLE__) || defined(__OpenBSD__) || \
46 defined(__FreeBSD__) || defined(__CYGWIN__) || \
60#include <linux/kdev_t.h>
62#include <sys/eventfd.h>
63#include <sys/statfs.h>
79#include <sys/socket.h>
102#include "params/Process.hh"
113#if defined(__APPLE__) && defined(__MACH__) && !defined(CMSG_ALIGN)
114#define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
115#elif defined(__FreeBSD__) && !defined(CMSG_ALIGN)
116#define CMSG_ALIGN(n) _ALIGN(n)
139SyscallReturn
ignoreFunc(SyscallDesc *desc, ThreadContext *tc);
145SyscallReturn
exitFunc(SyscallDesc *desc, ThreadContext *tc,
int status);
158SyscallReturn
brkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> new_brk);
161SyscallReturn
closeFunc(SyscallDesc *desc, ThreadContext *tc,
int tgt_fd);
164SyscallReturn
_llseekFunc(SyscallDesc *desc, ThreadContext *tc,
165 int tgt_fd, uint32_t offset_high,
166 uint32_t offset_low, VPtr<> result_ptr,
int whence);
169SyscallReturn
shutdownFunc(SyscallDesc *desc, ThreadContext *tc,
170 int tgt_fd,
int how);
174 VPtr<> buf_ptr,
int name_len);
177SyscallReturn
unlinkFunc(SyscallDesc *desc, ThreadContext *tc,
179SyscallReturn
unlinkImpl(SyscallDesc *desc, ThreadContext *tc,
183SyscallReturn
linkFunc(SyscallDesc *desc, ThreadContext *tc,
184 VPtr<> pathname, VPtr<> new_pathname);
187SyscallReturn
symlinkFunc(SyscallDesc *desc, ThreadContext *tc,
188 VPtr<> pathname, VPtr<> new_pathname);
191SyscallReturn
mkdirFunc(SyscallDesc *desc, ThreadContext *tc,
192 VPtr<> pathname, mode_t
mode);
193SyscallReturn
mkdirImpl(SyscallDesc *desc, ThreadContext *tc,
194 std::string path, mode_t
mode);
197SyscallReturn
mknodFunc(SyscallDesc *desc, ThreadContext *tc,
198 VPtr<> pathname, mode_t
mode, dev_t dev);
199SyscallReturn
mknodImpl(SyscallDesc *desc, ThreadContext *tc,
200 std::string path, mode_t
mode, dev_t dev);
203SyscallReturn
chdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname);
206SyscallReturn
rmdirFunc(SyscallDesc *desc, ThreadContext *tc,
208SyscallReturn
rmdirImpl(SyscallDesc *desc, ThreadContext *tc,
212SyscallReturn
renameFunc(SyscallDesc *desc, ThreadContext *tc,
213 VPtr<> oldpath, VPtr<> newpath);
214SyscallReturn
renameImpl(SyscallDesc *desc, ThreadContext *tc,
215 std::string oldpath, std::string newpath);
219 VPtr<> pathname, int64_t length);
223 int tgt_fd, int64_t length);
226SyscallReturn
umaskFunc(SyscallDesc *desc, ThreadContext *tc);
229SyscallReturn
gettidFunc(SyscallDesc *desc, ThreadContext *tc);
232SyscallReturn
chownFunc(SyscallDesc *desc, ThreadContext *tc,
233 VPtr<> pathname, uint32_t owner, uint32_t group);
234SyscallReturn
chownImpl(SyscallDesc *desc, ThreadContext *tc,
235 std::string path, uint32_t owner, uint32_t group);
238SyscallReturn
getpgrpFunc(SyscallDesc *desc, ThreadContext *tc);
241SyscallReturn
setpgidFunc(SyscallDesc *desc, ThreadContext *tc,
245SyscallReturn
fchownFunc(SyscallDesc *desc, ThreadContext *tc,
246 int tgt_fd, uint32_t owner, uint32_t group);
249SyscallReturn
dupFunc(SyscallDesc *desc, ThreadContext *tc,
253SyscallReturn
dup2Func(SyscallDesc *desc, ThreadContext *tc,
254 int old_tgt_fd,
int new_tgt_fd);
257SyscallReturn
fcntlFunc(SyscallDesc *desc, ThreadContext *tc,
258 int tgt_fd,
int cmd, guest_abi::VarArgs<int> varargs);
261SyscallReturn
fcntl64Func(SyscallDesc *desc, ThreadContext *tc,
262 int tgt_fd,
int cmd);
265SyscallReturn
pipeFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> tgt_addr);
268SyscallReturn
pipe2Func(SyscallDesc *desc, ThreadContext *tc,
269 VPtr<> tgt_addr,
int flags);
272SyscallReturn
getpidFunc(SyscallDesc *desc, ThreadContext *tc);
276 int tgt_fd, VPtr<> sockAddrPtr,
280SyscallReturn
bindFunc(SyscallDesc *desc, ThreadContext *tc,
281 int tgt_fd, VPtr<> buf_ptr,
int addrlen);
284SyscallReturn
listenFunc(SyscallDesc *desc, ThreadContext *tc,
285 int tgt_fd,
int backlog);
288SyscallReturn
connectFunc(SyscallDesc *desc, ThreadContext *tc,
289 int tgt_fd, VPtr<> buf_ptr,
int addrlen);
291#if defined(SYS_getdents)
293SyscallReturn getdentsFunc(SyscallDesc *desc, ThreadContext *tc,
294 int tgt_fd, VPtr<> buf_ptr,
unsigned count);
297#if defined(SYS_getdents64)
299SyscallReturn getdents64Func(SyscallDesc *desc, ThreadContext *tc,
300 int tgt_fd, VPtr<> buf_ptr,
unsigned count);
304SyscallReturn
recvmsgFunc(SyscallDesc *desc, ThreadContext *tc,
305 int tgt_fd, VPtr<> msgPtr,
int flags);
308SyscallReturn
sendmsgFunc(SyscallDesc *desc, ThreadContext *tc,
309 int tgt_fd, VPtr<> msgPtr,
int flags);
312SyscallReturn
getuidFunc(SyscallDesc *desc, ThreadContext *tc);
315SyscallReturn
getgidFunc(SyscallDesc *desc, ThreadContext *tc);
318SyscallReturn
getppidFunc(SyscallDesc *desc, ThreadContext *tc);
321SyscallReturn
geteuidFunc(SyscallDesc *desc, ThreadContext *tc);
324SyscallReturn
getegidFunc(SyscallDesc *desc, ThreadContext *tc);
327SyscallReturn
accessFunc(SyscallDesc *desc, ThreadContext *tc,
328 VPtr<> pathname, mode_t
mode);
329SyscallReturn
accessImpl(SyscallDesc *desc, ThreadContext *tc,
330 std::string path, mode_t
mode);
334 int tgt_fd,
int level,
int optname,
335 VPtr<> valPtr, VPtr<> lenPtr);
339 int tgt_fd,
int level,
int optname,
340 VPtr<> valPtr, socklen_t
len);
342SyscallReturn
getcpuFunc(SyscallDesc *desc, ThreadContext *tc,
343 VPtr<uint32_t> cpu, VPtr<uint32_t> node,
344 VPtr<uint32_t> tcache);
348 int tgt_fd, VPtr<> addrPtr, VPtr<> lenPtr);
355 if (dirfd != OS::TGT_AT_FDCWD && !
startswith(path,
"/")) {
358 std::shared_ptr<FDEntry> fdep = ((*process->fds)[dirfd]);
359 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
364 path = ffdp->getFileName();
366 path = ffdp->getFileName() +
"/" + path;
386 op &= ~OS::TGT_FUTEX_PRIVATE_FLAG;
387 op &= ~OS::TGT_FUTEX_CLOCK_REALTIME_FLAG;
391 if (OS::TGT_FUTEX_WAIT ==
op || OS::TGT_FUTEX_WAIT_BITSET ==
op) {
403 return -OS::TGT_EWOULDBLOCK;
405 if (OS::TGT_FUTEX_WAIT ==
op) {
406 futex_map.
suspend(uaddr, process->tgid(), tc);
412 }
else if (OS::TGT_FUTEX_WAKE ==
op) {
413 return futex_map.
wakeup(uaddr, process->tgid(),
val);
414 }
else if (OS::TGT_FUTEX_WAKE_BITSET ==
op) {
415 return futex_map.
wakeup_bitset(uaddr, process->tgid(), val3);
416 }
else if (OS::TGT_FUTEX_REQUEUE ==
op ||
417 OS::TGT_FUTEX_CMP_REQUEUE ==
op) {
427 if (OS::TGT_FUTEX_CMP_REQUEUE && val3 != mem_val)
428 return -OS::TGT_EWOULDBLOCK;
429 return futex_map.
requeue(uaddr, process->tgid(),
val, timeout, uaddr2);
430 }
else if (OS::TGT_FUTEX_WAKE_OP ==
op) {
458 int wake_cmparg = val3 & 0xfff;
459 int wake_oparg = (val3 & 0xfff000) >> 12;
460 int wake_cmp = (val3 & 0xf000000) >> 24;
461 int wake_op = (val3 & 0xf0000000) >> 28;
462 if ((wake_op & OS::TGT_FUTEX_OP_ARG_SHIFT) >> 3 == 1)
463 wake_oparg = (1 << wake_oparg);
464 wake_op &= ~OS::TGT_FUTEX_OP_ARG_SHIFT;
466 if (wake_op == OS::TGT_FUTEX_OP_SET)
468 else if (wake_op == OS::TGT_FUTEX_OP_ADD)
469 newval += wake_oparg;
470 else if (wake_op == OS::TGT_FUTEX_OP_OR)
471 newval |= wake_oparg;
472 else if (wake_op == OS::TGT_FUTEX_OP_ANDN)
473 newval &= ~wake_oparg;
474 else if (wake_op == OS::TGT_FUTEX_OP_XOR)
475 newval ^= wake_oparg;
480 int woken1 = futex_map.
wakeup(uaddr, process->tgid(),
val);
483 bool is_wake2 =
false;
484 if (wake_cmp == OS::TGT_FUTEX_OP_CMP_EQ)
485 is_wake2 = oldval == wake_cmparg;
486 else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_NE)
487 is_wake2 = oldval != wake_cmparg;
488 else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_LT)
489 is_wake2 = oldval < wake_cmparg;
490 else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_LE)
491 is_wake2 = oldval <= wake_cmparg;
492 else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_GT)
493 is_wake2 = oldval > wake_cmparg;
494 else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_GE)
495 is_wake2 = oldval >= wake_cmparg;
498 woken2 = futex_map.
wakeup(uaddr2, process->tgid(), timeout);
500 return woken1 + woken2;
502 warn(
"futex: op %d not implemented; ignoring.",
op);
508SyscallReturn
pipePseudoFunc(SyscallDesc *desc, ThreadContext *tc);
518template <
class T1,
class T2>
522 static const int OneMillion = 1000 * 1000;
525 sec = elapsed_usecs / OneMillion;
526 usec = elapsed_usecs % OneMillion;
531template <
class T1,
class T2>
535 static const int OneBillion = 1000 * 1000 * 1000;
538 sec = elapsed_nsecs / OneBillion;
539 nsec = elapsed_nsecs % OneBillion;
562template <
typename OS,
typename TgtStatPtr,
typename HostStatPtr>
566 constexpr ByteOrder
bo = OS::byteOrder;
571 tgt->st_dev = host->st_dev;
572 tgt->st_dev =
htog(tgt->st_dev,
bo);
573 tgt->st_ino = host->st_ino;
574 tgt->st_ino =
htog(tgt->st_ino,
bo);
575 tgt->st_mode = host->st_mode;
578 tgt->st_mode &= ~S_IFMT;
579 tgt->st_mode |= S_IFCHR;
581 tgt->st_mode =
htog(tgt->st_mode,
bo);
582 tgt->st_nlink = host->st_nlink;
583 tgt->st_nlink =
htog(tgt->st_nlink,
bo);
584 tgt->st_uid = host->st_uid;
585 tgt->st_uid =
htog(tgt->st_uid,
bo);
586 tgt->st_gid = host->st_gid;
587 tgt->st_gid =
htog(tgt->st_gid,
bo);
589 tgt->st_rdev = 0x880d;
591 tgt->st_rdev = host->st_rdev;
592 tgt->st_rdev =
htog(tgt->st_rdev,
bo);
593 tgt->st_size = host->st_size;
594 tgt->st_size =
htog(tgt->st_size,
bo);
595 tgt->st_atimeX = host->st_atime;
596 tgt->st_atimeX =
htog(tgt->st_atimeX,
bo);
597 tgt->st_mtimeX = host->st_mtime;
598 tgt->st_mtimeX =
htog(tgt->st_mtimeX,
bo);
599 tgt->st_ctimeX = host->st_ctime;
600 tgt->st_ctimeX =
htog(tgt->st_ctimeX,
bo);
603 tgt->st_blksize = 0x2000;
604 tgt->st_blksize =
htog(tgt->st_blksize,
bo);
605 tgt->st_blocks = host->st_blocks;
606 tgt->st_blocks =
htog(tgt->st_blocks,
bo);
611template <
typename OS,
typename TgtStatPtr,
typename HostStatPtr>
616 copyOutStatBuf<OS>(tgt, host, fakeTTY);
617#if defined(STAT_HAVE_NSEC)
618 constexpr ByteOrder
bo = OS::byteOrder;
620 tgt->st_atime_nsec = host->st_atime_nsec;
621 tgt->st_atime_nsec =
htog(tgt->st_atime_nsec,
bo);
622 tgt->st_mtime_nsec = host->st_mtime_nsec;
623 tgt->st_mtime_nsec =
htog(tgt->st_mtime_nsec,
bo);
624 tgt->st_ctime_nsec = host->st_ctime_nsec;
625 tgt->st_ctime_nsec =
htog(tgt->st_ctime_nsec,
bo);
627 tgt->st_atime_nsec = 0;
628 tgt->st_mtime_nsec = 0;
629 tgt->st_ctime_nsec = 0;
633template <
class OS,
typename TgtStatPtr,
typename HostStatPtr>
637 constexpr ByteOrder
bo = OS::byteOrder;
639 tgt->f_type =
htog(host->f_type,
bo);
640#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
641 tgt->f_bsize =
htog(host->f_iosize,
bo);
643 tgt->f_bsize =
htog(host->f_bsize,
bo);
645 tgt->f_blocks =
htog(host->f_blocks,
bo);
646 tgt->f_bfree =
htog(host->f_bfree,
bo);
647 tgt->f_bavail =
htog(host->f_bavail,
bo);
648 tgt->f_files =
htog(host->f_files,
bo);
649 tgt->f_ffree =
htog(host->f_ffree,
bo);
650 memcpy(&tgt->f_fsid, &host->f_fsid,
sizeof(host->f_fsid));
651#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
652 tgt->f_namelen =
htog(host->f_namemax,
bo);
653 tgt->f_frsize =
htog(host->f_bsize,
bo);
654#elif defined(__APPLE__)
658 tgt->f_namelen =
htog(host->f_namelen,
bo);
659 tgt->f_frsize =
htog(host->f_frsize,
bo);
661#if defined(__linux__)
662 memcpy(&tgt->f_spare, &host->f_spare,
663 std::min(
sizeof(host->f_spare),
sizeof(tgt->f_spare)));
669 memset(&tgt->f_spare, 0,
sizeof(tgt->f_spare));
673template <
typename OS,
typename TgtStatPtr,
typename HostStatPtr>
677 constexpr ByteOrder
bo = OS::byteOrder;
680 tgt->stx_dev_major = 0x00;
681 tgt->stx_dev_minor = 0x0A;
683 tgt->stx_dev_major = host->st_dev >> 8;
684 tgt->stx_dev_minor = host->st_dev & 0xFF;
686 tgt->stx_dev_major =
htog(tgt->stx_dev_major,
bo);
687 tgt->stx_dev_minor =
htog(tgt->stx_dev_minor,
bo);
688 tgt->stx_ino = host->st_ino;
689 tgt->stx_ino =
htog(tgt->stx_ino,
bo);
690 tgt->stx_mode = host->st_mode;
693 tgt->stx_mode &= ~S_IFMT;
694 tgt->stx_mode |= S_IFCHR;
696 tgt->stx_mode =
htog(tgt->stx_mode,
bo);
697 tgt->stx_nlink = host->st_nlink;
698 tgt->stx_nlink =
htog(tgt->stx_nlink,
bo);
699 tgt->stx_uid = host->st_uid;
700 tgt->stx_uid =
htog(tgt->stx_uid,
bo);
701 tgt->stx_gid = host->st_gid;
702 tgt->stx_gid =
htog(tgt->stx_gid,
bo);
704 tgt->stx_rdev_major = 0x880d >> 8;
705 tgt->stx_rdev_minor = 0x880d & 0xFF;
707 tgt->stx_rdev_major = host->st_rdev >> 8;
708 tgt->stx_rdev_minor = host->st_rdev & 0xFF;
710 tgt->stx_rdev_major =
htog(tgt->stx_rdev_major,
bo);
711 tgt->stx_rdev_minor =
htog(tgt->stx_rdev_minor,
bo);
712 tgt->stx_size = host->st_size;
713 tgt->stx_size =
htog(tgt->stx_size,
bo);
714 tgt->stx_atimeX = host->st_atime;
715 tgt->stx_atimeX =
htog(tgt->stx_atimeX,
bo);
716 tgt->stx_ctimeX = host->st_ctime;
717 tgt->stx_ctimeX =
htog(tgt->stx_ctimeX,
bo);
718 tgt->stx_mtimeX = host->st_mtime;
719 tgt->stx_mtimeX =
htog(tgt->stx_mtimeX,
bo);
722 tgt->stx_blksize = 0x2000;
723 tgt->stx_blksize =
htog(tgt->stx_blksize,
bo);
724 tgt->stx_blocks = host->st_blocks;
725 tgt->stx_blocks =
htog(tgt->stx_blocks,
bo);
726 tgt->stx_mask = 0x000007ffU;
727 tgt->stx_mask =
htog(tgt->stx_mask,
bo);
728 tgt->stx_attributes = 0;
729 tgt->stx_attributes_mask = 0;
730 tgt->stx_attributes_mask =
htog(tgt->stx_attributes_mask,
bo);
746 if (OS::isTtyReq(req))
749 auto dfdp = std::dynamic_pointer_cast<DeviceFDEntry>((*
p->fds)[tgt_fd]);
753 return emul_driver->
ioctl(tc, req,
addr);
756 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
765 ifconf *conf = (ifconf*)conf_arg.
bufferPtr();
766 Addr ifc_buf_addr = (
Addr)conf->ifc_buf;
767 BufferArg ifc_buf_arg(ifc_buf_addr, conf->ifc_len);
770 conf->ifc_buf = (
char*)ifc_buf_arg.
bufferPtr();
774 conf->ifc_buf = (
char*)ifc_buf_addr;
782#if defined(__linux__)
787#if defined(__linux__)
806 warn(
"Unsupported ioctl call (return ENOTTY): ioctl(%d, 0x%x, ...) @ \n",
815 int tgt_dirfd,
VPtr<> pathname,
int tgt_flags,
int mode)
828 int host_flags = O_BINARY;
836 for (
const auto &
p: OS::openFlagTable) {
837 if (tgt_flags &
p.first) {
838 tgt_flags &= ~p.first;
839 host_flags |=
p.second;
842 warn_if(tgt_flags,
"%s: cannot decode flags %#x", desc->
name(), tgt_flags);
845 host_flags |= O_BINARY;
860 std::string redir_path = path;
861 std::string abs_path = path;
862 if (tgt_dirfd == OS::TGT_AT_FDCWD) {
863 abs_path =
p->absolutePath(path,
true);
864 redir_path =
p->checkPathRedirect(path);
866 std::shared_ptr<FDEntry> fdep = ((*
p->fds)[tgt_dirfd]);
867 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
870 abs_path = ffdp->getFileName() + path;
871 redir_path =
p->checkPathRedirect(abs_path);
881 std::string filename = abs_path.substr(strlen(
"/dev/"));
885 "driver open with path[%s]\n",
886 desc->
name(), abs_path.c_str());
887 return drv->
open(tc,
mode, host_flags);
920 std::string used_path;
922 {
"/proc/meminfo",
"/system/",
"/platform/",
"/etc/passwd",
923 "/proc/self/maps",
"/dev/urandom",
924 "/sys/devices/system/cpu/online" };
925 for (
auto entry : special_paths) {
927 sim_fd = OS::openSpecialFile(abs_path,
p, tc);
928 used_path = abs_path;
932 sim_fd = open(redir_path.c_str(), host_flags,
mode);
933 used_path = redir_path;
938 "(inferred from:%s)\n", desc->
name(),
939 used_path.c_str(), path.c_str());
951 auto ffdp = std::make_shared<FileFDEntry>(sim_fd, host_flags, path, 0);
953 ffdp->setFileMode(
mode);
954 int tgt_fd =
p->fds->allocFD(ffdp);
956 "(inferred from:%s)\n", desc->
name(),
957 sim_fd, tgt_fd, used_path.c_str(), path.c_str());
967 return openatFunc<OS>(
968 desc, tc, OS::TGT_AT_FDCWD, pathname, tgt_flags,
mode);
975 VPtr<> buf_ptr,
typename OS::size_t size)
982 std::string cwd =
p->tgtCwd;
984 if (cwd.length() >= size) {
988 strncpy((
char *)buf.
bufferPtr(), cwd.c_str(), size);
989 result = cwd.length();
991 if (getcwd((
char *)buf.
bufferPtr(), size)) {
992 result = strlen((
char *)buf.
bufferPtr());
1000 return (result == -1) ? -errno : result;
1007 int tgt_fd,
typename OS::off_t offs,
int whence)
1011 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
1014 int sim_fd = ffdp->getSimFD();
1016 off_t result = lseek(sim_fd, offs, whence);
1018 return (result == (off_t)-1) ? -errno : result;
1032 if (
auto res = atSyscallPath<OS>(tc, dirfd, path); !res.successful()) {
1036 if (
flags & OS::TGT_AT_REMOVEDIR) {
1054 if (
auto res = atSyscallPath<OS>(tc, dirfd, path); !res.successful()) {
1066 typename OS::size_t bufsiz)
1073 if (
auto res = atSyscallPath<OS>(tc, dirfd, path); !res.successful()) {
1085 if (path !=
"/proc/self/exe") {
1086 result = readlink(path.c_str(), (
char *)buf.
bufferPtr(), bufsiz);
1100 char real_path[PATH_MAX];
1101 char *check_real_path = realpath(
p->progName(), real_path);
1102 if (!check_real_path) {
1103 fatal(
"readlink('/proc/self/exe') unable to resolve path to "
1104 "executable: %s",
p->progName());
1106 strncpy((
char*)buf.
bufferPtr(), real_path, bufsiz);
1107 typename OS::size_t real_path_len = strlen(real_path);
1108 if (real_path_len > bufsiz) {
1113 result = real_path_len;
1117 warn_once(
"readlink() called on '/proc/self/exe' may yield unexpected "
1118 "results in various settings.\n Returning '%s'\n",
1124 return (result == -1) ? -errno : result;
1132 typename OS::size_t bufsiz)
1134 return readlinkatFunc<OS>(desc, tc, OS::TGT_AT_FDCWD,
1135 pathname, buf_ptr, bufsiz);
1142 int olddirfd,
VPtr<> oldpath,
int newdirfd,
VPtr<> newpath)
1145 std::string old_name;
1149 std::string new_name;
1154 if (
auto res = atSyscallPath<OS>(tc, olddirfd, old_name); !res.successful()) {
1159 if (
auto res = atSyscallPath<OS>(tc, newdirfd, new_name); !res.successful()) {
1163 return renameImpl(desc, tc, old_name, new_name);
1170 int dirfd,
VPtr<> pathname, uint32_t owner, uint32_t group,
1178 if (
auto res = atSyscallPath<OS>(tc, dirfd, path); !res.successful()) {
1182 return chownImpl(desc, tc, path, owner, group);
1196 if (
auto res = atSyscallPath<OS>(tc, dirfd, path); !res.successful()) {
1207 int dirfd,
VPtr<> pathname, mode_t
mode, dev_t dev)
1214 if (
auto res = atSyscallPath<OS>(tc, dirfd, path); !res.successful()) {
1230 sysinfo->totalram = process->system->memSize();
1231 sysinfo->mem_unit = 1;
1247 if (
auto res = atSyscallPath<OS>(tc, dirfd, path); !res.successful()) {
1251 mode_t hostMode = 0;
1261 int result = chmod(path.c_str(), hostMode);
1273 return fchmodatFunc<OS>(desc, tc, OS::TGT_AT_FDCWD, pathname,
mode);
1279 VPtr<> fdsPtr,
int nfds,
int tmout)
1283 BufferArg fdsBuf(fdsPtr,
sizeof(
struct pollfd) * nfds);
1292 int temp_tgt_fds[nfds];
1295 auto tgt_fd = temp_tgt_fds[
index];
1296 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[tgt_fd]);
1299 auto host_fd = hbfdp->getSimFD();
1321 if (it->receiver ==
p)
1336 auto tgt_fd = temp_tgt_fds[
index];
1356 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
1359 int sim_fd = ffdp->getSimFD();
1361 mode_t hostMode =
mode;
1363 int result = fchmod(sim_fd, hostMode);
1365 return (result < 0) ? -errno : 0;
1372 VPtr<> start,
typename OS::size_t old_length,
1373 typename OS::size_t new_length,
int flags,
1378 uint64_t provided_address = 0;
1379 bool use_provided_address =
flags & OS::TGT_MREMAP_FIXED;
1381 if (use_provided_address)
1382 provided_address = varargs.
get<uint64_t>();
1384 if ((start % page_bytes != 0) ||
1385 (provided_address % page_bytes != 0)) {
1386 warn(
"mremap failing: arguments not page aligned");
1390 new_length =
roundUp(new_length, page_bytes);
1392 if (new_length > old_length) {
1393 Addr mmap_end =
p->memState->getMmapEnd();
1395 if ((start + old_length) == mmap_end &&
1396 (!use_provided_address || provided_address == start)) {
1399 uint64_t diff = new_length - old_length;
1400 p->memState->mapRegion(mmap_end, diff,
"remapped");
1401 p->memState->setMmapEnd(mmap_end + diff);
1404 if (!use_provided_address && !(
flags & OS::TGT_MREMAP_MAYMOVE)) {
1405 warn(
"can't remap here and MREMAP_MAYMOVE flag not set\n");
1408 uint64_t new_start = provided_address;
1409 if (!use_provided_address) {
1410 new_start =
p->mmapGrowsDown() ?
1411 mmap_end - new_length : mmap_end;
1412 mmap_end =
p->mmapGrowsDown() ?
1413 new_start : mmap_end + new_length;
1414 p->memState->setMmapEnd(mmap_end);
1417 warn(
"mremapping to new vaddr %08p-%08p, adding %d\n",
1418 new_start, new_start + new_length,
1419 new_length - old_length);
1422 p->allocateMem(new_start + old_length,
1423 new_length - old_length,
1424 use_provided_address );
1426 if (use_provided_address &&
1427 ((new_start + new_length >
p->memState->getMmapEnd() &&
1428 !
p->mmapGrowsDown()) ||
1429 (new_start < p->memState->getMmapEnd() &&
1430 p->mmapGrowsDown()))) {
1433 warn(
"mmap region limit exceeded with MREMAP_FIXED\n");
1436 warn(
"returning %08p as start\n", new_start);
1437 p->memState->remapRegion(start, new_start, old_length);
1443 if (use_provided_address && provided_address != start)
1444 p->memState->remapRegion(start, provided_address, new_length);
1445 if (new_length != old_length)
1446 p->memState->unmapRegion(start + new_length,
1447 old_length - new_length);
1448 return use_provided_address ? provided_address : (
Addr)start;
1467 struct stat hostBuf;
1468 int result = stat(path.c_str(), &hostBuf);
1473 copyOutStatBuf<OS>(tgt_stat, &hostBuf);
1490 if (path.empty() && !(
flags & OS::TGT_AT_EMPTY_PATH))
1497 if (
auto res = atSyscallPath<OS>(tc, dirfd, path); !res.successful()) {
1506 struct stat host_buf;
1507 int result = stat(path.c_str(), &host_buf);
1512 copyOutStat64Buf<OS>(tgt_stat, &host_buf);
1521 int dirfd,
VPtr<> pathname,
1529 if (
auto res = atSyscallPath<OS>(tc, dirfd, path); !res.successful()) {
1539 struct stat hostBuf;
1540 int result = stat(path.c_str(), &hostBuf);
1542 struct stat64 hostBuf;
1543 int result = stat64(path.c_str(), &hostBuf);
1549 copyOutStat64Buf<OS>(tgt_stat, &hostBuf);
1560 return fstatat64Func<OS>(desc, tc, OS::TGT_AT_FDCWD, pathname, tgt_stat);
1575 if (path.empty() && !(
flags & OS::TGT_AT_EMPTY_PATH))
1582 if (
auto res = atSyscallPath<OS>(tc, dirfd, path); !res.successful()) {
1591 struct stat host_buf;
1592 int result = stat(path.c_str(), &host_buf);
1597 copyOutStatxBuf<OS>(tgt_statx, &host_buf);
1610 auto ffdp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[tgt_fd]);
1613 int sim_fd = ffdp->getSimFD();
1616 struct stat hostBuf;
1617 int result = fstat(sim_fd, &hostBuf);
1619 struct stat64 hostBuf;
1620 int result = fstat64(sim_fd, &hostBuf);
1626 copyOutStat64Buf<OS>(tgt_stat, &hostBuf, (sim_fd == 1));
1647 struct stat hostBuf;
1648 int result = lstat(path.c_str(), &hostBuf);
1653 copyOutStatBuf<OS>(tgt_stat, &hostBuf);
1674 struct stat hostBuf;
1675 int result = lstat(path.c_str(), &hostBuf);
1677 struct stat64 hostBuf;
1678 int result = lstat64(path.c_str(), &hostBuf);
1684 copyOutStat64Buf<OS>(tgt_stat, &hostBuf);
1699 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
1702 int sim_fd = ffdp->getSimFD();
1704 struct stat hostBuf;
1705 int result = fstat(sim_fd, &hostBuf);
1710 copyOutStatBuf<OS>(tgt_stat, &hostBuf, (sim_fd == 1));
1721#if defined(__linux__)
1731 struct statfs hostBuf;
1732 int result = statfs(path.c_str(), &hostBuf);
1737 copyOutStatfsBuf<OS>(tgt_stat, &hostBuf);
1750 DPRINTF(SyscallVerbose,
"Doing clone. pid: %#llx, ctid: %#llx, tls: %#llx"
1751 " flags: %#llx, stack: %#llx\n",
1755 if (((
flags & OS::TGT_CLONE_SIGHAND)&& !(
flags & OS::TGT_CLONE_VM)) ||
1756 ((
flags & OS::TGT_CLONE_THREAD) && !(
flags & OS::TGT_CLONE_SIGHAND)) ||
1757 ((
flags & OS::TGT_CLONE_FS) && (
flags & OS::TGT_CLONE_NEWNS)) ||
1758 ((
flags & OS::TGT_CLONE_NEWIPC) && (
flags & OS::TGT_CLONE_SYSVSEM)) ||
1759 ((
flags & OS::TGT_CLONE_NEWPID) && (
flags & OS::TGT_CLONE_THREAD)) ||
1760 ((
flags & OS::TGT_CLONE_VM) && !(newStack)))
1776 ProcessParams *pp =
new ProcessParams();
1777 pp->executable.assign(*(
new std::string(
p->progName())));
1778 pp->cmd.push_back(*(
new std::string(
p->progName())));
1779 pp->system =
p->system;
1780 pp->cwd.assign(
p->tgtCwd);
1781 pp->input.assign(
"stdin");
1782 pp->output.assign(
"stdout");
1783 pp->errout.assign(
"stderr");
1785 pp->euid =
p->euid();
1787 pp->egid =
p->egid();
1788 pp->release =
p->release;
1791 std::set<int>
const& pids =
p->system->PIDs;
1792 int temp_pid = *pids.begin();
1795 }
while (pids.find(temp_pid) != pids.end());
1797 fatal(
"temp_pid is too large: %d", temp_pid);
1800 pp->ppid = (
flags & OS::TGT_CLONE_THREAD) ?
p->ppid() :
p->pid();
1801 pp->useArchPT =
p->useArchPT;
1802 pp->kvmInSE =
p->kvmInSE;
1813 if (
flags & OS::TGT_CLONE_PARENT_SETTID) {
1814 BufferArg ptidBuf(ptidPtr,
sizeof(
long));
1815 long *ptid = (
long *)ptidBuf.
bufferPtr();
1820 if (
flags & OS::TGT_CLONE_THREAD) {
1828 p->clone(tc, ctc, cp,
flags);
1830 if (
flags & OS::TGT_CLONE_THREAD) {
1833 }
else if (
flags & OS::TGT_SIGCHLD) {
1837 if (
flags & OS::TGT_CLONE_CHILD_SETTID) {
1838 BufferArg ctidBuf(ctidPtr,
sizeof(
long));
1839 long *ctid = (
long *)ctidBuf.
bufferPtr();
1844 if (
flags & OS::TGT_CLONE_CHILD_CLEARTID)
1849 OS::archClone(
flags,
p, cp, tc, ctc, newStack, tlsPtr);
1855 if (
flags & OS::TGT_CLONE_VFORK) {
1872 uint64_t new_stack = cl_args->stack + cl_args->stack_size;
1873 uint64_t
flags = cl_args->flags;
1875 return doClone<OS>(desc, tc,
flags, new_stack, ptidPtr, ctidPtr, tlsPtr);
1883 return doClone<OS>(desc, tc,
flags, newStack, ptidPtr, ctidPtr, tlsPtr);
1892 return cloneFunc<OS>(desc, tc,
flags, newStack, ptidPtr, ctidPtr, tlsPtr);
1903 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
1906 int sim_fd = ffdp->getSimFD();
1908 struct statfs hostBuf;
1909 int result = fstatfs(sim_fd, &hostBuf);
1914 copyOutStatfsBuf<OS>(tgt_stat, &hostBuf);
1923 int tgt_fd,
VPtr<> tiov_base,
1924 typename OS::size_t
count)
1928 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
1931 int sim_fd = ffdp->getSimFD();
1934 typename OS::tgt_iovec tiov[
count];
1935 struct iovec hiov[
count];
1936 for (
typename OS::size_t
i = 0;
i <
count; ++
i) {
1937 prox.
readBlob(tiov_base + (
i *
sizeof(
typename OS::tgt_iovec)),
1938 &tiov[
i],
sizeof(
typename OS::tgt_iovec));
1939 hiov[
i].iov_len =
gtoh(tiov[
i].iov_len, OS::byteOrder);
1940 hiov[
i].iov_base =
new char [hiov[
i].iov_len];
1943 int result = readv(sim_fd, hiov,
count);
1944 int local_errno = errno;
1946 for (
typename OS::size_t
i = 0;
i <
count; ++
i) {
1949 hiov[
i].iov_base, hiov[
i].iov_len);
1951 delete [] (
char *)hiov[
i].iov_base;
1954 return (result == -1) ? -local_errno : result;
1961 int tgt_fd,
VPtr<> tiov_base,
1962 typename OS::size_t
count)
1966 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[tgt_fd]);
1969 int sim_fd = hbfdp->getSimFD();
1972 struct iovec hiov[
count];
1973 for (
typename OS::size_t
i = 0;
i <
count; ++
i) {
1974 typename OS::tgt_iovec tiov;
1976 prox.
readBlob(tiov_base +
i*
sizeof(
typename OS::tgt_iovec),
1977 &tiov,
sizeof(
typename OS::tgt_iovec));
1978 hiov[
i].iov_len =
gtoh(tiov.iov_len, OS::byteOrder);
1979 hiov[
i].iov_base =
new char [hiov[
i].iov_len];
1980 prox.
readBlob(
gtoh(tiov.iov_base, OS::byteOrder), hiov[
i].iov_base,
1984 int result = writev(sim_fd, hiov,
count);
1986 for (
typename OS::size_t
i = 0;
i <
count; ++
i)
1987 delete [] (
char *)hiov[
i].iov_base;
1989 return (result == -1) ? -errno : result;
1996 VPtr<> start,
typename OS::size_t length,
int prot,
1997 int tgt_flags,
int tgt_fd,
typename OS::off_t
offset)
2002 if (start & (page_bytes - 1) ||
2003 offset & (page_bytes - 1) ||
2004 (tgt_flags & OS::TGT_MAP_PRIVATE &&
2005 tgt_flags & OS::TGT_MAP_SHARED) ||
2006 (!(tgt_flags & OS::TGT_MAP_PRIVATE) &&
2007 !(tgt_flags & OS::TGT_MAP_SHARED)) ||
2012 if ((
prot & PROT_WRITE) && (tgt_flags & OS::TGT_MAP_SHARED)) {
2033 warn_once(
"mmap: writing to shared mmap region is currently "
2034 "unsupported. The write succeeds on the target, but it "
2035 "will not be propagated to the host or shared mappings");
2038 length =
roundUp(length, page_bytes);
2041 if (!(tgt_flags & OS::TGT_MAP_ANONYMOUS)) {
2042 std::shared_ptr<FDEntry> fdep = (*
p->fds)[tgt_fd];
2044 auto dfdp = std::dynamic_pointer_cast<DeviceFDEntry>(fdep);
2047 return emul_driver->
mmap(tc, start, length,
prot, tgt_flags,
2051 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
2054 sim_fd = ffdp->getSimFD();
2065 std::shared_ptr<FDEntry> fdep = (*
p->fds)[tgt_fd];
2066 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
2068 ffdp->getFileName()));
2070 ffdp->getFileName());
2073 Addr offset = lib->buildImage().minAddr() + start;
2082 if (!(tgt_flags & OS::TGT_MAP_FIXED)) {
2090 if (!(start &&
p->memState->isUnmapped(start, length))) {
2094 start =
p->memState->extendMmap(length);
2099 start, start + length - 1);
2106 if (tgt_flags & OS::TGT_MAP_FIXED) {
2111 p->memState->unmapRegion(start, length);
2117 std::string region_name;
2118 if (tgt_flags & OS::TGT_MAP_ANONYMOUS) {
2119 region_name =
"anon";
2121 std::shared_ptr<FDEntry> fdep = (*
p->fds)[tgt_fd];
2122 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
2123 region_name = ffdp->getFileName();
2130 p->memState->mapRegion(start, length, region_name, sim_fd,
offset);
2138 int tgt_fd,
VPtr<> bufPtr,
typename OS::size_t nbytes,
2139 typename OS::off_t
offset)
2143 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
2146 int sim_fd = ffdp->getSimFD();
2154 return (bytes_read == -1) ? -errno : bytes_read;
2160 int tgt_fd,
VPtr<> bufPtr,
typename OS::size_t nbytes,
2161 typename OS::off_t
offset)
2165 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
2168 int sim_fd = ffdp->getSimFD();
2173 int bytes_written = pwrite(sim_fd, bufArg.
bufferPtr(), nbytes,
offset);
2175 return (bytes_written == -1) ? -errno : bytes_written;
2182 VPtr<> start,
typename OS::size_t length,
int prot,
2183 int tgt_flags,
int tgt_fd,
typename OS::off_t
offset)
2186 return mmapFunc<OS>(desc, tc, start, length,
prot, tgt_flags,
2187 tgt_fd,
offset * page_size);
2196 const ByteOrder
bo = OS::byteOrder;
2198 case OS::TGT_RLIMIT_STACK:
2200 rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
2201 rlp->rlim_cur =
htog(rlp->rlim_cur,
bo);
2202 rlp->rlim_max =
htog(rlp->rlim_max,
bo);
2205 case OS::TGT_RLIMIT_DATA:
2207 rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024;
2208 rlp->rlim_cur =
htog(rlp->rlim_cur,
bo);
2209 rlp->rlim_max =
htog(rlp->rlim_max,
bo);
2212 case OS::TGT_RLIMIT_NPROC:
2214 rlp->rlim_cur =
htog(rlp->rlim_cur,
bo);
2215 rlp->rlim_max =
htog(rlp->rlim_max,
bo);
2219 warn(
"getrlimit: unimplemented resource %d", resource);
2233 warn(
"prlimit: ignoring rlimits for nonzero pid");
2237 warn(
"prlimit: ignoring new rlimit");
2239 const ByteOrder
bo = OS::byteOrder;
2241 case OS::TGT_RLIMIT_STACK:
2243 rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
2244 rlp->rlim_cur =
htog(rlp->rlim_cur,
bo);
2245 rlp->rlim_max =
htog(rlp->rlim_max,
bo);
2247 case OS::TGT_RLIMIT_DATA:
2249 rlp->rlim_cur = rlp->rlim_max = 256*1024*1024;
2250 rlp->rlim_cur =
htog(rlp->rlim_cur,
bo);
2251 rlp->rlim_max =
htog(rlp->rlim_max,
bo);
2254 warn(
"prlimit: unimplemented resource %d", resource);
2270 tp->tv_sec =
htog(tp->tv_sec, OS::byteOrder);
2271 tp->tv_nsec =
htog(tp->tv_nsec, OS::byteOrder);
2297 tp->tv_sec =
htog(tp->tv_sec, OS::byteOrder);
2298 tp->tv_usec =
htog(tp->tv_usec, OS::byteOrder);
2307 int dirfd,
VPtr<> pathname,
VPtr<
typename OS::timeval [2]> tp)
2314 if (
auto res = atSyscallPath<OS>(tc, dirfd, path); !res.successful()) {
2318 struct timeval hostTimeval[2];
2319 for (
int i = 0;
i < 2; ++
i) {
2320 hostTimeval[
i].tv_sec =
gtoh((*tp)[
i].tv_sec, OS::byteOrder);
2321 hostTimeval[
i].tv_usec =
gtoh((*tp)[
i].tv_usec, OS::byteOrder);
2328 int result = utimes(path.c_str(), hostTimeval);
2340 VPtr<
typename OS::timeval [2]> tp)
2342 return futimesatFunc<OS>(desc, tc, OS::TGT_AT_FDCWD, pathname, tp);
2357 if (access(path.c_str(), F_OK) == -1)
2363 for (
int inc = 0; ; inc++) {
2365 b.copyIn(mem_proxy);
2367 if (!*(
Addr*)
b.bufferPtr())
2370 vect.push_back(std::string());
2379 if (!
p->vforkContexts.empty()) {
2391 ProcessParams *pp =
new ProcessParams();
2392 pp->executable = path;
2393 read_in(pp->cmd, mem_proxy, argv_mem_loc);
2394 read_in(pp->env, mem_proxy, envp_mem_loc);
2396 pp->egid =
p->egid();
2397 pp->euid =
p->euid();
2399 pp->ppid =
p->ppid();
2401 pp->input.assign(
"cin");
2402 pp->output.assign(
"cout");
2403 pp->errout.assign(
"cerr");
2404 pp->cwd.assign(
p->tgtCwd);
2405 pp->system =
p->system;
2406 pp->release =
p->release;
2415 p->system->PIDs.erase(
p->pid());
2416 Process *new_p = pp->create();
2425 new_p->
fds =
p->fds;
2426 for (
int i = 0;
i < new_p->
fds->getSize();
i++) {
2427 std::shared_ptr<FDEntry> fdep = (*new_p->
fds)[
i];
2428 if (fdep && fdep->getCOE())
2429 new_p->
fds->closeFDEntry(
i);
2451 rup->ru_utime.tv_sec = 0;
2452 rup->ru_utime.tv_usec = 0;
2453 rup->ru_stime.tv_sec = 0;
2454 rup->ru_stime.tv_usec = 0;
2462 rup->ru_inblock = 0;
2463 rup->ru_oublock = 0;
2466 rup->ru_nsignals = 0;
2471 case OS::TGT_RUSAGE_SELF:
2473 rup->ru_utime.tv_sec =
htog(rup->ru_utime.tv_sec, OS::byteOrder);
2474 rup->ru_utime.tv_usec =
htog(rup->ru_utime.tv_usec, OS::byteOrder);
2477 case OS::TGT_RUSAGE_CHILDREN:
2484 warn(
"getrusage() only supports RUSAGE_SELF. Parameter %d ignored.",
2498 bufp->tms_utime = clocks;
2499 bufp->tms_stime = 0;
2500 bufp->tms_cutime = 0;
2501 bufp->tms_cstime = 0;
2504 bufp->tms_utime =
htog(bufp->tms_utime, OS::byteOrder);
2515 typename OS::time_t sec, usec;
2521 typename OS::time_t
t = sec;
2522 t =
htog(
t, OS::byteOrder);
2523 p.writeBlob(taddr, &
t, (
int)
sizeof(
typename OS::time_t));
2549 for (
auto *tc: sys->
threads) {
2551 if (temp->
pid() == tid) {
2557 if (sig != 0 && sig != OS::TGT_SIGABRT)
2560 if (tgt_proc ==
nullptr)
2563 if (tgid != -1 && tgt_proc->
tgid() != tgid)
2566 if (sig == OS::TGT_SIGABRT)
2583 auto sfdp = std::make_shared<SocketFDEntry>(sim_fd,
domain,
type,
prot);
2584 int tgt_fd =
p->fds->allocFD(sfdp);
2603 auto sfdp1 = std::make_shared<SocketFDEntry>(fds[0],
domain,
type,
prot);
2604 fds[0] =
p->fds->allocFD(sfdp1);
2605 auto sfdp2 = std::make_shared<SocketFDEntry>(fds[1],
domain,
type,
prot);
2606 fds[1] =
p->fds->allocFD(sfdp2);
2630 FD_ZERO(&readfds_h);
2632 FD_ZERO(&writefds_h);
2634 FD_ZERO(&errorfds_h);
2646 std::map<int, int> trans_map;
2647 auto try_add_host_set = [&](
typename OS::fd_set *tgt_set_entry,
2648 fd_set *hst_set_entry,
2656 if (FD_ISSET(iter, (fd_set *)tgt_set_entry)) {
2662 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[iter]);
2665 auto sim_fd = hbfdp->getSimFD();
2672 trans_map[sim_fd] = iter;
2679 nfds_h = std::max(nfds_h - 1, sim_fd + 1);
2685 FD_SET(sim_fd, hst_set_entry);
2690 for (
int i = 0;
i < nfds;
i++) {
2692 bool ebadf = try_add_host_set(readfds, &readfds_h,
i);
2697 bool ebadf = try_add_host_set(writefds, &writefds_h,
i);
2702 bool ebadf = try_add_host_set(errorfds, &errorfds_h,
i);
2716 timeout->tv_sec = 0;
2717 timeout->tv_usec = 0;
2719 retval = select(nfds_h,
2720 readfds ? &readfds_h :
nullptr,
2721 writefds ? &writefds_h :
nullptr,
2722 errorfds ? &errorfds_h :
nullptr,
2723 (timeval *)(
typename OS::timeval *)timeout);
2732 struct timeval tv = { 0, 0 };
2734 retval = select(nfds_h,
2735 readfds ? &readfds_h :
nullptr,
2736 readfds ? &writefds_h :
nullptr,
2737 readfds ? &errorfds_h :
nullptr,
2747 if (sig.receiver ==
p)
2757 FD_ZERO(
reinterpret_cast<fd_set *
>((
typename OS::fd_set *)readfds));
2760 FD_ZERO(
reinterpret_cast<fd_set *
>((
typename OS::fd_set *)writefds));
2763 FD_ZERO(
reinterpret_cast<fd_set *
>((
typename OS::fd_set *)errorfds));
2771 for (
int i = 0;
i < nfds_h;
i++) {
2772 if (readfds && FD_ISSET(
i, &readfds_h))
2773 FD_SET(trans_map[
i],
2774 reinterpret_cast<fd_set *
>(
2775 (
typename OS::fd_set *)readfds));
2777 if (writefds && FD_ISSET(
i, &writefds_h))
2778 FD_SET(trans_map[
i],
2779 reinterpret_cast<fd_set *
>(
2780 (
typename OS::fd_set *)writefds));
2782 if (errorfds && FD_ISSET(
i, &errorfds_h))
2783 FD_SET(trans_map[
i],
2784 reinterpret_cast<fd_set *
>(
2785 (
typename OS::fd_set *)errorfds));
2794 int tgt_fd,
VPtr<> buf_ptr,
typename OS::size_t nbytes)
2798 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[tgt_fd]);
2801 int sim_fd = hbfdp->getSimFD();
2805 pfd.events = POLLIN | POLLPRI;
2806 if ((poll(&pfd, 1, 0) == 0)
2807 && !(hbfdp->getFlags() & OS::TGT_O_NONBLOCK))
2811 int bytes_read = read(sim_fd, buf_arg.
bufferPtr(), nbytes);
2816 return (bytes_read == -1) ? -errno : bytes_read;
2822 int tgt_fd,
VPtr<> buf_ptr,
typename OS::size_t nbytes)
2826 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[tgt_fd]);
2829 int sim_fd = hbfdp->getSimFD();
2836 pfd.events = POLLOUT;
2844 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(hbfdp);
2845 if (ffdp && (ffdp->getFileName() !=
"/dev/random")) {
2846 if (!poll(&pfd, 1, 0) && !(ffdp->getFlags() & OS::TGT_O_NONBLOCK))
2850 int bytes_written = write(sim_fd, buf_arg.
bufferPtr(), nbytes);
2852 if (bytes_written != -1)
2855 return (bytes_written == -1) ? -errno : bytes_written;
2861 pid_t pid,
VPtr<> statPtr,
int options,
VPtr<> rusagePtr)
2866 DPRINTF_SYSCALL(Verbose,
"wait4: rusage pointer provided %lx, however "
2867 "functionality not supported. Ignoring rusage pointer.\n",
2881 if (iter->receiver ==
p) {
2883 if ((iter->sender->pgid() == -pid)
2884 && (iter->signalValue == OS::TGT_SIGCHLD))
2886 }
else if (pid == -1) {
2887 if (iter->signalValue == OS::TGT_SIGCHLD)
2889 }
else if (pid == 0) {
2890 if ((iter->sender->pgid() ==
p->pgid())
2891 && (iter->signalValue == OS::TGT_SIGCHLD))
2894 if ((iter->sender->pid() == pid)
2895 && (iter->signalValue == OS::TGT_SIGCHLD))
2905 const int EXITED = 0;
2906 BufferArg statusBuf(statPtr,
sizeof(
int));
2911 pid_t retval = iter->sender->pid();
2929 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
2932 int sim_fd = sfdp->getSimFD();
2942 pfd.events = POLLIN | POLLPRI;
2943 if ((poll(&pfd, 1, 0) == 0) && !(sfdp->getFlags() & OS::TGT_O_NONBLOCK))
2947 lenBufPtr =
new BufferArg(lenPtr,
sizeof(socklen_t));
2949 memcpy(&addrLen, (socklen_t *)lenBufPtr->
bufferPtr(),
2954 addrBufPtr =
new BufferArg(addrPtr,
sizeof(
struct sockaddr));
2956 memcpy(&
sa, (
struct sockaddr *)addrBufPtr->
bufferPtr(),
2957 sizeof(
struct sockaddr));
2960 host_fd = accept(sim_fd, &
sa, &addrLen);
2972 *(socklen_t *)lenBufPtr->
bufferPtr() = addrLen;
2977 auto afdp = std::make_shared<SocketFDEntry>(host_fd, sfdp->_domain,
2978 sfdp->_type, sfdp->_protocol);
2979 return p->fds->allocFD(afdp);
2986 unsigned initval,
int in_flags)
2988#if defined(__linux__)
2991 int sim_fd = eventfd(initval, in_flags);
2995 bool cloexec = in_flags & OS::TGT_O_CLOEXEC;
2997 int flags = cloexec ? OS::TGT_O_CLOEXEC : 0;
2998 flags |= (in_flags & OS::TGT_O_NONBLOCK) ? OS::TGT_O_NONBLOCK : 0;
3000 auto hbfdp = std::make_shared<HBFDEntry>(
flags, sim_fd, cloexec);
3001 int tgt_fd =
p->fds->allocFD(hbfdp);
3013 pid_t pid,
typename OS::size_t cpusetsize,
3016#if defined(__linux__)
3021 BufferArg maskBuf(cpu_set_mask, cpusetsize);
3024 CPU_SET(
i, (cpu_set_t *)maskBuf.
bufferPtr());
3038 int tgt_fd,
VPtr<> buf_ptr,
typename OS::size_t buf_len,
3043 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
3046 int sim_fd = sfdp->getSimFD();
3054 socklen_t addr_len = 0;
3055 if (addrlen_ptr != 0) {
3057 BufferArg addrlen_buf(addrlen_ptr,
sizeof(socklen_t));
3058 addrlen_buf.
copyIn(proxy);
3059 addr_len = *((socklen_t *)addrlen_buf.
bufferPtr());
3062 struct sockaddr
sa, *sap = NULL;
3063 if (addr_len != 0) {
3066 memcpy(&
sa, (
struct sockaddr *)addr_buf.
bufferPtr(),
3067 sizeof(
struct sockaddr));
3071 ssize_t recvd_size = recvfrom(sim_fd,
3073 buf_len,
flags, sap, (socklen_t *)&addr_len);
3075 if (recvd_size == -1)
3089 if (addr_len != 0) {
3090 BufferArg addrlen_buf(addrlen_ptr,
sizeof(socklen_t));
3091 *(socklen_t *)addrlen_buf.
bufferPtr() = addr_len;
3099template <
typename OS>
3102 int tgt_fd,
VPtr<> buf_ptr,
typename OS::size_t buf_len,
int flags,
3103 VPtr<> addr_ptr, socklen_t addr_len)
3107 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
3110 int sim_fd = sfdp->getSimFD();
3116 struct sockaddr
sa, *sap =
nullptr;
3117 memset(&
sa, 0,
sizeof(sockaddr));
3118 if (addr_len != 0) {
3121 memcpy(&
sa, (sockaddr*)addr_buf.
bufferPtr(), addr_len);
3125 ssize_t sent_size = sendto(sim_fd,
3127 buf_len,
flags, sap, (socklen_t)addr_len);
3129 return (sent_size == -1) ? -errno : sent_size;
3133template <
typename OS>
3136 typename OS::size_t length)
3144 if (
p->pTable->pageOffset(start))
3147 length =
roundUp(length,
p->pTable->pageSize());
3149 p->memState->unmapRegion(start, length);
3155template <
typename OS>
3158 int tgt_fd,
int mode,
typename OS::off_t
offset,
3159 typename OS::off_t
len)
3161#if defined(__linux__)
3164 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
3167 int sim_fd = ffdp->getSimFD();
3180template <
typename OS>
3183 typename OS::off_t length)
3194 int result = truncate(path.c_str(), length);
3195 return (result == -1) ? -errno : result;
3199template <
typename OS>
3202 typename OS::off_t length)
3206 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
3209 int sim_fd = ffdp->getSimFD();
3211 int result = ftruncate(sim_fd, length);
3212 return (result == -1) ? -errno : result;
3215template <
typename OS>
3226 buf[
i] = se_prng->random<uint8_t>();
Defines global host-dependent types: Counter, Tick, and (indirectly) {int,uint}{8,...
bool copyIn(const PortProxy &memproxy)
copy data into simulator space (read from target memory)
bool copyOut(const PortProxy &memproxy)
copy data out of simulator space (write to target memory)
BufferArg represents an untyped buffer in target user space that is passed by reference to an (emulat...
void * bufferPtr()
Return a pointer to the internal simulator-space buffer.
EmulatedDriver is an abstract base class for fake SE-mode device drivers.
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...
virtual int open(ThreadContext *tc, int mode, int flags)=0
Abstract method, invoked when the user program calls open() on the device driver.
virtual Addr mmap(ThreadContext *tc, Addr start, uint64_t length, int prot, int tgtFlags, int tgtFd, off_t offset)
Virtual method, invoked when the user program calls mmap() on the file descriptor returned by a previ...
FutexMap class holds a map of all futexes used in the system.
void suspend_bitset(Addr addr, uint64_t tgid, ThreadContext *tc, int bitmask)
int requeue(Addr addr1, uint64_t tgid, int count, int count2, Addr addr2)
This operation wakes a given number (val) of waiters.
void suspend(Addr addr, uint64_t tgid, ThreadContext *tc)
Inserts a futex into the map with one waiting TC.
int wakeup(Addr addr, uint64_t tgid, int count)
Wakes up at most count waiting threads on a futex.
int wakeup_bitset(Addr addr, uint64_t tgid, int bitmask)
Addr instAddr() const
Returns the memory address of the instruction this PC points to.
This object is a proxy for a port or other object which implements the functional response protocol,...
void readBlob(Addr addr, void *p, uint64_t size) const
Higher level interfaces based on the above.
void writeBlob(Addr addr, const void *p, uint64_t size) const
Same as tryWriteBlob, but insists on success.
bool tryReadString(std::string &str, Addr addr) const
Reads the string at guest address addr into the std::string str.
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
std::shared_ptr< FDArray > fds
void assignThreadContext(ContextID context_id)
std::string checkPathRedirect(const std::string &filename)
Redirect file path if it matches any keys initialized by system object.
void initState() override
initState() is called on each SimObject when not restoring from a checkpoint.
void revokeThreadContext(int context_id)
After delegating a thread context to a child process no longer should relate to the ThreadContext.
EmulationPageTable * pTable
uint64_t childClearTID
Calls a futex wakeup at the address specified by this pointer when this process exits.
std::shared_ptr< Random > RandomPtr
static RandomPtr genRandom()
This class provides the wrapper interface for the system call implementations which are defined in th...
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...
This class represents the return value from an emulated system call, including any errno setting.
static SyscallReturn retry()
Pseudo-constructor to create an instance with the retry flag set.
ThreadContext * findFree()
std::list< BasicSignal > signalList
ThreadContext is the external interface to all thread state for anything outside of the CPU.
virtual void activate()=0
Set the status to Active.
virtual System * getSystemPtr()=0
virtual void clearArchRegs()=0
virtual void setProcessPtr(Process *p)=0
@ Suspended
Temporarily inactive.
virtual const PCStateBase & pcState() const =0
virtual int threadId() const =0
virtual Status status() const =0
virtual Process * getProcessPtr()=0
virtual ContextID contextId() const =0
virtual void suspend()=0
Set the status to Suspended.
void setUseForClone(bool new_val)
virtual int cpuId() const =0
TypedBufferArg is a class template; instances of this template represent typed buffers in target user...
bool insert(const Symbol &symbol)
Insert a new symbol in the table if it does not already exist.
static constexpr T roundUp(const T &val, const U &align)
This function is used to align addresses in memory.
#define fatal(...)
This implements a cprintf based fatal() function.
#define warn_if(cond,...)
Conditional warning macro that checks the supplied condition and only prints a warning if the conditi...
SymbolTable debugSymbolTable
Global unified debugging symbol table (for target).
ObjectFile * createObjectFile(const std::string &fname, bool raw)
Copyright (c) 2024 Arm Limited All rights reserved.
SyscallReturn linkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr<> new_pathname)
Target link() handler.
SyscallReturn getppidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getppid() handler.
SyscallReturn exitGroupFunc(SyscallDesc *desc, ThreadContext *tc, int status)
Target exit_group() handler: terminate simulation. (exit all threads)
SyscallReturn gettidFunc(SyscallDesc *desc, ThreadContext *tc)
Target gettid() handler.
SyscallReturn getrandomFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> buf_ptr, typename OS::size_t count, unsigned int flags)
SyscallReturn recvmsgFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> msgPtr, int flags)
SyscallReturn fstat64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr< typename OS::tgt_stat64 > tgt_stat)
Target fstat64() handler.
SyscallReturn wait4Func(SyscallDesc *desc, ThreadContext *tc, pid_t pid, VPtr<> statPtr, int options, VPtr<> rusagePtr)
SyscallReturn clock_gettimeFunc(SyscallDesc *desc, ThreadContext *tc, int clk_id, VPtr< typename OS::timespec > tp)
Target clock_gettime() function.
void warnUnsupportedOS(std::string syscall_name)
SyscallReturn brkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> new_brk)
Target brk() handler: set brk address.
SyscallReturn mmapFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> start, typename OS::size_t length, int prot, int tgt_flags, int tgt_fd, typename OS::off_t offset)
Target mmap() handler.
SyscallReturn pipe2Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> tgt_addr, int flags)
Target pipe() handler.
SyscallReturn getpidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getpid() handler.
bool startswith(const char *s, const char *prefix)
Return true if 's' starts with the prefix string 'prefix'.
SyscallReturn chdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname)
Target chdir() handler.
SyscallReturn fstatFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr< typename OS::tgt_stat > tgt_stat)
Target fstat() handler.
SyscallReturn truncate64Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, int64_t length)
Target truncate64() handler.
SyscallReturn getuidFunc(SyscallDesc *desc, ThreadContext *tc)
SyscallReturn pwrite64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> bufPtr, typename OS::size_t nbytes, typename OS::off_t offset)
SyscallReturn getrusageFunc(SyscallDesc *desc, ThreadContext *tc, int who, VPtr< typename OS::rusage > rup)
Target getrusage() function.
SyscallReturn cloneFunc(SyscallDesc *desc, ThreadContext *tc, RegVal flags, RegVal newStack, VPtr<> ptidPtr, VPtr<> ctidPtr, VPtr<> tlsPtr)
SyscallReturn pipePseudoFunc(SyscallDesc *desc, ThreadContext *tc)
Pseudo Funcs - These functions use a different return convension, returning a second value in a regis...
SyscallReturn recvfromFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> buf_ptr, typename OS::size_t buf_len, int flags, VPtr<> addr_ptr, VPtr<> addrlen_ptr)
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)
SyscallReturn utimesFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr< typename OS::timeval[2]> tp)
Target utimes() handler.
SyscallReturn socketFunc(SyscallDesc *desc, ThreadContext *tc, int domain, int type, int prot)
SyscallReturn chownFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, uint32_t owner, uint32_t group)
Target chown() handler.
SyscallReturn statFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr< typename OS::tgt_stat > tgt_stat)
Target stat() handler.
void copyOutStatBuf(TgtStatPtr tgt, HostStatPtr host, bool fakeTTY=false)
SyscallReturn renameImpl(SyscallDesc *desc, ThreadContext *tc, std::string old_name, std::string new_name)
SyscallReturn _llseekFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint32_t offset_high, uint32_t offset_low, VPtr<> result_ptr, int whence)
Target _llseek() handler.
SyscallReturn writeFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> buf_ptr, typename OS::size_t nbytes)
SyscallReturn writevFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> tiov_base, typename OS::size_t count)
Target writev() handler.
SyscallReturn doClone(SyscallDesc *desc, ThreadContext *tc, RegVal flags, RegVal newStack, VPtr<> ptidPtr, VPtr<> ctidPtr, VPtr<> tlsPtr)
SyscallReturn chmodFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode)
Target chmod() handler.
SyscallReturn mknodImpl(SyscallDesc *desc, ThreadContext *tc, std::string path, mode_t mode, dev_t dev)
SyscallReturn renameFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> oldpath, VPtr<> newpath)
Target rename() handler.
SyscallReturn mknodFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode, dev_t dev)
Target mknod() handler.
Tick curTick()
The universal simulation clock.
SyscallReturn setpgidFunc(SyscallDesc *desc, ThreadContext *tc, int pid, int pgid)
Target setpgid() handler.
SyscallReturn truncateFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, typename OS::off_t length)
Target truncate() handler.
SyscallReturn geteuidFunc(SyscallDesc *desc, ThreadContext *tc)
Target geteuid() handler.
SyscallReturn symlinkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr<> new_pathname)
Target symlink() handler.
SyscallReturn atSyscallPath(ThreadContext *tc, int dirfd, std::string &path)
SyscallReturn unlinkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname)
Target unlink() handler.
SyscallReturn lseekFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, typename OS::off_t offs, int whence)
Target lseek() handler.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
T gtoh(T value, ByteOrder guest_byte_order)
SyscallReturn accessImpl(SyscallDesc *desc, ThreadContext *tc, std::string path, mode_t mode)
SyscallReturn sysinfoFunc(SyscallDesc *desc, ThreadContext *tc, VPtr< typename OS::tgt_sysinfo > sysinfo)
Target sysinfo() handler.
SyscallReturn fchownatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, uint32_t owner, uint32_t group, int flags)
Target fchownat() handler.
SyscallReturn chownImpl(SyscallDesc *desc, ThreadContext *tc, std::string path, uint32_t owner, uint32_t group)
SyscallReturn gettimeofdayFunc(SyscallDesc *desc, ThreadContext *tc, VPtr< typename OS::timeval > tp, VPtr<> tz_ptr)
Target gettimeofday() handler.
SyscallReturn unlinkatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, int flags)
Target unlinkat() handler.
SyscallReturn pipeFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> tgt_addr)
Target pipe() handler.
SyscallReturn prlimitFunc(SyscallDesc *desc, ThreadContext *tc, int pid, int resource, VPtr<> n, VPtr< typename OS::rlimit > rlp)
SyscallReturn clock_getresFunc(SyscallDesc *desc, ThreadContext *tc, int clk_id, VPtr< typename OS::timespec > tp)
Target clock_getres() function.
void copyOutStat64Buf(TgtStatPtr tgt, HostStatPtr host, bool fakeTTY=false)
SyscallReturn faccessatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, int mode)
Target facessat() handler.
SyscallReturn getsockoptFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int level, int optname, VPtr<> valPtr, VPtr<> lenPtr)
SyscallReturn getrlimitFunc(SyscallDesc *desc, ThreadContext *tc, unsigned resource, VPtr< typename OS::rlimit > rlp)
Target getrlimit() handler.
SyscallReturn mknodatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, mode_t mode, dev_t dev)
Target mknodat() handler.
SyscallReturn fallocateFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int mode, typename OS::off_t offset, typename OS::off_t len)
SyscallReturn fcntl64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int cmd)
Target fcntl64() handler.
SyscallReturn futimesatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, VPtr< typename OS::timeval[2]> tp)
Target futimesat() handler.
SyscallReturn ignoreWarnOnceFunc(SyscallDesc *desc, ThreadContext *tc)
Like above, but only prints a warning once per syscall desc it's used with.
SyscallReturn socketpairFunc(SyscallDesc *desc, ThreadContext *tc, int domain, int type, int prot, VPtr<> svPtr)
void copyOutStatfsBuf(TgtStatPtr tgt, HostStatPtr host)
SyscallReturn ftruncateFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, typename OS::off_t length)
Target ftruncate() handler.
SyscallReturn statfsFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr< typename OS::tgt_statfs > tgt_stat)
Target statfs() handler.
SyscallReturn setsockoptFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int level, int optname, VPtr<> valPtr, socklen_t len)
SyscallReturn getpagesizeFunc(SyscallDesc *desc, ThreadContext *tc)
Target getpagesize() handler.
SyscallReturn lstatFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr< typename OS::tgt_stat > tgt_stat)
Target lstat() handler.
SyscallReturn rmdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname)
SyscallReturn mkdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode)
Target mkdir() handler.
SyscallReturn readlinkatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, VPtr<> buf_ptr, typename OS::size_t bufsiz)
Target readlinkat() handler.
SyscallReturn getpgrpFunc(SyscallDesc *desc, ThreadContext *tc)
Target getpgrpFunc() handler.
void copyOutStatxBuf(TgtStatPtr tgt, HostStatPtr host, bool fakeTTY=false)
SyscallReturn eventfdFunc(SyscallDesc *desc, ThreadContext *tc, unsigned initval, int in_flags)
Target eventfd() function.
SyscallReturn unlinkImpl(SyscallDesc *desc, ThreadContext *tc, std::string path)
SyscallReturn dupFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd)
FIXME: The file description is not shared among file descriptors created with dup.
SyscallReturn listenFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int backlog)
SyscallReturn readvFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> tiov_base, typename OS::size_t count)
Target readv() handler.
SyscallReturn ftruncate64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int64_t length)
Target ftruncate64() handler.
SyscallReturn getcwdFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> buf_ptr, typename OS::size_t size)
Target getcwd() handler.
SyscallReturn fchmodatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, mode_t mode)
Target chmod() handler.
SyscallReturn openatFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_dirfd, VPtr<> pathname, int tgt_flags, int mode)
Target open() handler.
SyscallReturn fchownFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint32_t owner, uint32_t group)
Target fchown() handler.
SyscallReturn munmapFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> start, typename OS::size_t length)
Target munmap() handler.
SyscallReturn readlinkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr<> buf_ptr, typename OS::size_t bufsiz)
Target readlink() handler.
SyscallReturn pread64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> bufPtr, typename OS::size_t nbytes, typename OS::off_t offset)
SyscallReturn setTidAddressFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> tidPtr)
Target set_tid_address() handler.
void getElapsedTimeMicro(T1 &sec, T2 &usec)
Helper function to convert current elapsed time to seconds and microseconds.
const unsigned seconds_since_epoch
Approximate seconds since the epoch (1/1/1970).
SyscallReturn timesFunc(SyscallDesc *desc, ThreadContext *tc, VPtr< typename OS::tms > bufp)
Target times() function.
SyscallReturn fcntlFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int cmd, guest_abi::VarArgs< int > varargs)
Target fcntl() handler.
SyscallReturn openFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, int tgt_flags, int mode)
Target open() handler.
void getElapsedTimeNano(T1 &sec, T2 &nsec)
Helper function to convert current elapsed time to seconds and nanoseconds.
T htog(T value, ByteOrder guest_byte_order)
SyscallReturn schedGetaffinityFunc(SyscallDesc *desc, ThreadContext *tc, pid_t pid, typename OS::size_t cpusetsize, VPtr<> cpu_set_mask)
Target sched_getaffinity.
SyscallReturn bindFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> buf_ptr, int addrlen)
SyscallReturn pollFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> fdsPtr, int nfds, int tmout)
SyscallReturn getegidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getegid() handler.
SyscallReturn timeFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> taddr)
Target time() function.
SyscallReturn newfstatatFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, VPtr< typename OS::tgt_stat64 > tgt_stat, int flags)
Target newfstatat() handler.
SyscallReturn fchmodFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint32_t mode)
Target fchmod() handler.
SyscallReturn shutdownFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int how)
Target shutdown() handler.
SyscallReturn renameatFunc(SyscallDesc *desc, ThreadContext *tc, int olddirfd, VPtr<> oldpath, int newdirfd, VPtr<> newpath)
Target renameat() handler.
SyscallReturn getcpuFunc(SyscallDesc *desc, ThreadContext *tc, VPtr< uint32_t > cpu, VPtr< uint32_t > node, VPtr< uint32_t > tcache)
SyscallReturn getsocknameFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> addrPtr, VPtr<> lenPtr)
SyscallReturn clone3Func(SyscallDesc *desc, ThreadContext *tc, VPtr< typename OS::tgt_clone_args > cl_args, RegVal size)
SyscallReturn mkdirImpl(SyscallDesc *desc, ThreadContext *tc, std::string path, mode_t mode)
SyscallReturn ioctlFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, unsigned req, VPtr<> addr)
Target ioctl() handler.
SyscallReturn getpeernameFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> sockAddrPtr, VPtr<> addrlenPtr)
SyscallReturn unimplementedFunc(SyscallDesc *desc, ThreadContext *tc)
Handler for unimplemented syscalls that we haven't thought about.
SyscallReturn gethostnameFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> buf_ptr, int name_len)
Target gethostname() handler.
SyscallReturn accessFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode)
Target access() handler.
SyscallReturn tgkillFunc(SyscallDesc *desc, ThreadContext *tc, int tgid, int tid, int sig)
SyscallReturn sendmsgFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> msgPtr, int flags)
SyscallReturn cloneBackwardsFunc(SyscallDesc *desc, ThreadContext *tc, RegVal flags, RegVal newStack, VPtr<> ptidPtr, VPtr<> tlsPtr, VPtr<> ctidPtr)
SyscallReturn lstat64Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr< typename OS::tgt_stat64 > tgt_stat)
Target lstat64() handler.
SyscallReturn fstatat64Func(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, VPtr< typename OS::tgt_stat64 > tgt_stat)
Target fstatat64() handler.
SyscallReturn ignoreFunc(SyscallDesc *desc, ThreadContext *tc)
Handler for unimplemented syscalls that we never intend to implement (signal handling,...
SyscallReturn rmdirImpl(SyscallDesc *desc, ThreadContext *tc, std::string path)
SyscallReturn acceptFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> addrPtr, VPtr<> lenPtr)
SyscallReturn futexFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> uaddr, int op, int val, int timeout, VPtr<> uaddr2, int val3)
Futex system call Implemented by Daniel Sanchez Used by printf's in multi-threaded apps.
SyscallReturn fstatfsFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr< typename OS::tgt_statfs > tgt_stat)
Target fstatfs() handler.
SyscallReturn statxFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, int flags, unsigned int mask, VPtr< typename OS::tgt_statx > tgt_statx)
Target statx() handler.
SyscallReturn mremapFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> start, typename OS::size_t old_length, typename OS::size_t new_length, int flags, guest_abi::VarArgs< uint64_t > varargs)
Target mremap() handler.
SyscallReturn stat64Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr< typename OS::tgt_stat64 > tgt_stat)
Target stat64() handler.
SyscallReturn connectFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> buf_ptr, int addrlen)
SyscallReturn execveFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr<> argv_mem_loc, VPtr<> envp_mem_loc)
SyscallReturn exitFunc(SyscallDesc *desc, ThreadContext *tc, int status)
Target exit() handler: terminate current context.
SyscallReturn dup2Func(SyscallDesc *desc, ThreadContext *tc, int old_tgt_fd, int new_tgt_fd)
Target dup2() handler.
SyscallReturn getgidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getgid() handler.
SyscallReturn readFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> buf_ptr, typename OS::size_t nbytes)
SyscallReturn closeFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd)
Target close() handler.
SyscallReturn umaskFunc(SyscallDesc *desc, ThreadContext *tc)
Target umask() handler.
SyscallReturn mmap2Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> start, typename OS::size_t length, int prot, int tgt_flags, int tgt_fd, typename OS::off_t offset)
Target mmap2() handler.
SyscallReturn sendtoFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> buf_ptr, typename OS::size_t buf_len, int flags, VPtr<> addr_ptr, socklen_t addr_len)
SyscallReturn mkdiratFunc(SyscallDesc *desc, ThreadContext *tc, int dirfd, VPtr<> pathname, mode_t mode)
Target mkdirat() handler.
Declarations of a non-full system Page Table.
#define DPRINTF_SYSCALL(FLAGEXT, FMT,...)
This macro is intended to help with readability.
This file defines buffer classes used to handle pointer arguments in emulated syscalls.