[jit] fix Super Mario 64 in SM3D: All-Stars (#3950)

jit service had wrong check for module versions
missing handlers for some funcs
the page cache i added interfered with jit (gee who would've tought)

Signed-off-by: lizzie <lizzie@eden-emu.dev>

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3950
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: crueter <crueter@eden-emu.dev>
This commit is contained in:
lizzie
2026-05-13 19:02:33 +02:00
committed by crueter
parent 7e84f9ef59
commit b89cd6903c
7 changed files with 198 additions and 213 deletions
+84 -87
View File
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -13,117 +16,111 @@ using namespace Common::ELF;
namespace Core {
namespace Symbols {
template <typename Word, typename ELFSymbol, typename ByteReader>
static Symbols GetSymbols(ByteReader ReadBytes) {
const auto Read8{[&](u64 index) {
struct ModuleHeaderLocation {
u32 version;
u32 header_offset;
u32 version_offset;
};
static_assert(sizeof(ModuleHeaderLocation) == 0x0C);
struct ModuleHeader {
u32 signature;
u32 dynamic_offset;
u32 bss_start_offset;
u32 bss_end_offset;
u32 exception_info_start_offset;
u32 exception_info_end_offset;
u32 module_offset;
u32 relro_start_offset;
u32 full_relro_end_offset;
u32 nx_debug_link_start_offset;
u32 nx_debug_link_end_offset;
u32 note_gnu_build_id_start_offset;
u32 note_gnu_build_id_end_offset;
};
static_assert(sizeof(ModuleHeader) == 0x34);
struct Mod32 {
using Sym = Elf32_Sym;
using Dyn = Elf32_Dyn;
};
struct Mod64 {
using Sym = Elf64_Sym;
using Dyn = Elf64_Dyn;
};
template <typename M, typename F>
static Symbols GetSymbols(F&& ReadBytes) {
const auto Read8 = [&](u64 index) {
u8 ret;
ReadBytes(&ret, index, sizeof(u8));
return ret;
}};
const auto Read32{[&](u64 index) {
u32 ret;
ReadBytes(&ret, index, sizeof(u32));
return ret;
}};
const auto ReadWord{[&](u64 index) {
Word ret;
ReadBytes(&ret, index, sizeof(Word));
return ret;
}};
const u32 mod_offset = Read32(4);
if (Read32(mod_offset) != Common::MakeMagic('M', 'O', 'D', '0')) {
};
ModuleHeaderLocation loc{};
ReadBytes(&loc, 0, sizeof(ModuleHeaderLocation));
ModuleHeader hdr;
ReadBytes(&hdr, loc.header_offset, sizeof(ModuleHeader));
if (hdr.signature != Common::MakeMagic('M', 'O', 'D', '0')) {
return {};
}
VAddr string_table_offset{};
VAddr symbol_table_offset{};
u64 symbol_entry_size{};
const auto dynamic_offset = Read32(mod_offset + 0x4) + mod_offset;
VAddr dynamic_index = dynamic_offset;
VAddr strtab_offs{};
VAddr symtab_offs{};
u64 syment_size = sizeof(typename M::Sym);
VAddr dynamic_offset = loc.header_offset + hdr.dynamic_offset;
while (true) {
const Word tag = ReadWord(dynamic_index);
const Word value = ReadWord(dynamic_index + sizeof(Word));
dynamic_index += 2 * sizeof(Word);
if (tag == ElfDtNull) {
typename M::Dyn dyn;
ReadBytes(&dyn, dynamic_offset, sizeof(typename M::Dyn));
dynamic_offset += sizeof(typename M::Dyn);
if (dyn.d_tag == ElfDtNull) {
break;
}
if (tag == ElfDtStrtab) {
string_table_offset = value;
} else if (tag == ElfDtSymtab) {
symbol_table_offset = value;
} else if (tag == ElfDtSyment) {
symbol_entry_size = value;
if (dyn.d_tag == ElfDtStrtab) {
strtab_offs = dyn.d_un.d_ptr;
} else if (dyn.d_tag == ElfDtSymtab) {
symtab_offs = dyn.d_un.d_ptr;
} else if (dyn.d_tag == ElfDtSyment) {
syment_size = dyn.d_un.d_val;
}
}
if (string_table_offset == 0 || symbol_table_offset == 0 || symbol_entry_size == 0) {
return {};
}
Symbols out;
VAddr symbol_index = symbol_table_offset;
while (symbol_index < string_table_offset) {
ELFSymbol symbol{};
ReadBytes(&symbol, symbol_index, sizeof(ELFSymbol));
VAddr string_offset = string_table_offset + symbol.st_name;
std::string name;
for (u8 c = Read8(string_offset); c != 0; c = Read8(++string_offset)) {
name += static_cast<char>(c);
if (strtab_offs > 0 && symtab_offs > 0) {
Symbols out;
VAddr symbol_index = symtab_offs;
while (symbol_index < strtab_offs) {
typename M::Sym symbol{};
ReadBytes(&symbol, symbol_index, sizeof(typename M::Sym));
VAddr offs = strtab_offs + symbol.st_name;
std::string name{};
for (u8 c = Read8(offs); c != 0; c = Read8(++offs))
name += char(c);
symbol_index += syment_size;
out[name] = std::make_pair(symbol.st_value, symbol.st_size);
}
symbol_index += symbol_entry_size;
out[name] = std::make_pair(symbol.st_value, symbol.st_size);
return out;
}
return out;
return {};
}
Symbols GetSymbols(VAddr base, Core::Memory::Memory& memory, bool is_64) {
const auto ReadBytes{
[&](void* ptr, size_t offset, size_t size) { memory.ReadBlock(base + offset, ptr, size); }};
if (is_64) {
return GetSymbols<u64, Elf64_Sym>(ReadBytes);
} else {
return GetSymbols<u32, Elf32_Sym>(ReadBytes);
}
const auto f = [base, &memory](void* ptr, size_t offset, size_t size) {
memory.ReadBlock(base + offset, ptr, size);
};
return is_64 ? GetSymbols<Mod64>(f) : GetSymbols<Mod32>(f);
}
Symbols GetSymbols(std::span<const u8> data, bool is_64) {
const auto ReadBytes{[&](void* ptr, size_t offset, size_t size) {
const auto f = [data](void* ptr, size_t offset, size_t size) {
std::memcpy(ptr, data.data() + offset, size);
}};
if (is_64) {
return GetSymbols<u64, Elf64_Sym>(ReadBytes);
} else {
return GetSymbols<u32, Elf32_Sym>(ReadBytes);
}
};
return is_64 ? GetSymbols<Mod64>(f) : GetSymbols<Mod32>(f);
}
std::optional<std::string> GetSymbolName(const Symbols& symbols, VAddr addr) {
const auto iter = std::find_if(symbols.cbegin(), symbols.cend(), [addr](const auto& pair) {
const auto& [name, sym_info] = pair;
const auto& [start_address, size] = sym_info;
const auto end_address = start_address + size;
return addr >= start_address && addr < end_address;
const auto it = std::find_if(symbols.cbegin(), symbols.cend(), [addr](const auto& e) {
auto const [start, size] = e.second;
auto const end = start + size;
return addr >= start && addr < end;
});
if (iter == symbols.cend()) {
return std::nullopt;
}
return iter->first;
return it != symbols.cend() ? std::optional<std::string>{it->first} : std::nullopt;
}
} // namespace Symbols