creport: Implement reading name/build id from .rodata

This commit is contained in:
Michael Scire 2018-06-25 09:50:36 -06:00
parent f189610af8
commit 92bc396972
2 changed files with 57 additions and 2 deletions

View file

@ -1,4 +1,5 @@
#include <switch.h>
#include <cstring>
#include "creport_code_info.hpp"
@ -19,7 +20,11 @@ void CodeList::ReadCodeRegionsFromProcess(Handle debug_handle, u64 pc, u64 lr) {
}
if (mi.perm == Perm_Rx) {
/* TODO: Parse CodeInfo. */
/* Parse CodeInfo. */
this->code_infos[this->code_count].start_address = mi.addr;
this->code_infos[this->code_count].end_address = mi.addr + mi.size;
GetCodeInfoName(debug_handle, mi.addr + mi.size, this->code_infos[this->code_count].name);
GetCodeInfoBuildId(debug_handle, mi.addr + mi.size, this->code_infos[this->code_count].build_id);
this->code_count++;
}
@ -60,3 +65,51 @@ bool CodeList::TryFindCodeRegion(Handle debug_handle, u64 guess, u64 *address) {
}
return false;
}
void CodeList::GetCodeInfoName(u64 debug_handle, u64 rodata_addr, char *name) {
char name_in_proc[0x200];
/* Clear name. */
memset(name, 0, 0x20);
/* Read name out of .rodata. */
if (R_FAILED(svcReadDebugProcessMemory(name_in_proc, debug_handle, rodata_addr + 8, sizeof(name_in_proc)))) {
return;
}
/* Start after last slash in path. */
int ofs = strnlen(name_in_proc, sizeof(name_in_proc));
while (ofs >= 0 && name_in_proc[ofs] != '/' && name_in_proc[ofs] != '\\') {
ofs--;
}
strncpy(name, name_in_proc + ofs + 1, 0x20);
name[0x1F] = '\x00';
}
void CodeList::GetCodeInfoBuildId(u64 debug_handle, u64 rodata_addr, u8 *build_id) {
MemoryInfo mi;
u32 pi;
/* Clear build id. */
memset(build_id, 0, 0x20);
/* Verify .rodata is read-only. */
if (R_FAILED(svcQueryDebugProcessMemory(&mi, &pi, debug_handle, rodata_addr)) || mi.perm != Perm_R) {
return;
}
/* We want to read the last two pages of .rodata. */
u8 last_pages[0x2000];
size_t last_pages_size = mi.size >= 0x2000 ? 0x2000 : 0x1000;
if (R_FAILED(svcReadDebugProcessMemory(last_pages, debug_handle, mi.addr + mi.size - last_pages_size, last_pages_size))) {
return;
}
/* Find GNU\x00 to locate start of Build ID. */
for (int ofs = last_pages_size - 0x24; ofs >= 0; ofs--) {
if (memcmp(last_pages + ofs, "GNU\x00", 4) == 0) {
memcpy(build_id, last_pages + ofs + 4, 0x20);
}
}
}

View file

@ -5,7 +5,7 @@
struct CodeInfo {
char name[0x20];
u8 id[0x20];
u8 build_id[0x20];
u64 start_address;
u64 end_address;
};
@ -21,4 +21,6 @@ class CodeList {
void ReadCodeRegionsFromProcess(Handle debug_handle, u64 pc, u64 lr);
private:
bool TryFindCodeRegion(Handle debug_handle, u64 guess, u64 *address);
void GetCodeInfoName(u64 debug_handle, u64 ro_address, char *name);
void GetCodeInfoBuildId(u64 debug_handle, u64 ro_address, u8 *build_id);
};