mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-26 22:02:15 +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,9 +599,12 @@ namespace ams::dmnt::cheat::impl {
|
||||||
/* Atomically wait (and clear) signal for new process. */
|
/* Atomically wait (and clear) signal for new process. */
|
||||||
this_ptr->debug_events_event.Wait();
|
this_ptr->debug_events_event.Wait();
|
||||||
while (true) {
|
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();
|
this_ptr->cheat_lock.Lock();
|
||||||
ON_SCOPE_EXIT { this_ptr->cheat_lock.Unlock(); };
|
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 we did an unsafe break, wait until we're not broken. */
|
||||||
if (this_ptr->broken_unsafe) {
|
if (this_ptr->broken_unsafe) {
|
||||||
|
@ -617,7 +620,13 @@ namespace ams::dmnt::cheat::impl {
|
||||||
|
|
||||||
/* Handle any pending debug events. */
|
/* Handle any pending debug events. */
|
||||||
if (this_ptr->HasActiveCheatProcess()) {
|
if (this_ptr->HasActiveCheatProcess()) {
|
||||||
dmnt::cheat::impl::ContinueCheatProcess(this_ptr->GetCheatProcessHandle());
|
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 NumCores = 4;
|
||||||
static constexpr size_t ThreadStackSize = os::MemoryPageSize;
|
static constexpr size_t ThreadStackSize = os::MemoryPageSize;
|
||||||
private:
|
private:
|
||||||
std::array<uintptr_t, NumCores> message_queue_buffers;
|
std::array<uintptr_t, NumCores> handle_message_queue_buffers;
|
||||||
std::array<os::MessageQueue, NumCores> message_queues;
|
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;
|
std::array<os::ThreadType, NumCores> threads;
|
||||||
os::Event continued_event;
|
|
||||||
|
|
||||||
alignas(os::MemoryPageSize) u8 thread_stacks[NumCores][ThreadStackSize];
|
alignas(os::MemoryPageSize) u8 thread_stacks[NumCores][ThreadStackSize];
|
||||||
private:
|
private:
|
||||||
|
@ -43,14 +44,14 @@ namespace ams::dmnt::cheat::impl {
|
||||||
Handle debug_handle = this_ptr->WaitReceiveHandle(current_core);
|
Handle debug_handle = this_ptr->WaitReceiveHandle(current_core);
|
||||||
|
|
||||||
/* Continue events on the correct 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. */
|
/* Return our result. */
|
||||||
this_ptr->SignalContinued();
|
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. */
|
/* If we don't need to continue on a specific core, use the system core. */
|
||||||
size_t target_core = NumCores - 1;
|
size_t target_core = NumCores - 1;
|
||||||
|
|
||||||
|
@ -58,20 +59,26 @@ namespace ams::dmnt::cheat::impl {
|
||||||
if (dbg_event.type == svc::DebugEvent_AttachThread) {
|
if (dbg_event.type == svc::DebugEvent_AttachThread) {
|
||||||
u64 out64 = 0;
|
u64 out64 = 0;
|
||||||
u32 out32 = 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;
|
target_core = out32;
|
||||||
}
|
}
|
||||||
|
|
||||||
return target_core;
|
/* Set the target core. */
|
||||||
|
*out = target_core;
|
||||||
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendHandle(size_t target_core, Handle debug_handle) {
|
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) {
|
Handle WaitReceiveHandle(size_t core_id) {
|
||||||
uintptr_t x = 0;
|
uintptr_t x = 0;
|
||||||
this->message_queues[core_id].Receive(&x);
|
this->handle_message_queues[core_id].Receive(&x);
|
||||||
return static_cast<Handle>(x);
|
return static_cast<Handle>(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,22 +90,27 @@ namespace ams::dmnt::cheat::impl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WaitContinued() {
|
void SendContinueResult(size_t target_core, Result result) {
|
||||||
this->continued_event.Wait();
|
this->result_message_queues[target_core].Send(static_cast<uintptr_t>(result.GetValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SignalContinued() {
|
Result GetContinueResult(size_t core_id) {
|
||||||
this->continued_event.Signal();
|
uintptr_t x = 0;
|
||||||
|
this->result_message_queues[core_id].Receive(&x);
|
||||||
|
return static_cast<Result>(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DebugEventsManager()
|
DebugEventsManager()
|
||||||
: message_queues{
|
: handle_message_queues{
|
||||||
os::MessageQueue(std::addressof(message_queue_buffers[0]), 1),
|
os::MessageQueue(std::addressof(handle_message_queue_buffers[0]), 1),
|
||||||
os::MessageQueue(std::addressof(message_queue_buffers[1]), 1),
|
os::MessageQueue(std::addressof(handle_message_queue_buffers[1]), 1),
|
||||||
os::MessageQueue(std::addressof(message_queue_buffers[2]), 1),
|
os::MessageQueue(std::addressof(handle_message_queue_buffers[2]), 1),
|
||||||
os::MessageQueue(std::addressof(message_queue_buffers[3]), 1)},
|
os::MessageQueue(std::addressof(handle_message_queue_buffers[3]), 1)},
|
||||||
continued_event(os::EventClearMode_AutoClear),
|
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{}
|
thread_stacks{}
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < NumCores; i++) {
|
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. */
|
/* Loop getting all debug events. */
|
||||||
svc::DebugEventInfo d;
|
svc::DebugEventInfo d;
|
||||||
size_t target_core = NumCores - 1;
|
size_t target_core = NumCores - 1;
|
||||||
while (R_SUCCEEDED(svc::GetDebugEvent(std::addressof(d), cheat_dbg_hnd))) {
|
while (R_SUCCEEDED(svc::GetDebugEvent(std::addressof(d), cheat_dbg_hnd))) {
|
||||||
if (d.type == svc::DebugEvent_AttachThread) {
|
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. */
|
/* Send handle to correct core, wait for continue to finish. */
|
||||||
this->SendHandle(target_core, cheat_dbg_hnd);
|
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;
|
new (GetPointer(g_events_manager)) DebugEventsManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContinueCheatProcess(Handle cheat_dbg_hnd) {
|
Result ContinueCheatProcess(Handle cheat_dbg_hnd) {
|
||||||
GetReference(g_events_manager).ContinueCheatProcess(cheat_dbg_hnd);
|
return GetReference(g_events_manager).ContinueCheatProcess(cheat_dbg_hnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,6 @@ namespace ams::dmnt::cheat::impl {
|
||||||
|
|
||||||
void InitializeDebugEventsManager();
|
void InitializeDebugEventsManager();
|
||||||
|
|
||||||
void ContinueCheatProcess(Handle cheat_dbg_hnd);
|
Result ContinueCheatProcess(Handle cheat_dbg_hnd);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ namespace ams {
|
||||||
|
|
||||||
namespace result {
|
namespace result {
|
||||||
|
|
||||||
bool CallFatalOnResultAssertion = true;
|
bool CallFatalOnResultAssertion = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue