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,
187SyscallReturn
symlinkFunc(SyscallDesc *desc, ThreadContext *tc,
191SyscallReturn
mkdirFunc(SyscallDesc *desc, ThreadContext *tc,
193SyscallReturn
mkdirImpl(SyscallDesc *desc, ThreadContext *tc,
194 std::string path, mode_t
mode);
197SyscallReturn
mknodFunc(SyscallDesc *desc, ThreadContext *tc,
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,
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,
297#if defined(SYS_getdents64)
299SyscallReturn getdents64Func(SyscallDesc *desc, ThreadContext *tc,
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,
329SyscallReturn
accessImpl(SyscallDesc *desc, ThreadContext *tc,
330 std::string path, mode_t
mode);
334 int tgt_fd,
int level,
int optname,
339 int tgt_fd,
int level,
int optname,
342SyscallReturn
getcpuFunc(SyscallDesc *desc, ThreadContext *tc,
359 if (dirfd != OS::TGT_AT_FDCWD && !
startswith(path,
"/")) {
362 std::shared_ptr<FDEntry> fdep = ((*process->fds)[dirfd]);
363 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
368 path = ffdp->getFileName();
370 path = ffdp->getFileName() +
"/" + path;
390 op &= ~OS::TGT_FUTEX_PRIVATE_FLAG;
391 op &= ~OS::TGT_FUTEX_CLOCK_REALTIME_FLAG;
395 if (OS::TGT_FUTEX_WAIT ==
op || OS::TGT_FUTEX_WAIT_BITSET ==
op) {
407 return -OS::TGT_EWOULDBLOCK;
409 if (OS::TGT_FUTEX_WAIT ==
op) {
410 futex_map.
suspend(uaddr, process->tgid(), tc);
416 }
else if (OS::TGT_FUTEX_WAKE ==
op) {
417 return futex_map.
wakeup(uaddr, process->tgid(),
val);
418 }
else if (OS::TGT_FUTEX_WAKE_BITSET ==
op) {
419 return futex_map.
wakeup_bitset(uaddr, process->tgid(), val3);
420 }
else if (OS::TGT_FUTEX_REQUEUE ==
op ||
421 OS::TGT_FUTEX_CMP_REQUEUE ==
op) {
431 if (OS::TGT_FUTEX_CMP_REQUEUE && val3 != mem_val)
432 return -OS::TGT_EWOULDBLOCK;
433 return futex_map.
requeue(uaddr, process->tgid(),
val, timeout, uaddr2);
434 }
else if (OS::TGT_FUTEX_WAKE_OP ==
op) {
462 int wake_cmparg = val3 & 0xfff;
463 int wake_oparg = (val3 & 0xfff000) >> 12;
464 int wake_cmp = (val3 & 0xf000000) >> 24;
465 int wake_op = (val3 & 0xf0000000) >> 28;
466 if ((wake_op & OS::TGT_FUTEX_OP_ARG_SHIFT) >> 3 == 1)
467 wake_oparg = (1 << wake_oparg);
468 wake_op &= ~OS::TGT_FUTEX_OP_ARG_SHIFT;
470 if (wake_op == OS::TGT_FUTEX_OP_SET)
472 else if (wake_op == OS::TGT_FUTEX_OP_ADD)
473 newval += wake_oparg;
474 else if (wake_op == OS::TGT_FUTEX_OP_OR)
475 newval |= wake_oparg;
476 else if (wake_op == OS::TGT_FUTEX_OP_ANDN)
477 newval &= ~wake_oparg;
478 else if (wake_op == OS::TGT_FUTEX_OP_XOR)
479 newval ^= wake_oparg;
484 int woken1 = futex_map.
wakeup(uaddr, process->tgid(),
val);
487 bool is_wake2 =
false;
488 if (wake_cmp == OS::TGT_FUTEX_OP_CMP_EQ)
489 is_wake2 = oldval == wake_cmparg;
490 else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_NE)
491 is_wake2 = oldval != wake_cmparg;
492 else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_LT)
493 is_wake2 = oldval < wake_cmparg;
494 else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_LE)
495 is_wake2 = oldval <= wake_cmparg;
496 else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_GT)
497 is_wake2 = oldval > wake_cmparg;
498 else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_GE)
499 is_wake2 = oldval >= wake_cmparg;
502 woken2 = futex_map.
wakeup(uaddr2, process->tgid(), timeout);
504 return woken1 + woken2;
506 warn(
"futex: op %d not implemented; ignoring.",
op);
512SyscallReturn
pipePseudoFunc(SyscallDesc *desc, ThreadContext *tc);
522template <
class T1,
class T2>
526 static const int OneMillion = 1000 * 1000;
529 sec = elapsed_usecs / OneMillion;
530 usec = elapsed_usecs % OneMillion;
535template <
class T1,
class T2>
539 static const int OneBillion = 1000 * 1000 * 1000;
542 sec = elapsed_nsecs / OneBillion;
543 nsec = elapsed_nsecs % OneBillion;
566template <
typename OS,
typename TgtStatPtr,
typename HostStatPtr>
570 constexpr ByteOrder
bo = OS::byteOrder;
575 tgt->st_dev = host->st_dev;
576 tgt->st_dev =
htog(tgt->st_dev,
bo);
577 tgt->st_ino = host->st_ino;
578 tgt->st_ino =
htog(tgt->st_ino,
bo);
579 tgt->st_mode = host->st_mode;
582 tgt->st_mode &= ~S_IFMT;
583 tgt->st_mode |= S_IFCHR;
585 tgt->st_mode =
htog(tgt->st_mode,
bo);
586 tgt->st_nlink = host->st_nlink;
587 tgt->st_nlink =
htog(tgt->st_nlink,
bo);
588 tgt->st_uid = host->st_uid;
589 tgt->st_uid =
htog(tgt->st_uid,
bo);
590 tgt->st_gid = host->st_gid;
591 tgt->st_gid =
htog(tgt->st_gid,
bo);
593 tgt->st_rdev = 0x880d;
595 tgt->st_rdev = host->st_rdev;
596 tgt->st_rdev =
htog(tgt->st_rdev,
bo);
597 tgt->st_size = host->st_size;
598 tgt->st_size =
htog(tgt->st_size,
bo);
599 tgt->st_atimeX = host->st_atime;
600 tgt->st_atimeX =
htog(tgt->st_atimeX,
bo);
601 tgt->st_mtimeX = host->st_mtime;
602 tgt->st_mtimeX =
htog(tgt->st_mtimeX,
bo);
603 tgt->st_ctimeX = host->st_ctime;
604 tgt->st_ctimeX =
htog(tgt->st_ctimeX,
bo);
607 tgt->st_blksize = 0x2000;
608 tgt->st_blksize =
htog(tgt->st_blksize,
bo);
609 tgt->st_blocks = host->st_blocks;
610 tgt->st_blocks =
htog(tgt->st_blocks,
bo);
615template <
typename OS,
typename TgtStatPtr,
typename HostStatPtr>
621#if defined(STAT_HAVE_NSEC)
622 constexpr ByteOrder
bo = OS::byteOrder;
624 tgt->st_atime_nsec = host->st_atime_nsec;
625 tgt->st_atime_nsec =
htog(tgt->st_atime_nsec,
bo);
626 tgt->st_mtime_nsec = host->st_mtime_nsec;
627 tgt->st_mtime_nsec =
htog(tgt->st_mtime_nsec,
bo);
628 tgt->st_ctime_nsec = host->st_ctime_nsec;
629 tgt->st_ctime_nsec =
htog(tgt->st_ctime_nsec,
bo);
631 tgt->st_atime_nsec = 0;
632 tgt->st_mtime_nsec = 0;
633 tgt->st_ctime_nsec = 0;
637template <
class OS,
typename TgtStatPtr,
typename HostStatPtr>
641 constexpr ByteOrder
bo = OS::byteOrder;
643 tgt->f_type =
htog(host->f_type,
bo);
644#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
645 tgt->f_bsize =
htog(host->f_iosize,
bo);
647 tgt->f_bsize =
htog(host->f_bsize,
bo);
649 tgt->f_blocks =
htog(host->f_blocks,
bo);
650 tgt->f_bfree =
htog(host->f_bfree,
bo);
651 tgt->f_bavail =
htog(host->f_bavail,
bo);
652 tgt->f_files =
htog(host->f_files,
bo);
653 tgt->f_ffree =
htog(host->f_ffree,
bo);
654 memcpy(&tgt->f_fsid, &host->f_fsid,
sizeof(host->f_fsid));
655#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
656 tgt->f_namelen =
htog(host->f_namemax,
bo);
657 tgt->f_frsize =
htog(host->f_bsize,
bo);
658#elif defined(__APPLE__)
662 tgt->f_namelen =
htog(host->f_namelen,
bo);
663 tgt->f_frsize =
htog(host->f_frsize,
bo);
665#if defined(__linux__)
666 memcpy(&tgt->f_spare, &host->f_spare,
667 std::min(
sizeof(host->f_spare),
sizeof(tgt->f_spare)));
673 memset(&tgt->f_spare, 0,
sizeof(tgt->f_spare));
677template <
typename OS,
typename TgtStatPtr,
typename HostStatPtr>
681 constexpr ByteOrder
bo = OS::byteOrder;
684 tgt->stx_dev_major = 0x00;
685 tgt->stx_dev_minor = 0x0A;
687 tgt->stx_dev_major = host->st_dev >> 8;
688 tgt->stx_dev_minor = host->st_dev & 0xFF;
690 tgt->stx_dev_major =
htog(tgt->stx_dev_major,
bo);
691 tgt->stx_dev_minor =
htog(tgt->stx_dev_minor,
bo);
692 tgt->stx_ino = host->st_ino;
693 tgt->stx_ino =
htog(tgt->stx_ino,
bo);
694 tgt->stx_mode = host->st_mode;
697 tgt->stx_mode &= ~S_IFMT;
698 tgt->stx_mode |= S_IFCHR;
700 tgt->stx_mode =
htog(tgt->stx_mode,
bo);
701 tgt->stx_nlink = host->st_nlink;
702 tgt->stx_nlink =
htog(tgt->stx_nlink,
bo);
703 tgt->stx_uid = host->st_uid;
704 tgt->stx_uid =
htog(tgt->stx_uid,
bo);
705 tgt->stx_gid = host->st_gid;
706 tgt->stx_gid =
htog(tgt->stx_gid,
bo);
708 tgt->stx_rdev_major = 0x880d >> 8;
709 tgt->stx_rdev_minor = 0x880d & 0xFF;
711 tgt->stx_rdev_major = host->st_rdev >> 8;
712 tgt->stx_rdev_minor = host->st_rdev & 0xFF;
714 tgt->stx_rdev_major =
htog(tgt->stx_rdev_major,
bo);
715 tgt->stx_rdev_minor =
htog(tgt->stx_rdev_minor,
bo);
716 tgt->stx_size = host->st_size;
717 tgt->stx_size =
htog(tgt->stx_size,
bo);
718 tgt->stx_atimeX = host->st_atime;
719 tgt->stx_atimeX =
htog(tgt->stx_atimeX,
bo);
720 tgt->stx_ctimeX = host->st_ctime;
721 tgt->stx_ctimeX =
htog(tgt->stx_ctimeX,
bo);
722 tgt->stx_mtimeX = host->st_mtime;
723 tgt->stx_mtimeX =
htog(tgt->stx_mtimeX,
bo);
726 tgt->stx_blksize = 0x2000;
727 tgt->stx_blksize =
htog(tgt->stx_blksize,
bo);
728 tgt->stx_blocks = host->st_blocks;
729 tgt->stx_blocks =
htog(tgt->stx_blocks,
bo);
730 tgt->stx_mask = 0x000007ffU;
731 tgt->stx_mask =
htog(tgt->stx_mask,
bo);
732 tgt->stx_attributes = 0;
733 tgt->stx_attributes_mask = 0;
734 tgt->stx_attributes_mask =
htog(tgt->stx_attributes_mask,
bo);
750 if (OS::isTtyReq(req))
753 auto dfdp = std::dynamic_pointer_cast<DeviceFDEntry>((*
p->fds)[tgt_fd]);
757 return emul_driver->
ioctl(tc, req,
addr);
760 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
769 ifconf *conf = (ifconf*)conf_arg.
bufferPtr();
770 Addr ifc_buf_addr = (
Addr)conf->ifc_buf;
771 BufferArg ifc_buf_arg(ifc_buf_addr, conf->ifc_len);
774 conf->ifc_buf = (
char*)ifc_buf_arg.
bufferPtr();
778 conf->ifc_buf = (
char*)ifc_buf_addr;
786#if defined(__linux__)
791#if defined(__linux__)
810 warn(
"Unsupported ioctl call (return ENOTTY): ioctl(%d, 0x%x, ...) @ %s\n",
819 int tgt_dirfd,
VPtr<> pathname,
int tgt_flags,
int mode)
832 int host_flags = O_BINARY;
840 for (
const auto &
p: OS::openFlagTable) {
841 if (tgt_flags &
p.first) {
842 tgt_flags &=
~p.first;
843 host_flags |=
p.second;
846 warn_if(tgt_flags,
"%s: cannot decode flags %#x", desc->
name(), tgt_flags);
849 host_flags |= O_BINARY;
864 std::string redir_path = path;
865 std::string abs_path = path;
866 if (tgt_dirfd == OS::TGT_AT_FDCWD) {
867 abs_path =
p->absolutePath(path,
true);
868 redir_path =
p->checkPathRedirect(path);
870 std::shared_ptr<FDEntry> fdep = ((*
p->fds)[tgt_dirfd]);
871 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
874 abs_path = ffdp->getFileName() + path;
875 redir_path =
p->checkPathRedirect(abs_path);
885 std::string filename = abs_path.substr(strlen(
"/dev/"));
889 "driver open with path[%s]\n",
890 desc->
name(), abs_path.c_str());
891 return drv->
open(tc,
mode, host_flags);
924 std::string used_path;
926 {
"/proc/meminfo",
"/system/",
"/platform/",
"/etc/passwd",
927 "/proc/self/maps",
"/dev/urandom",
928 "/sys/devices/system/cpu/online" };
929 for (
auto entry : special_paths) {
931 sim_fd = OS::openSpecialFile(abs_path,
p, tc);
932 used_path = abs_path;
936 sim_fd = open(redir_path.c_str(), host_flags,
mode);
937 used_path = redir_path;
942 "(inferred from:%s)\n", desc->
name(),
943 used_path.c_str(), path.c_str());
955 auto ffdp = std::make_shared<FileFDEntry>(sim_fd, host_flags, path, 0);
957 ffdp->setFileMode(
mode);
958 int tgt_fd =
p->fds->allocFD(ffdp);
960 "(inferred from:%s)\n", desc->
name(),
961 sim_fd, tgt_fd, used_path.c_str(), path.c_str());
972 desc, tc, OS::TGT_AT_FDCWD, pathname, tgt_flags,
mode);
979 VPtr<> buf_ptr,
typename OS::size_t size)
986 std::string cwd =
p->tgtCwd;
988 if (cwd.length() >= size) {
992 strncpy((
char *)buf.
bufferPtr(), cwd.c_str(), size);
993 result = cwd.length();
995 if (getcwd((
char *)buf.
bufferPtr(), size)) {
996 result = strlen((
char *)buf.
bufferPtr());
1004 return (result == -1) ? -errno : result;
1011 int tgt_fd,
typename OS::off_t offs,
int whence)
1015 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
1018 int sim_fd = ffdp->getSimFD();
1020 off_t result = lseek(sim_fd, offs, whence);
1022 return (result == (off_t)-1) ? -errno : result;
1029 int dirfd,
VPtr<> pathname,
int flags)
1040 if (flags & OS::TGT_AT_REMOVEDIR) {
1070 typename OS::size_t bufsiz)
1084 path =
p->checkPathRedirect(path);
1089 if (path !=
"/proc/self/exe") {
1090 result = readlink(path.c_str(), (
char *)buf.
bufferPtr(), bufsiz);
1104 char real_path[PATH_MAX];
1105 char *check_real_path = realpath(
p->progName(), real_path);
1106 if (!check_real_path) {
1107 fatal(
"readlink('/proc/self/exe') unable to resolve path to "
1108 "executable: %s",
p->progName());
1110 strncpy((
char*)buf.
bufferPtr(), real_path, bufsiz);
1111 typename OS::size_t real_path_len = strlen(real_path);
1112 if (real_path_len > bufsiz) {
1117 result = real_path_len;
1121 warn_once(
"readlink() called on '/proc/self/exe' may yield unexpected "
1122 "results in various settings.\n Returning '%s'\n",
1128 return (result == -1) ? -errno : result;
1136 typename OS::size_t bufsiz)
1139 pathname, buf_ptr, bufsiz);
1146 int olddirfd,
VPtr<> oldpath,
int newdirfd,
VPtr<> newpath)
1149 std::string old_name;
1153 std::string new_name;
1167 return renameImpl(desc, tc, old_name, new_name);
1174 int dirfd,
VPtr<> pathname, uint32_t owner, uint32_t group,
1186 return chownImpl(desc, tc, path, owner, group);
1211 int dirfd,
VPtr<> pathname, mode_t
mode, dev_t dev)
1234 sysinfo->totalram = process->system->memSize();
1235 sysinfo->mem_unit = 1;
1255 mode_t hostMode = 0;
1265 int result = chmod(path.c_str(), hostMode);
1283 VPtr<> fdsPtr,
int nfds,
int tmout)
1287 BufferArg fdsBuf(fdsPtr,
sizeof(
struct pollfd) * nfds);
1296 auto temp_tgt_fds = std::make_unique<int[]>(nfds);
1299 int tgt_fd = temp_tgt_fds[
index];
1300 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[tgt_fd]);
1303 auto host_fd = hbfdp->getSimFD();
1325 if (it->receiver ==
p)
1340 int tgt_fd = temp_tgt_fds[
index];
1360 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
1363 int sim_fd = ffdp->getSimFD();
1365 mode_t hostMode =
mode;
1367 int result = fchmod(sim_fd, hostMode);
1369 return (result < 0) ? -errno : 0;
1376 VPtr<> start,
typename OS::size_t old_length,
1377 typename OS::size_t new_length,
int flags,
1381 Addr page_bytes =
p->pTable->pageSize();
1382 uint64_t provided_address = 0;
1383 bool use_provided_address = flags & OS::TGT_MREMAP_FIXED;
1385 if (use_provided_address)
1386 provided_address = varargs.
get<uint64_t>();
1388 if ((start % page_bytes != 0) ||
1389 (provided_address % page_bytes != 0)) {
1390 warn(
"mremap failing: arguments not page aligned");
1394 new_length =
roundUp(new_length, page_bytes);
1396 if (new_length > old_length) {
1397 Addr mmap_end =
p->memState->getMmapEnd();
1399 if ((start + old_length) == mmap_end &&
1400 (!use_provided_address || provided_address == start)) {
1403 uint64_t diff = new_length - old_length;
1404 p->memState->mapRegion(mmap_end, diff,
"remapped");
1405 p->memState->setMmapEnd(mmap_end + diff);
1408 if (!use_provided_address && !(flags & OS::TGT_MREMAP_MAYMOVE)) {
1409 warn(
"can't remap here and MREMAP_MAYMOVE flag not set\n");
1412 uint64_t new_start = provided_address;
1413 if (!use_provided_address) {
1414 new_start =
p->mmapGrowsDown() ?
1415 mmap_end - new_length : mmap_end;
1416 mmap_end =
p->mmapGrowsDown() ?
1417 new_start : mmap_end + new_length;
1418 p->memState->setMmapEnd(mmap_end);
1421 warn(
"mremapping to new vaddr %08p-%08p, adding %d\n",
1422 new_start, new_start + new_length,
1423 new_length - old_length);
1426 p->allocateMem(new_start + old_length,
1427 new_length - old_length,
1428 use_provided_address );
1430 if (use_provided_address &&
1431 ((new_start + new_length >
p->memState->getMmapEnd() &&
1432 !
p->mmapGrowsDown()) ||
1433 (new_start < p->memState->getMmapEnd() &&
1434 p->mmapGrowsDown()))) {
1437 warn(
"mmap region limit exceeded with MREMAP_FIXED\n");
1440 warn(
"returning %08p as start\n", new_start);
1441 p->memState->remapRegion(start, new_start, old_length);
1447 if (use_provided_address && provided_address != start)
1448 p->memState->remapRegion(start, provided_address, new_length);
1449 if (new_length != old_length)
1450 p->memState->unmapRegion(start + new_length,
1451 old_length - new_length);
1452 return use_provided_address ? provided_address : (
Addr)start;
1471 struct stat hostBuf;
1472 int result = stat(path.c_str(), &hostBuf);
1494 if (path.empty() && !(flags & OS::TGT_AT_EMPTY_PATH))
1496 flags = flags & ~OS::TGT_AT_EMPTY_PATH;
1498 warn_if(flags != 0,
"newfstatat: Flag bits %#x not supported.", flags);
1508 path =
p->checkPathRedirect(path);
1510 struct stat host_buf;
1511 int result = stat(path.c_str(), &host_buf);
1525 int dirfd,
VPtr<> pathname,
1540 path =
p->checkPathRedirect(path);
1543 struct stat hostBuf;
1544 int result = stat(path.c_str(), &hostBuf);
1546 struct stat64 hostBuf;
1547 int result = stat64(path.c_str(), &hostBuf);
1571 int dirfd,
VPtr<> pathname,
int flags,
1579 if (path.empty() && !(flags & OS::TGT_AT_EMPTY_PATH))
1581 flags = flags & ~OS::TGT_AT_EMPTY_PATH;
1583 warn_if(flags != 0,
"statx: Flag bits %#x not supported.", flags);
1593 path =
p->checkPathRedirect(path);
1595 struct stat host_buf;
1596 int result = stat(path.c_str(), &host_buf);
1614 auto ffdp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[tgt_fd]);
1617 int sim_fd = ffdp->getSimFD();
1620 struct stat hostBuf;
1621 int result = fstat(sim_fd, &hostBuf);
1623 struct stat64 hostBuf;
1624 int result = fstat64(sim_fd, &hostBuf);
1651 struct stat hostBuf;
1652 int result = lstat(path.c_str(), &hostBuf);
1678 struct stat hostBuf;
1679 int result = lstat(path.c_str(), &hostBuf);
1681 struct stat64 hostBuf;
1682 int result = lstat64(path.c_str(), &hostBuf);
1703 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
1706 int sim_fd = ffdp->getSimFD();
1708 struct stat hostBuf;
1709 int result = fstat(sim_fd, &hostBuf);
1725#if defined(__linux__)
1735 struct statfs hostBuf;
1736 int result = statfs(path.c_str(), &hostBuf);
1754 DPRINTF(SyscallVerbose,
"Doing clone. pid: %#llx, ctid: %#llx, tls: %#llx"
1755 " flags: %#llx, stack: %#llx\n",
1756 ptidPtr.
addr(), ctidPtr.
addr(), tlsPtr.
addr(), flags, newStack);
1759 if (((flags & OS::TGT_CLONE_SIGHAND)&& !(flags & OS::TGT_CLONE_VM)) ||
1760 ((flags & OS::TGT_CLONE_THREAD) && !(flags & OS::TGT_CLONE_SIGHAND)) ||
1761 ((flags & OS::TGT_CLONE_FS) && (flags & OS::TGT_CLONE_NEWNS)) ||
1762 ((flags & OS::TGT_CLONE_NEWIPC) && (flags & OS::TGT_CLONE_SYSVSEM)) ||
1763 ((flags & OS::TGT_CLONE_NEWPID) && (flags & OS::TGT_CLONE_THREAD)) ||
1764 ((flags & OS::TGT_CLONE_VM) && !(newStack)))
1780 ProcessParams *pp =
new ProcessParams();
1781 pp->executable.assign(*(
new std::string(
p->progName())));
1782 pp->cmd.push_back(*(
new std::string(
p->progName())));
1783 pp->system =
p->system;
1784 pp->cwd.assign(
p->tgtCwd);
1785 pp->input.assign(
"stdin");
1786 pp->output.assign(
"stdout");
1787 pp->errout.assign(
"stderr");
1789 pp->euid =
p->euid();
1791 pp->egid =
p->egid();
1792 pp->release =
p->release;
1795 std::set<int>
const& pids =
p->system->PIDs;
1796 int temp_pid = *pids.begin();
1799 }
while (pids.find(temp_pid) != pids.end());
1801 fatal(
"temp_pid is too large: %d", temp_pid);
1804 pp->ppid = (flags & OS::TGT_CLONE_THREAD) ?
p->ppid() :
p->pid();
1805 pp->useArchPT =
p->useArchPT;
1806 pp->kvmInSE =
p->kvmInSE;
1817 if (flags & OS::TGT_CLONE_PARENT_SETTID) {
1818 BufferArg ptidBuf(ptidPtr,
sizeof(
long));
1819 long *ptid = (
long *)ptidBuf.
bufferPtr();
1824 if (flags & OS::TGT_CLONE_THREAD) {
1825 cp->pTable->initState();
1826 cp->pTable->shared =
true;
1827 cp->useForClone =
true;
1832 p->clone(tc, ctc,
cp, flags);
1834 if (flags & OS::TGT_CLONE_THREAD) {
1836 cp->sigchld =
p->sigchld;
1837 }
else if (flags & OS::TGT_SIGCHLD) {
1838 *
cp->sigchld =
true;
1841 if (flags & OS::TGT_CLONE_CHILD_SETTID) {
1842 BufferArg ctidBuf(ctidPtr,
sizeof(
long));
1843 long *ctid = (
long *)ctidBuf.
bufferPtr();
1848 if (flags & OS::TGT_CLONE_CHILD_CLEARTID)
1849 cp->childClearTID = (uint64_t)ctidPtr;
1853 OS::archClone(flags,
p,
cp, tc, ctc, newStack, tlsPtr);
1859 if (flags & OS::TGT_CLONE_VFORK) {
1876 uint64_t new_stack = cl_args->stack + cl_args->stack_size;
1877 uint64_t flags = cl_args->flags;
1879 return doClone<OS>(desc, tc, flags, new_stack, ptidPtr, ctidPtr, tlsPtr);
1887 return doClone<OS>(desc, tc, flags, newStack, ptidPtr, ctidPtr, tlsPtr);
1896 return cloneFunc<OS>(desc, tc, flags, newStack, ptidPtr, ctidPtr, tlsPtr);
1907 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
1910 int sim_fd = ffdp->getSimFD();
1912 struct statfs hostBuf;
1913 int result = fstatfs(sim_fd, &hostBuf);
1927 int tgt_fd,
VPtr<> tiov_base,
1928 typename OS::size_t
count)
1932 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
1935 int sim_fd = ffdp->getSimFD();
1938 auto tiov = std::make_unique<typename OS::tgt_iovec[]>(
count);
1939 auto hiov = std::make_unique<struct iovec[]>(
count);
1940 for (
typename OS::size_t
i = 0;
i <
count; ++
i) {
1941 prox.
readBlob(tiov_base + (
i *
sizeof(
typename OS::tgt_iovec)),
1942 &tiov[
i],
sizeof(
typename OS::tgt_iovec));
1943 hiov[
i].iov_len =
gtoh(tiov[
i].iov_len, OS::byteOrder);
1944 hiov[
i].iov_base =
new char [hiov[
i].iov_len];
1947 int result = readv(sim_fd, hiov.get(),
count);
1948 int local_errno = errno;
1950 for (
typename OS::size_t
i = 0;
i <
count; ++
i) {
1953 hiov[
i].iov_base, hiov[
i].iov_len);
1955 delete [] (
char *)hiov[
i].iov_base;
1958 return (result == -1) ? -local_errno : result;
1965 int tgt_fd,
VPtr<> tiov_base,
1966 typename OS::size_t
count)
1970 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[tgt_fd]);
1973 int sim_fd = hbfdp->getSimFD();
1976 auto hiov = std::make_unique<struct iovec[]>(
count);
1977 for (
typename OS::size_t
i = 0;
i <
count; ++
i) {
1978 typename OS::tgt_iovec tiov;
1980 prox.
readBlob(tiov_base +
i*
sizeof(
typename OS::tgt_iovec),
1981 &tiov,
sizeof(
typename OS::tgt_iovec));
1982 hiov[
i].iov_len =
gtoh(tiov.iov_len, OS::byteOrder);
1983 hiov[
i].iov_base =
new char [hiov[
i].iov_len];
1984 prox.
readBlob(
gtoh(tiov.iov_base, OS::byteOrder), hiov[
i].iov_base,
1988 int result = writev(sim_fd, hiov.get(),
count);
1990 for (
typename OS::size_t
i = 0;
i <
count; ++
i)
1991 delete [] (
char *)hiov[
i].iov_base;
1993 return (result == -1) ? -errno : result;
2000 VPtr<> start,
typename OS::size_t length,
int prot,
2001 int tgt_flags,
int tgt_fd,
typename OS::off_t
offset)
2004 Addr page_bytes =
p->pTable->pageSize();
2006 if (start & (page_bytes - 1) ||
2007 offset & (page_bytes - 1) ||
2008 (tgt_flags & OS::TGT_MAP_PRIVATE &&
2009 tgt_flags & OS::TGT_MAP_SHARED) ||
2010 (!(tgt_flags & OS::TGT_MAP_PRIVATE) &&
2011 !(tgt_flags & OS::TGT_MAP_SHARED)) ||
2016 if ((
prot & PROT_WRITE) && (tgt_flags & OS::TGT_MAP_SHARED)) {
2037 warn_once(
"mmap: writing to shared mmap region is currently "
2038 "unsupported. The write succeeds on the target, but it "
2039 "will not be propagated to the host or shared mappings");
2042 length =
roundUp(length, page_bytes);
2045 if (!(tgt_flags & OS::TGT_MAP_ANONYMOUS)) {
2046 std::shared_ptr<FDEntry> fdep = (*
p->fds)[tgt_fd];
2048 auto dfdp = std::dynamic_pointer_cast<DeviceFDEntry>(fdep);
2051 return emul_driver->
mmap(tc, start, length,
prot, tgt_flags,
2055 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
2058 sim_fd = ffdp->getSimFD();
2069 std::shared_ptr<FDEntry> fdep = (*
p->fds)[tgt_fd];
2070 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
2072 ffdp->getFileName()));
2074 ffdp->getFileName());
2077 Addr offset = lib->buildImage().minAddr() + start;
2086 if (!(tgt_flags & OS::TGT_MAP_FIXED)) {
2094 if (!(start &&
p->memState->isUnmapped(start, length))) {
2098 start =
p->memState->extendMmap(length);
2103 start, start + length - 1);
2110 if (tgt_flags & OS::TGT_MAP_FIXED) {
2115 p->memState->unmapRegion(start, length);
2121 std::string region_name;
2122 if (tgt_flags & OS::TGT_MAP_ANONYMOUS) {
2123 region_name =
"anon";
2125 std::shared_ptr<FDEntry> fdep = (*
p->fds)[tgt_fd];
2126 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
2127 region_name = ffdp->getFileName();
2134 p->memState->mapRegion(start, length, region_name, sim_fd,
offset);
2142 int tgt_fd,
VPtr<> bufPtr,
typename OS::size_t nbytes,
2143 typename OS::off_t
offset)
2147 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
2150 int sim_fd = ffdp->getSimFD();
2158 return (bytes_read == -1) ? -errno : bytes_read;
2164 int tgt_fd,
VPtr<> bufPtr,
typename OS::size_t nbytes,
2165 typename OS::off_t
offset)
2169 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
2172 int sim_fd = ffdp->getSimFD();
2177 int bytes_written = pwrite(sim_fd, bufArg.
bufferPtr(), nbytes,
offset);
2179 return (bytes_written == -1) ? -errno : bytes_written;
2186 VPtr<> start,
typename OS::size_t length,
int prot,
2187 int tgt_flags,
int tgt_fd,
typename OS::off_t
offset)
2191 tgt_fd,
offset * page_size);
2200 const ByteOrder
bo = OS::byteOrder;
2202 case OS::TGT_RLIMIT_STACK:
2204 rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
2205 rlp->rlim_cur =
htog(rlp->rlim_cur,
bo);
2206 rlp->rlim_max =
htog(rlp->rlim_max,
bo);
2209 case OS::TGT_RLIMIT_DATA:
2211 rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024;
2212 rlp->rlim_cur =
htog(rlp->rlim_cur,
bo);
2213 rlp->rlim_max =
htog(rlp->rlim_max,
bo);
2216 case OS::TGT_RLIMIT_NPROC:
2218 rlp->rlim_cur =
htog(rlp->rlim_cur,
bo);
2219 rlp->rlim_max =
htog(rlp->rlim_max,
bo);
2223 warn(
"getrlimit: unimplemented resource %d", resource);
2237 warn(
"prlimit: ignoring rlimits for nonzero pid");
2241 warn(
"prlimit: ignoring new rlimit");
2243 const ByteOrder
bo = OS::byteOrder;
2245 case OS::TGT_RLIMIT_STACK:
2247 rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
2248 rlp->rlim_cur =
htog(rlp->rlim_cur,
bo);
2249 rlp->rlim_max =
htog(rlp->rlim_max,
bo);
2251 case OS::TGT_RLIMIT_DATA:
2253 rlp->rlim_cur = rlp->rlim_max = 256*1024*1024;
2254 rlp->rlim_cur =
htog(rlp->rlim_cur,
bo);
2255 rlp->rlim_max =
htog(rlp->rlim_max,
bo);
2258 warn(
"prlimit: unimplemented resource %d", resource);
2274 tp->tv_sec =
htog(tp->tv_sec, OS::byteOrder);
2275 tp->tv_nsec =
htog(tp->tv_nsec, OS::byteOrder);
2301 tp->tv_sec =
htog(tp->tv_sec, OS::byteOrder);
2302 tp->tv_usec =
htog(tp->tv_usec, OS::byteOrder);
2311 int dirfd,
VPtr<> pathname,
VPtr<
typename OS::timeval [2]> tp)
2322 struct timeval hostTimeval[2];
2323 for (
int i = 0;
i < 2; ++
i) {
2324 hostTimeval[
i].tv_sec =
gtoh((*tp)[
i].tv_sec, OS::byteOrder);
2325 hostTimeval[
i].tv_usec =
gtoh((*tp)[
i].tv_usec, OS::byteOrder);
2332 int result = utimes(path.c_str(), hostTimeval);
2344 VPtr<
typename OS::timeval [2]> tp)
2361 if (access(path.c_str(), F_OK) == -1)
2367 for (
int inc = 0; ; inc++) {
2369 b.copyIn(mem_proxy);
2371 if (!*(
Addr*)
b.bufferPtr())
2374 vect.push_back(std::string());
2383 if (!
p->vforkContexts.empty()) {
2395 ProcessParams *pp =
new ProcessParams();
2396 pp->executable = path;
2397 read_in(pp->cmd, mem_proxy, argv_mem_loc);
2398 read_in(pp->env, mem_proxy, envp_mem_loc);
2400 pp->egid =
p->egid();
2401 pp->euid =
p->euid();
2403 pp->ppid =
p->ppid();
2405 pp->input.assign(
"cin");
2406 pp->output.assign(
"cout");
2407 pp->errout.assign(
"cerr");
2408 pp->cwd.assign(
p->tgtCwd);
2409 pp->system =
p->system;
2410 pp->release =
p->release;
2411 pp->maxStackSize =
p->memState->getMaxStackSize();
2420 p->system->PIDs.erase(
p->pid());
2421 Process *new_p = pp->create();
2430 new_p->
fds =
p->fds;
2431 for (
int i = 0;
i < new_p->
fds->getSize();
i++) {
2432 std::shared_ptr<FDEntry> fdep = (*new_p->
fds)[
i];
2433 if (fdep && fdep->getCOE())
2434 new_p->
fds->closeFDEntry(
i);
2456 rup->ru_utime.tv_sec = 0;
2457 rup->ru_utime.tv_usec = 0;
2458 rup->ru_stime.tv_sec = 0;
2459 rup->ru_stime.tv_usec = 0;
2467 rup->ru_inblock = 0;
2468 rup->ru_oublock = 0;
2471 rup->ru_nsignals = 0;
2476 case OS::TGT_RUSAGE_SELF:
2478 rup->ru_utime.tv_sec =
htog(rup->ru_utime.tv_sec, OS::byteOrder);
2479 rup->ru_utime.tv_usec =
htog(rup->ru_utime.tv_usec, OS::byteOrder);
2482 case OS::TGT_RUSAGE_CHILDREN:
2489 warn(
"getrusage() only supports RUSAGE_SELF. Parameter %d ignored.",
2503 bufp->tms_utime = clocks;
2504 bufp->tms_stime = 0;
2505 bufp->tms_cutime = 0;
2506 bufp->tms_cstime = 0;
2509 bufp->tms_utime =
htog(bufp->tms_utime, OS::byteOrder);
2520 typename OS::time_t sec, usec;
2526 typename OS::time_t
t = sec;
2527 t =
htog(
t, OS::byteOrder);
2528 p.writeBlob(taddr, &
t, (
int)
sizeof(
typename OS::time_t));
2554 for (
auto *tc: sys->
threads) {
2556 if (temp->
pid() == tid) {
2562 if (sig != 0 && sig != OS::TGT_SIGABRT)
2565 if (tgt_proc ==
nullptr)
2568 if (tgid != -1 && tgt_proc->
tgid() != tgid)
2571 if (sig == OS::TGT_SIGABRT)
2588 auto sfdp = std::make_shared<SocketFDEntry>(sim_fd,
domain, type,
prot);
2589 int tgt_fd =
p->fds->allocFD(sfdp);
2608 auto sfdp1 = std::make_shared<SocketFDEntry>(fds[0],
domain, type,
prot);
2609 fds[0] =
p->fds->allocFD(sfdp1);
2610 auto sfdp2 = std::make_shared<SocketFDEntry>(fds[1],
domain, type,
prot);
2611 fds[1] =
p->fds->allocFD(sfdp2);
2635 FD_ZERO(&readfds_h);
2637 FD_ZERO(&writefds_h);
2639 FD_ZERO(&errorfds_h);
2651 std::map<int, int> trans_map;
2652 auto try_add_host_set = [&](
typename OS::fd_set *tgt_set_entry,
2653 fd_set *hst_set_entry,
2661 if (FD_ISSET(iter, (fd_set *)tgt_set_entry)) {
2667 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[iter]);
2670 auto sim_fd = hbfdp->getSimFD();
2677 trans_map[sim_fd] = iter;
2684 nfds_h = std::max(nfds_h - 1, sim_fd + 1);
2690 FD_SET(sim_fd, hst_set_entry);
2695 for (
int i = 0;
i < nfds;
i++) {
2697 bool ebadf = try_add_host_set(readfds, &readfds_h,
i);
2702 bool ebadf = try_add_host_set(writefds, &writefds_h,
i);
2707 bool ebadf = try_add_host_set(errorfds, &errorfds_h,
i);
2721 timeout->tv_sec = 0;
2722 timeout->tv_usec = 0;
2724 retval = select(nfds_h,
2725 readfds ? &readfds_h :
nullptr,
2726 writefds ? &writefds_h :
nullptr,
2727 errorfds ? &errorfds_h :
nullptr,
2728 (timeval *)(
typename OS::timeval *)timeout);
2737 struct timeval tv = { 0, 0 };
2739 retval = select(nfds_h,
2740 readfds ? &readfds_h :
nullptr,
2741 readfds ? &writefds_h :
nullptr,
2742 readfds ? &errorfds_h :
nullptr,
2752 if (sig.receiver ==
p)
2762 FD_ZERO(
reinterpret_cast<fd_set *
>((
typename OS::fd_set *)readfds));
2765 FD_ZERO(
reinterpret_cast<fd_set *
>((
typename OS::fd_set *)writefds));
2768 FD_ZERO(
reinterpret_cast<fd_set *
>((
typename OS::fd_set *)errorfds));
2776 for (
int i = 0;
i < nfds_h;
i++) {
2777 if (readfds && FD_ISSET(
i, &readfds_h))
2778 FD_SET(trans_map[
i],
2779 reinterpret_cast<fd_set *
>(
2780 (
typename OS::fd_set *)readfds));
2782 if (writefds && FD_ISSET(
i, &writefds_h))
2783 FD_SET(trans_map[
i],
2784 reinterpret_cast<fd_set *
>(
2785 (
typename OS::fd_set *)writefds));
2787 if (errorfds && FD_ISSET(
i, &errorfds_h))
2788 FD_SET(trans_map[
i],
2789 reinterpret_cast<fd_set *
>(
2790 (
typename OS::fd_set *)errorfds));
2799 int tgt_fd,
VPtr<> buf_ptr,
typename OS::size_t nbytes)
2803 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[tgt_fd]);
2806 int sim_fd = hbfdp->getSimFD();
2810 pfd.events = POLLIN | POLLPRI;
2811 if ((poll(&pfd, 1, 0) == 0)
2812 && !(hbfdp->getFlags() & OS::TGT_O_NONBLOCK))
2816 int bytes_read = read(sim_fd, buf_arg.
bufferPtr(), nbytes);
2821 return (bytes_read == -1) ? -errno : bytes_read;
2827 int tgt_fd,
VPtr<> buf_ptr,
typename OS::size_t nbytes)
2831 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[tgt_fd]);
2834 int sim_fd = hbfdp->getSimFD();
2841 pfd.events = POLLOUT;
2849 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(hbfdp);
2850 if (ffdp && (ffdp->getFileName() !=
"/dev/random")) {
2851 if (!poll(&pfd, 1, 0) && !(ffdp->getFlags() & OS::TGT_O_NONBLOCK))
2855 int bytes_written = write(sim_fd, buf_arg.
bufferPtr(), nbytes);
2857 if (bytes_written != -1)
2860 return (bytes_written == -1) ? -errno : bytes_written;
2866 pid_t pid,
VPtr<> statPtr,
int options,
VPtr<> rusagePtr)
2871 DPRINTF_SYSCALL(Verbose,
"wait4: rusage pointer provided %lx, however "
2872 "functionality not supported. Ignoring rusage pointer.\n",
2886 if (iter->receiver ==
p) {
2888 if ((iter->sender->pgid() == -pid)
2889 && (iter->signalValue == OS::TGT_SIGCHLD))
2891 }
else if (pid == -1) {
2892 if (iter->signalValue == OS::TGT_SIGCHLD)
2894 }
else if (pid == 0) {
2895 if ((iter->sender->pgid() ==
p->pgid())
2896 && (iter->signalValue == OS::TGT_SIGCHLD))
2899 if ((iter->sender->pid() == pid)
2900 && (iter->signalValue == OS::TGT_SIGCHLD))
2910 const int EXITED = 0;
2911 BufferArg statusBuf(statPtr,
sizeof(
int));
2916 pid_t retval = iter->sender->pid();
2934 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
2937 int sim_fd = sfdp->getSimFD();
2947 pfd.events = POLLIN | POLLPRI;
2948 if ((poll(&pfd, 1, 0) == 0) && !(sfdp->getFlags() & OS::TGT_O_NONBLOCK))
2952 lenBufPtr =
new BufferArg(lenPtr,
sizeof(socklen_t));
2954 memcpy(&addrLen, (socklen_t *)lenBufPtr->
bufferPtr(),
2959 addrBufPtr =
new BufferArg(addrPtr,
sizeof(
struct sockaddr));
2961 memcpy(&
sa, (
struct sockaddr *)addrBufPtr->
bufferPtr(),
2962 sizeof(
struct sockaddr));
2965 host_fd = accept(sim_fd, &
sa, &addrLen);
2977 *(socklen_t *)lenBufPtr->
bufferPtr() = addrLen;
2982 auto afdp = std::make_shared<SocketFDEntry>(host_fd, sfdp->_domain,
2983 sfdp->_type, sfdp->_protocol);
2984 return p->fds->allocFD(afdp);
2991 unsigned initval,
int in_flags)
2993#if defined(__linux__)
2996 int sim_fd = eventfd(initval, in_flags);
3000 bool cloexec = in_flags & OS::TGT_O_CLOEXEC;
3002 int flags = cloexec ? OS::TGT_O_CLOEXEC : 0;
3003 flags |= (in_flags & OS::TGT_O_NONBLOCK) ? OS::TGT_O_NONBLOCK : 0;
3005 auto hbfdp = std::make_shared<HBFDEntry>(flags, sim_fd, cloexec);
3006 int tgt_fd =
p->fds->allocFD(hbfdp);
3018 pid_t pid,
typename OS::size_t cpusetsize,
3021#if defined(__linux__)
3026 BufferArg maskBuf(cpu_set_mask, cpusetsize);
3029 CPU_SET(
i, (cpu_set_t *)maskBuf.
bufferPtr());
3043 int tgt_fd,
VPtr<> buf_ptr,
typename OS::size_t buf_len,
3048 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
3051 int sim_fd = sfdp->getSimFD();
3059 socklen_t addr_len = 0;
3060 if (addrlen_ptr != 0) {
3062 BufferArg addrlen_buf(addrlen_ptr,
sizeof(socklen_t));
3063 addrlen_buf.
copyIn(proxy);
3064 addr_len = *((socklen_t *)addrlen_buf.
bufferPtr());
3067 struct sockaddr
sa, *sap = NULL;
3068 if (addr_len != 0) {
3071 memcpy(&
sa, (
struct sockaddr *)addr_buf.
bufferPtr(),
3072 sizeof(
struct sockaddr));
3076 ssize_t recvd_size = recvfrom(sim_fd,
3078 buf_len, flags, sap, (socklen_t *)&addr_len);
3080 if (recvd_size == -1)
3094 if (addr_len != 0) {
3095 BufferArg addrlen_buf(addrlen_ptr,
sizeof(socklen_t));
3096 *(socklen_t *)addrlen_buf.
bufferPtr() = addr_len;
3104template <
typename OS>
3107 int tgt_fd,
VPtr<> buf_ptr,
typename OS::size_t buf_len,
int flags,
3108 VPtr<> addr_ptr, socklen_t addr_len)
3112 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
3115 int sim_fd = sfdp->getSimFD();
3121 struct sockaddr
sa, *sap =
nullptr;
3122 memset(&
sa, 0,
sizeof(sockaddr));
3123 if (addr_len != 0) {
3126 memcpy(&
sa, (sockaddr*)addr_buf.
bufferPtr(), addr_len);
3130 ssize_t sent_size = sendto(sim_fd,
3132 buf_len, flags, sap, (socklen_t)addr_len);
3134 return (sent_size == -1) ? -errno : sent_size;
3138template <
typename OS>
3141 typename OS::size_t length)
3149 if (
p->pTable->pageOffset(start))
3152 length =
roundUp(length,
p->pTable->pageSize());
3154 p->memState->unmapRegion(start, length);
3160template <
typename OS>
3163 int tgt_fd,
int mode,
typename OS::off_t
offset,
3164 typename OS::off_t
len)
3166#if defined(__linux__)
3169 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
3172 int sim_fd = ffdp->getSimFD();
3185template <
typename OS>
3188 typename OS::off_t length)
3197 path =
p->checkPathRedirect(path);
3199 int result = truncate(path.c_str(), length);
3200 return (result == -1) ? -errno : result;
3204template <
typename OS>
3207 typename OS::off_t length)
3211 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
3214 int sim_fd = ffdp->getSimFD();
3216 int result = ftruncate(sim_fd, length);
3217 return (result == -1) ? -errno : result;
3220template <
typename OS>
3231 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
static RandomPtr genRandom(Random *r=nullptr)
std::shared_ptr< Random > RandomPtr
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...
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)
ProxyPtr< T, SETranslatingPortProxy > VPtr
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 sched_getparamFunc(SyscallDesc *desc, ThreadContext *tc, int pid, VPtr< int > paramPtr)
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.