diff --git a/src/loader/runtimeLinker.cpp b/src/loader/runtimeLinker.cpp index a1eed6d1f..e90c016e3 100644 --- a/src/loader/runtimeLinker.cpp +++ b/src/loader/runtimeLinker.cpp @@ -1007,17 +1007,12 @@ static RelocationInfo GetRelocationInfo(Elf64_Rela* r, Program* program) { return ret; } -static void RelocateRecord(uint32_t index, Elf64_Rela* r, Program* program, bool jmprela_table, - bool imports_only, std::vector* unresolved) { +static bool RelocateRecord(uint32_t index, Elf64_Rela* r, Program* program, bool jmprela_table, + std::vector* unresolved) { KYTY_PROFILER_FUNCTION(); 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; bool stubbed_import = 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()); } } + return ri.resolved; } 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* unresolved) { KYTY_PROFILER_FUNCTION(); uint32_t index = 0; for (auto* r = records; reinterpret_cast(r) < reinterpret_cast(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) { Relocate(p); } - - m_relocated = true; } void RuntimeLinker::RelocateProgram(Program* program) { @@ -1342,10 +1341,6 @@ void RuntimeLinker::UnloadProgram(Program* program) { } else { EXIT("program not found"); } - - if (m_relocated) { - RelocateAll(); - } } RuntimeLinker::RuntimeLinker(): m_symbols(std::make_unique()) { @@ -1499,7 +1494,6 @@ void RuntimeLinker::Clear() { g_tls_cached_main_tcb = nullptr; g_desired_base_addr = SYSTEM_RESERVED + CODE_BASE_OFFSET; m_symbols.reset(); - m_relocated = false; } 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_entry_size, DT_OS_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); @@ -2348,20 +2347,18 @@ static void InstallRelocateHandler(Program* program) { } // 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->dynamic_info->jmprela_table_size / sizeof(Elf64_Rela); - auto size = Jit::CallPlt::GetSize(program->custom_call_plt_num); - program->custom_call_plt_vaddr = Libs::LibKernel::Memory::AllocateRuntimeMemory( - SYSTEM_RESERVED, size, Common::VirtualMemory::Mode::Write, "custom_call_plt"); - EXIT_NOT_IMPLEMENTED(program->custom_call_plt_vaddr == 0); - auto* code = new (reinterpret_cast(program->custom_call_plt_vaddr)) - Jit::CallPlt(program->custom_call_plt_num); - code->SetPltGot(pltgot_vaddr); - EXIT_IF(!Libs::LibKernel::Memory::ProtectGuestMemory(program->custom_call_plt_vaddr, size, - Common::VirtualMemory::Mode::Execute)); - Common::VirtualMemory::FlushInstructionCache(program->custom_call_plt_vaddr, size); - } + program->custom_call_plt_num = + program->dynamic_info->jmprela_table_size / sizeof(Elf64_Rela); + auto size = Jit::CallPlt::GetSize(program->custom_call_plt_num); + program->custom_call_plt_vaddr = Libs::LibKernel::Memory::AllocateRuntimeMemory( + SYSTEM_RESERVED, size, Common::VirtualMemory::Mode::Write, "custom_call_plt"); + EXIT_NOT_IMPLEMENTED(program->custom_call_plt_vaddr == 0); + auto* code = new (reinterpret_cast(program->custom_call_plt_vaddr)) + Jit::CallPlt(program->custom_call_plt_num); + code->SetPltGot(pltgot_vaddr); + EXIT_IF(!Libs::LibKernel::Memory::ProtectGuestMemory(program->custom_call_plt_vaddr, size, + Common::VirtualMemory::Mode::Execute)); + Common::VirtualMemory::FlushInstructionCache(program->custom_call_plt_vaddr, size); } void RuntimeLinker::Relocate(Program* program) { @@ -2385,16 +2382,18 @@ void RuntimeLinker::Relocate(Program* program) { EXIT_NOT_IMPLEMENTED(program->dynamic_info->symbol_table == nullptr); EXIT_NOT_IMPLEMENTED(program->dynamic_info->pltgot_vaddr == 0); - InstallRelocateHandler(program); + if (program->custom_call_plt_vaddr == 0) { + InstallRelocateHandler(program); + } std::vector unresolved; - const bool imports_only = program->relocated; + const auto rela_count = static_cast( + program->dynamic_info->rela_table_total_size / sizeof(Elf64_Rela)); 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, - program, true, imports_only, &unresolved); - program->relocated = true; + program, true, rela_count, &unresolved); if (program->tls.image_vaddr != 0 && program->tls.init_size != 0 && program->tls.init_image.empty()) { diff --git a/src/loader/runtimeLinker.h b/src/loader/runtimeLinker.h index dfec7abfb..69b25bf81 100644 --- a/src/loader/runtimeLinker.h +++ b/src/loader/runtimeLinker.h @@ -132,7 +132,7 @@ struct Program { ThreadLocalStorage tls; bool fail_if_global_not_resolved = true; bool dbg_print_reloc = false; - bool relocated = false; + std::vector rela_bits; uint64_t proc_param_vaddr = 0; uint64_t custom_call_plt_vaddr = 0; uint32_t custom_call_plt_num = 0; @@ -201,7 +201,6 @@ private: std::vector m_programs; std::unique_ptr m_symbols; - bool m_relocated = false; Common::Mutex m_mutex; application_heap_malloc_func_t m_application_heap_malloc = nullptr;