diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_debug_base.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_debug_base.hpp index 32d12a76d..6b0902483 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_debug_base.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_debug_base.hpp @@ -38,6 +38,8 @@ namespace ams::kern { void Initialize(); Result Attach(KProcess *process); + Result QueryMemoryInfo(ams::svc::MemoryInfo *out_memory_info, ams::svc::PageInfo *out_page_info, KProcessAddress address); + Result GetDebugEventInfo(ams::svc::lp64::DebugEventInfo *out); Result GetDebugEventInfo(ams::svc::ilp32::DebugEventInfo *out); diff --git a/libraries/libmesosphere/source/kern_k_debug_base.cpp b/libraries/libmesosphere/source/kern_k_debug_base.cpp index 3a475c1ad..5c244ec87 100644 --- a/libraries/libmesosphere/source/kern_k_debug_base.cpp +++ b/libraries/libmesosphere/source/kern_k_debug_base.cpp @@ -31,6 +31,23 @@ namespace ams::kern { this->continue_flags = 0; } + Result KDebugBase::QueryMemoryInfo(ams::svc::MemoryInfo *out_memory_info, ams::svc::PageInfo *out_page_info, KProcessAddress address) { + /* Lock ourselves. */ + KScopedLightLock lk(this->lock); + + /* Check that we have a valid process. */ + R_UNLESS(this->process != nullptr, svc::ResultProcessTerminated()); + R_UNLESS(!this->process->IsTerminated(), svc::ResultProcessTerminated()); + + /* Query the mapping's info. */ + KMemoryInfo info; + R_TRY(process->GetPageTable().QueryInfo(std::addressof(info), out_page_info, address)); + + /* Write output. */ + *out_memory_info = info.GetSvcMemoryInfo(); + return ResultSuccess(); + } + Result KDebugBase::Attach(KProcess *target) { /* Check that the process isn't null. */ MESOSPHERE_ASSERT(target != nullptr); diff --git a/libraries/libmesosphere/source/svc/kern_svc_debug.cpp b/libraries/libmesosphere/source/svc/kern_svc_debug.cpp index f9da78302..810ad2f55 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_debug.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_debug.cpp @@ -79,6 +79,47 @@ namespace ams::kern::svc { return ResultSuccess(); } + Result QueryDebugProcessMemory(ams::svc::MemoryInfo *out_memory_info, ams::svc::PageInfo *out_page_info, ams::svc::Handle debug_handle, uintptr_t address) { + /* Get the debug object. */ + KScopedAutoObject debug = GetCurrentProcess().GetHandleTable().GetObject(debug_handle); + R_UNLESS(debug.IsNotNull(), svc::ResultInvalidHandle()); + + /* Query the mapping's info. */ + R_TRY(debug->QueryMemoryInfo(out_memory_info, out_page_info, address)); + + return ResultSuccess(); + } + + template + Result QueryDebugProcessMemory(KUserPointer out_memory_info, ams::svc::PageInfo *out_page_info, ams::svc::Handle debug_handle, uint64_t address) { + /* Get an ams::svc::MemoryInfo for the region. */ + ams::svc::MemoryInfo info = {}; + R_TRY(QueryDebugProcessMemory(std::addressof(info), out_page_info, debug_handle, address)); + + /* Copy the info to userspace. */ + if constexpr (std::same_as) { + R_TRY(out_memory_info.CopyFrom(std::addressof(info))); + } else { + /* Convert the info. */ + T converted_info = {}; + static_assert(std::same_as); + static_assert(std::same_as); + + converted_info.addr = info.addr; + converted_info.size = info.size; + converted_info.state = info.state; + converted_info.attr = info.attr; + converted_info.perm = info.perm; + converted_info.ipc_refcount = info.ipc_refcount; + converted_info.device_refcount = info.device_refcount; + + /* Copy it. */ + R_TRY(out_memory_info.CopyFrom(std::addressof(converted_info))); + } + + return ResultSuccess(); + } + } /* ============================= 64 ABI ============================= */ @@ -115,8 +156,8 @@ namespace ams::kern::svc { MESOSPHERE_PANIC("Stubbed SvcSetDebugThreadContext64 was called."); } - Result QueryDebugProcessMemory64(KUserPointer out_memory_info, ams::svc::PageInfo *out_page_info, ams::svc::Handle process_handle, ams::svc::Address address) { - MESOSPHERE_PANIC("Stubbed SvcQueryDebugProcessMemory64 was called."); + Result QueryDebugProcessMemory64(KUserPointer out_memory_info, ams::svc::PageInfo *out_page_info, ams::svc::Handle debug_handle, ams::svc::Address address) { + return QueryDebugProcessMemory(out_memory_info, out_page_info, debug_handle, address); } Result ReadDebugProcessMemory64(ams::svc::Address buffer, ams::svc::Handle debug_handle, ams::svc::Address address, ams::svc::Size size) { @@ -169,8 +210,8 @@ namespace ams::kern::svc { MESOSPHERE_PANIC("Stubbed SvcSetDebugThreadContext64From32 was called."); } - Result QueryDebugProcessMemory64From32(KUserPointer out_memory_info, ams::svc::PageInfo *out_page_info, ams::svc::Handle process_handle, ams::svc::Address address) { - MESOSPHERE_PANIC("Stubbed SvcQueryDebugProcessMemory64From32 was called."); + Result QueryDebugProcessMemory64From32(KUserPointer out_memory_info, ams::svc::PageInfo *out_page_info, ams::svc::Handle debug_handle, ams::svc::Address address) { + return QueryDebugProcessMemory(out_memory_info, out_page_info, debug_handle, address); } Result ReadDebugProcessMemory64From32(ams::svc::Address buffer, ams::svc::Handle debug_handle, ams::svc::Address address, ams::svc::Size size) {