diff options
author | Andreas Kling <awesomekling@gmail.com> | 2019-11-28 21:07:22 +0100 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-11-28 21:07:22 +0100 |
commit | a43b115a6c99881c964daa5012cd076e82a7d72f (patch) | |
tree | dbc28d95f716271b3790832f74cd8b6794b85af6 | |
parent | 6b150c794a4c71e36bd1e5e545be171d0e3b45d0 (diff) | |
download | serenity-a43b115a6c99881c964daa5012cd076e82a7d72f.zip |
Kernel: Implement basic module unloading :^)
Kernel modules can now be unloaded via a syscall. They get a chance to
run some code of course. Before deallocating them, we call their
"module_fini" symbol.
-rw-r--r-- | Kernel/Module.h | 9 | ||||
-rw-r--r-- | Kernel/Process.cpp | 20 | ||||
-rw-r--r-- | Kernel/TestModule.cpp | 7 | ||||
-rwxr-xr-x | Kernel/build-root-filesystem.sh | 4 | ||||
-rw-r--r-- | Userland/modload.cpp | 2 | ||||
-rw-r--r-- | Userland/modunload.cpp | 15 |
6 files changed, 43 insertions, 14 deletions
diff --git a/Kernel/Module.h b/Kernel/Module.h index 8a27f41940..f06948b84d 100644 --- a/Kernel/Module.h +++ b/Kernel/Module.h @@ -4,10 +4,13 @@ #include <AK/Vector.h> #include <Kernel/KBuffer.h> +typedef void* (*ModuleInitPtr)(); +typedef void* (*ModuleFiniPtr)(); + struct Module { String name; Vector<KBuffer> sections; -}; -typedef void* (*ModuleInitPtr)(); -typedef void* (*ModuleFiniPtr)(); + ModuleInitPtr module_init { nullptr }; + ModuleFiniPtr module_fini { nullptr }; +}; diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 5822b69597..f7990af921 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -3418,8 +3418,6 @@ int Process::sys$module_load(const char* path, size_t path_length) if (!elf_image->parse()) return -ENOEXEC; - ModuleInitPtr module_init = nullptr; - HashMap<String, u8*> section_storage_by_name; auto module = make<Module>(); @@ -3469,15 +3467,17 @@ int Process::sys$module_load(const char* path, size_t path_length) elf_image->for_each_symbol([&](const ELFImage::Symbol& symbol) { dbg() << " - " << symbol.type() << " '" << symbol.name() << "' @ " << (void*)symbol.value() << ", size=" << symbol.size(); if (!strcmp(symbol.name(), "module_init")) { - module_init = (ModuleInitPtr)(text_base + symbol.value()); + module->module_init = (ModuleInitPtr)(text_base + symbol.value()); + } else if (!strcmp(symbol.name(), "module_fini")) { + module->module_fini = (ModuleFiniPtr)(text_base + symbol.value()); } return IterationDecision::Continue; }); - if (!module_init) + if (!module->module_init) return -EINVAL; - module_init(); + module->module_init(); auto name = module->name; g_modules->set(name, move(module)); @@ -3493,6 +3493,14 @@ int Process::sys$module_unload(const char* name, size_t name_length) #endif if (!validate_read(name, name_length)) return -EFAULT; - // FIXME: Implement this syscall! + + auto it = g_modules->find(name); + if (it == g_modules->end()) + return -ENOENT; + + if (it->value->module_fini) + it->value->module_fini(); + + g_modules->remove(it); return 0; } diff --git a/Kernel/TestModule.cpp b/Kernel/TestModule.cpp index a3a1296156..20603c2028 100644 --- a/Kernel/TestModule.cpp +++ b/Kernel/TestModule.cpp @@ -1,7 +1,5 @@ #include <Kernel/kstdio.h> -extern "C" void outside_func(); - extern "C" void module_init() { kprintf("TestModule has booted!\n"); @@ -10,3 +8,8 @@ extern "C" void module_init() kprintf("i is now %d\n", i); } } + +extern "C" void module_fini() +{ + kprintf("TestModule is being removed!\n"); +} diff --git a/Kernel/build-root-filesystem.sh b/Kernel/build-root-filesystem.sh index de79043b05..68e893bae6 100755 --- a/Kernel/build-root-filesystem.sh +++ b/Kernel/build-root-filesystem.sh @@ -134,13 +134,13 @@ ln -s SoundPlayer mnt/bin/sp ln -s Help mnt/bin/help ln -s Browser mnt/bin/br ln -s HackStudio mnt/bin/hs -ln -s modload mnt/bin/m echo "done" mkdir -p mnt/boot/ cp kernel mnt/boot/ -cp TestModule.o mnt/ +mkdir -p mnt/mod/ +cp TestModule.o mnt/mod # Run local sync script, if it exists if [ -f sync-local.sh ]; then diff --git a/Userland/modload.cpp b/Userland/modload.cpp index 180f9a1a73..d0412a0fcd 100644 --- a/Userland/modload.cpp +++ b/Userland/modload.cpp @@ -5,7 +5,7 @@ int main(int argc, char** argv) { (void)argc; (void)argv; - const char* path = "/TestModule.o"; + const char* path = "/mod/TestModule.o"; int rc = module_load(path, strlen(path)); if (rc < 0) { perror("module_load"); diff --git a/Userland/modunload.cpp b/Userland/modunload.cpp new file mode 100644 index 0000000000..c65b5085a0 --- /dev/null +++ b/Userland/modunload.cpp @@ -0,0 +1,15 @@ +#include <serenity.h> +#include <string.h> + +int main(int argc, char** argv) +{ + (void)argc; + (void)argv; + const char* name = "FIXME"; + int rc = module_unload(name, strlen(name)); + if (rc < 0) { + perror("module_unload"); + return 1; + } + return 0; +} |