From 9011384dbe08d9792891fdb60008f292f9c81f14 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Sun, 31 Oct 2021 23:57:28 -0700 Subject: [PATCH] dmnt2: first pass at wait-for-application --- .../dmnt.gen2/source/dmnt2_debug_process.cpp | 7 +++- .../dmnt.gen2/source/dmnt2_debug_process.hpp | 2 +- .../source/dmnt2_gdb_server_impl.cpp | 34 +++++++++++++++---- .../source/dmnt2_gdb_server_impl.hpp | 1 + stratosphere/dmnt.gen2/source/dmnt2_main.cpp | 3 ++ .../dmnt/source/cheat/impl/dmnt_cheat_api.cpp | 1 - 6 files changed, 39 insertions(+), 9 deletions(-) diff --git a/stratosphere/dmnt.gen2/source/dmnt2_debug_process.cpp b/stratosphere/dmnt.gen2/source/dmnt2_debug_process.cpp index 01ef99bef..ea73fdedc 100644 --- a/stratosphere/dmnt.gen2/source/dmnt2_debug_process.cpp +++ b/stratosphere/dmnt.gen2/source/dmnt2_debug_process.cpp @@ -27,10 +27,15 @@ namespace ams::dmnt { } - Result DebugProcess::Attach(os::ProcessId process_id) { + Result DebugProcess::Attach(os::ProcessId process_id, bool start_process) { /* Attach to the process. */ R_TRY(svc::DebugActiveProcess(std::addressof(m_debug_handle), process_id.value)); + /* If necessary, start the process. */ + if (start_process) { + R_ABORT_UNLESS(pm::dmnt::StartProcess(process_id)); + } + /* Collect initial information. */ R_TRY(this->Start()); diff --git a/stratosphere/dmnt.gen2/source/dmnt2_debug_process.hpp b/stratosphere/dmnt.gen2/source/dmnt2_debug_process.hpp index 4ab1e83d1..3c20fda47 100644 --- a/stratosphere/dmnt.gen2/source/dmnt2_debug_process.hpp +++ b/stratosphere/dmnt.gen2/source/dmnt2_debug_process.hpp @@ -109,7 +109,7 @@ namespace ams::dmnt { m_status = ProcessStatus_DebugBreak; } public: - Result Attach(os::ProcessId process_id); + Result Attach(os::ProcessId process_id, bool start_process = false); void Detach(); Result GetThreadContext(svc::ThreadContext *out, u64 thread_id, u32 flags); diff --git a/stratosphere/dmnt.gen2/source/dmnt2_gdb_server_impl.cpp b/stratosphere/dmnt.gen2/source/dmnt2_gdb_server_impl.cpp index fd0683e34..7a0246b8d 100644 --- a/stratosphere/dmnt.gen2/source/dmnt2_gdb_server_impl.cpp +++ b/stratosphere/dmnt.gen2/source/dmnt2_gdb_server_impl.cpp @@ -857,11 +857,18 @@ namespace ams::dmnt { /* Detach. */ m_debug_process.Detach(); - /* If we have a process id, attach. */ - if (R_FAILED(m_debug_process.Attach(m_process_id))) { - AMS_DMNT2_GDB_LOG_DEBUG("Failed to attach to %016lx\n", m_process_id.value); - g_event_done_cv.Signal(); - continue; + /* Check if we need to start the process. */ + const bool start_process = m_process_id == m_wait_process_id; + { + /* Clear our wait process id. */ + ON_SCOPE_EXIT { if (start_process) { m_wait_process_id = os::InvalidProcessId; } }; + + /* If we have a process id, attach. */ + if (R_FAILED(m_debug_process.Attach(m_process_id, m_process_id == m_wait_process_id))) { + AMS_DMNT2_GDB_LOG_DEBUG("Failed to attach to %016lx\n", m_process_id.value); + g_event_done_cv.Signal(); + continue; + } } /* Set our process id. */ @@ -1882,7 +1889,22 @@ namespace ams::dmnt { } } } else if (ParsePrefix(command, "wait application") || ParsePrefix(command, "wait app")) { - SetReply(m_buffer, "[TODO] wait for next application\n"); + /* Wait for an application process. */ + { + /* Get hook to creation of application process. */ + os::NativeHandle h; + R_ABORT_UNLESS(pm::dmnt::HookToCreateApplicationProcess(std::addressof(h))); + + /* Wait for event. */ + os::SystemEvent hook_event(h, true, os::InvalidNativeHandle, false, os::EventClearMode_AutoClear); + hook_event.Wait(); + } + + /* Get application process id. */ + R_ABORT_UNLESS(pm::dmnt::GetApplicationProcessId(std::addressof(m_wait_process_id))); + + /* Note that we're attaching. */ + SetReply(m_buffer, "Attach to 0x%lx.\n", m_wait_process_id.value); } else if (ParsePrefix(command, "wait homebrew") || ParsePrefix(command, "wait hb")) { SetReply(m_buffer, "[TODO] wait for next homebrew\n"); } else if (ParsePrefix(command, "wait ")) { diff --git a/stratosphere/dmnt.gen2/source/dmnt2_gdb_server_impl.hpp b/stratosphere/dmnt.gen2/source/dmnt2_gdb_server_impl.hpp index d71cd2e0d..3c0c0aacb 100644 --- a/stratosphere/dmnt.gen2/source/dmnt2_gdb_server_impl.hpp +++ b/stratosphere/dmnt.gen2/source/dmnt2_gdb_server_impl.hpp @@ -42,6 +42,7 @@ namespace ams::dmnt { DebugProcess m_debug_process; os::ProcessId m_process_id{os::InvalidProcessId}; os::Event m_event; + os::ProcessId m_wait_process_id{os::InvalidProcessId}; public: GdbServerImpl(int socket, void *thread_stack, size_t stack_size); ~GdbServerImpl(); diff --git a/stratosphere/dmnt.gen2/source/dmnt2_main.cpp b/stratosphere/dmnt.gen2/source/dmnt2_main.cpp index ed8edb747..a51448480 100644 --- a/stratosphere/dmnt.gen2/source/dmnt2_main.cpp +++ b/stratosphere/dmnt.gen2/source/dmnt2_main.cpp @@ -42,6 +42,9 @@ namespace ams { /* Initialize our connection to sm. */ R_ABORT_UNLESS(sm::Initialize()); + /* Initialize other services we need. */ + R_ABORT_UNLESS(pmdmntInitialize()); + /* Verify that we can sanely execute. */ ams::CheckApiVersion(); } diff --git a/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_api.cpp b/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_api.cpp index 7db61d819..37de31161 100644 --- a/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_api.cpp +++ b/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_api.cpp @@ -248,7 +248,6 @@ namespace ams::dmnt::cheat::impl { void StartProcess(os::ProcessId process_id) const { R_ABORT_UNLESS(pm::dmnt::StartProcess(process_id)); } - public: CheatProcessManager() : m_cheat_lock(), m_unsafe_break_event(os::EventClearMode_ManualClear), m_debug_events_event(os::EventClearMode_AutoClear), m_cheat_process_event(os::EventClearMode_AutoClear, true) { /* Learn whether we should enable cheats by default. */