diff --git a/Source/Interface/HLE/FileManagement.cpp b/Source/Interface/HLE/FileManagement.cpp index 7ed45f31e..dc158cdfa 100644 --- a/Source/Interface/HLE/FileManagement.cpp +++ b/Source/Interface/HLE/FileManagement.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -22,16 +23,25 @@ public: } ssize_t writev(int fd, void *iov, int iovcnt) override { - iovec *iovObject = reinterpret_cast(iov); + struct Object { + void *iov_base; + size_t iov_len; + }; + Object *iovObject = reinterpret_cast(iov); if (CTX->Config.AccurateSTDOut) { - std::vector HostStructs(iovcnt); - for (int i = 0; i < iovcnt; ++i) { - HostStructs[i].iov_base = CTX->MemoryMapper.GetPointer(reinterpret_cast(iovObject[i].iov_base)); - HostStructs[i].iov_len = iovObject[i].iov_len; + if (CTX->Config.UnifiedMemory) { + return ::writev(fd, reinterpret_cast(iov), iovcnt); } + else { + std::vector HostStructs(iovcnt); + for (int i = 0; i < iovcnt; ++i) { + HostStructs[i].iov_base = CTX->MemoryMapper.GetPointer(reinterpret_cast(iovObject[i].iov_base)); + HostStructs[i].iov_len = iovObject[i].iov_len; + } - return ::writev(fd, &HostStructs.at(0), iovcnt); + return ::writev(fd, &HostStructs.at(0), iovcnt); + } } else { ssize_t FinalSize {}; @@ -39,7 +49,12 @@ public: for (int i = 0; i < iovcnt; ++i) { const char *String{}; - String = CTX->MemoryMapper.GetPointer(reinterpret_cast(iovObject[i].iov_base)); + if (CTX->Config.UnifiedMemory) { + String = reinterpret_cast(iovObject[i].iov_base); + } + else { + String = CTX->MemoryMapper.GetPointer(reinterpret_cast(iovObject[i].iov_base)); + } for (size_t j = 0; j < iovObject[i].iov_len; ++j) { OutputString += String[j]; } @@ -48,10 +63,11 @@ public: OutputString += '\0'; - if (FDOffset == STDOUT_FILENO) - LogMan::Msg::OUT("[%ld] %s", FinalSize, OutputString.c_str()); - else if (FDOffset == STDERR_FILENO) + if (FDOffset == STDERR_FILENO) LogMan::Msg::ERR("[%ld] %s", FinalSize, OutputString.c_str()); + else + LogMan::Msg::OUT("[%ld] %s", FinalSize, OutputString.c_str()); + return FinalSize; } } @@ -61,10 +77,10 @@ public: return ::write(fd, buf, count); } else { - if (FDOffset == STDOUT_FILENO) - LogMan::Msg::OUT("%s", reinterpret_cast(buf)); - else if (FDOffset == STDERR_FILENO) + if (FDOffset == STDERR_FILENO) LogMan::Msg::ERR("%s", reinterpret_cast(buf)); + else + LogMan::Msg::OUT("%s", reinterpret_cast(buf)); return count; } } @@ -90,16 +106,34 @@ public: }; +class TimerFD final : public FD { +public: + TimerFD(FEXCore::Context::Context *ctx, int32_t fd, int32_t clockid, int32_t flags) + : FD (ctx, fd, "Timer", 0, 0) { + HostFD = timerfd_create(clockid, flags); + } + +}; + uint64_t FD::read(int fd, void *buf, size_t count) { return ::read(HostFD, buf, count); } ssize_t FD::writev(int fd, void *iov, int iovcnt) { + if (CTX->Config.UnifiedMemory) { + return ::writev(HostFD, reinterpret_cast(iov), iovcnt); + } + const struct iovec *Guestiov = reinterpret_cast(iov); std::vector Hostiov; Hostiov.resize(iovcnt); for (int i = 0; i < iovcnt; ++i) { - Hostiov[i].iov_base = CTX->MemoryMapper.GetPointer(reinterpret_cast(Guestiov[i].iov_base)); + if (CTX->Config.UnifiedMemory) { + Hostiov[i].iov_base = reinterpret_cast(Guestiov[i].iov_base); + } + else { + Hostiov[i].iov_base = CTX->MemoryMapper.GetPointer(reinterpret_cast(Guestiov[i].iov_base)); + } Hostiov[i].iov_len = Guestiov[i].iov_len; } @@ -224,7 +258,7 @@ uint64_t FileManager::Fstat(int fd, void *buf) { } } - LogMan::Msg::D("Attempting to stat: %d", fd); + LogMan::Msg::D("Attempting to fstat: %d", fd); return -1LL; } @@ -272,6 +306,20 @@ uint64_t FileManager::Access(const char *pathname, [[maybe_unused]] int mode) { return Result; } +uint64_t FileManager::FAccessat(int dirfd, const char *pathname, int mode, int flags) { + auto Path = GetEmulatedPath(pathname); + if (!Path.empty()) { + uint64_t Result = ::faccessat(dirfd, Path.c_str(), mode, flags); + if (Result != -1) + return Result; + } + + int Result = ::faccessat(dirfd, pathname, mode, flags); + if (Result == -1) + return -errno; + return Result; +} + uint64_t FileManager::Pipe(int pipefd[2]) { int HostFD[2]; int Result = ::pipe(HostFD); @@ -331,6 +379,22 @@ uint64_t FileManager::Readlink(const char *pathname, char *buf, size_t bufsiz) { return ::readlink(pathname, buf, bufsiz); } +uint64_t FileManager::Readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz) { + if (strcmp(pathname, "/proc/self/exe") == 0) { + strncpy(buf, Filename.c_str(), bufsiz); + return std::min(bufsiz, Filename.size()); + } + + auto Path = GetEmulatedPath(pathname); + if (!Path.empty()) { + uint64_t Result = ::readlinkat(dirfd, Path.c_str(), buf, bufsiz); + if (Result != -1) + return Result; + } + + return ::readlinkat(dirfd, pathname, buf, bufsiz); +} + uint64_t FileManager::Openat([[maybe_unused]] int dirfs, const char *pathname, int flags, uint32_t mode) { int32_t fd = CurrentFDOffset; if (!strcmp(pathname, "/dev/tty")) { @@ -353,7 +417,7 @@ uint64_t FileManager::Openat([[maybe_unused]] int dirfs, const char *pathname, i if (Result == -1) { delete fdPtr; - return -1; + return -errno; } } @@ -368,7 +432,12 @@ uint64_t FileManager::Ioctl(int fd, uint64_t request, void *args) { return -1; } - return FD->second->ioctl(fd, request, args); + uint64_t Result = FD->second->ioctl(fd, request, args); + if (Result == -1) { + return -errno; + } + + return Result; } uint64_t FileManager::GetDents(int fd, void *dirp, uint32_t count) { @@ -495,7 +564,8 @@ uint64_t FileManager::Recvfrom(int sockfd, void *buf, size_t len, int flags, str } uint64_t FileManager::Sendmsg(int sockfd, const struct msghdr *msg, int flags) { - auto FD = FDMap.find(sockfd); + LogMan::Throw::A(!CTX->Config.UnifiedMemory, "Not yet supported"); + auto FD = FDMap.find(sockfd); if (FD == FDMap.end()) { return -1; } @@ -531,38 +601,67 @@ uint64_t FileManager::Sendmsg(int sockfd, const struct msghdr *msg, int flags) { } uint64_t FileManager::Recvmsg(int sockfd, struct msghdr *msg, int flags) { - auto FD = FDMap.find(sockfd); + auto FD = FDMap.find(sockfd); if (FD == FDMap.end()) { return -1; } - std::vector Hostvec; - struct msghdr Hosthdr; - memcpy(&Hosthdr, msg, sizeof(struct msghdr)); + int Result{}; + if (CTX->Config.UnifiedMemory) { + Result = recvmsg(FD->second->GetHostFD(), msg, flags); + } + else { + std::vector Hostvec; + struct msghdr Hosthdr; + memcpy(&Hosthdr, msg, sizeof(struct msghdr)); - if (Hosthdr.msg_name) - Hosthdr.msg_name = CTX->MemoryMapper.GetPointer(reinterpret_cast(Hosthdr.msg_name)); + if (Hosthdr.msg_name) + Hosthdr.msg_name = CTX->MemoryMapper.GetPointer(reinterpret_cast(Hosthdr.msg_name)); - if (Hosthdr.msg_control) - Hosthdr.msg_control = CTX->MemoryMapper.GetPointer(reinterpret_cast(Hosthdr.msg_control)); + if (Hosthdr.msg_control) + Hosthdr.msg_control = CTX->MemoryMapper.GetPointer(reinterpret_cast(Hosthdr.msg_control)); - Hostvec.resize(Hosthdr.msg_iovlen); + Hostvec.resize(Hosthdr.msg_iovlen); - struct iovec *Guestiov = CTX->MemoryMapper.GetPointer(reinterpret_cast(Hosthdr.msg_iov)); - for (int i = 0; i < Hosthdr.msg_iovlen; ++i) { - Hostvec[i].iov_base = CTX->MemoryMapper.GetPointer(reinterpret_cast(Guestiov[i].iov_base)); - Hostvec[i].iov_len = Guestiov[i].iov_len; + struct iovec *Guestiov = CTX->MemoryMapper.GetPointer(reinterpret_cast(Hosthdr.msg_iov)); + for (int i = 0; i < Hosthdr.msg_iovlen; ++i) { + Hostvec[i].iov_base = CTX->MemoryMapper.GetPointer(reinterpret_cast(Guestiov[i].iov_base)); + Hostvec[i].iov_len = Guestiov[i].iov_len; + } + + Hosthdr.msg_iov = &Hostvec.at(0); + + Result = recvmsg(FD->second->GetHostFD(), &Hosthdr, flags); } - Hosthdr.msg_iov = &Hostvec.at(0); - - int Result = recvmsg(FD->second->GetHostFD(), &Hosthdr, flags); if (Result == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK) { return -errno; } } + + if (msg->msg_control && msg->msg_controllen > 0) { + // Handle the Linux ancillary data + struct cmsghdr *cmsg = reinterpret_cast(msg->msg_control); + switch (cmsg->cmsg_type) { + case SCM_RIGHTS: { + uint32_t *HostFDs = reinterpret_cast(CMSG_DATA(cmsg)); + uint32_t NumFiles = (msg->msg_controllen - cmsg->cmsg_len) / sizeof(uint32_t); + for (size_t i = 0; i < NumFiles; ++i) { + int32_t fd = CurrentFDOffset; + auto fdPtr = new FEXCore::FD{CTX, fd, "", 0, 0}; + fdPtr->SetHostFD(HostFDs[i]); + FDMap[CurrentFDOffset++] = fdPtr; + + // Remap host FD to guest + HostFDs[i] = fd; + } + break; + } + default: LogMan::Msg::A("Unhandled Ancillary socket type: 0x%x", cmsg->cmsg_type); break; + } + } return Result; } @@ -685,6 +784,8 @@ uint64_t FileManager::Select(int nfds, fd_set *readfds, fd_set *writefds, fd_set } uint64_t FileManager::Sendmmsg(int sockfd, struct mmsghdr *msgvec, uint32_t vlen, int flags) { + LogMan::Throw::A(!CTX->Config.UnifiedMemory, "Not yet supported"); + auto FD = FDMap.find(sockfd); if (FD == FDMap.end()) { return -1; @@ -730,6 +831,22 @@ uint64_t FileManager::Sendmmsg(int sockfd, struct mmsghdr *msgvec, uint32_t vlen return Result; } +uint64_t FileManager::Timer_Create(int32_t clockid, int32_t flags) { + int32_t fd = CurrentFDOffset; + + auto fdPtr = new TimerFD{CTX, fd, clockid, flags}; + + auto Result = fdPtr->GetHostFD(); + if (Result == -1) { + delete fdPtr; + return -errno; + } + + FDMap[CurrentFDOffset++] = fdPtr; + + return fd; +} + int32_t FileManager::FindHostFD(int fd) { auto FD = FDMap.find(fd); if (FD == FDMap.end()) { @@ -757,6 +874,7 @@ int32_t FileManager::DupFD(int prevFD, int newFD) { int32_t fd = CurrentFDOffset; auto fdPtr = new FD{prevFDClass->second, fd}; + fdPtr->SetHostFD(newFD); FDMap[CurrentFDOffset++] = fdPtr; return fd; diff --git a/Source/Interface/HLE/FileManagement.h b/Source/Interface/HLE/FileManagement.h index 9e43ff40c..6acd9b8a8 100644 --- a/Source/Interface/HLE/FileManagement.h +++ b/Source/Interface/HLE/FileManagement.h @@ -77,9 +77,11 @@ public: uint64_t Lseek(int fd, uint64_t offset, int whence); uint64_t Writev(int fd, void *iov, int iovcnt); uint64_t Access(const char *pathname, int mode); + uint64_t FAccessat(int dirfd, const char *pathname, int mode, int flags); uint64_t Pipe(int pipefd[2]); uint64_t Pipe2(int pipefd[2], int flags); uint64_t Readlink(const char *pathname, char *buf, size_t bufsiz); + uint64_t Readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz); uint64_t Openat(int dirfs, const char *pathname, int flags, uint32_t mode); uint64_t Ioctl(int fd, uint64_t request, void *args); uint64_t GetDents(int fd, void *dirp, uint32_t count); @@ -111,6 +113,9 @@ public: uint64_t Select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); uint64_t Sendmmsg(int sockfd, struct mmsghdr *msgvec, uint32_t vlen, int flags); + // Timers + uint64_t Timer_Create(int32_t clockid, int32_t flags); + int32_t FindHostFD(int fd); FD const* GetFDBacking(int fd); diff --git a/Source/Interface/HLE/Syscalls.cpp b/Source/Interface/HLE/Syscalls.cpp index d4ba0870f..1678e5b9f 100644 --- a/Source/Interface/HLE/Syscalls.cpp +++ b/Source/Interface/HLE/Syscalls.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include constexpr uint64_t PAGE_SIZE = 4096; @@ -76,7 +77,7 @@ void SyscallHandler::Strace(FEXCore::HLE::SyscallArguments *Args, uint64_t Ret) switch (Args->Argument[0]) { case SYSCALL_BRK: LogMan::Msg::D("brk(%p) = 0x%lx", Args->Argument[1], Ret); break; case SYSCALL_ACCESS: - LogMan::Msg::D("access(\"%s\", %d) = %ld", CTX->MemoryMapper.GetPointer(Args->Argument[1]), Args->Argument[2], Ret); + LogMan::Msg::D("access(\"%s\", %d) = %ld", GetPointer(Args->Argument[1]), Args->Argument[2], Ret); break; case SYSCALL_PIPE: LogMan::Msg::D("pipe({...}) = %ld", Ret); @@ -101,34 +102,79 @@ void SyscallHandler::Strace(FEXCore::HLE::SyscallArguments *Args, uint64_t Ret) Args->Argument[3], Ret); break; + case SYSCALL_SHMGET: + LogMan::Msg::D("shmget(0x%lx, 0x%lx, 0x%lx) = %ld", + Args->Argument[1], + Args->Argument[2], + Args->Argument[3], + Ret); + break; + case SYSCALL_SHMAT: + LogMan::Msg::D("shmat(0x%lx, 0x%lx, 0x%lx) = %lx", + Args->Argument[1], + Args->Argument[2], + Args->Argument[3], + Ret); + break; + case SYSCALL_SHMCTL: + LogMan::Msg::D("shmctl(0x%lx, 0x%lx, 0x%lx) = %ld", + Args->Argument[1], + Args->Argument[2], + Args->Argument[3], + Ret); + break; + case SYSCALL_DUP2: + LogMan::Msg::D("dup2(0x%lx, 0x%lx) = %ld", + Args->Argument[1], + Args->Argument[2], + Ret); + break; case SYSCALL_NANOSLEEP: LogMan::Msg::D("nanosleep(0x%ld, 0x%lx) = %ld", Args->Argument[1], Args->Argument[2], Ret); break; + case SYSCALL_GETITIMER: + LogMan::Msg::D("getitimer(0x%ld, 0x%lx) = %ld", + Args->Argument[1], + Args->Argument[2], + Ret); + break; case SYSCALL_ALARM: LogMan::Msg::D("alarm(%ld) = %ld", Args->Argument[1], Ret); break; + case SYSCALL_SETITIMER: + LogMan::Msg::D("setitimer(0x%ld, 0x%lx) = %ld", + Args->Argument[1], + Args->Argument[2], + Ret); + break; case SYSCALL_OPENAT: - LogMan::Msg::D("openat(%ld, \"%s\", %d) = %ld", Args->Argument[1], CTX->MemoryMapper.GetPointer(Args->Argument[2]), Args->Argument[3], Ret); + LogMan::Msg::D("openat(%ld, \"%s\", %d) = %ld", Args->Argument[1], GetPointer(Args->Argument[2]), Args->Argument[3], Ret); + break; + case SYSCALL_READLINKAT: + LogMan::Msg::D("readlinkat(\"%s\") = %ld", GetPointer(Args->Argument[2]), Ret); + break; + case SYSCALL_FACCESSAT: + LogMan::Msg::D("faccessat(\"%s\", %d) = %ld", GetPointer(Args->Argument[2]), Args->Argument[3], Ret); break; case SYSCALL_STAT: - LogMan::Msg::D("stat(\"%s\", {...}) = %ld", CTX->MemoryMapper.GetPointer(Args->Argument[1]), Ret); + LogMan::Msg::D("stat(\"%s\", {...}) = %ld", GetPointer(Args->Argument[1]), Ret); break; case SYSCALL_FSTAT: LogMan::Msg::D("fstat(%ld, {...}) = %ld", Args->Argument[1], Ret); break; case SYSCALL_LSTAT: - LogMan::Msg::D("lstat(\"%s\", {...}) = %ld", CTX->MemoryMapper.GetPointer(Args->Argument[1]), Ret); + LogMan::Msg::D("lstat(\"%s\", {...}) = %ld", GetPointer(Args->Argument[1]), Ret); break; case SYSCALL_POLL: LogMan::Msg::D("poll(0x%lx, %ld, %ld) = %ld", Args->Argument[1], Args->Argument[2], Args->Argument[3], Ret); break; case SYSCALL_MMAP: - LogMan::Msg::D("mmap(%p, %ld, %ld, %ld, %d, %p) = %p", Args->Argument[1], Args->Argument[2], Args->Argument[3], Args->Argument[4], static_cast(Args->Argument[5]), Args->Argument[6], Ret); + LogMan::Msg::D("mmap(%p, 0x%lx, %ld, %lx, %d, %p) = %p", Args->Argument[1], Args->Argument[2], Args->Argument[3], Args->Argument[4], static_cast(Args->Argument[5]), Args->Argument[6], Ret); break; case SYSCALL_CLOSE: LogMan::Msg::D("close(%ld) = %ld", Args->Argument[1], Ret); @@ -144,7 +190,7 @@ void SyscallHandler::Strace(FEXCore::HLE::SyscallArguments *Args, uint64_t Ret) Ret); break; case SYSCALL_ARCH_PRCTL: - LogMan::Msg::D("arch_prctl(%ld, %p) = %ld", Args->Argument[1], Args->Argument[2], Ret); + LogMan::Msg::D("arch_prctl(0x%lx, %p) = %ld", Args->Argument[1], Args->Argument[2], Ret); break; case SYSCALL_MPROTECT: LogMan::Msg::D("mprotect(%p, %ld, %ld) = %ld", Args->Argument[1], Args->Argument[2], Args->Argument[3], Ret); @@ -155,6 +201,9 @@ void SyscallHandler::Strace(FEXCore::HLE::SyscallArguments *Args, uint64_t Ret) case SYSCALL_UNAME: LogMan::Msg::D("uname ({...}) = %ld", Ret); break; + case SYSCALL_SHMDT: + LogMan::Msg::D("shmdt(%p)= %ld", Args->Argument[1], Ret); + break; case SYSCALL_FCNTL: LogMan::Msg::D("fcntl (%ld, %ld, 0x%lx) = %ld", Args->Argument[1], Args->Argument[2], Args->Argument[3], Ret); break; @@ -168,19 +217,19 @@ void SyscallHandler::Strace(FEXCore::HLE::SyscallArguments *Args, uint64_t Ret) LogMan::Msg::D("sysinfo(0x%lx) = %ld", Args->Argument[1], Ret); break; case SYSCALL_GETCWD: - LogMan::Msg::D("getcwd(\"%s\", %ld) = %ld", CTX->MemoryMapper.GetPointer(Args->Argument[1]), Args->Argument[2], Ret); + LogMan::Msg::D("getcwd(\"%s\", %ld) = %ld", GetPointer(Args->Argument[1]), Args->Argument[2], Ret); break; case SYSCALL_CHDIR: - LogMan::Msg::D("chdir(\"%s\") = %ld", CTX->MemoryMapper.GetPointer(Args->Argument[1]), Ret); + LogMan::Msg::D("chdir(\"%s\") = %ld", GetPointer(Args->Argument[1]), Ret); break; case SYSCALL_MKDIR: - LogMan::Msg::D("mkdir(\"%s\", 0x%lx) = %ld", CTX->MemoryMapper.GetPointer(Args->Argument[1]), Args->Argument[2], Ret); + LogMan::Msg::D("mkdir(\"%s\", 0x%lx) = %ld", GetPointer(Args->Argument[1]), Args->Argument[2], Ret); break; case SYSCALL_RMDIR: - LogMan::Msg::D("rmdir(\"%s\", 0x%lx) = %ld", CTX->MemoryMapper.GetPointer(Args->Argument[1]), Args->Argument[2], Ret); + LogMan::Msg::D("rmdir(\"%s\", 0x%lx) = %ld", GetPointer(Args->Argument[1]), Args->Argument[2], Ret); break; case SYSCALL_UNLINK: - LogMan::Msg::D("unlink(\"%s\", 0x%lx) = %ld", CTX->MemoryMapper.GetPointer(Args->Argument[1]), Ret); + LogMan::Msg::D("unlink(\"%s\", 0x%lx) = %ld", GetPointer(Args->Argument[1]), Ret); break; case SYSCALL_EXIT: LogMan::Msg::D("exit(0x%lx)", Args->Argument[1]); @@ -203,6 +252,9 @@ void SyscallHandler::Strace(FEXCore::HLE::SyscallArguments *Args, uint64_t Ret) case SYSCALL_SET_ROBUST_LIST: LogMan::Msg::D("set_robust_list(%p, %ld) = %ld", Args->Argument[1], Args->Argument[2], Ret); break; + case SYSCALL_TIMERFD_CREATE: + LogMan::Msg::D("timerfd_create(%lx, %lx) = %ld", Args->Argument[1], Args->Argument[2], Ret); + break; case SYSCALL_EVENTFD: LogMan::Msg::D("eventfd(%lx, %ld) = %ld", Args->Argument[1], Args->Argument[2], Ret); break; @@ -317,13 +369,16 @@ void SyscallHandler::Strace(FEXCore::HLE::SyscallArguments *Args, uint64_t Ret) case SYSCALL_SETRESGID: LogMan::Msg::D("setresgid(%ld, %ld, %ld) = %ld", Args->Argument[1], Args->Argument[2], Args->Argument[3], Ret); break; + case SYSCALL_SIGALTSTACK: + LogMan::Msg::D("sigaltstack(%lx, %lx) = %ld", Args->Argument[1], Args->Argument[2], Ret); + break; case SYSCALL_MKNOD: - LogMan::Msg::D("mknod(\"%s\", %ld, %ld) = %ld", CTX->MemoryMapper.GetPointer(Args->Argument[1]), + LogMan::Msg::D("mknod(\"%s\", %ld, %ld) = %ld", GetPointer(Args->Argument[1]), Args->Argument[2], Args->Argument[3], Ret); break; case SYSCALL_STATFS: - LogMan::Msg::D("statfs(\"%s\", {...}) = %ld", CTX->MemoryMapper.GetPointer(Args->Argument[1]), Ret); + LogMan::Msg::D("statfs(\"%s\", {...}) = %ld", GetPointer(Args->Argument[1]), Ret); break; case SYSCALL_GETTID: LogMan::Msg::D("gettid() = %ld", Ret); @@ -335,7 +390,7 @@ void SyscallHandler::Strace(FEXCore::HLE::SyscallArguments *Args, uint64_t Ret) LogMan::Msg::D("lseek(%ld, %ld, %ld) = %ld", Args->Argument[1], Args->Argument[2], Args->Argument[3], Ret); break; case SYSCALL_IOCTL: - LogMan::Msg::D("ioctl(%ld, %ld, %p) = %ld", Args->Argument[1], Args->Argument[2], Args->Argument[3], Ret); + LogMan::Msg::D("ioctl(%ld, 0x%lx, %p) = %ld", Args->Argument[1], Args->Argument[2], Args->Argument[3], Ret); break; case SYSCALL_PREAD64: LogMan::Msg::D("pread64(%ld, 0x%lx, %ld, %ld) = %ld", Args->Argument[1], Args->Argument[2], Args->Argument[3], Args->Argument[4], Ret); @@ -353,6 +408,13 @@ void SyscallHandler::Strace(FEXCore::HLE::SyscallArguments *Args, uint64_t Ret) Args->Argument[6], Ret); break; + case SYSCALL_SCHED_GETAFFINITY: + LogMan::Msg::D("sched_getaffinity(%ld, %ld, %ld, 0x%lx) = %ld", + Args->Argument[1], + Args->Argument[2], + Args->Argument[3], + Ret); + break; case SYSCALL_CLOCK_GETTIME: LogMan::Msg::D("clock_gettime(%ld, %p) = %ld", Args->Argument[1], Args->Argument[2], Ret); break; @@ -360,7 +422,7 @@ void SyscallHandler::Strace(FEXCore::HLE::SyscallArguments *Args, uint64_t Ret) LogMan::Msg::D("clock_getres(%ld, %p) = %ld", Args->Argument[1], Args->Argument[2], Ret); break; case SYSCALL_READLINK: - LogMan::Msg::D("readlink(\"%s\") = %ld", CTX->MemoryMapper.GetPointer(Args->Argument[1]), Ret); + LogMan::Msg::D("readlink(\"%s\") = %ld", GetPointer(Args->Argument[1]), Ret); break; case SYSCALL_GETRANDOM: LogMan::Msg::D("getrandom(0x%lx, 0x%lx, 0x%lx) = %ld", @@ -372,7 +434,7 @@ void SyscallHandler::Strace(FEXCore::HLE::SyscallArguments *Args, uint64_t Ret) case SYSCALL_STATX: LogMan::Msg::D("statx(%ld, \"%s\", 0x%lx, 0x%lx, {...}) = %ld", Args->Argument[1], - CTX->MemoryMapper.GetPointer(Args->Argument[2]), + GetPointer(Args->Argument[2]), Args->Argument[3], Args->Argument[4], Ret); break; @@ -382,15 +444,42 @@ void SyscallHandler::Strace(FEXCore::HLE::SyscallArguments *Args, uint64_t Ret) #endif void SyscallHandler::DefaultProgramBreak(FEXCore::Core::InternalThreadState *Thread, uint64_t Addr) { DataSpaceSize = 0; - DataSpace = Addr; - DefaultProgramBreakAddress = Addr; - // Just allocate 1GB of data memory past the default program break location at this point CTX->MapRegion(Thread, Addr, 0x1000'0000, true); + + if (UnifiedMemory) { + Addr += CTX->MemoryMapper.GetBaseOffset(0); + } + + DataSpace = Addr; + DefaultProgramBreakAddress = Addr; +} + +SyscallHandler::SyscallHandler(FEXCore::Context::Context *ctx) + : CTX {ctx} + , UnifiedMemory {CTX->Config.UnifiedMemory} + , FM {ctx} { +} + +void *SyscallHandler::GetPointer(uint64_t Offset) { + if (UnifiedMemory) + return reinterpret_cast(Offset); + else + return CTX->MemoryMapper.GetPointer(Offset); +} + +void *SyscallHandler::GetPointerSizeCheck(uint64_t Offset, uint64_t Size) { + if (UnifiedMemory) { + return reinterpret_cast(Offset); + } + else { + return CTX->MemoryMapper.GetPointerSizeCheck(Offset, Size); + } } uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Thread, FEXCore::HLE::SyscallArguments *Args) { uint64_t Result = 0; + std::scoped_lock lk(SyscallMutex); switch (Args->Argument[0]) { case SYSCALL_UNAME: { @@ -401,7 +490,7 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa char version[65]; char machine[65]; }; - _utsname *Local = CTX->MemoryMapper.GetPointer<_utsname*>(Args->Argument[1]); + _utsname *Local = GetPointer<_utsname*>(Args->Argument[1]); strcpy(Local->sysname, "Linux"); strcpy(Local->nodename, "FEXCore"); strcpy(Local->release, "5.0.0"); @@ -453,9 +542,16 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa break; } + if (UnifiedMemory) { + // If we are running unified memory then we want to be after our base + // This makes code page loading less of a burden + Base += CTX->MemoryMapper.GetBaseOffset(0); + } + if (Flags & MAP_FIXED) { Base = Args->Argument[1]; - void *HostPtr = CTX->MemoryMapper.GetPointerSizeCheck(Base, FileSizeToUse); + + void *HostPtr = GetPointerSizeCheck(Base, FileSizeToUse); if (!HostPtr) { HostPtr = CTX->MapRegion(Thread, Base, Size, true); } @@ -475,7 +571,7 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa } else { // XXX: MMAP should map memory regions for all threads - void *HostPtr = CTX->MemoryMapper.GetPointerSizeCheck(Base, FileSizeToUse); + void *HostPtr = GetPointerSizeCheck(Base, FileSizeToUse); if (!HostPtr) { HostPtr = CTX->MapRegion(Thread, Base, Size, true); } @@ -524,11 +620,11 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa Result = 0; break; case 0x1003: // ARCH_GET_FS - *CTX->MemoryMapper.GetPointer(Args->Argument[2]) = Thread->State.State.fs; + *GetPointer(Args->Argument[2]) = Thread->State.State.fs; Result = 0; break; case 0x1004: // ARCH_GET_GS - *CTX->MemoryMapper.GetPointer(Args->Argument[2]) = Thread->State.State.gs; + *GetPointer(Args->Argument[2]) = Thread->State.State.gs; Result = 0; break; case 0x3001: // ARCH_CET_STATUS @@ -546,25 +642,25 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa break; case SYSCALL_CONNECT: Result = FM.Connect(Args->Argument[1], - CTX->MemoryMapper.GetPointer(Args->Argument[2]), + GetPointer(Args->Argument[2]), Args->Argument[3]); break; case SYSCALL_RECVFROM: Result = FM.Recvfrom(Args->Argument[1], - CTX->MemoryMapper.GetPointer(Args->Argument[2]), + GetPointer(Args->Argument[2]), Args->Argument[3], Args->Argument[4], - CTX->MemoryMapper.GetPointer(Args->Argument[5]), - CTX->MemoryMapper.GetPointer(Args->Argument[6])); + GetPointer(Args->Argument[5]), + GetPointer(Args->Argument[6])); break; case SYSCALL_SENDMSG: Result = FM.Sendmsg(Args->Argument[1], - CTX->MemoryMapper.GetPointer(Args->Argument[2]), + GetPointer(Args->Argument[2]), Args->Argument[3]); break; case SYSCALL_RECVMSG: Result = FM.Recvmsg(Args->Argument[1], - CTX->MemoryMapper.GetPointer(Args->Argument[2]), + GetPointer(Args->Argument[2]), Args->Argument[3]); break; case SYSCALL_SHUTDOWN: @@ -573,30 +669,30 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa break; case SYSCALL_GETSOCKNAME: Result = FM.GetSockName(Args->Argument[1], - CTX->MemoryMapper.GetPointer(Args->Argument[2]), - CTX->MemoryMapper.GetPointer(Args->Argument[3])); + GetPointer(Args->Argument[2]), + GetPointer(Args->Argument[3])); break; case SYSCALL_GETPEERNAME: Result = FM.GetPeerName(Args->Argument[1], - CTX->MemoryMapper.GetPointer(Args->Argument[2]), - CTX->MemoryMapper.GetPointer(Args->Argument[3])); + GetPointer(Args->Argument[2]), + GetPointer(Args->Argument[3])); break; case SYSCALL_SETSOCKOPT: Result = FM.SetSockOpt(Args->Argument[1], Args->Argument[2], Args->Argument[3], - CTX->MemoryMapper.GetPointer(Args->Argument[4]), + GetPointer(Args->Argument[4]), Args->Argument[5]); break; case SYSCALL_GETSOCKOPT: Result = FM.GetSockOpt(Args->Argument[1], Args->Argument[2], Args->Argument[3], - CTX->MemoryMapper.GetPointer(Args->Argument[4]), - CTX->MemoryMapper.GetPointer(Args->Argument[5])); + GetPointer(Args->Argument[4]), + GetPointer(Args->Argument[5])); break; case SYSCALL_POLL: - Result = FM.Poll(CTX->MemoryMapper.GetPointer(Args->Argument[1]), Args->Argument[2], Args->Argument[3]); + Result = FM.Poll(GetPointer(Args->Argument[1]), Args->Argument[2], Args->Argument[3]); break; // Thread management case SYSCALL_GETUID: @@ -647,13 +743,16 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa } break; + case SYSCALL_SIGALTSTACK: + Result = 0; + break; case SYSCALL_MKNOD: - Result = FM.Mknod(CTX->MemoryMapper.GetPointer(Args->Argument[1]), + Result = FM.Mknod(GetPointer(Args->Argument[1]), Args->Argument[2], Args->Argument[3]); break; case SYSCALL_STATFS: - Result = FM.Statfs(CTX->MemoryMapper.GetPointer(Args->Argument[1]), - CTX->MemoryMapper.GetPointer(Args->Argument[2])); + Result = FM.Statfs(GetPointer(Args->Argument[1]), + GetPointer(Args->Argument[2])); break; case SYSCALL_GETTID: Result = Thread->State.ThreadManager.GetTID(); @@ -686,13 +785,6 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa // 3: utime // 4: uaddr2 // 5: val3 - LogMan::Msg::I("futex(%lx,\n\t%lx,\n\t%lx,\n\t%lx,\n\t%lx,\n\t%lx)", - Args->Argument[1], - Args->Argument[2], - Args->Argument[3], - Args->Argument[4], - Args->Argument[5], - Args->Argument[6]); uint8_t Command = Args->Argument[2] & 0xF; Result = 0; @@ -703,7 +795,7 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa if (!futex) { futex = new Futex{}; // XXX: Definitely a memory leak. When should we free this? - futex->Addr = CTX->MemoryMapper.GetPointer*>(Args->Argument[1]); + futex->Addr = GetPointer*>(Args->Argument[1]); futex->Val = Args->Argument[3]; EmplaceFutex(Args->Argument[1], futex); } @@ -745,6 +837,13 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa } break; } + case SYSCALL_SCHED_GETAFFINITY: { + cpu_set_t *mask = GetPointer(Args->Argument[3]); + // Claim 1 CPU core + CPU_SET(0, mask); + Result = 0; + break; + } case SYSCALL_CLONE: { // 0: clone_flags // 1: New SP @@ -803,13 +902,13 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa // Sets the child TID to pointer in ParentTID if (Flags & CLONE_PARENT_SETTID) { - uint64_t *TIDPtr = CTX->MemoryMapper.GetPointer(ParentTID); + uint64_t *TIDPtr = GetPointer(ParentTID); TIDPtr[0] = NewThread->State.ThreadManager.GetTID(); } // Sets the child TID to the pointer in ChildTID if (Flags & CLONE_CHILD_SETTID) { - uint64_t *TIDPtr = CTX->MemoryMapper.GetPointer(ChildTID); + uint64_t *TIDPtr = GetPointer(ChildTID); TIDPtr[0] = NewThread->State.ThreadManager.GetTID(); } @@ -818,7 +917,7 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa // Address /may/ be changed with SET_TID_ADDRESS syscall if (Flags & CLONE_CHILD_CLEARTID) { Futex *futex = new Futex{}; // XXX: Definitely a memory leak. When should we free this? - futex->Addr = CTX->MemoryMapper.GetPointer*>(ChildTID); + futex->Addr = GetPointer*>(ChildTID); futex->Val = NewThread->State.ThreadManager.GetTID(); EmplaceFutex(ChildTID, futex); NewThread->State.ThreadManager.clear_tid = true; @@ -836,16 +935,16 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa // File management case SYSCALL_READ: Result = FM.Read(Args->Argument[1], - CTX->MemoryMapper.GetPointer(Args->Argument[2]), + GetPointer(Args->Argument[2]), Args->Argument[3]); break; case SYSCALL_WRITE: Result = FM.Write(Args->Argument[1], - CTX->MemoryMapper.GetPointer(Args->Argument[2]), + GetPointer(Args->Argument[2]), Args->Argument[3]); break; case SYSCALL_OPEN: - Result = FM.Open(CTX->MemoryMapper.GetPointer(Args->Argument[1]), + Result = FM.Open(GetPointer(Args->Argument[1]), Args->Argument[2], Args->Argument[3]); break; @@ -854,10 +953,10 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa break; case SYSCALL_STAT: { struct stat host_stat{}; - Result = FM.Stat(CTX->MemoryMapper.GetPointer(Args->Argument[1]), + Result = FM.Stat(GetPointer(Args->Argument[1]), &host_stat); - guest_stat *guest_data = CTX->MemoryMapper.GetPointer(Args->Argument[2]); + guest_stat *guest_data = GetPointer(Args->Argument[2]); CopyStat(guest_data, &host_stat); break; } @@ -866,17 +965,17 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa Result = FM.Fstat(Args->Argument[1], &host_stat); - guest_stat *guest_data = CTX->MemoryMapper.GetPointer(Args->Argument[2]); + guest_stat *guest_data = GetPointer(Args->Argument[2]); CopyStat(guest_data, &host_stat); break; } case SYSCALL_LSTAT: { struct stat host_stat{}; - Result = FM.Lstat(CTX->MemoryMapper.GetPointer(Args->Argument[1]), + Result = FM.Lstat(GetPointer(Args->Argument[1]), &host_stat); - guest_stat *guest_data = CTX->MemoryMapper.GetPointer(Args->Argument[2]); + guest_stat *guest_data = GetPointer(Args->Argument[2]); CopyStat(guest_data, &host_stat); break; } @@ -887,17 +986,17 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa break; case SYSCALL_WRITEV: Result = FM.Writev(Args->Argument[1], - CTX->MemoryMapper.GetPointer(Args->Argument[2]), + GetPointer(Args->Argument[2]), Args->Argument[3]); break; case SYSCALL_ACCESS: Result = FM.Access( - CTX->MemoryMapper.GetPointer(Args->Argument[1]), + GetPointer(Args->Argument[1]), Args->Argument[2]); break; case SYSCALL_PIPE: Result = FM.Pipe( - CTX->MemoryMapper.GetPointer(Args->Argument[1])); + GetPointer(Args->Argument[1])); break; case SYSCALL_SELECT: { fd_set *readfds{}; @@ -906,13 +1005,13 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa struct timeval *timeout{}; if (Args->Argument[2]) - readfds = CTX->MemoryMapper.GetPointer(Args->Argument[2]); + readfds = GetPointer(Args->Argument[2]); if (Args->Argument[3]) - writefds = CTX->MemoryMapper.GetPointer(Args->Argument[3]); + writefds = GetPointer(Args->Argument[3]); if (Args->Argument[4]) - exceptfds = CTX->MemoryMapper.GetPointer(Args->Argument[4]); + exceptfds = GetPointer(Args->Argument[4]); if (Args->Argument[5]) - timeout = CTX->MemoryMapper.GetPointer(Args->Argument[5]); + timeout = GetPointer(Args->Argument[5]); Result = select(Args->Argument[1], readfds, writefds, exceptfds, timeout); @@ -923,27 +1022,41 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa break; case SYSCALL_READLINK: Result = FM.Readlink( - CTX->MemoryMapper.GetPointer(Args->Argument[1]), - CTX->MemoryMapper.GetPointer(Args->Argument[2]), + GetPointer(Args->Argument[1]), + GetPointer(Args->Argument[2]), Args->Argument[3]); break; case SYSCALL_OPENAT: Result = FM.Openat( Args->Argument[1], - CTX->MemoryMapper.GetPointer(Args->Argument[2]), + GetPointer(Args->Argument[2]), Args->Argument[3], Args->Argument[4]); break; + case SYSCALL_READLINKAT: + Result = FM.Readlinkat( + Args->Argument[1], + GetPointer(Args->Argument[2]), + GetPointer(Args->Argument[3]), + Args->Argument[4]); + break; + case SYSCALL_FACCESSAT: + Result = FM.FAccessat( + Args->Argument[1], + GetPointer(Args->Argument[2]), + Args->Argument[2], + Args->Argument[3]); + break; case SYSCALL_IOCTL: Result = FM.Ioctl( Args->Argument[1], Args->Argument[2], - CTX->MemoryMapper.GetPointer(Args->Argument[3])); + Args->Argument[3] ? GetPointer(Args->Argument[3]) : nullptr); break; case SYSCALL_PREAD64: Result = FM.PRead64( Args->Argument[1], - CTX->MemoryMapper.GetPointer(Args->Argument[2]), + GetPointer(Args->Argument[2]), Args->Argument[3], Args->Argument[4]); break; @@ -951,7 +1064,7 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa time_t TmpTime; TmpTime = time(nullptr); if (Args->Argument[1]) { - time_t *ClockResult = CTX->MemoryMapper.GetPointer(Args->Argument[1]); + time_t *ClockResult = GetPointer(Args->Argument[1]); *ClockResult = TmpTime; #ifdef DEBUG_TIME memset(ClockResult, 0, sizeof(time_t)); @@ -964,7 +1077,7 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa } break; case SYSCALL_CLOCK_GETTIME: { - timespec *ClockResult = CTX->MemoryMapper.GetPointer(Args->Argument[2]); + timespec *ClockResult = GetPointer(Args->Argument[2]); Result = clock_gettime(Args->Argument[1], ClockResult); #ifdef DEBUG_TIME memset(ClockResult, 0, sizeof(timespec)); @@ -972,37 +1085,105 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa } break; case SYSCALL_SYSINFO: { - struct sysinfo *info = CTX->MemoryMapper.GetPointer(Args->Argument[1]); + struct sysinfo *info = GetPointer(Args->Argument[1]); Result = sysinfo(info); } break; case SYSCALL_CLOCK_GETRES: { struct timespec *res{}; if (Args->Argument[2]) - res = CTX->MemoryMapper.GetPointer(Args->Argument[2]); + res = GetPointer(Args->Argument[2]); Result = clock_getres(Args->Argument[1], res); } break; case SYSCALL_MINCORE: { - Result = mincore(CTX->MemoryMapper.GetPointer(Args->Argument[1]), + Result = mincore(GetPointer(Args->Argument[1]), Args->Argument[2], - CTX->MemoryMapper.GetPointer(Args->Argument[3])); + GetPointer(Args->Argument[3])); + break; + } + case SYSCALL_SHMGET: { + Result = shmget(Args->Argument[1], + Args->Argument[2], + Args->Argument[3]); + if (Result == -1) { + Result = -errno; + } + break; + } + case SYSCALL_SHMAT: { + void* HostPointer{}; + if (Args->Argument[2]) { + HostPointer = GetPointer(Args->Argument[2]); + } + else { + HostPointer = reinterpret_cast(GetPointer(0) + CTX->MemoryMapper.GetSHMSize()); + } + + Result = (uint64_t)shmat(Args->Argument[1], + HostPointer, + Args->Argument[3]); + if (Result == -1) { + Result = -errno; + } + else { + if (Args->Argument[2]) { + Result = Args->Argument[2]; + } + else { + Result = Result - GetPointer(0); + } + } + break; + } + case SYSCALL_SHMCTL: { + struct shmid_ds * HostPointer{}; + if (Args->Argument[3]) { + HostPointer = GetPointer(Args->Argument[3]); + } + + Result = shmctl(Args->Argument[1], + Args->Argument[2], + HostPointer); + if (Result == -1) { + Result = -errno; + } + break; + } + case SYSCALL_DUP2: { + auto FD = FM.GetFDBacking(Args->Argument[1]); + if (!FD) { + Result = EBADF; + } + else { + Result = FM.DupFD(Args->Argument[1], dup(FD->GetHostFD())); + } break; } case SYSCALL_NANOSLEEP: { - timespec const* req = CTX->MemoryMapper.GetPointer(Args->Argument[1]); - timespec *rem = CTX->MemoryMapper.GetPointer(Args->Argument[2]); + timespec const* req = GetPointer(Args->Argument[1]); + timespec *rem = GetPointer(Args->Argument[2]); Result = nanosleep(req, rem); break; } + case SYSCALL_GETITIMER: { + // XXX: Not a real result + Result = 0; + break; + } case SYSCALL_ALARM: { // XXX: Not a real result Result = 0; break; } + case SYSCALL_SETITIMER: { + // XXX: Not a real result + Result = 0; + break; + } case SYSCALL_GETDENTS64: { Result = FM.GetDents(Args->Argument[1], - CTX->MemoryMapper.GetPointer(Args->Argument[2]), + GetPointer(Args->Argument[2]), Args->Argument[3]); break; } @@ -1011,7 +1192,7 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa // If a futex for this address changes then the futex location needs to change... if (futex) { RemoveFutex(Thread->State.ThreadManager.child_tid); - futex->Addr = CTX->MemoryMapper.GetPointer*>(Args->Argument[1]); + futex->Addr = GetPointer*>(Args->Argument[1]); EmplaceFutex(Args->Argument[1], futex); } @@ -1024,6 +1205,10 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa Result = 0; break; } + case SYSCALL_TIMERFD_CREATE: { + Result = FM.Timer_Create(Args->Argument[1], Args->Argument[2]);; + break; + } case SYSCALL_EVENTFD: { Result = FM.Eventfd(Args->Argument[1], Args->Argument[2]); break; @@ -1034,7 +1219,7 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa } case SYSCALL_PIPE2: Result = FM.Pipe2( - CTX->MemoryMapper.GetPointer(Args->Argument[1]), + GetPointer(Args->Argument[1]), Args->Argument[2]); break; case SYSCALL_PRLIMIT64: { @@ -1045,7 +1230,7 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa }; switch (Args->Argument[2]) { case 3: { // Stack limits - rlimit *old_limit = CTX->MemoryMapper.GetPointer(Args->Argument[3]); + rlimit *old_limit = GetPointer(Args->Argument[4]); // Default size old_limit->rlim_cur = 8 * 1024; old_limit->rlim_max = ~0ULL; @@ -1058,7 +1243,7 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa } case SYSCALL_SENDMMSG: Result = FM.Sendmmsg(Args->Argument[1], - CTX->MemoryMapper.GetPointer(Args->Argument[2]), + GetPointer(Args->Argument[2]), Args->Argument[3], Args->Argument[4]); break; @@ -1070,33 +1255,39 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa struct timeval *tv{}; struct timezone *tz{}; if (Args->Argument[1]) - tv = CTX->MemoryMapper.GetPointer(Args->Argument[1]); + tv = GetPointer(Args->Argument[1]); if (Args->Argument[2]) - tz = CTX->MemoryMapper.GetPointer(Args->Argument[2]); + tz = GetPointer(Args->Argument[2]); Result = gettimeofday(tv, tz); break; } case SYSCALL_GETCWD: { - char *ptr = getcwd(CTX->MemoryMapper.GetPointer(Args->Argument[1]), Args->Argument[2]); + char *ptr = getcwd(GetPointer(Args->Argument[1]), Args->Argument[2]); if (!ptr) { - Result = errno; + Result = -errno; } else { Result = strlen(ptr) + 1; } break; } case SYSCALL_CHDIR: - Result = chdir(CTX->MemoryMapper.GetPointer(Args->Argument[1])); + Result = chdir(GetPointer(Args->Argument[1])); break; case SYSCALL_MKDIR: - Result = mkdir(CTX->MemoryMapper.GetPointer(Args->Argument[1]), Args->Argument[2]); + Result = mkdir(GetPointer(Args->Argument[1]), Args->Argument[2]); break; case SYSCALL_RMDIR: - Result = rmdir(CTX->MemoryMapper.GetPointer(Args->Argument[1])); + Result = rmdir(GetPointer(Args->Argument[1])); break; case SYSCALL_UNLINK: - Result = unlink(CTX->MemoryMapper.GetPointer(Args->Argument[1])); + Result = unlink(GetPointer(Args->Argument[1])); + break; + case SYSCALL_SHMDT: + Result = shmdt(reinterpret_cast(GetPointer(Args->Argument[1]))); + if (Result == -1) { + Result = -errno; + } break; case SYSCALL_FCNTL: { int Cmd = Args->Argument[2]; @@ -1109,8 +1300,7 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa switch (Cmd) { case 0: // F_DUPFD case 1030:{ // F_DUPFD_CLOEXEC - int NewFD = fcntl(HostFD, Cmd); - Result = FM.DupFD(Args->Argument[1], NewFD); + Result = FM.DupFD(Args->Argument[1], dup(HostFD)); break; } case 1: // F_GETFD @@ -1131,16 +1321,16 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa break; } case SYSCALL_GETRANDOM: - Result = getrandom(CTX->MemoryMapper.GetPointer(Args->Argument[1]), + Result = getrandom(GetPointer(Args->Argument[1]), Args->Argument[2], Args->Argument[3]); break; case SYSCALL_STATX: Result = FM.Statx( Args->Argument[1], - CTX->MemoryMapper.GetPointer(Args->Argument[2]), + GetPointer(Args->Argument[2]), Args->Argument[3], Args->Argument[4], - CTX->MemoryMapper.GetPointer(Args->Argument[5])); + GetPointer(Args->Argument[5])); break; // Currently unhandled // Return fake result diff --git a/Source/Interface/HLE/Syscalls.h b/Source/Interface/HLE/Syscalls.h index ea811e3fb..a1ad0b352 100644 --- a/Source/Interface/HLE/Syscalls.h +++ b/Source/Interface/HLE/Syscalls.h @@ -8,11 +8,6 @@ #include #include - -namespace FEXCore::Context { -struct Context; -} - namespace FEXCore::Core { struct InternalThreadState; } @@ -44,8 +39,14 @@ enum Syscalls { SYSCALL_SELECT = 23, ///< __NR_select SYSCALL_SCHED_YIELD = 24, ///< __NR_sched_yield SYSCALL_MINCORE = 27, ///< __NR_mincore + SYSCALL_SHMGET = 29, ///< __NR_shmget + SYSCALL_SHMAT = 30, ///< __NR_shmat + SYSCALL_SHMCTL = 31, ///< __NR_shmctl + SYSCALL_DUP2 = 33, ///< __NR_dup2 SYSCALL_NANOSLEEP = 35, ///< __NR_nanosleep + SYSCALL_GETITIMER = 36, ///< __NR_getitimer SYSCALL_ALARM = 37, ///< __NR_alarm + SYSCALL_SETITIMER = 38, ///< __NR_setitimer SYSCALL_GETPID = 39, ///< __NR_getpid SYSCALL_SOCKET = 41, ///< __NR_socket SYSCALL_CONNECT = 42, ///< __NR_connect @@ -61,6 +62,7 @@ enum Syscalls { SYSCALL_EXIT = 60, ///< __NR_exit SYSCALL_WAIT4 = 61, ///< __NR_wait4 SYSCALL_UNAME = 63, ///< __NR_uname + SYSCALL_SHMDT = 67, ///< __NR_shmdt SYSCALL_FCNTL = 72, ///< __NR_fcntl SYSCALL_GETCWD = 79, ///< __NR_getcwd SYSCALL_CHDIR = 80, ///< __NR_chdir @@ -79,6 +81,7 @@ enum Syscalls { SYSCALL_SETREGID = 114, ///< __NR_setregid SYSCALL_SETRESUID = 117, ///< __NR_setresuid SYSCALL_SETRESGID = 119, ///< __NR_setresgid + SYSCALL_SIGALTSTACK = 131, ///< __NR_sigaltstack SYSCALL_MKNOD = 133, ///< __NR_mknod SYSCALL_STATFS = 137, ///< __NR_statfs SYSCALL_PRCTL = 157, ///< __NR_prctl @@ -86,6 +89,7 @@ enum Syscalls { SYSCALL_GETTID = 186, ///< __NR_gettid SYSCALL_TIME = 201, ///< __NR_time SYSCALL_FUTEX = 202, ///< __NR_futex + SYSCALL_SCHED_GETAFFINITY = 204, ///< __NR_sched_getaffinity SYSCALL_GETDENTS64 = 217, ///< __NR_getdents64 SYSCALL_SET_TID_ADDRESS = 218, ///< __NR_set_tid_address SYSCALL_CLOCK_GETTIME = 228, ///< __NR_clock_gettime @@ -93,7 +97,10 @@ enum Syscalls { SYSCALL_EXIT_GROUP = 231, ///< __NR_exit_group SYSCALL_TGKILL = 234, ///< __NR_tgkill SYSCALL_OPENAT = 257, ///< __NR_openat + SYSCALL_READLINKAT = 267, ///< __NR_readlinkat + SYSCALL_FACCESSAT = 269, ///< __NR_faccessat SYSCALL_SET_ROBUST_LIST = 273, ///< __NR_set_robust_list + SYSCALL_TIMERFD_CREATE = 283, ///< __NR_timerfd_create SYSCALL_EVENTFD = 290, ///< __NR_eventfd SYSCALL_EPOLL_CREATE1 = 291, ///< __NR_epoll_create1 SYSCALL_PIPE2 = 293, ///< __NR_pipe2 @@ -114,7 +121,7 @@ struct Futex { // #define DEBUG_STRACE class SyscallHandler final { public: - SyscallHandler(FEXCore::Context::Context *ctx) : CTX {ctx}, FM {ctx} {} + SyscallHandler(FEXCore::Context::Context *ctx); uint64_t HandleSyscall(FEXCore::Core::InternalThreadState *Thread, FEXCore::HLE::SyscallArguments *Args); // XXX: This leaks memory. @@ -132,6 +139,7 @@ public: } void RemoveFutex(uint64_t Addr) { + std::scoped_lock lk (FutexMutex); Futexes.erase(Addr); } @@ -142,11 +150,13 @@ public: private: FEXCore::Context::Context *CTX; + bool const &UnifiedMemory; FileManager FM; // Futex management std::unordered_map Futexes; std::mutex FutexMutex; + std::mutex SyscallMutex; // BRK management uint64_t DataSpace {}; @@ -159,7 +169,13 @@ private: #ifdef DEBUG_STRACE void Strace(FEXCore::HLE::SyscallArguments *Args, uint64_t Ret); #endif + template + T GetPointer(uint64_t Offset) { + return reinterpret_cast(GetPointer(Offset)); + } + void *GetPointer(uint64_t Offset); + void *GetPointerSizeCheck(uint64_t Offset, uint64_t Size); }; } diff --git a/Source/Interface/Memory/MemMapper.h b/Source/Interface/Memory/MemMapper.h index e887e6eb3..259e61180 100644 --- a/Source/Interface/Memory/MemMapper.h +++ b/Source/Interface/Memory/MemMapper.h @@ -16,6 +16,9 @@ namespace FEXCore::Memory { void SetBaseRegion(FEXCore::SHM::SHMObject *NewSHM) { SHM = reinterpret_cast(NewSHM); } + size_t GetSHMSize() const { + return SHM->Size; + } void *MapRegion(uint64_t Offset, size_t Size, bool Fixed = true); void *MapRegion(uint64_t Offset, size_t Size, uint32_t Flags, bool Fixed = true); diff --git a/Source/Interface/Memory/SharedMem.cpp b/Source/Interface/Memory/SharedMem.cpp index 7e42a7bcb..ece66e376 100644 --- a/Source/Interface/Memory/SharedMem.cpp +++ b/Source/Interface/Memory/SharedMem.cpp @@ -42,6 +42,7 @@ namespace FEXCore::SHM { } SHM->Object.Ptr = MapRegionFlags(SHM, 0, Size, PROT_READ | PROT_WRITE, false); + SHM->Size = Size; if (SHM->Object.Ptr == nullptr) { goto err; } diff --git a/Source/Interface/Memory/SharedMem.h b/Source/Interface/Memory/SharedMem.h index 75f4ec4c1..d7fbdae22 100644 --- a/Source/Interface/Memory/SharedMem.h +++ b/Source/Interface/Memory/SharedMem.h @@ -8,5 +8,6 @@ namespace FEXCore::SHM { struct InternalSHMObject { SHMObject Object; int SHMFD; + size_t Size; }; }