diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/EPoll.cpp b/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/EPoll.cpp index d1ab9cdf8f..40b683fd46 100644 --- a/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/EPoll.cpp +++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/EPoll.cpp @@ -9,7 +9,6 @@ tags: LinuxSyscalls|syscalls-x86-64 #include "LinuxSyscalls/Syscalls.h" #include "LinuxSyscalls/Types.h" #include "LinuxSyscalls/x64/Syscalls.h" -#include "LinuxSyscalls/x64/Types.h" #include @@ -26,69 +25,71 @@ struct CpuStateFrame; } namespace FEX::HLE::x64 { -void RegisterEpoll(FEX::HLE::SyscallHandler* Handler) { - REGISTER_SYSCALL_IMPL_X64( - epoll_wait, [](FEXCore::Core::CpuStateFrame* Frame, int epfd, FEX::HLE::epoll_event_x86* events, int maxevents, int timeout) -> uint64_t { - fextl::vector Events(std::max(0, maxevents)); - uint64_t Result = ::syscall(SYSCALL_DEF(epoll_pwait), epfd, Events.data(), maxevents, timeout, nullptr, 8); - - if (Result != -1) { - FaultSafeUserMemAccess::VerifyIsWritable(events, sizeof(FEX::HLE::epoll_event_x86) * Result); - for (size_t i = 0; i < Result; ++i) { - events[i] = Events[i]; - } - } - SYSCALL_ERRNO(); - }); - - REGISTER_SYSCALL_IMPL_X64(epoll_ctl, [](FEXCore::Core::CpuStateFrame* Frame, int epfd, int op, int fd, FEX::HLE::epoll_event_x86* event) -> uint64_t { - struct epoll_event Event; - struct epoll_event* EventPtr {}; - if (event) { - FaultSafeUserMemAccess::VerifyIsReadable(event, sizeof(FEX::HLE::epoll_event_x86)); - Event = *event; - EventPtr = &Event; +auto epoll_wait(FEXCore::Core::CpuStateFrame* Frame, int epfd, FEX::HLE::epoll_event_x86* events, int maxevents, int timeout) -> uint64_t { + fextl::vector Events(std::max(0, maxevents)); + uint64_t Result = ::syscall(SYSCALL_DEF(epoll_pwait), epfd, Events.data(), maxevents, timeout, nullptr, 8); + + if (Result != -1) { + FaultSafeUserMemAccess::VerifyIsWritable(events, sizeof(FEX::HLE::epoll_event_x86) * Result); + for (size_t i = 0; i < Result; ++i) { + events[i] = Events[i]; + } + } + SYSCALL_ERRNO(); +} + +auto epoll_ctl(FEXCore::Core::CpuStateFrame* Frame, int epfd, int op, int fd, FEX::HLE::epoll_event_x86* event) -> uint64_t { + struct epoll_event Event; + struct epoll_event* EventPtr {}; + if (event) { + FaultSafeUserMemAccess::VerifyIsReadable(event, sizeof(FEX::HLE::epoll_event_x86)); + Event = *event; + EventPtr = &Event; + } + uint64_t Result = ::syscall(SYSCALL_DEF(epoll_ctl), epfd, op, fd, EventPtr); + if (Result != -1 && event) { + FaultSafeUserMemAccess::VerifyIsWritable(event, sizeof(FEX::HLE::epoll_event_x86)); + *event = Event; + } + SYSCALL_ERRNO(); +} + +auto epoll_pwait(FEXCore::Core::CpuStateFrame* Frame, int epfd, FEX::HLE::epoll_event_x86* events, int maxevent, int timeout, + const uint64_t* sigmask, size_t sigsetsize) -> uint64_t { + fextl::vector Events(std::max(0, maxevent)); + + uint64_t Result = ::syscall(SYSCALL_DEF(epoll_pwait), epfd, Events.data(), maxevent, timeout, sigmask, sigsetsize); + + if (Result != -1) { + FaultSafeUserMemAccess::VerifyIsWritable(events, sizeof(FEX::HLE::epoll_event_x86) * Result); + for (size_t i = 0; i < Result; ++i) { + events[i] = Events[i]; } - uint64_t Result = ::syscall(SYSCALL_DEF(epoll_ctl), epfd, op, fd, EventPtr); - if (Result != -1 && event) { - FaultSafeUserMemAccess::VerifyIsWritable(event, sizeof(FEX::HLE::epoll_event_x86)); - *event = Event; + } + + SYSCALL_ERRNO(); +} + +auto epoll_pwait2(FEXCore::Core::CpuStateFrame* Frame, int epfd, FEX::HLE::epoll_event_x86* events, int maxevent, timespec* timeout, + const uint64_t* sigmask, size_t sigsetsize) -> uint64_t { + fextl::vector Events(std::max(0, maxevent)); + + uint64_t Result = ::syscall(SYSCALL_DEF(epoll_pwait2), epfd, Events.data(), maxevent, timeout, sigmask, sigsetsize); + + if (Result != -1) { + FaultSafeUserMemAccess::VerifyIsWritable(events, sizeof(FEX::HLE::epoll_event_x86) * Result); + for (size_t i = 0; i < Result; ++i) { + events[i] = Events[i]; } - SYSCALL_ERRNO(); - }); - - REGISTER_SYSCALL_IMPL_X64(epoll_pwait, - [](FEXCore::Core::CpuStateFrame* Frame, int epfd, FEX::HLE::epoll_event_x86* events, int maxevent, int timeout, - const uint64_t* sigmask, size_t sigsetsize) -> uint64_t { - fextl::vector Events(std::max(0, maxevent)); - - uint64_t Result = ::syscall(SYSCALL_DEF(epoll_pwait), epfd, Events.data(), maxevent, timeout, sigmask, sigsetsize); - - if (Result != -1) { - FaultSafeUserMemAccess::VerifyIsWritable(events, sizeof(FEX::HLE::epoll_event_x86) * Result); - for (size_t i = 0; i < Result; ++i) { - events[i] = Events[i]; - } - } - - SYSCALL_ERRNO(); - }); - - REGISTER_SYSCALL_IMPL_X64(epoll_pwait2, - [](FEXCore::Core::CpuStateFrame* Frame, int epfd, FEX::HLE::epoll_event_x86* events, int maxevent, - timespec* timeout, const uint64_t* sigmask, size_t sigsetsize) -> uint64_t { - fextl::vector Events(std::max(0, maxevent)); - - uint64_t Result = ::syscall(SYSCALL_DEF(epoll_pwait2), epfd, Events.data(), maxevent, timeout, sigmask, sigsetsize); - - if (Result != -1) { - FaultSafeUserMemAccess::VerifyIsWritable(events, sizeof(FEX::HLE::epoll_event_x86) * Result); - for (size_t i = 0; i < Result; ++i) { - events[i] = Events[i]; - } - } - - SYSCALL_ERRNO(); - }); + } + + SYSCALL_ERRNO(); +} + +void RegisterEpoll(FEX::HLE::SyscallHandler* Handler) { + REGISTER_SYSCALL_IMPL_X64(epoll_wait, epoll_wait); + REGISTER_SYSCALL_IMPL_X64(epoll_ctl, epoll_ctl); + REGISTER_SYSCALL_IMPL_X64(epoll_pwait, epoll_pwait); + REGISTER_SYSCALL_IMPL_X64(epoll_pwait2, epoll_pwait2); } } // namespace FEX::HLE::x64 diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/FD.cpp b/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/FD.cpp index 703c875f70..6d06c51c5a 100644 --- a/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/FD.cpp +++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/FD.cpp @@ -28,115 +28,126 @@ tags: LinuxSyscalls|syscalls-x86-64 #include namespace FEX::HLE::x64 { -void RegisterFD(FEX::HLE::SyscallHandler* Handler) { - 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 { - ///< All FD arrays need to be writable - FaultSafeUserMemAccess::VerifyIsWritableOrNull(readfds, sizeof(uint64_t) * nfds); - FaultSafeUserMemAccess::VerifyIsWritableOrNull(writefds, sizeof(uint64_t) * nfds); - FaultSafeUserMemAccess::VerifyIsWritableOrNull(exceptfds, sizeof(uint64_t) * nfds); - FaultSafeUserMemAccess::VerifyIsReadableOrNull(timeout, sizeof(*timeout)); - ///< timeout doesn't actually need to be writable, this is a quirk of glibc. Kernel just doesn't update timeout if not possible. - FaultSafeUserMemAccess::VerifyIsWritableOrNull(timeout, sizeof(*timeout)); - 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 { - return FEX::HLE::futimesat_compat(dirfd, pathname, times); - }); - - REGISTER_SYSCALL_IMPL_X64(stat, [](FEXCore::Core::CpuStateFrame* Frame, const char* pathname, FEX::HLE::x64::guest_stat* buf) -> uint64_t { - FaultSafeUserMemAccess::VerifyIsStringReadableMaxSize(pathname, PATH_MAX); - FaultSafeUserMemAccess::VerifyIsWritable(buf, sizeof(*buf)); - struct stat host_stat; - uint64_t Result = FEX::HLE::_SyscallHandler->FM.Stat(pathname, &host_stat); - if (Result != -1) { - *buf = host_stat; - } - SYSCALL_ERRNO(); - }); - REGISTER_SYSCALL_IMPL_X64(fstat, [](FEXCore::Core::CpuStateFrame* Frame, int fd, FEX::HLE::x64::guest_stat* buf) -> uint64_t { - FaultSafeUserMemAccess::VerifyIsWritable(buf, sizeof(*buf)); - struct stat host_stat; - uint64_t Result = ::fstat(fd, &host_stat); - if (Result != -1) { - *buf = host_stat; - } - SYSCALL_ERRNO(); - }); - - REGISTER_SYSCALL_IMPL_X64(lstat, [](FEXCore::Core::CpuStateFrame* Frame, const char* path, FEX::HLE::x64::guest_stat* buf) -> uint64_t { - FaultSafeUserMemAccess::VerifyIsStringReadableMaxSize(path, PATH_MAX); - FaultSafeUserMemAccess::VerifyIsWritable(buf, sizeof(*buf)); - struct stat host_stat; - uint64_t Result = FEX::HLE::_SyscallHandler->FM.Lstat(path, &host_stat); +auto select(FEXCore::Core::CpuStateFrame* Frame, int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, struct timeval* timeout) + -> uint64_t { + ///< All FD arrays need to be writable + FaultSafeUserMemAccess::VerifyIsWritableOrNull(readfds, sizeof(uint64_t) * nfds); + FaultSafeUserMemAccess::VerifyIsWritableOrNull(writefds, sizeof(uint64_t) * nfds); + FaultSafeUserMemAccess::VerifyIsWritableOrNull(exceptfds, sizeof(uint64_t) * nfds); + FaultSafeUserMemAccess::VerifyIsReadableOrNull(timeout, sizeof(*timeout)); + ///< timeout doesn't actually need to be writable, this is a quirk of glibc. Kernel just doesn't update timeout if not possible. + FaultSafeUserMemAccess::VerifyIsWritableOrNull(timeout, sizeof(*timeout)); + uint64_t Result = ::select(nfds, readfds, writefds, exceptfds, timeout); + SYSCALL_ERRNO(); +} + +auto 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) { - *buf = host_stat; + Result = FEX::HLE::RemapToX86Flags(Result); } - SYSCALL_ERRNO(); - }); - - REGISTER_SYSCALL_IMPL_X64( - newfstatat, [](FEXCore::Core::CpuStateFrame* Frame, int dirfd, const char* pathname, FEX::HLE::x64::guest_stat* buf, int flag) -> uint64_t { - FaultSafeUserMemAccess::VerifyIsStringReadableMaxSize(pathname, PATH_MAX); - FaultSafeUserMemAccess::VerifyIsWritable(buf, sizeof(*buf)); - struct stat host_stat; - uint64_t Result = FEX::HLE::_SyscallHandler->FM.NewFSStatAt(dirfd, pathname, &host_stat, flag); - if (Result != -1) { - *buf = host_stat; - } - SYSCALL_ERRNO(); - }); + 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(getdents, [](FEXCore::Core::CpuStateFrame* Frame, int fd, void* dirp, uint32_t count) -> uint64_t { - return GetDentsEmulation(fd, reinterpret_cast(dirp), count); - }); +auto futimesat(FEXCore::Core::CpuStateFrame* Frame, int dirfd, const char* pathname, const struct timeval times[2]) -> uint64_t { + return FEX::HLE::futimesat_compat(dirfd, pathname, times); +} - REGISTER_SYSCALL_IMPL_X64(getdents64, [](FEXCore::Core::CpuStateFrame* Frame, int fd, void* dirp, uint32_t count) -> uint64_t { - uint64_t Result = ::syscall(SYSCALL_DEF(getdents64), static_cast(fd), dirp, static_cast(count)); - if (Result != -1) { - // Check for and hide the RootFS FD - for (size_t i = 0; i < Result;) { - linux_dirent_64* Incoming = (linux_dirent_64*)(reinterpret_cast(dirp) + i); - if (FEX::HLE::_SyscallHandler->FM.IsProtectedFile(fd, Incoming->d_ino)) { - Result -= Incoming->d_reclen; - memmove(Incoming, (linux_dirent_64*)(reinterpret_cast(Incoming) + Incoming->d_reclen), Result - i); - continue; - } - i += Incoming->d_reclen; +auto stat(FEXCore::Core::CpuStateFrame* Frame, const char* pathname, FEX::HLE::x64::guest_stat* buf) -> uint64_t { + FaultSafeUserMemAccess::VerifyIsStringReadableMaxSize(pathname, PATH_MAX); + FaultSafeUserMemAccess::VerifyIsWritable(buf, sizeof(*buf)); + struct stat host_stat; + uint64_t Result = FEX::HLE::_SyscallHandler->FM.Stat(pathname, &host_stat); + if (Result != -1) { + *buf = host_stat; + } + SYSCALL_ERRNO(); +} + +auto fstat(FEXCore::Core::CpuStateFrame* Frame, int fd, FEX::HLE::x64::guest_stat* buf) -> uint64_t { + FaultSafeUserMemAccess::VerifyIsWritable(buf, sizeof(*buf)); + struct stat host_stat; + uint64_t Result = ::fstat(fd, &host_stat); + if (Result != -1) { + *buf = host_stat; + } + SYSCALL_ERRNO(); +} + +auto lstat(FEXCore::Core::CpuStateFrame* Frame, const char* path, FEX::HLE::x64::guest_stat* buf) -> uint64_t { + FaultSafeUserMemAccess::VerifyIsStringReadableMaxSize(path, PATH_MAX); + FaultSafeUserMemAccess::VerifyIsWritable(buf, sizeof(*buf)); + struct stat host_stat; + uint64_t Result = FEX::HLE::_SyscallHandler->FM.Lstat(path, &host_stat); + if (Result != -1) { + *buf = host_stat; + } + SYSCALL_ERRNO(); +} + +auto newfstatat(FEXCore::Core::CpuStateFrame* Frame, int dirfd, const char* pathname, FEX::HLE::x64::guest_stat* buf, int flag) -> uint64_t { + FaultSafeUserMemAccess::VerifyIsStringReadableMaxSize(pathname, PATH_MAX); + FaultSafeUserMemAccess::VerifyIsWritable(buf, sizeof(*buf)); + struct stat host_stat; + uint64_t Result = FEX::HLE::_SyscallHandler->FM.NewFSStatAt(dirfd, pathname, &host_stat, flag); + if (Result != -1) { + *buf = host_stat; + } + SYSCALL_ERRNO(); +} + +auto getdents(FEXCore::Core::CpuStateFrame* Frame, int fd, void* dirp, uint32_t count) -> uint64_t { + return GetDentsEmulation(fd, reinterpret_cast(dirp), count); +} + +auto getdents64(FEXCore::Core::CpuStateFrame* Frame, int fd, void* dirp, uint32_t count) -> uint64_t { + uint64_t Result = ::syscall(SYSCALL_DEF(getdents64), static_cast(fd), dirp, static_cast(count)); + if (Result != -1) { + // Check for and hide the RootFS FD + for (size_t i = 0; i < Result;) { + linux_dirent_64* Incoming = (linux_dirent_64*)(reinterpret_cast(dirp) + i); + if (FEX::HLE::_SyscallHandler->FM.IsProtectedFile(fd, Incoming->d_ino)) { + Result -= Incoming->d_reclen; + memmove(Incoming, (linux_dirent_64*)(reinterpret_cast(Incoming) + Incoming->d_reclen), Result - i); + continue; } + i += Incoming->d_reclen; } - 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(); - }); - - REGISTER_SYSCALL_IMPL_X64(statfs, [](FEXCore::Core::CpuStateFrame* Frame, const char* path, struct statfs* buf) -> uint64_t { - FaultSafeUserMemAccess::VerifyIsStringReadableMaxSize(path, PATH_MAX); - FaultSafeUserMemAccess::VerifyIsWritable(buf, sizeof(*buf)); - uint64_t Result = FEX::HLE::_SyscallHandler->FM.Statfs(path, buf); - SYSCALL_ERRNO(); - }); + } + SYSCALL_ERRNO(); +} + +auto dup2(FEXCore::Core::CpuStateFrame* Frame, int oldfd, int newfd) -> uint64_t { + uint64_t Result = ::dup2(oldfd, newfd); + SYSCALL_ERRNO(); +} + +auto statfs(FEXCore::Core::CpuStateFrame* Frame, const char* path, struct statfs* buf) -> uint64_t { + FaultSafeUserMemAccess::VerifyIsStringReadableMaxSize(path, PATH_MAX); + FaultSafeUserMemAccess::VerifyIsWritable(buf, sizeof(*buf)); + uint64_t Result = FEX::HLE::_SyscallHandler->FM.Statfs(path, buf); + SYSCALL_ERRNO(); +} + +void RegisterFD(FEX::HLE::SyscallHandler* Handler) { + REGISTER_SYSCALL_IMPL_X64(select, select); + REGISTER_SYSCALL_IMPL_X64(fcntl, fcntl); + REGISTER_SYSCALL_IMPL_X64(futimesat, futimesat); + REGISTER_SYSCALL_IMPL_X64(stat, stat); + REGISTER_SYSCALL_IMPL_X64(fstat, fstat); + REGISTER_SYSCALL_IMPL_X64(lstat, lstat); + REGISTER_SYSCALL_IMPL_X64(newfstatat, newfstatat); + REGISTER_SYSCALL_IMPL_X64(getdents, getdents); + REGISTER_SYSCALL_IMPL_X64(getdents64, getdents64); + REGISTER_SYSCALL_IMPL_X64(dup2, dup2); + REGISTER_SYSCALL_IMPL_X64(statfs, statfs); } } // namespace FEX::HLE::x64 diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/Info.cpp b/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/Info.cpp index 61fb614316..7dbb995664 100644 --- a/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/Info.cpp +++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/Info.cpp @@ -15,16 +15,17 @@ tags: LinuxSyscalls|syscalls-x86-64 #include namespace FEX::HLE::x64 { -void RegisterInfo(FEX::HLE::SyscallHandler* Handler) { - using namespace FEXCore::IR; - - if (Handler->IsHostKernelVersionAtLeast(6, 6, 0)) { - REGISTER_SYSCALL_IMPL_X64(map_shadow_stack, [](FEXCore::Core::CpuStateFrame* Frame, uint64_t addr, uint64_t size, uint32_t flags) -> uint64_t { - // Claim that shadow stack isn't supported. - return -EOPNOTSUPP; - }); +auto map_shadow_stack(FEXCore::Core::CpuStateFrame* Frame, uint64_t addr, uint64_t size, uint32_t flags) -> uint64_t { + if (FEX::HLE::_SyscallHandler->IsHostKernelVersionAtLeast(6, 6, 0)) { + // Claim that shadow stack isn't supported. + return -EOPNOTSUPP; } else { - REGISTER_SYSCALL_IMPL_X64(map_shadow_stack, UnimplementedSyscallSafe); + return -ENOSYS; } } + +void RegisterInfo(FEX::HLE::SyscallHandler* Handler) { + using namespace FEXCore::IR; + REGISTER_SYSCALL_IMPL_X64(map_shadow_stack, map_shadow_stack); +} } // namespace FEX::HLE::x64 diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/Memory.cpp b/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/Memory.cpp index 994e4873d9..6739419337 100644 --- a/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/Memory.cpp +++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/Memory.cpp @@ -5,7 +5,6 @@ tags: LinuxSyscalls|syscalls-x86-64 $end_info$ */ -#include "LinuxSyscalls/LinuxAllocator.h" #include "LinuxSyscalls/Syscalls.h" #include "LinuxSyscalls/x64/Syscalls.h" #include @@ -24,33 +23,37 @@ tags: LinuxSyscalls|syscalls-x86-64 namespace FEX::HLE::x64 { -void RegisterMemory(FEX::HLE::SyscallHandler* Handler) { - using namespace FEXCore::IR; +auto mmap(FEXCore::Core::CpuStateFrame* Frame, void* addr, size_t length, int prot, int flags, int fd, off_t offset) -> uint64_t { + return (uint64_t)FEX::HLE::_SyscallHandler->GuestMmap(Frame->Thread, addr, length, prot, flags, fd, offset); +} - REGISTER_SYSCALL_IMPL_X64( - mmap, [](FEXCore::Core::CpuStateFrame* Frame, void* addr, size_t length, int prot, int flags, int fd, off_t offset) -> uint64_t { - return (uint64_t)FEX::HLE::_SyscallHandler->GuestMmap(Frame->Thread, addr, length, prot, flags, fd, offset); - }); +auto munmap(FEXCore::Core::CpuStateFrame* Frame, void* addr, size_t length) -> uint64_t { + return FEX::HLE::_SyscallHandler->GuestMunmap(Frame->Thread, addr, length); +} - REGISTER_SYSCALL_IMPL_X64(munmap, [](FEXCore::Core::CpuStateFrame* Frame, void* addr, size_t length) -> uint64_t { - return FEX::HLE::_SyscallHandler->GuestMunmap(Frame->Thread, addr, length); - }); +auto mremap(FEXCore::Core::CpuStateFrame* Frame, void* old_address, size_t old_size, size_t new_size, int flags, void* new_address) -> uint64_t { + return FEX::HLE::_SyscallHandler->GuestMremap(true, Frame->Thread, old_address, old_size, new_size, flags, new_address); +} - REGISTER_SYSCALL_IMPL_X64( - mremap, [](FEXCore::Core::CpuStateFrame* Frame, void* old_address, size_t old_size, size_t new_size, int flags, void* new_address) -> uint64_t { - return FEX::HLE::_SyscallHandler->GuestMremap(true, Frame->Thread, old_address, old_size, new_size, flags, new_address); - }); +auto mprotect(FEXCore::Core::CpuStateFrame* Frame, void* addr, size_t len, int prot) -> uint64_t { + return FEX::HLE::_SyscallHandler->GuestMprotect(Frame->Thread, addr, len, prot); +} - REGISTER_SYSCALL_IMPL_X64(mprotect, [](FEXCore::Core::CpuStateFrame* Frame, void* addr, size_t len, int prot) -> uint64_t { - return FEX::HLE::_SyscallHandler->GuestMprotect(Frame->Thread, addr, len, prot); - }); +auto shmat(FEXCore::Core::CpuStateFrame* Frame, int shmid, const void* shmaddr, int shmflg) -> uint64_t { + return FEX::HLE::_SyscallHandler->GuestShmat(true, Frame->Thread, shmid, shmaddr, shmflg); +} - REGISTER_SYSCALL_IMPL_X64(shmat, ([](FEXCore::Core::CpuStateFrame* Frame, int shmid, const void* shmaddr, int shmflg) -> uint64_t { - return FEX::HLE::_SyscallHandler->GuestShmat(true, Frame->Thread, shmid, shmaddr, shmflg); - })); +auto shmdt(FEXCore::Core::CpuStateFrame* Frame, const void* shmaddr) -> uint64_t { + return FEX::HLE::_SyscallHandler->GuestShmdt(true, Frame->Thread, shmaddr); +} - REGISTER_SYSCALL_IMPL_X64(shmdt, [](FEXCore::Core::CpuStateFrame* Frame, const void* shmaddr) -> uint64_t { - return FEX::HLE::_SyscallHandler->GuestShmdt(true, Frame->Thread, shmaddr); - }); +void RegisterMemory(FEX::HLE::SyscallHandler* Handler) { + using namespace FEXCore::IR; + REGISTER_SYSCALL_IMPL_X64(mmap, mmap); + REGISTER_SYSCALL_IMPL_X64(munmap, munmap); + REGISTER_SYSCALL_IMPL_X64(mremap, mremap); + REGISTER_SYSCALL_IMPL_X64(mprotect, mprotect); + REGISTER_SYSCALL_IMPL_X64(shmat, shmat); + REGISTER_SYSCALL_IMPL_X64(shmdt, shmdt); } } // namespace FEX::HLE::x64 diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/NotImplemented.cpp b/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/NotImplemented.cpp index c6929b8a0e..a1010f07bc 100644 --- a/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/NotImplemented.cpp +++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/NotImplemented.cpp @@ -17,27 +17,40 @@ struct CpuStateFrame; } namespace FEX::HLE::x64 { -#define REGISTER_SYSCALL_NOT_IMPL_X64(name) \ - REGISTER_SYSCALL_IMPL_X64(name, [](FEXCore::Core::CpuStateFrame* Frame) -> uint64_t { \ - LogMan::Msg::DFmt("Using deprecated/removed syscall: " #name); \ - return -ENOSYS; \ - }); +#define SYSCALL_NOT_IMPL_X64(name) \ + auto name(FEXCore::Core::CpuStateFrame* Frame) -> uint64_t { \ + LogMan::Msg::DFmt("Using deprecated/removed syscall: " #name); \ + return -ENOSYS; \ + }; -#define REGISTER_SYSCALL_NOT_IMPL_SAFE_X64(name) \ - REGISTER_SYSCALL_IMPL_X64(name, [](FEXCore::Core::CpuStateFrame* Frame) -> uint64_t { return -ENOSYS; }); +#define SYSCALL_NOT_IMPL_SAFE_X64(name) \ + auto name(FEXCore::Core::CpuStateFrame* Frame) -> uint64_t { \ + return -ENOSYS; \ + } -#define REGISTER_SYSCALL_NO_PERM_X64(name) \ - REGISTER_SYSCALL_IMPL_X64(name, [](FEXCore::Core::CpuStateFrame* Frame) -> uint64_t { return -EPERM; }); +#define SYSCALL_NO_PERM_X64(name) \ + auto name(FEXCore::Core::CpuStateFrame* Frame) -> uint64_t { \ + return -EPERM; \ + } + +SYSCALL_NOT_IMPL_X64(tuxcall); +SYSCALL_NOT_IMPL_X64(security); +SYSCALL_NOT_IMPL_X64(set_thread_area); +SYSCALL_NOT_IMPL_X64(get_thread_area); +SYSCALL_NOT_IMPL_X64(epoll_ctl_old); +SYSCALL_NOT_IMPL_X64(epoll_wait_old); +SYSCALL_NO_PERM_X64(kexec_file_load); +SYSCALL_NOT_IMPL_SAFE_X64(uretprobe); // these are removed/not implemented in the linux kernel we present void RegisterNotImplemented(FEX::HLE::SyscallHandler* Handler) { - REGISTER_SYSCALL_NOT_IMPL_X64(tuxcall); - REGISTER_SYSCALL_NOT_IMPL_X64(security); - REGISTER_SYSCALL_NOT_IMPL_X64(set_thread_area); - REGISTER_SYSCALL_NOT_IMPL_X64(get_thread_area); - REGISTER_SYSCALL_NOT_IMPL_X64(epoll_ctl_old); - REGISTER_SYSCALL_NOT_IMPL_X64(epoll_wait_old); - REGISTER_SYSCALL_NO_PERM_X64(kexec_file_load); - REGISTER_SYSCALL_NOT_IMPL_SAFE_X64(uretprobe); + REGISTER_SYSCALL_IMPL_X64(tuxcall, tuxcall); + REGISTER_SYSCALL_IMPL_X64(security, security); + REGISTER_SYSCALL_IMPL_X64(set_thread_area, set_thread_area); + REGISTER_SYSCALL_IMPL_X64(get_thread_area, get_thread_area); + REGISTER_SYSCALL_IMPL_X64(epoll_ctl_old, epoll_ctl_old); + REGISTER_SYSCALL_IMPL_X64(epoll_wait_old, epoll_wait_old); + REGISTER_SYSCALL_IMPL_X64(kexec_file_load, kexec_file_load); + REGISTER_SYSCALL_IMPL_X64(uretprobe, uretprobe); } } // namespace FEX::HLE::x64 diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/Semaphore.cpp b/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/Semaphore.cpp index b0daaeea3d..4f3ba55925 100644 --- a/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/Semaphore.cpp +++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/Semaphore.cpp @@ -22,61 +22,62 @@ struct CpuStateFrame; ARG_TO_STR(FEX::HLE::x64::semun, "%lx") namespace FEX::HLE::x64 { -void RegisterSemaphore(FEX::HLE::SyscallHandler* Handler) { - REGISTER_SYSCALL_IMPL_X64(semctl, [](FEXCore::Core::CpuStateFrame* Frame, int semid, int semnum, int cmd, FEX::HLE::x64::semun semun) -> uint64_t { - uint64_t Result {}; - switch (cmd) { - case IPC_SET: { - struct semid64_ds buf {}; - FaultSafeUserMemAccess::VerifyIsReadable(semun.buf, sizeof(*semun.buf)); - buf = *semun.buf; - Result = ::syscall(SYSCALL_DEF(semctl), semid, semnum, cmd, &buf); - if (Result != -1) { - FaultSafeUserMemAccess::VerifyIsWritable(semun.buf, sizeof(*semun.buf)); - *semun.buf = buf; - } - break; - } - case SEM_STAT: - case SEM_STAT_ANY: - case IPC_STAT: { - struct semid64_ds buf {}; - Result = ::syscall(SYSCALL_DEF(semctl), semid, semnum, cmd, &buf); - if (Result != -1) { - FaultSafeUserMemAccess::VerifyIsWritable(semun.buf, sizeof(*semun.buf)); - *semun.buf = buf; - } - break; - } - case SEM_INFO: - case IPC_INFO: { - struct fex_seminfo si {}; - Result = ::syscall(SYSCALL_DEF(semctl), semid, semnum, cmd, &si); - if (Result != -1) { - FaultSafeUserMemAccess::VerifyIsWritable(semun.__buf, sizeof(si)); - memcpy(semun.__buf, &si, sizeof(si)); - } - break; +auto semctl(FEXCore::Core::CpuStateFrame* Frame, int semid, int semnum, int cmd, FEX::HLE::x64::semun semun) -> uint64_t { + uint64_t Result {}; + switch (cmd) { + case IPC_SET: { + struct semid64_ds buf {}; + FaultSafeUserMemAccess::VerifyIsReadable(semun.buf, sizeof(*semun.buf)); + buf = *semun.buf; + Result = ::syscall(SYSCALL_DEF(semctl), semid, semnum, cmd, &buf); + if (Result != -1) { + FaultSafeUserMemAccess::VerifyIsWritable(semun.buf, sizeof(*semun.buf)); + *semun.buf = buf; } - case GETALL: - case SETALL: { - // ptr is just a int32_t* in this case - Result = ::syscall(SYSCALL_DEF(semctl), semid, semnum, cmd, semun.array); - break; + break; + } + case SEM_STAT: + case SEM_STAT_ANY: + case IPC_STAT: { + struct semid64_ds buf {}; + Result = ::syscall(SYSCALL_DEF(semctl), semid, semnum, cmd, &buf); + if (Result != -1) { + FaultSafeUserMemAccess::VerifyIsWritable(semun.buf, sizeof(*semun.buf)); + *semun.buf = buf; } - case SETVAL: { - // ptr is just a int32_t in this case - Result = ::syscall(SYSCALL_DEF(semctl), semid, semnum, cmd, semun.val); - break; + break; + } + case SEM_INFO: + case IPC_INFO: { + struct fex_seminfo si {}; + Result = ::syscall(SYSCALL_DEF(semctl), semid, semnum, cmd, &si); + if (Result != -1) { + FaultSafeUserMemAccess::VerifyIsWritable(semun.__buf, sizeof(si)); + memcpy(semun.__buf, &si, sizeof(si)); } - case IPC_RMID: - case GETPID: - case GETNCNT: - case GETZCNT: - case GETVAL: Result = ::syscall(SYSCALL_DEF(semctl), semid, semnum, cmd, semun); break; - default: LOGMAN_MSG_A_FMT("Unhandled semctl cmd: {}", cmd); return -EINVAL; - } - SYSCALL_ERRNO(); - }); + break; + } + case GETALL: + case SETALL: { + // ptr is just a int32_t* in this case + Result = ::syscall(SYSCALL_DEF(semctl), semid, semnum, cmd, semun.array); + break; + } + case SETVAL: { + // ptr is just a int32_t in this case + Result = ::syscall(SYSCALL_DEF(semctl), semid, semnum, cmd, semun.val); + break; + } + case IPC_RMID: + case GETPID: + case GETNCNT: + case GETZCNT: + case GETVAL: Result = ::syscall(SYSCALL_DEF(semctl), semid, semnum, cmd, semun); break; + default: LOGMAN_MSG_A_FMT("Unhandled semctl cmd: {}", cmd); return -EINVAL; + } + SYSCALL_ERRNO(); +} +void RegisterSemaphore(FEX::HLE::SyscallHandler* Handler) { + REGISTER_SYSCALL_IMPL_X64(semctl, semctl); } } // namespace FEX::HLE::x64 diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/Signals.cpp b/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/Signals.cpp index d8754ccbc5..265ee2d6dd 100644 --- a/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/Signals.cpp +++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/Signals.cpp @@ -14,30 +14,30 @@ tags: LinuxSyscalls|syscalls-x86-64 #include #include -#include #include #include namespace FEX::HLE::x64 { +auto rt_sigaction(FEXCore::Core::CpuStateFrame* Frame, int signum, const GuestSigAction* act, GuestSigAction* oldact, size_t sigsetsize) -> uint64_t { + if (sigsetsize != 8) { + return -EINVAL; + } + FaultSafeUserMemAccess::VerifyIsReadableOrNull(act, sizeof(GuestSigAction)); + FaultSafeUserMemAccess::VerifyIsWritableOrNull(oldact, sizeof(GuestSigAction)); + + return FEX::HLE::_SyscallHandler->GetSignalDelegator()->RegisterGuestSignalHandler(signum, act, oldact); +} + +auto rt_sigtimedwait(FEXCore::Core::CpuStateFrame* Frame, uint64_t* set, siginfo_t* info, const struct timespec* timeout, size_t sigsetsize) + -> uint64_t { + FaultSafeUserMemAccess::VerifyIsReadable(set, sizeof(sigsetsize)); + FaultSafeUserMemAccess::VerifyIsWritableOrNull(info, sizeof(siginfo_t)); + FaultSafeUserMemAccess::VerifyIsReadableOrNull(timeout, sizeof(timespec)); + return FEX::HLE::_SyscallHandler->GetSignalDelegator()->GuestSigTimedWait(set, info, timeout, sigsetsize); +} + void RegisterSignals(FEX::HLE::SyscallHandler* Handler) { - REGISTER_SYSCALL_IMPL_X64( - rt_sigaction, [](FEXCore::Core::CpuStateFrame* Frame, int signum, const GuestSigAction* act, GuestSigAction* oldact, size_t sigsetsize) -> uint64_t { - if (sigsetsize != 8) { - return -EINVAL; - } - FaultSafeUserMemAccess::VerifyIsReadableOrNull(act, sizeof(GuestSigAction)); - FaultSafeUserMemAccess::VerifyIsWritableOrNull(oldact, sizeof(GuestSigAction)); - - return FEX::HLE::_SyscallHandler->GetSignalDelegator()->RegisterGuestSignalHandler(signum, act, oldact); - }); - - REGISTER_SYSCALL_IMPL_X64( - rt_sigtimedwait, - [](FEXCore::Core::CpuStateFrame* Frame, uint64_t* set, siginfo_t* info, const struct timespec* timeout, size_t sigsetsize) -> uint64_t { - FaultSafeUserMemAccess::VerifyIsReadable(set, sizeof(sigsetsize)); - FaultSafeUserMemAccess::VerifyIsWritableOrNull(info, sizeof(siginfo_t)); - FaultSafeUserMemAccess::VerifyIsReadableOrNull(timeout, sizeof(timespec)); - return FEX::HLE::_SyscallHandler->GetSignalDelegator()->GuestSigTimedWait(set, info, timeout, sigsetsize); - }); + REGISTER_SYSCALL_IMPL_X64(rt_sigaction, rt_sigaction); + REGISTER_SYSCALL_IMPL_X64(rt_sigtimedwait, rt_sigtimedwait); } } // namespace FEX::HLE::x64 diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/Thread.cpp b/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/Thread.cpp index 414ac1c84b..6e83cd62e9 100644 --- a/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/Thread.cpp +++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/Thread.cpp @@ -233,117 +233,121 @@ enum Modify_ldt_func : int32_t { LDT_WRITE = 0x11, }; -void RegisterThread(FEX::HLE::SyscallHandler* Handler) { - using namespace FEXCore::IR; - REGISTER_SYSCALL_IMPL_X64(modify_ldt, [](FEXCore::Core::CpuStateFrame* Frame, int func, void* ptr, unsigned long bytecount) -> uint64_t { - switch (func) { - case Modify_ldt_func::LDT_READ: return FEX::HLE::_SyscallHandler->read_ldt(Frame, ptr, bytecount); - case Modify_ldt_func::LDT_WRITE_LEGACY: return FEX::HLE::_SyscallHandler->write_ldt(Frame, ptr, bytecount, true); - case Modify_ldt_func::LDT_READ_DEFAULT: return read_default_ldt(Frame, ptr, bytecount); - case Modify_ldt_func::LDT_WRITE: return FEX::HLE::_SyscallHandler->write_ldt(Frame, ptr, bytecount, false); - default: return -ENOSYS; - } - }); - - REGISTER_SYSCALL_IMPL_X64( - clone, ([](FEXCore::Core::CpuStateFrame* Frame, uint32_t flags, void* stack, pid_t* parent_tid, pid_t* child_tid, void* tls) -> uint64_t { - // This is slightly different EFAULT behaviour, if child_tid or parent_tid is invalid then the kernel just doesn't write to the - // pointer. Still need to be EFAULT safe although. - if ((flags & (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)) && child_tid) { - FaultSafeUserMemAccess::VerifyIsWritable(child_tid, sizeof(*child_tid)); - } - - if ((flags & CLONE_PARENT_SETTID) && parent_tid) { - FaultSafeUserMemAccess::VerifyIsWritable(parent_tid, sizeof(*parent_tid)); - } - - FEX::HLE::clone3_args args { - .Type = TypeOfClone::TYPE_CLONE2, - .args = - { - - .flags = flags & ~CSIGNAL, // This no longer contains CSIGNAL - .pidfd = 0, // For clone, pidfd is duplicated here - .child_tid = reinterpret_cast(child_tid), - .parent_tid = reinterpret_cast(parent_tid), - .exit_signal = flags & CSIGNAL, - .stack = reinterpret_cast(stack), - .stack_size = 0, // This syscall isn't able to see the stack size - .tls = reinterpret_cast(tls), - .set_tid = 0, // This syscall isn't able to select TIDs - .set_tid_size = 0, - .cgroup = 0, // This syscall can't select cgroups - }, - }; - return CloneHandler(Frame, &args); - })); - - REGISTER_SYSCALL_IMPL_X64(sigaltstack, [](FEXCore::Core::CpuStateFrame* Frame, const stack_t* ss, stack_t* old_ss) -> uint64_t { - FaultSafeUserMemAccess::VerifyIsReadableOrNull(ss, sizeof(*ss)); - FaultSafeUserMemAccess::VerifyIsWritableOrNull(old_ss, sizeof(*old_ss)); - return FEX::HLE::_SyscallHandler->GetSignalDelegator()->RegisterGuestSigAltStack( - FEX::HLE::ThreadManager::GetStateObjectFromCPUState(Frame), ss, old_ss); - }); - - // launch a new process under fex - // currently does not propagate argv[0] correctly - REGISTER_SYSCALL_IMPL_X64(execve, [](FEXCore::Core::CpuStateFrame* Frame, const char* pathname, char* const argv[], char* const envp[]) -> uint64_t { - fextl::vector Args; - fextl::vector Envp; - - if (argv) { - for (int i = 0; argv[i]; i++) { - Args.push_back(argv[i]); - } - - Args.push_back(nullptr); +auto modify_ldt(FEXCore::Core::CpuStateFrame* Frame, int func, void* ptr, unsigned long bytecount) -> uint64_t { + switch (func) { + case Modify_ldt_func::LDT_READ: return FEX::HLE::_SyscallHandler->read_ldt(Frame, ptr, bytecount); + case Modify_ldt_func::LDT_WRITE_LEGACY: return FEX::HLE::_SyscallHandler->write_ldt(Frame, ptr, bytecount, true); + case Modify_ldt_func::LDT_READ_DEFAULT: return read_default_ldt(Frame, ptr, bytecount); + case Modify_ldt_func::LDT_WRITE: return FEX::HLE::_SyscallHandler->write_ldt(Frame, ptr, bytecount, false); + default: return -ENOSYS; + } +} + +auto clone(FEXCore::Core::CpuStateFrame* Frame, uint32_t flags, void* stack, pid_t* parent_tid, pid_t* child_tid, void* tls) -> uint64_t { + // This is slightly different EFAULT behaviour, if child_tid or parent_tid is invalid then the kernel just doesn't write to the + // pointer. Still need to be EFAULT safe although. + if ((flags & (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)) && child_tid) { + FaultSafeUserMemAccess::VerifyIsWritable(child_tid, sizeof(*child_tid)); + } + + if ((flags & CLONE_PARENT_SETTID) && parent_tid) { + FaultSafeUserMemAccess::VerifyIsWritable(parent_tid, sizeof(*parent_tid)); + } + + FEX::HLE::clone3_args args { + .Type = TypeOfClone::TYPE_CLONE2, + .args = + { + + .flags = flags & ~CSIGNAL, // This no longer contains CSIGNAL + .pidfd = 0, // For clone, pidfd is duplicated here + .child_tid = reinterpret_cast(child_tid), + .parent_tid = reinterpret_cast(parent_tid), + .exit_signal = flags & CSIGNAL, + .stack = reinterpret_cast(stack), + .stack_size = 0, // This syscall isn't able to see the stack size + .tls = reinterpret_cast(tls), + .set_tid = 0, // This syscall isn't able to select TIDs + .set_tid_size = 0, + .cgroup = 0, // This syscall can't select cgroups + }, + }; + return CloneHandler(Frame, &args); +} + +auto sigaltstack(FEXCore::Core::CpuStateFrame* Frame, const stack_t* ss, stack_t* old_ss) -> uint64_t { + FaultSafeUserMemAccess::VerifyIsReadableOrNull(ss, sizeof(*ss)); + FaultSafeUserMemAccess::VerifyIsWritableOrNull(old_ss, sizeof(*old_ss)); + return FEX::HLE::_SyscallHandler->GetSignalDelegator()->RegisterGuestSigAltStack( + FEX::HLE::ThreadManager::GetStateObjectFromCPUState(Frame), ss, old_ss); +} + +// launch a new process under fex +// currently does not propagate argv[0] correctly +auto execve(FEXCore::Core::CpuStateFrame* Frame, const char* pathname, char* const argv[], char* const envp[]) -> uint64_t { + fextl::vector Args; + fextl::vector Envp; + + if (argv) { + for (int i = 0; argv[i]; i++) { + Args.push_back(argv[i]); } - if (envp) { - for (int i = 0; envp[i]; i++) { - Envp.push_back(envp[i]); - } + Args.push_back(nullptr); + } - Envp.push_back(nullptr); + if (envp) { + for (int i = 0; envp[i]; i++) { + Envp.push_back(envp[i]); } - auto* const* ArgsPtr = argv ? const_cast(Args.data()) : nullptr; - auto* const* EnvpPtr = envp ? const_cast(Envp.data()) : nullptr; + Envp.push_back(nullptr); + } - FEX::HLE::ExecveAtArgs AtArgs = FEX::HLE::ExecveAtArgs::Empty(); + auto* const* ArgsPtr = argv ? const_cast(Args.data()) : nullptr; + auto* const* EnvpPtr = envp ? const_cast(Envp.data()) : nullptr; - return FEX::HLE::ExecveHandler(Frame, pathname, ArgsPtr, EnvpPtr, AtArgs); - }); + FEX::HLE::ExecveAtArgs AtArgs = FEX::HLE::ExecveAtArgs::Empty(); - REGISTER_SYSCALL_IMPL_X64(execveat, ([](FEXCore::Core::CpuStateFrame* Frame, int dirfd, const char* pathname, char* const argv[], - char* const envp[], int flags) -> uint64_t { - fextl::vector Args; - fextl::vector Envp; + return FEX::HLE::ExecveHandler(Frame, pathname, ArgsPtr, EnvpPtr, AtArgs); +} + +auto execveat(FEXCore::Core::CpuStateFrame* Frame, int dirfd, const char* pathname, char* const argv[], char* const envp[], int flags) -> uint64_t { + fextl::vector Args; + fextl::vector Envp; + + if (argv) { + for (int i = 0; argv[i]; i++) { + Args.push_back(argv[i]); + } - if (argv) { - for (int i = 0; argv[i]; i++) { - Args.push_back(argv[i]); - } + Args.push_back(nullptr); + } - Args.push_back(nullptr); - } + if (envp) { + for (int i = 0; envp[i]; i++) { + Envp.push_back(envp[i]); + } - if (envp) { - for (int i = 0; envp[i]; i++) { - Envp.push_back(envp[i]); - } + Envp.push_back(nullptr); + } - Envp.push_back(nullptr); - } + FEX::HLE::ExecveAtArgs AtArgs { + .dirfd = dirfd, + .flags = flags, + }; - FEX::HLE::ExecveAtArgs AtArgs { - .dirfd = dirfd, - .flags = flags, - }; + auto* const* ArgsPtr = argv ? const_cast(Args.data()) : nullptr; + auto* const* EnvpPtr = envp ? const_cast(Envp.data()) : nullptr; + return FEX::HLE::ExecveHandler(Frame, pathname, ArgsPtr, EnvpPtr, AtArgs); +} - auto* const* ArgsPtr = argv ? const_cast(Args.data()) : nullptr; - auto* const* EnvpPtr = envp ? const_cast(Envp.data()) : nullptr; - return FEX::HLE::ExecveHandler(Frame, pathname, ArgsPtr, EnvpPtr, AtArgs); - })); +void RegisterThread(FEX::HLE::SyscallHandler* Handler) { + using namespace FEXCore::IR; + REGISTER_SYSCALL_IMPL_X64(modify_ldt, modify_ldt); + REGISTER_SYSCALL_IMPL_X64(clone, clone); + REGISTER_SYSCALL_IMPL_X64(sigaltstack, sigaltstack); + REGISTER_SYSCALL_IMPL_X64(execve, execve); + REGISTER_SYSCALL_IMPL_X64(execveat, execveat); } } // namespace FEX::HLE::x64 diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/Time.cpp b/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/Time.cpp index 7859872567..4239b9d136 100644 --- a/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/Time.cpp +++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/Time.cpp @@ -6,7 +6,6 @@ tags: LinuxSyscalls|syscalls-x86-64 */ #include "LinuxSyscalls/Syscalls.h" -#include "LinuxSyscalls/Types.h" #include "LinuxSyscalls/x64/Syscalls.h" #include @@ -20,26 +19,30 @@ tags: LinuxSyscalls|syscalls-x86-64 #include namespace FEX::HLE::x64 { -void RegisterTime(FEX::HLE::SyscallHandler* Handler) { - using namespace FEXCore::IR; - REGISTER_SYSCALL_IMPL_X64(time, [](FEXCore::Core::CpuStateFrame* Frame, time_t* tloc) -> uint64_t { - FaultSafeUserMemAccess::VerifyIsWritableOrNull(tloc, sizeof(time_t)); - uint64_t Result = ::time(tloc); - SYSCALL_ERRNO(); - }); +auto time(FEXCore::Core::CpuStateFrame* Frame, time_t* tloc) -> uint64_t { + FaultSafeUserMemAccess::VerifyIsWritableOrNull(tloc, sizeof(time_t)); + uint64_t Result = ::time(tloc); + SYSCALL_ERRNO(); +} + +auto utime(FEXCore::Core::CpuStateFrame* Frame, const char* filename, const struct utimbuf* times) -> uint64_t { + FaultSafeUserMemAccess::VerifyIsStringReadable(filename); + FaultSafeUserMemAccess::VerifyIsReadableOrNull(times, sizeof(utimbuf)); + uint64_t Result = ::utime(filename, times); + SYSCALL_ERRNO(); +} - REGISTER_SYSCALL_IMPL_X64(utime, [](FEXCore::Core::CpuStateFrame* Frame, const char* filename, const struct utimbuf* times) -> uint64_t { - FaultSafeUserMemAccess::VerifyIsStringReadable(filename); - FaultSafeUserMemAccess::VerifyIsReadableOrNull(times, sizeof(utimbuf)); - uint64_t Result = ::utime(filename, times); - SYSCALL_ERRNO(); - }); +auto utimes(FEXCore::Core::CpuStateFrame* Frame, const char* filename, const struct timeval times[2]) -> uint64_t { + FaultSafeUserMemAccess::VerifyIsStringReadable(filename); + FaultSafeUserMemAccess::VerifyIsReadableOrNull(times, sizeof(timeval) * 2); + uint64_t Result = ::utimes(filename, times); + SYSCALL_ERRNO(); +} - REGISTER_SYSCALL_IMPL_X64(utimes, [](FEXCore::Core::CpuStateFrame* Frame, const char* filename, const struct timeval times[2]) -> uint64_t { - FaultSafeUserMemAccess::VerifyIsStringReadable(filename); - FaultSafeUserMemAccess::VerifyIsReadableOrNull(times, sizeof(timeval) * 2); - uint64_t Result = ::utimes(filename, times); - SYSCALL_ERRNO(); - }); +void RegisterTime(FEX::HLE::SyscallHandler* Handler) { + using namespace FEXCore::IR; + REGISTER_SYSCALL_IMPL_X64(time, time); + REGISTER_SYSCALL_IMPL_X64(utime, utime); + REGISTER_SYSCALL_IMPL_X64(utimes, utimes); } } // namespace FEX::HLE::x64