Browse Source

Kernel: Make kernel symbols available much earlier in the boot process

This adds a new section .ksyms at the end of the linker map, reserves
5MiB for it (which are after end_of_kernel_image so they get re-used
once MemoryManager is initialized) and then embeds the symbol map into
the kernel binary with objcopy. This also shrinks the .ksyms section to
the real size of the symbol file (around 900KiB at the moment).

By doing this we can make the symbol map available much earlier in the
boot process, i.e. even before VFS is available.
Gunnar Beutner 4 years ago
parent
commit
7236584
5 changed files with 28 additions and 18 deletions
  1. 4 7
      Kernel/CMakeLists.txt
  2. 11 9
      Kernel/KSyms.cpp
  3. 5 0
      Kernel/embedmap.sh
  4. 2 2
      Kernel/init.cpp
  5. 6 0
      Kernel/linker.ld

+ 4 - 7
Kernel/CMakeLists.txt

@@ -414,16 +414,13 @@ add_dependencies(${KERNEL_TARGET} kernel_heap)
 add_custom_command(
     TARGET ${KERNEL_TARGET} POST_BUILD
     COMMAND ${TOOLCHAIN_PREFIX}objcopy -O elf32-i386 ${CMAKE_CURRENT_BINARY_DIR}/${KERNEL_TARGET} ${CMAKE_CURRENT_BINARY_DIR}/Kernel
-    BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/Kernel
+    COMMAND sh ${CMAKE_CURRENT_SOURCE_DIR}/mkmap.sh
+    COMMAND sh ${CMAKE_CURRENT_SOURCE_DIR}/embedmap.sh
+    BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/Kernel ${CMAKE_CURRENT_BINARY_DIR}/kernel.map
 )
 
 install(FILES "${CMAKE_CURRENT_BINARY_DIR}/Kernel" DESTINATION boot)
-
-add_custom_command(
-    TARGET ${KERNEL_TARGET} POST_BUILD
-    COMMAND sh ${CMAKE_CURRENT_SOURCE_DIR}/mkmap.sh
-)
-install(FILES ${CMAKE_CURRENT_BINARY_DIR}/kernel.map DESTINATION res)
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/kernel.map" DESTINATION res)
 
 serenity_install_headers(Kernel)
 serenity_install_sources(Kernel)

+ 11 - 9
Kernel/KSyms.cpp

@@ -18,6 +18,10 @@ FlatPtr g_lowest_kernel_symbol_address = 0xffffffff;
 FlatPtr g_highest_kernel_symbol_address = 0;
 bool g_kernel_symbols_available = false;
 
+extern "C" {
+__attribute__((section(".kernel_symbols"))) char kernel_symbols[5 * MiB] {};
+}
+
 static KernelSymbol* s_symbols;
 static size_t s_symbol_count = 0;
 
@@ -50,7 +54,7 @@ const KernelSymbol* symbolicate_kernel_address(FlatPtr address)
     return nullptr;
 }
 
-UNMAP_AFTER_INIT static void load_kernel_symbols_from_data(const KBuffer& buffer)
+UNMAP_AFTER_INIT static void load_kernel_symbols_from_data(ReadonlyBytes const& buffer)
 {
     g_lowest_kernel_symbol_address = 0xffffffff;
     g_highest_kernel_symbol_address = 0;
@@ -68,7 +72,7 @@ UNMAP_AFTER_INIT static void load_kernel_symbols_from_data(const KBuffer& buffer
 
     size_t current_symbol_index = 0;
 
-    while (bufptr < buffer.end_pointer()) {
+    while ((u8 const*)bufptr < buffer.data() + buffer.size()) {
         for (size_t i = 0; i < 8; ++i)
             address = (address << 4) | parse_hex_digit(*(bufptr++));
         bufptr += 3;
@@ -166,13 +170,11 @@ void dump_backtrace()
 
 UNMAP_AFTER_INIT void load_kernel_symbol_table()
 {
-    auto result = VirtualFileSystem::the().open("/res/kernel.map", O_RDONLY, 0, VirtualFileSystem::the().root_custody());
-    if (!result.is_error()) {
-        auto description = result.value();
-        auto buffer = description->read_entire_file();
-        if (!buffer.is_error())
-            load_kernel_symbols_from_data(*buffer.value());
-    }
+    auto kernel_symbols_size = strnlen(kernel_symbols, sizeof(kernel_symbols));
+    // If we're hitting this VERIFY the kernel symbol file has grown beyond
+    // the array size of kernel_symbols. Try making the array larger.
+    VERIFY(kernel_symbols_size != sizeof(kernel_symbols));
+    load_kernel_symbols_from_data({ kernel_symbols, kernel_symbols_size });
 }
 
 }

+ 5 - 0
Kernel/embedmap.sh

@@ -0,0 +1,5 @@
+#!/bin/sh
+tmp=$(mktemp)
+(cat kernel.map; printf '%b' '\0') > "$tmp"
+objcopy --update-section .ksyms="$tmp" Kernel
+rm -f "$tmp"

+ 2 - 2
Kernel/init.cpp

@@ -123,6 +123,8 @@ extern "C" [[noreturn]] UNMAP_AFTER_INIT void init()
     kmalloc_init();
     slab_alloc_init();
 
+    load_kernel_symbol_table();
+
     ConsoleDevice::initialize();
     s_bsp_processor.initialize(0);
 
@@ -264,8 +266,6 @@ void init_stage2(void*)
 
     Process::current()->set_root_directory(VirtualFileSystem::the().root_custody());
 
-    load_kernel_symbol_table();
-
     // Switch out of early boot mode.
     g_in_early_boot = false;
 

+ 6 - 0
Kernel/linker.ld

@@ -9,6 +9,7 @@ PHDRS
   text PT_LOAD ;
   data PT_LOAD ;
   bss PT_LOAD ;
+  ksyms PT_LOAD ;
 }
 
 SECTIONS
@@ -93,4 +94,9 @@ SECTIONS
     } :bss
 
     end_of_kernel_image = .;
+
+    .ksyms ALIGN(4K) : AT (ADDR(.ksyms) - KERNEL_VIRTUAL_BASE)
+    {
+        *(.kernel_symbols)
+    } :ksyms
 }