diff --git a/Libraries/LibELF/ELFDynamicLoader.cpp b/Libraries/LibELF/ELFDynamicLoader.cpp index 2a6dcb0780..c6b463d34e 100644 --- a/Libraries/LibELF/ELFDynamicLoader.cpp +++ b/Libraries/LibELF/ELFDynamicLoader.cpp @@ -32,7 +32,8 @@ ELFDynamicLoader::ELFDynamicLoader(const char* filename, int fd, size_t size) { String file_mmap_name = String::format("ELF_DYN: %s", m_filename.characters()); - m_file_mapping = mmap_with_name(nullptr, size, PROT_READ, MAP_PRIVATE, m_image_fd, 0, file_mmap_name.characters()); + // FIXME: When MAP_PRIVATE is implemented for file-backed regions, change to MAP_PRIVATE + m_file_mapping = mmap_with_name(nullptr, size, PROT_READ, MAP_SHARED, m_image_fd, 0, file_mmap_name.characters()); if (MAP_FAILED == m_file_mapping) { m_valid = false; } @@ -64,20 +65,13 @@ bool ELFDynamicLoader::load_from_image(unsigned flags) return false; } - const ELFImage::DynamicSection probably_dynamic_section = elf_image.dynamic_section(); - if (StringView(".dynamic") != probably_dynamic_section.name() || probably_dynamic_section.type() != SHT_DYNAMIC) { - m_valid = false; - return false; - } - #ifdef DYNAMIC_LOAD_VERBOSE m_image->dump(); #endif load_program_headers(elf_image); - const ELFImage::DynamicSection image_dynamic_section = elf_image.dynamic_section(); - m_dynamic_object = AK::make(m_text_segment_load_address, image_dynamic_section.offset()); + m_dynamic_object = AK::make(m_text_segment_load_address, m_dynamic_section_address); return load_stage_2(flags); } @@ -94,7 +88,7 @@ bool ELFDynamicLoader::load_stage_2(unsigned flags) if (m_dynamic_object->has_text_relocations()) { ASSERT(m_text_segment_load_address.get() != 0); if (0 > mprotect(m_text_segment_load_address.as_ptr(), m_text_segment_size, PROT_READ | PROT_WRITE)) { - perror("mprotect"); // FIXME: dlerror? + perror("mprotect .text: PROT_READ | PROT_WRITE"); // FIXME: dlerror? return false; } } @@ -105,7 +99,7 @@ bool ELFDynamicLoader::load_stage_2(unsigned flags) // Clean up our setting of .text to PROT_READ | PROT_WRITE if (m_dynamic_object->has_text_relocations()) { if (0 > mprotect(m_text_segment_load_address.as_ptr(), m_text_segment_size, PROT_READ | PROT_EXEC)) { - perror("mprotect"); // FIXME: dlerror? + perror("mprotect .text: PROT_READ | PROT_EXEC"); // FIXME: dlerror? return false; } } @@ -127,6 +121,7 @@ void ELFDynamicLoader::load_program_headers(const ELFImage& elf_image) ProgramHeaderRegion* text_region_ptr = nullptr; ProgramHeaderRegion* data_region_ptr = nullptr; ProgramHeaderRegion* tls_region_ptr = nullptr; + VirtualAddress dynamic_region_desired_vaddr; elf_image.for_each_program_header([&](const ELFImage::ProgramHeader& program_header) { ProgramHeaderRegion new_region; @@ -143,18 +138,30 @@ void ELFDynamicLoader::load_program_headers(const ELFImage& elf_image) else data_region_ptr = ®ion; } + else if (region.is_dynamic()) { + dynamic_region_desired_vaddr = region.desired_load_address(); + } }); ASSERT(text_region_ptr && data_region_ptr); // Process regions in order: .text, .data, .tls auto* region = text_region_ptr; - void* text_segment_begin = mmap_with_name(nullptr, region->required_load_size(), region->mmap_prot(), MAP_PRIVATE, m_image_fd, region->offset(), String::format(".text: %s", m_filename.characters()).characters()); + // FIXME: When MAP_PRIVATE is implemented for file-backed regions, change to MAP_PRIVATE without the mprotect and memcpy + //void* text_segment_begin = mmap_with_name(nullptr, region->required_load_size(), region->mmap_prot(), MAP_PRIVATE, m_image_fd, region->offset(), String::format(".text: %s", m_filename.characters()).characters()); + void* text_segment_begin = mmap_with_name(nullptr, region->required_load_size(), PROT_READ | PROT_WRITE , MAP_ANONYMOUS | MAP_PRIVATE, 0, 0, String::format(".text: %s", m_filename.characters()).characters()); if (MAP_FAILED == text_segment_begin) { ASSERT_NOT_REACHED(); } m_text_segment_size = region->required_load_size(); m_text_segment_load_address = VirtualAddress { (u32)text_segment_begin }; + memcpy(m_text_segment_load_address.as_ptr(), (u8*)m_file_mapping + region->offset(), region->size_in_image()); + if (0 > mprotect(text_segment_begin, m_text_segment_size, region->mmap_prot())) { + perror("mprotect .text PROT_READ | PROT_EXEC"); + ASSERT_NOT_REACHED(); + } + + m_dynamic_section_address = dynamic_region_desired_vaddr.offset(m_text_segment_load_address.get()); region = data_region_ptr; 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, 0, 0, String::format(".data: %s", m_filename.characters()).characters()); diff --git a/Libraries/LibELF/ELFDynamicLoader.h b/Libraries/LibELF/ELFDynamicLoader.h index 4fb5e1d32c..81fa0f384d 100644 --- a/Libraries/LibELF/ELFDynamicLoader.h +++ b/Libraries/LibELF/ELFDynamicLoader.h @@ -86,4 +86,5 @@ private: size_t m_text_segment_size; VirtualAddress m_tls_segment_address; + VirtualAddress m_dynamic_section_address; }; diff --git a/Libraries/LibELF/ELFDynamicObject.cpp b/Libraries/LibELF/ELFDynamicObject.cpp index ef2ffbef40..3f073a489d 100644 --- a/Libraries/LibELF/ELFDynamicObject.cpp +++ b/Libraries/LibELF/ELFDynamicObject.cpp @@ -8,9 +8,9 @@ static const char* name_for_dtag(Elf32_Sword d_tag); -ELFDynamicObject::ELFDynamicObject(VirtualAddress base_address, u32 dynamic_offset) +ELFDynamicObject::ELFDynamicObject(VirtualAddress base_address, VirtualAddress dynamic_section_addresss) : m_base_address(base_address) - , m_dynamic_offset(dynamic_offset) + , m_dynamic_address(dynamic_section_addresss) { parse(); } @@ -32,7 +32,7 @@ void ELFDynamicObject::dump() const return IterationDecision::Continue; }); - dbgprintf("Dynamic section at offset 0x%x contains %zu entries:\n", m_dynamic_offset, num_dynamic_sections); + dbgprintf("Dynamic section at address 0x%x contains %zu entries:\n", m_dynamic_address.as_ptr(), num_dynamic_sections); dbgprintf(builder.to_string().characters()); } diff --git a/Libraries/LibELF/ELFDynamicObject.h b/Libraries/LibELF/ELFDynamicObject.h index 42a5ea9114..45bbd0de42 100644 --- a/Libraries/LibELF/ELFDynamicObject.h +++ b/Libraries/LibELF/ELFDynamicObject.h @@ -6,7 +6,7 @@ class ELFDynamicObject { public: - explicit ELFDynamicObject(VirtualAddress base_address, u32 dynamic_offset); + explicit ELFDynamicObject(VirtualAddress base_address, VirtualAddress dynamic_section_address); ~ELFDynamicObject(); void dump() const; @@ -196,7 +196,7 @@ private: void for_each_dynamic_entry(F) const; VirtualAddress m_base_address; - u32 m_dynamic_offset; + VirtualAddress m_dynamic_address; Symbol m_the_undefined_symbol { *this, 0, {} }; unsigned m_symbol_count { 0 }; @@ -255,7 +255,7 @@ inline void ELFDynamicObject::for_each_symbol(F func) const template inline void ELFDynamicObject::for_each_dynamic_entry(F func) const { - auto* dyns = reinterpret_cast(m_base_address.offset(m_dynamic_offset).as_ptr()); + auto* dyns = reinterpret_cast(m_dynamic_address.as_ptr()); for (unsigned i = 0;; ++i) { auto&& dyn = DynamicEntry(dyns[i]); if (dyn.tag() == DT_NULL)