Files
FEX-Emu--FEX/Source/Tests/LinuxSyscalls/x64/FD.cpp
T
Ryan Houdek 565f0e6af3 Handle FD flag remapping correctly
FD flag remapping was broken. It would remap one flag on to another and then the next check would remap it back.

Instead keep a mask of the flags to be remapped then remap them all at the end.
Also goes through the ops and fixes a few cases where it was remapping wrong flags.
2021-05-11 18:29:21 -07:00

237 lines
8.9 KiB
C++

/*
$info$
tags: LinuxSyscalls|syscalls-x86-64
$end_info$
*/
#include "Tests/LinuxSyscalls/Syscalls.h"
#include "Tests/LinuxSyscalls/x64/Syscalls.h"
#include <FEXCore/Core/Context.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/uio.h>
#include <sys/sendfile.h>
#include <sys/syscall.h>
#include <unistd.h>
namespace FEX::HLE::x64 {
struct __attribute__((packed)) guest_stat {
__kernel_ulong_t st_dev;
__kernel_ulong_t st_ino;
__kernel_ulong_t st_nlink;
unsigned int st_mode;
unsigned int st_uid;
unsigned int st_gid;
unsigned int __pad0;
__kernel_ulong_t st_rdev;
__kernel_long_t st_size;
__kernel_long_t st_blksize;
__kernel_long_t st_blocks; /* Number 512-byte blocks allocated. */
__kernel_ulong_t st_atime_;
__kernel_ulong_t st_atime_nsec;
__kernel_ulong_t st_mtime_;
__kernel_ulong_t st_mtime_nsec;
__kernel_ulong_t st_ctime_;
__kernel_ulong_t st_ctime_nsec;
__kernel_long_t __unused[3];
};
static void CopyStat(guest_stat *guest, struct stat *host) {
#define COPY(x) guest->x = host->x
COPY(st_dev);
COPY(st_ino);
COPY(st_nlink);
COPY(st_mode);
COPY(st_uid);
COPY(st_gid);
COPY(st_rdev);
COPY(st_size);
COPY(st_blksize);
COPY(st_blocks);
guest->st_atime_ = host->st_atim.tv_sec;
guest->st_atime_nsec = host->st_atim.tv_nsec;
guest->st_mtime_ = host->st_mtime;
guest->st_mtime_nsec = host->st_mtim.tv_nsec;
guest->st_ctime_ = host->st_ctime;
guest->st_ctime_nsec = host->st_ctim.tv_nsec;
#undef COPY
}
void RegisterFD() {
REGISTER_SYSCALL_IMPL_X64(poll, [](FEXCore::Core::CpuStateFrame *Frame, struct pollfd *fds, nfds_t nfds, int timeout) -> uint64_t {
uint64_t Result = ::poll(fds, nfds, timeout);
SYSCALL_ERRNO();
});
REGISTER_SYSCALL_IMPL_X64(select, [](FEXCore::Core::CpuStateFrame *Frame, int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) -> uint64_t {
uint64_t Result = ::select(nfds, readfds, writefds, exceptfds, timeout);
SYSCALL_ERRNO();
});
REGISTER_SYSCALL_IMPL_X64(fcntl, [](FEXCore::Core::CpuStateFrame *Frame, int fd, int cmd, uint64_t arg) -> uint64_t {
uint64_t Result{};
switch (cmd) {
case F_GETFL:
Result = ::fcntl(fd, cmd, arg);
if (Result != -1) {
Result = FEX::HLE::RemapToX86Flags(Result);
}
break;
case F_SETFL:
Result = ::fcntl(fd, cmd, FEX::HLE::RemapFromX86Flags(arg));
break;
default:
Result = ::fcntl(fd, cmd, arg);
break;
}
SYSCALL_ERRNO();
});
REGISTER_SYSCALL_IMPL_X64(futimesat, [](FEXCore::Core::CpuStateFrame *Frame, int dirfd, const char *pathname, const struct timeval times[2]) -> uint64_t {
uint64_t Result = ::futimesat(dirfd, pathname, times);
SYSCALL_ERRNO();
});
REGISTER_SYSCALL_IMPL_X64(utimensat, [](FEXCore::Core::CpuStateFrame *Frame, int dirfd, const char *pathname, const struct timespec times[2], int flags) -> uint64_t {
uint64_t Result = ::syscall(SYS_utimensat, dirfd, pathname, times, flags);
SYSCALL_ERRNO();
});
REGISTER_SYSCALL_IMPL_X64(pselect6, [](FEXCore::Core::CpuStateFrame *Frame, int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *timeout, const void *sigmaskpack) -> uint64_t {
uint64_t Result = ::syscall(SYS_pselect6, nfds, readfds, writefds, exceptfds, timeout, sigmaskpack);
SYSCALL_ERRNO();
});
REGISTER_SYSCALL_IMPL_X64(stat, [](FEXCore::Core::CpuStateFrame *Frame, const char *pathname, guest_stat *buf) -> uint64_t {
struct stat host_stat;
uint64_t Result = FEX::HLE::_SyscallHandler->FM.Stat(pathname, &host_stat);
if (Result != -1) {
CopyStat(buf, &host_stat);
}
SYSCALL_ERRNO();
});
REGISTER_SYSCALL_IMPL_X64(fstat, [](FEXCore::Core::CpuStateFrame *Frame, int fd, guest_stat *buf) -> uint64_t {
struct stat host_stat;
uint64_t Result = ::fstat(fd, &host_stat);
if (Result != -1) {
CopyStat(buf, &host_stat);
}
SYSCALL_ERRNO();
});
REGISTER_SYSCALL_IMPL_X64(lstat, [](FEXCore::Core::CpuStateFrame *Frame, const char *path, guest_stat *buf) -> uint64_t {
struct stat host_stat;
uint64_t Result = FEX::HLE::_SyscallHandler->FM.Lstat(path, &host_stat);
if (Result != -1) {
CopyStat(buf, &host_stat);
}
SYSCALL_ERRNO();
});
REGISTER_SYSCALL_IMPL_X64(readv, [](FEXCore::Core::CpuStateFrame *Frame, int fd, const struct iovec *iov, int iovcnt) -> uint64_t {
uint64_t Result = ::readv(fd, iov, iovcnt);
SYSCALL_ERRNO();
});
REGISTER_SYSCALL_IMPL_X64(writev, [](FEXCore::Core::CpuStateFrame *Frame, int fd, const struct iovec *iov, int iovcnt) -> uint64_t {
uint64_t Result = ::writev(fd, iov, iovcnt);
SYSCALL_ERRNO();
});
REGISTER_SYSCALL_IMPL_X64(newfstatat, [](FEXCore::Core::CpuStateFrame *Frame, int dirfd, const char *pathname, guest_stat *buf, int flag) -> uint64_t {
struct stat host_stat;
uint64_t Result = FEX::HLE::_SyscallHandler->FM.NewFSStatAt(dirfd, pathname, &host_stat, flag);
if (Result != -1) {
CopyStat(buf, &host_stat);
}
SYSCALL_ERRNO();
});
REGISTER_SYSCALL_IMPL_X64(vmsplice, [](FEXCore::Core::CpuStateFrame *Frame, int fd, const struct iovec *iov, unsigned long nr_segs, unsigned int flags) -> uint64_t {
uint64_t Result = ::vmsplice(fd, iov, nr_segs, flags);
SYSCALL_ERRNO();
});
REGISTER_SYSCALL_IMPL_X64(preadv, [](FEXCore::Core::CpuStateFrame *Frame, int fd, const struct iovec *iov, int iovcnt, off_t offset) -> uint64_t {
uint64_t Result = ::preadv(fd, iov, iovcnt, offset);
SYSCALL_ERRNO();
});
REGISTER_SYSCALL_IMPL_X64(pwritev, [](FEXCore::Core::CpuStateFrame *Frame, int fd, const struct iovec *iov, int iovcnt, off_t offset) -> uint64_t {
uint64_t Result = ::pwritev(fd, iov, iovcnt, offset);
SYSCALL_ERRNO();
});
REGISTER_SYSCALL_IMPL_X64(preadv2, [](FEXCore::Core::CpuStateFrame *Frame, int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags) -> uint64_t {
uint64_t Result = ::preadv2(fd, iov, iovcnt, offset, flags);
SYSCALL_ERRNO();
});
REGISTER_SYSCALL_IMPL_X64(pwritev2, [](FEXCore::Core::CpuStateFrame *Frame, int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags) -> uint64_t {
uint64_t Result = ::pwritev2(fd, iov, iovcnt, offset, flags);
SYSCALL_ERRNO();
});
REGISTER_SYSCALL_IMPL_X64(process_vm_readv, [](FEXCore::Core::CpuStateFrame *Frame, pid_t pid, const struct iovec *local_iov, unsigned long liovcnt, const struct iovec *remote_iov, unsigned long riovcnt, unsigned long flags) -> uint64_t {
uint64_t Result = ::process_vm_readv(pid, local_iov, liovcnt, remote_iov, riovcnt, flags);
SYSCALL_ERRNO();
});
REGISTER_SYSCALL_IMPL_X64(process_vm_writev, [](FEXCore::Core::CpuStateFrame *Frame, pid_t pid, const struct iovec *local_iov, unsigned long liovcnt, const struct iovec *remote_iov, unsigned long riovcnt, unsigned long flags) -> uint64_t {
uint64_t Result = ::process_vm_writev(pid, local_iov, liovcnt, remote_iov, riovcnt, flags);
SYSCALL_ERRNO();
});
REGISTER_SYSCALL_IMPL_X64(ppoll, [](FEXCore::Core::CpuStateFrame *Frame, struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts, const sigset_t *sigmask, size_t sigsetsize) -> uint64_t {
// sigsetsize is unused here since it is currently a constant and not exposed through glibc
uint64_t Result = ::ppoll(fds, nfds, timeout_ts, sigmask);
SYSCALL_ERRNO();
});
REGISTER_SYSCALL_IMPL_X64(getdents, [](FEXCore::Core::CpuStateFrame *Frame, int fd, void *dirp, uint32_t count) -> uint64_t {
#ifdef SYS_getdents
uint64_t Result = syscall(SYS_getdents,
static_cast<uint64_t>(fd),
reinterpret_cast<uint64_t>(dirp),
static_cast<uint64_t>(count));
SYSCALL_ERRNO();
#else
// XXX: Emulate
return -EFAULT;
#endif
});
REGISTER_SYSCALL_IMPL_X64(getdents64, [](FEXCore::Core::CpuStateFrame *Frame, int fd, void *dirp, uint32_t count) -> uint64_t {
uint64_t Result = syscall(SYS_getdents64,
static_cast<uint64_t>(fd),
reinterpret_cast<uint64_t>(dirp),
static_cast<uint64_t>(count));
SYSCALL_ERRNO();
});
REGISTER_SYSCALL_IMPL_X64(sendfile, [](FEXCore::Core::CpuStateFrame *Frame, int out_fd, int in_fd, off_t *offset, size_t count) -> uint64_t {
uint64_t Result = ::sendfile(out_fd, in_fd, offset, count);
SYSCALL_ERRNO();
});
REGISTER_SYSCALL_IMPL_X64(dup, [](FEXCore::Core::CpuStateFrame *Frame, int oldfd) -> uint64_t {
uint64_t Result = ::dup(oldfd);
SYSCALL_ERRNO();
});
REGISTER_SYSCALL_IMPL_X64(dup2, [](FEXCore::Core::CpuStateFrame *Frame, int oldfd, int newfd) -> uint64_t {
uint64_t Result = ::dup2(oldfd, newfd);
SYSCALL_ERRNO();
});
}
}