浏览代码

Prekernel: Don't assume that PT_LOAD headers are ordered by address

These headers are ordered by virtual address - at least with GCC - but
that might not always be the case.
Gunnar Beutner 4 年之前
父节点
当前提交
56f952a5f2
共有 1 个文件被更改,包括 16 次插入8 次删除
  1. 16 8
      Kernel/Prekernel/init.cpp

+ 16 - 8
Kernel/Prekernel/init.cpp

@@ -75,18 +75,26 @@ extern "C" [[noreturn]] void init()
         halt();
         halt();
     __builtin_memcpy(kernel_program_headers, kernel_image + kernel_elf_header.e_phoff, sizeof(ElfW(Phdr)) * kernel_elf_header.e_phnum);
     __builtin_memcpy(kernel_program_headers, kernel_image + kernel_elf_header.e_phoff, sizeof(ElfW(Phdr)) * kernel_elf_header.e_phnum);
 
 
-    FlatPtr kernel_load_base = kernel_program_headers[0].p_vaddr;
-    FlatPtr kernel_load_end = kernel_program_headers[kernel_elf_header.e_phnum - 1].p_vaddr + kernel_program_headers[kernel_elf_header.e_phnum - 1].p_memsz;
+    FlatPtr kernel_load_base, kernel_load_end;
+    for (size_t i = 0; i < kernel_elf_header.e_phnum; i++) {
+        auto& kernel_program_header = kernel_program_headers[i];
+        if (kernel_program_header.p_type != PT_LOAD)
+            continue;
+        auto start = kernel_program_header.p_vaddr;
+        auto end = start + kernel_program_header.p_memsz;
+        if (start < (FlatPtr)end_of_prekernel_image)
+            halt();
+        if (kernel_program_header.p_paddr < (FlatPtr)end_of_prekernel_image)
+            halt();
+        if (kernel_load_base == 0 || start < kernel_load_base)
+            kernel_load_base = start;
+        if (end > kernel_load_end)
+            kernel_load_end = end;
+    }
 
 
     // align to 1GB
     // align to 1GB
     kernel_load_base &= ~(FlatPtr)0x3fffffff;
     kernel_load_base &= ~(FlatPtr)0x3fffffff;
 
 
-    if (kernel_program_headers[0].p_vaddr < (FlatPtr)end_of_prekernel_image)
-        halt();
-
-    if (kernel_program_headers[0].p_paddr < (FlatPtr)end_of_prekernel_image)
-        halt();
-
 #if ARCH(I386)
 #if ARCH(I386)
     int pdpt_flags = 0x1;
     int pdpt_flags = 0x1;
 #else
 #else