32 #include <sys/syscall.h>
39 #include <unordered_map>
61 warn(
"Cannot invoke %s on host operating system.", syscall_name);
67 fatal(
"syscall %s (#%d) unimplemented.", desc->
name(), desc->
num());
74 warn(
"ignoring syscall %s(...)", desc->
name());
81 static std::unordered_map<SyscallDesc *, bool> bool_map;
83 bool &warned = bool_map[desc];
85 warn(
"ignoring syscall %s(...)\n"
86 " (further warnings will be suppressed)", desc->
name());
115 *
p->exitGroup =
true;
117 if (
p->childClearTID)
120 bool last_thread =
true;
121 Process *parent =
nullptr, *tg_lead =
nullptr;
124 if (!(walk = sys->
threads[
i]->getProcessPtr()))
133 if (walk->
pid() ==
p->tgid())
146 if (walk->
tgid() ==
p->tgid()) {
159 if (*(
p->exitGroup)) {
175 if (*
p->sigchld && (
p->ppid() != 0) && (walk->
pid() ==
p->ppid()))
191 for (
int i = 0;
i <
p->fds->getSize();
i++) {
193 p->fds->closeFDEntry(
i);
201 if (!
p->vforkContexts.empty()) {
213 int activeContexts = 0;
215 activeContexts +=
system->threads.numRunning();
217 if (activeContexts == 0) {
263 std::shared_ptr<MemState> mem_state =
p->memState;
264 Addr brk_point = mem_state->getBrkPoint();
268 if (new_brk == 0 || (new_brk == brk_point))
271 mem_state->updateBrkRegion(brk_point, new_brk);
274 mem_state->getBrkPoint());
276 return mem_state->getBrkPoint();
285 return process->pid();
292 return p->fds->closeFDEntry(tgt_fd);
297 int tgt_fd, uint64_t offs,
int whence)
301 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
304 int sim_fd = ffdp->getSimFD();
306 off_t result = lseek(sim_fd, offs, whence);
308 return (result == (off_t)-1) ? -errno : result;
314 int tgt_fd, uint64_t offset_high, uint32_t offset_low,
315 VPtr<> result_ptr,
int whence)
319 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
322 int sim_fd = ffdp->getSimFD();
324 uint64_t
offset = (offset_high << 32) | offset_low;
326 uint64_t result = lseek(sim_fd,
offset, whence);
329 if (result == (off_t)-1)
332 BufferArg result_buf(result_ptr,
sizeof(result));
333 std::memcpy(result_buf.
bufferPtr(), &result,
sizeof(result));
343 VPtr<> buf_ptr,
int name_len)
353 VPtr<> buf_ptr,
unsigned long size)
360 std::string cwd =
p->tgtCwd;
362 if (cwd.length() >= size) {
366 strncpy((
char *)buf.
bufferPtr(), cwd.c_str(), size);
367 result = cwd.length();
369 if (getcwd((
char *)buf.
bufferPtr(), size)) {
370 result = strlen((
char *)buf.
bufferPtr());
378 return (result == -1) ? -errno : result;
395 path =
p->checkPathRedirect(path);
397 int result = unlink(path.c_str());
398 return (result == -1) ? -errno : result;
406 std::string new_path;
415 path =
p->absolutePath(path,
true);
416 new_path =
p->absolutePath(new_path,
true);
418 int result = link(path.c_str(), new_path.c_str());
419 return (result == -1) ? -errno : result;
427 std::string new_path;
436 path =
p->absolutePath(path,
true);
437 new_path =
p->absolutePath(new_path,
true);
439 int result = symlink(path.c_str(), new_path.c_str());
440 return (result == -1) ? -errno : result;
457 path =
p->checkPathRedirect(path);
459 auto result = mkdir(path.c_str(),
mode);
460 return (result == -1) ? -errno : result;
468 std::string old_name;
472 std::string new_name;
476 return renameImpl(desc, tc, old_name, new_name);
481 std::string old_name, std::string new_name)
486 old_name =
p->checkPathRedirect(old_name);
487 new_name =
p->checkPathRedirect(new_name);
489 int64_t result = rename(old_name.c_str(), new_name.c_str());
490 return (result == -1) ? -errno : result;
496 VPtr<> pathname, int64_t length)
508 int result = truncate(path.c_str(), length);
510 int result = truncate64(path.c_str(), length);
512 return (result == -1) ? -errno : result;
517 int tgt_fd, int64_t length)
521 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
524 int sim_fd = ffdp->getSimFD();
527 int result = ftruncate(sim_fd, length);
529 int result = ftruncate64(sim_fd, length);
531 return (result == -1) ? -errno : result;
540 mode_t oldMask = umask(0);
547 VPtr<> pathname, uint32_t owner, uint32_t group)
553 return chownImpl(desc, tc, path, owner, group);
558 std::string path, uint32_t owner, uint32_t group)
563 uid_t hostOwner = owner;
564 gid_t hostGroup = group;
567 path =
p->checkPathRedirect(path);
569 int result = chown(path.c_str(), hostOwner, hostGroup);
570 return (result == -1) ? -errno : result;
575 int tgt_fd, uint32_t owner, uint32_t group)
579 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*
p->fds)[tgt_fd]);
582 int sim_fd = ffdp->getSimFD();
585 uid_t hostOwner = owner;
586 gid_t hostGroup = group;
588 int result = fchown(sim_fd, hostOwner, hostGroup);
589 return (result == -1) ? -errno : result;
603 auto old_hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[tgt_fd]);
606 int sim_fd = old_hbfdp->getSimFD();
608 int result = dup(sim_fd);
612 auto new_hbfdp = std::dynamic_pointer_cast<HBFDEntry>(old_hbfdp->clone());
613 new_hbfdp->setSimFD(result);
614 new_hbfdp->setCOE(
false);
615 return p->fds->allocFD(new_hbfdp);
622 auto old_hbp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[old_tgt_fd]);
625 int old_sim_fd = old_hbp->getSimFD();
632 int res_fd = dup2(old_sim_fd, open(
"/dev/null", O_RDONLY));
636 auto new_hbp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[new_tgt_fd]);
638 p->fds->closeFDEntry(new_tgt_fd);
639 new_hbp = std::dynamic_pointer_cast<HBFDEntry>(old_hbp->clone());
640 new_hbp->setSimFD(res_fd);
641 new_hbp->setCOE(
false);
643 return p->fds->allocFD(new_hbp);
652 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[tgt_fd]);
655 int sim_fd = hbfdp->getSimFD();
657 int coe = hbfdp->getCOE();
661 return coe & FD_CLOEXEC;
664 int arg = varargs.
get<
int>();
665 arg ? hbfdp->setCOE(
true) : hbfdp->setCOE(
false);
677 int arg = varargs.
get<
int>();
678 int rv = fcntl(sim_fd, cmd, arg);
679 return (rv == -1) ? -errno : rv;
683 warn(
"fcntl: unsupported command %d\n", cmd);
693 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[tgt_fd]);
696 int sim_fd = hbfdp->getSimFD();
700 warn(
"fcntl64(%d, F_GETLK64) not supported, error returned\n", tgt_fd);
705 warn(
"fcntl64(%d, F_SETLK(W)64) not supported, error returned\n",
712 warn(
"fcntl64(%d, %d) passed through to host\n", tgt_fd, cmd);
713 return fcntl(sim_fd, cmd);
734 int sim_fds[2], tgt_fds[2];
736 int pipe_retval = pipe(sim_fds);
737 if (pipe_retval == -1)
740 auto rend = PipeFDEntry::EndType::read;
741 auto rpfd = std::make_shared<PipeFDEntry>(sim_fds[0], O_WRONLY, rend);
742 tgt_fds[0] =
p->fds->allocFD(rpfd);
743 int sim_fd_rpfd = rpfd->getSimFD();
745 auto wend = PipeFDEntry::EndType::write;
746 auto wpfd = std::make_shared<PipeFDEntry>(sim_fds[1], O_RDONLY, wend);
747 tgt_fds[1] =
p->fds->allocFD(wpfd);
748 int sim_fd_wpfd = wpfd->getSimFD();
754 rpfd->setPipeReadSource(tgt_fds[1]);
768 BufferArg tgt_handle(tgt_addr,
sizeof(
int[2]));
769 int *buf_ptr = (
int*)tgt_handle.
bufferPtr();
770 buf_ptr[0] = tgt_fds[0];
771 buf_ptr[1] = tgt_fds[1];
777 if ((
flags != O_CLOEXEC) && (
flags != O_NONBLOCK) &&
778 (
flags != (O_CLOEXEC | O_NONBLOCK))) {
786 if (
flags & O_NONBLOCK) {
793 if (fcntl(sim_fd_rpfd, F_SETFL, O_NONBLOCK)) {
796 if (fcntl(sim_fd_wpfd, F_SETFL, O_NONBLOCK)) {
805 if (
flags & O_CLOEXEC) {
818 return process->
pgid();
830 process->
pgid(process->pid());
838 for (
auto *tc: sysh->
threads) {
843 if (walk_ph && walk_ph->
pid() == process->pid())
844 matched_ph = walk_ph;
849 matched_ph->
pgid((pgid == 0) ? matched_ph->
pid() : pgid);
859 return process->
tgid();
866 return process->
pid();
873 return process->
ppid();
880 return process->
uid();
887 return process->
euid();
894 return process->
gid();
901 return process->
egid();
917 std::string path, mode_t
mode)
921 path =
p->checkPathRedirect(path);
923 int result = access(path.c_str(),
mode);
924 return (result == -1) ? -errno : result;
940 std::string path, mode_t
mode, dev_t dev)
943 path =
p->checkPathRedirect(path);
945 auto result = mknod(path.c_str(),
mode, dev);
946 return (result == -1) ? -errno : result;
962 tgt_cwd = realpath((
p->tgtCwd +
"/" + path).c_str(), buf);
964 std::string host_cwd =
p->checkPathRedirect(tgt_cwd);
966 int result = chdir(host_cwd.c_str());
971 p->hostCwd = host_cwd;
990 path =
p->checkPathRedirect(path);
992 auto result = rmdir(path.c_str());
993 return (result == -1) ? -errno : result;
996 #if defined(SYS_getdents) || defined(SYS_getdents64)
997 template<
typename DE,
int SYS_NUM>
999 getdentsImpl(SyscallDesc *desc, ThreadContext *tc,
1000 int tgt_fd, VPtr<> buf_ptr,
unsigned count)
1002 auto p = tc->getProcessPtr();
1004 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*
p->fds)[tgt_fd]);
1007 int sim_fd = hbfdp->getSimFD();
1009 BufferArg buf_arg(buf_ptr,
count);
1010 auto status = syscall(SYS_NUM, sim_fd, buf_arg.bufferPtr(),
count);
1015 unsigned traversed = 0;
1016 while (traversed <
status) {
1017 DE *buffer = (DE*)((
Addr)buf_arg.bufferPtr() + traversed);
1019 auto host_reclen = buffer->d_reclen;
1026 const ByteOrder
bo = tc->getSystemPtr()->getGuestByteOrder();
1027 buffer->d_ino =
htog(buffer->d_ino,
bo);
1028 buffer->d_off =
htog(buffer->d_off,
bo);
1029 buffer->d_reclen =
htog(buffer->d_reclen,
bo);
1031 traversed += host_reclen;
1034 buf_arg.copyOut(SETranslatingPortProxy(tc));
1039 #if defined(SYS_getdents)
1041 getdentsFunc(SyscallDesc *desc, ThreadContext *tc,
1042 int tgt_fd, VPtr<> buf_ptr,
unsigned count)
1044 typedef struct linux_dirent
1046 unsigned long d_ino;
1047 unsigned long d_off;
1048 unsigned short d_reclen;
1052 return getdentsImpl<LinDent, SYS_getdents>(desc, tc,
1053 tgt_fd, buf_ptr,
count);
1057 #if defined(SYS_getdents64)
1059 getdents64Func(SyscallDesc *desc, ThreadContext *tc,
1060 int tgt_fd, VPtr<> buf_ptr,
unsigned count)
1062 typedef struct linux_dirent64
1066 unsigned short d_reclen;
1070 return getdentsImpl<LinDent64, SYS_getdents64>(desc, tc,
1071 tgt_fd, buf_ptr,
count);
1080 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
1083 int sim_fd = sfdp->getSimFD();
1085 int retval = shutdown(sim_fd, how);
1087 return (retval == -1) ? -errno : retval;
1092 int tgt_fd,
VPtr<> buf_ptr,
int addrlen)
1099 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
1102 int sim_fd = sfdp->getSimFD();
1104 int status = ::bind(sim_fd,
1116 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
1119 int sim_fd = sfdp->getSimFD();
1121 int status = listen(sim_fd, backlog);
1128 int tgt_fd,
VPtr<> buf_ptr,
int addrlen)
1135 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
1138 int sim_fd = sfdp->getSimFD();
1140 int status = connect(sim_fd,
1141 (
struct sockaddr *)
addr.bufferPtr(),
1142 (socklen_t)addrlen);
1154 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
1157 int sim_fd = sfdp->getSimFD();
1184 BufferArg msgBuf(msgPtr,
sizeof(
struct msghdr));
1186 struct msghdr *msgHdr = (
struct msghdr *)msgBuf.
bufferPtr();
1193 Addr msg_name_phold = 0;
1194 Addr msg_iov_phold = 0;
1195 Addr iovec_base_phold[msgHdr->msg_iovlen];
1196 Addr msg_control_phold = 0;
1202 if (msgHdr->msg_name) {
1203 msg_name_phold = (
Addr)msgHdr->msg_name;
1204 nameBuf =
new BufferArg(msg_name_phold, msgHdr->msg_namelen);
1206 msgHdr->msg_name = nameBuf->
bufferPtr();
1215 BufferArg *iovecBuf[msgHdr->msg_iovlen];
1216 for (
int i = 0;
i < msgHdr->msg_iovlen;
i++) {
1217 iovec_base_phold[
i] = 0;
1221 if (msgHdr->msg_iov) {
1222 msg_iov_phold = (
Addr)msgHdr->msg_iov;
1223 iovBuf =
new BufferArg(msg_iov_phold, msgHdr->msg_iovlen *
1224 sizeof(
struct iovec));
1226 for (
int i = 0;
i < msgHdr->msg_iovlen;
i++) {
1227 if (((
struct iovec *)iovBuf->
bufferPtr())[
i].iov_base) {
1228 iovec_base_phold[
i] =
1231 ((
struct iovec *)iovBuf->
bufferPtr())[
i].iov_len);
1233 ((
struct iovec *)iovBuf->
bufferPtr())[
i].iov_base =
1234 iovecBuf[
i]->bufferPtr();
1237 msgHdr->msg_iov = (
struct iovec *)iovBuf->
bufferPtr();
1244 if (msgHdr->msg_control) {
1245 msg_control_phold = (
Addr)msgHdr->msg_control;
1246 controlBuf =
new BufferArg(msg_control_phold,
1247 CMSG_ALIGN(msgHdr->msg_controllen));
1248 controlBuf->
copyIn(proxy);
1249 msgHdr->msg_control = controlBuf->
bufferPtr();
1252 ssize_t recvd_size = recvmsg(sim_fd, msgHdr,
flags);
1257 if (msgHdr->msg_name) {
1260 msgHdr->msg_name = (
void *)msg_name_phold;
1263 if (msgHdr->msg_iov) {
1264 for (
int i = 0;
i< msgHdr->msg_iovlen;
i++) {
1265 if (((
struct iovec *)iovBuf->
bufferPtr())[
i].iov_base) {
1268 ((
struct iovec *)iovBuf->
bufferPtr())[
i].iov_base =
1269 (
void *)iovec_base_phold[
i];
1274 msgHdr->msg_iov = (
struct iovec *)msg_iov_phold;
1277 if (msgHdr->msg_control) {
1280 msgHdr->msg_control = (
void *)msg_control_phold;
1294 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
1297 int sim_fd = sfdp->getSimFD();
1304 BufferArg msgBuf(msgPtr,
sizeof(
struct msghdr));
1306 struct msghdr msgHdr = *((
struct msghdr *)msgBuf.
bufferPtr());
1312 struct iovec *iovPtr = msgHdr.msg_iov;
1313 BufferArg iovBuf((
Addr)iovPtr,
sizeof(
struct iovec) * msgHdr.msg_iovlen);
1315 struct iovec *iov = (
struct iovec *)iovBuf.
bufferPtr();
1316 msgHdr.msg_iov = iov;
1331 for (
int iovIndex = 0 ; iovIndex < msgHdr.msg_iovlen; iovIndex++) {
1332 Addr basePtr = (
Addr) iov[iovIndex].iov_base;
1333 bufferArray[iovIndex] =
new BufferArg(basePtr, iov[iovIndex].iov_len);
1334 bufferArray[iovIndex]->
copyIn(proxy);
1335 iov[iovIndex].iov_base = bufferArray[iovIndex]->
bufferPtr();
1338 ssize_t sent_size = sendmsg(sim_fd, &msgHdr,
flags);
1339 int local_errno = errno;
1344 for (
int iovIndex = 0 ; iovIndex < msgHdr.msg_iovlen; iovIndex++) {
1354 return (sent_size < 0) ? -local_errno : sent_size;
1359 int tgt_fd,
int level,
int optname,
VPtr<> valPtr,
1367 struct linger linger_val;
1368 struct timeval timeval_val;
1373 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
1376 int sim_fd = sfdp->getSimFD();
1378 socklen_t
len =
sizeof(
val);
1405 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
1408 int sim_fd = sfdp->getSimFD();
1416 BufferArg lenBuf(lenPtr,
sizeof(socklen_t));
1444 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
1447 int sim_fd = sfdp->getSimFD();
1451 BufferArg bufAddrlen(addrlenPtr,
sizeof(
unsigned));
1452 bufAddrlen.
copyIn(proxy);
1455 int retval = getpeername(sim_fd,
1464 return (retval == -1) ? -errno : retval;
1469 int tgt_fd,
int level,
int optname,
VPtr<> valPtr,
1477 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*
p->fds)[tgt_fd]);
1480 int sim_fd = sfdp->getSimFD();