Adds 11 new emulated syscalls

This commit is contained in:
Ryan Houdek authored and Stefanos Kornilios Mitsis Poiitidis committed 2020-03-06 07:56:15 +02:00
1 parent d2bfb39b54
commit 472ec5f5cf
6 files changed
+407 -62

No files matched your search

@@ -50,6 +50,9 @@ void OpDispatchBuilder::SyscallOp(OpcodeArgs) {
FEXCore::X86State::REG_R9,
};
auto NewRIP = _Constant(Op->PC);
_StoreContext(8, offsetof(FEXCore::Core::CPUState, rip), NewRIP);
auto SyscallOp = _Syscall(
_LoadContext(8, offsetof(FEXCore::Core::CPUState, gregs) + GPRIndexes[0] * 8),
_LoadContext(8, offsetof(FEXCore::Core::CPUState, gregs) + GPRIndexes[1] * 8),
+117
View File
@@ -4,10 +4,12 @@
#include "Interface/HLE/FileManagement.h"
#include <fcntl.h>
#include <sys/epoll.h>
#include <sys/eventfd.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <sys/vfs.h>
#include <unistd.h>
namespace FEXCore {
@@ -76,6 +78,15 @@ private:
};
class EventFD final : public FD {
public:
EventFD(FEXCore::Context::Context *ctx, int32_t fd, uint32_t initval, uint32_t flags)
: FD (ctx, fd, "Event", 0, 0) {
HostFD = eventfd(initval, flags);
}
};
uint64_t FD::read(int fd, void *buf, size_t count) {
return ::read(HostFD, buf, count);
}
@@ -373,6 +384,36 @@ uint64_t FileManager::PRead64(int fd, void *buf, size_t count, off_t offset) {
return pread(FD->second->GetHostFD(), buf, count, offset);
}
uint64_t FileManager::Statx(int dirfd, const char *pathname, int flags, uint32_t mask, struct statx *statxbuf) {
// Do we need the dirfd?
if (pathname[0] == '/' ||
((flags & AT_EMPTY_PATH) && pathname[0] == '\0')) {
auto FD = FDMap.find(dirfd);
if (FD == FDMap.end()) {
return EBADF;
}
dirfd = FD->second->GetHostFD();
}
auto Path = GetEmulatedPath(pathname);
if (!Path.empty()) {
uint64_t Result = ::statx(dirfd, Path.c_str(), flags, mask, statxbuf);
if (Result != -1)
return Result;
}
return ::statx(dirfd, pathname, flags, mask, statxbuf);
}
uint64_t FileManager::Mknod(const char *pathname, mode_t mode, dev_t dev) {
auto Path = GetEmulatedPath(pathname);
if (!Path.empty()) {
uint64_t Result = ::mknod(Path.c_str(), mode, dev);
if (Result != -1)
return Result;
}
return ::mknod(pathname, mode, dev);
}
uint64_t FileManager::EPoll_Create1(int flags) {
int HostFD = epoll_create1(flags);
int32_t fd = CurrentFDOffset;
@@ -382,6 +423,32 @@ uint64_t FileManager::EPoll_Create1(int flags) {
return fd;
}
uint64_t FileManager::Statfs(const char *path, void *buf) {
auto Path = GetEmulatedPath(path);
if (!Path.empty()) {
uint64_t Result = ::statfs(Path.c_str(), reinterpret_cast<struct statfs*>(buf));
if (Result != -1)
return Result;
}
return ::statfs(path, reinterpret_cast<struct statfs*>(buf));
}
uint64_t FileManager::Eventfd(uint32_t initval, uint32_t flags) {
int32_t fd = CurrentFDOffset;
auto fdPtr = new EventFD{CTX, fd, initval, flags};
auto Result = fdPtr->GetHostFD();
if (Result == -1) {
delete fdPtr;
return -errno;
}
FDMap[CurrentFDOffset++] = fdPtr;
return fd;
}
uint64_t FileManager::Socket(int domain, int type, int protocol) {
int32_t fd = CurrentFDOffset;
@@ -420,6 +487,42 @@ uint64_t FileManager::Recvfrom(int sockfd, void *buf, size_t len, int flags, str
return recvfrom(FD->second->GetHostFD(), buf, len, flags, src_addr, addrlen);
}
uint64_t FileManager::Sendmsg(int sockfd, const struct msghdr *msg, int flags) {
auto FD = FDMap.find(sockfd);
if (FD == FDMap.end()) {
return -1;
}
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_control)
Hosthdr.msg_control = CTX->MemoryMapper.GetPointer(reinterpret_cast<uint64_t>(Hosthdr.msg_control));
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;
}
Hosthdr.msg_iov = &Hostvec.at(0);
int Result = sendmsg(FD->second->GetHostFD(), &Hosthdr, flags);
if (Result == -1) {
if (errno == EAGAIN ||
errno == EWOULDBLOCK) {
return -errno;
}
}
return Result;
}
uint64_t FileManager::Recvmsg(int sockfd, struct msghdr *msg, int flags) {
auto FD = FDMap.find(sockfd);
if (FD == FDMap.end()) {
@@ -638,4 +741,18 @@ FD const* FileManager::GetFDBacking(int fd) {
return FD->second;
}
int32_t FileManager::DupFD(int prevFD, int newFD) {
auto prevFDClass = FDMap.find(prevFD);
if (prevFDClass == FDMap.end()) {
return -1;
}
int32_t fd = CurrentFDOffset;
auto fdPtr = new FD{prevFDClass->second, fd};
FDMap[CurrentFDOffset++] = fdPtr;
return fd;
}
}
+18
View File
@@ -24,6 +24,14 @@ public:
, Flags {flags}
, Mode {mode} {
}
FD(FD *Prev, int32_t fd)
: CTX {Prev->CTX}
, FDOffset {fd}
, PathName {Prev->PathName}
, Flags {Prev->Flags}
, Mode {Prev->Mode} {
}
virtual ~FD() {}
uint64_t read(int fd, void *buf, size_t count);
@@ -74,14 +82,23 @@ public:
uint64_t Ioctl(int fd, uint64_t request, void *args);
uint64_t GetDents(int fd, void *dirp, uint32_t count);
uint64_t PRead64(int fd, void *buf, size_t count, off_t offset);
uint64_t Statx(int dirfd, const char *pathname, int flags, uint32_t mask, struct statx *statxbuf);
uint64_t Mknod(const char *pathname, mode_t mode, dev_t dev);
// EPoll
uint64_t EPoll_Create1(int flags);
// vfs
uint64_t Statfs(const char *path, void *buf);
// Eventfd
uint64_t Eventfd(uint32_t initval, uint32_t flags);
// Sockets
uint64_t Socket(int domain, int type, int protocol);
uint64_t Connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
uint64_t Recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
uint64_t Sendmsg(int sockfd, const struct msghdr *msg, int flags);
uint64_t Recvmsg(int sockfd, struct msghdr *msg, int flags);
uint64_t Shutdown(int sockfd, int how);
uint64_t GetSockName(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
@@ -95,6 +112,7 @@ public:
int32_t FindHostFD(int fd);
FD const* GetFDBacking(int fd);
int32_t DupFD(int prevFD, int newFD);
void SetFilename(std::string const &File) { Filename = File; }
std::string const & GetFilename() const { return Filename; }
+249 -61
View File
@@ -8,6 +8,7 @@
#include <FEXCore/Core/X86Enums.h>
#include <fcntl.h>
#include <limits.h>
#include <poll.h>
#include <sys/mman.h>
#include <sys/time.h>
@@ -89,12 +90,28 @@ void SyscallHandler::Strace(FEXCore::HLE::SyscallArguments *Args, uint64_t Ret)
Args->Argument[5],
Ret);
break;
case SYSCALL_SCHED_YIELD:
LogMan::Msg::D("sched_yield() = %ld",
Ret);
break;
case SYSCALL_MINCORE:
LogMan::Msg::D("mincore(0x%lx, 0x%lx, 0x%lx) = %ld",
Args->Argument[1],
Args->Argument[2],
Args->Argument[3],
Ret);
break;
case SYSCALL_NANOSLEEP:
LogMan::Msg::D("nanosleep(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_OPENAT:
LogMan::Msg::D("openat(%ld, \"%s\", %d) = %ld", Args->Argument[1], CTX->MemoryMapper.GetPointer<char const*>(Args->Argument[2]), Args->Argument[3], Ret);
break;
@@ -119,6 +136,13 @@ void SyscallHandler::Strace(FEXCore::HLE::SyscallArguments *Args, uint64_t Ret)
case SYSCALL_READ:
LogMan::Msg::D("read(%ld, {...}, %ld) = %ld", Args->Argument[1], Args->Argument[3], Ret);
break;
case SYSCALL_PRCTL:
LogMan::Msg::D("arch_prctl(%ld, %p, %p, %p, %p) = %ld",
Args->Argument[1], Args->Argument[2],
Args->Argument[3], Args->Argument[4],
Args->Argument[5],
Ret);
break;
case SYSCALL_ARCH_PRCTL:
LogMan::Msg::D("arch_prctl(%ld, %p) = %ld", Args->Argument[1], Args->Argument[2], Ret);
break;
@@ -152,6 +176,9 @@ void SyscallHandler::Strace(FEXCore::HLE::SyscallArguments *Args, uint64_t Ret)
case SYSCALL_MKDIR:
LogMan::Msg::D("mkdir(\"%s\", 0x%lx) = %ld", CTX->MemoryMapper.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);
break;
case SYSCALL_UNLINK:
LogMan::Msg::D("unlink(\"%s\", 0x%lx) = %ld", CTX->MemoryMapper.GetPointer<char const*>(Args->Argument[1]), Ret);
break;
@@ -176,6 +203,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_EVENTFD:
LogMan::Msg::D("eventfd(%lx, %ld) = %ld", Args->Argument[1], Args->Argument[2], Ret);
break;
case SYSCALL_EPOLL_CREATE1:
LogMan::Msg::D("epoll_create1(%ld) = %ld", Args->Argument[1], Ret);
break;
@@ -213,6 +243,13 @@ void SyscallHandler::Strace(FEXCore::HLE::SyscallArguments *Args, uint64_t Ret)
Args->Argument[6],
Ret);
break;
case SYSCALL_SENDMSG:
LogMan::Msg::D("sendmsg(%ld, 0x%lx, %ld) = %ld",
Args->Argument[1],
Args->Argument[2],
Args->Argument[3],
Ret);
break;
case SYSCALL_RECVMSG:
LogMan::Msg::D("recvmsg(%ld, 0x%lx, %ld) = %ld",
Args->Argument[1],
@@ -277,6 +314,17 @@ void SyscallHandler::Strace(FEXCore::HLE::SyscallArguments *Args, uint64_t Ret)
case SYSCALL_SETRESUID:
LogMan::Msg::D("setresuid(%ld, %ld, %ld) = %ld", Args->Argument[1], Args->Argument[2], Args->Argument[3], Ret);
break;
case SYSCALL_SETRESGID:
LogMan::Msg::D("setresgid(%ld, %ld, %ld) = %ld", Args->Argument[1], Args->Argument[2], Args->Argument[3], Ret);
break;
case SYSCALL_MKNOD:
LogMan::Msg::D("mknod(\"%s\", %ld, %ld) = %ld", CTX->MemoryMapper.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);
break;
case SYSCALL_GETTID:
LogMan::Msg::D("gettid() = %ld", Ret);
break;
@@ -321,6 +369,13 @@ void SyscallHandler::Strace(FEXCore::HLE::SyscallArguments *Args, uint64_t Ret)
Args->Argument[3],
Ret);
break;
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]),
Args->Argument[3], Args->Argument[4],
Ret);
break;
default: LogMan::Msg::D("Unknown strace: %d", Args->Argument[0]);
}
}
@@ -393,6 +448,10 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa
uint64_t Size = AlignUp(Args->Argument[2], PAGE_SIZE);
uint64_t FileSizeToUse = Args->Argument[2];
uint64_t Prot = Args->Argument[3];
if (Args->Argument[2] == 0) {
Result = EINVAL;
break;
}
if (Flags & MAP_FIXED) {
Base = Args->Argument[1];
@@ -441,6 +500,19 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa
Result = mprotect(HostPtr, Args->Argument[2], Args->Argument[3]);
break;
}
case SYSCALL_PRCTL: {
switch (Args->Argument[1]) {
case 0xF: // PR_SET_NAME
case 0x10: // PR_GET_NAME
Result = 0;
break;
default:
LogMan::Msg::E("Unknown prctl: 0x%x", Args->Argument[1]);
CTX->ShouldStop = true;
break;
}
break;
}
case SYSCALL_ARCH_PRCTL: {
switch (Args->Argument[1]) {
case 0x1001: // ARCH_SET_GS
@@ -485,6 +557,11 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa
CTX->MemoryMapper.GetPointer<struct sockaddr *>(Args->Argument[5]),
CTX->MemoryMapper.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]),
Args->Argument[3]);
break;
case SYSCALL_RECVMSG:
Result = FM.Recvmsg(Args->Argument[1],
CTX->MemoryMapper.GetPointer<struct msghdr*>(Args->Argument[2]),
@@ -529,8 +606,12 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa
Result = Thread->State.ThreadManager.GetGID();
break;
case SYSCALL_SETUID:
// XXX: Not a real result
Result = -1;
if (Thread->State.ThreadManager.GetUID() == Args->Argument[1]) {
Result = 0;
}
else {
Result = EINVAL;
}
break;
case SYSCALL_GETEUID:
Result = Thread->State.ThreadManager.GetEUID();
@@ -539,13 +620,41 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa
Result = Thread->State.ThreadManager.GetEGID();
break;
case SYSCALL_SETREGID:
// XXX: Not a real result
Result = 0;
if (Thread->State.ThreadManager.GetEGID() == Args->Argument[1]) {
Result = 0;
}
else {
Result = EINVAL;
}
break;
case SYSCALL_SETRESUID:
// XXX: Not a real result
Result = -1;
break;
case SYSCALL_SETRESGID:
// rgid, egid, sgid
Result = 0;
if (Args->Argument[1] != -1 &&
Args->Argument[1] != Thread->State.ThreadManager.GetGID()) {
Result = EPERM;
}
if (Args->Argument[2] != -1 &&
Args->Argument[2] != Thread->State.ThreadManager.GetEGID()) {
Result = EPERM;
}
if (Args->Argument[3] != -1) {
Result = EPERM;
}
break;
case SYSCALL_MKNOD:
Result = FM.Mknod(CTX->MemoryMapper.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]));
break;
case SYSCALL_GETTID:
Result = Thread->State.ThreadManager.GetTID();
break;
@@ -555,6 +664,11 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa
case SYSCALL_EXIT:
LogMan::Msg::D("Thread exit with: %zd\n", Args->Argument[1]);
Thread->State.RunningEvents.ShouldStop = true;
if (Thread->State.ThreadManager.clear_tid) {
Futex *futex = GetFutex(Thread->State.ThreadManager.child_tid);
futex->Addr->store(0);
futex->cv.notify_all();
}
break;
case SYSCALL_WAIT4:
LogMan::Msg::I("wait4(%lx,\n\t%lx,\n\t%lx,\n\t%lx)",
@@ -566,51 +680,70 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa
// Futexes
case SYSCALL_FUTEX: {
// 0 : uaddr
// 1 : op
// 2: val
// 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]);
// 0 : uaddr
// 1 : op
// 2: val
// 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;
switch (Command) {
case 0: { // WAIT
LogMan::Throw::A(!Args->Argument[4], "Can't handle timed futexes");
Futex *futex = GetFutex(Args->Argument[1]);
uint8_t Command = Args->Argument[2] & 0xF;
Result = 0;
switch (Command) {
case 0: { // WAIT
LogMan::Throw::A(!Args->Argument[4], "Can't handle timed futexes");
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->Val = Args->Argument[3];
EmplaceFutex(Args->Argument[1], futex);
{
std::unique_lock<std::mutex> lk(futex->Mutex);
futex->cv.wait(lk, [futex] { return futex->Addr->load() != futex->Val; });
}
break;
}
case 1: { // WAKE
Futex *futex = GetFutex(Args->Argument[1]);
if (!futex) {
Result = 0;
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->Val = Args->Argument[3];
EmplaceFutex(Args->Argument[1], futex);
}
if (futex->Addr->load() != futex->Val) {
// Immediate check can return EAGAIN
Result = EAGAIN;
}
else
{
std::unique_lock<std::mutex> lk(futex->Mutex);
futex->Waiters++;
futex->cv.wait(lk, [futex] { return futex->Addr->load() != futex->Val; });
futex->Waiters--;
}
break;
}
case 1: { // WAKE
Futex *futex = GetFutex(Args->Argument[1]);
if (!futex) {
// Tried to wake up an unknown futex?
Result = 0;
break;
}
if (Args->Argument[3] == INT_MAX) {
Result = futex->Waiters;
futex->cv.notify_all();
}
else {
uint32_t PrevWaiters = futex->Waiters;
for (uint64_t i = 0; i < Args->Argument[3]; ++i)
futex->cv.notify_one();
Result = std::min(PrevWaiters, (uint32_t)Args->Argument[3]);
}
break;
}
default:
LogMan::Msg::A("Unknown futex command");
break;
}
for (uint64_t i = 0; i < Args->Argument[3]; ++i)
futex->cv.notify_one();
break;
}
default:
LogMan::Msg::A("Unknown futex command");
break;
}
break;
break;
}
case SYSCALL_CLONE: {
// 0: clone_flags
@@ -657,7 +790,10 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa
NewThreadState.gregs[FEXCore::X86State::REG_RBX] = 0;
NewThreadState.gregs[FEXCore::X86State::REG_RBP] = 0;
NewThreadState.gregs[FEXCore::X86State::REG_RSP] = NewSP;
NewThreadState.fs = NewTLS;
if (Flags & CLONE_SETTLS) {
NewThreadState.fs = NewTLS;
}
// Set us to start just after the syscall instruction
NewThreadState.rip += 2;
@@ -681,6 +817,11 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa
// Additionally wakeup a futex at that address
// 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->Val = NewThread->State.ThreadManager.GetTID();
EmplaceFutex(ChildTID, futex);
NewThread->State.ThreadManager.clear_tid = true;
}
CTX->InitializeThread(NewThread);
@@ -777,6 +918,9 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa
readfds, writefds, exceptfds, timeout);
break;
}
case SYSCALL_SCHED_YIELD:
Result = sched_yield();
break;
case SYSCALL_READLINK:
Result = FM.Readlink(
CTX->MemoryMapper.GetPointer<const char*>(Args->Argument[1]),
@@ -839,12 +983,23 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa
Result = clock_getres(Args->Argument[1], res);
}
break;
case SYSCALL_MINCORE: {
Result = mincore(CTX->MemoryMapper.GetPointer(Args->Argument[1]),
Args->Argument[2],
CTX->MemoryMapper.GetPointer<unsigned char*>(Args->Argument[3]));
break;
}
case SYSCALL_NANOSLEEP: {
timespec const* req = CTX->MemoryMapper.GetPointer<timespec const*>(Args->Argument[1]);
timespec *rem = CTX->MemoryMapper.GetPointer<timespec*>(Args->Argument[2]);
Result = nanosleep(req, rem);
break;
}
case SYSCALL_ALARM: {
// XXX: Not a real result
Result = 0;
break;
}
case SYSCALL_GETDENTS64: {
Result = FM.GetDents(Args->Argument[1],
CTX->MemoryMapper.GetPointer(Args->Argument[2]),
@@ -852,6 +1007,14 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa
break;
}
case SYSCALL_SET_TID_ADDRESS: {
Futex *futex = GetFutex(Thread->State.ThreadManager.child_tid);
// 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]);
EmplaceFutex(Args->Argument[1], futex);
}
Thread->State.ThreadManager.child_tid = Args->Argument[1];
Result = Thread->State.ThreadManager.GetTID();
break;
@@ -861,6 +1024,10 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa
Result = 0;
break;
}
case SYSCALL_EVENTFD: {
Result = FM.Eventfd(Args->Argument[1], Args->Argument[2]);
break;
}
case SYSCALL_EPOLL_CREATE1: {
Result = FM.EPoll_Create1(Args->Argument[1]);
break;
@@ -925,27 +1092,41 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa
case SYSCALL_MKDIR:
Result = mkdir(CTX->MemoryMapper.GetPointer<char const*>(Args->Argument[1]), Args->Argument[2]);
break;
case SYSCALL_RMDIR:
Result = rmdir(CTX->MemoryMapper.GetPointer<char const*>(Args->Argument[1]));
break;
case SYSCALL_UNLINK:
Result = unlink(CTX->MemoryMapper.GetPointer<char const*>(Args->Argument[1]));
break;
case SYSCALL_FCNTL: {
int Cmd = Args->Argument[2];
auto FD = FM.GetFDBacking(Args->Argument[1]);
auto HostFD = FD->GetHostFD();
switch (Cmd) {
case 1: // F_GETFD
Result = fcntl(HostFD, Cmd);
break;
case 2: // F_SETFD
Result = fcntl(HostFD, Cmd, Args->Argument[3]);
break;
case 3: // F_GETFL
Result = fcntl(HostFD, Cmd);
break;
case 4: // F_SETFL
Result = fcntl(HostFD, Cmd, Args->Argument[3]);
break;
default: LogMan::Msg::A("FCNTL: Unknown Command: %ld", Cmd); break;
if (!FD) {
Result = EBADF;
}
else {
auto HostFD = FD->GetHostFD();
switch (Cmd) {
case 0: // F_DUPFD
case 1030:{ // F_DUPFD_CLOEXEC
int NewFD = fcntl(HostFD, Cmd);
Result = FM.DupFD(Args->Argument[1], NewFD);
break;
}
case 1: // F_GETFD
Result = fcntl(HostFD, Cmd);
break;
case 2: // F_SETFD
Result = fcntl(HostFD, Cmd, Args->Argument[3]);
break;
case 3: // F_GETFL
Result = fcntl(HostFD, Cmd);
break;
case 4: // F_SETFL
Result = fcntl(HostFD, Cmd, Args->Argument[3]);
break;
default: LogMan::Msg::A("FCNTL: Unknown Command: %ld", Cmd); break;
}
}
break;
}
@@ -954,6 +1135,13 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa
Args->Argument[2],
Args->Argument[3]);
break;
case SYSCALL_STATX:
Result = FM.Statx(
Args->Argument[1],
CTX->MemoryMapper.GetPointer<char const*>(Args->Argument[2]),
Args->Argument[3], Args->Argument[4],
CTX->MemoryMapper.GetPointer<struct statx*>(Args->Argument[5]));
break;
// Currently unhandled
// Return fake result
case SYSCALL_RT_SIGACTION:
+19 -1
View File
@@ -42,11 +42,15 @@ enum Syscalls {
SYSCALL_ACCESS = 21, ///< __NR_access
SYSCALL_PIPE = 22, ///< __NR_pipe
SYSCALL_SELECT = 23, ///< __NR_select
SYSCALL_SCHED_YIELD = 24, ///< __NR_sched_yield
SYSCALL_MINCORE = 27, ///< __NR_mincore
SYSCALL_NANOSLEEP = 35, ///< __NR_nanosleep
SYSCALL_ALARM = 37, ///< __NR_alarm
SYSCALL_GETPID = 39, ///< __NR_getpid
SYSCALL_SOCKET = 41, ///< __NR_socket
SYSCALL_CONNECT = 42, ///< __NR_connect
SYSCALL_RECVFROM = 45, ///< __NR_recvfrom
SYSCALL_SENDMSG = 46, ///< __NR_sendmsg
SYSCALL_RECVMSG = 47, ///< __NR_recvmsg
SYSCALL_SHUTDOWN = 48, ///< __NR_shutdown
SYSCALL_GETSOCKNAME = 51, ///< __NR_getsockname
@@ -61,6 +65,7 @@ enum Syscalls {
SYSCALL_GETCWD = 79, ///< __NR_getcwd
SYSCALL_CHDIR = 80, ///< __NR_chdir
SYSCALL_MKDIR = 83, ///< __NR_mkdir
SYSCALL_RMDIR = 84, ///< __NR_rmdir
SYSCALL_UNLINK = 87, ///< __NR_unlink
SYSCALL_READLINK = 89, ///< __NR_readlink
SYSCALL_UMASK = 95, ///< __NR_umask
@@ -73,6 +78,10 @@ enum Syscalls {
SYSCALL_GETEGID = 108, ///< __NR_getegid
SYSCALL_SETREGID = 114, ///< __NR_setregid
SYSCALL_SETRESUID = 117, ///< __NR_setresuid
SYSCALL_SETRESGID = 119, ///< __NR_setresgid
SYSCALL_MKNOD = 133, ///< __NR_mknod
SYSCALL_STATFS = 137, ///< __NR_statfs
SYSCALL_PRCTL = 157, ///< __NR_prctl
SYSCALL_ARCH_PRCTL = 158, ///< __NR_arch_prctl
SYSCALL_GETTID = 186, ///< __NR_gettid
SYSCALL_TIME = 201, ///< __NR_time
@@ -85,17 +94,20 @@ enum Syscalls {
SYSCALL_TGKILL = 234, ///< __NR_tgkill
SYSCALL_OPENAT = 257, ///< __NR_openat
SYSCALL_SET_ROBUST_LIST = 273, ///< __NR_set_robust_list
SYSCALL_EVENTFD = 290, ///< __NR_eventfd
SYSCALL_EPOLL_CREATE1 = 291, ///< __NR_epoll_create1
SYSCALL_PIPE2 = 293, ///< __NR_pipe2
SYSCALL_PRLIMIT64 = 302, ///< __NR_prlimit64
SYSCALL_SENDMMSG = 307, ///< __NR_sendmmsg
SYSCALL_GETRANDOM = 318, ///< __NR_getrandom
SYSCALL_STATX = 332, ///< __NR_statx
};
struct Futex {
std::mutex Mutex;
std::condition_variable cv;
std::atomic<uint32_t> *Addr;
std::atomic<uint32_t> Waiters{};
uint32_t Val;
};
@@ -114,7 +126,13 @@ public:
Futex *GetFutex(uint64_t Addr) {
std::scoped_lock<std::mutex> lk (FutexMutex);
return Futexes[Addr];
auto it = Futexes.find(Addr);
if (it == Futexes.end()) return nullptr;
return it->second;
}
void RemoveFutex(uint64_t Addr) {
Futexes.erase(Addr);
}
void DefaultProgramBreak(FEXCore::Core::InternalThreadState *Thread, uint64_t Addr);
@@ -22,5 +22,6 @@ public:
uint64_t child_tid{0};
uint64_t parent_tid{0};
uint64_t robust_list_head{0};
bool clear_tid{false};
};
}