From f9cd0f0179c65ffda1112082fd1695d9f4a146c6 Mon Sep 17 00:00:00 2001 From: duck <37@cmail.nu> Date: Wed, 6 Jan 2021 05:07:47 -0500 Subject: [PATCH 1/3] Have tests that throw a non-HLT SIGSEGV fail Patch moves HandleSIGSEGV in HostFactory.cpp to a non-frontend host signal handler, then registers its own frontend signal handler to catch unhandled segfaults. --- External/FEXCore/Source/Interface/Context/Context.cpp | 4 ++++ External/FEXCore/Source/Interface/Context/Context.h | 1 + External/FEXCore/Source/Interface/Core/Core.cpp | 4 ++++ External/FEXCore/include/FEXCore/Core/Context.h | 1 + Source/CommonCore/HostFactory.cpp | 4 ++-- Source/Tests/TestHarnessRunner.cpp | 11 +++++++++-- 6 files changed, 21 insertions(+), 4 deletions(-) diff --git a/External/FEXCore/Source/Interface/Context/Context.cpp b/External/FEXCore/Source/Interface/Context/Context.cpp index 883043b0e..5a0b8bee8 100644 --- a/External/FEXCore/Source/Interface/Context/Context.cpp +++ b/External/FEXCore/Source/Interface/Context/Context.cpp @@ -99,6 +99,10 @@ namespace FEXCore::Context { CTX->HandleCallback(RIP); } + void RegisterHostSignalHandler(FEXCore::Context::Context *CTX, int Signal, HostSignalDelegatorFunction Func) { + CTX->RegisterHostSignalHandler(Signal, Func); + } + void RegisterFrontendHostSignalHandler(FEXCore::Context::Context *CTX, int Signal, HostSignalDelegatorFunction Func) { CTX->RegisterFrontendHostSignalHandler(Signal, Func); } diff --git a/External/FEXCore/Source/Interface/Context/Context.h b/External/FEXCore/Source/Interface/Context/Context.h index be4f26bf6..e71856156 100644 --- a/External/FEXCore/Source/Interface/Context/Context.h +++ b/External/FEXCore/Source/Interface/Context/Context.h @@ -117,6 +117,7 @@ namespace FEXCore::Context { void StartGdbServer(); void StopGdbServer(); void HandleCallback(uint64_t RIP); + void RegisterHostSignalHandler(int Signal, HostSignalDelegatorFunction Func); void RegisterFrontendHostSignalHandler(int Signal, HostSignalDelegatorFunction Func); static void RemoveCodeEntry(FEXCore::Core::InternalThreadState *Thread, uint64_t GuestRIP); diff --git a/External/FEXCore/Source/Interface/Core/Core.cpp b/External/FEXCore/Source/Interface/Core/Core.cpp index d308d9550..75c30b22d 100644 --- a/External/FEXCore/Source/Interface/Core/Core.cpp +++ b/External/FEXCore/Source/Interface/Core/Core.cpp @@ -286,6 +286,10 @@ namespace FEXCore::Context { Thread->CPUBackend->CallbackPtr(Thread, RIP); } + void Context::RegisterHostSignalHandler(int Signal, HostSignalDelegatorFunction Func) { + SignalDelegation->RegisterHostSignalHandler(Signal, Func); + } + void Context::RegisterFrontendHostSignalHandler(int Signal, HostSignalDelegatorFunction Func) { SignalDelegation->RegisterFrontendHostSignalHandler(Signal, Func); } diff --git a/External/FEXCore/include/FEXCore/Core/Context.h b/External/FEXCore/include/FEXCore/Core/Context.h index 2e9f00352..eecdef535 100644 --- a/External/FEXCore/include/FEXCore/Core/Context.h +++ b/External/FEXCore/include/FEXCore/Core/Context.h @@ -218,6 +218,7 @@ namespace FEXCore::Context { void HandleCallback(FEXCore::Context::Context *CTX, uint64_t RIP); + void RegisterHostSignalHandler(FEXCore::Context::Context *CTX, int Signal, HostSignalDelegatorFunction Func); void RegisterFrontendHostSignalHandler(FEXCore::Context::Context *CTX, int Signal, HostSignalDelegatorFunction Func); FEXCore::Core::InternalThreadState* CreateThread(FEXCore::Context::Context *CTX, FEXCore::Core::CPUState *NewThreadState, uint64_t ParentTID); diff --git a/Source/CommonCore/HostFactory.cpp b/Source/CommonCore/HostFactory.cpp index a28734605..6c516d319 100644 --- a/Source/CommonCore/HostFactory.cpp +++ b/Source/CommonCore/HostFactory.cpp @@ -58,7 +58,7 @@ namespace HostFactory { , CTX {CTX} , ThreadState {Thread} , IsFallback {Fallback} { - FEXCore::Context::RegisterFrontendHostSignalHandler(CTX, SIGSEGV, + FEXCore::Context::RegisterHostSignalHandler(CTX, SIGSEGV, [](FEXCore::Core::InternalThreadState *Thread, int Signal, void *info, void *ucontext) -> bool { auto InternalThread = reinterpret_cast(Thread); HostCore *Core = reinterpret_cast(InternalThread->CPUBackend.get()); @@ -66,7 +66,7 @@ namespace HostFactory { } ); - FEXCore::Context::RegisterFrontendHostSignalHandler(CTX, 63, [](FEXCore::Core::InternalThreadState *Thread, int Signal, void *info, void *ucontext) -> bool { + FEXCore::Context::RegisterHostSignalHandler(CTX, 63, [](FEXCore::Core::InternalThreadState *Thread, int Signal, void *info, void *ucontext) -> bool { return true; }); } diff --git a/Source/Tests/TestHarnessRunner.cpp b/Source/Tests/TestHarnessRunner.cpp index 470f39e0b..0a962be62 100644 --- a/Source/Tests/TestHarnessRunner.cpp +++ b/Source/Tests/TestHarnessRunner.cpp @@ -101,6 +101,12 @@ int main(int argc, char **argv, char **const envp) { std::unique_ptr SignalDelegation = std::make_unique(); std::unique_ptr SyscallHandler{FEX::HLE::CreateHandler(Loader.Is64BitMode() ? FEXCore::Context::OperatingMode::MODE_64BIT : FEXCore::Context::OperatingMode::MODE_32BIT, CTX, SignalDelegation.get())}; + bool DidFail = false; + SignalDelegation->RegisterFrontendHostSignalHandler(SIGSEGV, [&DidFail](FEXCore::Core::InternalThreadState *Thread, int Signal, void *info, void *ucontext) { + DidFail = true; + return false; + }); + FEXCore::Context::SetSignalDelegator(CTX, SignalDelegation.get()); FEXCore::Context::SetSyscallHandler(CTX, SyscallHandler.get()); bool Result1 = FEXCore::Context::InitCore(CTX, &Loader); @@ -113,9 +119,10 @@ int main(int argc, char **argv, char **const envp) { // Just re-use compare state. It also checks against the expected values in config. FEXCore::Core::CPUState State; FEXCore::Context::GetCPUState(CTX, &State); - bool Passed = Loader.CompareStates(&State, nullptr); + bool Passed = !DidFail && Loader.CompareStates(&State, nullptr); - LogMan::Msg::I("Passed? %s\n", Passed ? "Yes" : "No"); + LogMan::Msg::I("Faulted? %s", DidFail ? "Yes" : "No"); + LogMan::Msg::I("Passed? %s", Passed ? "Yes" : "No"); FEXCore::Context::DestroyContext(CTX); From ffc4996ca6a0f450b696ff99d0d60aeed39216ce Mon Sep 17 00:00:00 2001 From: duck <37@cmail.nu> Date: Wed, 6 Jan 2021 18:11:23 -0500 Subject: [PATCH 2/3] DidFail -> DidFault --- Source/Tests/TestHarnessRunner.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/Tests/TestHarnessRunner.cpp b/Source/Tests/TestHarnessRunner.cpp index 0a962be62..8c07a8c63 100644 --- a/Source/Tests/TestHarnessRunner.cpp +++ b/Source/Tests/TestHarnessRunner.cpp @@ -101,9 +101,9 @@ int main(int argc, char **argv, char **const envp) { std::unique_ptr SignalDelegation = std::make_unique(); std::unique_ptr SyscallHandler{FEX::HLE::CreateHandler(Loader.Is64BitMode() ? FEXCore::Context::OperatingMode::MODE_64BIT : FEXCore::Context::OperatingMode::MODE_32BIT, CTX, SignalDelegation.get())}; - bool DidFail = false; + bool DidFault = false; SignalDelegation->RegisterFrontendHostSignalHandler(SIGSEGV, [&DidFail](FEXCore::Core::InternalThreadState *Thread, int Signal, void *info, void *ucontext) { - DidFail = true; + DidFault = true; return false; }); @@ -119,9 +119,9 @@ int main(int argc, char **argv, char **const envp) { // Just re-use compare state. It also checks against the expected values in config. FEXCore::Core::CPUState State; FEXCore::Context::GetCPUState(CTX, &State); - bool Passed = !DidFail && Loader.CompareStates(&State, nullptr); + bool Passed = !DidFault && Loader.CompareStates(&State, nullptr); - LogMan::Msg::I("Faulted? %s", DidFail ? "Yes" : "No"); + LogMan::Msg::I("Faulted? %s", DidFault ? "Yes" : "No"); LogMan::Msg::I("Passed? %s", Passed ? "Yes" : "No"); FEXCore::Context::DestroyContext(CTX); From 6388151fc0a3acde2d438b55fd64f3c96ae26cc6 Mon Sep 17 00:00:00 2001 From: duck <37@cmail.nu> Date: Wed, 6 Jan 2021 18:12:09 -0500 Subject: [PATCH 3/3] Oops. --- Source/Tests/TestHarnessRunner.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Tests/TestHarnessRunner.cpp b/Source/Tests/TestHarnessRunner.cpp index 8c07a8c63..6bcf30271 100644 --- a/Source/Tests/TestHarnessRunner.cpp +++ b/Source/Tests/TestHarnessRunner.cpp @@ -102,7 +102,7 @@ int main(int argc, char **argv, char **const envp) { std::unique_ptr SyscallHandler{FEX::HLE::CreateHandler(Loader.Is64BitMode() ? FEXCore::Context::OperatingMode::MODE_64BIT : FEXCore::Context::OperatingMode::MODE_32BIT, CTX, SignalDelegation.get())}; bool DidFault = false; - SignalDelegation->RegisterFrontendHostSignalHandler(SIGSEGV, [&DidFail](FEXCore::Core::InternalThreadState *Thread, int Signal, void *info, void *ucontext) { + SignalDelegation->RegisterFrontendHostSignalHandler(SIGSEGV, [&DidFault](FEXCore::Core::InternalThreadState *Thread, int Signal, void *info, void *ucontext) { DidFault = true; return false; });