Skip to content

Commit

Permalink
Kernel: Implement basic module unloading :^)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
awesomekling committed Nov 28, 2019
1 parent 6b150c7 commit a43b115
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 14 deletions.
9 changes: 6 additions & 3 deletions Kernel/Module.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
};
20 changes: 14 additions & 6 deletions Kernel/Process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>();
Expand Down Expand Up @@ -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));
Expand All @@ -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;
}
7 changes: 5 additions & 2 deletions Kernel/TestModule.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
#include <Kernel/kstdio.h>

extern "C" void outside_func();

extern "C" void module_init()
{
kprintf("TestModule has booted!\n");
Expand All @@ -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");
}
4 changes: 2 additions & 2 deletions Kernel/build-root-filesystem.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion Userland/modload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
15 changes: 15 additions & 0 deletions Userland/modunload.cpp
Original file line number Diff line number Diff line change
@@ -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;
}

0 comments on commit a43b115

Please sign in to comment.