LinuxSyscalls: Unify shmat implementations

This commit is contained in:
Tony Wasserka committed 2025-06-03 11:10:07 +02:00
1 parent 365ed2cd70
commit ca12dc9213
5 files changed
+41 -80

No files matched your search

@@ -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);
@@ -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<uint64_t>(::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);
@@ -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<const void*>(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 {
@@ -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<const void*>(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<const void*>(ptr), second);
if (!FEX::HLE::HasSyscallError(Result)) {
*reinterpret_cast<uint32_t*>(third) = Result;
}
FEX::HLE::_SyscallHandler->InvalidateCodeRangeIfNecessary(Thread, ResultAddr, Length);
*reinterpret_cast<uint32_t*>(third) = ResultAddr;
return Result;
}
case OP_SHMDT: {
@@ -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<uint64_t>(::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();
}));