creport: Implement reading a dying message

This commit is contained in:
Michael Scire 2018-06-25 03:40:32 -06:00
parent e6b7793916
commit 5268a9f9f3
2 changed files with 49 additions and 9 deletions

View file

@ -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;

View file

@ -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);
};