mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-09 22:56:35 +00:00
dmnt: make debug event result handling more robust (closes #938)
This commit is contained in:
parent
9598da0a0b
commit
9baf096a10
4 changed files with 64 additions and 43 deletions
|
@ -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<u64>::max()))) {
|
||||
Handle cheat_process_handle = this_ptr->GetCheatProcessHandle();
|
||||
while (cheat_process_handle != svc::InvalidHandle && R_SUCCEEDED(svcWaitSynchronizationSingle(this_ptr->GetCheatProcessHandle(), std::numeric_limits<u64>::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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<uintptr_t, NumCores> message_queue_buffers;
|
||||
std::array<os::MessageQueue, NumCores> message_queues;
|
||||
std::array<uintptr_t, NumCores> handle_message_queue_buffers;
|
||||
std::array<uintptr_t, NumCores> result_message_queue_buffers;
|
||||
std::array<os::MessageQueue, NumCores> handle_message_queues;
|
||||
std::array<os::MessageQueue, NumCores> result_message_queues;
|
||||
std::array<os::ThreadType, NumCores> 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<uintptr_t>(debug_handle));
|
||||
this->handle_message_queues[target_core].Send(static_cast<uintptr_t>(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<Handle>(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<uintptr_t>(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<Result>(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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,6 +20,6 @@ namespace ams::dmnt::cheat::impl {
|
|||
|
||||
void InitializeDebugEventsManager();
|
||||
|
||||
void ContinueCheatProcess(Handle cheat_dbg_hnd);
|
||||
Result ContinueCheatProcess(Handle cheat_dbg_hnd);
|
||||
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ namespace ams {
|
|||
|
||||
namespace result {
|
||||
|
||||
bool CallFatalOnResultAssertion = true;
|
||||
bool CallFatalOnResultAssertion = false;
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue