Syscall additions and fixes

Adds unified memory support for most things
Fixes a couple of bugs
This commit is contained in:
Ryan Houdek authored and Stefanos Kornilios Mitsis Poiitidis committed 2020-03-06 07:56:17 +02:00
1 parent 8d293e9184
commit 6f5b9358e2
7 files changed
+472 -138

No files matched your search

+152 -34
View File
@@ -8,6 +8,7 @@
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/ioctl.h>
#include <sys/timerfd.h>
#include <sys/uio.h>
#include <sys/vfs.h>
#include <unistd.h>
@@ -22,16 +23,25 @@ public:
}
ssize_t writev(int fd, void *iov, int iovcnt) override {
iovec *iovObject = reinterpret_cast<iovec*>(iov);
struct Object {
void *iov_base;
size_t iov_len;
};
Object *iovObject = reinterpret_cast<Object*>(iov);
if (CTX->Config.AccurateSTDOut) {
std::vector<iovec> HostStructs(iovcnt);
for (int i = 0; i < iovcnt; ++i) {
HostStructs[i].iov_base = CTX->MemoryMapper.GetPointer<void*>(reinterpret_cast<uint64_t>(iovObject[i].iov_base));
HostStructs[i].iov_len = iovObject[i].iov_len;
if (CTX->Config.UnifiedMemory) {
return ::writev(fd, reinterpret_cast<iovec const *>(iov), iovcnt);
}
else {
std::vector<iovec> HostStructs(iovcnt);
for (int i = 0; i < iovcnt; ++i) {
HostStructs[i].iov_base = CTX->MemoryMapper.GetPointer<void*>(reinterpret_cast<uint64_t>(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<const char*>(reinterpret_cast<uint64_t>(iovObject[i].iov_base));
if (CTX->Config.UnifiedMemory) {
String = reinterpret_cast<const char*>(iovObject[i].iov_base);
}
else {
String = CTX->MemoryMapper.GetPointer<const char*>(reinterpret_cast<uint64_t>(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<char*>(buf));
else if (FDOffset == STDERR_FILENO)
if (FDOffset == STDERR_FILENO)
LogMan::Msg::ERR("%s", reinterpret_cast<char*>(buf));
else
LogMan::Msg::OUT("%s", reinterpret_cast<char*>(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<const struct iovec*>(iov), iovcnt);
}
const struct iovec *Guestiov = reinterpret_cast<const struct iovec*>(iov);
std::vector<struct iovec> Hostiov;
Hostiov.resize(iovcnt);
for (int i = 0; i < iovcnt; ++i) {
Hostiov[i].iov_base = CTX->MemoryMapper.GetPointer(reinterpret_cast<uint64_t>(Guestiov[i].iov_base));
if (CTX->Config.UnifiedMemory) {
Hostiov[i].iov_base = reinterpret_cast<void*>(Guestiov[i].iov_base);
}
else {
Hostiov[i].iov_base = CTX->MemoryMapper.GetPointer(reinterpret_cast<uint64_t>(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<iovec> 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<iovec> Hostvec;
struct msghdr Hosthdr;
memcpy(&Hosthdr, msg, sizeof(struct msghdr));
if (Hosthdr.msg_name)
Hosthdr.msg_name = CTX->MemoryMapper.GetPointer(reinterpret_cast<uint64_t>(Hosthdr.msg_name));
if (Hosthdr.msg_name)
Hosthdr.msg_name = CTX->MemoryMapper.GetPointer(reinterpret_cast<uint64_t>(Hosthdr.msg_name));
if (Hosthdr.msg_control)
Hosthdr.msg_control = CTX->MemoryMapper.GetPointer(reinterpret_cast<uint64_t>(Hosthdr.msg_control));
if (Hosthdr.msg_control)
Hosthdr.msg_control = CTX->MemoryMapper.GetPointer(reinterpret_cast<uint64_t>(Hosthdr.msg_control));
Hostvec.resize(Hosthdr.msg_iovlen);
Hostvec.resize(Hosthdr.msg_iovlen);
struct iovec *Guestiov = CTX->MemoryMapper.GetPointer<struct iovec*>(reinterpret_cast<uint64_t>(Hosthdr.msg_iov));
for (int i = 0; i < Hosthdr.msg_iovlen; ++i) {
Hostvec[i].iov_base = CTX->MemoryMapper.GetPointer(reinterpret_cast<uint64_t>(Guestiov[i].iov_base));
Hostvec[i].iov_len = Guestiov[i].iov_len;
struct iovec *Guestiov = CTX->MemoryMapper.GetPointer<struct iovec*>(reinterpret_cast<uint64_t>(Hosthdr.msg_iov));
for (int i = 0; i < Hosthdr.msg_iovlen; ++i) {
Hostvec[i].iov_base = CTX->MemoryMapper.GetPointer(reinterpret_cast<uint64_t>(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<struct cmsghdr*>(msg->msg_control);
switch (cmsg->cmsg_type) {
case SCM_RIGHTS: {
uint32_t *HostFDs = reinterpret_cast<uint32_t*>(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, "<Shared>", 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;
+5
View File
@@ -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);
+288 -98
View File
@@ -15,6 +15,7 @@
#include <sys/random.h>
#include <sys/sysinfo.h>
#include <sys/utsname.h>
#include <sys/shm.h>
#include <unistd.h>
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<char const*>(Args->Argument[1]), Args->Argument[2], Ret);
LogMan::Msg::D("access(\"%s\", %d) = %ld", GetPointer<char const*>(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<char const*>(Args->Argument[2]), Args->Argument[3], Ret);
LogMan::Msg::D("openat(%ld, \"%s\", %d) = %ld", Args->Argument[1], GetPointer<char const*>(Args->Argument[2]), Args->Argument[3], Ret);
break;
case SYSCALL_READLINKAT:
LogMan::Msg::D("readlinkat(\"%s\") = %ld", GetPointer<char const*>(Args->Argument[2]), Ret);
break;
case SYSCALL_FACCESSAT:
LogMan::Msg::D("faccessat(\"%s\", %d) = %ld", GetPointer<char const*>(Args->Argument[2]), Args->Argument[3], Ret);
break;
case SYSCALL_STAT:
LogMan::Msg::D("stat(\"%s\", {...}) = %ld", CTX->MemoryMapper.GetPointer<char const*>(Args->Argument[1]), Ret);
LogMan::Msg::D("stat(\"%s\", {...}) = %ld", GetPointer<char const*>(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<char const*>(Args->Argument[1]), Ret);
LogMan::Msg::D("lstat(\"%s\", {...}) = %ld", GetPointer<char const*>(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<int32_t>(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<int32_t>(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<char const*>(Args->Argument[1]), Args->Argument[2], Ret);
LogMan::Msg::D("getcwd(\"%s\", %ld) = %ld", GetPointer<char const*>(Args->Argument[1]), Args->Argument[2], Ret);
break;
case SYSCALL_CHDIR:
LogMan::Msg::D("chdir(\"%s\") = %ld", CTX->MemoryMapper.GetPointer<char const*>(Args->Argument[1]), Ret);
LogMan::Msg::D("chdir(\"%s\") = %ld", GetPointer<char const*>(Args->Argument[1]), Ret);
break;
case SYSCALL_MKDIR:
LogMan::Msg::D("mkdir(\"%s\", 0x%lx) = %ld", CTX->MemoryMapper.GetPointer<char const*>(Args->Argument[1]), Args->Argument[2], Ret);
LogMan::Msg::D("mkdir(\"%s\", 0x%lx) = %ld", GetPointer<char const*>(Args->Argument[1]), Args->Argument[2], Ret);
break;
case SYSCALL_RMDIR:
LogMan::Msg::D("rmdir(\"%s\", 0x%lx) = %ld", CTX->MemoryMapper.GetPointer<char const*>(Args->Argument[1]), Args->Argument[2], Ret);
LogMan::Msg::D("rmdir(\"%s\", 0x%lx) = %ld", GetPointer<char const*>(Args->Argument[1]), Args->Argument[2], Ret);
break;
case SYSCALL_UNLINK:
LogMan::Msg::D("unlink(\"%s\", 0x%lx) = %ld", CTX->MemoryMapper.GetPointer<char const*>(Args->Argument[1]), Ret);
LogMan::Msg::D("unlink(\"%s\", 0x%lx) = %ld", GetPointer<char const*>(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<char const*>(Args->Argument[1]),
LogMan::Msg::D("mknod(\"%s\", %ld, %ld) = %ld", GetPointer<char const*>(Args->Argument[1]),
Args->Argument[2], Args->Argument[3],
Ret);
break;
case SYSCALL_STATFS:
LogMan::Msg::D("statfs(\"%s\", {...}) = %ld", CTX->MemoryMapper.GetPointer<char const*>(Args->Argument[1]), Ret);
LogMan::Msg::D("statfs(\"%s\", {...}) = %ld", GetPointer<char const*>(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<char const*>(Args->Argument[1]), Ret);
LogMan::Msg::D("readlink(\"%s\") = %ld", GetPointer<char const*>(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<char const*>(Args->Argument[2]),
GetPointer<char const*>(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<uint64_t>(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<void*>(Offset);
else
return CTX->MemoryMapper.GetPointer(Offset);
}
void *SyscallHandler::GetPointerSizeCheck(uint64_t Offset, uint64_t Size) {
if (UnifiedMemory) {
return reinterpret_cast<void*>(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<std::mutex> 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<uint64_t>(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<uint64_t*>(Args->Argument[2]) = Thread->State.State.fs;
*GetPointer<uint64_t*>(Args->Argument[2]) = Thread->State.State.fs;
Result = 0;
break;
case 0x1004: // ARCH_GET_GS
*CTX->MemoryMapper.GetPointer<uint64_t*>(Args->Argument[2]) = Thread->State.State.gs;
*GetPointer<uint64_t*>(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<const struct sockaddr *>(Args->Argument[2]),
GetPointer<const struct sockaddr *>(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<struct sockaddr *>(Args->Argument[5]),
CTX->MemoryMapper.GetPointer<socklen_t*>(Args->Argument[6]));
GetPointer<struct sockaddr *>(Args->Argument[5]),
GetPointer<socklen_t*>(Args->Argument[6]));
break;
case SYSCALL_SENDMSG:
Result = FM.Sendmsg(Args->Argument[1],
CTX->MemoryMapper.GetPointer<const struct msghdr*>(Args->Argument[2]),
GetPointer<const struct msghdr*>(Args->Argument[2]),
Args->Argument[3]);
break;
case SYSCALL_RECVMSG:
Result = FM.Recvmsg(Args->Argument[1],
CTX->MemoryMapper.GetPointer<struct msghdr*>(Args->Argument[2]),
GetPointer<struct msghdr*>(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<struct sockaddr *>(Args->Argument[2]),
CTX->MemoryMapper.GetPointer<socklen_t *>(Args->Argument[3]));
GetPointer<struct sockaddr *>(Args->Argument[2]),
GetPointer<socklen_t *>(Args->Argument[3]));
break;
case SYSCALL_GETPEERNAME:
Result = FM.GetPeerName(Args->Argument[1],
CTX->MemoryMapper.GetPointer<struct sockaddr *>(Args->Argument[2]),
CTX->MemoryMapper.GetPointer<socklen_t *>(Args->Argument[3]));
GetPointer<struct sockaddr *>(Args->Argument[2]),
GetPointer<socklen_t *>(Args->Argument[3]));
break;
case SYSCALL_SETSOCKOPT:
Result = FM.SetSockOpt(Args->Argument[1],
Args->Argument[2],
Args->Argument[3],
CTX->MemoryMapper.GetPointer<const void*>(Args->Argument[4]),
GetPointer<const void*>(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<void*>(Args->Argument[4]),
CTX->MemoryMapper.GetPointer<socklen_t *>(Args->Argument[5]));
GetPointer<void*>(Args->Argument[4]),
GetPointer<socklen_t *>(Args->Argument[5]));
break;
case SYSCALL_POLL:
Result = FM.Poll(CTX->MemoryMapper.GetPointer<struct pollfd*>(Args->Argument[1]), Args->Argument[2], Args->Argument[3]);
Result = FM.Poll(GetPointer<struct pollfd*>(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<char const*>(Args->Argument[1]),
Result = FM.Mknod(GetPointer<char const*>(Args->Argument[1]),
Args->Argument[2], Args->Argument[3]);
break;
case SYSCALL_STATFS:
Result = FM.Statfs(CTX->MemoryMapper.GetPointer<char const*>(Args->Argument[1]),
CTX->MemoryMapper.GetPointer(Args->Argument[2]));
Result = FM.Statfs(GetPointer<char const*>(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<std::atomic<uint32_t>*>(Args->Argument[1]);
futex->Addr = GetPointer<std::atomic<uint32_t>*>(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<cpu_set_t*>(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<uint64_t*>(ParentTID);
uint64_t *TIDPtr = GetPointer<uint64_t*>(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<uint64_t*>(ChildTID);
uint64_t *TIDPtr = GetPointer<uint64_t*>(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<std::atomic<uint32_t>*>(ChildTID);
futex->Addr = GetPointer<std::atomic<uint32_t>*>(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<char const*>(Args->Argument[1]),
Result = FM.Open(GetPointer<char const*>(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<char const*>(Args->Argument[1]),
Result = FM.Stat(GetPointer<char const*>(Args->Argument[1]),
&host_stat);
guest_stat *guest_data = CTX->MemoryMapper.GetPointer<guest_stat*>(Args->Argument[2]);
guest_stat *guest_data = GetPointer<guest_stat*>(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<guest_stat*>(Args->Argument[2]);
guest_stat *guest_data = GetPointer<guest_stat*>(Args->Argument[2]);
CopyStat(guest_data, &host_stat);
break;
}
case SYSCALL_LSTAT: {
struct stat host_stat{};
Result = FM.Lstat(CTX->MemoryMapper.GetPointer<char const*>(Args->Argument[1]),
Result = FM.Lstat(GetPointer<char const*>(Args->Argument[1]),
&host_stat);
guest_stat *guest_data = CTX->MemoryMapper.GetPointer<guest_stat*>(Args->Argument[2]);
guest_stat *guest_data = GetPointer<guest_stat*>(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<const char*>(Args->Argument[1]),
GetPointer<const char*>(Args->Argument[1]),
Args->Argument[2]);
break;
case SYSCALL_PIPE:
Result = FM.Pipe(
CTX->MemoryMapper.GetPointer<int*>(Args->Argument[1]));
GetPointer<int*>(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<fd_set*>(Args->Argument[2]);
readfds = GetPointer<fd_set*>(Args->Argument[2]);
if (Args->Argument[3])
writefds = CTX->MemoryMapper.GetPointer<fd_set*>(Args->Argument[3]);
writefds = GetPointer<fd_set*>(Args->Argument[3]);
if (Args->Argument[4])
exceptfds = CTX->MemoryMapper.GetPointer<fd_set*>(Args->Argument[4]);
exceptfds = GetPointer<fd_set*>(Args->Argument[4]);
if (Args->Argument[5])
timeout = CTX->MemoryMapper.GetPointer<struct timeval*>(Args->Argument[5]);
timeout = GetPointer<struct timeval*>(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<const char*>(Args->Argument[1]),
CTX->MemoryMapper.GetPointer<char*>(Args->Argument[2]),
GetPointer<const char*>(Args->Argument[1]),
GetPointer<char*>(Args->Argument[2]),
Args->Argument[3]);
break;
case SYSCALL_OPENAT:
Result = FM.Openat(
Args->Argument[1],
CTX->MemoryMapper.GetPointer<const char*>(Args->Argument[2]),
GetPointer<const char*>(Args->Argument[2]),
Args->Argument[3],
Args->Argument[4]);
break;
case SYSCALL_READLINKAT:
Result = FM.Readlinkat(
Args->Argument[1],
GetPointer<const char*>(Args->Argument[2]),
GetPointer<char*>(Args->Argument[3]),
Args->Argument[4]);
break;
case SYSCALL_FACCESSAT:
Result = FM.FAccessat(
Args->Argument[1],
GetPointer<const char*>(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<void*>(Args->Argument[3]));
Args->Argument[3] ? GetPointer<void*>(Args->Argument[3]) : nullptr);
break;
case SYSCALL_PREAD64:
Result = FM.PRead64(
Args->Argument[1],
CTX->MemoryMapper.GetPointer<void*>(Args->Argument[2]),
GetPointer<void*>(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<time_t*>(Args->Argument[1]);
time_t *ClockResult = GetPointer<time_t*>(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<timespec*>(Args->Argument[2]);
timespec *ClockResult = GetPointer<timespec*>(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<struct sysinfo*>(Args->Argument[1]);
struct sysinfo *info = GetPointer<struct sysinfo*>(Args->Argument[1]);
Result = sysinfo(info);
}
break;
case SYSCALL_CLOCK_GETRES: {
struct timespec *res{};
if (Args->Argument[2])
res = CTX->MemoryMapper.GetPointer<struct timespec*>(Args->Argument[2]);
res = GetPointer<struct timespec*>(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<unsigned char*>(Args->Argument[3]));
GetPointer<unsigned char*>(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<unsigned char*>(Args->Argument[2]);
}
else {
HostPointer = reinterpret_cast<void*>(GetPointer<uint64_t>(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<uint64_t>(0);
}
}
break;
}
case SYSCALL_SHMCTL: {
struct shmid_ds * HostPointer{};
if (Args->Argument[3]) {
HostPointer = GetPointer<struct shmid_ds*>(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<timespec const*>(Args->Argument[1]);
timespec *rem = CTX->MemoryMapper.GetPointer<timespec*>(Args->Argument[2]);
timespec const* req = GetPointer<timespec const*>(Args->Argument[1]);
timespec *rem = GetPointer<timespec*>(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<std::atomic<uint32_t>*>(Args->Argument[1]);
futex->Addr = GetPointer<std::atomic<uint32_t>*>(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<int*>(Args->Argument[1]),
GetPointer<int*>(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<rlimit*>(Args->Argument[3]);
rlimit *old_limit = GetPointer<rlimit*>(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<struct mmsghdr*>(Args->Argument[2]),
GetPointer<struct mmsghdr*>(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<struct timeval*>(Args->Argument[1]);
tv = GetPointer<struct timeval*>(Args->Argument[1]);
if (Args->Argument[2])
tz = CTX->MemoryMapper.GetPointer<struct timezone*>(Args->Argument[2]);
tz = GetPointer<struct timezone*>(Args->Argument[2]);
Result = gettimeofday(tv, tz);
break;
}
case SYSCALL_GETCWD:
{
char *ptr = getcwd(CTX->MemoryMapper.GetPointer<char *>(Args->Argument[1]), Args->Argument[2]);
char *ptr = getcwd(GetPointer<char *>(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<char const*>(Args->Argument[1]));
Result = chdir(GetPointer<char const*>(Args->Argument[1]));
break;
case SYSCALL_MKDIR:
Result = mkdir(CTX->MemoryMapper.GetPointer<char const*>(Args->Argument[1]), Args->Argument[2]);
Result = mkdir(GetPointer<char const*>(Args->Argument[1]), Args->Argument[2]);
break;
case SYSCALL_RMDIR:
Result = rmdir(CTX->MemoryMapper.GetPointer<char const*>(Args->Argument[1]));
Result = rmdir(GetPointer<char const*>(Args->Argument[1]));
break;
case SYSCALL_UNLINK:
Result = unlink(CTX->MemoryMapper.GetPointer<char const*>(Args->Argument[1]));
Result = unlink(GetPointer<char const*>(Args->Argument[1]));
break;
case SYSCALL_SHMDT:
Result = shmdt(reinterpret_cast<void*>(GetPointer<uint64_t>(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<void*>(Args->Argument[1]),
Result = getrandom(GetPointer<void*>(Args->Argument[1]),
Args->Argument[2],
Args->Argument[3]);
break;
case SYSCALL_STATX:
Result = FM.Statx(
Args->Argument[1],
CTX->MemoryMapper.GetPointer<char const*>(Args->Argument[2]),
GetPointer<char const*>(Args->Argument[2]),
Args->Argument[3], Args->Argument[4],
CTX->MemoryMapper.GetPointer<struct statx*>(Args->Argument[5]));
GetPointer<struct statx*>(Args->Argument[5]));
break;
// Currently unhandled
// Return fake result
+22 -6
View File
@@ -8,11 +8,6 @@
#include <mutex>
#include <unordered_map>
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<std::mutex> 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<uint64_t, Futex*> 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<typename T>
T GetPointer(uint64_t Offset) {
return reinterpret_cast<T>(GetPointer(Offset));
}
void *GetPointer(uint64_t Offset);
void *GetPointerSizeCheck(uint64_t Offset, uint64_t Size);
};
}
+3
View File
@@ -16,6 +16,9 @@ namespace FEXCore::Memory {
void SetBaseRegion(FEXCore::SHM::SHMObject *NewSHM) {
SHM = reinterpret_cast<FEXCore::SHM::InternalSHMObject*>(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);
+1
View File
@@ -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;
}
+1
View File
@@ -8,5 +8,6 @@ namespace FEXCore::SHM {
struct InternalSHMObject {
SHMObject Object;
int SHMFD;
size_t Size;
};
}