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 <AK/Vector.h> | ||||||
| #include <Kernel/KBuffer.h> | #include <Kernel/KBuffer.h> | ||||||
| 
 | 
 | ||||||
|  | typedef void* (*ModuleInitPtr)(); | ||||||
|  | typedef void* (*ModuleFiniPtr)(); | ||||||
|  | 
 | ||||||
| struct Module { | struct Module { | ||||||
|     String name; |     String name; | ||||||
|     Vector<KBuffer> sections; |     Vector<KBuffer> sections; | ||||||
| }; |  | ||||||
| 
 | 
 | ||||||
| typedef void* (*ModuleInitPtr)(); |     ModuleInitPtr module_init { nullptr }; | ||||||
| typedef void* (*ModuleFiniPtr)(); |     ModuleFiniPtr module_fini { nullptr }; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | @ -3418,8 +3418,6 @@ int Process::sys$module_load(const char* path, size_t path_length) | ||||||
|     if (!elf_image->parse()) |     if (!elf_image->parse()) | ||||||
|         return -ENOEXEC; |         return -ENOEXEC; | ||||||
| 
 | 
 | ||||||
|     ModuleInitPtr module_init = nullptr; |  | ||||||
| 
 |  | ||||||
|     HashMap<String, u8*> section_storage_by_name; |     HashMap<String, u8*> section_storage_by_name; | ||||||
| 
 | 
 | ||||||
|     auto module = make<Module>(); |     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) { |     elf_image->for_each_symbol([&](const ELFImage::Symbol& symbol) { | ||||||
|         dbg() << " - " << symbol.type() << " '" << symbol.name() << "' @ " << (void*)symbol.value() << ", size=" << symbol.size(); |         dbg() << " - " << symbol.type() << " '" << symbol.name() << "' @ " << (void*)symbol.value() << ", size=" << symbol.size(); | ||||||
|         if (!strcmp(symbol.name(), "module_init")) { |         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; |         return IterationDecision::Continue; | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     if (!module_init) |     if (!module->module_init) | ||||||
|         return -EINVAL; |         return -EINVAL; | ||||||
| 
 | 
 | ||||||
|     module_init(); |     module->module_init(); | ||||||
| 
 | 
 | ||||||
|     auto name = module->name; |     auto name = module->name; | ||||||
|     g_modules->set(name, move(module)); |     g_modules->set(name, move(module)); | ||||||
|  | @ -3493,6 +3493,14 @@ int Process::sys$module_unload(const char* name, size_t name_length) | ||||||
| #endif | #endif | ||||||
|     if (!validate_read(name, name_length)) |     if (!validate_read(name, name_length)) | ||||||
|         return -EFAULT; |         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; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,7 +1,5 @@ | ||||||
| #include <Kernel/kstdio.h> | #include <Kernel/kstdio.h> | ||||||
| 
 | 
 | ||||||
| extern "C" void outside_func(); |  | ||||||
| 
 |  | ||||||
| extern "C" void module_init() | extern "C" void module_init() | ||||||
| { | { | ||||||
|     kprintf("TestModule has booted!\n"); |     kprintf("TestModule has booted!\n"); | ||||||
|  | @ -10,3 +8,8 @@ extern "C" void module_init() | ||||||
|         kprintf("i is now %d\n", i); |         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 Help mnt/bin/help | ||||||
| ln -s Browser mnt/bin/br | ln -s Browser mnt/bin/br | ||||||
| ln -s HackStudio mnt/bin/hs | ln -s HackStudio mnt/bin/hs | ||||||
| ln -s modload mnt/bin/m |  | ||||||
| echo "done" | echo "done" | ||||||
| 
 | 
 | ||||||
| mkdir -p mnt/boot/ | mkdir -p mnt/boot/ | ||||||
| cp kernel 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 | # Run local sync script, if it exists | ||||||
| if [ -f sync-local.sh ]; then | if [ -f sync-local.sh ]; then | ||||||
|  |  | ||||||
|  | @ -5,7 +5,7 @@ int main(int argc, char** argv) | ||||||
| { | { | ||||||
|     (void)argc; |     (void)argc; | ||||||
|     (void)argv; |     (void)argv; | ||||||
|     const char* path = "/TestModule.o"; |     const char* path = "/mod/TestModule.o"; | ||||||
|     int rc = module_load(path, strlen(path)); |     int rc = module_load(path, strlen(path)); | ||||||
|     if (rc < 0) { |     if (rc < 0) { | ||||||
|         perror("module_load"); |         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