ソースを参照

Kernel: Allow modules to link against anything in kernel.map :^)

We now use the symbols from kernel.map to link modules as they are
loaded into the kernel. This is pretty fricken cool!
Andreas Kling 5 年 前
コミット
4ef6be8212
5 ファイル変更27 行追加20 行削除
  1. 9 0
      Kernel/KSyms.cpp
  2. 1 0
      Kernel/KSyms.h
  3. 11 18
      Kernel/Process.cpp
  4. 5 1
      Kernel/TestModule.cpp
  5. 1 1
      Kernel/mkmap.sh

+ 9 - 0
Kernel/KSyms.cpp

@@ -19,6 +19,15 @@ static u8 parse_hex_digit(char nibble)
     return 10 + (nibble - 'a');
 }
 
+u32 address_for_kernel_symbol(const char* name)
+{
+    for (unsigned i = 0; i < ksym_count; ++i) {
+        if (!strcmp(name, s_ksyms[i].name))
+            return s_ksyms[i].address;
+    }
+    return 0;
+}
+
 const KSym* ksymbolicate(u32 address)
 {
     if (address < ksym_lowest_address || address > ksym_highest_address)

+ 1 - 0
Kernel/KSyms.h

@@ -8,6 +8,7 @@ struct KSym {
     const char* name;
 };
 
+u32 address_for_kernel_symbol(const char* name);
 const KSym* ksymbolicate(u32 address);
 void load_ksyms();
 

+ 11 - 18
Kernel/Process.cpp

@@ -3382,20 +3382,6 @@ int Process::sys$beep()
     return 0;
 }
 
-extern "C" void outside_func()
-{
-    kprintf("I'm the outside func!\n");
-}
-
-static u32 find_kernel_symbol(const StringView& name)
-{
-    if (name == "kprintf")
-        return (u32)kprintf;
-    if (name == "outside_func")
-        return (u32)outside_func;
-    ASSERT_NOT_REACHED();
-}
-
 int Process::sys$module_load(const char* path, size_t path_length)
 {
 #if 0
@@ -3439,7 +3425,7 @@ int Process::sys$module_load(const char* path, size_t path_length)
             case R_386_PC32: {
                 // PC-relative relocation
                 dbg() << "PC-relative relocation: " << relocation.symbol().name();
-                u32 symbol_address = find_kernel_symbol(relocation.symbol().name());
+                u32 symbol_address = address_for_kernel_symbol(relocation.symbol().name());
                 dbg() << "   Symbol address: " << (void*)symbol_address;
                 ptrdiff_t relative_offset = (char*)symbol_address - ((char*)&patch_ptr + 4);
                 patch_ptr = relative_offset;
@@ -3447,9 +3433,16 @@ int Process::sys$module_load(const char* path, size_t path_length)
             }
             case R_386_32: // Absolute relocation
                 dbg() << "Absolute relocation: '" << relocation.symbol().name() << "' value:" << relocation.symbol().value() << ", index:" << relocation.symbol_index();
-                auto* section_storage_containing_symbol = section_storage_by_name.get(relocation.symbol().section().name()).value_or(nullptr);
-                ASSERT(section_storage_containing_symbol);
-                patch_ptr += (ptrdiff_t)(section_storage_containing_symbol + relocation.symbol().value());
+
+                if (relocation.symbol().bind() == STB_LOCAL) {
+                    auto* section_storage_containing_symbol = section_storage_by_name.get(relocation.symbol().section().name()).value_or(nullptr);
+                    ASSERT(section_storage_containing_symbol);
+                    patch_ptr += (ptrdiff_t)(section_storage_containing_symbol + relocation.symbol().value());
+                } else if (relocation.symbol().bind() == STB_GLOBAL) {
+                    patch_ptr += address_for_kernel_symbol(relocation.symbol().name());
+                } else {
+                    ASSERT_NOT_REACHED();
+                }
                 break;
             }
             return IterationDecision::Continue;

+ 5 - 1
Kernel/TestModule.cpp

@@ -1,12 +1,16 @@
 #include <Kernel/kstdio.h>
+#include <Kernel/Process.h>
 
 extern "C" void module_init()
 {
     kprintf("TestModule has booted!\n");
 
-    for (int i = 0; i < 99; ++i) {
+    for (int i = 0; i < 3; ++i) {
         kprintf("i is now %d\n", i);
     }
+
+    kprintf("current pid: %d\n", current->process().sys$getpid());
+    kprintf("current process name: %s\n", current->process().name().characters());
 }
 
 extern "C" void module_fini()

+ 1 - 1
Kernel/mkmap.sh

@@ -1,6 +1,6 @@
 #!/bin/sh
 tmp=$(mktemp)
-nm -nC kernel | awk '{ if ($2 != "a") print; }' | uniq > $tmp
+nm -n kernel | awk '{ if ($2 != "a") print; }' | uniq > $tmp
 printf "%08x\n" $(wc -l $tmp | cut -f1 -d' ') > kernel.map
 cat $tmp >> kernel.map
 rm -f $tmp