mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 17:02:45 +00:00 
			
		
		
		
	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.
This commit is contained in:
		
							parent
							
								
									6b150c794a
								
							
						
					
					
						commit
						a43b115a6c
					
				
					 6 changed files with 43 additions and 14 deletions
				
			
		|  | @ -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 }; | ||||
| }; | ||||
|  |  | |||
|  | @ -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; | ||||
| } | ||||
|  |  | |||
|  | @ -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"); | ||||
| } | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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"); | ||||
|  |  | |||
							
								
								
									
										15
									
								
								Userland/modunload.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								Userland/modunload.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -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; | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling