From f189610af8de1c1956ed7be4094bb0e49ffcc34d Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Mon, 25 Jun 2018 04:38:54 -0600 Subject: [PATCH] creport: Skeleton reading of Code Regions. --- .../creport/source/creport_code_info.cpp | 62 +++++++++++++++++++ .../creport/source/creport_code_info.hpp | 24 +++++++ .../creport/source/creport_crash_report.cpp | 2 +- .../creport/source/creport_crash_report.hpp | 2 + .../creport/source/creport_thread_info.hpp | 3 + 5 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 stratosphere/creport/source/creport_code_info.cpp create mode 100644 stratosphere/creport/source/creport_code_info.hpp diff --git a/stratosphere/creport/source/creport_code_info.cpp b/stratosphere/creport/source/creport_code_info.cpp new file mode 100644 index 000000000..7922dd206 --- /dev/null +++ b/stratosphere/creport/source/creport_code_info.cpp @@ -0,0 +1,62 @@ +#include + +#include "creport_code_info.hpp" + +void CodeList::ReadCodeRegionsFromProcess(Handle debug_handle, u64 pc, u64 lr) { + u64 code_base; + + /* Guess that either PC or LR will point to a code region. This could be false. */ + if (!TryFindCodeRegion(debug_handle, pc, &code_base) && !TryFindCodeRegion(debug_handle, lr, &code_base)) { + return; + } + + u64 cur_ptr = code_base; + while (this->code_count < max_code_count) { + MemoryInfo mi; + u32 pi; + if (R_FAILED(svcQueryDebugProcessMemory(&mi, &pi, debug_handle, cur_ptr))) { + break; + } + + if (mi.perm == Perm_Rx) { + /* TODO: Parse CodeInfo. */ + this->code_count++; + } + + /* If we're out of readable memory, we're done reading code. */ + if (mi.type == MemType_Unmapped || mi.type == MemType_Reserved) { + break; + } + + /* Verify we're not getting stuck in an infinite loop. */ + if (mi.size == 0 || U64_MAX - mi.size <= cur_ptr) { + break; + } + + cur_ptr += mi.size; + } +} + +bool CodeList::TryFindCodeRegion(Handle debug_handle, u64 guess, u64 *address) { + MemoryInfo mi; + u32 pi; + if (R_FAILED(svcQueryDebugProcessMemory(&mi, &pi, debug_handle, guess)) || mi.perm != Perm_Rx) { + return false; + } + + /* Iterate backwards until we find the memory before the code region. */ + while (mi.addr > 0) { + if (R_FAILED(svcQueryDebugProcessMemory(&mi, &pi, debug_handle, guess))) { + return false; + } + + if (mi.type == MemType_Unmapped) { + /* Code region will be at the end of the unmapped region preceding it. */ + *address = mi.addr + mi.size; + return true; + } + + guess -= 4; + } + return false; +} \ No newline at end of file diff --git a/stratosphere/creport/source/creport_code_info.hpp b/stratosphere/creport/source/creport_code_info.hpp new file mode 100644 index 000000000..68edad9d7 --- /dev/null +++ b/stratosphere/creport/source/creport_code_info.hpp @@ -0,0 +1,24 @@ +#pragma once +#include + +#include "creport_debug_types.hpp" + +struct CodeInfo { + char name[0x20]; + u8 id[0x20]; + u64 start_address; + u64 end_address; +}; + +class CodeList { + private: + static const size_t max_code_count = 0x10; + u32 code_count; + CodeInfo code_infos[max_code_count]; + public: + CodeList() : code_count(0), code_infos({}) { } + + void ReadCodeRegionsFromProcess(Handle debug_handle, u64 pc, u64 lr); + private: + bool TryFindCodeRegion(Handle debug_handle, u64 guess, u64 *address); +}; diff --git a/stratosphere/creport/source/creport_crash_report.cpp b/stratosphere/creport/source/creport_crash_report.cpp index 830f9ef41..3a353e12a 100644 --- a/stratosphere/creport/source/creport_crash_report.cpp +++ b/stratosphere/creport/source/creport_crash_report.cpp @@ -11,7 +11,7 @@ void CrashReport::BuildReport(u64 pid, bool has_extra_info) { if (OpenProcess(pid)) { ProcessExceptions(); if (kernelAbove500()) { - /* TODO: Process Code Regions. */ + this->code_list.ReadCodeRegionsFromProcess(this->debug_handle, this->crashed_thread_info.GetPC(), this->crashed_thread_info.GetLR()); this->thread_list.ReadThreadsFromProcess(this->debug_handle, Is64Bit()); } diff --git a/stratosphere/creport/source/creport_crash_report.hpp b/stratosphere/creport/source/creport_crash_report.hpp index 812ec7568..7566fb19d 100644 --- a/stratosphere/creport/source/creport_crash_report.hpp +++ b/stratosphere/creport/source/creport_crash_report.hpp @@ -4,6 +4,7 @@ #include "creport_debug_types.hpp" #include "creport_thread_info.hpp" +#include "creport_code_info.hpp" enum class CrashReportResult : Result { UndefinedInstruction = 0x00A8, @@ -38,6 +39,7 @@ class CrashReport { ThreadInfo crashed_thread_info; /* Extra Info. */ + CodeList code_list; ThreadList thread_list; public: diff --git a/stratosphere/creport/source/creport_thread_info.hpp b/stratosphere/creport/source/creport_thread_info.hpp index 1c15c8642..6efc69c8a 100644 --- a/stratosphere/creport/source/creport_thread_info.hpp +++ b/stratosphere/creport/source/creport_thread_info.hpp @@ -41,6 +41,9 @@ class ThreadInfo { (*this) = {}; } + u64 GetPC() { return context.pc; } + u64 GetLR() { return context.lr; } + bool ReadFromProcess(Handle debug_handle, u64 thread_id, bool is_64_bit); private: void TryGetStackInfo(Handle debug_handle);