diff --git a/stratosphere/creport/source/creport_code_info.cpp b/stratosphere/creport/source/creport_code_info.cpp index 7922dd206..2fc38240d 100644 --- a/stratosphere/creport/source/creport_code_info.cpp +++ b/stratosphere/creport/source/creport_code_info.cpp @@ -1,4 +1,5 @@ #include +#include #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++; } @@ -59,4 +64,52 @@ bool CodeList::TryFindCodeRegion(Handle debug_handle, u64 guess, u64 *address) { guess -= 4; } 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); + } + } } \ No newline at end of file diff --git a/stratosphere/creport/source/creport_code_info.hpp b/stratosphere/creport/source/creport_code_info.hpp index 68edad9d7..7f069a188 100644 --- a/stratosphere/creport/source/creport_code_info.hpp +++ b/stratosphere/creport/source/creport_code_info.hpp @@ -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); };