ソースを参照

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).
Gunnar Beutner 4 年 前
コミット
13a14b3112
1 ファイル変更5 行追加7 行削除
  1. 5 7
      Userland/Libraries/LibELF/DynamicLoader.cpp

+ 5 - 7
Userland/Libraries/LibELF/DynamicLoader.cpp

@@ -319,20 +319,18 @@ void DynamicLoader::load_program_headers()
     }
     }
 
 
     for (auto& text_region : text_regions) {
     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_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);
         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.
         // 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(
-            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,
             PROT_READ,
             MAP_FILE | MAP_SHARED | MAP_FIXED,
             MAP_FILE | MAP_SHARED | MAP_FIXED,
             m_image_fd,
             m_image_fd,
-            text_region.offset(),
+            VirtualAddress { text_region.offset() }.page_base().get(),
             String::formatted("{}: .text", m_filename).characters());
             String::formatted("{}: .text", m_filename).characters());
 
 
         if (text_segment_begin == MAP_FAILED) {
         if (text_segment_begin == MAP_FAILED) {
@@ -340,7 +338,7 @@ void DynamicLoader::load_program_headers()
             VERIFY_NOT_REACHED();
             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);
     VERIFY(requested_load_address == nullptr || requested_load_address == reservation);