32 #include <sys/syscall.h>
39 #include <unordered_map>
60 warn(
"Cannot invoke %s on host operating system.", syscall_name);
66 fatal(
"syscall %s (#%d) unimplemented.", desc->
name(), desc->
num());
73 warn(
"ignoring syscall %s(...)", desc->
name());
80 static std::unordered_map<SyscallDesc *, bool> bool_map;
82 bool &warned = bool_map[desc];
84 warn(
"ignoring syscall %s(...)\n"
85 " (further warnings will be suppressed)", desc->
name());
114 *
p->exitGroup =
true;
116 if (
p->childClearTID)
119 bool last_thread =
true;
120 Process *parent =
nullptr, *tg_lead =
nullptr;
123 if (!(walk = sys->
threads[
i]->getProcessPtr()))
132 if (walk->
pid() ==
p->tgid())
145 if (walk->
tgid() ==
p->tgid()) {
158 if (*(
p->exitGroup)) {
174 if (*
p->sigchld && (
p->ppid() != 0) && (walk->
pid() ==
p->ppid()))
190 for (
int i = 0;
i <
p->fds->getSize();
i++) {
192 p->fds->closeFDEntry(
i);
200 if (!
p->vforkContexts.empty()) {
212 int activeContexts = 0;
214 activeContexts +=
system->threads.numRunning();
216 if (activeContexts == 0) {
262 std::shared_ptr<MemState> mem_state =
p->memState;
263 Addr brk_point = mem_state->getBrkPoint();
267 if (new_brk == 0 || (new_brk == brk_point))
270 mem_state->updateBrkRegion(brk_point, new_brk);
273 mem_state->getBrkPoint());
275 return mem_state->getBrkPoint();
284 return process->pid();
291 return p->fds->closeFDEntry(tgt_fd);
296 int tgt_fd, uint64_t offs,
int whence)
300 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
303 int sim_fd = ffdp->getSimFD();
305 off_t result = lseek(sim_fd, offs, whence);
307 return (result == (off_t)-1) ? -errno : result;
313 int tgt_fd, uint64_t offset_high, uint32_t offset_low,
314 VPtr<> result_ptr,
int whence)
318 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
321 int sim_fd = ffdp->getSimFD();
323 uint64_t
offset = (offset_high << 32) | offset_low;
325 uint64_t result = lseek(sim_fd,
offset, whence);
328 if (result == (off_t)-1)
331 BufferArg result_buf(result_ptr,
sizeof(result));
332 std::memcpy(result_buf.
bufferPtr(), &result,
sizeof(result));
347 if (
p->pTable->pageOffset(start))
350 length =
roundUp(length,
p->pTable->pageSize());
352 p->memState->unmapRegion(start, length);
362 VPtr<> buf_ptr,
int name_len)
372 VPtr<> buf_ptr,
unsigned long size)
379 std::string cwd =
p->tgtCwd;
381 if (cwd.length() >= size) {
385 strncpy((
char *)buf.
bufferPtr(), cwd.c_str(), size);
386 result = cwd.length();
388 if (getcwd((
char *)buf.
bufferPtr(), size)) {
389 result = strlen((
char *)buf.
bufferPtr());
397 return (result == -1) ? -errno : result;
411 path =
p->checkPathRedirect(path);
416 if (path !=
"/proc/self/exe") {
417 result = readlink(path.c_str(), (
char *)buf.
bufferPtr(), bufsiz);
431 char real_path[PATH_MAX];
432 char *check_real_path = realpath(
p->progName(), real_path);
433 if (!check_real_path) {
434 fatal(
"readlink('/proc/self/exe') unable to resolve path to "
435 "executable: %s",
p->progName());
437 strncpy((
char*)buf.
bufferPtr(), real_path, bufsiz);
438 size_t real_path_len = strlen(real_path);
439 if (real_path_len > bufsiz) {
444 result = real_path_len;
448 warn_once(
"readlink() called on '/proc/self/exe' may yield unexpected "
449 "results in various settings.\n Returning '%s'\n",
455 return (result == -1) ? -errno : result;
467 path =
p->checkPathRedirect(path);
469 int result = unlink(path.c_str());
470 return (result == -1) ? -errno : result;
478 std::string new_path;
482 if (!virt_mem.tryReadString(path, pathname))
484 if (!virt_mem.tryReadString(new_path, new_pathname))
487 path =
p->absolutePath(path,
true);
488 new_path =
p->absolutePath(new_path,
true);
490 int result = link(path.c_str(), new_path.c_str());
491 return (result == -1) ? -errno : result;
499 std::string new_path;
503 if (!virt_mem.tryReadString(path, pathname))
505 if (!virt_mem.tryReadString(new_path, new_pathname))
508 path =
p->absolutePath(path,
true);
509 new_path =
p->absolutePath(new_path,
true);
511 int result = symlink(path.c_str(), new_path.c_str());
512 return (result == -1) ? -errno : result;
523 path =
p->checkPathRedirect(path);
525 auto result = mkdir(path.c_str(),
mode);
526 return (result == -1) ? -errno : result;
535 std::string old_name;
539 std::string new_name;
544 old_name =
p->checkPathRedirect(old_name);
545 new_name =
p->checkPathRedirect(new_name);
547 int64_t result = rename(old_name.c_str(), new_name.c_str());
548 return (result == -1) ? -errno : result;
562 path =
p->checkPathRedirect(path);
564 int result = truncate(path.c_str(), length);
565 return (result == -1) ? -errno : result;
573 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
576 int sim_fd = ffdp->getSimFD();
578 int result = ftruncate(sim_fd, length);
579 return (result == -1) ? -errno : result;
584 VPtr<> pathname, int64_t length)
596 int result = truncate(path.c_str(), length);
598 int result = truncate64(path.c_str(), length);
600 return (result == -1) ? -errno : result;
605 int tgt_fd, int64_t length)
609 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
612 int sim_fd = ffdp->getSimFD();
615 int result = ftruncate(sim_fd, length);
617 int result = ftruncate64(sim_fd, length);
619 return (result == -1) ? -errno : result;
628 mode_t oldMask = umask(0);
635 VPtr<> pathname, uint32_t owner, uint32_t group)
644 uid_t hostOwner = owner;
645 gid_t hostGroup = group;
648 path =
p->checkPathRedirect(path);
650 int result = chown(path.c_str(), hostOwner, hostGroup);
651 return (result == -1) ? -errno : result;
656 int tgt_fd, uint32_t owner, uint32_t group)
660 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
663 int sim_fd = ffdp->getSimFD();
666 uid_t hostOwner = owner;
667 gid_t hostGroup = group;
669 int result = fchown(sim_fd, hostOwner, hostGroup);
670 return (result == -1) ? -errno : result;
684 auto old_hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[tgt_fd]);
687 int sim_fd = old_hbfdp->getSimFD();
689 int result = dup(sim_fd);
693 auto new_hbfdp = std::dynamic_pointer_cast<HBFDEntry>(old_hbfdp->clone());
694 new_hbfdp->setSimFD(result);
695 new_hbfdp->setCOE(
false);
696 return p->fds->allocFD(new_hbfdp);
703 auto old_hbp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[old_tgt_fd]);
706 int old_sim_fd = old_hbp->getSimFD();
713 int res_fd = dup2(old_sim_fd, open(
"/dev/null", O_RDONLY));
717 auto new_hbp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[new_tgt_fd]);
719 p->fds->closeFDEntry(new_tgt_fd);
720 new_hbp = std::dynamic_pointer_cast<HBFDEntry>(old_hbp->clone());
721 new_hbp->setSimFD(res_fd);
722 new_hbp->setCOE(
false);
724 return p->fds->allocFD(new_hbp);
733 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[tgt_fd]);
736 int sim_fd = hbfdp->getSimFD();
738 int coe = hbfdp->getCOE();
742 return coe & FD_CLOEXEC;
745 int arg = varargs.
get<
int>();
746 arg ? hbfdp->setCOE(
true) : hbfdp->setCOE(
false);
758 int arg = varargs.
get<
int>();
759 int rv = fcntl(sim_fd, cmd, arg);
760 return (rv == -1) ? -errno : rv;
764 warn(
"fcntl: unsupported command %d\n", cmd);
774 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[tgt_fd]);
777 int sim_fd = hbfdp->getSimFD();
781 warn(
"fcntl64(%d, F_GETLK64) not supported, error returned\n", tgt_fd);
786 warn(
"fcntl64(%d, F_SETLK(W)64) not supported, error returned\n",
793 warn(
"fcntl64(%d, %d) passed through to host\n", tgt_fd, cmd);
794 return fcntl(sim_fd, cmd);
815 int sim_fds[2], tgt_fds[2];
817 int pipe_retval = pipe(sim_fds);
818 if (pipe_retval == -1)
821 auto rend = PipeFDEntry::EndType::read;
822 auto rpfd = std::make_shared<PipeFDEntry>(sim_fds[0], O_WRONLY, rend);
823 tgt_fds[0] =
p->fds->allocFD(rpfd);
824 int sim_fd_rpfd = rpfd->getSimFD();
826 auto wend = PipeFDEntry::EndType::write;
827 auto wpfd = std::make_shared<PipeFDEntry>(sim_fds[1], O_RDONLY, wend);
828 tgt_fds[1] =
p->fds->allocFD(wpfd);
829 int sim_fd_wpfd = wpfd->getSimFD();
835 rpfd->setPipeReadSource(tgt_fds[1]);
849 BufferArg tgt_handle(tgt_addr,
sizeof(
int[2]));
850 int *buf_ptr = (
int*)tgt_handle.
bufferPtr();
851 buf_ptr[0] = tgt_fds[0];
852 buf_ptr[1] = tgt_fds[1];
858 if ((flags != O_CLOEXEC) && (flags != O_NONBLOCK) &&
859 (flags != (O_CLOEXEC | O_NONBLOCK))) {
867 if (flags & O_NONBLOCK) {
874 if (fcntl(sim_fd_rpfd, F_SETFL, O_NONBLOCK)) {
877 if (fcntl(sim_fd_wpfd, F_SETFL, O_NONBLOCK)) {
886 if (flags & O_CLOEXEC) {
899 return process->
pgid();
911 process->
pgid(process->pid());
919 for (
auto *tc: sysh->
threads) {
924 if (walk_ph && walk_ph->
pid() == process->pid())
925 matched_ph = walk_ph;
930 matched_ph->
pgid((pgid == 0) ? matched_ph->
pid() : pgid);
940 return process->
tgid();
947 return process->
pid();
954 return process->
ppid();
961 return process->
uid();
968 return process->
euid();
975 return process->
gid();
982 return process->
egid();
989 #if defined(__linux__)
992 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
995 int sim_fd = ffdp->getSimFD();
1017 path =
p->checkPathRedirect(path);
1019 int result = access(path.c_str(),
mode);
1020 return (result == -1) ? -errno : result;
1032 path =
p->checkPathRedirect(path);
1034 auto result = mknod(path.c_str(),
mode, dev);
1035 return (result == -1) ? -errno : result;
1046 std::string tgt_cwd;
1051 tgt_cwd = realpath((
p->tgtCwd +
"/" + path).c_str(), buf);
1053 std::string host_cwd =
p->checkPathRedirect(tgt_cwd);
1055 int result = chdir(host_cwd.c_str());
1060 p->hostCwd = host_cwd;
1061 p->tgtCwd = tgt_cwd;
1073 path =
p->checkPathRedirect(path);
1075 auto result = rmdir(path.c_str());
1076 return (result == -1) ? -errno : result;
1079 #if defined(SYS_getdents) || defined(SYS_getdents64)
1080 template<
typename DE,
int SYS_NUM>
1081 static SyscallReturn
1082 getdentsImpl(SyscallDesc *desc, ThreadContext *tc,
1083 int tgt_fd, VPtr<> buf_ptr,
unsigned count)
1085 auto p = tc->getProcessPtr();
1087 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[tgt_fd]);
1090 int sim_fd = hbfdp->getSimFD();
1092 BufferArg buf_arg(buf_ptr,
count);
1093 auto status = syscall(SYS_NUM, sim_fd, buf_arg.bufferPtr(),
count);
1098 unsigned traversed = 0;
1099 while (traversed <
status) {
1100 DE *buffer = (DE*)((
Addr)buf_arg.bufferPtr() + traversed);
1102 auto host_reclen = buffer->d_reclen;
1109 const ByteOrder
bo = tc->getSystemPtr()->getGuestByteOrder();
1110 buffer->d_ino =
htog(buffer->d_ino,
bo);
1111 buffer->d_off =
htog(buffer->d_off,
bo);
1112 buffer->d_reclen =
htog(buffer->d_reclen,
bo);
1114 traversed += host_reclen;
1117 buf_arg.copyOut(tc->getVirtProxy());
1122 #if defined(SYS_getdents)
1124 getdentsFunc(SyscallDesc *desc, ThreadContext *tc,
1125 int tgt_fd, VPtr<> buf_ptr,
unsigned count)
1127 typedef struct linux_dirent
1129 unsigned long d_ino;
1130 unsigned long d_off;
1131 unsigned short d_reclen;
1135 return getdentsImpl<LinDent, SYS_getdents>(desc, tc,
1136 tgt_fd, buf_ptr,
count);
1140 #if defined(SYS_getdents64)
1142 getdents64Func(SyscallDesc *desc, ThreadContext *tc,
1143 int tgt_fd, VPtr<> buf_ptr,
unsigned count)
1145 typedef struct linux_dirent64
1149 unsigned short d_reclen;
1153 return getdentsImpl<LinDent64, SYS_getdents64>(desc, tc,
1154 tgt_fd, buf_ptr,
count);
1163 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
1166 int sim_fd = sfdp->getSimFD();
1168 int retval = shutdown(sim_fd, how);
1170 return (retval == -1) ? -errno : retval;
1175 int tgt_fd,
VPtr<> buf_ptr,
int addrlen)
1182 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
1185 int sim_fd = sfdp->getSimFD();
1187 int status = ::bind(sim_fd,
1199 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
1202 int sim_fd = sfdp->getSimFD();
1204 int status = listen(sim_fd, backlog);
1211 int tgt_fd,
VPtr<> buf_ptr,
int addrlen)
1218 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
1221 int sim_fd = sfdp->getSimFD();
1223 int status = connect(sim_fd,
1224 (
struct sockaddr *)
addr.bufferPtr(),
1225 (socklen_t)addrlen);
1232 int tgt_fd,
VPtr<> bufrPtr,
size_t bufrLen,
int flags,
1237 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
1240 int sim_fd = sfdp->getSimFD();
1246 socklen_t addrLen = 0;
1247 if (addrlenPtr != 0) {
1249 BufferArg addrlenBuf(addrlenPtr,
sizeof(socklen_t));
1251 addrLen = *((socklen_t *)addrlenBuf.
bufferPtr());
1254 struct sockaddr
sa, *sap = NULL;
1258 memcpy(&
sa, (
struct sockaddr *)addrBuf.
bufferPtr(),
1259 sizeof(
struct sockaddr));
1263 ssize_t recvd_size = recvfrom(sim_fd,
1265 bufrLen, flags, sap, (socklen_t *)&addrLen);
1267 if (recvd_size == -1)
1282 BufferArg addrlenBuf(addrlenPtr,
sizeof(socklen_t));
1283 *(socklen_t *)addrlenBuf.
bufferPtr() = addrLen;
1292 int tgt_fd,
VPtr<> bufrPtr,
size_t bufrLen,
int flags,
1293 VPtr<> addrPtr, socklen_t addrLen)
1297 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
1300 int sim_fd = sfdp->getSimFD();
1306 struct sockaddr
sa, *sap =
nullptr;
1307 memset(&
sa, 0,
sizeof(sockaddr));
1311 memcpy(&
sa, (sockaddr*)addrBuf.
bufferPtr(), addrLen);
1315 ssize_t sent_size = sendto(sim_fd,
1317 bufrLen, flags, sap, (socklen_t)addrLen);
1319 return (sent_size == -1) ? -errno : sent_size;
1324 int tgt_fd,
VPtr<> msgPtr,
int flags)
1328 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
1331 int sim_fd = sfdp->getSimFD();
1356 BufferArg msgBuf(msgPtr,
sizeof(
struct msghdr));
1358 struct msghdr *msgHdr = (
struct msghdr *)msgBuf.
bufferPtr();
1365 Addr msg_name_phold = 0;
1366 Addr msg_iov_phold = 0;
1367 Addr iovec_base_phold[msgHdr->msg_iovlen];
1368 Addr msg_control_phold = 0;
1374 if (msgHdr->msg_name) {
1375 msg_name_phold = (
Addr)msgHdr->msg_name;
1376 nameBuf =
new BufferArg(msg_name_phold, msgHdr->msg_namelen);
1378 msgHdr->msg_name = nameBuf->
bufferPtr();
1387 BufferArg *iovecBuf[msgHdr->msg_iovlen];
1388 for (
int i = 0;
i < msgHdr->msg_iovlen;
i++) {
1389 iovec_base_phold[
i] = 0;
1393 if (msgHdr->msg_iov) {
1394 msg_iov_phold = (
Addr)msgHdr->msg_iov;
1395 iovBuf =
new BufferArg(msg_iov_phold, msgHdr->msg_iovlen *
1396 sizeof(
struct iovec));
1398 for (
int i = 0;
i < msgHdr->msg_iovlen;
i++) {
1399 if (((
struct iovec *)iovBuf->
bufferPtr())[
i].iov_base) {
1400 iovec_base_phold[
i] =
1403 ((
struct iovec *)iovBuf->
bufferPtr())[
i].iov_len);
1405 ((
struct iovec *)iovBuf->
bufferPtr())[
i].iov_base =
1406 iovecBuf[
i]->bufferPtr();
1409 msgHdr->msg_iov = (
struct iovec *)iovBuf->
bufferPtr();
1416 if (msgHdr->msg_control) {
1417 msg_control_phold = (
Addr)msgHdr->msg_control;
1418 controlBuf =
new BufferArg(msg_control_phold,
1419 CMSG_ALIGN(msgHdr->msg_controllen));
1421 msgHdr->msg_control = controlBuf->
bufferPtr();
1424 ssize_t recvd_size = recvmsg(sim_fd, msgHdr, flags);
1429 if (msgHdr->msg_name) {
1432 msgHdr->msg_name = (
void *)msg_name_phold;
1435 if (msgHdr->msg_iov) {
1436 for (
int i = 0;
i< msgHdr->msg_iovlen;
i++) {
1437 if (((
struct iovec *)iovBuf->
bufferPtr())[
i].iov_base) {
1440 ((
struct iovec *)iovBuf->
bufferPtr())[
i].iov_base =
1441 (
void *)iovec_base_phold[
i];
1446 msgHdr->msg_iov = (
struct iovec *)msg_iov_phold;
1449 if (msgHdr->msg_control) {
1452 msgHdr->msg_control = (
void *)msg_control_phold;
1462 int tgt_fd,
VPtr<> msgPtr,
int flags)
1466 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
1469 int sim_fd = sfdp->getSimFD();
1474 BufferArg msgBuf(msgPtr,
sizeof(
struct msghdr));
1476 struct msghdr msgHdr = *((
struct msghdr *)msgBuf.
bufferPtr());
1482 struct iovec *iovPtr = msgHdr.msg_iov;
1483 BufferArg iovBuf((
Addr)iovPtr,
sizeof(
struct iovec) * msgHdr.msg_iovlen);
1485 struct iovec *iov = (
struct iovec *)iovBuf.
bufferPtr();
1486 msgHdr.msg_iov = iov;
1501 for (
int iovIndex = 0 ; iovIndex < msgHdr.msg_iovlen; iovIndex++) {
1502 Addr basePtr = (
Addr) iov[iovIndex].iov_base;
1503 bufferArray[iovIndex] =
new BufferArg(basePtr, iov[iovIndex].iov_len);
1505 iov[iovIndex].iov_base = bufferArray[iovIndex]->
bufferPtr();
1508 ssize_t sent_size = sendmsg(sim_fd, &msgHdr, flags);
1509 int local_errno = errno;
1514 for (
int iovIndex = 0 ; iovIndex < msgHdr.msg_iovlen; iovIndex++) {
1524 return (sent_size < 0) ? -local_errno : sent_size;
1529 int tgt_fd,
int level,
int optname,
VPtr<> valPtr,
1537 struct linger linger_val;
1538 struct timeval timeval_val;
1543 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
1546 int sim_fd = sfdp->getSimFD();
1548 socklen_t
len =
sizeof(
val);
1573 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
1576 int sim_fd = sfdp->getSimFD();
1582 BufferArg lenBuf(lenPtr,
sizeof(socklen_t));
1610 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
1613 int sim_fd = sfdp->getSimFD();
1615 BufferArg bufAddrlen(addrlenPtr,
sizeof(
unsigned));
1619 int retval = getpeername(sim_fd,
1628 return (retval == -1) ? -errno : retval;
1633 int tgt_fd,
int level,
int optname,
VPtr<> valPtr,
1641 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
1644 int sim_fd = sfdp->getSimFD();