1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 09:38:11 +00:00

Loader: Support loading non-position independent executables

This commit is contained in:
Itamar 2020-12-18 15:59:22 +02:00 committed by Andreas Kling
parent 0cb636078a
commit a83a9f3a55
5 changed files with 88 additions and 41 deletions

View file

@ -144,9 +144,10 @@ void* DynamicLoader::symbol_for_name(const char* name)
RefPtr<DynamicObject> DynamicLoader::load_from_image(unsigned flags, size_t total_tls_size)
{
m_valid = m_elf_image.is_valid() && m_elf_image.is_dynamic();
m_valid = m_elf_image.is_valid();
if (!m_valid) {
dbgprintf("DynamicLoader::load_from_image failed: image is invalid\n");
return nullptr;
}
@ -163,8 +164,10 @@ RefPtr<DynamicObject> DynamicLoader::load_from_image(unsigned flags, size_t tota
m_dynamic_object->m_global_symbol_lookup_func = m_global_symbol_lookup_func;
auto rc = load_stage_2(flags, total_tls_size);
if (!rc)
if (!rc) {
dbgprintf("DynamicLoader::load_from_image failed at load_stage_2\n");
return nullptr;
}
return m_dynamic_object;
}
@ -235,7 +238,9 @@ void DynamicLoader::load_program_headers()
// Process regions in order: .text, .data, .tls
auto* region = text_region_ptr;
void* text_segment_begin = mmap_with_name(nullptr,
void* requested_load_address = m_elf_image.is_dynamic() ? nullptr : region->desired_load_address().as_ptr();
void* text_segment_begin = mmap_with_name(
requested_load_address,
region->required_load_size(),
region->mmap_prot(),
MAP_PRIVATE,
@ -245,13 +250,18 @@ void DynamicLoader::load_program_headers()
if (MAP_FAILED == text_segment_begin) {
ASSERT_NOT_REACHED();
}
ASSERT(requested_load_address == nullptr || requested_load_address == text_segment_begin);
m_text_segment_size = region->required_load_size();
m_text_segment_load_address = VirtualAddress { (FlatPtr)text_segment_begin };
m_dynamic_section_address = dynamic_region_desired_vaddr.offset(m_text_segment_load_address.get());
if (m_elf_image.is_dynamic())
m_dynamic_section_address = dynamic_region_desired_vaddr.offset(m_text_segment_load_address.get());
else
m_dynamic_section_address = dynamic_region_desired_vaddr;
region = data_region_ptr;
void* data_segment_begin = mmap_with_name((u8*)text_segment_begin + m_text_segment_size,
void* data_segment_begin = mmap_with_name(
(u8*)text_segment_begin + m_text_segment_size,
region->required_load_size(),
region->mmap_prot(),
MAP_ANONYMOUS | MAP_PRIVATE,
@ -261,10 +271,14 @@ void DynamicLoader::load_program_headers()
if (MAP_FAILED == data_segment_begin) {
ASSERT_NOT_REACHED();
}
VirtualAddress data_segment_actual_addr = region->desired_load_address().offset((FlatPtr)text_segment_begin);
VirtualAddress data_segment_actual_addr;
if (m_elf_image.is_dynamic()) {
data_segment_actual_addr = region->desired_load_address().offset((FlatPtr)text_segment_begin);
} else {
data_segment_actual_addr = region->desired_load_address();
}
memcpy(data_segment_actual_addr.as_ptr(), (u8*)m_file_mapping + region->offset(), region->size_in_image());
// FIXME: Initialize the values in the TLS section. Currently, it will always be zeroed.
// FIXME: Initialize the values in the TLS section. Currently, it is zeroed.
}
void DynamicLoader::do_relocations(size_t total_tls_size)
@ -272,7 +286,12 @@ void DynamicLoader::do_relocations(size_t total_tls_size)
auto main_relocation_section = m_dynamic_object->relocation_section();
main_relocation_section.for_each_relocation([&](ELF::DynamicObject::Relocation relocation) {
VERBOSE("Relocation symbol: %s, type: %d\n", relocation.symbol().name(), relocation.type());
u32* patch_ptr = (u32*)(m_dynamic_object->base_address().as_ptr() + relocation.offset());
FlatPtr* patch_ptr = nullptr;
if (is_dynamic())
patch_ptr = (FlatPtr*)(m_dynamic_object->base_address().as_ptr() + relocation.offset());
else
patch_ptr = (FlatPtr*)(FlatPtr)relocation.offset();
// VERBOSE("dynamic object name: %s\n", dynamic_object.object_name());
VERBOSE("dynamic object base address: %p\n", m_dynamic_object->base_address());
VERBOSE("relocation offset: 0x%x\n", relocation.offset());
@ -393,13 +412,12 @@ void DynamicLoader::do_relocations(size_t total_tls_size)
VERBOSE("patching plt reloaction: 0x%x\n", relocation.offset_in_section());
[[maybe_unused]] auto rc = m_dynamic_object->patch_plt_entry(relocation.offset_in_section());
} else {
// LAZY-ily bind the PLT slots by just adding the base address to the offsets stored there
// This avoids doing symbol lookup, which might be expensive
ASSERT(relocation.type() == R_386_JMP_SLOT);
u8* relocation_address = relocation.address().as_ptr();
*(u32*)relocation_address += (FlatPtr)m_dynamic_object->base_address().as_ptr();
if (m_elf_image.is_dynamic())
*(u32*)relocation_address += (FlatPtr)m_dynamic_object->base_address().as_ptr();
}
return IterationDecision::Continue;
});