loader: consolidate eager symbol resolution and remove dead PLT machinery

This commit is contained in:
nmzik
2026-09-25 20:25:34 +04:00
parent 1371219f5c
commit e056d55dd5
3 changed files with 59 additions and 391 deletions
-47
View File
@@ -7,53 +7,6 @@ namespace Loader::Jit {
#pragma pack(1)
struct JmpWithIndex {
void SetIndex(uint32_t index) { *reinterpret_cast<uint32_t*>(&code[1]) = index; }
void SetFunc(void* handler) {
auto func_addr = reinterpret_cast<int64_t>(handler);
auto rip_addr = reinterpret_cast<int64_t>(&code[10]);
auto offset64 = func_addr - rip_addr;
auto offset32 = static_cast<uint32_t>(static_cast<uint64_t>(offset64) & 0xffffffffu);
*reinterpret_cast<uint32_t*>(&code[6]) = offset32;
}
static uint64_t GetSize() { return 16; }
// 68 00 00 00 00 push <index>
// E9 E0 FF FF FF jmp <handler>
uint8_t code[16] = {0x68, 0x00, 0x00, 0x00, 0x00, 0xE9, 0x00, 0x00,
0x00, 0x00, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
};
struct CallPlt {
explicit CallPlt(uint32_t table_size) {
for (uint32_t index = 0; index < table_size; index++) {
auto* c = new (&code[32] + JmpWithIndex::GetSize() * index) JmpWithIndex;
c->SetIndex(index);
c->SetFunc(this);
}
}
void SetPltGot(uint64_t vaddr) { *reinterpret_cast<uint64_t*>(&code[2]) = vaddr; }
uint64_t GetAddr(uint32_t index) {
return reinterpret_cast<uint64_t>(&code[32] + JmpWithIndex::GetSize() * index);
}
static uint64_t GetSize(uint32_t table_size) {
return 32 + JmpWithIndex::GetSize() * table_size;
}
// 0: 49 bb 88 77 66 55 44 movabs r11,0x1122334455667788
// 7: 33 22 11
// a: 41 ff 73 08 push QWORD PTR [r11+0x8]
// e: 41 ff 63 10 jmp QWORD PTR [r11+0x10]
uint8_t code[32] = {0x49, 0xBB, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x41, 0xFF,
0x73, 0x08, 0x41, 0xFF, 0x63, 0x10, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
};
struct JmpRax {
template <class Handler>
void SetFunc(Handler func) {
+59 -338
View File
@@ -126,19 +126,13 @@ struct StubbedImportRecord {
std::string program;
};
// The structure will be passed via the stack
// since the size of an object is larger than 16 bytes
struct RelocateHandlerStack {
uint64_t stack[3];
};
static std::vector<StubbedImportRecord> g_stubbed_imports;
static std::atomic_uint32_t g_unresolved_stub_call_log_count {0};
static std::vector<uint64_t> g_unresolved_stub_thunk_pages;
static uint64_t g_unresolved_stub_thunk_offset = 0;
static constexpr uint64_t UNRESOLVED_STUB_PAGE_SIZE = 4096;
static KYTY_SYSV_ABI uint64_t ResolveImportStubWithId(uint64_t record_id);
static KYTY_SYSV_ABI uint64_t UnresolvedImportStub(uint64_t record_id);
static bool PatchGuestMemory64(uint64_t vaddr, uint64_t value) {
auto* ptr = reinterpret_cast<uint64_t*>(vaddr);
@@ -148,7 +142,7 @@ static bool PatchGuestMemory64(uint64_t vaddr, uint64_t value) {
}
static uint64_t AllocateUnresolvedImportThunk(uint64_t record_id) {
constexpr uint64_t thunk_size = 165;
constexpr uint64_t thunk_size = 34;
if (g_unresolved_stub_thunk_pages.empty() ||
g_unresolved_stub_thunk_offset + thunk_size > UNRESOLVED_STUB_PAGE_SIZE) {
@@ -164,105 +158,18 @@ static uint64_t AllocateUnresolvedImportThunk(uint64_t record_id) {
g_unresolved_stub_thunk_offset);
g_unresolved_stub_thunk_offset += thunk_size;
const auto target = reinterpret_cast<uint64_t>(ResolveImportStubWithId);
uint8_t bytes[thunk_size] {};
size_t i = 0;
const auto emit = [&](uint8_t b) { bytes[i++] = b; };
const auto emit64 = [&](uint64_t v) {
std::memcpy(bytes + i, &v, sizeof(v));
i += sizeof(v);
uint8_t bytes[thunk_size] = {
0x48, 0x83, 0xec, 0x08, // sub rsp, 8
0x48, 0xbf, 0, 0, 0, 0, 0, 0, 0, 0, // mov rdi, record_id
0x48, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, // mov rax, UnresolvedImportStub
0xff, 0xd0, // call rax
0x48, 0x83, 0xc4, 0x08, // add rsp, 8
0x0f, 0x57, 0xc0, // xorps xmm0, xmm0
0xc3, // ret
};
const auto emit32 = [&](uint32_t v) {
std::memcpy(bytes + i, &v, sizeof(v));
i += sizeof(v);
};
const auto save_xmm = [&](uint8_t reg, uint8_t offset) {
emit(0xf3);
emit(0x0f);
emit(0x7f);
if (offset == 0) {
emit(static_cast<uint8_t>(0x04u | (reg << 3u)));
emit(0x24);
} else {
emit(static_cast<uint8_t>(0x44u | (reg << 3u)));
emit(0x24);
emit(offset);
}
};
const auto load_xmm = [&](uint8_t reg, uint8_t offset) {
emit(0xf3);
emit(0x0f);
emit(0x6f);
if (offset == 0) {
emit(static_cast<uint8_t>(0x04u | (reg << 3u)));
emit(0x24);
} else {
emit(static_cast<uint8_t>(0x44u | (reg << 3u)));
emit(0x24);
emit(offset);
}
};
emit(0x50); // push rax; preserve AL for variadic SysV calls
emit(0x57); // push rdi
emit(0x56); // push rsi
emit(0x52); // push rdx
emit(0x51); // push rcx
emit(0x41);
emit(0x50); // push r8
emit(0x41);
emit(0x51); // push r9
emit(0x48);
emit(0x81);
emit(0xec);
emit32(0x80); // sub rsp, 0x80
for (uint8_t reg = 0; reg < 8; reg++) {
save_xmm(reg, static_cast<uint8_t>(reg * 0x10u));
}
emit(0x48);
emit(0xbf);
emit64(record_id); // mov rdi, record_id
emit(0x48);
emit(0xb8);
emit64(target); // mov rax, ResolveImportStubWithId
emit(0xff);
emit(0xd0); // call rax
emit(0x49);
emit(0x89);
emit(0xc3); // mov r11, rax
for (uint8_t reg = 0; reg < 8; reg++) {
load_xmm(reg, static_cast<uint8_t>(reg * 0x10u));
}
emit(0x48);
emit(0x81);
emit(0xc4);
emit32(0x80); // add rsp, 0x80
emit(0x41);
emit(0x59); // pop r9
emit(0x41);
emit(0x58); // pop r8
emit(0x59); // pop rcx
emit(0x5a); // pop rdx
emit(0x5e); // pop rsi
emit(0x5f); // pop rdi
emit(0x58); // pop rax
emit(0x4d);
emit(0x85);
emit(0xdb); // test r11, r11
emit(0x74);
emit(0x03); // jz +3
emit(0x41);
emit(0xff);
emit(0xe3); // jmp r11
// Match the integer fallback for floating-point return values.
emit(0x0f);
emit(0x57);
emit(0xc0); // xorps xmm0, xmm0
emit(0x31);
emit(0xc0); // xor eax, eax
emit(0xc3); // ret
EXIT_NOT_IMPLEMENTED(i != thunk_size);
const auto target = reinterpret_cast<uint64_t>(UnresolvedImportStub);
std::memcpy(bytes + 6, &record_id, sizeof(record_id));
std::memcpy(bytes + 16, &target, sizeof(target));
std::memcpy(code, bytes, sizeof(bytes));
Common::VirtualMemory::FlushInstructionCache(reinterpret_cast<uint64_t>(code), thunk_size);
return reinterpret_cast<uint64_t>(code);
@@ -270,15 +177,8 @@ static uint64_t AllocateUnresolvedImportThunk(uint64_t record_id) {
static uint64_t RegisterStubbedImport(uint32_t index, const Program* program,
const RelocationInfo& ri) {
const auto program_name = program != nullptr ? Common::PathToString(program->file_name) : "";
for (auto& record: g_stubbed_imports) {
for (const auto& record: g_stubbed_imports) {
if (record.patch_vaddr == ri.vaddr) {
record.index = index;
record.name = ri.name;
record.type = ri.type;
record.bind = ri.bind;
record.program = program_name;
return record.thunk_vaddr;
}
}
@@ -289,7 +189,7 @@ static uint64_t RegisterStubbedImport(uint32_t index, const Program* program,
record.name = ri.name;
record.type = ri.type;
record.bind = ri.bind;
record.program = program_name;
record.program = Common::PathToString(program->file_name);
g_stubbed_imports.push_back(record);
const auto record_id = g_stubbed_imports.size() - 1;
const auto thunk = AllocateUnresolvedImportThunk(record_id);
@@ -297,31 +197,7 @@ static uint64_t RegisterStubbedImport(uint32_t index, const Program* program,
return thunk;
}
static KYTY_SYSV_ABI uint64_t ResolveImportStubWithId(uint64_t record_id) {
if (record_id < g_stubbed_imports.size()) {
auto& record = g_stubbed_imports[record_id];
auto nid = record.name;
auto pos = nid.find('[');
if (pos != std::string::npos) {
nid.resize(pos);
}
SymbolRecord resolved {};
if (!nid.empty() &&
Common::Singleton<RuntimeLinker>::Instance()->ResolveLoadedSymbolByNid(nid, record.type,
&resolved) &&
resolved.vaddr != 0 && resolved.vaddr != record.thunk_vaddr) {
LOGF("Late-resolved import: %s -> %s [0x%016" PRIx64 "]\n", record.name.c_str(),
resolved.name.c_str(), resolved.vaddr);
if (record.patch_vaddr != 0) {
PatchGuestMemory64(record.patch_vaddr, resolved.vaddr);
}
return resolved.vaddr;
}
}
static KYTY_SYSV_ABI uint64_t UnresolvedImportStub(uint64_t record_id) {
const auto log_index = g_unresolved_stub_call_log_count.fetch_add(1);
if (log_index < 1024) {
if (record_id < g_stubbed_imports.size()) {
@@ -1008,97 +884,50 @@ static RelocationInfo GetRelocationInfo(Elf64_Rela* r, Program* program) {
}
static bool RelocateRecord(uint32_t index, Elf64_Rela* r, Program* program, bool jmprela_table,
std::vector<std::string>* unresolved) {
std::vector<std::string>& unresolved) {
KYTY_PROFILER_FUNCTION();
auto ri = GetRelocationInfo(r, program);
[[maybe_unused]] bool patched = false;
bool stubbed_import = false;
bool stubbed_func = false;
// KYTY_PROFILER_BLOCK("patch");
if (ri.resolved) {
patched = PatchGuestMemory64(ri.vaddr, ri.value);
} else {
uint64_t value = 0;
bool weak = (ri.bind == BindType::Weak || !program->fail_if_global_not_resolved);
if (ri.type == SymbolType::Object && weak) {
const auto ri = GetRelocationInfo(r, program);
auto value = ri.value;
bool stubbed = false;
if (!ri.resolved) {
const bool weak = ri.bind == BindType::Weak || !program->fail_if_global_not_resolved;
if (!weak) {
unresolved.push_back(fmt::format("[{:016x}] <- {:016x}, {}, {}, {}, {}", ri.vaddr,
ri.value, ri.name, magic_enum::enum_name(ri.type),
magic_enum::enum_name(ri.bind), ri.dbg_name));
}
if (ri.type == SymbolType::Object) {
value = g_invalid_memory;
} else if (ri.type == SymbolType::Func && jmprela_table && weak) {
value = RegisterStubbedImport(index, program, ri);
stubbed_import = true;
stubbed_func = true;
} else if (ri.type == SymbolType::Func && !jmprela_table && weak) {
value = RegisterStubbedImport(index, program, ri);
stubbed_func = true;
} else if (ri.type == SymbolType::NoType && weak) {
value = RuntimeLinker::ReadFromElf(program, ri.vaddr) + ri.base_vaddr;
}
if (value != 0) {
patched = PatchGuestMemory64(ri.vaddr, value);
} else {
auto dbg_str = fmt::format("[{:016x}] <- {:016x}, {}, {}, {}, {}", ri.vaddr, ri.value,
ri.name.c_str(), magic_enum::enum_name(ri.type),
magic_enum::enum_name(ri.bind), ri.dbg_name.c_str());
if (unresolved != nullptr) {
unresolved->push_back(dbg_str);
} else {
EXIT("Can't resolve: %s\n", dbg_str.c_str());
}
if (ri.type == SymbolType::Object) {
value = g_invalid_memory;
} else if (ri.type == SymbolType::Func || ri.type == SymbolType::NoType) {
value = RegisterStubbedImport(index, program, ri);
stubbed_func = true;
if (jmprela_table) {
stubbed_import = true;
}
}
if (value != 0) {
patched = PatchGuestMemory64(ri.vaddr, value);
}
value = RegisterStubbedImport(index, program, ri);
stubbed = true;
}
}
// KYTY_PROFILER_END_BLOCK;
if (patched && stubbed_import) {
const auto thunk = RegisterStubbedImport(index, program, ri);
LOGF("Relocate: unresolved PLT import patched to stub [%u] [%016" PRIx64 "] <- %016" PRIx64
const bool patched = PatchGuestMemory64(ri.vaddr, value);
if (patched && stubbed) {
LOGF("Relocate: unresolved %s import patched to stub [%u] [%016" PRIx64 "] <- %016" PRIx64
", %s, %s, %s, %s\n",
index, ri.vaddr, thunk, ri.name.c_str(), magic_enum::enum_name(ri.type),
magic_enum::enum_name(ri.bind), Common::PathToString(program->file_name).c_str());
} else if (patched && stubbed_func) {
const auto thunk = RegisterStubbedImport(index, program, ri);
LOGF("Relocate: unresolved non-PLT function patched to stub [%u] [%016" PRIx64
"] <- %016" PRIx64 ", %s, %s, %s, %s\n",
index, ri.vaddr, thunk, ri.name.c_str(), magic_enum::enum_name(ri.type),
magic_enum::enum_name(ri.bind), Common::PathToString(program->file_name).c_str());
jmprela_table ? "PLT" : "non-PLT", index, ri.vaddr, value, ri.name.c_str(),
magic_enum::enum_name(ri.type), magic_enum::enum_name(ri.bind),
Common::PathToString(program->file_name).c_str());
}
if (program->dbg_print_reloc) {
if (patched && !ri.bind_self &&
(ri.bind == BindType::Global || ri.bind == BindType::Weak ||
ri.type == SymbolType::TlsModule)) {
auto dbg_str = fmt::format("[{:016x}] <- {:016x}, {}, {}, {}, {}", ri.vaddr, ri.value,
ri.name.c_str(), magic_enum::enum_name(ri.type),
magic_enum::enum_name(ri.bind), ri.dbg_name.c_str());
LOGF("Relocate: %s\n", dbg_str.c_str());
}
if (program->dbg_print_reloc && patched && !ri.bind_self &&
(ri.bind == BindType::Global || ri.bind == BindType::Weak ||
ri.type == SymbolType::TlsModule)) {
LOGF("Relocate: %s\n",
fmt::format("[{:016x}] <- {:016x}, {}, {}, {}, {}", ri.vaddr, ri.value, ri.name,
magic_enum::enum_name(ri.type), magic_enum::enum_name(ri.bind),
ri.dbg_name).c_str());
}
return ri.resolved;
}
static void RelocateRecords(Elf64_Rela* records, uint64_t size, Program* program,
bool jmprela_table, uint32_t bit_base,
std::vector<std::string>* unresolved) {
std::vector<std::string>& unresolved) {
KYTY_PROFILER_FUNCTION();
uint32_t index = 0;
@@ -1113,32 +942,6 @@ static void RelocateRecords(Elf64_Rela* records, uint64_t size, Program* program
}
}
__attribute__((naked)) static KYTY_SYSV_ABI void RelocateHandlerReturnStub() {
asm volatile("addq $8, %rsp\n\t"
"retq\n");
}
static KYTY_SYSV_ABI uint64_t RelocateHandler(RelocateHandlerStack s) {
auto* stack = s.stack;
auto* program = reinterpret_cast<Program*>(stack[-1]);
auto rel_index = stack[0];
std::string name = "<unknown function>";
if (program != nullptr && program->dynamic_info != nullptr &&
program->dynamic_info->jmprela_table != nullptr) {
auto ri = GetRelocationInfo(program->dynamic_info->jmprela_table + rel_index, program);
name = ri.name.c_str();
}
// Restore return address (for stack trace)
stack[-1] = reinterpret_cast<uint64_t>(RelocateHandlerReturnStub);
LOGF("=== Stubbed function, returning OK ===\n[%d]\t%s\n", Common::Thread::GetThreadIdUnique(),
name.c_str());
return 0;
}
static KYTY_MS_ABI uint8_t* TlsMainGetAddr() {
EXIT_IF(g_tls_main_program == nullptr);
@@ -1553,10 +1356,20 @@ void RuntimeLinker::Resolve(const std::string& name, SymbolType type, Program* p
}
if (rec == nullptr) {
if (auto* p = FindProgram(*m, *l); p != nullptr && p->export_symbols != nullptr) {
for (auto* p: m_programs) {
const auto& libs = p->dynamic_info->export_libs;
const auto& modules = p->dynamic_info->export_modules;
if (p->export_symbols == nullptr ||
std::find(libs.begin(), libs.end(), *l) == libs.end() ||
std::find(modules.begin(), modules.end(), *m) == modules.end()) {
continue;
}
rec = p->export_symbols->Find(sr);
if (bind_self != nullptr) {
*bind_self = (p == program);
if (rec != nullptr) {
if (bind_self != nullptr) {
*bind_self = (p == program);
}
break;
}
}
}
@@ -1569,7 +1382,6 @@ void RuntimeLinker::Resolve(const std::string& name, SymbolType type, Program* p
}
if (rec != nullptr) {
//*out_vaddr = rec->vaddr;
*out_info = *rec;
} else {
out_info->vaddr = 0;
@@ -1592,33 +1404,6 @@ void RuntimeLinker::Resolve(const std::string& name, SymbolType type, Program* p
}
}
bool RuntimeLinker::ResolveLoadedSymbolByNid(const std::string& nid, SymbolType type,
SymbolRecord* out_info) {
KYTY_PROFILER_FUNCTION();
Common::LockGuard lock(m_mutex);
EXIT_IF(out_info == nullptr);
for (auto* p: m_programs) {
if (p != nullptr && p->export_symbols != nullptr) {
if (const auto* rec = p->export_symbols->FindByNid(nid, type); rec != nullptr) {
*out_info = *rec;
return true;
}
}
}
if (m_symbols != nullptr) {
if (const auto* rec = m_symbols->FindByNid(nid, type); rec != nullptr) {
*out_info = *rec;
return true;
}
}
return false;
}
uint64_t RuntimeLinker::ReadFromElf(Program* program, uint64_t vaddr) {
EXIT_IF(program == nullptr);
EXIT_IF(program->base_vaddr == 0 || program->base_size == 0);
@@ -2202,11 +1987,6 @@ void RuntimeLinker::DeleteProgram(Program* p) {
EXIT_IF(
!Libs::LibKernel::Memory::FreeGuestMemory(program->base_vaddr, program->mapped_size));
}
if (program->custom_call_plt_vaddr != 0 || program->custom_call_plt_num != 0) {
const auto size = Jit::CallPlt::GetSize(program->custom_call_plt_num);
EXIT_IF(!Libs::LibKernel::Memory::FreeGuestMemory(program->custom_call_plt_vaddr, size));
}
}
void RuntimeLinker::ParseProgramDynamicInfo(Program* program) {
@@ -2249,10 +2029,6 @@ void RuntimeLinker::ParseProgramDynamicInfo(Program* program) {
GetDynValue(elf, &program->dynamic_info->fini_array_size, DT_FINI_ARRAYSZ);
GetDynValue(elf, &program->dynamic_info->preinit_array_size, DT_PREINIT_ARRAYSZ);
EXIT_NOT_IMPLEMENTED(elf->HasDynValue(DT_OS_PLTGOT) && elf->HasDynValue(DT_PLTGOT));
GetDynPtr(elf, &program->dynamic_info->pltgot_vaddr, DT_OS_PLTGOT);
GetDynPtr(elf, &program->dynamic_info->pltgot_vaddr, DT_PLTGOT);
Elf64_Sxword jmprel_type = 0;
EXIT_NOT_IMPLEMENTED(elf->HasDynValue(DT_OS_PLTREL) && elf->HasDynValue(DT_PLTREL));
GetDynValue(elf, &jmprel_type, DT_OS_PLTREL);
@@ -2326,41 +2102,6 @@ void RuntimeLinker::ParseProgramDynamicInfo(Program* program) {
DT_OS_EXPORT_LIB_1);
}
static void InstallRelocateHandler(Program* program) {
KYTY_PROFILER_FUNCTION();
uint64_t pltgot_vaddr = program->dynamic_info->pltgot_vaddr + program->base_vaddr;
uint64_t pltgot_size = static_cast<uint64_t>(3) * 8;
void** pltgot = reinterpret_cast<void**>(pltgot_vaddr);
Common::VirtualMemory::Mode old_mode {};
EXIT_IF(!Libs::LibKernel::Memory::ProtectGuestMemory(
pltgot_vaddr, pltgot_size, Common::VirtualMemory::Mode::Write, &old_mode));
pltgot[1] = program;
pltgot[2] = reinterpret_cast<void*>(RelocateHandler);
EXIT_IF(!Libs::LibKernel::Memory::ProtectGuestMemory(pltgot_vaddr, pltgot_size, old_mode));
if (Common::VirtualMemory::IsExecute(old_mode)) {
Common::VirtualMemory::FlushInstructionCache(pltgot_vaddr, pltgot_size);
}
// TODO(): check if this table already generated by compiler (sometimes it is missing)
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<void*>(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) {
KYTY_PROFILER_FUNCTION();
@@ -2380,20 +2121,15 @@ void RuntimeLinker::Relocate(Program* program) {
EXIT_NOT_IMPLEMENTED(program->dynamic_info->jmprela_table == nullptr);
EXIT_NOT_IMPLEMENTED(program->dynamic_info->rela_table == nullptr);
EXIT_NOT_IMPLEMENTED(program->dynamic_info->symbol_table == nullptr);
EXIT_NOT_IMPLEMENTED(program->dynamic_info->pltgot_vaddr == 0);
if (program->custom_call_plt_vaddr == 0) {
InstallRelocateHandler(program);
}
std::vector<std::string> unresolved;
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,
program, false, 0, &unresolved);
program, false, 0, unresolved);
RelocateRecords(program->dynamic_info->jmprela_table, program->dynamic_info->jmprela_table_size,
program, true, rela_count, &unresolved);
program, true, rela_count, unresolved);
if (program->tls.image_vaddr != 0 && program->tls.init_size != 0 &&
program->tls.init_image.empty()) {
@@ -2409,21 +2145,6 @@ void RuntimeLinker::Relocate(Program* program) {
}
}
Program* RuntimeLinker::FindProgram(const ModuleId& m, const LibraryId& l) {
Common::LockGuard lock(m_mutex);
for (auto* p: m_programs) {
const auto& export_libs = p->dynamic_info->export_libs;
const auto& export_modules = p->dynamic_info->export_modules;
if (std::find(export_libs.begin(), export_libs.end(), l) != export_libs.end() &&
std::find(export_modules.begin(), export_modules.end(), m) != export_modules.end()) {
return p;
}
}
return nullptr;
}
const ModuleId* RuntimeLinker::FindModule(const Program& program, const std::string& id) {
const auto& import_modules = program.dynamic_info->import_modules;
-6
View File
@@ -86,7 +86,6 @@ struct DynamicInfo {
uint64_t init_array_size = 0;
uint64_t fini_array_size = 0;
uint64_t preinit_array_size = 0;
uint64_t pltgot_vaddr = 0;
Elf64_Rela* jmprela_table = nullptr;
uint64_t jmprela_table_size = 0;
@@ -134,8 +133,6 @@ struct Program {
bool dbg_print_reloc = false;
std::vector<uint8_t> rela_bits;
uint64_t proc_param_vaddr = 0;
uint64_t custom_call_plt_vaddr = 0;
uint32_t custom_call_plt_num = 0;
};
class RuntimeLinker {
@@ -171,7 +168,6 @@ public:
void Resolve(const std::string& name, SymbolType type, Program* program, SymbolRecord* out_info,
bool* bind_self);
bool ResolveLoadedSymbolByNid(const std::string& nid, SymbolType type, SymbolRecord* out_info);
SymbolDatabase* Symbols() { return m_symbols.get(); }
@@ -194,8 +190,6 @@ private:
static void SetupTlsHandler(Program* program);
void PreloadAdjacentPrograms();
Program* FindProgram(const ModuleId& m, const LibraryId& l);
static const ModuleId* FindModule(const Program& program, const std::string& id);
static const LibraryId* FindLibrary(const Program& program, const std::string& id);