mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-12-23 10:52:13 +00:00
creport: Implement process open, stub exception parsing.
This commit is contained in:
parent
6ffc9bd8e0
commit
851d21a276
3 changed files with 207 additions and 3 deletions
|
@ -1,10 +1,105 @@
|
||||||
#include <switch.h>
|
#include <switch.h>
|
||||||
#include "creport_crash_report.hpp"
|
#include "creport_crash_report.hpp"
|
||||||
|
#include "creport_debug_types.hpp"
|
||||||
|
|
||||||
void CrashReport::BuildReport(u64 pid, bool has_extra_info) {
|
void CrashReport::BuildReport(u64 pid, bool has_extra_info) {
|
||||||
this->has_extra_info = has_extra_info;
|
this->has_extra_info = has_extra_info;
|
||||||
if (OpenProcess(pid)) {
|
if (OpenProcess(pid)) {
|
||||||
/* TODO: Actually generate report... */
|
ProcessExceptions();
|
||||||
|
|
||||||
|
/* TODO: More stuff here (sub_7100002260)... */
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CrashReport::ProcessExceptions() {
|
||||||
|
if (!IsOpen()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugEventInfo d;
|
||||||
|
while (R_SUCCEEDED(svcGetDebugEvent((u8 *)&d, this->debug_handle))) {
|
||||||
|
switch (d.type) {
|
||||||
|
case DebugEventType::AttachProcess:
|
||||||
|
HandleAttachProcess(d);
|
||||||
|
break;
|
||||||
|
case DebugEventType::Exception:
|
||||||
|
HandleException(d);
|
||||||
|
break;
|
||||||
|
case DebugEventType::AttachThread:
|
||||||
|
case DebugEventType::ExitProcess:
|
||||||
|
case DebugEventType::ExitThread:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CrashReport::HandleAttachProcess(DebugEventInfo &d) {
|
||||||
|
this->process_info = d.info.attach_process;
|
||||||
|
if (kernelAbove500() && IsApplication()) {
|
||||||
|
/* Parse out user data. */
|
||||||
|
MemoryInfo mi;
|
||||||
|
u32 pi;
|
||||||
|
u64 address = this->process_info.user_exception_context_address;
|
||||||
|
u64 userdata_address = 0;
|
||||||
|
u64 userdata_size = 0;
|
||||||
|
|
||||||
|
if (R_FAILED(svcQueryDebugProcessMemory(&mi, &pi, this->debug_handle, address))) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read userdata address. */
|
||||||
|
if (R_FAILED(svcReadDebugProcessMemory(&userdata_address, this->debug_handle, address, sizeof(userdata_address)))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Validate userdata address. */
|
||||||
|
if (userdata_address == 0 || userdata_address & 0xFFF) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read userdata size. */
|
||||||
|
if (R_FAILED(svcReadDebugProcessMemory(&userdata_size, this->debug_handle, address + sizeof(userdata_address), sizeof(userdata_size)))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cap userdata size. */
|
||||||
|
if (userdata_size > 0x1000) {
|
||||||
|
userdata_size = 0x1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Assign. */
|
||||||
|
this->userdata_5x_address = userdata_address;
|
||||||
|
this->userdata_5x_size = userdata_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CrashReport::HandleException(DebugEventInfo &d) {
|
||||||
|
switch (d.info.exception.type) {
|
||||||
|
case DebugExceptionType::UndefinedInstruction:
|
||||||
|
case DebugExceptionType::InstructionAbort:
|
||||||
|
case DebugExceptionType::DataAbort:
|
||||||
|
case DebugExceptionType::AlignmentFault:
|
||||||
|
case DebugExceptionType::UserBreak:
|
||||||
|
case DebugExceptionType::BadSvc:
|
||||||
|
case DebugExceptionType::UnknownNine:
|
||||||
|
/* TODO: Handle these exceptions...creport seems to discard all but the latest exception? */
|
||||||
|
break;
|
||||||
|
case DebugExceptionType::DebuggerAttached:
|
||||||
|
case DebugExceptionType::BreakPoint:
|
||||||
|
case DebugExceptionType::DebuggerBreak:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,16 +2,24 @@
|
||||||
|
|
||||||
#include <switch.h>
|
#include <switch.h>
|
||||||
|
|
||||||
|
#include "creport_debug_types.hpp"
|
||||||
|
|
||||||
class CrashReport {
|
class CrashReport {
|
||||||
private:
|
private:
|
||||||
Handle debug_handle;
|
Handle debug_handle;
|
||||||
bool has_extra_info;
|
bool has_extra_info;
|
||||||
Result result;
|
Result result;
|
||||||
|
|
||||||
|
/* Attach Process Info. */
|
||||||
|
AttachProcessInfo process_info;
|
||||||
|
u64 userdata_5x_address;
|
||||||
|
u64 userdata_5x_size;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CrashReport() : debug_handle(INVALID_HANDLE), result(0x4A2) { }
|
CrashReport() : debug_handle(INVALID_HANDLE), result(0xC6A8), process_info({0}) { }
|
||||||
|
|
||||||
void BuildReport(u64 pid, bool has_extra_info);
|
void BuildReport(u64 pid, bool has_extra_info);
|
||||||
|
void ProcessExceptions();
|
||||||
|
|
||||||
Result GetResult() {
|
Result GetResult() {
|
||||||
return this->result;
|
return this->result;
|
||||||
|
@ -21,10 +29,25 @@ class CrashReport {
|
||||||
return R_SUCCEEDED(svcDebugActiveProcess(&debug_handle, pid));
|
return R_SUCCEEDED(svcDebugActiveProcess(&debug_handle, pid));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsOpen() {
|
||||||
|
return this->debug_handle != INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
void Close() {
|
void Close() {
|
||||||
if (debug_handle != INVALID_HANDLE) {
|
if (IsOpen()) {
|
||||||
svcCloseHandle(debug_handle);
|
svcCloseHandle(debug_handle);
|
||||||
debug_handle = INVALID_HANDLE;
|
debug_handle = INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsApplication() {
|
||||||
|
return (process_info.flags & 0x40) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Is64Bit() {
|
||||||
|
return (process_info.flags & 0x01) != 0;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
void HandleAttachProcess(DebugEventInfo &d);
|
||||||
|
void HandleException(DebugEventInfo &d);
|
||||||
};
|
};
|
86
stratosphere/creport/source/creport_debug_types.hpp
Normal file
86
stratosphere/creport/source/creport_debug_types.hpp
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
#pragma once
|
||||||
|
#include <switch.h>
|
||||||
|
|
||||||
|
struct AttachProcessInfo {
|
||||||
|
u64 title_id;
|
||||||
|
u64 process_id;
|
||||||
|
char name[0xC];
|
||||||
|
u32 flags;
|
||||||
|
u64 user_exception_context_address; /* 5.0.0+ */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AttachThreadInfo {
|
||||||
|
u64 thread_id;
|
||||||
|
u64 tls_address;
|
||||||
|
u64 entrypoint;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* TODO: ExitProcessInfo */
|
||||||
|
/* TODO: ExitThreadInfo */
|
||||||
|
|
||||||
|
enum class DebugExceptionType : u32 {
|
||||||
|
UndefinedInstruction = 0,
|
||||||
|
InstructionAbort = 1,
|
||||||
|
DataAbort = 2,
|
||||||
|
AlignmentFault = 3,
|
||||||
|
DebuggerAttached = 4,
|
||||||
|
BreakPoint = 5,
|
||||||
|
UserBreak = 6,
|
||||||
|
DebuggerBreak = 7,
|
||||||
|
BadSvc = 8,
|
||||||
|
UnknownNine = 9,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct UndefinedInstructionInfo {
|
||||||
|
u32 insn;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DataAbortInfo {
|
||||||
|
u64 address;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AlignmentFaultInfo {
|
||||||
|
u64 address;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BadSvcInfo {
|
||||||
|
u32 id;
|
||||||
|
};
|
||||||
|
|
||||||
|
union SpecificExceptionInfo {
|
||||||
|
UndefinedInstructionInfo undefined_instruction;
|
||||||
|
DataAbortInfo data_abort;
|
||||||
|
AlignmentFaultInfo alignment_fault;
|
||||||
|
BadSvcInfo bad_svc;
|
||||||
|
u64 raw;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(SpecificExceptionInfo) == sizeof(u64), "Bad SpecificExceptionInfo definition!");
|
||||||
|
|
||||||
|
struct ExceptionInfo {
|
||||||
|
DebugExceptionType type;
|
||||||
|
u64 address;
|
||||||
|
SpecificExceptionInfo specific;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum class DebugEventType : u32 {
|
||||||
|
AttachProcess = 0,
|
||||||
|
AttachThread = 1,
|
||||||
|
ExitProcess = 2,
|
||||||
|
ExitThread = 3,
|
||||||
|
Exception = 4
|
||||||
|
};
|
||||||
|
|
||||||
|
union DebugInfo {
|
||||||
|
AttachProcessInfo attach_process;
|
||||||
|
AttachThreadInfo attach_thread;
|
||||||
|
ExceptionInfo exception;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DebugEventInfo {
|
||||||
|
DebugEventType type;
|
||||||
|
u32 flags;
|
||||||
|
u64 thread_id;
|
||||||
|
DebugInfo info;
|
||||||
|
};
|
Loading…
Reference in a new issue