Removes syscall's FD remapper

Required because we can't track all FD remapping
This commit is contained in:
Ryan Houdek 2020-03-03 02:42:33 -08:00 committed by Stefanos Kornilios Mitsis Poiitidis
parent b0df2e4f18
commit 0d870147ec
6 changed files with 255 additions and 479 deletions

View File

@ -73,20 +73,28 @@ address sizes : 43 bits physical, 48 bits virtual
EmulatedMap.emplace("/proc/cpuinfo");
EmulatedMap.emplace("/sys/devices/system/cpu/online");
FDReadCreators["/proc/cpuinfo"] = [&](FEXCore::Context::Context *ctx, int32_t fd, const char *pathname, int32_t flags, mode_t mode) -> FEXCore::FD* {
return new SimpleStringFD(ctx, fd, pathname, flags, mode, proc_cpuinfo);
FDReadCreators["/proc/cpuinfo"] = [&](FEXCore::Context::Context *ctx, int32_t fd, const char *pathname, int32_t flags, mode_t mode) -> int32_t {
FILE *fp = tmpfile();
fwrite((void*)&proc_cpuinfo.at(0), sizeof(uint8_t), proc_cpuinfo.size(), fp);
fseek(fp, 0, SEEK_SET);
int32_t f = fileno(fp);
return f;
};
FDReadCreators["/sys/devices/system/cpu/online"] = [&](FEXCore::Context::Context *ctx, int32_t fd, const char *pathname, int32_t flags, mode_t mode) -> FEXCore::FD* {
return new SimpleStringFD(ctx, fd, pathname, flags, mode, cpus_online);
FDReadCreators["/sys/devices/system/cpu/online"] = [&](FEXCore::Context::Context *ctx, int32_t fd, const char *pathname, int32_t flags, mode_t mode) -> int32_t {
FILE *fp = tmpfile();
fwrite((void*)&cpus_online.at(0), sizeof(uint8_t), cpus_online.size(), fp);
fseek(fp, 0, SEEK_SET);
int32_t f = fileno(fp);
return f;
};
}
EmulatedFDManager::~EmulatedFDManager() {
}
FEXCore::FD *EmulatedFDManager::OpenAt(int dirfs, const char *pathname, int flags, uint32_t mode) {
int32_t EmulatedFDManager::OpenAt(int dirfs, const char *pathname, int flags, uint32_t mode) {
if (EmulatedMap.find(pathname) == EmulatedMap.end()) {
return nullptr;
return -1;
}
return FDReadCreators[pathname](CTX, dirfs, pathname, flags, mode);

View File

@ -17,11 +17,11 @@ namespace FEXCore::EmulatedFile {
public:
EmulatedFDManager(FEXCore::Context::Context *ctx);
~EmulatedFDManager();
FEXCore::FD *OpenAt(int dirfs, const char *pathname, int flags, uint32_t mode);
int32_t OpenAt(int dirfs, const char *pathname, int flags, uint32_t mode);
private:
FEXCore::Context::Context *CTX;
using FDReadStringFunc = std::function<FEXCore::FD*(FEXCore::Context::Context *ctx, int32_t fd, const char *pathname, int32_t flags, mode_t mode)>;
using FDReadStringFunc = std::function<int32_t(FEXCore::Context::Context *ctx, int32_t fd, const char *pathname, int32_t flags, mode_t mode)>;
std::unordered_set<std::string> EmulatedMap;
std::unordered_map<std::string, FDReadStringFunc> FDReadCreators;
};

View File

@ -5,6 +5,7 @@
#include <fcntl.h>
#include <sys/epoll.h>
#include <sys/eventfd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/ioctl.h>
@ -19,7 +20,6 @@ class STDFD final : public FD {
public:
STDFD(FEXCore::Context::Context *ctx, int32_t fd, const char *pathname, int32_t flags, mode_t mode)
: FD (ctx, fd, pathname, flags, mode) {
HostFD = fd;
}
ssize_t writev(int fd, void *iov, int iovcnt) override {
@ -86,42 +86,13 @@ public:
}
};
class SocketFD final : public FD {
public:
SocketFD(FEXCore::Context::Context *ctx, int32_t fd, int domain, int type, int protocol)
: FD (ctx, fd, "Socket", 0, 0) {
HostFD = socket(domain, type, protocol);
}
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);
}
};
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);
return ::read(fd, 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);
return ::writev(fd, reinterpret_cast<const struct iovec*>(iov), iovcnt);
}
const struct iovec *Guestiov = reinterpret_cast<const struct iovec*>(iov);
@ -137,7 +108,7 @@ ssize_t FD::writev(int fd, void *iov, int iovcnt) {
Hostiov[i].iov_len = Guestiov[i].iov_len;
}
return ::writev(HostFD, &Hostiov.at(0), iovcnt);
return ::writev(fd, &Hostiov.at(0), iovcnt);
}
uint64_t FD::write(int fd, void *buf, size_t count) {
@ -145,39 +116,32 @@ uint64_t FD::write(int fd, void *buf, size_t count) {
}
int FD::openat(int dirfd, const char *pathname, int flags, mode_t mode) {
HostFD = ::openat(dirfd, pathname, flags, mode);
return HostFD;
FDOffset = ::openat(dirfd, pathname, flags, mode);
return FDOffset;
}
int FD::fstat(int fd, struct stat *buf) {
return ::fstat(HostFD, buf);
return ::fstat(fd, buf);
}
int FD::close(int fd) {
return ::close(HostFD);
return ::close(fd);
}
int FD::ioctl(int fd, uint64_t request, void *args) {
return ::ioctl(HostFD, request, args);
return ::ioctl(fd, request, args);
}
int FD::lseek(int fd, off_t offset, int whence) {
return ::lseek(HostFD, offset, whence);
return ::lseek(fd, offset, whence);
}
FileManager::FileManager(FEXCore::Context::Context *ctx)
: CTX {ctx}
, EmuFD {ctx} {
FDMap[CurrentFDOffset++] = new STDFD{CTX, STDIN_FILENO, "stdin", 0, 0};
FDMap[CurrentFDOffset++] = new STDFD{CTX, STDOUT_FILENO, "stdout", 0, 0};
FDMap[CurrentFDOffset++] = new STDFD{CTX, STDERR_FILENO, "stderr", 0, 0};
}
FileManager::~FileManager() {
for (auto &FD : FDMap) {
delete FD.second;
}
}
std::string FileManager::GetEmulatedPath(const char *pathname) {
@ -189,23 +153,11 @@ std::string FileManager::GetEmulatedPath(const char *pathname) {
}
uint64_t FileManager::Read(int fd, [[maybe_unused]] void *buf, [[maybe_unused]] size_t count) {
auto FD = FDMap.find(fd);
if (FD == FDMap.end()) {
LogMan::Msg::I("XXX: Implement Read: %d", fd);
return -1;
}
return FD->second->read(fd, buf, count);
return ::read(fd, buf, count);
}
uint64_t FileManager::Write(int fd, void *buf, size_t count) {
auto FD = FDMap.find(fd);
if (FD == FDMap.end()) {
LogMan::Msg::I("XXX: Implement write: %d", fd);
return -1;
}
return FD->second->write(fd, buf, count);
return ::write(fd, buf, count);
}
uint64_t FileManager::Open(const char *pathname, [[maybe_unused]] int flags, [[maybe_unused]] uint32_t mode) {
@ -214,15 +166,8 @@ uint64_t FileManager::Open(const char *pathname, [[maybe_unused]] int flags, [[m
}
uint64_t FileManager::Close(int fd) {
auto FD = FDMap.find(fd);
if (FD == FDMap.end()) {
LogMan::Msg::I("XXX: Trying to close: '%d'", fd);
return 0;
}
int Result = FD->second->close(fd);
delete FD->second;
FDMap.erase(FD);
int Result = ::close(fd);
FDToNameMap.erase(fd);
return Result;
}
@ -239,7 +184,7 @@ uint64_t FileManager::Stat(const char *pathname, void *buf) {
uint64_t FileManager::Fstat(int fd, void *buf) {
if (fd == STDOUT_FILENO || fd == STDERR_FILENO) {
struct stat TmpBuf;
int Result = fstat(fd, &TmpBuf);
int Result = ::fstat(fd, &TmpBuf);
// Blow away access times
// Causes issues with lockstep runner and file acesses
@ -251,15 +196,8 @@ uint64_t FileManager::Fstat(int fd, void *buf) {
memcpy(buf, &TmpBuf, sizeof(struct stat));
return Result;
}
else {
auto FD = FDMap.find(fd);
if (FD != FDMap.end()) {
return FD->second->fstat(fd, reinterpret_cast<struct stat*>(buf));
}
}
LogMan::Msg::D("Attempting to fstat: %d", fd);
return -1LL;
return ::fstat(fd, reinterpret_cast<struct stat*>(buf));
}
uint64_t FileManager::Lstat(const char *path, void *buf) {
@ -274,22 +212,11 @@ uint64_t FileManager::Lstat(const char *path, void *buf) {
}
uint64_t FileManager::Lseek(int fd, uint64_t offset, int whence) {
auto fdPtr = FDMap.find(fd);
if (fdPtr == FDMap.end()) {
LogMan::Msg::E("XXX: Trying to lseek unknown fd: %d", fd);
return -1LL;
}
return fdPtr->second->lseek(fd, offset, whence);
return ::lseek(fd, offset, whence);
}
uint64_t FileManager::Writev(int fd, void *iov, int iovcnt) {
auto fdPtr = FDMap.find(fd);
if (fdPtr == FDMap.end()) {
LogMan::Msg::E("XXX: Trying to writev unknown fd: %d", fd);
return FDMap.find(0)->second->writev(0, iov, iovcnt);
return -1LL;
}
return fdPtr->second->writev(fd, iov, iovcnt);
return ::writev(fd, reinterpret_cast<iovec const *>(iov), iovcnt);
}
uint64_t FileManager::Access(const char *pathname, [[maybe_unused]] int mode) {
@ -321,45 +248,11 @@ uint64_t FileManager::FAccessat(int dirfd, const char *pathname, int mode, int f
}
uint64_t FileManager::Pipe(int pipefd[2]) {
int HostFD[2];
int Result = ::pipe(HostFD);
{
int32_t fd = CurrentFDOffset;
auto fdPtr = new FD{CTX, fd, "<Pipe>", 0, 0};
fdPtr->SetHostFD(HostFD[0]);
pipefd[0] = fd;
FDMap[CurrentFDOffset++] = fdPtr;
}
{
int32_t fd = CurrentFDOffset;
auto fdPtr = new FD{CTX, fd, "<Pipe>", 0, 0};
fdPtr->SetHostFD(HostFD[1]);
pipefd[1] = fd;
FDMap[CurrentFDOffset++] = fdPtr;
}
int Result = ::pipe(pipefd);
return Result;
}
uint64_t FileManager::Pipe2(int pipefd[2], int flags) {
int HostFD[2];
int Result = ::pipe2(HostFD, flags);
{
int32_t fd = CurrentFDOffset;
auto fdPtr = new FD{CTX, fd, "<Pipe>", 0, 0};
fdPtr->SetHostFD(HostFD[0]);
pipefd[0] = fd;
FDMap[CurrentFDOffset++] = fdPtr;
}
{
int32_t fd = CurrentFDOffset;
auto fdPtr = new FD{CTX, fd, "<Pipe>", 0, 0};
fdPtr->SetHostFD(HostFD[1]);
pipefd[1] = fd;
FDMap[CurrentFDOffset++] = fdPtr;
}
int Result = ::pipe2(pipefd, flags);
return Result;
}
@ -396,43 +289,29 @@ uint64_t FileManager::Readlinkat(int dirfd, const char *pathname, char *buf, siz
}
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")) {
FDMap[CurrentFDOffset++] = new STDFD{CTX, STDOUT_FILENO, "/dev/tty", 0, 0};
return fd;
}
int32_t fd = -1;
auto fdPtr = EmuFD.OpenAt(dirfs, pathname, flags, mode);
if (!fdPtr) {
fdPtr = new FD{CTX, fd, pathname, flags, mode};
uint64_t Result = -1;
fd = EmuFD.OpenAt(dirfs, pathname, flags, mode);
if (fd == -1) {
auto Path = GetEmulatedPath(pathname);
if (!Path.empty()) {
Result = fdPtr->openat(dirfs, Path.c_str(), flags, mode);
fd = ::openat(dirfs, Path.c_str(), flags, mode);
}
if (Result == -1)
Result = fdPtr->openat(dirfs, pathname, flags, mode);
if (fd == -1)
fd = ::openat(dirfs, pathname, flags, mode);
if (Result == -1) {
delete fdPtr;
if (fd == -1) {
return -errno;
}
}
FDMap[CurrentFDOffset++] = fdPtr;
FDToNameMap[fd] = pathname;
return fd;
}
uint64_t FileManager::Ioctl(int fd, uint64_t request, void *args) {
auto FD = FDMap.find(fd);
if (FD == FDMap.end()) {
return -1;
}
uint64_t Result = FD->second->ioctl(fd, request, args);
uint64_t Result = ::ioctl(fd, request, args);
if (Result == -1) {
return -errno;
}
@ -441,35 +320,17 @@ uint64_t FileManager::Ioctl(int fd, uint64_t request, void *args) {
}
uint64_t FileManager::GetDents(int fd, void *dirp, uint32_t count) {
auto FD = FDMap.find(fd);
if (FD == FDMap.end()) {
return -1;
}
return syscall(SYS_getdents64,
static_cast<uint64_t>(FD->second->GetHostFD()),
static_cast<uint64_t>(fd),
reinterpret_cast<uint64_t>(dirp),
static_cast<uint64_t>(count));
}
uint64_t FileManager::PRead64(int fd, void *buf, size_t count, off_t offset) {
auto FD = FDMap.find(fd);
if (FD == FDMap.end()) {
return -1;
}
return pread(FD->second->GetHostFD(), buf, count, offset);
return pread(fd, 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);
@ -489,14 +350,12 @@ uint64_t FileManager::Mknod(const char *pathname, mode_t mode, dev_t dev) {
return ::mknod(pathname, mode, dev);
}
uint64_t FileManager::Ftruncate(int fd, off_t length) {
return ftruncate(fd, length);
}
uint64_t FileManager::EPoll_Create1(int flags) {
int HostFD = epoll_create1(flags);
int32_t fd = CurrentFDOffset;
auto fdPtr = new FD{CTX, fd, "<EPoll>", 0, 0};
fdPtr->SetHostFD(HostFD);
FDMap[CurrentFDOffset++] = fdPtr;
return fd;
return epoll_create1(flags);
}
uint64_t FileManager::Statfs(const char *path, void *buf) {
@ -509,45 +368,30 @@ uint64_t FileManager::Statfs(const char *path, void *buf) {
return ::statfs(path, reinterpret_cast<struct statfs*>(buf));
}
uint64_t FileManager::FStatfs(int fd, void *buf) {
return ::fstatfs(fd, 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;
int32_t fd = eventfd(initval, flags);
if (fd == -1) {
return -errno;
}
FDMap[CurrentFDOffset++] = fdPtr;
return fd;
}
uint64_t FileManager::Socket(int domain, int type, int protocol) {
int32_t fd = CurrentFDOffset;
auto fdPtr = new SocketFD{CTX, fd, domain, type, protocol};
auto Result = fdPtr->GetHostFD();
if (Result == -1) {
delete fdPtr;
return -1;
int fd = socket(domain, type, protocol);
if (fd == -1) {
return -errno;
}
FDMap[CurrentFDOffset++] = fdPtr;
return fd;
}
uint64_t FileManager::Connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
auto FD = FDMap.find(sockfd);
if (FD == FDMap.end()) {
return -1;
}
int Result = connect(FD->second->GetHostFD(), addr, addrlen);
int Result = connect(sockfd, addr, addrlen);
if (Result == -1) {
return -errno;
}
@ -555,57 +399,18 @@ uint64_t FileManager::Connect(int sockfd, const struct sockaddr *addr, socklen_t
}
uint64_t FileManager::Recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen) {
auto FD = FDMap.find(sockfd);
if (FD == FDMap.end()) {
return -1;
int Result = recvfrom(sockfd, buf, len, flags, src_addr, addrlen);
if (Result == -1) {
return -errno;
}
return Result;
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;
}
int Result{};
if (CTX->Config.UnifiedMemory) {
if (msg->msg_control && msg->msg_controllen > 0) {
// If we have ancillary data then we need to transform the data
struct msghdr Hosthdr;
memcpy(&Hosthdr, msg, sizeof(struct msghdr));
void *New_msg_control = malloc(Hosthdr.msg_controllen);
memcpy(New_msg_control, Hosthdr.msg_control, Hosthdr.msg_controllen);
Hosthdr.msg_control = New_msg_control;
struct cmsghdr *cmsg = reinterpret_cast<struct cmsghdr*>(Hosthdr.msg_control);
switch (cmsg->cmsg_type) {
case SCM_RIGHTS: {
uint32_t *GuestFDs = 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) {
auto GuestFD = FDMap.find(GuestFDs[i]);
// Remap guestFDs back to hostFDs so the other process knows what the real FD is
if (GuestFD == FDMap.end()) {
LogMan::Msg::D("Couldn't find GuestFD %d", GuestFDs[i]);
}
else {
GuestFDs[i] = GuestFD->second->GetHostFD();
}
}
break;
}
default: LogMan::Msg::A("Unhandled Ancillary socket type: 0x%x", cmsg->cmsg_type); break;
}
Result = sendmsg(FD->second->GetHostFD(), &Hosthdr, flags);
free(New_msg_control);
}
else {
Result = sendmsg(FD->second->GetHostFD(), msg, flags);
}
Result = sendmsg(sockfd, msg, flags);
}
else {
std::vector<iovec> Hostvec;
@ -628,26 +433,18 @@ uint64_t FileManager::Sendmsg(int sockfd, const struct msghdr *msg, int flags) {
Hosthdr.msg_iov = &Hostvec.at(0);
Result = sendmsg(FD->second->GetHostFD(), &Hosthdr, flags);
Result = sendmsg(sockfd, &Hosthdr, flags);
}
if (Result == -1) {
if (errno == EAGAIN ||
errno == EWOULDBLOCK) {
return -errno;
}
return -errno;
}
return Result;
}
uint64_t FileManager::Recvmsg(int sockfd, struct msghdr *msg, int flags) {
auto FD = FDMap.find(sockfd);
if (FD == FDMap.end()) {
return -1;
}
int Result{};
if (CTX->Config.UnifiedMemory) {
Result = recvmsg(FD->second->GetHostFD(), msg, flags);
Result = recvmsg(sockfd, msg, flags);
}
else {
std::vector<iovec> Hostvec;
@ -670,165 +467,52 @@ uint64_t FileManager::Recvmsg(int sockfd, struct msghdr *msg, int flags) {
Hosthdr.msg_iov = &Hostvec.at(0);
Result = recvmsg(FD->second->GetHostFD(), &Hosthdr, flags);
Result = recvmsg(sockfd, &Hosthdr, flags);
}
if (Result == -1) {
if (errno == EAGAIN ||
errno == EWOULDBLOCK) {
return -errno;
}
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;
}
uint64_t FileManager::Shutdown(int sockfd, int how) {
auto FD = FDMap.find(sockfd);
if (FD == FDMap.end()) {
return -1;
}
return shutdown(FD->second->GetHostFD(), how);
return shutdown(sockfd, how);
}
uint64_t FileManager::GetSockName(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
auto FD = FDMap.find(sockfd);
if (FD == FDMap.end()) {
return -1;
}
return getsockname(FD->second->GetHostFD(), addr, addrlen);
return getsockname(sockfd, addr, addrlen);
}
uint64_t FileManager::GetPeerName(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
auto FD = FDMap.find(sockfd);
if (FD == FDMap.end()) {
return -1;
}
return getpeername(FD->second->GetHostFD(), addr, addrlen);
return getpeername(sockfd, addr, addrlen);
}
uint64_t FileManager::SetSockOpt(int sockfd, int level, int optname, const void *optval, socklen_t optlen) {
auto FD = FDMap.find(sockfd);
if (FD == FDMap.end()) {
return -1;
}
int Result = ::setsockopt(FD->second->GetHostFD(), level, optname, optval, optlen);
int Result = ::setsockopt(sockfd, level, optname, optval, optlen);
if (Result == -1)
return -errno;
return Result;
}
uint64_t FileManager::GetSockOpt(int sockfd, int level, int optname, void *optval, socklen_t *optlen) {
auto FD = FDMap.find(sockfd);
if (FD == FDMap.end()) {
return -1;
}
int Result = ::getsockopt(FD->second->GetHostFD(), level, optname, optval, optlen);
int Result = ::getsockopt(sockfd, level, optname, optval, optlen);
if (Result == -1)
return -errno;
return Result;
}
uint64_t FileManager::Poll(struct pollfd *fds, nfds_t nfds, int timeout) {
std::vector<pollfd> HostFDs;
HostFDs.resize(nfds);
memcpy(&HostFDs.at(0), fds, sizeof(pollfd) * nfds);
for (auto &FD : HostFDs) {
auto HostFD = FDMap.find(FD.fd);
if (HostFD == FDMap.end()) {
LogMan::Msg::D("Poll. Failed to map FD: %d", FD.fd);
return -1;
}
FD.fd = HostFD->second->GetHostFD();
}
int Result = poll(&HostFDs.at(0), nfds, timeout);
for (int i = 0; i < nfds; ++i) {
fds[i].revents = HostFDs[i].revents;
}
return Result;
return ::poll(fds, nfds, timeout);
}
uint64_t FileManager::Select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) {
fd_set Host_readfds;
fd_set Host_writefds;
fd_set Host_exceptfds;
FD_ZERO(&Host_readfds);
FD_ZERO(&Host_writefds);
FD_ZERO(&Host_exceptfds);
int Host_nfds = 0;
if (readfds) {
for (int i = 0; i < nfds; ++i) {
if (FD_ISSET(i, readfds)) {
auto HostFD = FDMap.find(i);
if (HostFD == FDMap.end())
return -1;
Host_nfds = std::max(Host_nfds, HostFD->second->GetHostFD());
FD_SET(HostFD->second->GetHostFD(), &Host_readfds);
}
}
}
if (writefds) {
for (int i = 0; i < nfds; ++i) {
if (FD_ISSET(i, writefds)) {
auto HostFD = FDMap.find(i);
if (HostFD == FDMap.end())
return -1;
Host_nfds = std::max(Host_nfds, HostFD->second->GetHostFD());
FD_SET(HostFD->second->GetHostFD(), &Host_writefds);
}
}
}
if (exceptfds) {
for (int i = 0; i < nfds; ++i) {
if (FD_ISSET(i, exceptfds)) {
auto HostFD = FDMap.find(i);
if (HostFD == FDMap.end())
return -1;
Host_nfds = std::max(Host_nfds, HostFD->second->GetHostFD());
FD_SET(HostFD->second->GetHostFD(), &Host_exceptfds);
}
}
}
return select(Host_nfds, readfds ? &Host_readfds : nullptr, writefds ? &Host_writefds : nullptr, exceptfds ? &Host_exceptfds : nullptr, timeout);
return select(nfds, readfds, writefds, exceptfds, timeout);
}
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;
}
LogMan::Throw::A(!CTX->Config.UnifiedMemory, "Not yet supported: Sendmmsg");
std::vector<mmsghdr> Hostmmghdr;
std::vector<iovec> Hostvec;
@ -864,59 +548,48 @@ uint64_t FileManager::Sendmmsg(int sockfd, struct mmsghdr *msgvec, uint32_t vlen
HostVecOffset += Hosthdr.msg_iovlen;
}
int Result = ::sendmmsg(FD->second->GetHostFD(), &Hostmmghdr.at(0), vlen, flags);
int Result = ::sendmmsg(sockfd, &Hostmmghdr.at(0), vlen, flags);
if (Result == -1)
return -errno;
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;
int32_t fd = timerfd_create(clockid, flags);
if (fd == -1) {
return -errno;
}
return fd;
}
FDMap[CurrentFDOffset++] = fdPtr;
uint64_t FileManager::Memfd_Create(const char *name, uint32_t flags) {
int32_t fd = memfd_create(name, flags);
if (fd== -1) {
return -errno;
}
return fd;
}
int32_t FileManager::FindHostFD(int fd) {
auto FD = FDMap.find(fd);
if (FD == FDMap.end()) {
return -1;
}
return FD->second->GetHostFD();
}
FD const* FileManager::GetFDBacking(int fd) {
auto FD = FDMap.find(fd);
if (FD == FDMap.end()) {
return nullptr;
}
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};
fdPtr->SetHostFD(newFD);
FDMap[CurrentFDOffset++] = fdPtr;
return fd;
}
std::string *FileManager::FindFDName(int fd) {
auto it = FDToNameMap.find(fd);
if (it == FDToNameMap.end()) {
return nullptr;
}
return &it->second;
}
FD const* FileManager::GetFDBacking(int fd) {
LogMan::Msg::A("DERP");
return nullptr;
}
int32_t FileManager::DupFD(int prevFD, int newFD) {
return ::dup2(prevFD, newFD);
}
}

View File

@ -45,8 +45,8 @@ public:
int ioctl(int fd, uint64_t request, void *args);
int lseek(int fd, off_t offset, int wehnce);
int GetHostFD() const { return HostFD; }
void SetHostFD(int fd) { HostFD = fd; }
int GetHostFD() const { return FDOffset; }
void SetHostFD(int fd) { FDOffset = fd; }
std::string const& GetName() const { return PathName; }
@ -56,8 +56,6 @@ protected:
std::string PathName;
[[maybe_unused]] int32_t Flags;
[[maybe_unused]] mode_t Mode;
int32_t HostFD;
};
class FileManager final {
@ -88,12 +86,14 @@ public:
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);
uint64_t Ftruncate(int fd, off_t length);
// EPoll
uint64_t EPoll_Create1(int flags);
// vfs
uint64_t Statfs(const char *path, void *buf);
uint64_t FStatfs(int fd, void *buf);
// Eventfd
uint64_t Eventfd(uint32_t initval, uint32_t flags);
@ -116,8 +116,12 @@ public:
// Timers
uint64_t Timer_Create(int32_t clockid, int32_t flags);
// MemFD
uint64_t Memfd_Create(const char *name, uint32_t flags);
int32_t FindHostFD(int fd);
std::string *FindFDName(int fd);
FD const* GetFDBacking(int fd);
int32_t DupFD(int prevFD, int newFD);
@ -126,10 +130,9 @@ public:
private:
FEXCore::Context::Context *CTX;
int32_t CurrentFDOffset{0};
std::unordered_map<int32_t, FD*> FDMap;
FEXCore::EmulatedFile::EmulatedFDManager EmuFD;
std::unordered_map<int32_t, std::string> FDToNameMap;
std::string Filename;
std::string GetEmulatedPath(const char *pathname);
};

View File

@ -10,12 +10,14 @@
#include <fcntl.h>
#include <limits.h>
#include <poll.h>
#include <linux/futex.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <sys/random.h>
#include <sys/sysinfo.h>
#include <sys/utsname.h>
#include <sys/shm.h>
#include <sys/syscall.h>
#include <unistd.h>
constexpr uint64_t PAGE_SIZE = 4096;
@ -95,6 +97,15 @@ void SyscallHandler::Strace(FEXCore::HLE::SyscallArguments *Args, uint64_t Ret)
LogMan::Msg::D("sched_yield() = %ld",
Ret);
break;
case SYSCALL_MREMAP:
LogMan::Msg::D("mremap(0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx) = %ld",
Args->Argument[1],
Args->Argument[2],
Args->Argument[3],
Args->Argument[4],
Args->Argument[5],
Ret);
break;
case SYSCALL_MINCORE:
LogMan::Msg::D("mincore(0x%lx, 0x%lx, 0x%lx) = %ld",
Args->Argument[1],
@ -182,6 +193,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_SCHED_SETSCHEDULER:
LogMan::Msg::D("sched_setscheduler(%ld, %p, %p) = %ld",
Args->Argument[1],
Args->Argument[2],
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],
@ -207,6 +225,9 @@ void SyscallHandler::Strace(FEXCore::HLE::SyscallArguments *Args, uint64_t Ret)
case SYSCALL_FCNTL:
LogMan::Msg::D("fcntl (%ld, %ld, 0x%lx) = %ld", Args->Argument[1], Args->Argument[2], Args->Argument[3], Ret);
break;
case SYSCALL_FTRUNCATE:
LogMan::Msg::D("ftruncate(%ld, 0x%lx) = %ld", Args->Argument[1], Args->Argument[2], Ret);
break;
case SYSCALL_UMASK:
LogMan::Msg::D("umask(0x%lx) = %ld", Args->Argument[1], Ret);
break;
@ -246,6 +267,9 @@ void SyscallHandler::Strace(FEXCore::HLE::SyscallArguments *Args, uint64_t Ret)
case SYSCALL_GETDENTS64:
LogMan::Msg::D("getdents(%ld, 0x%lx, %ld) = %ld", Args->Argument[1], Args->Argument[2], Args->Argument[3], Ret);
break;
case SYSCALL_FADVISE64:
LogMan::Msg::D("fadvise64(%ld, 0x%lx, %ld, %lx) = %ld", Args->Argument[1], Args->Argument[2], Args->Argument[3], Args->Argument[4], Ret);
break;
case SYSCALL_SET_TID_ADDRESS:
LogMan::Msg::D("set_tid_address(%p) = %ld", Args->Argument[1], Ret);
break;
@ -380,6 +404,9 @@ void SyscallHandler::Strace(FEXCore::HLE::SyscallArguments *Args, uint64_t Ret)
case SYSCALL_STATFS:
LogMan::Msg::D("statfs(\"%s\", {...}) = %ld", GetPointer<char const*>(Args->Argument[1]), Ret);
break;
case SYSCALL_FSTATFS:
LogMan::Msg::D("fstatfs(%ld, {...}) = %ld", Args->Argument[1], Ret);
break;
case SYSCALL_GETTID:
LogMan::Msg::D("gettid() = %ld", Ret);
break;
@ -408,8 +435,15 @@ void SyscallHandler::Strace(FEXCore::HLE::SyscallArguments *Args, uint64_t Ret)
Args->Argument[6],
Ret);
break;
case SYSCALL_SCHED_SETAFFINITY:
LogMan::Msg::D("sched_setaffinity(%ld, %ld, 0x%lx) = %ld",
Args->Argument[1],
Args->Argument[2],
Args->Argument[3],
Ret);
break;
case SYSCALL_SCHED_GETAFFINITY:
LogMan::Msg::D("sched_getaffinity(%ld, %ld, %ld, 0x%lx) = %ld",
LogMan::Msg::D("sched_getaffinity(%ld, %ld, 0x%lx) = %ld",
Args->Argument[1],
Args->Argument[2],
Args->Argument[3],
@ -431,6 +465,12 @@ void SyscallHandler::Strace(FEXCore::HLE::SyscallArguments *Args, uint64_t Ret)
Args->Argument[3],
Ret);
break;
case SYSCALL_MEMFD_CREATE:
LogMan::Msg::D("memfd_create(\"%s\", 0x%lx) = %ld",
GetPointer<char const*>(Args->Argument[1]),
Args->Argument[2],
Ret);
break;
case SYSCALL_STATX:
LogMan::Msg::D("statx(%ld, \"%s\", 0x%lx, 0x%lx, {...}) = %ld",
Args->Argument[1],
@ -527,11 +567,6 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa
case SYSCALL_MMAP: {
int Flags = Args->Argument[4];
int GuestFD = static_cast<int32_t>(Args->Argument[5]);
int HostFD = -1;
if (GuestFD != -1) {
HostFD = FM.FindHostFD(GuestFD);
}
uint64_t Base = AlignDown(LastMMAP, PAGE_SIZE);
uint64_t Size = AlignUp(Args->Argument[2], PAGE_SIZE);
@ -554,17 +589,23 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa
void *HostPtr = GetPointerSizeCheck(Base, FileSizeToUse);
if (!HostPtr) {
HostPtr = CTX->MapRegion(Thread, Base, Size, true);
if (GuestFD != -1) {
auto Name = FM.FindFDName(GuestFD);
if (Name) {
LogMan::Msg::D("Mapping File to [0x%lx, 0x%lx) -> '%s' -> %p", Base, Base + Size, Name->c_str(), HostPtr);
}
}
}
if (HostFD != -1) {
void *FileMem = mmap(HostPtr, FileSizeToUse, Prot, MAP_DENYWRITE | MAP_PRIVATE | MAP_FIXED, HostFD, Args->Argument[6]);
if (GuestFD != -1) {
void *FileMem = mmap(HostPtr, FileSizeToUse, Prot, MAP_DENYWRITE | MAP_PRIVATE | MAP_FIXED, GuestFD, Args->Argument[6]);
if (FileMem == MAP_FAILED) {
LogMan::Msg::A("Couldn't map file to %p\n", HostPtr);
}
}
else {
LogMan::Throw::A(Args->Argument[6] == 0, "Don't understand a fixed offset mmap");
mmap(HostPtr, Size, Prot, Flags, HostFD, Args->Argument[6]);
mmap(HostPtr, Size, Prot, Flags, GuestFD, Args->Argument[6]);
}
Result = Base;
@ -575,15 +616,24 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa
if (!HostPtr) {
HostPtr = CTX->MapRegion(Thread, Base, Size, true);
}
else {
if (GuestFD != -1) {
auto Name = FM.FindFDName(GuestFD);
if (Name) {
LogMan::Msg::D("Mapping File to [0x%lx, 0x%lx) -> '%s' -> %p", Base, Base + Size, Name->c_str(), HostPtr);
}
}
}
if (HostFD != -1) {
void *FileMem = mmap(HostPtr, FileSizeToUse, Prot, MAP_PRIVATE | MAP_FIXED, HostFD, Args->Argument[6]);
if (GuestFD != -1) {
void *FileMem = mmap(HostPtr, FileSizeToUse, Prot, MAP_PRIVATE | MAP_FIXED, GuestFD, Args->Argument[6]);
if (FileMem == MAP_FAILED) {
LogMan::Msg::A("Couldn't map file to %p\n", HostPtr);
perror(nullptr);
LogMan::Msg::A("Couldn't map file to %p. error %d(%s)\n", HostPtr, errno, strerror(errno));
}
}
else {
mmap(HostPtr, Size, Prot, Flags, HostFD, Args->Argument[6]);
mmap(HostPtr, Size, Prot, Flags, GuestFD, Args->Argument[6]);
}
LastMMAP += Size;
@ -592,10 +642,15 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa
break;
}
case SYSCALL_MPROTECT: {
void *HostPtr = CTX->MemoryMapper.GetPointer<void*>(Args->Argument[1]);
void *HostPtr = GetPointer<void*>(Args->Argument[1]);
Result = mprotect(HostPtr, Args->Argument[2], Args->Argument[3]);
break;
}
case SYSCALL_SCHED_SETSCHEDULER: {
// XXX: Not a real result
Result = 0;
break;
}
case SYSCALL_PRCTL: {
switch (Args->Argument[1]) {
case 0xF: // PR_SET_NAME
@ -754,6 +809,10 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa
Result = FM.Statfs(GetPointer<char const*>(Args->Argument[1]),
GetPointer(Args->Argument[2]));
break;
case SYSCALL_FSTATFS:
Result = FM.FStatfs(Args->Argument[1],
GetPointer(Args->Argument[2]));
break;
case SYSCALL_GETTID:
Result = Thread->State.ThreadManager.GetTID();
break;
@ -831,12 +890,31 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa
}
break;
}
case 9: { // WAKE_BITSET
// We don't actually support this
// Just handle it like a WAKE but wake up everything
Futex *futex = GetFutex(Args->Argument[1]);
if (!futex) {
// Tried to wake up an unknown futex?
Result = 0;
break;
}
Result = futex->Waiters;
futex->cv.notify_all();
break;
}
default:
LogMan::Msg::A("Unknown futex command");
LogMan::Msg::A("Unknown futex command: %d", Command);
break;
}
break;
}
case SYSCALL_SCHED_SETAFFINITY: {
// XXX: Not a real result
Result = 0;
break;
}
case SYSCALL_SCHED_GETAFFINITY: {
cpu_set_t *mask = GetPointer<cpu_set_t*>(Args->Argument[3]);
// Claim 1 CPU core
@ -1096,6 +1174,14 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa
Result = clock_getres(Args->Argument[1], res);
}
break;
case SYSCALL_MREMAP: {
Result = (uint64_t)mremap(GetPointer(Args->Argument[1]),
Args->Argument[2],
Args->Argument[3],
Args->Argument[4],
GetPointer(Args->Argument[5]));
break;
}
case SYSCALL_MINCORE: {
Result = mincore(GetPointer(Args->Argument[1]),
Args->Argument[2],
@ -1151,13 +1237,7 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa
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()));
}
Result = FM.DupFD(Args->Argument[1], Args->Argument[2]);
break;
}
case SYSCALL_NANOSLEEP: {
@ -1187,6 +1267,10 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa
Args->Argument[3]);
break;
}
case SYSCALL_FADVISE64: {
Result = posix_fadvise(Args->Argument[1], Args->Argument[2], Args->Argument[3], Args->Argument[4]);
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...
@ -1232,7 +1316,7 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa
case 3: { // Stack limits
rlimit *old_limit = GetPointer<rlimit*>(Args->Argument[4]);
// Default size
old_limit->rlim_cur = 8 * 1024;
old_limit->rlim_cur = 8 * 1024 * 1024;
old_limit->rlim_max = ~0ULL;
break;
}
@ -1291,40 +1375,41 @@ uint64_t SyscallHandler::HandleSyscall(FEXCore::Core::InternalThreadState *Threa
break;
case SYSCALL_FCNTL: {
int Cmd = Args->Argument[2];
auto FD = FM.GetFDBacking(Args->Argument[1]);
if (!FD) {
Result = EBADF;
}
else {
auto HostFD = FD->GetHostFD();
switch (Cmd) {
case 0: // F_DUPFD
case 1030:{ // F_DUPFD_CLOEXEC
Result = FM.DupFD(Args->Argument[1], dup(HostFD));
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;
switch (Cmd) {
case 0: // F_DUPFD
case 1030:{ // F_DUPFD_CLOEXEC
Result = fcntl(Args->Argument[1], Cmd, Args->Argument[3]);
break;
}
case 1: // F_GETFD
Result = fcntl(Args->Argument[1], Cmd);
break;
case 2: // F_SETFD
Result = fcntl(Args->Argument[1], Cmd, Args->Argument[3]);
break;
case 3: // F_GETFL
Result = fcntl(Args->Argument[1], Cmd);
break;
case 4: // F_SETFL
Result = fcntl(Args->Argument[1], Cmd, Args->Argument[3]);
break;
default: LogMan::Msg::A("FCNTL: Unknown Command: %ld", Cmd); break;
}
break;
}
case SYSCALL_FTRUNCATE:
Result = FM.Ftruncate(Args->Argument[1],
Args->Argument[2]);
break;
case SYSCALL_GETRANDOM:
Result = getrandom(GetPointer<void*>(Args->Argument[1]),
Args->Argument[2],
Args->Argument[3]);
break;
case SYSCALL_MEMFD_CREATE: {
Result = FM.Memfd_Create(GetPointer<char const*>(Args->Argument[1]), Args->Argument[2]);;
break;
}
case SYSCALL_STATX:
Result = FM.Statx(
Args->Argument[1],

View File

@ -38,6 +38,7 @@ enum Syscalls {
SYSCALL_PIPE = 22, ///< __NR_pipe
SYSCALL_SELECT = 23, ///< __NR_select
SYSCALL_SCHED_YIELD = 24, ///< __NR_sched_yield
SYSCALL_MREMAP = 25, ///< __NR_mremap
SYSCALL_MINCORE = 27, ///< __NR_mincore
SYSCALL_SHMGET = 29, ///< __NR_shmget
SYSCALL_SHMAT = 30, ///< __NR_shmat
@ -64,6 +65,7 @@ enum Syscalls {
SYSCALL_UNAME = 63, ///< __NR_uname
SYSCALL_SHMDT = 67, ///< __NR_shmdt
SYSCALL_FCNTL = 72, ///< __NR_fcntl
SYSCALL_FTRUNCATE = 77, ///< __NR_ftruncate
SYSCALL_GETCWD = 79, ///< __NR_getcwd
SYSCALL_CHDIR = 80, ///< __NR_chdir
SYSCALL_MKDIR = 83, ///< __NR_mkdir
@ -84,13 +86,17 @@ enum Syscalls {
SYSCALL_SIGALTSTACK = 131, ///< __NR_sigaltstack
SYSCALL_MKNOD = 133, ///< __NR_mknod
SYSCALL_STATFS = 137, ///< __NR_statfs
SYSCALL_FSTATFS = 138, ///< __NR_fstatfs
SYSCALL_SCHED_SETSCHEDULER = 144, ///< __NR_sched_setscheduler
SYSCALL_PRCTL = 157, ///< __NR_prctl
SYSCALL_ARCH_PRCTL = 158, ///< __NR_arch_prctl
SYSCALL_GETTID = 186, ///< __NR_gettid
SYSCALL_TIME = 201, ///< __NR_time
SYSCALL_FUTEX = 202, ///< __NR_futex
SYSCALL_SCHED_SETAFFINITY = 203, ///< __NR_sched_setaffinity
SYSCALL_SCHED_GETAFFINITY = 204, ///< __NR_sched_getaffinity
SYSCALL_GETDENTS64 = 217, ///< __NR_getdents64
SYSCALL_FADVISE64 = 221, ///< __NR_fadvise64
SYSCALL_SET_TID_ADDRESS = 218, ///< __NR_set_tid_address
SYSCALL_CLOCK_GETTIME = 228, ///< __NR_clock_gettime
SYSCALL_CLOCK_GETRES = 229, ///< __NR_clock_getres
@ -107,6 +113,7 @@ enum Syscalls {
SYSCALL_PRLIMIT64 = 302, ///< __NR_prlimit64
SYSCALL_SENDMMSG = 307, ///< __NR_sendmmsg
SYSCALL_GETRANDOM = 318, ///< __NR_getrandom
SYSCALL_MEMFD_CREATE = 319, ///< __NR_memfd_create
SYSCALL_STATX = 332, ///< __NR_statx
};