From 9baf096a106726ab46beb96382e19b8a16a74a2f Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Sat, 16 May 2020 15:05:36 -0700 Subject: [PATCH] dmnt: make debug event result handling more robust (closes #938) --- .../dmnt/source/cheat/impl/dmnt_cheat_api.cpp | 37 +++++++---- .../impl/dmnt_cheat_debug_events_manager.cpp | 66 +++++++++++-------- .../impl/dmnt_cheat_debug_events_manager.hpp | 2 +- stratosphere/dmnt/source/dmnt_main.cpp | 2 +- 4 files changed, 64 insertions(+), 43 deletions(-) diff --git a/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_api.cpp b/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_api.cpp index 6369937ef..ee88402c4 100644 --- a/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_api.cpp +++ b/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_api.cpp @@ -599,25 +599,34 @@ namespace ams::dmnt::cheat::impl { /* Atomically wait (and clear) signal for new process. */ this_ptr->debug_events_event.Wait(); while (true) { - while (R_SUCCEEDED(svcWaitSynchronizationSingle(this_ptr->GetCheatProcessHandle(), std::numeric_limits::max()))) { + Handle cheat_process_handle = this_ptr->GetCheatProcessHandle(); + while (cheat_process_handle != svc::InvalidHandle && R_SUCCEEDED(svcWaitSynchronizationSingle(this_ptr->GetCheatProcessHandle(), std::numeric_limits::max()))) { this_ptr->cheat_lock.Lock(); ON_SCOPE_EXIT { this_ptr->cheat_lock.Unlock(); }; + { + ON_SCOPE_EXIT { cheat_process_handle = this_ptr->GetCheatProcessHandle(); }; - /* If we did an unsafe break, wait until we're not broken. */ - if (this_ptr->broken_unsafe) { - this_ptr->cheat_lock.Unlock(); - this_ptr->unsafe_break_event.Wait(); - this_ptr->cheat_lock.Lock(); - if (this_ptr->GetCheatProcessHandle() != svc::InvalidHandle) { - continue; - } else { - break; + /* If we did an unsafe break, wait until we're not broken. */ + if (this_ptr->broken_unsafe) { + this_ptr->cheat_lock.Unlock(); + this_ptr->unsafe_break_event.Wait(); + this_ptr->cheat_lock.Lock(); + if (this_ptr->GetCheatProcessHandle() != svc::InvalidHandle) { + continue; + } else { + break; + } } - } - /* Handle any pending debug events. */ - if (this_ptr->HasActiveCheatProcess()) { - dmnt::cheat::impl::ContinueCheatProcess(this_ptr->GetCheatProcessHandle()); + /* Handle any pending debug events. */ + if (this_ptr->HasActiveCheatProcess()) { + R_TRY_CATCH(dmnt::cheat::impl::ContinueCheatProcess(this_ptr->GetCheatProcessHandle())) { + R_CATCH(svc::ResultProcessTerminated) { + this_ptr->CloseActiveCheatProcess(); + break; + } + } R_END_TRY_CATCH_WITH_ABORT_UNLESS; + } } } diff --git a/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_debug_events_manager.cpp b/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_debug_events_manager.cpp index 3cc7dd057..6a4ba7a39 100644 --- a/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_debug_events_manager.cpp +++ b/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_debug_events_manager.cpp @@ -27,10 +27,11 @@ namespace ams::dmnt::cheat::impl { static constexpr size_t NumCores = 4; static constexpr size_t ThreadStackSize = os::MemoryPageSize; private: - std::array message_queue_buffers; - std::array message_queues; + std::array handle_message_queue_buffers; + std::array result_message_queue_buffers; + std::array handle_message_queues; + std::array result_message_queues; std::array threads; - os::Event continued_event; alignas(os::MemoryPageSize) u8 thread_stacks[NumCores][ThreadStackSize]; private: @@ -43,14 +44,14 @@ namespace ams::dmnt::cheat::impl { Handle debug_handle = this_ptr->WaitReceiveHandle(current_core); /* Continue events on the correct core. */ - R_ABORT_UNLESS(this_ptr->ContinueDebugEvent(debug_handle)); + Result result = this_ptr->ContinueDebugEvent(debug_handle); - /* Signal that we've continued. */ - this_ptr->SignalContinued(); + /* Return our result. */ + this_ptr->SendContinueResult(current_core, result); } } - size_t GetTargetCore(const svc::DebugEventInfo &dbg_event, Handle debug_handle) { + Result GetTargetCore(size_t *out, const svc::DebugEventInfo &dbg_event, Handle debug_handle) { /* If we don't need to continue on a specific core, use the system core. */ size_t target_core = NumCores - 1; @@ -58,20 +59,26 @@ namespace ams::dmnt::cheat::impl { if (dbg_event.type == svc::DebugEvent_AttachThread) { u64 out64 = 0; u32 out32 = 0; - R_ABORT_UNLESS(svcGetDebugThreadParam(&out64, &out32, debug_handle, dbg_event.info.attach_thread.thread_id, DebugThreadParam_CurrentCore)); + + R_TRY_CATCH(svcGetDebugThreadParam(&out64, &out32, debug_handle, dbg_event.info.attach_thread.thread_id, DebugThreadParam_CurrentCore)) { + R_CATCH_RETHROW(svc::ResultProcessTerminated) + } R_END_TRY_CATCH_WITH_ABORT_UNLESS; + target_core = out32; } - return target_core; + /* Set the target core. */ + *out = target_core; + return ResultSuccess(); } void SendHandle(size_t target_core, Handle debug_handle) { - this->message_queues[target_core].Send(static_cast(debug_handle)); + this->handle_message_queues[target_core].Send(static_cast(debug_handle)); } Handle WaitReceiveHandle(size_t core_id) { uintptr_t x = 0; - this->message_queues[core_id].Receive(&x); + this->handle_message_queues[core_id].Receive(&x); return static_cast(x); } @@ -83,22 +90,27 @@ namespace ams::dmnt::cheat::impl { } } - void WaitContinued() { - this->continued_event.Wait(); + void SendContinueResult(size_t target_core, Result result) { + this->result_message_queues[target_core].Send(static_cast(result.GetValue())); } - void SignalContinued() { - this->continued_event.Signal(); + Result GetContinueResult(size_t core_id) { + uintptr_t x = 0; + this->result_message_queues[core_id].Receive(&x); + return static_cast(x); } - public: DebugEventsManager() - : message_queues{ - os::MessageQueue(std::addressof(message_queue_buffers[0]), 1), - os::MessageQueue(std::addressof(message_queue_buffers[1]), 1), - os::MessageQueue(std::addressof(message_queue_buffers[2]), 1), - os::MessageQueue(std::addressof(message_queue_buffers[3]), 1)}, - continued_event(os::EventClearMode_AutoClear), + : handle_message_queues{ + os::MessageQueue(std::addressof(handle_message_queue_buffers[0]), 1), + os::MessageQueue(std::addressof(handle_message_queue_buffers[1]), 1), + os::MessageQueue(std::addressof(handle_message_queue_buffers[2]), 1), + os::MessageQueue(std::addressof(handle_message_queue_buffers[3]), 1)}, + result_message_queues{ + os::MessageQueue(std::addressof(result_message_queue_buffers[0]), 1), + os::MessageQueue(std::addressof(result_message_queue_buffers[1]), 1), + os::MessageQueue(std::addressof(result_message_queue_buffers[2]), 1), + os::MessageQueue(std::addressof(result_message_queue_buffers[3]), 1)}, thread_stacks{} { for (size_t i = 0; i < NumCores; i++) { @@ -114,19 +126,19 @@ namespace ams::dmnt::cheat::impl { } } - void ContinueCheatProcess(Handle cheat_dbg_hnd) { + Result ContinueCheatProcess(Handle cheat_dbg_hnd) { /* Loop getting all debug events. */ svc::DebugEventInfo d; size_t target_core = NumCores - 1; while (R_SUCCEEDED(svc::GetDebugEvent(std::addressof(d), cheat_dbg_hnd))) { if (d.type == svc::DebugEvent_AttachThread) { - target_core = GetTargetCore(d, cheat_dbg_hnd); + R_TRY(GetTargetCore(std::addressof(target_core), d, cheat_dbg_hnd)); } } /* Send handle to correct core, wait for continue to finish. */ this->SendHandle(target_core, cheat_dbg_hnd); - this->WaitContinued(); + return this->GetContinueResult(target_core); } }; @@ -139,8 +151,8 @@ namespace ams::dmnt::cheat::impl { new (GetPointer(g_events_manager)) DebugEventsManager; } - void ContinueCheatProcess(Handle cheat_dbg_hnd) { - GetReference(g_events_manager).ContinueCheatProcess(cheat_dbg_hnd); + Result ContinueCheatProcess(Handle cheat_dbg_hnd) { + return GetReference(g_events_manager).ContinueCheatProcess(cheat_dbg_hnd); } } diff --git a/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_debug_events_manager.hpp b/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_debug_events_manager.hpp index 604183c60..f5eea0ea0 100644 --- a/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_debug_events_manager.hpp +++ b/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_debug_events_manager.hpp @@ -20,6 +20,6 @@ namespace ams::dmnt::cheat::impl { void InitializeDebugEventsManager(); - void ContinueCheatProcess(Handle cheat_dbg_hnd); + Result ContinueCheatProcess(Handle cheat_dbg_hnd); } diff --git a/stratosphere/dmnt/source/dmnt_main.cpp b/stratosphere/dmnt/source/dmnt_main.cpp index 12aded756..3839d4b9a 100644 --- a/stratosphere/dmnt/source/dmnt_main.cpp +++ b/stratosphere/dmnt/source/dmnt_main.cpp @@ -40,7 +40,7 @@ namespace ams { namespace result { - bool CallFatalOnResultAssertion = true; + bool CallFatalOnResultAssertion = false; }