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

LibELF: Fix loading libs with a .text segment that's not page-aligned

It's perfectly acceptable for the segment's vaddr to not be page aligned
as long as the segment itself is page-aligned. We'll just map a few more
bytes at the start of the segment that will be unused by the library.

We didn't notice this problem because because GCC either always uses
0 for the .text segment's vaddr or at least aligns the vaddr to the
page size.

LibELF would also fail to load really small libraries (i.e. smaller than
4096 bytes).
This commit is contained in:
Gunnar Beutner 2021-07-06 11:14:44 +02:00 committed by Andreas Kling
parent 4591c00328
commit 13a14b3112

View file

@ -319,20 +319,18 @@ void DynamicLoader::load_program_headers()
}
for (auto& text_region : text_regions) {
FlatPtr ph_text_desired_base = text_region.desired_load_address().get();
FlatPtr ph_text_base = text_region.desired_load_address().page_base().get();
FlatPtr ph_text_end = ph_text_base + round_up_to_power_of_two(text_region.size_in_memory() + (size_t)(text_region.desired_load_address().as_ptr() - ph_text_base), PAGE_SIZE);
auto* text_segment_address = (u8*)reservation + ph_text_base - ph_load_base;
size_t text_segment_size = ph_text_end - ph_text_base;
// Now we can map the text segment at the reserved address.
auto* text_segment_begin = (u8*)mmap_with_name(
text_segment_address,
text_segment_size,
(u8*)reservation + ph_text_base - ph_load_base,
ph_text_desired_base - ph_text_base + text_region.size_in_image(),
PROT_READ,
MAP_FILE | MAP_SHARED | MAP_FIXED,
m_image_fd,
text_region.offset(),
VirtualAddress { text_region.offset() }.page_base().get(),
String::formatted("{}: .text", m_filename).characters());
if (text_segment_begin == MAP_FAILED) {
@ -340,7 +338,7 @@ void DynamicLoader::load_program_headers()
VERIFY_NOT_REACHED();
}
m_text_segments.append({ VirtualAddress { (FlatPtr)text_segment_begin }, text_segment_size });
m_text_segments.append({ VirtualAddress { (FlatPtr)text_segment_begin }, ph_text_end - ph_text_base });
}
VERIFY(requested_load_address == nullptr || requested_load_address == reservation);