42 #ifndef __SIM_SYSCALL_EMUL_HH__
43 #define __SIM_SYSCALL_EMUL_HH__
45 #if (defined(__APPLE__) || defined(__OpenBSD__) || \
46 defined(__FreeBSD__) || defined(__CYGWIN__) || \
59 #if defined(__linux__)
61 #include <sys/eventfd.h>
62 #include <sys/statfs.h>
65 #include <sys/mount.h>
70 #include <sys/fcntl.h>
76 #include <sys/ioctl.h>
78 #include <sys/socket.h>
81 #include <sys/types.h>
95 #include "config/the_isa.hh"
100 #include "params/Process.hh"
111 #if defined(__APPLE__) && defined(__MACH__) && !defined(CMSG_ALIGN)
112 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
113 #elif defined(__FreeBSD__) && !defined(CMSG_ALIGN)
114 #define CMSG_ALIGN(n) _ALIGN(n)
137 SyscallReturn
ignoreFunc(SyscallDesc *desc, ThreadContext *tc);
143 SyscallReturn
fallocateFunc(SyscallDesc *desc, ThreadContext *tc,
147 SyscallReturn
exitFunc(SyscallDesc *desc, ThreadContext *tc,
int status);
160 SyscallReturn
brkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> new_brk);
163 SyscallReturn
closeFunc(SyscallDesc *desc, ThreadContext *tc,
int tgt_fd);
166 SyscallReturn
lseekFunc(SyscallDesc *desc, ThreadContext *tc,
167 int tgt_fd, uint64_t offs,
int whence);
170 SyscallReturn
_llseekFunc(SyscallDesc *desc, ThreadContext *tc,
171 int tgt_fd, uint64_t offset_high,
172 uint32_t offset_low, VPtr<> result_ptr,
int whence);
175 SyscallReturn
munmapFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> start,
179 SyscallReturn
shutdownFunc(SyscallDesc *desc, ThreadContext *tc,
180 int tgt_fd,
int how);
184 VPtr<> buf_ptr,
int name_len);
187 SyscallReturn
getcwdFunc(SyscallDesc *desc, ThreadContext *tc,
188 VPtr<> buf_ptr,
unsigned long size);
191 SyscallReturn
readlinkFunc(SyscallDesc *desc, ThreadContext *tc,
192 VPtr<> pathname, VPtr<> buf,
size_t bufsiz);
195 SyscallReturn
unlinkFunc(SyscallDesc *desc, ThreadContext *tc,
199 SyscallReturn
linkFunc(SyscallDesc *desc, ThreadContext *tc,
200 VPtr<> pathname, VPtr<> new_pathname);
203 SyscallReturn
symlinkFunc(SyscallDesc *desc, ThreadContext *tc,
204 VPtr<> pathname, VPtr<> new_pathname);
207 SyscallReturn
mkdirFunc(SyscallDesc *desc, ThreadContext *tc,
208 VPtr<> pathname, mode_t
mode);
211 SyscallReturn
mknodFunc(SyscallDesc *desc, ThreadContext *tc,
212 VPtr<> pathname, mode_t
mode, dev_t dev);
215 SyscallReturn
chdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname);
218 SyscallReturn
rmdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname);
221 SyscallReturn
renameFunc(SyscallDesc *desc, ThreadContext *tc,
222 VPtr<> oldpath, VPtr<> newpath);
226 SyscallReturn
truncateFunc(SyscallDesc *desc, ThreadContext *tc,
227 VPtr<> pathname, off_t length);
231 SyscallReturn
ftruncateFunc(SyscallDesc *desc, ThreadContext *tc,
232 int tgt_fd, off_t length);
236 SyscallReturn
truncate64Func(SyscallDesc *desc, ThreadContext *tc,
237 VPtr<> pathname, int64_t length);
241 int tgt_fd, int64_t length);
244 SyscallReturn
umaskFunc(SyscallDesc *desc, ThreadContext *tc);
247 SyscallReturn
gettidFunc(SyscallDesc *desc, ThreadContext *tc);
250 SyscallReturn
chownFunc(SyscallDesc *desc, ThreadContext *tc,
251 VPtr<> pathname, uint32_t owner, uint32_t group);
254 SyscallReturn
getpgrpFunc(SyscallDesc *desc, ThreadContext *tc);
257 SyscallReturn
setpgidFunc(SyscallDesc *desc, ThreadContext *tc,
261 SyscallReturn
fchownFunc(SyscallDesc *desc, ThreadContext *tc,
262 int tgt_fd, uint32_t owner, uint32_t group);
265 SyscallReturn
dupFunc(SyscallDesc *desc, ThreadContext *tc,
269 SyscallReturn
dup2Func(SyscallDesc *desc, ThreadContext *tc,
270 int old_tgt_fd,
int new_tgt_fd);
273 SyscallReturn
fcntlFunc(SyscallDesc *desc, ThreadContext *tc,
274 int tgt_fd,
int cmd, guest_abi::VarArgs<int> varargs);
277 SyscallReturn
fcntl64Func(SyscallDesc *desc, ThreadContext *tc,
278 int tgt_fd,
int cmd);
281 SyscallReturn
pipeFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> tgt_addr);
284 SyscallReturn
pipe2Func(SyscallDesc *desc, ThreadContext *tc,
285 VPtr<> tgt_addr,
int flags);
288 SyscallReturn
getpidFunc(SyscallDesc *desc, ThreadContext *tc);
292 int tgt_fd, VPtr<> sockAddrPtr,
296 SyscallReturn
bindFunc(SyscallDesc *desc, ThreadContext *tc,
297 int tgt_fd, VPtr<> buf_ptr,
int addrlen);
300 SyscallReturn
listenFunc(SyscallDesc *desc, ThreadContext *tc,
301 int tgt_fd,
int backlog);
304 SyscallReturn
connectFunc(SyscallDesc *desc, ThreadContext *tc,
305 int tgt_fd, VPtr<> buf_ptr,
int addrlen);
307 #if defined(SYS_getdents)
309 SyscallReturn getdentsFunc(SyscallDesc *desc, ThreadContext *tc,
310 int tgt_fd, VPtr<> buf_ptr,
unsigned count);
313 #if defined(SYS_getdents64)
315 SyscallReturn getdents64Func(SyscallDesc *desc, ThreadContext *tc,
316 int tgt_fd, VPtr<> buf_ptr,
unsigned count);
320 SyscallReturn
sendtoFunc(SyscallDesc *desc, ThreadContext *tc,
321 int tgt_fd, VPtr<> bufrPtr,
size_t bufrLen,
int flags,
322 VPtr<> addrPtr, socklen_t addrLen);
325 SyscallReturn
recvfromFunc(SyscallDesc *desc, ThreadContext *tc,
326 int tgt_fd, VPtr<> bufrPtr,
size_t bufrLen,
327 int flags, VPtr<> addrPtr, VPtr<> addrlenPtr);
330 SyscallReturn
recvmsgFunc(SyscallDesc *desc, ThreadContext *tc,
331 int tgt_fd, VPtr<> msgPtr,
int flags);
334 SyscallReturn
sendmsgFunc(SyscallDesc *desc, ThreadContext *tc,
335 int tgt_fd, VPtr<> msgPtr,
int flags);
338 SyscallReturn
getuidFunc(SyscallDesc *desc, ThreadContext *tc);
341 SyscallReturn
getgidFunc(SyscallDesc *desc, ThreadContext *tc);
344 SyscallReturn
getppidFunc(SyscallDesc *desc, ThreadContext *tc);
347 SyscallReturn
geteuidFunc(SyscallDesc *desc, ThreadContext *tc);
350 SyscallReturn
getegidFunc(SyscallDesc *desc, ThreadContext *tc);
353 SyscallReturn
accessFunc(SyscallDesc *desc, ThreadContext *tc,
354 VPtr<> pathname, mode_t
mode);
357 SyscallReturn
getsockoptFunc(SyscallDesc *desc, ThreadContext *tc,
358 int tgt_fd,
int level,
int optname,
359 VPtr<> valPtr, VPtr<> lenPtr);
362 SyscallReturn
setsockoptFunc(SyscallDesc *desc, ThreadContext *tc,
363 int tgt_fd,
int level,
int optname,
364 VPtr<> valPtr, socklen_t
len);
366 SyscallReturn
getcpuFunc(SyscallDesc *desc, ThreadContext *tc,
367 VPtr<uint32_t> cpu, VPtr<uint32_t> node,
368 VPtr<uint32_t> tcache);
372 int tgt_fd, VPtr<> addrPtr, VPtr<> lenPtr);
388 op &= ~OS::TGT_FUTEX_PRIVATE_FLAG;
389 op &= ~OS::TGT_FUTEX_CLOCK_REALTIME_FLAG;
393 if (OS::TGT_FUTEX_WAIT ==
op || OS::TGT_FUTEX_WAIT_BITSET ==
op) {
405 return -OS::TGT_EWOULDBLOCK;
407 if (OS::TGT_FUTEX_WAIT ==
op) {
408 futex_map.
suspend(uaddr, process->tgid(), tc);
414 }
else if (OS::TGT_FUTEX_WAKE ==
op) {
415 return futex_map.
wakeup(uaddr, process->tgid(),
val);
416 }
else if (OS::TGT_FUTEX_WAKE_BITSET ==
op) {
417 return futex_map.
wakeup_bitset(uaddr, process->tgid(), val3);
418 }
else if (OS::TGT_FUTEX_REQUEUE ==
op ||
419 OS::TGT_FUTEX_CMP_REQUEUE ==
op) {
429 if (OS::TGT_FUTEX_CMP_REQUEUE && val3 != mem_val)
430 return -OS::TGT_EWOULDBLOCK;
431 return futex_map.
requeue(uaddr, process->tgid(),
val, timeout, uaddr2);
432 }
else if (OS::TGT_FUTEX_WAKE_OP ==
op) {
460 int wake_cmparg = val3 & 0xfff;
461 int wake_oparg = (val3 & 0xfff000) >> 12;
462 int wake_cmp = (val3 & 0xf000000) >> 24;
463 int wake_op = (val3 & 0xf0000000) >> 28;
464 if ((wake_op & OS::TGT_FUTEX_OP_ARG_SHIFT) >> 3 == 1)
465 wake_oparg = (1 << wake_oparg);
466 wake_op &= ~OS::TGT_FUTEX_OP_ARG_SHIFT;
468 if (wake_op == OS::TGT_FUTEX_OP_SET)
470 else if (wake_op == OS::TGT_FUTEX_OP_ADD)
471 newval += wake_oparg;
472 else if (wake_op == OS::TGT_FUTEX_OP_OR)
473 newval |= wake_oparg;
474 else if (wake_op == OS::TGT_FUTEX_OP_ANDN)
475 newval &= ~wake_oparg;
476 else if (wake_op == OS::TGT_FUTEX_OP_XOR)
477 newval ^= wake_oparg;
482 int woken1 = futex_map.
wakeup(uaddr, process->tgid(),
val);
485 bool is_wake2 =
false;
486 if (wake_cmp == OS::TGT_FUTEX_OP_CMP_EQ)
487 is_wake2 = oldval == wake_cmparg;
488 else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_NE)
489 is_wake2 = oldval != wake_cmparg;
490 else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_LT)
491 is_wake2 = oldval < wake_cmparg;
492 else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_LE)
493 is_wake2 = oldval <= wake_cmparg;
494 else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_GT)
495 is_wake2 = oldval > wake_cmparg;
496 else if (wake_cmp == OS::TGT_FUTEX_OP_CMP_GE)
497 is_wake2 = oldval >= wake_cmparg;
500 woken2 = futex_map.
wakeup(uaddr2, process->tgid(), timeout);
502 return woken1 + woken2;
504 warn(
"futex: op %d not implemented; ignoring.",
op);
510 SyscallReturn
pipePseudoFunc(SyscallDesc *desc, ThreadContext *tc);
520 template <
class T1,
class T2>
524 static const int OneMillion = 1000 * 1000;
527 sec = elapsed_usecs / OneMillion;
528 usec = elapsed_usecs % OneMillion;
533 template <
class T1,
class T2>
537 static const int OneBillion = 1000 * 1000 * 1000;
540 sec = elapsed_nsecs / OneBillion;
541 nsec = elapsed_nsecs % OneBillion;
564 template <
typename OS,
typename TgtStatPtr,
typename HostStatPtr>
573 tgt->st_dev = host->st_dev;
574 tgt->st_dev =
htog(tgt->st_dev,
bo);
575 tgt->st_ino = host->st_ino;
576 tgt->st_ino =
htog(tgt->st_ino,
bo);
577 tgt->st_mode = host->st_mode;
580 tgt->st_mode &= ~S_IFMT;
581 tgt->st_mode |= S_IFCHR;
583 tgt->st_mode =
htog(tgt->st_mode,
bo);
584 tgt->st_nlink = host->st_nlink;
585 tgt->st_nlink =
htog(tgt->st_nlink,
bo);
586 tgt->st_uid = host->st_uid;
587 tgt->st_uid =
htog(tgt->st_uid,
bo);
588 tgt->st_gid = host->st_gid;
589 tgt->st_gid =
htog(tgt->st_gid,
bo);
591 tgt->st_rdev = 0x880d;
593 tgt->st_rdev = host->st_rdev;
594 tgt->st_rdev =
htog(tgt->st_rdev,
bo);
595 tgt->st_size = host->st_size;
596 tgt->st_size =
htog(tgt->st_size,
bo);
597 tgt->st_atimeX = host->st_atime;
598 tgt->st_atimeX =
htog(tgt->st_atimeX,
bo);
599 tgt->st_mtimeX = host->st_mtime;
600 tgt->st_mtimeX =
htog(tgt->st_mtimeX,
bo);
601 tgt->st_ctimeX = host->st_ctime;
602 tgt->st_ctimeX =
htog(tgt->st_ctimeX,
bo);
605 tgt->st_blksize = 0x2000;
606 tgt->st_blksize =
htog(tgt->st_blksize,
bo);
607 tgt->st_blocks = host->st_blocks;
608 tgt->st_blocks =
htog(tgt->st_blocks,
bo);
613 template <
typename OS,
typename TgtStatPtr,
typename HostStatPtr>
618 copyOutStatBuf<OS>(tgt, host, fakeTTY);
619 #if defined(STAT_HAVE_NSEC)
622 tgt->st_atime_nsec = host->st_atime_nsec;
623 tgt->st_atime_nsec =
htog(tgt->st_atime_nsec,
bo);
624 tgt->st_mtime_nsec = host->st_mtime_nsec;
625 tgt->st_mtime_nsec =
htog(tgt->st_mtime_nsec,
bo);
626 tgt->st_ctime_nsec = host->st_ctime_nsec;
627 tgt->st_ctime_nsec =
htog(tgt->st_ctime_nsec,
bo);
629 tgt->st_atime_nsec = 0;
630 tgt->st_mtime_nsec = 0;
631 tgt->st_ctime_nsec = 0;
635 template <
class OS,
typename TgtStatPtr,
typename HostStatPtr>
641 tgt->f_type =
htog(host->f_type,
bo);
642 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
643 tgt->f_bsize =
htog(host->f_iosize,
bo);
645 tgt->f_bsize =
htog(host->f_bsize,
bo);
647 tgt->f_blocks =
htog(host->f_blocks,
bo);
648 tgt->f_bfree =
htog(host->f_bfree,
bo);
649 tgt->f_bavail =
htog(host->f_bavail,
bo);
650 tgt->f_files =
htog(host->f_files,
bo);
651 tgt->f_ffree =
htog(host->f_ffree,
bo);
652 memcpy(&tgt->f_fsid, &host->f_fsid,
sizeof(host->f_fsid));
653 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
654 tgt->f_namelen =
htog(host->f_namemax,
bo);
655 tgt->f_frsize =
htog(host->f_bsize,
bo);
656 #elif defined(__APPLE__)
660 tgt->f_namelen =
htog(host->f_namelen,
bo);
661 tgt->f_frsize =
htog(host->f_frsize,
bo);
663 #if defined(__linux__)
664 memcpy(&tgt->f_spare, &host->f_spare,
665 std::min(
sizeof(host->f_spare),
sizeof(tgt->f_spare)));
671 memset(&tgt->f_spare, 0,
sizeof(tgt->f_spare));
688 if (OS::isTtyReq(req))
691 auto dfdp = std::dynamic_pointer_cast<DeviceFDEntry>((*
p->fds)[tgt_fd]);
695 return emul_driver->
ioctl(tc, req,
addr);
698 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
707 ifconf *conf = (ifconf*)conf_arg.
bufferPtr();
708 Addr ifc_buf_addr = (
Addr)conf->ifc_buf;
709 BufferArg ifc_buf_arg(ifc_buf_addr, conf->ifc_len);
712 conf->ifc_buf = (
char*)ifc_buf_arg.bufferPtr();
716 conf->ifc_buf = (
char*)ifc_buf_addr;
724 #if defined(__linux__)
729 #if defined(__linux__)
748 warn(
"Unsupported ioctl call (return ENOTTY): ioctl(%d, 0x%x, ...) @ \n",
757 int tgt_dirfd,
VPtr<> pathname,
int tgt_flags,
int mode)
770 int host_flags = O_BINARY;
778 for (
const auto &
p: OS::openFlagTable) {
779 if (tgt_flags &
p.first) {
780 tgt_flags &= ~
p.first;
781 host_flags |=
p.second;
784 warn_if(tgt_flags,
"%s: cannot decode flags %#x", desc->
name(), tgt_flags);
787 host_flags |= O_BINARY;
802 std::string redir_path = path;
803 std::string abs_path = path;
804 if (tgt_dirfd == OS::TGT_AT_FDCWD) {
805 abs_path =
p->absolutePath(path,
true);
806 redir_path =
p->checkPathRedirect(path);
808 std::shared_ptr<FDEntry> fdep = ((*
p->fds)[tgt_dirfd]);
809 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
812 abs_path = ffdp->getFileName() + path;
813 redir_path =
p->checkPathRedirect(abs_path);
823 std::string filename = abs_path.substr(strlen(
"/dev/"));
827 "driver open with path[%s]\n",
828 desc->
name(), abs_path.c_str());
829 return drv->
open(tc,
mode, host_flags);
862 std::string used_path;
864 {
"/proc/meminfo/",
"/system/",
"/platform/",
"/etc/passwd",
865 "/proc/self/maps",
"/dev/urandom",
866 "/sys/devices/system/cpu/online" };
867 for (
auto entry : special_paths) {
869 sim_fd = OS::openSpecialFile(abs_path,
p, tc);
870 used_path = abs_path;
874 sim_fd = open(redir_path.c_str(), host_flags,
mode);
875 used_path = redir_path;
880 "(inferred from:%s)\n", desc->
name(),
881 used_path.c_str(), path.c_str());
893 auto ffdp = std::make_shared<FileFDEntry>(sim_fd, host_flags, path, 0);
895 ffdp->setFileMode(
mode);
896 int tgt_fd =
p->fds->allocFD(ffdp);
898 "(inferred from:%s)\n", desc->
name(),
899 sim_fd, tgt_fd, used_path.c_str(), path.c_str());
909 return openatFunc<OS>(
910 desc, tc, OS::TGT_AT_FDCWD, pathname, tgt_flags,
mode);
918 if (dirfd != OS::TGT_AT_FDCWD)
919 warn(
"unlinkat: first argument not AT_FDCWD; unlikely to work");
930 if (dirfd != OS::TGT_AT_FDCWD)
931 warn(
"faccessat: first argument not AT_FDCWD; unlikely to work");
941 if (dirfd != OS::TGT_AT_FDCWD)
942 warn(
"openat: first argument not AT_FDCWD; unlikely to work");
950 int olddirfd,
VPtr<> oldpath,
int newdirfd,
VPtr<> newpath)
952 if (olddirfd != OS::TGT_AT_FDCWD)
953 warn(
"renameat: first argument not AT_FDCWD; unlikely to work");
955 if (newdirfd != OS::TGT_AT_FDCWD)
956 warn(
"renameat: third argument not AT_FDCWD; unlikely to work");
958 return renameFunc(desc, tc, oldpath, newpath);
970 sysinfo->totalram = process->system->memSize();
971 sysinfo->mem_unit = 1;
993 path = process->checkPathRedirect(path);
996 int result = chmod(path.c_str(), hostMode);
1006 VPtr<> fdsPtr,
int nfds,
int tmout)
1010 BufferArg fdsBuf(fdsPtr,
sizeof(
struct pollfd) * nfds);
1019 int temp_tgt_fds[nfds];
1022 auto tgt_fd = temp_tgt_fds[
index];
1023 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[tgt_fd]);
1026 auto host_fd = hbfdp->getSimFD();
1048 if (it->receiver ==
p)
1063 auto tgt_fd = temp_tgt_fds[
index];
1083 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
1086 int sim_fd = ffdp->getSimFD();
1088 mode_t hostMode =
mode;
1090 int result = fchmod(sim_fd, hostMode);
1092 return (result < 0) ? -errno : 0;
1099 VPtr<> start, uint64_t old_length, uint64_t new_length, uint64_t flags,
1103 Addr page_bytes =
p->pTable->pageSize();
1104 uint64_t provided_address = 0;
1105 bool use_provided_address = flags & OS::TGT_MREMAP_FIXED;
1107 if (use_provided_address)
1108 provided_address = varargs.
get<uint64_t>();
1110 if ((start % page_bytes != 0) ||
1111 (provided_address % page_bytes != 0)) {
1112 warn(
"mremap failing: arguments not page aligned");
1116 new_length =
roundUp(new_length, page_bytes);
1118 if (new_length > old_length) {
1119 Addr mmap_end =
p->memState->getMmapEnd();
1121 if ((start + old_length) == mmap_end &&
1122 (!use_provided_address || provided_address == start)) {
1125 uint64_t diff = new_length - old_length;
1126 p->memState->mapRegion(mmap_end, diff,
"remapped");
1127 p->memState->setMmapEnd(mmap_end + diff);
1130 if (!use_provided_address && !(flags & OS::TGT_MREMAP_MAYMOVE)) {
1131 warn(
"can't remap here and MREMAP_MAYMOVE flag not set\n");
1134 uint64_t new_start = provided_address;
1135 if (!use_provided_address) {
1136 new_start =
p->mmapGrowsDown() ?
1137 mmap_end - new_length : mmap_end;
1138 mmap_end =
p->mmapGrowsDown() ?
1139 new_start : mmap_end + new_length;
1140 p->memState->setMmapEnd(mmap_end);
1143 warn(
"mremapping to new vaddr %08p-%08p, adding %d\n",
1144 new_start, new_start + new_length,
1145 new_length - old_length);
1148 p->allocateMem(new_start + old_length,
1149 new_length - old_length,
1150 use_provided_address );
1152 if (use_provided_address &&
1153 ((new_start + new_length >
p->memState->getMmapEnd() &&
1154 !
p->mmapGrowsDown()) ||
1155 (new_start < p->memState->getMmapEnd() &&
1156 p->mmapGrowsDown()))) {
1159 warn(
"mmap region limit exceeded with MREMAP_FIXED\n");
1162 warn(
"returning %08p as start\n", new_start);
1163 p->memState->remapRegion(start, new_start, old_length);
1169 if (use_provided_address && provided_address != start)
1170 p->memState->remapRegion(start, provided_address, new_length);
1171 if (new_length != old_length)
1172 p->memState->unmapRegion(start + new_length,
1173 old_length - new_length);
1174 return use_provided_address ? provided_address : (
Addr)start;
1193 struct stat hostBuf;
1194 int result = stat(path.c_str(), &hostBuf);
1199 copyOutStatBuf<OS>(tgt_stat, &hostBuf);
1221 struct stat hostBuf;
1222 int result = stat(path.c_str(), &hostBuf);
1224 struct stat64 hostBuf;
1225 int result = stat64(path.c_str(), &hostBuf);
1231 copyOutStat64Buf<OS>(tgt_stat, &hostBuf);
1241 int dirfd,
VPtr<> pathname,
1245 if (dirfd != OS::TGT_AT_FDCWD)
1246 warn(
"fstatat64: first argument not AT_FDCWD; unlikely to work");
1253 path = process->checkPathRedirect(path);
1256 struct stat hostBuf;
1257 int result = stat(path.c_str(), &hostBuf);
1259 struct stat64 hostBuf;
1260 int result = stat64(path.c_str(), &hostBuf);
1266 copyOutStat64Buf<OS>(tgt_stat, &hostBuf);
1280 auto ffdp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[tgt_fd]);
1283 int sim_fd = ffdp->getSimFD();
1286 struct stat hostBuf;
1287 int result = fstat(sim_fd, &hostBuf);
1289 struct stat64 hostBuf;
1290 int result = fstat64(sim_fd, &hostBuf);
1296 copyOutStat64Buf<OS>(tgt_stat, &hostBuf, (sim_fd == 1));
1317 struct stat hostBuf;
1318 int result = lstat(path.c_str(), &hostBuf);
1323 copyOutStatBuf<OS>(tgt_stat, &hostBuf);
1344 struct stat hostBuf;
1345 int result = lstat(path.c_str(), &hostBuf);
1347 struct stat64 hostBuf;
1348 int result = lstat64(path.c_str(), &hostBuf);
1354 copyOutStat64Buf<OS>(tgt_stat, &hostBuf);
1369 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
1372 int sim_fd = ffdp->getSimFD();
1374 struct stat hostBuf;
1375 int result = fstat(sim_fd, &hostBuf);
1380 copyOutStatBuf<OS>(tgt_stat, &hostBuf, (sim_fd == 1));
1391 #if defined(__linux__)
1401 struct statfs hostBuf;
1402 int result = statfs(path.c_str(), &hostBuf);
1407 copyOutStatfsBuf<OS>(tgt_stat, &hostBuf);
1422 if (((flags & OS::TGT_CLONE_SIGHAND)&& !(flags & OS::TGT_CLONE_VM)) ||
1423 ((flags & OS::TGT_CLONE_THREAD) && !(flags & OS::TGT_CLONE_SIGHAND)) ||
1424 ((flags & OS::TGT_CLONE_FS) && (flags & OS::TGT_CLONE_NEWNS)) ||
1425 ((flags & OS::TGT_CLONE_NEWIPC) && (flags & OS::TGT_CLONE_SYSVSEM)) ||
1426 ((flags & OS::TGT_CLONE_NEWPID) && (flags & OS::TGT_CLONE_THREAD)) ||
1427 ((flags & OS::TGT_CLONE_VM) && !(newStack)))
1443 ProcessParams *pp =
new ProcessParams();
1444 pp->executable.assign(*(
new std::string(
p->progName())));
1445 pp->cmd.push_back(*(
new std::string(
p->progName())));
1446 pp->system =
p->system;
1447 pp->cwd.assign(
p->tgtCwd);
1448 pp->input.assign(
"stdin");
1449 pp->output.assign(
"stdout");
1450 pp->errout.assign(
"stderr");
1452 pp->euid =
p->euid();
1454 pp->egid =
p->egid();
1455 pp->release =
p->release;
1458 std::set<int>
const& pids =
p->system->PIDs;
1459 int temp_pid = *pids.begin();
1462 }
while (pids.find(temp_pid) != pids.end());
1464 fatal(
"temp_pid is too large: %d", temp_pid);
1467 pp->ppid = (flags & OS::TGT_CLONE_THREAD) ?
p->ppid() :
p->pid();
1468 pp->useArchPT =
p->useArchPT;
1469 pp->kvmInSE =
p->kvmInSE;
1480 if (flags & OS::TGT_CLONE_PARENT_SETTID) {
1481 BufferArg ptidBuf(ptidPtr,
sizeof(
long));
1482 long *ptid = (
long *)ptidBuf.
bufferPtr();
1487 if (flags & OS::TGT_CLONE_THREAD) {
1494 p->clone(tc, ctc, cp, flags);
1496 if (flags & OS::TGT_CLONE_THREAD) {
1499 }
else if (flags & OS::TGT_SIGCHLD) {
1503 if (flags & OS::TGT_CLONE_CHILD_SETTID) {
1504 BufferArg ctidBuf(ctidPtr,
sizeof(
long));
1505 long *ctid = (
long *)ctidBuf.
bufferPtr();
1510 if (flags & OS::TGT_CLONE_CHILD_CLEARTID)
1515 OS::archClone(flags,
p, cp, tc, ctc, newStack, tlsPtr);
1524 if (flags & OS::TGT_CLONE_VFORK) {
1537 return cloneFunc<OS>(desc, tc, flags, newStack, ptidPtr, ctidPtr, tlsPtr);
1548 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
1551 int sim_fd = ffdp->getSimFD();
1553 struct statfs hostBuf;
1554 int result = fstatfs(sim_fd, &hostBuf);
1559 copyOutStatfsBuf<OS>(tgt_stat, &hostBuf);
1568 int tgt_fd, uint64_t tiov_base,
size_t count)
1572 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
1575 int sim_fd = ffdp->getSimFD();
1578 typename OS::tgt_iovec tiov[
count];
1579 struct iovec hiov[
count];
1580 for (
size_t i = 0;
i <
count; ++
i) {
1581 prox.
readBlob(tiov_base + (
i *
sizeof(
typename OS::tgt_iovec)),
1582 &tiov[
i],
sizeof(
typename OS::tgt_iovec));
1584 hiov[
i].iov_base =
new char [hiov[
i].iov_len];
1587 int result = readv(sim_fd, hiov,
count);
1588 int local_errno = errno;
1590 for (
size_t i = 0;
i <
count; ++
i) {
1593 hiov[
i].iov_base, hiov[
i].iov_len);
1595 delete [] (
char *)hiov[
i].iov_base;
1598 return (result == -1) ? -local_errno : result;
1605 int tgt_fd, uint64_t tiov_base,
size_t count)
1609 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[tgt_fd]);
1612 int sim_fd = hbfdp->getSimFD();
1615 struct iovec hiov[
count];
1616 for (
size_t i = 0;
i <
count; ++
i) {
1617 typename OS::tgt_iovec tiov;
1619 prox.
readBlob(tiov_base +
i*
sizeof(
typename OS::tgt_iovec),
1620 &tiov,
sizeof(
typename OS::tgt_iovec));
1622 hiov[
i].iov_base =
new char [hiov[
i].iov_len];
1627 int result = writev(sim_fd, hiov,
count);
1630 delete [] (
char *)hiov[
i].iov_base;
1632 return (result == -1) ? -errno : result;
1639 VPtr<> start,
typename OS::size_t length,
int prot,
1640 int tgt_flags,
int tgt_fd,
typename OS::off_t
offset)
1643 Addr page_bytes =
p->pTable->pageSize();
1645 if (start & (page_bytes - 1) ||
1646 offset & (page_bytes - 1) ||
1647 (tgt_flags & OS::TGT_MAP_PRIVATE &&
1648 tgt_flags & OS::TGT_MAP_SHARED) ||
1649 (!(tgt_flags & OS::TGT_MAP_PRIVATE) &&
1650 !(tgt_flags & OS::TGT_MAP_SHARED)) ||
1655 if ((
prot & PROT_WRITE) && (tgt_flags & OS::TGT_MAP_SHARED)) {
1676 warn_once(
"mmap: writing to shared mmap region is currently "
1677 "unsupported. The write succeeds on the target, but it "
1678 "will not be propagated to the host or shared mappings");
1681 length =
roundUp(length, page_bytes);
1684 if (!(tgt_flags & OS::TGT_MAP_ANONYMOUS)) {
1685 std::shared_ptr<FDEntry> fdep = (*
p->fds)[tgt_fd];
1687 auto dfdp = std::dynamic_pointer_cast<DeviceFDEntry>(fdep);
1690 return emul_driver->
mmap(tc, start, length,
prot, tgt_flags,
1694 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
1697 sim_fd = ffdp->getSimFD();
1707 if (
p->interpImage.contains(tc->
pcState().instAddr())) {
1708 std::shared_ptr<FDEntry> fdep = (*
p->fds)[tgt_fd];
1709 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
1711 ffdp->getFileName()));
1713 ffdp->getFileName());
1716 Addr offset = lib->buildImage().minAddr() + start;
1725 if (!(tgt_flags & OS::TGT_MAP_FIXED)) {
1733 if (!(start &&
p->memState->isUnmapped(start, length))) {
1737 start =
p->memState->extendMmap(length);
1742 start, start + length - 1);
1749 if (tgt_flags & OS::TGT_MAP_FIXED) {
1754 p->memState->unmapRegion(start, length);
1760 std::string region_name;
1761 if (tgt_flags & OS::TGT_MAP_ANONYMOUS) {
1762 region_name =
"anon";
1764 std::shared_ptr<FDEntry> fdep = (*
p->fds)[tgt_fd];
1765 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
1766 region_name = ffdp->getFileName();
1773 p->memState->mapRegion(start, length, region_name, sim_fd,
offset);
1785 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
1788 int sim_fd = ffdp->getSimFD();
1796 return (bytes_read == -1) ? -errno : bytes_read;
1806 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
1809 int sim_fd = ffdp->getSimFD();
1814 int bytes_written = pwrite(sim_fd, bufArg.
bufferPtr(), nbytes,
offset);
1816 return (bytes_written == -1) ? -errno : bytes_written;
1823 VPtr<> start,
typename OS::size_t length,
int prot,
1824 int tgt_flags,
int tgt_fd,
typename OS::off_t
offset)
1827 return mmapFunc<OS>(desc, tc, start, length,
prot, tgt_flags,
1828 tgt_fd,
offset * page_size);
1839 case OS::TGT_RLIMIT_STACK:
1841 rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
1842 rlp->rlim_cur =
htog(rlp->rlim_cur,
bo);
1843 rlp->rlim_max =
htog(rlp->rlim_max,
bo);
1846 case OS::TGT_RLIMIT_DATA:
1848 rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024;
1849 rlp->rlim_cur =
htog(rlp->rlim_cur,
bo);
1850 rlp->rlim_max =
htog(rlp->rlim_max,
bo);
1853 case OS::TGT_RLIMIT_NPROC:
1855 rlp->rlim_cur =
htog(rlp->rlim_cur,
bo);
1856 rlp->rlim_max =
htog(rlp->rlim_max,
bo);
1860 warn(
"getrlimit: unimplemented resource %d", resource);
1874 warn(
"prlimit: ignoring rlimits for nonzero pid");
1878 warn(
"prlimit: ignoring new rlimit");
1882 case OS::TGT_RLIMIT_STACK:
1884 rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
1885 rlp->rlim_cur =
htog(rlp->rlim_cur,
bo);
1886 rlp->rlim_max =
htog(rlp->rlim_max,
bo);
1888 case OS::TGT_RLIMIT_DATA:
1890 rlp->rlim_cur = rlp->rlim_max = 256*1024*1024;
1891 rlp->rlim_cur =
htog(rlp->rlim_cur,
bo);
1892 rlp->rlim_max =
htog(rlp->rlim_max,
bo);
1895 warn(
"prlimit: unimplemented resource %d", resource);
1949 VPtr<
typename OS::timeval [2]> tp)
1957 struct timeval hostTimeval[2];
1958 for (
int i = 0;
i < 2; ++
i) {
1964 path = process->checkPathRedirect(path);
1966 int result = utimes(path.c_str(), hostTimeval);
1986 if (access(path.c_str(), F_OK) == -1)
1992 for (
int inc = 0; ;
inc++) {
1994 b.copyIn(mem_proxy);
1996 if (!*(
Addr*)
b.bufferPtr())
1999 vect.push_back(std::string());
2000 mem_proxy.tryReadString(vect[
inc], *(
Addr*)
b.bufferPtr());
2008 if (!
p->vforkContexts.empty()) {
2020 ProcessParams *pp =
new ProcessParams();
2021 pp->executable = path;
2022 read_in(pp->cmd, mem_proxy, argv_mem_loc);
2023 read_in(pp->env, mem_proxy, envp_mem_loc);
2025 pp->egid =
p->egid();
2026 pp->euid =
p->euid();
2028 pp->ppid =
p->ppid();
2030 pp->input.assign(
"cin");
2031 pp->output.assign(
"cout");
2032 pp->errout.assign(
"cerr");
2033 pp->cwd.assign(
p->tgtCwd);
2034 pp->system =
p->system;
2035 pp->release =
p->release;
2044 p->system->PIDs.erase(
p->pid());
2045 Process *new_p = pp->create();
2054 new_p->
fds =
p->fds;
2055 for (
int i = 0;
i < new_p->
fds->getSize();
i++) {
2056 std::shared_ptr<FDEntry> fdep = (*new_p->
fds)[
i];
2057 if (fdep && fdep->getCOE())
2058 new_p->
fds->closeFDEntry(
i);
2070 tc->
setNPC(pcState.instAddr());
2082 rup->ru_utime.tv_sec = 0;
2083 rup->ru_utime.tv_usec = 0;
2084 rup->ru_stime.tv_sec = 0;
2085 rup->ru_stime.tv_usec = 0;
2093 rup->ru_inblock = 0;
2094 rup->ru_oublock = 0;
2097 rup->ru_nsignals = 0;
2102 case OS::TGT_RUSAGE_SELF:
2108 case OS::TGT_RUSAGE_CHILDREN:
2115 warn(
"getrusage() only supports RUSAGE_SELF. Parameter %d ignored.",
2129 bufp->tms_utime = clocks;
2130 bufp->tms_stime = 0;
2131 bufp->tms_cutime = 0;
2132 bufp->tms_cstime = 0;
2146 typename OS::time_t sec, usec;
2151 typename OS::time_t
t = sec;
2154 p.writeBlob(taddr, &
t, (
int)
sizeof(
typename OS::time_t));
2180 for (
auto *tc: sys->
threads) {
2182 if (temp->
pid() == tid) {
2188 if (sig != 0 || sig != OS::TGT_SIGABRT)
2191 if (tgt_proc ==
nullptr)
2194 if (tgid != -1 && tgt_proc->
tgid() != tgid)
2197 if (sig == OS::TGT_SIGABRT)
2214 auto sfdp = std::make_shared<SocketFDEntry>(sim_fd,
domain,
type,
prot);
2215 int tgt_fd =
p->fds->allocFD(sfdp);
2234 auto sfdp1 = std::make_shared<SocketFDEntry>(fds[0],
domain,
type,
prot);
2235 fds[0] =
p->fds->allocFD(sfdp1);
2236 auto sfdp2 = std::make_shared<SocketFDEntry>(fds[1],
domain,
type,
prot);
2237 fds[1] =
p->fds->allocFD(sfdp2);
2261 FD_ZERO(&readfds_h);
2263 FD_ZERO(&writefds_h);
2265 FD_ZERO(&errorfds_h);
2277 std::map<int, int> trans_map;
2278 auto try_add_host_set = [&](
typename OS::fd_set *tgt_set_entry,
2279 fd_set *hst_set_entry,
2287 if (FD_ISSET(iter, (fd_set *)tgt_set_entry)) {
2293 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[iter]);
2296 auto sim_fd = hbfdp->getSimFD();
2303 trans_map[sim_fd] = iter;
2310 nfds_h = std::max(nfds_h - 1, sim_fd + 1);
2316 FD_SET(sim_fd, hst_set_entry);
2321 for (
int i = 0;
i < nfds;
i++) {
2323 bool ebadf = try_add_host_set(readfds, &readfds_h,
i);
2328 bool ebadf = try_add_host_set(writefds, &writefds_h,
i);
2333 bool ebadf = try_add_host_set(errorfds, &errorfds_h,
i);
2347 timeout->tv_sec = 0;
2348 timeout->tv_usec = 0;
2350 retval = select(nfds_h,
2351 readfds ? &readfds_h :
nullptr,
2352 writefds ? &writefds_h :
nullptr,
2353 errorfds ? &errorfds_h :
nullptr,
2354 (timeval *)(
typename OS::timeval *)timeout);
2363 struct timeval tv = { 0, 0 };
2365 retval = select(nfds_h,
2366 readfds ? &readfds_h :
nullptr,
2367 readfds ? &writefds_h :
nullptr,
2368 readfds ? &errorfds_h :
nullptr,
2378 if (sig.receiver ==
p)
2387 FD_ZERO(
reinterpret_cast<fd_set *
>((
typename OS::fd_set *)readfds));
2388 FD_ZERO(
reinterpret_cast<fd_set *
>((
typename OS::fd_set *)writefds));
2389 FD_ZERO(
reinterpret_cast<fd_set *
>((
typename OS::fd_set *)errorfds));
2396 for (
int i = 0;
i < nfds_h;
i++) {
2397 if (readfds && FD_ISSET(
i, &readfds_h))
2398 FD_SET(trans_map[
i],
2399 reinterpret_cast<fd_set *
>(
2400 (
typename OS::fd_set *)readfds));
2402 if (writefds && FD_ISSET(
i, &writefds_h))
2403 FD_SET(trans_map[
i],
2404 reinterpret_cast<fd_set *
>(
2405 (
typename OS::fd_set *)writefds));
2407 if (errorfds && FD_ISSET(
i, &errorfds_h))
2408 FD_SET(trans_map[
i],
2409 reinterpret_cast<fd_set *
>(
2410 (
typename OS::fd_set *)errorfds));
2419 int tgt_fd,
VPtr<> buf_ptr,
int nbytes)
2423 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[tgt_fd]);
2426 int sim_fd = hbfdp->getSimFD();
2430 pfd.events = POLLIN | POLLPRI;
2431 if ((poll(&pfd, 1, 0) == 0)
2432 && !(hbfdp->getFlags() & OS::TGT_O_NONBLOCK))
2436 int bytes_read = read(sim_fd, buf_arg.
bufferPtr(), nbytes);
2441 return (bytes_read == -1) ? -errno : bytes_read;
2447 int tgt_fd,
VPtr<> buf_ptr,
int nbytes)
2451 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[tgt_fd]);
2454 int sim_fd = hbfdp->getSimFD();
2461 pfd.events = POLLOUT;
2469 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(hbfdp);
2470 if (ffdp && (ffdp->getFileName() !=
"/dev/random")) {
2471 if (!poll(&pfd, 1, 0) && !(ffdp->getFlags() & OS::TGT_O_NONBLOCK))
2475 int bytes_written = write(sim_fd, buf_arg.
bufferPtr(), nbytes);
2477 if (bytes_written != -1)
2480 return (bytes_written == -1) ? -errno : bytes_written;
2486 pid_t pid,
VPtr<> statPtr,
int options,
VPtr<> rusagePtr)
2491 DPRINTF_SYSCALL(Verbose,
"wait4: rusage pointer provided %lx, however "
2492 "functionality not supported. Ignoring rusage pointer.\n",
2506 if (iter->receiver ==
p) {
2508 if ((iter->sender->pgid() == -pid)
2509 && (iter->signalValue == OS::TGT_SIGCHLD))
2511 }
else if (pid == -1) {
2512 if (iter->signalValue == OS::TGT_SIGCHLD)
2514 }
else if (pid == 0) {
2515 if ((iter->sender->pgid() ==
p->pgid())
2516 && (iter->signalValue == OS::TGT_SIGCHLD))
2519 if ((iter->sender->pid() == pid)
2520 && (iter->signalValue == OS::TGT_SIGCHLD))
2530 const int EXITED = 0;
2531 BufferArg statusBuf(statPtr,
sizeof(
int));
2536 pid_t retval = iter->sender->pid();
2554 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
2557 int sim_fd = sfdp->getSimFD();
2567 pfd.events = POLLIN | POLLPRI;
2568 if ((poll(&pfd, 1, 0) == 0) && !(sfdp->getFlags() & OS::TGT_O_NONBLOCK))
2572 lenBufPtr =
new BufferArg(lenPtr,
sizeof(socklen_t));
2574 memcpy(&addrLen, (socklen_t *)lenBufPtr->
bufferPtr(),
2579 addrBufPtr =
new BufferArg(addrPtr,
sizeof(
struct sockaddr));
2581 memcpy(&
sa, (
struct sockaddr *)addrBufPtr->
bufferPtr(),
2582 sizeof(
struct sockaddr));
2585 host_fd = accept(sim_fd, &
sa, &addrLen);
2597 *(socklen_t *)lenBufPtr->
bufferPtr() = addrLen;
2602 auto afdp = std::make_shared<SocketFDEntry>(host_fd, sfdp->_domain,
2603 sfdp->_type, sfdp->_protocol);
2604 return p->fds->allocFD(afdp);
2611 unsigned initval,
int in_flags)
2613 #if defined(__linux__)
2616 int sim_fd = eventfd(initval, in_flags);
2620 bool cloexec = in_flags & OS::TGT_O_CLOEXEC;
2622 int flags = cloexec ? OS::TGT_O_CLOEXEC : 0;
2623 flags |= (in_flags & OS::TGT_O_NONBLOCK) ? OS::TGT_O_NONBLOCK : 0;
2625 auto hbfdp = std::make_shared<HBFDEntry>(flags, sim_fd, cloexec);
2626 int tgt_fd =
p->fds->allocFD(hbfdp);
2638 pid_t pid,
size_t cpusetsize,
VPtr<> cpu_set_mask)
2640 #if defined(__linux__)
2644 BufferArg maskBuf(cpu_set_mask, cpusetsize);
2647 CPU_SET(
i, (cpu_set_t *)maskBuf.
bufferPtr());
2659 #endif // __SIM_SYSCALL_EMUL_HH__