diff --git a/stratosphere/creport/source/creport_code_info.cpp b/stratosphere/creport/source/creport_code_info.cpp index 3bb6e1bed..95e6af722 100644 --- a/stratosphere/creport/source/creport_code_info.cpp +++ b/stratosphere/creport/source/creport_code_info.cpp @@ -32,15 +32,37 @@ void CodeList::SaveToFile(FILE *f_report) { } } -void CodeList::ReadCodeRegionsFromProcess(Handle debug_handle, u64 pc, u64 lr) { +void CodeList::ReadCodeRegionsFromThreadInfo(Handle debug_handle, const ThreadInfo *thread) { 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; + /* Try to add the thread's PC. */ + if (TryFindCodeRegion(debug_handle, thread->GetPC(), &code_base)) { + AddCodeRegion(debug_handle, code_base); } - u64 cur_ptr = code_base; + /* Try to add the thread's LR. */ + if (TryFindCodeRegion(debug_handle, thread->GetLR(), &code_base)) { + AddCodeRegion(debug_handle, code_base); + } + + /* Try to add all the addresses in the thread's stacktrace. */ + for (u32 i = 0; i < thread->GetStackTraceSize(); i++) { + if (TryFindCodeRegion(debug_handle, thread->GetStackTrace(i), &code_base)) { + AddCodeRegion(debug_handle, code_base); + } + } +} + +void CodeList::AddCodeRegion(u64 debug_handle, u64 code_address) { + /* Check whether we already have this code region. */ + for (size_t i = 0; i < this->code_count; i++) { + if (this->code_infos[i].start_address <= code_address && code_address < this->code_infos[i].end_address) { + return; + } + } + + /* Add all contiguous code regions. */ + u64 cur_ptr = code_address; while (this->code_count < max_code_count) { MemoryInfo mi; u32 pi; diff --git a/stratosphere/creport/source/creport_code_info.hpp b/stratosphere/creport/source/creport_code_info.hpp index ff1c1fb1c..23f8922e4 100644 --- a/stratosphere/creport/source/creport_code_info.hpp +++ b/stratosphere/creport/source/creport_code_info.hpp @@ -19,6 +19,7 @@ #include #include "creport_debug_types.hpp" +#include "creport_thread_info.hpp" struct CodeInfo { char name[0x20]; @@ -29,18 +30,19 @@ struct CodeInfo { class CodeList { private: - static const size_t max_code_count = 0x10; + static const size_t max_code_count = 0x60; u32 code_count = 0; CodeInfo code_infos[max_code_count]; /* For pretty-printing. */ char address_str_buf[0x280]; public: - void ReadCodeRegionsFromProcess(Handle debug_handle, u64 pc, u64 lr); + void ReadCodeRegionsFromThreadInfo(Handle debug_handle, const ThreadInfo *thread); const char *GetFormattedAddressString(u64 address); void SaveToFile(FILE *f_report); private: bool TryFindCodeRegion(Handle debug_handle, u64 guess, u64 *address); + void AddCodeRegion(u64 debug_handle, u64 code_address); void GetCodeInfoName(u64 debug_handle, u64 rx_address, u64 ro_address, char *name); void GetCodeInfoBuildId(u64 debug_handle, u64 ro_address, u8 *build_id); }; diff --git a/stratosphere/creport/source/creport_crash_report.cpp b/stratosphere/creport/source/creport_crash_report.cpp index cd9d1f9bb..6bcab5443 100644 --- a/stratosphere/creport/source/creport_crash_report.cpp +++ b/stratosphere/creport/source/creport_crash_report.cpp @@ -27,7 +27,7 @@ void CrashReport::BuildReport(u64 pid, bool has_extra_info) { this->has_extra_info = has_extra_info; if (OpenProcess(pid)) { ProcessExceptions(); - this->code_list.ReadCodeRegionsFromProcess(this->debug_handle, this->crashed_thread_info.GetPC(), this->crashed_thread_info.GetLR()); + this->code_list.ReadCodeRegionsFromThreadInfo(this->debug_handle, &this->crashed_thread_info); this->thread_list.ReadThreadsFromProcess(this->debug_handle, Is64Bit()); this->crashed_thread_info.SetCodeList(&this->code_list); this->thread_list.SetCodeList(&this->code_list); @@ -36,6 +36,11 @@ void CrashReport::BuildReport(u64 pid, bool has_extra_info) { ProcessDyingMessage(); } + /* Real creport only does this if application, but there's no reason not to do it all the time. */ + for (u32 i = 0; i < this->thread_list.GetThreadCount(); i++) { + this->code_list.ReadCodeRegionsFromThreadInfo(this->debug_handle, this->thread_list.GetThreadInfo(i)); + } + /* Real creport builds the report here. We do it later. */ Close(); @@ -258,7 +263,7 @@ void CrashReport::SaveReport() { void CrashReport::SaveToFile(FILE *f_report) { char buf[0x10] = {0}; - fprintf(f_report, "Atmosphère Crash Report (v1.1):\n"); + fprintf(f_report, "Atmosphère Crash Report (v1.2):\n"); fprintf(f_report, "Result: 0x%X (2%03d-%04d)\n\n", this->result, R_MODULE(this->result), R_DESCRIPTION(this->result)); /* Process Info. */ diff --git a/stratosphere/creport/source/creport_thread_info.hpp b/stratosphere/creport/source/creport_thread_info.hpp index 0b3d3f07f..e3f2ed606 100644 --- a/stratosphere/creport/source/creport_thread_info.hpp +++ b/stratosphere/creport/source/creport_thread_info.hpp @@ -19,7 +19,8 @@ #include #include "creport_debug_types.hpp" -#include "creport_code_info.hpp" + +class CodeList; class ThreadInfo { private: @@ -31,9 +32,11 @@ class ThreadInfo { u32 stack_trace_size = 0; CodeList *code_list; public: - u64 GetPC() { return context.pc.x; } - u64 GetLR() { return context.lr; } - u64 GetId() { return thread_id; } + u64 GetPC() const { return context.pc.x; } + u64 GetLR() const { return context.lr; } + u64 GetId() const { return thread_id; } + u32 GetStackTraceSize() const { return stack_trace_size; } + u64 GetStackTrace(u32 i) const { return stack_trace[i]; } bool ReadFromProcess(Handle debug_handle, u64 thread_id, bool is_64_bit); void SaveToFile(FILE *f_report); @@ -48,7 +51,10 @@ class ThreadList { static const size_t max_thread_count = 0x60; u32 thread_count = 0; ThreadInfo thread_infos[max_thread_count]; - public: + public: + u32 GetThreadCount() const { return thread_count; } + const ThreadInfo *GetThreadInfo(u32 i) const { return &thread_infos[i]; } + void SaveToFile(FILE *f_report); void DumpBinary(FILE *f_bin, u64 crashed_id); void ReadThreadsFromProcess(Handle debug_handle, bool is_64_bit);