mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 20:47:45 +00:00
LibELF: Make a dummy VM reservation before mapping dynamic objects
Using the text segment for the VM reservation ran into trouble when there was a discrepancy between the p_filesz and p_memsz. Simplify this mechanism and avoid trouble by making the reservation as a MAP_PRIVATE | MAP_NORESERVE throwaway mapping instead. Fixes #5225.
This commit is contained in:
parent
c9cd5ff6bb
commit
3a3270eb68
1 changed files with 22 additions and 15 deletions
|
@ -286,25 +286,38 @@ void DynamicLoader::load_program_headers()
|
||||||
|
|
||||||
ASSERT(!text_region.value().is_writable());
|
ASSERT(!text_region.value().is_writable());
|
||||||
|
|
||||||
// First, we map the text *and* data segments, in order to allocate enough VM
|
// First, we make a dummy reservation mapping, in order to allocate enough VM
|
||||||
// to hold both contiguously in the address space.
|
// to hold both text+data contiguously in the address space.
|
||||||
|
|
||||||
Checked<size_t> total_mapping_size;
|
Checked<size_t> total_mapping_size;
|
||||||
total_mapping_size = text_region.value().required_load_size();
|
total_mapping_size = text_region.value().required_load_size();
|
||||||
total_mapping_size += data_region.value().required_load_size();
|
total_mapping_size += data_region.value().required_load_size();
|
||||||
ASSERT(!total_mapping_size.has_overflow());
|
ASSERT(!total_mapping_size.has_overflow());
|
||||||
|
|
||||||
|
auto* reservation = mmap(requested_load_address, total_mapping_size.value(), PROT_NONE, MAP_ANON | MAP_PRIVATE | MAP_NORESERVE, 0, 0);
|
||||||
|
if (reservation == MAP_FAILED) {
|
||||||
|
perror("mmap reservation");
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then we unmap the reservation.
|
||||||
|
if (munmap(reservation, total_mapping_size.value()) < 0) {
|
||||||
|
perror("munmap reservation");
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now we can map the text segment at the reserved address.
|
||||||
auto* text_segment_begin = (u8*)mmap_with_name(
|
auto* text_segment_begin = (u8*)mmap_with_name(
|
||||||
requested_load_address,
|
reservation,
|
||||||
total_mapping_size.value(),
|
text_region.value().required_load_size(),
|
||||||
PROT_READ,
|
PROT_READ,
|
||||||
text_mmap_flags,
|
text_mmap_flags,
|
||||||
m_image_fd,
|
m_image_fd,
|
||||||
text_region.value().offset(),
|
text_region.value().offset(),
|
||||||
String::formatted("{}: .text", m_filename).characters());
|
String::formatted("{}: .text", m_filename).characters());
|
||||||
|
|
||||||
if (MAP_FAILED == text_segment_begin) {
|
if (text_segment_begin == MAP_FAILED) {
|
||||||
perror("mmap text / initial segment");
|
perror("mmap text");
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,19 +325,13 @@ void DynamicLoader::load_program_headers()
|
||||||
m_text_segment_size = text_region.value().required_load_size();
|
m_text_segment_size = text_region.value().required_load_size();
|
||||||
m_text_segment_load_address = VirtualAddress { (FlatPtr)text_segment_begin };
|
m_text_segment_load_address = VirtualAddress { (FlatPtr)text_segment_begin };
|
||||||
|
|
||||||
// Then, we unmap the data segment part of the above combined VM allocation.
|
|
||||||
auto* data_segment_address = (u8*)text_segment_begin + text_region.value().required_load_size();
|
|
||||||
if (munmap(data_segment_address, data_region.value().required_load_size()) < 0) {
|
|
||||||
perror("munmap");
|
|
||||||
ASSERT_NOT_REACHED();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_elf_image.is_dynamic())
|
if (m_elf_image.is_dynamic())
|
||||||
m_dynamic_section_address = dynamic_region_desired_vaddr.offset(m_text_segment_load_address.get());
|
m_dynamic_section_address = dynamic_region_desired_vaddr.offset(m_text_segment_load_address.get());
|
||||||
else
|
else
|
||||||
m_dynamic_section_address = dynamic_region_desired_vaddr;
|
m_dynamic_section_address = dynamic_region_desired_vaddr;
|
||||||
|
|
||||||
// Finally, we remap the data segment, this time privately.
|
// Finally, we make an anonymous mapping for the data segment. Contents are then copied from the file.
|
||||||
|
auto* data_segment_address = (u8*)text_segment_begin + text_region.value().required_load_size();
|
||||||
auto* data_segment = (u8*)mmap_with_name(
|
auto* data_segment = (u8*)mmap_with_name(
|
||||||
data_segment_address,
|
data_segment_address,
|
||||||
data_region.value().required_load_size(),
|
data_region.value().required_load_size(),
|
||||||
|
@ -335,7 +342,7 @@ void DynamicLoader::load_program_headers()
|
||||||
String::formatted("{}: .data", m_filename).characters());
|
String::formatted("{}: .data", m_filename).characters());
|
||||||
|
|
||||||
if (MAP_FAILED == data_segment) {
|
if (MAP_FAILED == data_segment) {
|
||||||
perror("mmap data segment");
|
perror("mmap data");
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue