diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/SignalDelegator.cpp b/Source/Tools/LinuxEmulation/LinuxSyscalls/SignalDelegator.cpp index b556690abc..51abf11619 100644 --- a/Source/Tools/LinuxEmulation/LinuxSyscalls/SignalDelegator.cpp +++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/SignalDelegator.cpp @@ -578,18 +578,8 @@ void SignalDelegator::HandleGuestSignal(FEX::HLE::ThreadStateObject* ThreadObjec ERROR_AND_DIE_FMT("X86 shouldn't hit this InterruptFaultPage"); #endif } - } else if (Signal == SIGSEGV && (SigInfo.si_code == SEGV_MAPERR || SigInfo.si_code == SEGV_ACCERR) && - FaultSafeUserMemAccess::IsFaultLocation(ArchHelpers::Context::GetPc(UContext))) { - // If you want to emulate EFAULT behaviour then enable this if-statement. - // Do this once we find an application that depends on this. - if constexpr (false) { - // Return from the subroutine, returning EFAULT. - ArchHelpers::Context::SetArmReg(UContext, 0, EFAULT); - ArchHelpers::Context::SetPc(UContext, ArchHelpers::Context::GetArmReg(UContext, 30)); - return; - } else { - ERROR_AND_DIE_FMT("Received invalid data to syscall. Crashing now!"); - } + } else if (FaultSafeUserMemAccess::TryHandleSafeFault(Signal, SigInfo, UContext)) { + ERROR_AND_DIE_FMT("Received invalid data to syscall. Crashing now!"); } else { if (IsAsyncSignal(&SigInfo, Signal) && MustDeferSignal) { // If the signal is asynchronous (as determined by si_code) and FEX is in a state of needing diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls.h b/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls.h index 5417a3c6ec..7dd609bfe2 100644 --- a/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls.h +++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls.h @@ -12,6 +12,7 @@ desc: Glue logic, STRACE magic #include "LinuxSyscalls/LinuxAllocator.h" #include "LinuxSyscalls/ThreadManager.h" #include "LinuxSyscalls/Seccomp/SeccompEmulator.h" +#include "ArchHelpers/MContext.h" #include #include @@ -674,6 +675,18 @@ namespace FaultSafeUserMemAccess { } #endif bool IsFaultLocation(uint64_t PC); + + static inline bool TryHandleSafeFault(int Signal, siginfo_t const &SigInfo, void *UContext) { + if (Signal == SIGSEGV && (SigInfo.si_code == SEGV_MAPERR || SigInfo.si_code == SEGV_ACCERR) && + FaultSafeUserMemAccess::IsFaultLocation(ArchHelpers::Context::GetPc(UContext))) { + // Return from the subroutine, returning EFAULT. + ArchHelpers::Context::SetArmReg(UContext, 0, EFAULT); + ArchHelpers::Context::SetPc(UContext, ArchHelpers::Context::GetArmReg(UContext, 30)); + return true; + } + + return false; + } } // namespace FaultSafeUserMemAccess } // namespace FEX::HLE