From ca12dc9213415d50e529e2ff4e03e20e4fab58e4 Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Thu, 29 May 2025 14:41:32 +0200 Subject: [PATCH] LinuxSyscalls: Unify shmat implementations --- .../LinuxEmulation/LinuxSyscalls/Syscalls.h | 1 + .../LinuxSyscalls/SyscallsSMCTracking.cpp | 35 +++++++++++++++++++ .../LinuxSyscalls/x32/Memory.cpp | 29 +-------------- .../LinuxSyscalls/x32/Semaphore.cpp | 31 ++-------------- .../LinuxSyscalls/x64/Memory.cpp | 25 +------------ 5 files changed, 41 insertions(+), 80 deletions(-) diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls.h b/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls.h index 85caa506f..1e0f8518a 100644 --- a/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls.h +++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls.h @@ -248,6 +248,7 @@ public: uint64_t GuestMunmap(bool Is64Bit, FEXCore::Core::InternalThreadState* Thread, void* addr, uint64_t length); uint64_t GuestMprotect(FEXCore::Core::InternalThreadState*, void* addr, size_t len, int prot); + uint64_t GuestShmat(bool Is64Bit, FEXCore::Core::InternalThreadState*, int shmid, const void* shmaddr, int shmflg); ///// Memory Manager tracking ///// void TrackMmap(FEXCore::Core::InternalThreadState* Thread, uint64_t addr, size_t length, int prot, int flags, int fd, off_t offset); diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/SyscallsSMCTracking.cpp b/Source/Tools/LinuxEmulation/LinuxSyscalls/SyscallsSMCTracking.cpp index b17a7c3d2..296e546bc 100644 --- a/Source/Tools/LinuxEmulation/LinuxSyscalls/SyscallsSMCTracking.cpp +++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/SyscallsSMCTracking.cpp @@ -239,6 +239,41 @@ uint64_t SyscallHandler::GuestMprotect(FEXCore::Core::InternalThreadState* Threa return Result; } +uint64_t SyscallHandler::GuestShmat(bool Is64Bit, FEXCore::Core::InternalThreadState* Thread, int shmid, const void* shmaddr, int shmflg) { + auto CTX = Thread->CTX; + uint64_t Result {}; + uint64_t Length {}; + CTX->MarkMemoryShared(Thread); + + { + auto lk = FEXCore::GuardSignalDeferringSection(FEX::HLE::_SyscallHandler->VMATracking.Mutex, Thread); + if (Is64Bit) { + Result = reinterpret_cast(::shmat(shmid, shmaddr, shmflg)); + if (Result == -1) { + return Result; + } + } else { + uint32_t Addr; + Result = FEX::HLE::_SyscallHandler->Get32BitAllocator()->Shmat(shmid, shmaddr, shmflg, &Addr); + if (FEX::HLE::HasSyscallError(Result)) { + return Result; + } + Result = Addr; + } + + shmid_ds stat; + + [[maybe_unused]] auto res = shmctl(shmid, IPC_STAT, &stat); + LOGMAN_THROW_A_FMT(res != -1, "shmctl IPC_STAT failed"); + + Length = stat.shm_segsz; + FEX::HLE::_SyscallHandler->TrackShmat(Thread, shmid, Result, shmflg, Length); + } + + FEX::HLE::_SyscallHandler->InvalidateCodeRangeIfNecessary(Thread, Result, Length); + return Result; +} + // MMan Tracking void SyscallHandler::TrackMmap(FEXCore::Core::InternalThreadState* Thread, uint64_t addr, size_t length, int prot, int flags, int fd, off_t offset) { size_t Size = FEXCore::AlignUp(length, FEXCore::Utils::FEX_PAGE_SIZE); diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/x32/Memory.cpp b/Source/Tools/LinuxEmulation/LinuxSyscalls/x32/Memory.cpp index c6051ebff..d7475b7e4 100644 --- a/Source/Tools/LinuxEmulation/LinuxSyscalls/x32/Memory.cpp +++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/x32/Memory.cpp @@ -82,34 +82,7 @@ void RegisterMemory(FEX::HLE::SyscallHandler* Handler) { }); REGISTER_SYSCALL_IMPL_X32(shmat, [](FEXCore::Core::CpuStateFrame* Frame, int shmid, const void* shmaddr, int shmflg) -> uint64_t { - // also implemented in ipc:OP_SHMAT - auto Thread = Frame->Thread; - auto CTX = Thread->CTX; - uint64_t Result {}; - uint32_t ResultAddr {}; - uint64_t Length {}; - CTX->MarkMemoryShared(Thread); - - { - auto lk = FEXCore::GuardSignalDeferringSection(FEX::HLE::_SyscallHandler->VMATracking.Mutex, Thread); - - Result = FEX::HLE::_SyscallHandler->Get32BitAllocator()->Shmat(shmid, reinterpret_cast(shmaddr), shmflg, &ResultAddr); - - if (FEX::HLE::HasSyscallError(Result)) { - return Result; - } - - shmid_ds stat; - - [[maybe_unused]] auto res = shmctl(shmid, IPC_STAT, &stat); - LOGMAN_THROW_A_FMT(res != -1, "shmctl IPC_STAT failed"); - - Length = stat.shm_segsz; - FEX::HLE::_SyscallHandler->TrackShmat(Thread, shmid, ResultAddr, shmflg, Length); - } - - FEX::HLE::_SyscallHandler->InvalidateCodeRangeIfNecessary(Thread, ResultAddr, Length); - return ResultAddr; + return FEX::HLE::_SyscallHandler->GuestShmat(false, Frame->Thread, shmid, shmaddr, shmflg); }); REGISTER_SYSCALL_IMPL_X32(shmdt, [](FEXCore::Core::CpuStateFrame* Frame, const void* shmaddr) -> uint64_t { diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/x32/Semaphore.cpp b/Source/Tools/LinuxEmulation/LinuxSyscalls/x32/Semaphore.cpp index b84df424e..7184fe156 100644 --- a/Source/Tools/LinuxEmulation/LinuxSyscalls/x32/Semaphore.cpp +++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/x32/Semaphore.cpp @@ -293,35 +293,10 @@ uint64_t _ipc(FEXCore::Core::CpuStateFrame* Frame, uint32_t call, uint32_t first // shmat explicitly doesn't support version 1. return -EINVAL; } - // also implemented in memory:shmat - auto Thread = Frame->Thread; - auto CTX = Thread->CTX; - uint64_t Result {}; - uint32_t ResultAddr {}; - uint64_t Length {}; - CTX->MarkMemoryShared(Thread); - - { - auto lk = FEXCore::GuardSignalDeferringSection(FEX::HLE::_SyscallHandler->VMATracking.Mutex, Thread); - - Result = FEX::HLE::_SyscallHandler->Get32BitAllocator()->Shmat(first, reinterpret_cast(ptr), second, &ResultAddr); - - if (FEX::HLE::HasSyscallError(Result)) { - return Result; - } - - shmid_ds stat; - - [[maybe_unused]] auto res = shmctl(first, IPC_STAT, &stat); - LOGMAN_THROW_A_FMT(res != -1, "shmctl IPC_STAT failed"); - - Length = stat.shm_segsz; - FEX::HLE::_SyscallHandler->TrackShmat(Thread, first, ResultAddr, second, Length); + auto Result = FEX::HLE::_SyscallHandler->GuestShmat(false, Frame->Thread, first, reinterpret_cast(ptr), second); + if (!FEX::HLE::HasSyscallError(Result)) { + *reinterpret_cast(third) = Result; } - - FEX::HLE::_SyscallHandler->InvalidateCodeRangeIfNecessary(Thread, ResultAddr, Length); - - *reinterpret_cast(third) = ResultAddr; return Result; } case OP_SHMDT: { diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/Memory.cpp b/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/Memory.cpp index 0c431740b..1b2b15039 100644 --- a/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/Memory.cpp +++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/Memory.cpp @@ -67,30 +67,7 @@ void RegisterMemory(FEX::HLE::SyscallHandler* Handler) { REGISTER_SYSCALL_IMPL_X64_FLAGS(shmat, SyscallFlags::OPTIMIZETHROUGH | SyscallFlags::NOSYNCSTATEONENTRY, ([](FEXCore::Core::CpuStateFrame* Frame, int shmid, const void* shmaddr, int shmflg) -> uint64_t { - auto Thread = Frame->Thread; - auto CTX = Thread->CTX; - uint64_t Result {}; - uint64_t Length {}; - CTX->MarkMemoryShared(Thread); - - { - auto lk = FEXCore::GuardSignalDeferringSection(FEX::HLE::_SyscallHandler->VMATracking.Mutex, Thread); - Result = reinterpret_cast(::shmat(shmid, shmaddr, shmflg)); - - if (Result == -1) { - SYSCALL_ERRNO(); - } - - shmid_ds stat; - - [[maybe_unused]] auto res = shmctl(shmid, IPC_STAT, &stat); - LOGMAN_THROW_A_FMT(res != -1, "shmctl IPC_STAT failed"); - - Length = stat.shm_segsz; - FEX::HLE::_SyscallHandler->TrackShmat(Thread, shmid, Result, shmflg, Length); - } - - FEX::HLE::_SyscallHandler->InvalidateCodeRangeIfNecessary(Thread, Result, Length); + auto Result = FEX::HLE::_SyscallHandler->GuestShmat(true, Frame->Thread, shmid, shmaddr, shmflg); SYSCALL_ERRNO(); }));