creport: Skeleton reading of Code Regions.

This commit is contained in:
Michael Scire 2018-06-25 04:38:54 -06:00
parent fd6fa89122
commit f189610af8
5 changed files with 92 additions and 1 deletions

View file

@ -0,0 +1,62 @@
#include <switch.h>
#include "creport_code_info.hpp"
void CodeList::ReadCodeRegionsFromProcess(Handle debug_handle, u64 pc, u64 lr) {
u64 code_base;
/* Guess that either PC or LR will point to a code region. This could be false. */
if (!TryFindCodeRegion(debug_handle, pc, &code_base) && !TryFindCodeRegion(debug_handle, lr, &code_base)) {
return;
}
u64 cur_ptr = code_base;
while (this->code_count < max_code_count) {
MemoryInfo mi;
u32 pi;
if (R_FAILED(svcQueryDebugProcessMemory(&mi, &pi, debug_handle, cur_ptr))) {
break;
}
if (mi.perm == Perm_Rx) {
/* TODO: Parse CodeInfo. */
this->code_count++;
}
/* If we're out of readable memory, we're done reading code. */
if (mi.type == MemType_Unmapped || mi.type == MemType_Reserved) {
break;
}
/* Verify we're not getting stuck in an infinite loop. */
if (mi.size == 0 || U64_MAX - mi.size <= cur_ptr) {
break;
}
cur_ptr += mi.size;
}
}
bool CodeList::TryFindCodeRegion(Handle debug_handle, u64 guess, u64 *address) {
MemoryInfo mi;
u32 pi;
if (R_FAILED(svcQueryDebugProcessMemory(&mi, &pi, debug_handle, guess)) || mi.perm != Perm_Rx) {
return false;
}
/* Iterate backwards until we find the memory before the code region. */
while (mi.addr > 0) {
if (R_FAILED(svcQueryDebugProcessMemory(&mi, &pi, debug_handle, guess))) {
return false;
}
if (mi.type == MemType_Unmapped) {
/* Code region will be at the end of the unmapped region preceding it. */
*address = mi.addr + mi.size;
return true;
}
guess -= 4;
}
return false;
}

View file

@ -0,0 +1,24 @@
#pragma once
#include <switch.h>
#include "creport_debug_types.hpp"
struct CodeInfo {
char name[0x20];
u8 id[0x20];
u64 start_address;
u64 end_address;
};
class CodeList {
private:
static const size_t max_code_count = 0x10;
u32 code_count;
CodeInfo code_infos[max_code_count];
public:
CodeList() : code_count(0), code_infos({}) { }
void ReadCodeRegionsFromProcess(Handle debug_handle, u64 pc, u64 lr);
private:
bool TryFindCodeRegion(Handle debug_handle, u64 guess, u64 *address);
};

View file

@ -11,7 +11,7 @@ void CrashReport::BuildReport(u64 pid, bool has_extra_info) {
if (OpenProcess(pid)) { if (OpenProcess(pid)) {
ProcessExceptions(); ProcessExceptions();
if (kernelAbove500()) { if (kernelAbove500()) {
/* TODO: Process Code Regions. */ this->code_list.ReadCodeRegionsFromProcess(this->debug_handle, this->crashed_thread_info.GetPC(), this->crashed_thread_info.GetLR());
this->thread_list.ReadThreadsFromProcess(this->debug_handle, Is64Bit()); this->thread_list.ReadThreadsFromProcess(this->debug_handle, Is64Bit());
} }

View file

@ -4,6 +4,7 @@
#include "creport_debug_types.hpp" #include "creport_debug_types.hpp"
#include "creport_thread_info.hpp" #include "creport_thread_info.hpp"
#include "creport_code_info.hpp"
enum class CrashReportResult : Result { enum class CrashReportResult : Result {
UndefinedInstruction = 0x00A8, UndefinedInstruction = 0x00A8,
@ -38,6 +39,7 @@ class CrashReport {
ThreadInfo crashed_thread_info; ThreadInfo crashed_thread_info;
/* Extra Info. */ /* Extra Info. */
CodeList code_list;
ThreadList thread_list; ThreadList thread_list;
public: public:

View file

@ -41,6 +41,9 @@ class ThreadInfo {
(*this) = {}; (*this) = {};
} }
u64 GetPC() { return context.pc; }
u64 GetLR() { return context.lr; }
bool ReadFromProcess(Handle debug_handle, u64 thread_id, bool is_64_bit); bool ReadFromProcess(Handle debug_handle, u64 thread_id, bool is_64_bit);
private: private:
void TryGetStackInfo(Handle debug_handle); void TryGetStackInfo(Handle debug_handle);