strat: use m_ for member variables

This commit is contained in:
Michael Scire 2021-10-10 00:14:06 -07:00
parent ce28591ab2
commit a595c232b9
425 changed files with 8531 additions and 8484 deletions

View file

@ -86,31 +86,31 @@ namespace ams::creport {
void CrashReport::Initialize() {
/* Initialize the heap. */
this->heap_handle = lmem::CreateExpHeap(this->heap_storage, sizeof(this->heap_storage), lmem::CreateOption_None);
m_heap_handle = lmem::CreateExpHeap(m_heap_storage, sizeof(m_heap_storage), lmem::CreateOption_None);
/* Allocate members. */
this->module_list = std::construct_at(static_cast<ModuleList *>(lmem::AllocateFromExpHeap(this->heap_handle, sizeof(ModuleList))));
this->thread_list = std::construct_at(static_cast<ThreadList *>(lmem::AllocateFromExpHeap(this->heap_handle, sizeof(ThreadList))));
this->dying_message = static_cast<u8 *>(lmem::AllocateFromExpHeap(this->heap_handle, DyingMessageSizeMax));
if (this->dying_message != nullptr) {
std::memset(this->dying_message, 0, DyingMessageSizeMax);
m_module_list = std::construct_at(static_cast<ModuleList *>(lmem::AllocateFromExpHeap(m_heap_handle, sizeof(ModuleList))));
m_thread_list = std::construct_at(static_cast<ThreadList *>(lmem::AllocateFromExpHeap(m_heap_handle, sizeof(ThreadList))));
m_dying_message = static_cast<u8 *>(lmem::AllocateFromExpHeap(m_heap_handle, DyingMessageSizeMax));
if (m_dying_message != nullptr) {
std::memset(m_dying_message, 0, DyingMessageSizeMax);
}
}
void CrashReport::BuildReport(os::ProcessId process_id, bool has_extra_info) {
this->has_extra_info = has_extra_info;
m_has_extra_info = has_extra_info;
if (this->OpenProcess(process_id)) {
ON_SCOPE_EXIT { this->Close(); };
/* Parse info from the crashed process. */
this->ProcessExceptions();
this->module_list->FindModulesFromThreadInfo(this->debug_handle, this->crashed_thread);
this->thread_list->ReadFromProcess(this->debug_handle, this->thread_tls_map, this->Is64Bit());
m_module_list->FindModulesFromThreadInfo(m_debug_handle, m_crashed_thread);
m_thread_list->ReadFromProcess(m_debug_handle, m_thread_tls_map, this->Is64Bit());
/* Associate module list to threads. */
this->crashed_thread.SetModuleList(this->module_list);
this->thread_list->SetModuleList(this->module_list);
m_crashed_thread.SetModuleList(m_module_list);
m_thread_list->SetModuleList(m_module_list);
/* Process dying message for applications. */
if (this->IsApplication()) {
@ -119,13 +119,13 @@ namespace ams::creport {
/* Nintendo's creport finds extra modules by looking at all threads if application, */
/* but there's no reason for us not to always go looking. */
for (size_t i = 0; i < this->thread_list->GetThreadCount(); i++) {
this->module_list->FindModulesFromThreadInfo(this->debug_handle, this->thread_list->GetThreadInfo(i));
for (size_t i = 0; i < m_thread_list->GetThreadCount(); i++) {
m_module_list->FindModulesFromThreadInfo(m_debug_handle, m_thread_list->GetThreadInfo(i));
}
/* Cache the module base address to send to fatal. */
if (this->module_list->GetModuleCount()) {
this->module_base_address = this->module_list->GetModuleStartAddress(0);
if (m_module_list->GetModuleCount()) {
m_module_base_address = m_module_list->GetModuleStartAddress(0);
}
/* Nintendo's creport saves the report to erpt here, but we'll save to SD card later. */
@ -139,33 +139,33 @@ namespace ams::creport {
/* TODO: Support generating 32-bit fatal contexts? */
out->architecture = fatal::CpuContext::Architecture_Aarch64;
out->type = static_cast<u32>(this->exception_info.type);
out->type = static_cast<u32>(m_exception_info.type);
for (size_t i = 0; i < fatal::aarch64::RegisterName_FP; i++) {
out->aarch64_ctx.SetRegisterValue(static_cast<fatal::aarch64::RegisterName>(i), this->crashed_thread.GetGeneralPurposeRegister(i));
out->aarch64_ctx.SetRegisterValue(static_cast<fatal::aarch64::RegisterName>(i), m_crashed_thread.GetGeneralPurposeRegister(i));
}
out->aarch64_ctx.SetRegisterValue(fatal::aarch64::RegisterName_FP, this->crashed_thread.GetFP());
out->aarch64_ctx.SetRegisterValue(fatal::aarch64::RegisterName_LR, this->crashed_thread.GetLR());
out->aarch64_ctx.SetRegisterValue(fatal::aarch64::RegisterName_SP, this->crashed_thread.GetSP());
out->aarch64_ctx.SetRegisterValue(fatal::aarch64::RegisterName_PC, this->crashed_thread.GetPC());
out->aarch64_ctx.SetRegisterValue(fatal::aarch64::RegisterName_FP, m_crashed_thread.GetFP());
out->aarch64_ctx.SetRegisterValue(fatal::aarch64::RegisterName_LR, m_crashed_thread.GetLR());
out->aarch64_ctx.SetRegisterValue(fatal::aarch64::RegisterName_SP, m_crashed_thread.GetSP());
out->aarch64_ctx.SetRegisterValue(fatal::aarch64::RegisterName_PC, m_crashed_thread.GetPC());
out->aarch64_ctx.stack_trace_size = this->crashed_thread.GetStackTraceSize();
out->aarch64_ctx.stack_trace_size = m_crashed_thread.GetStackTraceSize();
for (size_t i = 0; i < out->aarch64_ctx.stack_trace_size; i++) {
out->aarch64_ctx.stack_trace[i] = this->crashed_thread.GetStackTrace(i);
out->aarch64_ctx.stack_trace[i] = m_crashed_thread.GetStackTrace(i);
}
if (this->module_base_address != 0) {
out->aarch64_ctx.SetBaseAddress(this->module_base_address);
if (m_module_base_address != 0) {
out->aarch64_ctx.SetBaseAddress(m_module_base_address);
}
/* For ams fatal, which doesn't use afsr0, pass program_id instead. */
out->aarch64_ctx.SetProgramIdForAtmosphere(ncm::ProgramId{this->process_info.program_id});
out->aarch64_ctx.SetProgramIdForAtmosphere(ncm::ProgramId{m_process_info.program_id});
}
void CrashReport::ProcessExceptions() {
/* Loop all debug events. */
svc::DebugEventInfo d;
while (R_SUCCEEDED(svc::GetDebugEvent(std::addressof(d), this->debug_handle))) {
while (R_SUCCEEDED(svc::GetDebugEvent(std::addressof(d), m_debug_handle))) {
switch (d.type) {
case svc::DebugEvent_CreateProcess:
this->HandleDebugEventInfoCreateProcess(d);
@ -183,11 +183,11 @@ namespace ams::creport {
}
/* Parse crashed thread info. */
this->crashed_thread.ReadFromProcess(this->debug_handle, this->thread_tls_map, this->crashed_thread_id, this->Is64Bit());
m_crashed_thread.ReadFromProcess(m_debug_handle, m_thread_tls_map, m_crashed_thread_id, this->Is64Bit());
}
void CrashReport::HandleDebugEventInfoCreateProcess(const svc::DebugEventInfo &d) {
this->process_info = d.info.create_process;
m_process_info = d.info.create_process;
/* On 5.0.0+, we want to parse out a dying message from application crashes. */
if (hos::GetVersion() < hos::Version_5_0_0 || !IsApplication()) {
@ -195,12 +195,12 @@ namespace ams::creport {
}
/* Parse out user data. */
const u64 address = this->process_info.user_exception_context_address + DyingMessageAddressOffset;
const u64 address = m_process_info.user_exception_context_address + DyingMessageAddressOffset;
u64 userdata_address = 0;
u64 userdata_size = 0;
/* Read userdata address. */
if (R_FAILED(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(std::addressof(userdata_address)), this->debug_handle, address, sizeof(userdata_address)))) {
if (R_FAILED(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(std::addressof(userdata_address)), m_debug_handle, address, sizeof(userdata_address)))) {
return;
}
@ -210,48 +210,48 @@ namespace ams::creport {
}
/* Read userdata size. */
if (R_FAILED(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(std::addressof(userdata_size)), this->debug_handle, address + sizeof(userdata_address), sizeof(userdata_size)))) {
if (R_FAILED(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(std::addressof(userdata_size)), m_debug_handle, address + sizeof(userdata_address), sizeof(userdata_size)))) {
return;
}
/* Cap userdata size. */
userdata_size = std::min(size_t(userdata_size), DyingMessageSizeMax);
this->dying_message_address = userdata_address;
this->dying_message_size = userdata_size;
m_dying_message_address = userdata_address;
m_dying_message_size = userdata_size;
}
void CrashReport::HandleDebugEventInfoCreateThread(const svc::DebugEventInfo &d) {
/* Save info on the thread's TLS address for later. */
this->thread_tls_map.SetThreadTls(d.info.create_thread.thread_id, d.info.create_thread.tls_address);
m_thread_tls_map.SetThreadTls(d.info.create_thread.thread_id, d.info.create_thread.tls_address);
}
void CrashReport::HandleDebugEventInfoException(const svc::DebugEventInfo &d) {
switch (d.info.exception.type) {
case svc::DebugException_UndefinedInstruction:
this->result = creport::ResultUndefinedInstruction();
m_result = creport::ResultUndefinedInstruction();
break;
case svc::DebugException_InstructionAbort:
this->result = creport::ResultInstructionAbort();
m_result = creport::ResultInstructionAbort();
break;
case svc::DebugException_DataAbort:
this->result = creport::ResultDataAbort();
m_result = creport::ResultDataAbort();
break;
case svc::DebugException_AlignmentFault:
this->result = creport::ResultAlignmentFault();
m_result = creport::ResultAlignmentFault();
break;
case svc::DebugException_UserBreak:
this->result = creport::ResultUserBreak();
m_result = creport::ResultUserBreak();
/* Try to parse out the user break result. */
if (hos::GetVersion() >= hos::Version_5_0_0) {
svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(std::addressof(this->result)), this->debug_handle, d.info.exception.specific.user_break.address, sizeof(this->result));
svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(std::addressof(m_result)), m_debug_handle, d.info.exception.specific.user_break.address, sizeof(m_result));
}
break;
case svc::DebugException_UndefinedSystemCall:
this->result = creport::ResultUndefinedSystemCall();
m_result = creport::ResultUndefinedSystemCall();
break;
case svc::DebugException_MemorySystemError:
this->result = creport::ResultMemorySystemError();
m_result = creport::ResultMemorySystemError();
break;
case svc::DebugException_DebuggerAttached:
case svc::DebugException_BreakPoint:
@ -260,8 +260,8 @@ namespace ams::creport {
}
/* Save exception info. */
this->exception_info = d.info.exception;
this->crashed_thread_id = d.thread_id;
m_exception_info = d.info.exception;
m_crashed_thread_id = d.thread_id;
}
void CrashReport::ProcessDyingMessage() {
@ -271,10 +271,10 @@ namespace ams::creport {
}
/* Validate address/size. */
if (this->dying_message_address == 0 || this->dying_message_address & 0xFFF) {
if (m_dying_message_address == 0 || m_dying_message_address & 0xFFF) {
return;
}
if (this->dying_message_size > DyingMessageSizeMax) {
if (m_dying_message_size > DyingMessageSizeMax) {
return;
}
@ -284,12 +284,12 @@ namespace ams::creport {
}
/* Verify that we have a dying message buffer. */
if (this->dying_message == nullptr) {
if (m_dying_message == nullptr) {
return;
}
/* Read the dying message. */
svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(this->dying_message), this->debug_handle, this->dying_message_address, this->dying_message_size);
svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(m_dying_message), m_debug_handle, m_dying_message_address, m_dying_message_size);
}
void CrashReport::SaveReport(bool enable_screenshot) {
@ -307,7 +307,7 @@ namespace ams::creport {
char file_path[fs::EntryNameLengthMax + 1];
/* Save crash report. */
util::SNPrintf(file_path, sizeof(file_path), "sdmc:/atmosphere/crash_reports/%011lu_%016lx.log", timestamp, this->process_info.program_id);
util::SNPrintf(file_path, sizeof(file_path), "sdmc:/atmosphere/crash_reports/%011lu_%016lx.log", timestamp, m_process_info.program_id);
{
ScopedFile file(file_path);
if (file.IsOpen()) {
@ -316,25 +316,25 @@ namespace ams::creport {
}
/* Dump threads. */
util::SNPrintf(file_path, sizeof(file_path), "sdmc:/atmosphere/crash_reports/dumps/%011lu_%016lx_thread_info.bin", timestamp, this->process_info.program_id);
util::SNPrintf(file_path, sizeof(file_path), "sdmc:/atmosphere/crash_reports/dumps/%011lu_%016lx_thread_info.bin", timestamp, m_process_info.program_id);
{
ScopedFile file(file_path);
if (file.IsOpen()) {
this->thread_list->DumpBinary(file, this->crashed_thread.GetThreadId());
m_thread_list->DumpBinary(file, m_crashed_thread.GetThreadId());
}
}
/* Finalize our heap. */
std::destroy_at(this->module_list);
std::destroy_at(this->thread_list);
lmem::FreeToExpHeap(this->heap_handle, this->module_list);
lmem::FreeToExpHeap(this->heap_handle, this->thread_list);
if (this->dying_message != nullptr) {
lmem::FreeToExpHeap(this->heap_handle, this->dying_message);
std::destroy_at(m_module_list);
std::destroy_at(m_thread_list);
lmem::FreeToExpHeap(m_heap_handle, m_module_list);
lmem::FreeToExpHeap(m_heap_handle, m_thread_list);
if (m_dying_message != nullptr) {
lmem::FreeToExpHeap(m_heap_handle, m_dying_message);
}
this->module_list = nullptr;
this->thread_list = nullptr;
this->dying_message = nullptr;
m_module_list = nullptr;
m_thread_list = nullptr;
m_dying_message = nullptr;
/* Try to take a screenshot. */
/* NOTE: Nintendo validates that enable_screenshot is true here, and validates that the application id is not in a blacklist. */
@ -345,11 +345,11 @@ namespace ams::creport {
ON_SCOPE_EXIT { capsrv::FinalizeScreenShotControl(); };
u64 jpeg_size;
if (R_SUCCEEDED(capsrv::CaptureJpegScreenshot(std::addressof(jpeg_size), this->heap_storage, sizeof(this->heap_storage), vi::LayerStack_ApplicationForDebug, TimeSpan::FromSeconds(10)))) {
util::SNPrintf(file_path, sizeof(file_path), "sdmc:/atmosphere/crash_reports/%011lu_%016lx.jpg", timestamp, this->process_info.program_id);
if (R_SUCCEEDED(capsrv::CaptureJpegScreenshot(std::addressof(jpeg_size), m_heap_storage, sizeof(m_heap_storage), vi::LayerStack_ApplicationForDebug, TimeSpan::FromSeconds(10)))) {
util::SNPrintf(file_path, sizeof(file_path), "sdmc:/atmosphere/crash_reports/%011lu_%016lx.jpg", timestamp, m_process_info.program_id);
ScopedFile file(file_path);
if (file.IsOpen()) {
file.Write(this->heap_storage, jpeg_size);
file.Write(m_heap_storage, jpeg_size);
}
}
}
@ -360,42 +360,42 @@ namespace ams::creport {
void CrashReport::SaveToFile(ScopedFile &file) {
file.WriteFormat("Atmosphère Crash Report (v1.6):\n");
file.WriteFormat("Result: 0x%X (2%03d-%04d)\n\n", this->result.GetValue(), this->result.GetModule(), this->result.GetDescription());
file.WriteFormat("Result: 0x%X (2%03d-%04d)\n\n", m_result.GetValue(), m_result.GetModule(), m_result.GetDescription());
/* Process Info. */
char name_buf[0x10] = {};
static_assert(sizeof(name_buf) >= sizeof(this->process_info.name), "buffer overflow!");
std::memcpy(name_buf, this->process_info.name, sizeof(this->process_info.name));
static_assert(sizeof(name_buf) >= sizeof(m_process_info.name), "buffer overflow!");
std::memcpy(name_buf, m_process_info.name, sizeof(m_process_info.name));
file.WriteFormat("Process Info:\n");
file.WriteFormat(" Process Name: %s\n", name_buf);
file.WriteFormat(" Program ID: %016lx\n", this->process_info.program_id);
file.WriteFormat(" Process ID: %016lx\n", this->process_info.process_id);
file.WriteFormat(" Process Flags: %08x\n", this->process_info.flags);
file.WriteFormat(" Program ID: %016lx\n", m_process_info.program_id);
file.WriteFormat(" Process ID: %016lx\n", m_process_info.process_id);
file.WriteFormat(" Process Flags: %08x\n", m_process_info.flags);
if (hos::GetVersion() >= hos::Version_5_0_0) {
file.WriteFormat(" User Exception Address: %s\n", this->module_list->GetFormattedAddressString(this->process_info.user_exception_context_address));
file.WriteFormat(" User Exception Address: %s\n", m_module_list->GetFormattedAddressString(m_process_info.user_exception_context_address));
}
/* Exception Info. */
file.WriteFormat("Exception Info:\n");
file.WriteFormat(" Type: %s\n", GetDebugExceptionString(this->exception_info.type));
file.WriteFormat(" Address: %s\n", this->module_list->GetFormattedAddressString(this->exception_info.address));
switch (this->exception_info.type) {
file.WriteFormat(" Type: %s\n", GetDebugExceptionString(m_exception_info.type));
file.WriteFormat(" Address: %s\n", m_module_list->GetFormattedAddressString(m_exception_info.address));
switch (m_exception_info.type) {
case svc::DebugException_UndefinedInstruction:
file.WriteFormat(" Opcode: %08x\n", this->exception_info.specific.undefined_instruction.insn);
file.WriteFormat(" Opcode: %08x\n", m_exception_info.specific.undefined_instruction.insn);
break;
case svc::DebugException_DataAbort:
case svc::DebugException_AlignmentFault:
if (this->exception_info.specific.raw != this->exception_info.address) {
file.WriteFormat(" Fault Address: %s\n", this->module_list->GetFormattedAddressString(this->exception_info.specific.raw));
if (m_exception_info.specific.raw != m_exception_info.address) {
file.WriteFormat(" Fault Address: %s\n", m_module_list->GetFormattedAddressString(m_exception_info.specific.raw));
}
break;
case svc::DebugException_UndefinedSystemCall:
file.WriteFormat(" Svc Id: 0x%02x\n", this->exception_info.specific.undefined_system_call.id);
file.WriteFormat(" Svc Id: 0x%02x\n", m_exception_info.specific.undefined_system_call.id);
break;
case svc::DebugException_UserBreak:
file.WriteFormat(" Break Reason: 0x%x\n", this->exception_info.specific.user_break.break_reason);
file.WriteFormat(" Break Address: %s\n", this->module_list->GetFormattedAddressString(this->exception_info.specific.user_break.address));
file.WriteFormat(" Break Size: 0x%lx\n", this->exception_info.specific.user_break.size);
file.WriteFormat(" Break Reason: 0x%x\n", m_exception_info.specific.user_break.break_reason);
file.WriteFormat(" Break Address: %s\n", m_module_list->GetFormattedAddressString(m_exception_info.specific.user_break.address));
file.WriteFormat(" Break Size: 0x%lx\n", m_exception_info.specific.user_break.size);
break;
default:
break;
@ -403,23 +403,23 @@ namespace ams::creport {
/* Crashed Thread Info. */
file.WriteFormat("Crashed Thread Info:\n");
this->crashed_thread.SaveToFile(file);
m_crashed_thread.SaveToFile(file);
/* Dying Message. */
if (hos::GetVersion() >= hos::Version_5_0_0 && this->dying_message_size != 0) {
if (hos::GetVersion() >= hos::Version_5_0_0 && m_dying_message_size != 0) {
file.WriteFormat("Dying Message Info:\n");
file.WriteFormat(" Address: 0x%s\n", this->module_list->GetFormattedAddressString(this->dying_message_address));
file.WriteFormat(" Size: 0x%016lx\n", this->dying_message_size);
file.DumpMemory( " Dying Message: ", this->dying_message, this->dying_message_size);
file.WriteFormat(" Address: 0x%s\n", m_module_list->GetFormattedAddressString(m_dying_message_address));
file.WriteFormat(" Size: 0x%016lx\n", m_dying_message_size);
file.DumpMemory( " Dying Message: ", m_dying_message, m_dying_message_size);
}
/* Module Info. */
file.WriteFormat("Module Info:\n");
this->module_list->SaveToFile(file);
m_module_list->SaveToFile(file);
/* Thread Info. */
file.WriteFormat("Thread Report:\n");
this->thread_list->SaveToFile(file);
m_thread_list->SaveToFile(file);
}
}

View file

@ -25,66 +25,66 @@ namespace ams::creport {
static constexpr size_t MemoryHeapSize = 512_KB;
static_assert(MemoryHeapSize >= DyingMessageSizeMax + sizeof(ModuleList) + sizeof(ThreadList) + os::MemoryPageSize);
private:
os::NativeHandle debug_handle = os::InvalidNativeHandle;
bool has_extra_info = true;
Result result = creport::ResultIncompleteReport();
os::NativeHandle m_debug_handle = os::InvalidNativeHandle;
bool m_has_extra_info = true;
Result m_result = creport::ResultIncompleteReport();
/* Meta, used for building module/thread list. */
ThreadTlsMap thread_tls_map = {};
ThreadTlsMap m_thread_tls_map = {};
/* Attach process info. */
svc::DebugInfoCreateProcess process_info = {};
u64 dying_message_address = 0;
u64 dying_message_size = 0;
u8 *dying_message = nullptr;
svc::DebugInfoCreateProcess m_process_info = {};
u64 m_dying_message_address = 0;
u64 m_dying_message_size = 0;
u8 *m_dying_message = nullptr;
/* Exception info. */
svc::DebugInfoException exception_info = {};
u64 module_base_address = 0;
u64 crashed_thread_id = 0;
ThreadInfo crashed_thread;
svc::DebugInfoException m_exception_info = {};
u64 m_module_base_address = 0;
u64 m_crashed_thread_id = 0;
ThreadInfo m_crashed_thread;
/* Lists. */
ModuleList *module_list = nullptr;
ThreadList *thread_list = nullptr;
ModuleList *m_module_list = nullptr;
ThreadList *m_thread_list = nullptr;
/* Memory heap. */
lmem::HeapHandle heap_handle = nullptr;
u8 heap_storage[MemoryHeapSize] = {};
lmem::HeapHandle m_heap_handle = nullptr;
u8 m_heap_storage[MemoryHeapSize] = {};
public:
constexpr CrashReport() = default;
Result GetResult() const {
return this->result;
return m_result;
}
bool IsComplete() const {
return !ResultIncompleteReport::Includes(this->result);
return !ResultIncompleteReport::Includes(m_result);
}
bool IsOpen() const {
return this->debug_handle != os::InvalidNativeHandle;
return m_debug_handle != os::InvalidNativeHandle;
}
bool IsApplication() const {
return (this->process_info.flags & svc::CreateProcessFlag_IsApplication) != 0;
return (m_process_info.flags & svc::CreateProcessFlag_IsApplication) != 0;
}
bool Is64Bit() const {
return (this->process_info.flags & svc::CreateProcessFlag_Is64Bit) != 0;
return (m_process_info.flags & svc::CreateProcessFlag_Is64Bit) != 0;
}
bool IsUserBreak() const {
return this->exception_info.type == svc::DebugException_UserBreak;
return m_exception_info.type == svc::DebugException_UserBreak;
}
bool OpenProcess(os::ProcessId process_id) {
return R_SUCCEEDED(svc::DebugActiveProcess(std::addressof(this->debug_handle), process_id.value));
return R_SUCCEEDED(svc::DebugActiveProcess(std::addressof(m_debug_handle), process_id.value));
}
void Close() {
os::CloseNativeHandle(this->debug_handle);
this->debug_handle = os::InvalidNativeHandle;
os::CloseNativeHandle(m_debug_handle);
m_debug_handle = os::InvalidNativeHandle;
}
void Initialize();

View file

@ -46,12 +46,12 @@ namespace ams::creport {
}
void ModuleList::SaveToFile(ScopedFile &file) {
file.WriteFormat(" Number of Modules: %zu\n", this->num_modules);
for (size_t i = 0; i < this->num_modules; i++) {
const auto& module = this->modules[i];
file.WriteFormat(" Number of Modules: %zu\n", m_num_modules);
for (size_t i = 0; i < m_num_modules; i++) {
const auto& module = m_modules[i];
file.WriteFormat(" Module %02zu:\n", i);
file.WriteFormat(" Address: %016lx-%016lx\n", module.start_address, module.end_address);
if (std::strcmp(this->modules[i].name, "") != 0) {
if (std::strcmp(m_modules[i].name, "") != 0) {
file.WriteFormat(" Name: %s\n", module.name);
}
file.DumpMemory(" Build Id: ", module.build_id, sizeof(module.build_id));
@ -60,7 +60,7 @@ namespace ams::creport {
void ModuleList::FindModulesFromThreadInfo(os::NativeHandle debug_handle, const ThreadInfo &thread) {
/* Set the debug handle, for access in other member functions. */
this->debug_handle = debug_handle;
m_debug_handle = debug_handle;
/* Try to add the thread's PC. */
this->TryAddModule(thread.GetPC());
@ -82,25 +82,25 @@ namespace ams::creport {
}
/* Check whether we already have this module. */
for (size_t i = 0; i < this->num_modules; i++) {
if (this->modules[i].start_address <= base_address && base_address < this->modules[i].end_address) {
for (size_t i = 0; i < m_num_modules; i++) {
if (m_modules[i].start_address <= base_address && base_address < m_modules[i].end_address) {
return;
}
}
/* Add all contiguous modules. */
uintptr_t cur_address = base_address;
while (this->num_modules < ModuleCountMax) {
while (m_num_modules < ModuleCountMax) {
/* Get the region extents. */
svc::MemoryInfo mi;
svc::PageInfo pi;
if (R_FAILED(svc::QueryDebugProcessMemory(std::addressof(mi), std::addressof(pi), this->debug_handle, cur_address))) {
if (R_FAILED(svc::QueryDebugProcessMemory(std::addressof(mi), std::addressof(pi), m_debug_handle, cur_address))) {
break;
}
/* Parse module. */
if (mi.permission == svc::MemoryPermission_ReadExecute) {
auto& module = this->modules[this->num_modules++];
auto& module = m_modules[m_num_modules++];
module.start_address = mi.base_address;
module.end_address = mi.base_address + mi.size;
GetModuleName(module.name, module.start_address, module.end_address);
@ -129,20 +129,20 @@ namespace ams::creport {
/* Query the memory region our guess falls in. */
svc::MemoryInfo mi;
svc::PageInfo pi;
if (R_FAILED(svc::QueryDebugProcessMemory(std::addressof(mi), std::addressof(pi), this->debug_handle, guess))) {
if (R_FAILED(svc::QueryDebugProcessMemory(std::addressof(mi), std::addressof(pi), m_debug_handle, guess))) {
return false;
}
/* If we fall into a RW region, it may be rwdata. Query the region before it, which may be rodata or text. */
if (mi.permission == svc::MemoryPermission_ReadWrite) {
if (R_FAILED(svc::QueryDebugProcessMemory(std::addressof(mi), std::addressof(pi), debug_handle, mi.base_address - 4))) {
if (R_FAILED(svc::QueryDebugProcessMemory(std::addressof(mi), std::addressof(pi), m_debug_handle, mi.base_address - 4))) {
return false;
}
}
/* If we fall into an RO region, it may be rodata. Query the region before it, which should be text. */
if (mi.permission == svc::MemoryPermission_Read) {
if (R_FAILED(svc::QueryDebugProcessMemory(std::addressof(mi), std::addressof(pi), debug_handle, mi.base_address - 4))) {
if (R_FAILED(svc::QueryDebugProcessMemory(std::addressof(mi), std::addressof(pi), m_debug_handle, mi.base_address - 4))) {
return false;
}
}
@ -155,7 +155,7 @@ namespace ams::creport {
/* Modules are a series of contiguous (text/rodata/rwdata) regions. */
/* Iterate backwards until we find unmapped memory, to find the start of the set of modules loaded here. */
while (mi.base_address > 0) {
if (R_FAILED(svc::QueryDebugProcessMemory(std::addressof(mi), std::addressof(pi), debug_handle, mi.base_address - 4))) {
if (R_FAILED(svc::QueryDebugProcessMemory(std::addressof(mi), std::addressof(pi), m_debug_handle, mi.base_address - 4))) {
return false;
}
@ -181,7 +181,7 @@ namespace ams::creport {
svc::PageInfo pi;
/* Verify .rodata is read-only. */
if (R_FAILED(svc::QueryDebugProcessMemory(std::addressof(mi), std::addressof(pi), this->debug_handle, ro_start_address)) || mi.permission != svc::MemoryPermission_Read) {
if (R_FAILED(svc::QueryDebugProcessMemory(std::addressof(mi), std::addressof(pi), m_debug_handle, ro_start_address)) || mi.permission != svc::MemoryPermission_Read) {
return;
}
@ -189,7 +189,7 @@ namespace ams::creport {
const u64 rw_start_address = mi.base_address + mi.size;
/* Read start of .rodata. */
if (R_FAILED(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(std::addressof(rodata_start)), this->debug_handle, ro_start_address, sizeof(rodata_start)))) {
if (R_FAILED(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(std::addressof(rodata_start)), m_debug_handle, ro_start_address, sizeof(rodata_start)))) {
return;
}
@ -228,13 +228,13 @@ namespace ams::creport {
/* Verify .rodata is read-only. */
svc::MemoryInfo mi;
svc::PageInfo pi;
if (R_FAILED(svc::QueryDebugProcessMemory(std::addressof(mi), std::addressof(pi), this->debug_handle, ro_start_address)) || mi.permission != svc::MemoryPermission_Read) {
if (R_FAILED(svc::QueryDebugProcessMemory(std::addressof(mi), std::addressof(pi), m_debug_handle, ro_start_address)) || mi.permission != svc::MemoryPermission_Read) {
return;
}
/* We want to read the last two pages of .rodata. */
const size_t read_size = mi.size >= sizeof(g_last_rodata_pages) ? sizeof(g_last_rodata_pages) : (sizeof(g_last_rodata_pages) / 2);
if (R_FAILED(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(g_last_rodata_pages), this->debug_handle, mi.base_address + mi.size - read_size, read_size))) {
if (R_FAILED(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(g_last_rodata_pages), m_debug_handle, mi.base_address + mi.size - read_size, read_size))) {
return;
}
@ -249,18 +249,18 @@ namespace ams::creport {
const char *ModuleList::GetFormattedAddressString(uintptr_t address) {
/* Print default formatted string. */
util::SNPrintf(this->address_str_buf, sizeof(this->address_str_buf), "%016lx", address);
util::SNPrintf(m_address_str_buf, sizeof(m_address_str_buf), "%016lx", address);
/* See if the address is inside a module, for pretty-printing. */
for (size_t i = 0; i < this->num_modules; i++) {
const auto& module = this->modules[i];
for (size_t i = 0; i < m_num_modules; i++) {
const auto& module = m_modules[i];
if (module.start_address <= address && address < module.end_address) {
util::SNPrintf(this->address_str_buf, sizeof(this->address_str_buf), "%016lx (%s + 0x%lx)", address, module.name, address - module.start_address);
util::SNPrintf(m_address_str_buf, sizeof(m_address_str_buf), "%016lx (%s + 0x%lx)", address, module.name, address - module.start_address);
break;
}
}
return this->address_str_buf;
return m_address_str_buf;
}
}

View file

@ -32,23 +32,23 @@ namespace ams::creport {
u64 end_address;
};
private:
os::NativeHandle debug_handle;
size_t num_modules;
ModuleInfo modules[ModuleCountMax];
os::NativeHandle m_debug_handle;
size_t m_num_modules;
ModuleInfo m_modules[ModuleCountMax];
/* For pretty-printing. */
char address_str_buf[0x280];
char m_address_str_buf[0x280];
public:
ModuleList() : debug_handle(os::InvalidNativeHandle), num_modules(0) {
std::memset(this->modules, 0, sizeof(this->modules));
ModuleList() : m_debug_handle(os::InvalidNativeHandle), m_num_modules(0) {
std::memset(m_modules, 0, sizeof(m_modules));
}
size_t GetModuleCount() const {
return this->num_modules;
return m_num_modules;
}
u64 GetModuleStartAddress(size_t i) const {
return this->modules[i].start_address;
return m_modules[i].start_address;
}
void FindModulesFromThreadInfo(os::NativeHandle debug_handle, const ThreadInfo &thread);

View file

@ -90,8 +90,8 @@ namespace ams::creport {
}
/* Advance, if we write successfully. */
if (R_SUCCEEDED(fs::WriteFile(this->file, this->offset, data, size, fs::WriteOption::Flush))) {
this->offset += size;
if (R_SUCCEEDED(fs::WriteFile(m_file, m_offset, data, size, fs::WriteOption::Flush))) {
m_offset += size;
}
}

View file

@ -22,24 +22,24 @@ namespace ams::creport {
NON_COPYABLE(ScopedFile);
NON_MOVEABLE(ScopedFile);
private:
fs::FileHandle file;
s64 offset;
bool opened;
fs::FileHandle m_file;
s64 m_offset;
bool m_opened;
public:
ScopedFile(const char *path) : file(), offset(), opened(false) {
ScopedFile(const char *path) : m_file(), m_offset(), m_opened(false) {
if (R_SUCCEEDED(fs::CreateFile(path, 0))) {
this->opened = R_SUCCEEDED(fs::OpenFile(std::addressof(this->file), path, fs::OpenMode_Write | fs::OpenMode_AllowAppend));
m_opened = R_SUCCEEDED(fs::OpenFile(std::addressof(m_file), path, fs::OpenMode_Write | fs::OpenMode_AllowAppend));
}
}
~ScopedFile() {
if (this->opened) {
fs::CloseFile(file);
if (m_opened) {
fs::CloseFile(m_file);
}
}
bool IsOpen() const {
return this->opened;
return m_opened;
}
void WriteString(const char *str);

View file

@ -61,67 +61,67 @@ namespace ams::creport {
}
void ThreadList::SaveToFile(ScopedFile &file) {
file.WriteFormat("Number of Threads: %02zu\n", this->thread_count);
for (size_t i = 0; i < this->thread_count; i++) {
file.WriteFormat("Number of Threads: %02zu\n", m_thread_count);
for (size_t i = 0; i < m_thread_count; i++) {
file.WriteFormat("Threads[%02zu]:\n", i);
this->threads[i].SaveToFile(file);
m_threads[i].SaveToFile(file);
}
}
void ThreadInfo::SaveToFile(ScopedFile &file) {
file.WriteFormat(" Thread ID: %016lx\n", this->thread_id);
if (std::strcmp(this->name, "") != 0) {
file.WriteFormat(" Thread Name: %s\n", this->name);
file.WriteFormat(" Thread ID: %016lx\n", m_thread_id);
if (std::strcmp(m_name, "") != 0) {
file.WriteFormat(" Thread Name: %s\n", m_name);
}
if (this->stack_top != 0) {
file.WriteFormat(" Stack Region: %016lx-%016lx\n", this->stack_bottom, this->stack_top);
if (m_stack_top != 0) {
file.WriteFormat(" Stack Region: %016lx-%016lx\n", m_stack_bottom, m_stack_top);
}
file.WriteFormat(" Registers:\n");
{
for (unsigned int i = 0; i <= 28; i++) {
file.WriteFormat(" X[%02u]: %s\n", i, this->module_list->GetFormattedAddressString(this->context.r[i]));
file.WriteFormat(" X[%02u]: %s\n", i, m_module_list->GetFormattedAddressString(m_context.r[i]));
}
file.WriteFormat(" FP: %s\n", this->module_list->GetFormattedAddressString(this->context.fp));
file.WriteFormat(" LR: %s\n", this->module_list->GetFormattedAddressString(this->context.lr));
file.WriteFormat(" SP: %s\n", this->module_list->GetFormattedAddressString(this->context.sp));
file.WriteFormat(" PC: %s\n", this->module_list->GetFormattedAddressString(this->context.pc));
file.WriteFormat(" FP: %s\n", m_module_list->GetFormattedAddressString(m_context.fp));
file.WriteFormat(" LR: %s\n", m_module_list->GetFormattedAddressString(m_context.lr));
file.WriteFormat(" SP: %s\n", m_module_list->GetFormattedAddressString(m_context.sp));
file.WriteFormat(" PC: %s\n", m_module_list->GetFormattedAddressString(m_context.pc));
}
if (this->stack_trace_size != 0) {
if (m_stack_trace_size != 0) {
file.WriteFormat(" Stack Trace:\n");
for (size_t i = 0; i < this->stack_trace_size; i++) {
file.WriteFormat(" ReturnAddress[%02zu]: %s\n", i, this->module_list->GetFormattedAddressString(this->stack_trace[i]));
for (size_t i = 0; i < m_stack_trace_size; i++) {
file.WriteFormat(" ReturnAddress[%02zu]: %s\n", i, m_module_list->GetFormattedAddressString(m_stack_trace[i]));
}
}
if (this->stack_dump_base != 0) {
if (m_stack_dump_base != 0) {
file.WriteFormat(" Stack Dump: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n");
for (size_t i = 0; i < 0x10; i++) {
const size_t ofs = i * 0x10;
file.WriteFormat(" %012lx %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
this->stack_dump_base + ofs, this->stack_dump[ofs + 0], this->stack_dump[ofs + 1], this->stack_dump[ofs + 2], this->stack_dump[ofs + 3], this->stack_dump[ofs + 4], this->stack_dump[ofs + 5], this->stack_dump[ofs + 6], this->stack_dump[ofs + 7],
this->stack_dump[ofs + 8], this->stack_dump[ofs + 9], this->stack_dump[ofs + 10], this->stack_dump[ofs + 11], this->stack_dump[ofs + 12], this->stack_dump[ofs + 13], this->stack_dump[ofs + 14], this->stack_dump[ofs + 15]);
m_stack_dump_base + ofs, m_stack_dump[ofs + 0], m_stack_dump[ofs + 1], m_stack_dump[ofs + 2], m_stack_dump[ofs + 3], m_stack_dump[ofs + 4], m_stack_dump[ofs + 5], m_stack_dump[ofs + 6], m_stack_dump[ofs + 7],
m_stack_dump[ofs + 8], m_stack_dump[ofs + 9], m_stack_dump[ofs + 10], m_stack_dump[ofs + 11], m_stack_dump[ofs + 12], m_stack_dump[ofs + 13], m_stack_dump[ofs + 14], m_stack_dump[ofs + 15]);
}
}
if (this->tls_address != 0) {
file.WriteFormat(" TLS Address: %016lx\n", this->tls_address);
if (m_tls_address != 0) {
file.WriteFormat(" TLS Address: %016lx\n", m_tls_address);
file.WriteFormat(" TLS Dump: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n");
for (size_t i = 0; i < 0x10; i++) {
const size_t ofs = i * 0x10;
file.WriteFormat(" %012lx %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
this->tls_address + ofs, this->tls[ofs + 0], this->tls[ofs + 1], this->tls[ofs + 2], this->tls[ofs + 3], this->tls[ofs + 4], this->tls[ofs + 5], this->tls[ofs + 6], this->tls[ofs + 7],
this->tls[ofs + 8], this->tls[ofs + 9], this->tls[ofs + 10], this->tls[ofs + 11], this->tls[ofs + 12], this->tls[ofs + 13], this->tls[ofs + 14], this->tls[ofs + 15]);
m_tls_address + ofs, m_tls[ofs + 0], m_tls[ofs + 1], m_tls[ofs + 2], m_tls[ofs + 3], m_tls[ofs + 4], m_tls[ofs + 5], m_tls[ofs + 6], m_tls[ofs + 7],
m_tls[ofs + 8], m_tls[ofs + 9], m_tls[ofs + 10], m_tls[ofs + 11], m_tls[ofs + 12], m_tls[ofs + 13], m_tls[ofs + 14], m_tls[ofs + 15]);
}
}
}
bool ThreadInfo::ReadFromProcess(os::NativeHandle debug_handle, ThreadTlsMap &tls_map, u64 thread_id, bool is_64_bit) {
/* Set thread id. */
this->thread_id = thread_id;
m_thread_id = thread_id;
/* Verify that the thread is running or waiting. */
{
u64 _;
u32 _thread_state;
if (R_FAILED(svc::GetDebugThreadParam(&_, &_thread_state, debug_handle, this->thread_id, svc::DebugThreadParam_State))) {
if (R_FAILED(svc::GetDebugThreadParam(&_, &_thread_state, debug_handle, m_thread_id, svc::DebugThreadParam_State))) {
return false;
}
@ -132,24 +132,24 @@ namespace ams::creport {
}
/* Get the thread context. */
if (R_FAILED(svc::GetDebugThreadContext(std::addressof(this->context), debug_handle, this->thread_id, svc::ThreadContextFlag_All))) {
if (R_FAILED(svc::GetDebugThreadContext(std::addressof(m_context), debug_handle, m_thread_id, svc::ThreadContextFlag_All))) {
return false;
}
/* In aarch32 mode svc::GetDebugThreadContext does not set the LR, FP, and SP registers correctly. */
if (!is_64_bit) {
this->context.fp = this->context.r[11];
this->context.sp = this->context.r[13];
this->context.lr = this->context.r[14];
m_context.fp = m_context.r[11];
m_context.sp = m_context.r[13];
m_context.lr = m_context.r[14];
}
/* Read TLS, if present. */
/* TODO: struct definitions for nnSdk's ThreadType/TLS Layout? */
this->tls_address = 0;
if (tls_map.GetThreadTls(std::addressof(this->tls_address), thread_id)) {
m_tls_address = 0;
if (tls_map.GetThreadTls(std::addressof(m_tls_address), thread_id)) {
u8 thread_tls[sizeof(svc::ThreadLocalRegion)];
if (R_SUCCEEDED(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(thread_tls), debug_handle, this->tls_address, sizeof(thread_tls)))) {
std::memcpy(this->tls, thread_tls, sizeof(this->tls));
if (R_SUCCEEDED(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(thread_tls), debug_handle, m_tls_address, sizeof(thread_tls)))) {
std::memcpy(m_tls, thread_tls, sizeof(m_tls));
/* Try to detect libnx threads, and skip name parsing then. */
if (*(reinterpret_cast<u32 *>(std::addressof(thread_tls[0x1E0]))) != LibnxThreadVarMagic) {
u8 thread_type[0x1C0];
@ -161,12 +161,12 @@ namespace ams::creport {
/* Check thread name is actually at thread name. */
static_assert(0x1A8 - 0x188 == NameLengthMax, "NameLengthMax definition!");
if (*(reinterpret_cast<u64 *>(std::addressof(thread_type[0x1A8]))) == thread_type_addr + 0x188) {
std::memcpy(this->name, thread_type + 0x188, NameLengthMax);
std::memcpy(m_name, thread_type + 0x188, NameLengthMax);
}
} else if (thread_version == 1) {
static_assert(0x1A0 - 0x180 == NameLengthMax, "NameLengthMax definition!");
if (*(reinterpret_cast<u64 *>(std::addressof(thread_type[0x1A0]))) == thread_type_addr + 0x180) {
std::memcpy(this->name, thread_type + 0x180, NameLengthMax);
std::memcpy(m_name, thread_type + 0x180, NameLengthMax);
}
}
}
@ -179,9 +179,9 @@ namespace ams::creport {
/* Dump stack trace. */
if (is_64_bit) {
ReadStackTrace<u64>(std::addressof(this->stack_trace_size), this->stack_trace, StackTraceSizeMax, debug_handle, this->context.fp);
ReadStackTrace<u64>(std::addressof(m_stack_trace_size), m_stack_trace, StackTraceSizeMax, debug_handle, m_context.fp);
} else {
ReadStackTrace<u32>(std::addressof(this->stack_trace_size), this->stack_trace, StackTraceSizeMax, debug_handle, this->context.fp);
ReadStackTrace<u32>(std::addressof(m_stack_trace_size), m_stack_trace, StackTraceSizeMax, debug_handle, m_context.fp);
}
return true;
@ -191,7 +191,7 @@ namespace ams::creport {
/* Query stack region. */
svc::MemoryInfo mi;
svc::PageInfo pi;
if (R_FAILED(svc::QueryDebugProcessMemory(std::addressof(mi), std::addressof(pi), debug_handle, this->context.sp))) {
if (R_FAILED(svc::QueryDebugProcessMemory(std::addressof(mi), std::addressof(pi), debug_handle, m_context.sp))) {
return;
}
@ -204,56 +204,56 @@ namespace ams::creport {
}
/* Save stack extents. */
this->stack_bottom = mi.base_address;
this->stack_top = mi.base_address + mi.size;
m_stack_bottom = mi.base_address;
m_stack_top = mi.base_address + mi.size;
/* We always want to dump 0x100 of stack, starting from the lowest 0x10-byte aligned address below the stack pointer. */
/* Note: if the stack pointer is below the stack bottom, we will start dumping from the stack bottom. */
this->stack_dump_base = std::min(std::max(this->context.sp & ~0xFul, this->stack_bottom), this->stack_top - sizeof(this->stack_dump));
m_stack_dump_base = std::min(std::max(m_context.sp & ~0xFul, m_stack_bottom), m_stack_top - sizeof(m_stack_dump));
/* Try to read stack. */
if (R_FAILED(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(this->stack_dump), debug_handle, this->stack_dump_base, sizeof(this->stack_dump)))) {
this->stack_dump_base = 0;
if (R_FAILED(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(m_stack_dump), debug_handle, m_stack_dump_base, sizeof(m_stack_dump)))) {
m_stack_dump_base = 0;
}
}
void ThreadInfo::DumpBinary(ScopedFile &file) {
/* Dump id and context. */
file.Write(std::addressof(this->thread_id), sizeof(this->thread_id));
file.Write(std::addressof(this->context), sizeof(this->context));
file.Write(std::addressof(m_thread_id), sizeof(m_thread_id));
file.Write(std::addressof(m_context), sizeof(m_context));
/* Dump TLS info and name. */
file.Write(std::addressof(this->tls_address), sizeof(this->tls_address));
file.Write(std::addressof(this->tls), sizeof(this->tls));
file.Write(std::addressof(this->name), sizeof(this->name));
file.Write(std::addressof(m_tls_address), sizeof(m_tls_address));
file.Write(std::addressof(m_tls), sizeof(m_tls));
file.Write(std::addressof(m_name), sizeof(m_name));
/* Dump stack extents and stack dump. */
file.Write(std::addressof(this->stack_bottom), sizeof(this->stack_bottom));
file.Write(std::addressof(this->stack_top), sizeof(this->stack_top));
file.Write(std::addressof(this->stack_dump_base), sizeof(this->stack_dump_base));
file.Write(std::addressof(this->stack_dump), sizeof(this->stack_dump));
file.Write(std::addressof(m_stack_bottom), sizeof(m_stack_bottom));
file.Write(std::addressof(m_stack_top), sizeof(m_stack_top));
file.Write(std::addressof(m_stack_dump_base), sizeof(m_stack_dump_base));
file.Write(std::addressof(m_stack_dump), sizeof(m_stack_dump));
/* Dump stack trace. */
{
const u64 sts = this->stack_trace_size;
const u64 sts = m_stack_trace_size;
file.Write(std::addressof(sts), sizeof(sts));
}
file.Write(this->stack_trace, this->stack_trace_size);
file.Write(m_stack_trace, m_stack_trace_size);
}
void ThreadList::DumpBinary(ScopedFile &file, u64 crashed_thread_id) {
const u32 magic = DumpedThreadInfoMagic;
const u32 count = this->thread_count;
const u32 count = m_thread_count;
file.Write(std::addressof(magic), sizeof(magic));
file.Write(std::addressof(count), sizeof(count));
file.Write(std::addressof(crashed_thread_id), sizeof(crashed_thread_id));
for (size_t i = 0; i < this->thread_count; i++) {
this->threads[i].DumpBinary(file);
for (size_t i = 0; i < m_thread_count; i++) {
m_threads[i].DumpBinary(file);
}
}
void ThreadList::ReadFromProcess(os::NativeHandle debug_handle, ThreadTlsMap &tls_map, bool is_64_bit) {
this->thread_count = 0;
m_thread_count = 0;
/* Get thread list. */
s32 num_threads;
@ -267,8 +267,8 @@ namespace ams::creport {
/* Parse thread infos. */
for (s32 i = 0; i < num_threads; i++) {
if (this->threads[this->thread_count].ReadFromProcess(debug_handle, tls_map, thread_ids[i], is_64_bit)) {
this->thread_count++;
if (m_threads[m_thread_count].ReadFromProcess(debug_handle, tls_map, thread_ids[i], is_64_bit)) {
m_thread_count++;
}
}
}

View file

@ -60,53 +60,53 @@ namespace ams::creport {
static constexpr size_t StackTraceSizeMax = 0x20;
static constexpr size_t NameLengthMax = 0x20;
private:
svc::ThreadContext context = {};
u64 thread_id = 0;
u64 stack_top = 0;
u64 stack_bottom = 0;
u64 stack_trace[StackTraceSizeMax] = {};
size_t stack_trace_size = 0;
u64 tls_address = 0;
u8 tls[0x100] = {};
u64 stack_dump_base = 0;
u8 stack_dump[0x100] = {};
char name[NameLengthMax + 1] = {};
ModuleList *module_list = nullptr;
svc::ThreadContext m_context = {};
u64 m_thread_id = 0;
u64 m_stack_top = 0;
u64 m_stack_bottom = 0;
u64 m_stack_trace[StackTraceSizeMax] = {};
size_t m_stack_trace_size = 0;
u64 m_tls_address = 0;
u8 m_tls[0x100] = {};
u64 m_stack_dump_base = 0;
u8 m_stack_dump[0x100] = {};
char m_name[NameLengthMax + 1] = {};
ModuleList *m_module_list = nullptr;
public:
u64 GetGeneralPurposeRegister(size_t i) const {
return this->context.r[i];
return m_context.r[i];
}
u64 GetPC() const {
return this->context.pc;
return m_context.pc;
}
u64 GetLR() const {
return this->context.lr;
return m_context.lr;
}
u64 GetFP() const {
return this->context.fp;
return m_context.fp;
}
u64 GetSP() const {
return this->context.sp;
return m_context.sp;
}
u64 GetThreadId() const {
return this->thread_id;
return m_thread_id;
}
size_t GetStackTraceSize() const {
return this->stack_trace_size;
return m_stack_trace_size;
}
u64 GetStackTrace(size_t i) const {
return this->stack_trace[i];
return m_stack_trace[i];
}
void SetModuleList(ModuleList *ml) {
this->module_list = ml;
m_module_list = ml;
}
bool ReadFromProcess(os::NativeHandle debug_handle, ThreadTlsMap &tls_map, u64 thread_id, bool is_64_bit);
@ -118,20 +118,20 @@ namespace ams::creport {
class ThreadList {
private:
size_t thread_count = 0;
ThreadInfo threads[ThreadCountMax];
size_t m_thread_count = 0;
ThreadInfo m_threads[ThreadCountMax];
public:
size_t GetThreadCount() const {
return this->thread_count;
return m_thread_count;
}
const ThreadInfo &GetThreadInfo(size_t i) const {
return this->threads[i];
return m_threads[i];
}
void SetModuleList(ModuleList *ml) {
for (size_t i = 0; i < this->thread_count; i++) {
this->threads[i].SetModuleList(ml);
for (size_t i = 0; i < m_thread_count; i++) {
m_threads[i].SetModuleList(ml);
}
}