mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-09 22:56:35 +00:00
creport: Read exception info properly (except for crashed thread info)
This commit is contained in:
parent
4e7fcc1a50
commit
7cd44e8980
3 changed files with 62 additions and 19 deletions
|
@ -43,23 +43,11 @@ void CrashReport::HandleAttachProcess(DebugEventInfo &d) {
|
||||||
this->process_info = d.info.attach_process;
|
this->process_info = d.info.attach_process;
|
||||||
if (kernelAbove500() && IsApplication()) {
|
if (kernelAbove500() && IsApplication()) {
|
||||||
/* Parse out user data. */
|
/* Parse out user data. */
|
||||||
MemoryInfo mi;
|
|
||||||
u32 pi;
|
|
||||||
u64 address = this->process_info.user_exception_context_address;
|
u64 address = this->process_info.user_exception_context_address;
|
||||||
u64 userdata_address = 0;
|
u64 userdata_address = 0;
|
||||||
u64 userdata_size = 0;
|
u64 userdata_size = 0;
|
||||||
|
|
||||||
if (R_FAILED(svcQueryDebugProcessMemory(&mi, &pi, this->debug_handle, address))) {
|
if (!IsAddressReadable(address, sizeof(userdata_address) + sizeof(userdata_size))) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Must be read or read-write */
|
|
||||||
if ((mi.perm | Perm_W) != Perm_Rw) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Must have space for both userdata address and userdata size. */
|
|
||||||
if (address < mi.addr || mi.addr + mi.size < address + 2 * sizeof(u64)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,20 +78,65 @@ void CrashReport::HandleAttachProcess(DebugEventInfo &d) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CrashReport::HandleException(DebugEventInfo &d) {
|
void CrashReport::HandleException(DebugEventInfo &d) {
|
||||||
|
this->exception_info = d.info.exception;
|
||||||
switch (d.info.exception.type) {
|
switch (d.info.exception.type) {
|
||||||
case DebugExceptionType::UndefinedInstruction:
|
case DebugExceptionType::UndefinedInstruction:
|
||||||
|
this->result = (Result)CrashReportResult::UndefinedInstruction;
|
||||||
|
break;
|
||||||
case DebugExceptionType::InstructionAbort:
|
case DebugExceptionType::InstructionAbort:
|
||||||
|
this->result = (Result)CrashReportResult::InstructionAbort;
|
||||||
|
this->exception_info.specific.raw = 0;
|
||||||
|
break;
|
||||||
case DebugExceptionType::DataAbort:
|
case DebugExceptionType::DataAbort:
|
||||||
|
this->result = (Result)CrashReportResult::DataAbort;
|
||||||
|
break;
|
||||||
case DebugExceptionType::AlignmentFault:
|
case DebugExceptionType::AlignmentFault:
|
||||||
|
this->result = (Result)CrashReportResult::AlignmentFault;
|
||||||
|
break;
|
||||||
case DebugExceptionType::UserBreak:
|
case DebugExceptionType::UserBreak:
|
||||||
|
this->result = (Result)CrashReportResult::UserBreak;
|
||||||
|
/* Try to parse out the user break result. */
|
||||||
|
if (kernelAbove500() && IsAddressReadable(this->exception_info.specific.user_break.address, sizeof(this->result))) {
|
||||||
|
svcReadDebugProcessMemory(&this->result, this->debug_handle, this->exception_info.specific.user_break.address, sizeof(this->result));
|
||||||
|
}
|
||||||
|
break;
|
||||||
case DebugExceptionType::BadSvc:
|
case DebugExceptionType::BadSvc:
|
||||||
|
this->result = (Result)CrashReportResult::BadSvc;
|
||||||
|
break;
|
||||||
case DebugExceptionType::UnknownNine:
|
case DebugExceptionType::UnknownNine:
|
||||||
/* TODO: Handle these exceptions...creport seems to discard all but the latest exception? */
|
this->result = (Result)CrashReportResult::UnknownNine;
|
||||||
|
this->exception_info.specific.raw = 0;
|
||||||
break;
|
break;
|
||||||
case DebugExceptionType::DebuggerAttached:
|
case DebugExceptionType::DebuggerAttached:
|
||||||
case DebugExceptionType::BreakPoint:
|
case DebugExceptionType::BreakPoint:
|
||||||
case DebugExceptionType::DebuggerBreak:
|
case DebugExceptionType::DebuggerBreak:
|
||||||
default:
|
default:
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
|
/* TODO: Parse crashing thread info. */
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CrashReport::IsAddressReadable(u64 address, u64 size, MemoryInfo *o_mi) {
|
||||||
|
MemoryInfo mi;
|
||||||
|
u32 pi;
|
||||||
|
|
||||||
|
if (o_mi == NULL) {
|
||||||
|
o_mi = &mi;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (R_FAILED(svcQueryDebugProcessMemory(o_mi, &pi, this->debug_handle, address))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Must be read or read-write */
|
||||||
|
if ((o_mi->perm | Perm_W) != Perm_Rw) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Must have space for both userdata address and userdata size. */
|
||||||
|
if (address < o_mi->addr || o_mi->addr + o_mi->size < address + size) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
|
@ -29,13 +29,18 @@ class CrashReport {
|
||||||
u64 userdata_5x_address;
|
u64 userdata_5x_address;
|
||||||
u64 userdata_5x_size;
|
u64 userdata_5x_size;
|
||||||
|
|
||||||
|
/* Exception Info. */
|
||||||
|
ExceptionInfo exception_info;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CrashReport() : debug_handle(INVALID_HANDLE), result((Result)CrashReportResult::IncompleteReport), process_info({0}) { }
|
CrashReport() : debug_handle(INVALID_HANDLE), result((Result)CrashReportResult::IncompleteReport), process_info({}), exception_info({}) { }
|
||||||
|
|
||||||
void BuildReport(u64 pid, bool has_extra_info);
|
void BuildReport(u64 pid, bool has_extra_info);
|
||||||
void SaveReport();
|
void SaveReport();
|
||||||
void ProcessExceptions();
|
void ProcessExceptions();
|
||||||
|
|
||||||
|
bool IsAddressReadable(u64 address, u64 size, MemoryInfo *mi = NULL);
|
||||||
|
|
||||||
Result GetResult() {
|
Result GetResult() {
|
||||||
return this->result;
|
return this->result;
|
||||||
}
|
}
|
||||||
|
@ -68,7 +73,7 @@ class CrashReport {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsUserBreak() {
|
bool IsUserBreak() {
|
||||||
return this->result == (Result)CrashReportResult::UserBreak;
|
return this->exception_info.type == DebugExceptionType::UserBreak;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
void HandleAttachProcess(DebugEventInfo &d);
|
void HandleAttachProcess(DebugEventInfo &d);
|
||||||
|
|
|
@ -43,6 +43,12 @@ struct AlignmentFaultInfo {
|
||||||
u64 address;
|
u64 address;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct UserBreakInfo {
|
||||||
|
u64 info_0;
|
||||||
|
u64 address;
|
||||||
|
u64 size;
|
||||||
|
};
|
||||||
|
|
||||||
struct BadSvcInfo {
|
struct BadSvcInfo {
|
||||||
u32 id;
|
u32 id;
|
||||||
};
|
};
|
||||||
|
@ -51,12 +57,11 @@ union SpecificExceptionInfo {
|
||||||
UndefinedInstructionInfo undefined_instruction;
|
UndefinedInstructionInfo undefined_instruction;
|
||||||
DataAbortInfo data_abort;
|
DataAbortInfo data_abort;
|
||||||
AlignmentFaultInfo alignment_fault;
|
AlignmentFaultInfo alignment_fault;
|
||||||
|
UserBreakInfo user_break;
|
||||||
BadSvcInfo bad_svc;
|
BadSvcInfo bad_svc;
|
||||||
u64 raw;
|
u64 raw;
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(SpecificExceptionInfo) == sizeof(u64), "Bad SpecificExceptionInfo definition!");
|
|
||||||
|
|
||||||
struct ExceptionInfo {
|
struct ExceptionInfo {
|
||||||
DebugExceptionType type;
|
DebugExceptionType type;
|
||||||
u64 address;
|
u64 address;
|
||||||
|
|
Loading…
Reference in a new issue