mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 22:06:59 +01:00
loader: preserve resolved relocations across dynamic loads
This commit is contained in:
@@ -1007,17 +1007,12 @@ static RelocationInfo GetRelocationInfo(Elf64_Rela* r, Program* program) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void RelocateRecord(uint32_t index, Elf64_Rela* r, Program* program, bool jmprela_table,
|
static bool RelocateRecord(uint32_t index, Elf64_Rela* r, Program* program, bool jmprela_table,
|
||||||
bool imports_only, std::vector<std::string>* unresolved) {
|
std::vector<std::string>* unresolved) {
|
||||||
KYTY_PROFILER_FUNCTION();
|
KYTY_PROFILER_FUNCTION();
|
||||||
|
|
||||||
auto ri = GetRelocationInfo(r, program);
|
auto ri = GetRelocationInfo(r, program);
|
||||||
|
|
||||||
if (imports_only &&
|
|
||||||
(ri.bind_self || (ri.bind != BindType::Global && ri.bind != BindType::Weak))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[maybe_unused]] bool patched = false;
|
[[maybe_unused]] bool patched = false;
|
||||||
bool stubbed_import = false;
|
bool stubbed_import = false;
|
||||||
bool stubbed_func = false;
|
bool stubbed_func = false;
|
||||||
@@ -1098,17 +1093,23 @@ static void RelocateRecord(uint32_t index, Elf64_Rela* r, Program* program, bool
|
|||||||
LOGF("Relocate: %s\n", dbg_str.c_str());
|
LOGF("Relocate: %s\n", dbg_str.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return ri.resolved;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void RelocateRecords(Elf64_Rela* records, uint64_t size, Program* program,
|
static void RelocateRecords(Elf64_Rela* records, uint64_t size, Program* program,
|
||||||
bool jmprela_table, bool imports_only,
|
bool jmprela_table, uint32_t bit_base,
|
||||||
std::vector<std::string>* unresolved) {
|
std::vector<std::string>* unresolved) {
|
||||||
KYTY_PROFILER_FUNCTION();
|
KYTY_PROFILER_FUNCTION();
|
||||||
|
|
||||||
uint32_t index = 0;
|
uint32_t index = 0;
|
||||||
for (auto* r = records;
|
for (auto* r = records;
|
||||||
reinterpret_cast<uint8_t*>(r) < reinterpret_cast<uint8_t*>(records) + size; r++, index++) {
|
reinterpret_cast<uint8_t*>(r) < reinterpret_cast<uint8_t*>(records) + size; r++, index++) {
|
||||||
RelocateRecord(index, r, program, jmprela_table, imports_only, unresolved);
|
const auto bit_index = bit_base + index;
|
||||||
|
if ((program->rela_bits[bit_index >> 3u] & (1u << (bit_index & 7u))) == 0) {
|
||||||
|
if (RelocateRecord(index, r, program, jmprela_table, unresolved)) {
|
||||||
|
program->rela_bits[bit_index >> 3u] |= 1u << (bit_index & 7u);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1314,8 +1315,6 @@ void RuntimeLinker::RelocateAll() {
|
|||||||
for (auto* p: m_programs) {
|
for (auto* p: m_programs) {
|
||||||
Relocate(p);
|
Relocate(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_relocated = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RuntimeLinker::RelocateProgram(Program* program) {
|
void RuntimeLinker::RelocateProgram(Program* program) {
|
||||||
@@ -1342,10 +1341,6 @@ void RuntimeLinker::UnloadProgram(Program* program) {
|
|||||||
} else {
|
} else {
|
||||||
EXIT("program not found");
|
EXIT("program not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_relocated) {
|
|
||||||
RelocateAll();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RuntimeLinker::RuntimeLinker(): m_symbols(std::make_unique<SymbolDatabase>()) {
|
RuntimeLinker::RuntimeLinker(): m_symbols(std::make_unique<SymbolDatabase>()) {
|
||||||
@@ -1499,7 +1494,6 @@ void RuntimeLinker::Clear() {
|
|||||||
g_tls_cached_main_tcb = nullptr;
|
g_tls_cached_main_tcb = nullptr;
|
||||||
g_desired_base_addr = SYSTEM_RESERVED + CODE_BASE_OFFSET;
|
g_desired_base_addr = SYSTEM_RESERVED + CODE_BASE_OFFSET;
|
||||||
m_symbols.reset();
|
m_symbols.reset();
|
||||||
m_relocated = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RuntimeLinker::Resolve(const std::string& name, SymbolType type, Program* program,
|
void RuntimeLinker::Resolve(const std::string& name, SymbolType type, Program* program,
|
||||||
@@ -2281,6 +2275,11 @@ void RuntimeLinker::ParseProgramDynamicInfo(Program* program) {
|
|||||||
GetDynValue(elf, &program->dynamic_info->rela_table_total_size, DT_RELASZ);
|
GetDynValue(elf, &program->dynamic_info->rela_table_total_size, DT_RELASZ);
|
||||||
GetDynValue(elf, &program->dynamic_info->rela_table_entry_size, DT_OS_RELAENT);
|
GetDynValue(elf, &program->dynamic_info->rela_table_entry_size, DT_OS_RELAENT);
|
||||||
GetDynValue(elf, &program->dynamic_info->rela_table_entry_size, DT_RELAENT);
|
GetDynValue(elf, &program->dynamic_info->rela_table_entry_size, DT_RELAENT);
|
||||||
|
EXIT_NOT_IMPLEMENTED(program->dynamic_info->rela_table_total_size % sizeof(Elf64_Rela) != 0 ||
|
||||||
|
program->dynamic_info->jmprela_table_size % sizeof(Elf64_Rela) != 0);
|
||||||
|
const auto rela_count = program->dynamic_info->rela_table_total_size / sizeof(Elf64_Rela);
|
||||||
|
const auto jmprela_count = program->dynamic_info->jmprela_table_size / sizeof(Elf64_Rela);
|
||||||
|
program->rela_bits.resize((rela_count + jmprela_count + 7u) / 8u);
|
||||||
|
|
||||||
GetDynValue(elf, &program->dynamic_info->relative_count, DT_RELACOUNT);
|
GetDynValue(elf, &program->dynamic_info->relative_count, DT_RELACOUNT);
|
||||||
|
|
||||||
@@ -2348,7 +2347,6 @@ static void InstallRelocateHandler(Program* program) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO(): check if this table already generated by compiler (sometimes it is missing)
|
// TODO(): check if this table already generated by compiler (sometimes it is missing)
|
||||||
if (program->custom_call_plt_vaddr == 0) {
|
|
||||||
program->custom_call_plt_num =
|
program->custom_call_plt_num =
|
||||||
program->dynamic_info->jmprela_table_size / sizeof(Elf64_Rela);
|
program->dynamic_info->jmprela_table_size / sizeof(Elf64_Rela);
|
||||||
auto size = Jit::CallPlt::GetSize(program->custom_call_plt_num);
|
auto size = Jit::CallPlt::GetSize(program->custom_call_plt_num);
|
||||||
@@ -2362,7 +2360,6 @@ static void InstallRelocateHandler(Program* program) {
|
|||||||
Common::VirtualMemory::Mode::Execute));
|
Common::VirtualMemory::Mode::Execute));
|
||||||
Common::VirtualMemory::FlushInstructionCache(program->custom_call_plt_vaddr, size);
|
Common::VirtualMemory::FlushInstructionCache(program->custom_call_plt_vaddr, size);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void RuntimeLinker::Relocate(Program* program) {
|
void RuntimeLinker::Relocate(Program* program) {
|
||||||
KYTY_PROFILER_FUNCTION();
|
KYTY_PROFILER_FUNCTION();
|
||||||
@@ -2385,16 +2382,18 @@ void RuntimeLinker::Relocate(Program* program) {
|
|||||||
EXIT_NOT_IMPLEMENTED(program->dynamic_info->symbol_table == nullptr);
|
EXIT_NOT_IMPLEMENTED(program->dynamic_info->symbol_table == nullptr);
|
||||||
EXIT_NOT_IMPLEMENTED(program->dynamic_info->pltgot_vaddr == 0);
|
EXIT_NOT_IMPLEMENTED(program->dynamic_info->pltgot_vaddr == 0);
|
||||||
|
|
||||||
|
if (program->custom_call_plt_vaddr == 0) {
|
||||||
InstallRelocateHandler(program);
|
InstallRelocateHandler(program);
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::string> unresolved;
|
std::vector<std::string> unresolved;
|
||||||
const bool imports_only = program->relocated;
|
const auto rela_count = static_cast<uint32_t>(
|
||||||
|
program->dynamic_info->rela_table_total_size / sizeof(Elf64_Rela));
|
||||||
|
|
||||||
RelocateRecords(program->dynamic_info->rela_table, program->dynamic_info->rela_table_total_size,
|
RelocateRecords(program->dynamic_info->rela_table, program->dynamic_info->rela_table_total_size,
|
||||||
program, false, imports_only, &unresolved);
|
program, false, 0, &unresolved);
|
||||||
RelocateRecords(program->dynamic_info->jmprela_table, program->dynamic_info->jmprela_table_size,
|
RelocateRecords(program->dynamic_info->jmprela_table, program->dynamic_info->jmprela_table_size,
|
||||||
program, true, imports_only, &unresolved);
|
program, true, rela_count, &unresolved);
|
||||||
program->relocated = true;
|
|
||||||
|
|
||||||
if (program->tls.image_vaddr != 0 && program->tls.init_size != 0 &&
|
if (program->tls.image_vaddr != 0 && program->tls.init_size != 0 &&
|
||||||
program->tls.init_image.empty()) {
|
program->tls.init_image.empty()) {
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ struct Program {
|
|||||||
ThreadLocalStorage tls;
|
ThreadLocalStorage tls;
|
||||||
bool fail_if_global_not_resolved = true;
|
bool fail_if_global_not_resolved = true;
|
||||||
bool dbg_print_reloc = false;
|
bool dbg_print_reloc = false;
|
||||||
bool relocated = false;
|
std::vector<uint8_t> rela_bits;
|
||||||
uint64_t proc_param_vaddr = 0;
|
uint64_t proc_param_vaddr = 0;
|
||||||
uint64_t custom_call_plt_vaddr = 0;
|
uint64_t custom_call_plt_vaddr = 0;
|
||||||
uint32_t custom_call_plt_num = 0;
|
uint32_t custom_call_plt_num = 0;
|
||||||
@@ -201,7 +201,6 @@ private:
|
|||||||
|
|
||||||
std::vector<Program*> m_programs;
|
std::vector<Program*> m_programs;
|
||||||
std::unique_ptr<SymbolDatabase> m_symbols;
|
std::unique_ptr<SymbolDatabase> m_symbols;
|
||||||
bool m_relocated = false;
|
|
||||||
Common::Mutex m_mutex;
|
Common::Mutex m_mutex;
|
||||||
|
|
||||||
application_heap_malloc_func_t m_application_heap_malloc = nullptr;
|
application_heap_malloc_func_t m_application_heap_malloc = nullptr;
|
||||||
|
|||||||
Reference in New Issue
Block a user