32 #include <sys/syscall.h>
39 #include <unordered_map>
41 #include "arch/utility.hh"
44 #include "config/the_isa.hh"
59 warn(
"Cannot invoke %s on host operating system.", syscall_name);
65 fatal(
"syscall %s (#%d) unimplemented.", desc->
name(), desc->
num());
72 warn(
"ignoring syscall %s(...)", desc->
name());
79 static std::unordered_map<SyscallDesc *, bool> bool_map;
81 bool &warned = bool_map[desc];
83 warn(
"ignoring syscall %s(...)\n"
84 " (further warnings will be suppressed)", desc->
name());
113 *
p->exitGroup =
true;
115 if (
p->childClearTID)
118 bool last_thread =
true;
119 Process *parent =
nullptr, *tg_lead =
nullptr;
122 if (!(walk = sys->
threads[
i]->getProcessPtr()))
131 if (walk->
pid() ==
p->tgid())
144 if (walk->
tgid() ==
p->tgid()) {
157 if (*(
p->exitGroup)) {
173 if (*
p->sigchld && (
p->ppid() != 0) && (walk->
pid() ==
p->ppid()))
189 for (
int i = 0;
i <
p->fds->getSize();
i++) {
191 p->fds->closeFDEntry(
i);
201 int activeContexts = 0;
203 activeContexts +=
system->threads.numRunning();
205 if (activeContexts == 0) {
251 std::shared_ptr<MemState> mem_state =
p->memState;
252 Addr brk_point = mem_state->getBrkPoint();
256 if (new_brk == 0 || (new_brk == brk_point))
259 mem_state->updateBrkRegion(brk_point, new_brk);
262 mem_state->getBrkPoint());
264 return mem_state->getBrkPoint();
273 return process->pid();
280 return p->fds->closeFDEntry(tgt_fd);
285 int tgt_fd, uint64_t offs,
int whence)
289 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
292 int sim_fd = ffdp->getSimFD();
294 off_t result = lseek(sim_fd, offs, whence);
296 return (result == (off_t)-1) ? -errno : result;
302 int tgt_fd, uint64_t offset_high, uint32_t offset_low,
303 VPtr<> result_ptr,
int whence)
307 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
310 int sim_fd = ffdp->getSimFD();
312 uint64_t
offset = (offset_high << 32) | offset_low;
314 uint64_t result = lseek(sim_fd,
offset, whence);
317 if (result == (off_t)-1)
320 BufferArg result_buf(result_ptr,
sizeof(result));
321 std::memcpy(result_buf.
bufferPtr(), &result,
sizeof(result));
336 if (
p->pTable->pageOffset(start))
339 length =
roundUp(length,
p->pTable->pageSize());
341 p->memState->unmapRegion(start, length);
351 VPtr<> buf_ptr,
int name_len)
361 VPtr<> buf_ptr,
unsigned long size)
368 std::string cwd =
p->tgtCwd;
370 if (cwd.length() >= size) {
374 strncpy((
char *)buf.
bufferPtr(), cwd.c_str(), size);
375 result = cwd.length();
377 if (getcwd((
char *)buf.
bufferPtr(), size)) {
378 result = strlen((
char *)buf.
bufferPtr());
386 return (result == -1) ? -errno : result;
400 path =
p->checkPathRedirect(path);
405 if (path !=
"/proc/self/exe") {
406 result = readlink(path.c_str(), (
char *)buf.
bufferPtr(), bufsiz);
420 char real_path[PATH_MAX];
421 char *check_real_path = realpath(
p->progName(), real_path);
422 if (!check_real_path) {
423 fatal(
"readlink('/proc/self/exe') unable to resolve path to "
424 "executable: %s",
p->progName());
426 strncpy((
char*)buf.
bufferPtr(), real_path, bufsiz);
427 size_t real_path_len = strlen(real_path);
428 if (real_path_len > bufsiz) {
433 result = real_path_len;
437 warn_once(
"readlink() called on '/proc/self/exe' may yield unexpected "
438 "results in various settings.\n Returning '%s'\n",
444 return (result == -1) ? -errno : result;
456 path =
p->checkPathRedirect(path);
458 int result = unlink(path.c_str());
459 return (result == -1) ? -errno : result;
467 std::string new_path;
471 if (!virt_mem.tryReadString(path, pathname))
473 if (!virt_mem.tryReadString(new_path, new_pathname))
476 path =
p->absolutePath(path,
true);
477 new_path =
p->absolutePath(new_path,
true);
479 int result = link(path.c_str(), new_path.c_str());
480 return (result == -1) ? -errno : result;
488 std::string new_path;
492 if (!virt_mem.tryReadString(path, pathname))
494 if (!virt_mem.tryReadString(new_path, new_pathname))
497 path =
p->absolutePath(path,
true);
498 new_path =
p->absolutePath(new_path,
true);
500 int result = symlink(path.c_str(), new_path.c_str());
501 return (result == -1) ? -errno : result;
512 path =
p->checkPathRedirect(path);
514 auto result = mkdir(path.c_str(),
mode);
515 return (result == -1) ? -errno : result;
524 std::string old_name;
528 std::string new_name;
533 old_name =
p->checkPathRedirect(old_name);
534 new_name =
p->checkPathRedirect(new_name);
536 int64_t result = rename(old_name.c_str(), new_name.c_str());
537 return (result == -1) ? -errno : result;
551 path =
p->checkPathRedirect(path);
553 int result = truncate(path.c_str(), length);
554 return (result == -1) ? -errno : result;
562 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
565 int sim_fd = ffdp->getSimFD();
567 int result = ftruncate(sim_fd, length);
568 return (result == -1) ? -errno : result;
573 VPtr<> pathname, int64_t length)
585 int result = truncate(path.c_str(), length);
587 int result = truncate64(path.c_str(), length);
589 return (result == -1) ? -errno : result;
594 int tgt_fd, int64_t length)
598 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
601 int sim_fd = ffdp->getSimFD();
604 int result = ftruncate(sim_fd, length);
606 int result = ftruncate64(sim_fd, length);
608 return (result == -1) ? -errno : result;
617 mode_t oldMask = umask(0);
624 VPtr<> pathname, uint32_t owner, uint32_t group)
633 uid_t hostOwner = owner;
634 gid_t hostGroup = group;
637 path =
p->checkPathRedirect(path);
639 int result = chown(path.c_str(), hostOwner, hostGroup);
640 return (result == -1) ? -errno : result;
645 int tgt_fd, uint32_t owner, uint32_t group)
649 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
652 int sim_fd = ffdp->getSimFD();
655 uid_t hostOwner = owner;
656 gid_t hostGroup = group;
658 int result = fchown(sim_fd, hostOwner, hostGroup);
659 return (result == -1) ? -errno : result;
673 auto old_hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[tgt_fd]);
676 int sim_fd = old_hbfdp->getSimFD();
678 int result = dup(sim_fd);
682 auto new_hbfdp = std::dynamic_pointer_cast<HBFDEntry>(old_hbfdp->clone());
683 new_hbfdp->setSimFD(result);
684 new_hbfdp->setCOE(
false);
685 return p->fds->allocFD(new_hbfdp);
692 auto old_hbp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[old_tgt_fd]);
695 int old_sim_fd = old_hbp->getSimFD();
702 int res_fd = dup2(old_sim_fd, open(
"/dev/null", O_RDONLY));
706 auto new_hbp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[new_tgt_fd]);
708 p->fds->closeFDEntry(new_tgt_fd);
709 new_hbp = std::dynamic_pointer_cast<HBFDEntry>(old_hbp->clone());
710 new_hbp->setSimFD(res_fd);
711 new_hbp->setCOE(
false);
713 return p->fds->allocFD(new_hbp);
722 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[tgt_fd]);
725 int sim_fd = hbfdp->getSimFD();
727 int coe = hbfdp->getCOE();
731 return coe & FD_CLOEXEC;
734 int arg = varargs.
get<
int>();
735 arg ? hbfdp->setCOE(
true) : hbfdp->setCOE(
false);
747 int arg = varargs.
get<
int>();
748 int rv = fcntl(sim_fd, cmd, arg);
749 return (rv == -1) ? -errno : rv;
753 warn(
"fcntl: unsupported command %d\n", cmd);
763 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[tgt_fd]);
766 int sim_fd = hbfdp->getSimFD();
770 warn(
"fcntl64(%d, F_GETLK64) not supported, error returned\n", tgt_fd);
775 warn(
"fcntl64(%d, F_SETLK(W)64) not supported, error returned\n",
782 warn(
"fcntl64(%d, %d) passed through to host\n", tgt_fd, cmd);
783 return fcntl(sim_fd, cmd);
804 int sim_fds[2], tgt_fds[2];
806 int pipe_retval = pipe(sim_fds);
807 if (pipe_retval == -1)
810 auto rend = PipeFDEntry::EndType::read;
811 auto rpfd = std::make_shared<PipeFDEntry>(sim_fds[0], O_WRONLY, rend);
812 tgt_fds[0] =
p->fds->allocFD(rpfd);
813 int sim_fd_rpfd = rpfd->getSimFD();
815 auto wend = PipeFDEntry::EndType::write;
816 auto wpfd = std::make_shared<PipeFDEntry>(sim_fds[1], O_RDONLY, wend);
817 tgt_fds[1] =
p->fds->allocFD(wpfd);
818 int sim_fd_wpfd = wpfd->getSimFD();
824 rpfd->setPipeReadSource(tgt_fds[1]);
838 BufferArg tgt_handle(tgt_addr,
sizeof(
int[2]));
839 int *buf_ptr = (
int*)tgt_handle.
bufferPtr();
840 buf_ptr[0] = tgt_fds[0];
841 buf_ptr[1] = tgt_fds[1];
847 if ((flags != O_CLOEXEC) && (flags != O_NONBLOCK) &&
848 (flags != (O_CLOEXEC | O_NONBLOCK))) {
856 if (flags & O_NONBLOCK) {
863 if (fcntl(sim_fd_rpfd, F_SETFL, O_NONBLOCK)) {
866 if (fcntl(sim_fd_wpfd, F_SETFL, O_NONBLOCK)) {
875 if (flags & O_CLOEXEC) {
888 return process->
pgid();
900 process->
pgid(process->pid());
908 for (
auto *tc: sysh->
threads) {
913 if (walk_ph && walk_ph->
pid() == process->pid())
914 matched_ph = walk_ph;
919 matched_ph->
pgid((pgid == 0) ? matched_ph->
pid() : pgid);
929 return process->
tgid();
936 return process->
pid();
943 return process->
ppid();
950 return process->
uid();
957 return process->
euid();
964 return process->
gid();
971 return process->
egid();
978 #if defined(__linux__)
981 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
984 int sim_fd = ffdp->getSimFD();
1006 path =
p->checkPathRedirect(path);
1008 int result = access(path.c_str(),
mode);
1009 return (result == -1) ? -errno : result;
1021 path =
p->checkPathRedirect(path);
1023 auto result = mknod(path.c_str(),
mode, dev);
1024 return (result == -1) ? -errno : result;
1035 std::string tgt_cwd;
1040 tgt_cwd = realpath((
p->tgtCwd +
"/" + path).c_str(), buf);
1042 std::string host_cwd =
p->checkPathRedirect(tgt_cwd);
1044 int result = chdir(host_cwd.c_str());
1049 p->hostCwd = host_cwd;
1050 p->tgtCwd = tgt_cwd;
1062 path =
p->checkPathRedirect(path);
1064 auto result = rmdir(path.c_str());
1065 return (result == -1) ? -errno : result;
1068 #if defined(SYS_getdents) || defined(SYS_getdents64)
1069 template<
typename DE,
int SYS_NUM>
1076 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[tgt_fd]);
1079 int sim_fd = hbfdp->getSimFD();
1082 auto status = syscall(SYS_NUM, sim_fd, buf_arg.bufferPtr(),
count);
1087 unsigned traversed = 0;
1088 while (traversed <
status) {
1089 DE *buffer = (DE*)((
Addr)buf_arg.bufferPtr() + traversed);
1091 auto host_reclen = buffer->d_reclen;
1099 buffer->d_ino =
htog(buffer->d_ino,
bo);
1100 buffer->d_off =
htog(buffer->d_off,
bo);
1101 buffer->d_reclen =
htog(buffer->d_reclen,
bo);
1103 traversed += host_reclen;
1111 #if defined(SYS_getdents)
1116 typedef struct linux_dirent {
1117 unsigned long d_ino;
1118 unsigned long d_off;
1119 unsigned short d_reclen;
1123 return getdentsImpl<LinDent, SYS_getdents>(desc, tc,
1124 tgt_fd, buf_ptr,
count);
1128 #if defined(SYS_getdents64)
1133 typedef struct linux_dirent64 {
1136 unsigned short d_reclen;
1140 return getdentsImpl<LinDent64, SYS_getdents64>(desc, tc,
1141 tgt_fd, buf_ptr,
count);
1150 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
1153 int sim_fd = sfdp->getSimFD();
1155 int retval = shutdown(sim_fd, how);
1157 return (retval == -1) ? -errno : retval;
1162 int tgt_fd,
VPtr<> buf_ptr,
int addrlen)
1169 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
1172 int sim_fd = sfdp->getSimFD();
1174 int status = ::bind(sim_fd,
1186 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
1189 int sim_fd = sfdp->getSimFD();
1191 int status = listen(sim_fd, backlog);
1198 int tgt_fd,
VPtr<> buf_ptr,
int addrlen)
1205 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
1208 int sim_fd = sfdp->getSimFD();
1210 int status = connect(sim_fd,
1211 (
struct sockaddr *)
addr.bufferPtr(),
1212 (socklen_t)addrlen);
1219 int tgt_fd,
VPtr<> bufrPtr,
size_t bufrLen,
int flags,
1224 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
1227 int sim_fd = sfdp->getSimFD();
1233 socklen_t addrLen = 0;
1234 if (addrlenPtr != 0) {
1236 BufferArg addrlenBuf(addrlenPtr,
sizeof(socklen_t));
1238 addrLen = *((socklen_t *)addrlenBuf.
bufferPtr());
1241 struct sockaddr
sa, *sap = NULL;
1245 memcpy(&
sa, (
struct sockaddr *)addrBuf.
bufferPtr(),
1246 sizeof(
struct sockaddr));
1250 ssize_t recvd_size = recvfrom(sim_fd,
1252 bufrLen, flags, sap, (socklen_t *)&addrLen);
1254 if (recvd_size == -1)
1269 BufferArg addrlenBuf(addrlenPtr,
sizeof(socklen_t));
1270 *(socklen_t *)addrlenBuf.
bufferPtr() = addrLen;
1279 int tgt_fd,
VPtr<> bufrPtr,
size_t bufrLen,
int flags,
1280 VPtr<> addrPtr, socklen_t addrLen)
1284 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
1287 int sim_fd = sfdp->getSimFD();
1293 struct sockaddr
sa, *sap =
nullptr;
1294 memset(&
sa, 0,
sizeof(sockaddr));
1298 memcpy(&
sa, (sockaddr*)addrBuf.
bufferPtr(), addrLen);
1302 ssize_t sent_size = sendto(sim_fd,
1304 bufrLen, flags, sap, (socklen_t)addrLen);
1306 return (sent_size == -1) ? -errno : sent_size;
1311 int tgt_fd,
VPtr<> msgPtr,
int flags)
1315 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
1318 int sim_fd = sfdp->getSimFD();
1343 BufferArg msgBuf(msgPtr,
sizeof(
struct msghdr));
1345 struct msghdr *msgHdr = (
struct msghdr *)msgBuf.
bufferPtr();
1352 Addr msg_name_phold = 0;
1353 Addr msg_iov_phold = 0;
1354 Addr iovec_base_phold[msgHdr->msg_iovlen];
1355 Addr msg_control_phold = 0;
1361 if (msgHdr->msg_name) {
1362 msg_name_phold = (
Addr)msgHdr->msg_name;
1363 nameBuf =
new BufferArg(msg_name_phold, msgHdr->msg_namelen);
1365 msgHdr->msg_name = nameBuf->
bufferPtr();
1374 BufferArg *iovecBuf[msgHdr->msg_iovlen];
1375 for (
int i = 0;
i < msgHdr->msg_iovlen;
i++) {
1376 iovec_base_phold[
i] = 0;
1380 if (msgHdr->msg_iov) {
1381 msg_iov_phold = (
Addr)msgHdr->msg_iov;
1382 iovBuf =
new BufferArg(msg_iov_phold, msgHdr->msg_iovlen *
1383 sizeof(
struct iovec));
1385 for (
int i = 0;
i < msgHdr->msg_iovlen;
i++) {
1386 if (((
struct iovec *)iovBuf->
bufferPtr())[
i].iov_base) {
1387 iovec_base_phold[
i] =
1390 ((
struct iovec *)iovBuf->
bufferPtr())[
i].iov_len);
1392 ((
struct iovec *)iovBuf->
bufferPtr())[
i].iov_base =
1393 iovecBuf[
i]->bufferPtr();
1396 msgHdr->msg_iov = (
struct iovec *)iovBuf->
bufferPtr();
1403 if (msgHdr->msg_control) {
1404 msg_control_phold = (
Addr)msgHdr->msg_control;
1405 controlBuf =
new BufferArg(msg_control_phold,
1406 CMSG_ALIGN(msgHdr->msg_controllen));
1408 msgHdr->msg_control = controlBuf->
bufferPtr();
1411 ssize_t recvd_size = recvmsg(sim_fd, msgHdr, flags);
1416 if (msgHdr->msg_name) {
1419 msgHdr->msg_name = (
void *)msg_name_phold;
1422 if (msgHdr->msg_iov) {
1423 for (
int i = 0;
i< msgHdr->msg_iovlen;
i++) {
1424 if (((
struct iovec *)iovBuf->
bufferPtr())[
i].iov_base) {
1427 ((
struct iovec *)iovBuf->
bufferPtr())[
i].iov_base =
1428 (
void *)iovec_base_phold[
i];
1433 msgHdr->msg_iov = (
struct iovec *)msg_iov_phold;
1436 if (msgHdr->msg_control) {
1439 msgHdr->msg_control = (
void *)msg_control_phold;
1449 int tgt_fd,
VPtr<> msgPtr,
int flags)
1453 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
1456 int sim_fd = sfdp->getSimFD();
1461 BufferArg msgBuf(msgPtr,
sizeof(
struct msghdr));
1463 struct msghdr msgHdr = *((
struct msghdr *)msgBuf.
bufferPtr());
1469 struct iovec *iovPtr = msgHdr.msg_iov;
1470 BufferArg iovBuf((
Addr)iovPtr,
sizeof(
struct iovec) * msgHdr.msg_iovlen);
1472 struct iovec *iov = (
struct iovec *)iovBuf.
bufferPtr();
1473 msgHdr.msg_iov = iov;
1488 for (
int iovIndex = 0 ; iovIndex < msgHdr.msg_iovlen; iovIndex++) {
1489 Addr basePtr = (
Addr) iov[iovIndex].iov_base;
1490 bufferArray[iovIndex] =
new BufferArg(basePtr, iov[iovIndex].iov_len);
1492 iov[iovIndex].iov_base = bufferArray[iovIndex]->
bufferPtr();
1495 ssize_t sent_size = sendmsg(sim_fd, &msgHdr, flags);
1496 int local_errno = errno;
1501 for (
int iovIndex = 0 ; iovIndex < msgHdr.msg_iovlen; iovIndex++) {
1511 return (sent_size < 0) ? -local_errno : sent_size;
1516 int tgt_fd,
int level,
int optname,
VPtr<> valPtr,
1523 struct linger linger_val;
1524 struct timeval timeval_val;
1529 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
1532 int sim_fd = sfdp->getSimFD();
1534 socklen_t
len =
sizeof(
val);
1559 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
1562 int sim_fd = sfdp->getSimFD();
1568 BufferArg lenBuf(lenPtr,
sizeof(socklen_t));
1596 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
1599 int sim_fd = sfdp->getSimFD();
1601 BufferArg bufAddrlen(addrlenPtr,
sizeof(
unsigned));
1605 int retval = getpeername(sim_fd,
1614 return (retval == -1) ? -errno : retval;
1619 int tgt_fd,
int level,
int optname,
VPtr<> valPtr,
1627 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
1630 int sim_fd = sfdp->getSimFD();