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"
114#if defined(__APPLE__) && defined(__MACH__) && !defined(CMSG_ALIGN)
115#define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
116#elif defined(__FreeBSD__) && !defined(CMSG_ALIGN)
117#define CMSG_ALIGN(n) _ALIGN(n)
140SyscallReturn
ignoreFunc(SyscallDesc *desc, ThreadContext *tc);
150SyscallReturn
exitFunc(SyscallDesc *desc, ThreadContext *tc,
int status);
163SyscallReturn
brkFunc(SyscallDesc *desc, ThreadContext *tc,
VPtr<> new_brk);
166SyscallReturn
closeFunc(SyscallDesc *desc, ThreadContext *tc,
int tgt_fd);
169SyscallReturn
_llseekFunc(SyscallDesc *desc, ThreadContext *tc,
170 int tgt_fd, uint32_t offset_high,
171 uint32_t offset_low,
VPtr<> result_ptr,
int whence);
174SyscallReturn
shutdownFunc(SyscallDesc *desc, ThreadContext *tc,
175 int tgt_fd,
int how);
179 VPtr<> buf_ptr,
int name_len);
182SyscallReturn
unlinkFunc(SyscallDesc *desc, ThreadContext *tc,
184SyscallReturn
unlinkImpl(SyscallDesc *desc, ThreadContext *tc,
188SyscallReturn
linkFunc(SyscallDesc *desc, ThreadContext *tc,
192SyscallReturn
symlinkFunc(SyscallDesc *desc, ThreadContext *tc,
196SyscallReturn
mkdirFunc(SyscallDesc *desc, ThreadContext *tc,
198SyscallReturn
mkdirImpl(SyscallDesc *desc, ThreadContext *tc,
199 std::string path, mode_t
mode);
202SyscallReturn
mknodFunc(SyscallDesc *desc, ThreadContext *tc,
204SyscallReturn
mknodImpl(SyscallDesc *desc, ThreadContext *tc,
205 std::string path, mode_t
mode, dev_t dev);
208SyscallReturn
chdirFunc(SyscallDesc *desc, ThreadContext *tc,
VPtr<> pathname);
211SyscallReturn
rmdirFunc(SyscallDesc *desc, ThreadContext *tc,
213SyscallReturn
rmdirImpl(SyscallDesc *desc, ThreadContext *tc,
217SyscallReturn
renameFunc(SyscallDesc *desc, ThreadContext *tc,
219SyscallReturn
renameImpl(SyscallDesc *desc, ThreadContext *tc,
220 std::string oldpath, std::string newpath);
224 VPtr<> pathname, int64_t length);
228 int tgt_fd, int64_t length);
231SyscallReturn
umaskFunc(SyscallDesc *desc, ThreadContext *tc);
234SyscallReturn
gettidFunc(SyscallDesc *desc, ThreadContext *tc);
237SyscallReturn
chownFunc(SyscallDesc *desc, ThreadContext *tc,
238 VPtr<> pathname, uint32_t owner, uint32_t group);
239SyscallReturn
chownImpl(SyscallDesc *desc, ThreadContext *tc,
240 std::string path, uint32_t owner, uint32_t group);
243SyscallReturn
getpgrpFunc(SyscallDesc *desc, ThreadContext *tc);
246SyscallReturn
setpgidFunc(SyscallDesc *desc, ThreadContext *tc,
250SyscallReturn
fchownFunc(SyscallDesc *desc, ThreadContext *tc,
251 int tgt_fd, uint32_t owner, uint32_t group);
254SyscallReturn
dupFunc(SyscallDesc *desc, ThreadContext *tc,
258SyscallReturn
dup2Func(SyscallDesc *desc, ThreadContext *tc,
259 int old_tgt_fd,
int new_tgt_fd);
262SyscallReturn
fcntlFunc(SyscallDesc *desc, ThreadContext *tc,
263 int tgt_fd,
int cmd, guest_abi::VarArgs<int> varargs);
266SyscallReturn
fcntl64Func(SyscallDesc *desc, ThreadContext *tc,
267 int tgt_fd,
int cmd);
270SyscallReturn
pipeFunc(SyscallDesc *desc, ThreadContext *tc,
VPtr<> tgt_addr);
273SyscallReturn
pipe2Func(SyscallDesc *desc, ThreadContext *tc,
274 VPtr<> tgt_addr,
int flags);
277SyscallReturn
getpidFunc(SyscallDesc *desc, ThreadContext *tc);
281 int tgt_fd,
VPtr<> sockAddrPtr,
285SyscallReturn
bindFunc(SyscallDesc *desc, ThreadContext *tc,
286 int tgt_fd,
VPtr<> buf_ptr,
int addrlen);
289SyscallReturn
listenFunc(SyscallDesc *desc, ThreadContext *tc,
290 int tgt_fd,
int backlog);
293SyscallReturn
connectFunc(SyscallDesc *desc, ThreadContext *tc,
294 int tgt_fd,
VPtr<> buf_ptr,
int addrlen);
296#if defined(SYS_getdents)
298SyscallReturn getdentsFunc(SyscallDesc *desc, ThreadContext *tc,
302#if defined(SYS_getdents64)
304SyscallReturn getdents64Func(SyscallDesc *desc, ThreadContext *tc,
309SyscallReturn
recvmsgFunc(SyscallDesc *desc, ThreadContext *tc,
310 int tgt_fd,
VPtr<> msgPtr,
int flags);
313SyscallReturn
sendmsgFunc(SyscallDesc *desc, ThreadContext *tc,
314 int tgt_fd,
VPtr<> msgPtr,
int flags);
317SyscallReturn
getuidFunc(SyscallDesc *desc, ThreadContext *tc);
320SyscallReturn
getgidFunc(SyscallDesc *desc, ThreadContext *tc);
323SyscallReturn
getppidFunc(SyscallDesc *desc, ThreadContext *tc);
326SyscallReturn
geteuidFunc(SyscallDesc *desc, ThreadContext *tc);
329SyscallReturn
getegidFunc(SyscallDesc *desc, ThreadContext *tc);
332SyscallReturn
accessFunc(SyscallDesc *desc, ThreadContext *tc,
334SyscallReturn
accessImpl(SyscallDesc *desc, ThreadContext *tc,
335 std::string path, mode_t
mode);
339 int tgt_fd,
int level,
int optname,
344 int tgt_fd,
int level,
int optname,
347SyscallReturn
getcpuFunc(SyscallDesc *desc, ThreadContext *tc,
364 if (dirfd != OS::TGT_AT_FDCWD && !
startswith(path,
"/")) {
367 std::shared_ptr<FDEntry> fdep = ((*process->fds)[dirfd]);
368 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
373 path = ffdp->getFileName();
375 path = ffdp->getFileName() +
"/" + path;
395 op &= ~OS::TGT_FUTEX_PRIVATE_FLAG;
396 op &= ~OS::TGT_FUTEX_CLOCK_REALTIME_FLAG;
400 if (OS::TGT_FUTEX_WAIT ==
op || OS::TGT_FUTEX_WAIT_BITSET ==
op) {
412 return -OS::TGT_EWOULDBLOCK;
414 if (OS::TGT_FUTEX_WAIT ==
op) {
415 futex_map.
suspend(uaddr, process->tgid(), tc);
421 }
else if (OS::TGT_FUTEX_WAKE ==
op) {
422 return futex_map.
wakeup(uaddr, process->tgid(),
val);
423 }
else if (OS::TGT_FUTEX_WAKE_BITSET ==
op) {
424 return futex_map.
wakeup_bitset(uaddr, process->tgid(), val3);
425 }
else if (OS::TGT_FUTEX_REQUEUE ==
op ||
426 OS::TGT_FUTEX_CMP_REQUEUE ==
op) {
436 if (OS::TGT_FUTEX_CMP_REQUEUE && val3 != mem_val)
437 return -OS::TGT_EWOULDBLOCK;
438 return futex_map.
requeue(uaddr, process->tgid(),
val, timeout, uaddr2);
439 }
else if (OS::TGT_FUTEX_WAKE_OP ==
op) {
467 int wake_cmparg = val3 & 0xfff;
468 int wake_oparg = (val3 & 0xfff000) >> 12;
469 int wake_cmp = (val3 & 0xf000000) >> 24;
470 int wake_op = (val3 & 0xf0000000) >> 28;
471 if ((wake_op & OS::TGT_FUTEX_OP_ARG_SHIFT) >> 3 == 1)
472 wake_oparg = (1 << wake_oparg);
473 wake_op &= ~OS::TGT_FUTEX_OP_ARG_SHIFT;
475 if (wake_op == OS::TGT_FUTEX_OP_SET)
477 else if (wake_op == OS::TGT_FUTEX_OP_ADD)
478 newval += wake_oparg;
479 else if (wake_op == OS::TGT_FUTEX_OP_OR)
480 newval |= wake_oparg;
481 else if (wake_op == OS::TGT_FUTEX_OP_ANDN)
482 newval &= ~wake_oparg;
483 else if (wake_op == OS::TGT_FUTEX_OP_XOR)
484 newval ^= wake_oparg;
489 int woken1 = futex_map.
wakeup(uaddr, process->tgid(),
val);
492 bool is_wake2 =
false;
493 if (wake_cmp == OS::TGT_FUTEX_OP_CMP_EQ)
494 is_wake2 = oldval == wake_cmparg;
495 else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_NE)
496 is_wake2 = oldval != wake_cmparg;
497 else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_LT)
498 is_wake2 = oldval < wake_cmparg;
499 else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_LE)
500 is_wake2 = oldval <= wake_cmparg;
501 else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_GT)
502 is_wake2 = oldval > wake_cmparg;
503 else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_GE)
504 is_wake2 = oldval >= wake_cmparg;
507 woken2 = futex_map.
wakeup(uaddr2, process->tgid(), timeout);
509 return woken1 + woken2;
511 warn(
"futex: op %d not implemented; ignoring.",
op);
517SyscallReturn
pipePseudoFunc(SyscallDesc *desc, ThreadContext *tc);
527template <
class T1,
class T2>
531 static const int OneMillion = 1000 * 1000;
534 sec = elapsed_usecs / OneMillion;
535 usec = elapsed_usecs % OneMillion;
540template <
class T1,
class T2>
544 static const int OneBillion = 1000 * 1000 * 1000;
547 sec = elapsed_nsecs / OneBillion;
548 nsec = elapsed_nsecs % OneBillion;
571template <
typename OS,
typename TgtStatPtr,
typename HostStatPtr>
575 constexpr ByteOrder
bo = OS::byteOrder;
580 tgt->st_dev = host->st_dev;
581 tgt->st_dev =
htog(tgt->st_dev,
bo);
582 tgt->st_ino = host->st_ino;
583 tgt->st_ino =
htog(tgt->st_ino,
bo);
584 tgt->st_mode = host->st_mode;
587 tgt->st_mode &= ~S_IFMT;
588 tgt->st_mode |= S_IFCHR;
590 tgt->st_mode =
htog(tgt->st_mode,
bo);
591 tgt->st_nlink = host->st_nlink;
592 tgt->st_nlink =
htog(tgt->st_nlink,
bo);
593 tgt->st_uid = host->st_uid;
594 tgt->st_uid =
htog(tgt->st_uid,
bo);
595 tgt->st_gid = host->st_gid;
596 tgt->st_gid =
htog(tgt->st_gid,
bo);
598 tgt->st_rdev = 0x880d;
600 tgt->st_rdev = host->st_rdev;
601 tgt->st_rdev =
htog(tgt->st_rdev,
bo);
602 tgt->st_size = host->st_size;
603 tgt->st_size =
htog(tgt->st_size,
bo);
604 tgt->st_atimeX = host->st_atime;
605 tgt->st_atimeX =
htog(tgt->st_atimeX,
bo);
606 tgt->st_mtimeX = host->st_mtime;
607 tgt->st_mtimeX =
htog(tgt->st_mtimeX,
bo);
608 tgt->st_ctimeX = host->st_ctime;
609 tgt->st_ctimeX =
htog(tgt->st_ctimeX,
bo);
612 tgt->st_blksize = 0x2000;
613 tgt->st_blksize =
htog(tgt->st_blksize,
bo);
614 tgt->st_blocks = host->st_blocks;
615 tgt->st_blocks =
htog(tgt->st_blocks,
bo);
620template <
typename OS,
typename TgtStatPtr,
typename HostStatPtr>
626#if defined(STAT_HAVE_NSEC)
627 constexpr ByteOrder
bo = OS::byteOrder;
629 tgt->st_atime_nsec = host->st_atime_nsec;
630 tgt->st_atime_nsec =
htog(tgt->st_atime_nsec,
bo);
631 tgt->st_mtime_nsec = host->st_mtime_nsec;
632 tgt->st_mtime_nsec =
htog(tgt->st_mtime_nsec,
bo);
633 tgt->st_ctime_nsec = host->st_ctime_nsec;
634 tgt->st_ctime_nsec =
htog(tgt->st_ctime_nsec,
bo);
636 tgt->st_atime_nsec = 0;
637 tgt->st_mtime_nsec = 0;
638 tgt->st_ctime_nsec = 0;
642template <
class OS,
typename TgtStatPtr,
typename HostStatPtr>
646 constexpr ByteOrder
bo = OS::byteOrder;
648 tgt->f_type =
htog(host->f_type,
bo);
649#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
650 tgt->f_bsize =
htog(host->f_iosize,
bo);
652 tgt->f_bsize =
htog(host->f_bsize,
bo);
654 tgt->f_blocks =
htog(host->f_blocks,
bo);
655 tgt->f_bfree =
htog(host->f_bfree,
bo);
656 tgt->f_bavail =
htog(host->f_bavail,
bo);
657 tgt->f_files =
htog(host->f_files,
bo);
658 tgt->f_ffree =
htog(host->f_ffree,
bo);
659 memcpy(&tgt->f_fsid, &host->f_fsid,
sizeof(host->f_fsid));
660#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
661 tgt->f_namelen =
htog(host->f_namemax,
bo);
662 tgt->f_frsize =
htog(host->f_bsize,
bo);
663#elif defined(__APPLE__)
667 tgt->f_namelen =
htog(host->f_namelen,
bo);
668 tgt->f_frsize =
htog(host->f_frsize,
bo);
670#if defined(__linux__)
671 memcpy(&tgt->f_spare, &host->f_spare,
672 std::min(
sizeof(host->f_spare),
sizeof(tgt->f_spare)));
678 memset(&tgt->f_spare, 0,
sizeof(tgt->f_spare));
682template <
typename OS,
typename TgtStatPtr,
typename HostStatPtr>
686 constexpr ByteOrder
bo = OS::byteOrder;
689 tgt->stx_dev_major = 0x00;
690 tgt->stx_dev_minor = 0x0A;
692 tgt->stx_dev_major = host->st_dev >> 8;
693 tgt->stx_dev_minor = host->st_dev & 0xFF;
695 tgt->stx_dev_major =
htog(tgt->stx_dev_major,
bo);
696 tgt->stx_dev_minor =
htog(tgt->stx_dev_minor,
bo);
697 tgt->stx_ino = host->st_ino;
698 tgt->stx_ino =
htog(tgt->stx_ino,
bo);
699 tgt->stx_mode = host->st_mode;
702 tgt->stx_mode &= ~S_IFMT;
703 tgt->stx_mode |= S_IFCHR;
705 tgt->stx_mode =
htog(tgt->stx_mode,
bo);
706 tgt->stx_nlink = host->st_nlink;
707 tgt->stx_nlink =
htog(tgt->stx_nlink,
bo);
708 tgt->stx_uid = host->st_uid;
709 tgt->stx_uid =
htog(tgt->stx_uid,
bo);
710 tgt->stx_gid = host->st_gid;
711 tgt->stx_gid =
htog(tgt->stx_gid,
bo);
713 tgt->stx_rdev_major = 0x880d >> 8;
714 tgt->stx_rdev_minor = 0x880d & 0xFF;
716 tgt->stx_rdev_major = host->st_rdev >> 8;
717 tgt->stx_rdev_minor = host->st_rdev & 0xFF;
719 tgt->stx_rdev_major =
htog(tgt->stx_rdev_major,
bo);
720 tgt->stx_rdev_minor =
htog(tgt->stx_rdev_minor,
bo);
721 tgt->stx_size = host->st_size;
722 tgt->stx_size =
htog(tgt->stx_size,
bo);
723 tgt->stx_atimeX = host->st_atime;
724 tgt->stx_atimeX =
htog(tgt->stx_atimeX,
bo);
725 tgt->stx_ctimeX = host->st_ctime;
726 tgt->stx_ctimeX =
htog(tgt->stx_ctimeX,
bo);
727 tgt->stx_mtimeX = host->st_mtime;
728 tgt->stx_mtimeX =
htog(tgt->stx_mtimeX,
bo);
731 tgt->stx_blksize = 0x2000;
732 tgt->stx_blksize =
htog(tgt->stx_blksize,
bo);
733 tgt->stx_blocks = host->st_blocks;
734 tgt->stx_blocks =
htog(tgt->stx_blocks,
bo);
735 tgt->stx_mask = 0x000007ffU;
736 tgt->stx_mask =
htog(tgt->stx_mask,
bo);
737 tgt->stx_attributes = 0;
738 tgt->stx_attributes_mask = 0;
739 tgt->stx_attributes_mask =
htog(tgt->stx_attributes_mask,
bo);
755 if (OS::isTtyReq(req))
758 auto dfdp = std::dynamic_pointer_cast<DeviceFDEntry>((*
p->fds)[tgt_fd]);
762 return emul_driver->
ioctl(tc, req,
addr);
765 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
774 ifconf *conf = (ifconf*)conf_arg.
bufferPtr();
775 Addr ifc_buf_addr = (
Addr)conf->ifc_buf;
776 BufferArg ifc_buf_arg(ifc_buf_addr, conf->ifc_len);
779 conf->ifc_buf = (
char*)ifc_buf_arg.
bufferPtr();
783 conf->ifc_buf = (
char*)ifc_buf_addr;
791#if defined(__linux__)
796#if defined(__linux__)
815 warn(
"Unsupported ioctl call (return ENOTTY): ioctl(%d, 0x%x, ...) @ %s\n",
824 int tgt_dirfd,
VPtr<> pathname,
int tgt_flags,
int mode)
837 int host_flags = O_BINARY;
845 for (
const auto &
p: OS::openFlagTable) {
846 if (tgt_flags &
p.first) {
847 tgt_flags &=
~p.first;
848 host_flags |=
p.second;
851 warn_if(tgt_flags,
"%s: cannot decode flags %#x", desc->
name(), tgt_flags);
854 host_flags |= O_BINARY;
869 std::string redir_path = path;
870 std::string abs_path = path;
871 if (tgt_dirfd == OS::TGT_AT_FDCWD) {
872 abs_path =
p->absolutePath(path,
true);
873 redir_path =
p->checkPathRedirect(path);
875 std::shared_ptr<FDEntry> fdep = ((*
p->fds)[tgt_dirfd]);
876 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
879 abs_path = ffdp->getFileName() + path;
880 redir_path =
p->checkPathRedirect(abs_path);
890 std::string filename = abs_path.substr(strlen(
"/dev/"));
894 "driver open with path[%s]\n",
895 desc->
name(), abs_path.c_str());
896 return drv->
open(tc,
mode, host_flags);
929 std::string used_path;
931 {
"/proc/meminfo",
"/system/",
"/platform/",
"/etc/passwd",
932 "/proc/self/maps",
"/dev/urandom",
933 "/sys/devices/system/cpu/online" };
934 for (
auto entry : special_paths) {
936 sim_fd = OS::openSpecialFile(abs_path,
p, tc);
937 used_path = abs_path;
941 sim_fd = open(redir_path.c_str(), host_flags,
mode);
942 used_path = redir_path;
947 "(inferred from:%s)\n", desc->
name(),
948 used_path.c_str(), path.c_str());
960 auto ffdp = std::make_shared<FileFDEntry>(sim_fd, host_flags, path, 0);
962 ffdp->setFileMode(
mode);
963 int tgt_fd =
p->fds->allocFD(ffdp);
965 "(inferred from:%s)\n", desc->
name(),
966 sim_fd, tgt_fd, used_path.c_str(), path.c_str());
977 desc, tc, OS::TGT_AT_FDCWD, pathname, tgt_flags,
mode);
984 VPtr<> buf_ptr,
typename OS::size_t size)
991 std::string cwd =
p->tgtCwd;
993 if (cwd.length() >= size) {
997 strncpy((
char *)buf.
bufferPtr(), cwd.c_str(), size);
998 result = cwd.length();
1000 if (getcwd((
char *)buf.
bufferPtr(), size)) {
1001 result = strlen((
char *)buf.
bufferPtr());
1009 return (result == -1) ? -errno : result;
1016 int tgt_fd,
typename OS::off_t offs,
int whence)
1020 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
1023 int sim_fd = ffdp->getSimFD();
1025 off_t result = lseek(sim_fd, offs, whence);
1027 return (result == (off_t)-1) ? -errno : result;
1034 int dirfd,
VPtr<> pathname,
int flags)
1045 if (flags & OS::TGT_AT_REMOVEDIR) {
1075 typename OS::size_t bufsiz)
1089 path =
p->checkPathRedirect(path);
1094 if (path !=
"/proc/self/exe") {
1095 result = readlink(path.c_str(), (
char *)buf.
bufferPtr(), bufsiz);
1109 char real_path[PATH_MAX];
1110 char *check_real_path = realpath(
p->progName(), real_path);
1111 if (!check_real_path) {
1112 fatal(
"readlink('/proc/self/exe') unable to resolve path to "
1113 "executable: %s",
p->progName());
1115 strncpy((
char*)buf.
bufferPtr(), real_path, bufsiz);
1116 typename OS::size_t real_path_len = strlen(real_path);
1117 if (real_path_len > bufsiz) {
1122 result = real_path_len;
1126 warn_once(
"readlink() called on '/proc/self/exe' may yield unexpected "
1127 "results in various settings.\n Returning '%s'\n",
1133 return (result == -1) ? -errno : result;
1141 typename OS::size_t bufsiz)
1144 pathname, buf_ptr, bufsiz);
1151 int olddirfd,
VPtr<> oldpath,
int newdirfd,
VPtr<> newpath)
1154 std::string old_name;
1158 std::string new_name;
1172 return renameImpl(desc, tc, old_name, new_name);
1179 int dirfd,
VPtr<> pathname, uint32_t owner, uint32_t group,
1191 return chownImpl(desc, tc, path, owner, group);
1216 int dirfd,
VPtr<> pathname, mode_t
mode, dev_t dev)
1239 sysinfo->totalram = process->system->memSize();
1240 sysinfo->mem_unit = 1;
1260 mode_t hostMode = 0;
1270 int result = chmod(path.c_str(), hostMode);
1288 VPtr<> fdsPtr,
int nfds,
int tmout)
1292 BufferArg fdsBuf(fdsPtr,
sizeof(
struct pollfd) * nfds);
1301 auto temp_tgt_fds = std::make_unique<int[]>(nfds);
1304 int tgt_fd = temp_tgt_fds[
index];
1305 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[tgt_fd]);
1308 auto host_fd = hbfdp->getSimFD();
1330 if (it->receiver ==
p)
1345 int tgt_fd = temp_tgt_fds[
index];
1365 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
1368 int sim_fd = ffdp->getSimFD();
1370 mode_t hostMode =
mode;
1372 int result = fchmod(sim_fd, hostMode);
1374 return (result < 0) ? -errno : 0;
1381 VPtr<> start,
typename OS::size_t old_length,
1382 typename OS::size_t new_length,
int flags,
1386 Addr page_bytes =
p->pTable->pageSize();
1387 uint64_t provided_address = 0;
1388 bool use_provided_address = flags & OS::TGT_MREMAP_FIXED;
1390 if (use_provided_address)
1391 provided_address = varargs.
get<uint64_t>();
1393 if ((start % page_bytes != 0) ||
1394 (provided_address % page_bytes != 0)) {
1395 warn(
"mremap failing: arguments not page aligned");
1399 new_length =
roundUp(new_length, page_bytes);
1401 if (new_length > old_length) {
1402 Addr mmap_end =
p->memState->getMmapEnd();
1404 if ((start + old_length) == mmap_end &&
1405 (!use_provided_address || provided_address == start)) {
1408 uint64_t diff = new_length - old_length;
1409 p->memState->mapRegion(mmap_end, diff,
"remapped");
1410 p->memState->setMmapEnd(mmap_end + diff);
1413 if (!use_provided_address && !(flags & OS::TGT_MREMAP_MAYMOVE)) {
1414 warn(
"can't remap here and MREMAP_MAYMOVE flag not set\n");
1417 uint64_t new_start = provided_address;
1418 if (!use_provided_address) {
1419 new_start =
p->mmapGrowsDown() ?
1420 mmap_end - new_length : mmap_end;
1421 mmap_end =
p->mmapGrowsDown() ?
1422 new_start : mmap_end + new_length;
1423 p->memState->setMmapEnd(mmap_end);
1426 warn(
"mremapping to new vaddr %08p-%08p, adding %d\n",
1427 new_start, new_start + new_length,
1428 new_length - old_length);
1431 p->allocateMem(new_start + old_length,
1432 new_length - old_length,
1433 use_provided_address );
1435 if (use_provided_address &&
1436 ((new_start + new_length >
p->memState->getMmapEnd() &&
1437 !
p->mmapGrowsDown()) ||
1438 (new_start < p->memState->getMmapEnd() &&
1439 p->mmapGrowsDown()))) {
1442 warn(
"mmap region limit exceeded with MREMAP_FIXED\n");
1445 warn(
"returning %08p as start\n", new_start);
1446 p->memState->remapRegion(start, new_start, old_length);
1452 if (use_provided_address && provided_address != start)
1453 p->memState->remapRegion(start, provided_address, new_length);
1454 if (new_length != old_length)
1455 p->memState->unmapRegion(start + new_length,
1456 old_length - new_length);
1457 return use_provided_address ? provided_address : (
Addr)start;
1476 struct stat hostBuf;
1477 int result = stat(path.c_str(), &hostBuf);
1499 if (path.empty() && !(flags & OS::TGT_AT_EMPTY_PATH))
1501 flags = flags & ~OS::TGT_AT_EMPTY_PATH;
1503 warn_if(flags != 0,
"newfstatat: Flag bits %#x not supported.", flags);
1513 path =
p->checkPathRedirect(path);
1515 struct stat host_buf;
1516 int result = stat(path.c_str(), &host_buf);
1530 int dirfd,
VPtr<> pathname,
1545 path =
p->checkPathRedirect(path);
1548 struct stat hostBuf;
1549 int result = stat(path.c_str(), &hostBuf);
1551 struct stat64 hostBuf;
1552 int result = stat64(path.c_str(), &hostBuf);
1576 int dirfd,
VPtr<> pathname,
int flags,
1584 if (path.empty() && !(flags & OS::TGT_AT_EMPTY_PATH))
1586 flags = flags & ~OS::TGT_AT_EMPTY_PATH;
1588 warn_if(flags != 0,
"statx: Flag bits %#x not supported.", flags);
1598 path =
p->checkPathRedirect(path);
1600 struct stat host_buf;
1601 int result = stat(path.c_str(), &host_buf);
1619 auto ffdp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[tgt_fd]);
1622 int sim_fd = ffdp->getSimFD();
1625 struct stat hostBuf;
1626 int result = fstat(sim_fd, &hostBuf);
1628 struct stat64 hostBuf;
1629 int result = fstat64(sim_fd, &hostBuf);
1656 struct stat hostBuf;
1657 int result = lstat(path.c_str(), &hostBuf);
1683 struct stat hostBuf;
1684 int result = lstat(path.c_str(), &hostBuf);
1686 struct stat64 hostBuf;
1687 int result = lstat64(path.c_str(), &hostBuf);
1708 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
1711 int sim_fd = ffdp->getSimFD();
1713 struct stat hostBuf;
1714 int result = fstat(sim_fd, &hostBuf);
1730#if defined(__linux__)
1740 struct statfs hostBuf;
1741 int result = statfs(path.c_str(), &hostBuf);
1759 DPRINTF(SyscallVerbose,
"Doing clone. pid: %#llx, ctid: %#llx, tls: %#llx"
1760 " flags: %#llx, stack: %#llx\n",
1761 ptidPtr.
addr(), ctidPtr.
addr(), tlsPtr.
addr(), flags, newStack);
1764 if (((flags & OS::TGT_CLONE_SIGHAND)&& !(flags & OS::TGT_CLONE_VM)) ||
1765 ((flags & OS::TGT_CLONE_THREAD) && !(flags & OS::TGT_CLONE_SIGHAND)) ||
1766 ((flags & OS::TGT_CLONE_FS) && (flags & OS::TGT_CLONE_NEWNS)) ||
1767 ((flags & OS::TGT_CLONE_NEWIPC) && (flags & OS::TGT_CLONE_SYSVSEM)) ||
1768 ((flags & OS::TGT_CLONE_NEWPID) && (flags & OS::TGT_CLONE_THREAD)) ||
1769 ((flags & OS::TGT_CLONE_VM) && !(newStack)))
1785 ProcessParams *pp =
new ProcessParams();
1786 pp->executable.assign(*(
new std::string(
p->progName())));
1787 pp->cmd.push_back(*(
new std::string(
p->progName())));
1788 pp->system =
p->system;
1789 pp->cwd.assign(
p->tgtCwd);
1790 pp->input.assign(
"stdin");
1791 pp->output.assign(
"stdout");
1792 pp->errout.assign(
"stderr");
1794 pp->euid =
p->euid();
1796 pp->egid =
p->egid();
1797 pp->release =
p->release;
1800 std::set<int>
const& pids =
p->system->PIDs;
1801 int temp_pid = *pids.begin();
1804 }
while (pids.find(temp_pid) != pids.end());
1806 fatal(
"temp_pid is too large: %d", temp_pid);
1809 pp->ppid = (flags & OS::TGT_CLONE_THREAD) ?
p->ppid() :
p->pid();
1810 pp->useArchPT =
p->useArchPT;
1811 pp->kvmInSE =
p->kvmInSE;
1822 if (flags & OS::TGT_CLONE_PARENT_SETTID) {
1823 BufferArg ptidBuf(ptidPtr,
sizeof(
long));
1824 long *ptid = (
long *)ptidBuf.
bufferPtr();
1829 if (flags & OS::TGT_CLONE_THREAD) {
1830 cp->pTable->initState();
1831 cp->pTable->shared =
true;
1832 cp->useForClone =
true;
1837 p->clone(tc, ctc,
cp, flags);
1839 if (flags & OS::TGT_CLONE_THREAD) {
1841 cp->sigchld =
p->sigchld;
1842 }
else if (flags & OS::TGT_SIGCHLD) {
1843 *
cp->sigchld =
true;
1846 if (flags & OS::TGT_CLONE_CHILD_SETTID) {
1847 BufferArg ctidBuf(ctidPtr,
sizeof(
long));
1848 long *ctid = (
long *)ctidBuf.
bufferPtr();
1853 if (flags & OS::TGT_CLONE_CHILD_CLEARTID)
1854 cp->childClearTID = (uint64_t)ctidPtr;
1858 OS::archClone(flags,
p,
cp, tc, ctc, newStack, tlsPtr);
1864 if (flags & OS::TGT_CLONE_VFORK) {
1881 uint64_t new_stack = cl_args->stack + cl_args->stack_size;
1882 uint64_t flags = cl_args->flags;
1884 return doClone<OS>(desc, tc, flags, new_stack, ptidPtr, ctidPtr, tlsPtr);
1892 return doClone<OS>(desc, tc, flags, newStack, ptidPtr, ctidPtr, tlsPtr);
1901 return cloneFunc<OS>(desc, tc, flags, newStack, ptidPtr, ctidPtr, tlsPtr);
1912 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
1915 int sim_fd = ffdp->getSimFD();
1917 struct statfs hostBuf;
1918 int result = fstatfs(sim_fd, &hostBuf);
1932 int tgt_fd,
VPtr<> tiov_base,
1933 typename OS::size_t
count)
1937 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
1940 int sim_fd = ffdp->getSimFD();
1943 auto tiov = std::make_unique<typename OS::tgt_iovec[]>(
count);
1944 auto hiov = std::make_unique<struct iovec[]>(
count);
1945 for (
typename OS::size_t
i = 0;
i <
count; ++
i) {
1946 prox.
readBlob(tiov_base + (
i *
sizeof(
typename OS::tgt_iovec)),
1947 &tiov[
i],
sizeof(
typename OS::tgt_iovec));
1948 hiov[
i].iov_len =
gtoh(tiov[
i].iov_len, OS::byteOrder);
1949 hiov[
i].iov_base =
new char [hiov[
i].iov_len];
1952 int result = readv(sim_fd, hiov.get(),
count);
1953 int local_errno = errno;
1955 for (
typename OS::size_t
i = 0;
i <
count; ++
i) {
1958 hiov[
i].iov_base, hiov[
i].iov_len);
1960 delete [] (
char *)hiov[
i].iov_base;
1963 return (result == -1) ? -local_errno : result;
1970 int tgt_fd,
VPtr<> tiov_base,
1971 typename OS::size_t
count)
1975 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[tgt_fd]);
1978 int sim_fd = hbfdp->getSimFD();
1981 auto hiov = std::make_unique<struct iovec[]>(
count);
1982 for (
typename OS::size_t
i = 0;
i <
count; ++
i) {
1983 typename OS::tgt_iovec tiov;
1985 prox.
readBlob(tiov_base +
i*
sizeof(
typename OS::tgt_iovec),
1986 &tiov,
sizeof(
typename OS::tgt_iovec));
1987 hiov[
i].iov_len =
gtoh(tiov.iov_len, OS::byteOrder);
1988 hiov[
i].iov_base =
new char [hiov[
i].iov_len];
1989 prox.
readBlob(
gtoh(tiov.iov_base, OS::byteOrder), hiov[
i].iov_base,
1993 int result = writev(sim_fd, hiov.get(),
count);
1995 for (
typename OS::size_t
i = 0;
i <
count; ++
i)
1996 delete [] (
char *)hiov[
i].iov_base;
1998 return (result == -1) ? -errno : result;
2005 VPtr<> start,
typename OS::size_t length,
int prot,
2006 int tgt_flags,
int tgt_fd,
typename OS::off_t
offset)
2009 Addr page_bytes =
p->pTable->pageSize();
2011 if (start & (page_bytes - 1) ||
2012 offset & (page_bytes - 1) ||
2013 (tgt_flags & OS::TGT_MAP_PRIVATE &&
2014 tgt_flags & OS::TGT_MAP_SHARED) ||
2015 (!(tgt_flags & OS::TGT_MAP_PRIVATE) &&
2016 !(tgt_flags & OS::TGT_MAP_SHARED)) ||
2021 if ((
prot & PROT_WRITE) && (tgt_flags & OS::TGT_MAP_SHARED)) {
2042 warn_once(
"mmap: writing to shared mmap region is currently "
2043 "unsupported. The write succeeds on the target, but it "
2044 "will not be propagated to the host or shared mappings");
2047 length =
roundUp(length, page_bytes);
2050 if (!(tgt_flags & OS::TGT_MAP_ANONYMOUS)) {
2051 std::shared_ptr<FDEntry> fdep = (*
p->fds)[tgt_fd];
2053 auto dfdp = std::dynamic_pointer_cast<DeviceFDEntry>(fdep);
2056 return emul_driver->
mmap(tc, start, length,
prot, tgt_flags,
2060 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
2063 sim_fd = ffdp->getSimFD();
2074 std::shared_ptr<FDEntry> fdep = (*
p->fds)[tgt_fd];
2075 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
2077 ffdp->getFileName()));
2079 ffdp->getFileName());
2082 Addr offset = lib->buildImage().minAddr() + start;
2091 if (!(tgt_flags & OS::TGT_MAP_FIXED)) {
2099 if (!(start &&
p->memState->isUnmapped(start, length))) {
2103 start =
p->memState->extendMmap(length);
2108 start, start + length - 1);
2115 if (tgt_flags & OS::TGT_MAP_FIXED) {
2120 p->memState->unmapRegion(start, length);
2126 std::string region_name;
2127 if (tgt_flags & OS::TGT_MAP_ANONYMOUS) {
2128 region_name =
"anon";
2130 std::shared_ptr<FDEntry> fdep = (*
p->fds)[tgt_fd];
2131 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
2132 region_name = ffdp->getFileName();
2139 p->memState->mapRegion(start, length, region_name, sim_fd,
offset);
2147 int tgt_fd,
VPtr<> bufPtr,
typename OS::size_t nbytes,
2148 typename OS::off_t
offset)
2152 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
2155 int sim_fd = ffdp->getSimFD();
2163 return (bytes_read == -1) ? -errno : bytes_read;
2169 int tgt_fd,
VPtr<> bufPtr,
typename OS::size_t nbytes,
2170 typename OS::off_t
offset)
2174 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
2177 int sim_fd = ffdp->getSimFD();
2182 int bytes_written = pwrite(sim_fd, bufArg.
bufferPtr(), nbytes,
offset);
2184 return (bytes_written == -1) ? -errno : bytes_written;
2191 VPtr<> start,
typename OS::size_t length,
int prot,
2192 int tgt_flags,
int tgt_fd,
typename OS::off_t
offset)
2196 tgt_fd,
offset * page_size);
2205 const ByteOrder
bo = OS::byteOrder;
2207 case OS::TGT_RLIMIT_STACK:
2209 rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
2210 rlp->rlim_cur =
htog(rlp->rlim_cur,
bo);
2211 rlp->rlim_max =
htog(rlp->rlim_max,
bo);
2214 case OS::TGT_RLIMIT_DATA:
2216 rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024;
2217 rlp->rlim_cur =
htog(rlp->rlim_cur,
bo);
2218 rlp->rlim_max =
htog(rlp->rlim_max,
bo);
2221 case OS::TGT_RLIMIT_NPROC:
2223 rlp->rlim_cur =
htog(rlp->rlim_cur,
bo);
2224 rlp->rlim_max =
htog(rlp->rlim_max,
bo);
2228 warn(
"getrlimit: unimplemented resource %d", resource);
2242 warn(
"prlimit: ignoring rlimits for nonzero pid");
2246 warn(
"prlimit: ignoring new rlimit");
2248 const ByteOrder
bo = OS::byteOrder;
2250 case OS::TGT_RLIMIT_STACK:
2252 rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
2253 rlp->rlim_cur =
htog(rlp->rlim_cur,
bo);
2254 rlp->rlim_max =
htog(rlp->rlim_max,
bo);
2256 case OS::TGT_RLIMIT_DATA:
2258 rlp->rlim_cur = rlp->rlim_max = 256*1024*1024;
2259 rlp->rlim_cur =
htog(rlp->rlim_cur,
bo);
2260 rlp->rlim_max =
htog(rlp->rlim_max,
bo);
2263 warn(
"prlimit: unimplemented resource %d", resource);
2279 tp->tv_sec =
htog(tp->tv_sec, OS::byteOrder);
2280 tp->tv_nsec =
htog(tp->tv_nsec, OS::byteOrder);
2306 tp->tv_sec =
htog(tp->tv_sec, OS::byteOrder);
2307 tp->tv_usec =
htog(tp->tv_usec, OS::byteOrder);
2316 int dirfd,
VPtr<> pathname,
VPtr<
typename OS::timeval [2]> tp)
2327 struct timeval hostTimeval[2];
2328 for (
int i = 0;
i < 2; ++
i) {
2329 hostTimeval[
i].tv_sec =
gtoh((*tp)[
i].tv_sec, OS::byteOrder);
2330 hostTimeval[
i].tv_usec =
gtoh((*tp)[
i].tv_usec, OS::byteOrder);
2337 int result = utimes(path.c_str(), hostTimeval);
2349 VPtr<
typename OS::timeval [2]> tp)
2366 if (access(path.c_str(), F_OK) == -1)
2372 for (
int inc = 0; ; inc++) {
2374 b.copyIn(mem_proxy);
2376 if (!*(
Addr*)
b.bufferPtr())
2379 vect.push_back(std::string());
2388 if (!
p->vforkContexts.empty()) {
2400 ProcessParams *pp =
new ProcessParams();
2401 pp->executable = path;
2402 read_in(pp->cmd, mem_proxy, argv_mem_loc);
2403 read_in(pp->env, mem_proxy, envp_mem_loc);
2405 pp->egid =
p->egid();
2406 pp->euid =
p->euid();
2408 pp->ppid =
p->ppid();
2410 pp->input.assign(
"cin");
2411 pp->output.assign(
"cout");
2412 pp->errout.assign(
"cerr");
2413 pp->cwd.assign(
p->tgtCwd);
2414 pp->system =
p->system;
2415 pp->release =
p->release;
2416 pp->maxStackSize =
p->memState->getMaxStackSize();
2425 p->system->PIDs.erase(
p->pid());
2426 Process *new_p = pp->create();
2435 new_p->
fds =
p->fds;
2436 for (
int i = 0;
i < new_p->
fds->getSize();
i++) {
2437 std::shared_ptr<FDEntry> fdep = (*new_p->
fds)[
i];
2438 if (fdep && fdep->getCOE())
2439 new_p->
fds->closeFDEntry(
i);
2461 rup->ru_utime.tv_sec = 0;
2462 rup->ru_utime.tv_usec = 0;
2463 rup->ru_stime.tv_sec = 0;
2464 rup->ru_stime.tv_usec = 0;
2472 rup->ru_inblock = 0;
2473 rup->ru_oublock = 0;
2476 rup->ru_nsignals = 0;
2481 case OS::TGT_RUSAGE_SELF:
2483 rup->ru_utime.tv_sec =
htog(rup->ru_utime.tv_sec, OS::byteOrder);
2484 rup->ru_utime.tv_usec =
htog(rup->ru_utime.tv_usec, OS::byteOrder);
2487 case OS::TGT_RUSAGE_CHILDREN:
2494 warn(
"getrusage() only supports RUSAGE_SELF. Parameter %d ignored.",
2508 bufp->tms_utime = clocks;
2509 bufp->tms_stime = 0;
2510 bufp->tms_cutime = 0;
2511 bufp->tms_cstime = 0;
2514 bufp->tms_utime =
htog(bufp->tms_utime, OS::byteOrder);
2525 typename OS::time_t sec, usec;
2531 typename OS::time_t
t = sec;
2532 t =
htog(
t, OS::byteOrder);
2533 p.writeBlob(taddr, &
t, (
int)
sizeof(
typename OS::time_t));
2559 for (
auto *tc: sys->
threads) {
2561 if (temp->
pid() == tid) {
2567 if (sig != 0 && sig != OS::TGT_SIGABRT)
2570 if (tgt_proc ==
nullptr)
2573 if (tgid != -1 && tgt_proc->
tgid() != tgid)
2576 if (sig == OS::TGT_SIGABRT)
2593 auto sfdp = std::make_shared<SocketFDEntry>(sim_fd,
domain, type,
prot);
2594 int tgt_fd =
p->fds->allocFD(sfdp);
2613 auto sfdp1 = std::make_shared<SocketFDEntry>(fds[0],
domain, type,
prot);
2614 fds[0] =
p->fds->allocFD(sfdp1);
2615 auto sfdp2 = std::make_shared<SocketFDEntry>(fds[1],
domain, type,
prot);
2616 fds[1] =
p->fds->allocFD(sfdp2);
2640 FD_ZERO(&readfds_h);
2642 FD_ZERO(&writefds_h);
2644 FD_ZERO(&errorfds_h);
2656 std::map<int, int> trans_map;
2657 auto try_add_host_set = [&](
typename OS::fd_set *tgt_set_entry,
2658 fd_set *hst_set_entry,
2666 if (FD_ISSET(iter, (fd_set *)tgt_set_entry)) {
2672 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[iter]);
2675 auto sim_fd = hbfdp->getSimFD();
2682 trans_map[sim_fd] = iter;
2689 nfds_h = std::max(nfds_h - 1, sim_fd + 1);
2695 FD_SET(sim_fd, hst_set_entry);
2700 for (
int i = 0;
i < nfds;
i++) {
2702 bool ebadf = try_add_host_set(readfds, &readfds_h,
i);
2707 bool ebadf = try_add_host_set(writefds, &writefds_h,
i);
2712 bool ebadf = try_add_host_set(errorfds, &errorfds_h,
i);
2726 timeout->tv_sec = 0;
2727 timeout->tv_usec = 0;
2729 retval = select(nfds_h,
2730 readfds ? &readfds_h :
nullptr,
2731 writefds ? &writefds_h :
nullptr,
2732 errorfds ? &errorfds_h :
nullptr,
2733 (timeval *)(
typename OS::timeval *)timeout);
2742 struct timeval tv = { 0, 0 };
2744 retval = select(nfds_h,
2745 readfds ? &readfds_h :
nullptr,
2746 readfds ? &writefds_h :
nullptr,
2747 readfds ? &errorfds_h :
nullptr,
2757 if (sig.receiver ==
p)
2767 FD_ZERO(
reinterpret_cast<fd_set *
>((
typename OS::fd_set *)readfds));
2770 FD_ZERO(
reinterpret_cast<fd_set *
>((
typename OS::fd_set *)writefds));
2773 FD_ZERO(
reinterpret_cast<fd_set *
>((
typename OS::fd_set *)errorfds));
2781 for (
int i = 0;
i < nfds_h;
i++) {
2782 if (readfds && FD_ISSET(
i, &readfds_h))
2783 FD_SET(trans_map[
i],
2784 reinterpret_cast<fd_set *
>(
2785 (
typename OS::fd_set *)readfds));
2787 if (writefds && FD_ISSET(
i, &writefds_h))
2788 FD_SET(trans_map[
i],
2789 reinterpret_cast<fd_set *
>(
2790 (
typename OS::fd_set *)writefds));
2792 if (errorfds && FD_ISSET(
i, &errorfds_h))
2793 FD_SET(trans_map[
i],
2794 reinterpret_cast<fd_set *
>(
2795 (
typename OS::fd_set *)errorfds));
2804 int tgt_fd,
VPtr<> buf_ptr,
typename OS::size_t nbytes)
2808 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[tgt_fd]);
2811 int sim_fd = hbfdp->getSimFD();
2815 pfd.events = POLLIN | POLLPRI;
2816 if ((poll(&pfd, 1, 0) == 0)
2817 && !(hbfdp->getFlags() & OS::TGT_O_NONBLOCK))
2821 int bytes_read = read(sim_fd, buf_arg.
bufferPtr(), nbytes);
2826 return (bytes_read == -1) ? -errno : bytes_read;
2832 int tgt_fd,
VPtr<> buf_ptr,
typename OS::size_t nbytes)
2836 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[tgt_fd]);
2839 int sim_fd = hbfdp->getSimFD();
2846 pfd.events = POLLOUT;
2854 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(hbfdp);
2855 if (ffdp && (ffdp->getFileName() !=
"/dev/random")) {
2856 if (!poll(&pfd, 1, 0) && !(ffdp->getFlags() & OS::TGT_O_NONBLOCK))
2860 int bytes_written = write(sim_fd, buf_arg.
bufferPtr(), nbytes);
2862 if (bytes_written != -1)
2865 return (bytes_written == -1) ? -errno : bytes_written;
2871 pid_t pid,
VPtr<> statPtr,
int options,
VPtr<> rusagePtr)
2876 DPRINTF_SYSCALL(Verbose,
"wait4: rusage pointer provided %lx, however "
2877 "functionality not supported. Ignoring rusage pointer.\n",
2891 if (iter->receiver ==
p) {
2893 if ((iter->sender->pgid() == -pid)
2894 && (iter->signalValue == OS::TGT_SIGCHLD))
2896 }
else if (pid == -1) {
2897 if (iter->signalValue == OS::TGT_SIGCHLD)
2899 }
else if (pid == 0) {
2900 if ((iter->sender->pgid() ==
p->pgid())
2901 && (iter->signalValue == OS::TGT_SIGCHLD))
2904 if ((iter->sender->pid() == pid)
2905 && (iter->signalValue == OS::TGT_SIGCHLD))
2915 const int EXITED = 0;
2916 BufferArg statusBuf(statPtr,
sizeof(
int));
2921 pid_t retval = iter->sender->pid();
2939 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
2942 int sim_fd = sfdp->getSimFD();
2952 pfd.events = POLLIN | POLLPRI;
2953 if ((poll(&pfd, 1, 0) == 0) && !(sfdp->getFlags() & OS::TGT_O_NONBLOCK))
2957 lenBufPtr =
new BufferArg(lenPtr,
sizeof(socklen_t));
2959 memcpy(&addrLen, (socklen_t *)lenBufPtr->
bufferPtr(),
2964 addrBufPtr =
new BufferArg(addrPtr,
sizeof(
struct sockaddr));
2966 memcpy(&
sa, (
struct sockaddr *)addrBufPtr->
bufferPtr(),
2967 sizeof(
struct sockaddr));
2970 host_fd = accept(sim_fd, &
sa, &addrLen);
2982 *(socklen_t *)lenBufPtr->
bufferPtr() = addrLen;
2987 auto afdp = std::make_shared<SocketFDEntry>(host_fd, sfdp->_domain,
2988 sfdp->_type, sfdp->_protocol);
2989 return p->fds->allocFD(afdp);
2996 unsigned initval,
int in_flags)
2998#if defined(__linux__)
3001 int sim_fd = eventfd(initval, in_flags);
3005 bool cloexec = in_flags & OS::TGT_O_CLOEXEC;
3007 int flags = cloexec ? OS::TGT_O_CLOEXEC : 0;
3008 flags |= (in_flags & OS::TGT_O_NONBLOCK) ? OS::TGT_O_NONBLOCK : 0;
3010 auto hbfdp = std::make_shared<HBFDEntry>(flags, sim_fd, cloexec);
3011 int tgt_fd =
p->fds->allocFD(hbfdp);
3023 pid_t pid,
typename OS::size_t cpusetsize,
3026#if defined(__linux__)
3031 BufferArg maskBuf(cpu_set_mask, cpusetsize);
3034 CPU_SET(
i, (cpu_set_t *)maskBuf.
bufferPtr());
3048 int tgt_fd,
VPtr<> buf_ptr,
typename OS::size_t buf_len,
3053 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
3056 int sim_fd = sfdp->getSimFD();
3064 socklen_t addr_len = 0;
3065 if (addrlen_ptr != 0) {
3067 BufferArg addrlen_buf(addrlen_ptr,
sizeof(socklen_t));
3068 addrlen_buf.
copyIn(proxy);
3069 addr_len = *((socklen_t *)addrlen_buf.
bufferPtr());
3072 struct sockaddr
sa, *sap = NULL;
3073 if (addr_len != 0) {
3076 memcpy(&
sa, (
struct sockaddr *)addr_buf.
bufferPtr(),
3077 sizeof(
struct sockaddr));
3081 ssize_t recvd_size = recvfrom(sim_fd,
3083 buf_len, flags, sap, (socklen_t *)&addr_len);
3085 if (recvd_size == -1)
3099 if (addr_len != 0) {
3100 BufferArg addrlen_buf(addrlen_ptr,
sizeof(socklen_t));
3101 *(socklen_t *)addrlen_buf.
bufferPtr() = addr_len;
3109template <
typename OS>
3112 int tgt_fd,
VPtr<> buf_ptr,
typename OS::size_t buf_len,
int flags,
3113 VPtr<> addr_ptr, socklen_t addr_len)
3117 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
3120 int sim_fd = sfdp->getSimFD();
3126 struct sockaddr
sa, *sap =
nullptr;
3127 memset(&
sa, 0,
sizeof(sockaddr));
3128 if (addr_len != 0) {
3131 memcpy(&
sa, (sockaddr*)addr_buf.
bufferPtr(), addr_len);
3135 ssize_t sent_size = sendto(sim_fd,
3137 buf_len, flags, sap, (socklen_t)addr_len);
3139 return (sent_size == -1) ? -errno : sent_size;
3143template <
typename OS>
3146 typename OS::size_t length)
3154 if (
p->pTable->pageOffset(start))
3157 length =
roundUp(length,
p->pTable->pageSize());
3159 p->memState->unmapRegion(start, length);
3165template <
typename OS>
3168 int tgt_fd,
int mode,
typename OS::off_t
offset,
3169 typename OS::off_t
len)
3171#if defined(__linux__)
3174 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
3177 int sim_fd = ffdp->getSimFD();
3190template <
typename OS>
3193 typename OS::off_t length)
3202 path =
p->checkPathRedirect(path);
3204 int result = truncate(path.c_str(), length);
3205 return (result == -1) ? -errno : result;
3209template <
typename OS>
3212 typename OS::off_t length)
3216 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
3219 int sim_fd = ffdp->getSimFD();
3221 int result = ftruncate(sim_fd, length);
3222 return (result == -1) ? -errno : result;
3225template <
typename OS>
3236 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 ignoreWithEnosysFunc(SyscallDesc *desc, ThreadContext *tc)
Handler for unimplemented syscalls that return -ENOSYS to the target program.
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.