mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-28 16:01:03 +01:00
FEXCore: Fixes ERROR_AND_DIE
ERROR_AND_DIE was using __builtin_trap which would send our application either a SIGILL or SIGTRAP depending on architecture. This would then be captured by our faulting system and passed over to the guest application. If the guest application happened to have a signal handler installed for these then it would pick up this fault and potentially continue unsafely. Now we can remove this usage of __builtin_trap and switch over to our own handler. Our frontend will check to see if the fault came from our handler and uninstall the host signal handlers in this case. Which is what we want for "ERROR_AND_DIE"
This commit is contained in:
1 parent
3dc938b8c5
commit
47d04ae807
6 files changed
+49
-2
No files matched your search
+1
@@ -142,6 +142,7 @@ set (SRCS
|
||||
Utils/Allocator.cpp
|
||||
Utils/Allocator/64BitAllocator.cpp
|
||||
Utils/FileLoading.cpp
|
||||
Utils/ForcedAssert.cpp
|
||||
Utils/LogManager.cpp
|
||||
Utils/Telemetry.cpp
|
||||
Utils/Threads.cpp
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
namespace FEXCore::Assert {
|
||||
// This function can not be inlined
|
||||
[[noreturn]]
|
||||
__attribute__((noinline, naked))
|
||||
void ForcedAssert() {
|
||||
#ifdef _M_X86_64
|
||||
asm volatile("ud2");
|
||||
#else
|
||||
asm volatile("hlt #1");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+7
-2
@@ -1,5 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
// Contains general abstractions related to compilers used to build FEX.
|
||||
|
||||
// Specifies the minimum alignment for a variable or structure field, measured in bytes.
|
||||
@@ -21,9 +20,15 @@
|
||||
#define FEX_PACKED __attribute__((packed))
|
||||
|
||||
// Causes execution to exit abnormally.
|
||||
#define FEX_TRAP_EXECUTION __builtin_trap()
|
||||
#define FEX_TRAP_EXECUTION FEXCore::Assert::ForcedAssert()
|
||||
|
||||
// Dictates to the compiler that the path this is on should not be reachable
|
||||
// from normal execution control flow. If normal execution does reach this,
|
||||
// then program behavior is undefined.
|
||||
#define FEX_UNREACHABLE __builtin_unreachable()
|
||||
|
||||
namespace FEXCore::Assert {
|
||||
// This function can not be inlined
|
||||
[[noreturn]]
|
||||
FEX_DEFAULT_VISIBILITY void ForcedAssert();
|
||||
}
|
||||
@@ -49,6 +49,7 @@ $end_info$
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <sys/sysinfo.h>
|
||||
#include <sys/signal.h>
|
||||
|
||||
namespace {
|
||||
static bool SilentLog;
|
||||
@@ -534,6 +535,25 @@ int main(int argc, char **argv, char **const envp) {
|
||||
FEXCore::Context::InitializeContext(CTX);
|
||||
|
||||
auto SignalDelegation = std::make_unique<FEX::HLE::SignalDelegator>();
|
||||
|
||||
SignalDelegation->RegisterFrontendHostSignalHandler(SIGILL, [&SignalDelegation](FEXCore::Core::InternalThreadState *Thread, int Signal, void *info, void *ucontext) -> bool {
|
||||
ucontext_t* _context = (ucontext_t*)ucontext;
|
||||
auto &mcontext = _context->uc_mcontext;
|
||||
uint64_t PC{};
|
||||
#ifdef _M_ARM_64
|
||||
PC = mcontext.pc;
|
||||
#else
|
||||
PC = mcontext.gregs[REG_RIP];
|
||||
#endif
|
||||
if (PC == reinterpret_cast<uint64_t>(&FEXCore::Assert::ForcedAssert)) {
|
||||
// This is a host side assert. Don't deliver this to the guest
|
||||
// We want to actually break here
|
||||
SignalDelegation->UninstallHostHandler(Signal);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}, true);
|
||||
|
||||
auto SyscallHandler = Loader.Is64BitMode() ? FEX::HLE::x64::CreateHandler(CTX, SignalDelegation.get())
|
||||
: FEX::HLE::x32::CreateHandler(CTX, SignalDelegation.get(), std::move(Allocator));
|
||||
|
||||
|
||||
@@ -241,6 +241,12 @@ namespace FEX::HLE {
|
||||
return true;
|
||||
}
|
||||
|
||||
void SignalDelegator::UninstallHostHandler(int Signal) {
|
||||
SignalHandler &SignalHandler = HostHandlers[Signal];
|
||||
|
||||
::syscall(SYS_rt_sigaction, Signal, &SignalHandler.OldAction, nullptr, 8);
|
||||
}
|
||||
|
||||
SignalDelegator::SignalDelegator() {
|
||||
// Register this delegate
|
||||
LOGMAN_THROW_A(!GlobalDelegator, "Can't register global delegator multiple times!");
|
||||
|
||||
@@ -55,6 +55,7 @@ namespace FEX::HLE {
|
||||
uint64_t GuestSignalFD(int fd, const uint64_t *set, size_t sigsetsize , int flags);
|
||||
/** @} */
|
||||
|
||||
void UninstallHostHandler(int Signal);
|
||||
protected:
|
||||
// Called from the thunk handler to handle the signal
|
||||
void HandleGuestSignal(FEXCore::Core::InternalThreadState *Thread, int Signal, void *Info, void *UContext) override;
|
||||
|
||||
Reference in new issue
Block a user