From 5268a9f9f3dd214a2c2318eb76fab88cccbff421 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Mon, 25 Jun 2018 03:40:32 -0600 Subject: [PATCH] creport: Implement reading a dying message --- .../creport/source/creport_crash_report.cpp | 45 ++++++++++++++++--- .../creport/source/creport_crash_report.hpp | 13 ++++-- 2 files changed, 49 insertions(+), 9 deletions(-) diff --git a/stratosphere/creport/source/creport_crash_report.cpp b/stratosphere/creport/source/creport_crash_report.cpp index c4ce86e86..3bddef162 100644 --- a/stratosphere/creport/source/creport_crash_report.cpp +++ b/stratosphere/creport/source/creport_crash_report.cpp @@ -10,8 +10,17 @@ void CrashReport::BuildReport(u64 pid, bool has_extra_info) { this->has_extra_info = has_extra_info; if (OpenProcess(pid)) { ProcessExceptions(); + if (kernelAbove500()) { + /* TODO: Process Code Regions. */ + /* TODO: Process Threads. */ + } + + if (IsApplication()) { + ProcessDyingMessage(); + } + + /* Real creport builds the report here. We do it later. */ - /* TODO: More stuff here (sub_7100002260)... */ Close(); } } @@ -67,13 +76,13 @@ void CrashReport::HandleAttachProcess(DebugEventInfo &d) { } /* Cap userdata size. */ - if (userdata_size > 0x1000) { - userdata_size = 0x1000; + if (userdata_size > sizeof(this->dying_message)) { + userdata_size = sizeof(this->dying_message); } /* Assign. */ - this->userdata_5x_address = userdata_address; - this->userdata_5x_size = userdata_size; + this->dying_message_address = userdata_address; + this->dying_message_size = userdata_size; } } @@ -117,6 +126,32 @@ void CrashReport::HandleException(DebugEventInfo &d) { this->crashed_thread_info.ReadFromProcess(this->debug_handle, d.thread_id, Is64Bit()); } +void CrashReport::ProcessDyingMessage() { + /* Dying message is only stored starting in 5.0.0. */ + if (!kernelAbove500()) { + return; + } + + /* Validate the message address/size. */ + if (this->dying_message_address == 0 || this->dying_message_address & 0xFFF) { + return; + } + if (this->dying_message_size > sizeof(this->dying_message)) { + return; + } + + /* Validate that the report isn't garbage. */ + if (!IsOpen() || !WasSuccessful()) { + return; + } + + if (!IsAddressReadable(this->dying_message_address, this->dying_message_size)) { + return; + } + + svcReadDebugProcessMemory(this->dying_message, this->debug_handle, this->dying_message_address, this->dying_message_size); +} + bool CrashReport::IsAddressReadable(u64 address, u64 size, MemoryInfo *o_mi) { MemoryInfo mi; u32 pi; diff --git a/stratosphere/creport/source/creport_crash_report.hpp b/stratosphere/creport/source/creport_crash_report.hpp index 68fbecafd..99fd1acdf 100644 --- a/stratosphere/creport/source/creport_crash_report.hpp +++ b/stratosphere/creport/source/creport_crash_report.hpp @@ -27,19 +27,22 @@ class CrashReport { /* Attach Process Info. */ AttachProcessInfo process_info; - u64 userdata_5x_address; - u64 userdata_5x_size; + u64 dying_message_address; + u64 dying_message_size; + u8 dying_message[0x1000]; + + static_assert(sizeof(dying_message) == 0x1000, "Incorrect definition for dying message!"); /* Exception Info. */ ExceptionInfo exception_info; ThreadInfo crashed_thread_info; public: - CrashReport() : debug_handle(INVALID_HANDLE), result((Result)CrashReportResult::IncompleteReport), process_info({}), exception_info({}) { } + CrashReport() : debug_handle(INVALID_HANDLE), result((Result)CrashReportResult::IncompleteReport), process_info({}), dying_message_address(0), + dying_message_size(0), dying_message{}, exception_info({}) { } void BuildReport(u64 pid, bool has_extra_info); void SaveReport(); - void ProcessExceptions(); bool IsAddressReadable(u64 address, u64 size, MemoryInfo *mi = NULL); @@ -78,6 +81,8 @@ class CrashReport { return this->exception_info.type == DebugExceptionType::UserBreak; } private: + void ProcessExceptions(); + void ProcessDyingMessage(); void HandleAttachProcess(DebugEventInfo &d); void HandleException(DebugEventInfo &d); }; \ No newline at end of file