core: Handle ELF metadata and toolchain comments program headers (#5480)

- Parse PT_INTERP and record interpreter dynamic linker path
- Parse PT_SCE_COMMENT and extract original compiler/toolchain build path
- Parse PT_SCE_LIBVERSION and log SCE SDK version
- Handle non-loadable metadata/flag segments (PT_GNU_STACK, PT_GNU_RELRO, PT_NOTE, PT_PHDR) to avoid false unimplemented type errors
This commit is contained in:
Marcin Mitura authored and GitHub committed 2026-10-24 06:33:36 -07:00
1 parent 9d3524f53b
commit cc4dbd45bc
2 files changed
+67

No files matched your search

+65
View File
@@ -256,6 +256,71 @@ void Module::LoadModuleToMemory(u32& max_tls_index) {
case PT_SCE_MODULE_PARAM:
module_param_virtual_addr = elf_pheader[i].p_vaddr + base_virtual_addr;
break;
case PT_INTERP: {
if (elf_pheader[i].p_filesz != 0) {
interpreter_path.resize(elf_pheader[i].p_filesz);
elf.LoadSegment(std::bit_cast<VAddr>(interpreter_path.data()),
elf_pheader[i].p_offset, elf_pheader[i].p_filesz);
while (!interpreter_path.empty() && interpreter_path.back() == '\0') {
interpreter_path.pop_back();
}
LOG_INFO(Core_Linker, "Module interpreter: '{}'", interpreter_path);
}
break;
}
case PT_SCE_COMMENT: {
if (elf_pheader[i].p_filesz != 0) {
comment.resize(elf_pheader[i].p_filesz);
elf.LoadSegment(std::bit_cast<VAddr>(comment.data()), elf_pheader[i].p_offset,
elf_pheader[i].p_filesz);
if (comment.starts_with("PATH") && comment.size() > 12) {
comment = comment.substr(12);
comment = comment.substr(0, comment.find('\0'));
} else {
for (char& c : comment) {
if (c == '\0') {
c = ' ';
}
}
while (!comment.empty() && (comment.back() == ' ' || comment.back() == '\0')) {
comment.pop_back();
}
}
LOG_INFO(Core_Linker, "Module comment: '{}'", comment);
}
break;
}
case PT_SCE_LIBVERSION: {
if (elf_pheader[i].p_filesz != 0) {
std::vector<u8> libver_data(elf_pheader[i].p_filesz);
elf.LoadSegment(std::bit_cast<VAddr>(libver_data.data()), elf_pheader[i].p_offset,
elf_pheader[i].p_filesz);
if (!libver_data.empty()) {
const u8 rec_len = libver_data[0];
if (rec_len > 4 && 1u + rec_len <= libver_data.size()) {
const std::string_view rec(
reinterpret_cast<const char*>(libver_data.data() + 1), rec_len);
const auto colon = rec.find(':');
if (colon != std::string_view::npos && colon + 5 <= rec_len) {
const u8* ver_bytes =
reinterpret_cast<const u8*>(rec.data() + colon + 1);
const u32 sdk_ver = (u32(ver_bytes[0]) << 24) |
(u32(ver_bytes[1]) << 16) |
(u32(ver_bytes[2]) << 8) | u32(ver_bytes[3]);
LOG_INFO(Core_Linker, "SCE SDK version: {:x}.{:02x} [{:#010x}]",
ver_bytes[0], ver_bytes[1], sdk_ver);
}
}
}
}
break;
}
case PT_GNU_STACK:
case PT_GNU_RELRO:
case PT_NOTE:
case PT_PHDR:
// Non-loadable metadata/flags segments; nothing to map
break;
case PT_GNU_EH_FRAME: {
eh_frame_hdr_addr = elf_pheader[i].p_vaddr;
eh_frame_hdr_size = elf_pheader[i].p_memsz;
+2
View File
@@ -238,6 +238,8 @@ public:
VAddr base_virtual_addr{};
VAddr proc_param_virtual_addr{};
VAddr module_param_virtual_addr{};
std::string interpreter_path{};
std::string comment{};
VAddr eh_frame_hdr_addr{};
VAddr eh_frame_addr{};
u32 eh_frame_hdr_size{};