Browse Source

Module dependencies

Kevin Lange 6 years ago
parent
commit
8080a74a2d
7 changed files with 65 additions and 7 deletions
  1. 5 0
      kernel/include/module.h
  2. 40 5
      kernel/sys/module.c
  3. 1 0
      modules/crash.c
  4. 13 2
      modules/debug_shell.c
  5. 4 0
      modules/link.ld
  6. 1 0
      modules/test.c
  7. 1 0
      modules/testb.c

+ 5 - 0
kernel/include/module.h

@@ -15,6 +15,8 @@ typedef struct {
     void * bin_data;
     hashmap_t * symbols;
     uintptr_t end;
+    size_t deps_length;
+    char * deps;
 } module_data_t;
 
 extern void * module_load_direct(void * blob, size_t size);
@@ -32,4 +34,7 @@ extern void modules_install(void);
 extern hashmap_t * modules_get_list(void);
 extern hashmap_t * modules_get_symbols(void);
 
+#define MODULE_DEPENDS(n) \
+    static char _mod_dependency_ ## n [] __attribute__((section("moddeps"), used)) = #n
+
 #endif

+ 40 - 5
kernel/sys/module.c

@@ -30,12 +30,14 @@ void * module_load_direct(void * blob, size_t length) {
 
 		debug_print(ERROR, "Module is not a valid ELF object.");
 
-		goto mod_load_error;
+		goto mod_load_error_unload;
 	}
 
 	char * shstrtab = NULL;
 	char * symstrtab = NULL;
 	Elf32_Shdr * sym_shdr = NULL;
+	char * deps = NULL;
+	size_t deps_length = 0;
 
 	/* TODO: Actually load the ELF somewhere! This is moronic, you're not initializing a BSS! */
 	/*       (and maybe keep the elf header somewhere) */
@@ -52,7 +54,7 @@ void * module_load_direct(void * blob, size_t length) {
 	}
 	if (!shstrtab) {
 		debug_print(ERROR, "Could not locate module section header string table.");
-		goto mod_load_error;
+		goto mod_load_error_unload;
 	}
 
 	{
@@ -65,7 +67,28 @@ void * module_load_direct(void * blob, size_t length) {
 	}
 	if (!shstrtab) {
 		debug_print(ERROR, "Could not locate module symbol string table.");
-		goto mod_load_error;
+		goto mod_load_error_unload;
+	}
+
+	{
+		debug_print(INFO, "Checking dependencies.");
+		for (unsigned int x = 0; x < (unsigned int)target->e_shentsize * target->e_shnum; x += target->e_shentsize) {
+			Elf32_Shdr * shdr = (Elf32_Shdr *)((uintptr_t)target + (target->e_shoff + x));
+			if ((!strcmp((char *)((uintptr_t)shstrtab + shdr->sh_name), "moddeps"))) {
+				deps = (char*)((Elf32_Addr)target + shdr->sh_offset);
+				deps_length = shdr->sh_size;
+
+				unsigned int i = 0;
+				while (i < deps_length) {
+					if (strlen(&deps[i]) && !hashmap_get(modules, &deps[i])) {
+						debug_print(ERROR, "   %s - not loaded", &deps[i]);
+						goto mod_load_error_unload;
+					}
+					debug_print(INFO, "   %s", &deps[i]);
+					i += strlen(&deps[i]) + 1;
+				}
+			}
+		}
 	}
 
 	{
@@ -78,7 +101,7 @@ void * module_load_direct(void * blob, size_t length) {
 	}
 	if (!sym_shdr) {
 		debug_print(ERROR, "Could not locate section for symbol table.");
-		goto mod_load_error;
+		goto mod_load_error_unload;
 	}
 
 	{
@@ -104,7 +127,8 @@ void * module_load_direct(void * blob, size_t length) {
 					if (table->st_shndx == 0) {
 						if (!hashmap_get(symboltable, name)) {
 							debug_print(ERROR, "Unresolved symbol in module: %s", name);
-							debug_print(ERROR, "Did you forget to load a dependency?");
+							debug_print(ERROR, "This module is faulty! Verify it specifies all of its");
+							debug_print(ERROR, "dependencies properly with MODULE_DEPENDS.");
 							goto mod_load_error;
 						}
 					} else {
@@ -210,11 +234,16 @@ void * module_load_direct(void * blob, size_t length) {
 	mod_data->bin_data = target;
 	mod_data->symbols  = local_symbols;
 	mod_data->end      = (uintptr_t)target + length;
+	mod_data->deps     = deps;
+	mod_data->deps_length = deps_length;
 
 	hashmap_set(modules, mod_info->name, (void *)mod_data);
 
 	return mod_data;
 
+mod_load_error_unload:
+	return (void *)-1;
+
 mod_load_error:
 	return NULL;
 }
@@ -237,6 +266,12 @@ void * module_load(char * filename) {
 
 	void * result = module_load_direct(blob, file->length);
 
+	if (result == (void *)-1) {
+		debug_print(ERROR, "Failed to load module due to unsatisfied dependency.");
+		free(blob);
+		result = NULL;
+	}
+
 	close_fs(file);
 	return result;
 }

+ 1 - 0
modules/crash.c

@@ -16,3 +16,4 @@ static int crash_fini(void) {
 }
 
 MODULE_DEF(crash, crash_init, crash_fini);
+MODULE_DEPENDS(debugshell);

+ 13 - 2
modules/debug_shell.c

@@ -685,9 +685,20 @@ static int shell_modules(fs_node_t * tty, int argc, char * argv[]) {
 		char * key = (char *)_key->value;
 		module_data_t * mod_info = hashmap_get(modules_get_list(), key);
 
-		fs_printf(tty, "%s at 0x%x {.init=0x%x, .fini=0x%x}\n",
+		fs_printf(tty, "%s at 0x%x {.init=0x%x, .fini=0x%x}",
 				mod_info->mod_info->name, mod_info->bin_data,
 				mod_info->mod_info->initialize, mod_info->mod_info->finalize);
+
+		if (mod_info->deps) {
+			unsigned int i = 0;
+			fs_printf(tty, " Deps: ");
+			while (i < mod_info->deps_length) {
+				fs_printf(tty, "%s ", &mod_info->deps[i]);
+				i += strlen(&mod_info->deps[i]) + 1;
+			}
+		}
+
+		fs_printf(tty, "\n");
 	}
 
 	return 0;
@@ -941,4 +952,4 @@ int debug_shell_stop(void) {
 }
 
 MODULE_DEF(debugshell, debug_shell_start, debug_shell_stop);
-
+MODULE_DEPENDS(serial);

+ 4 - 0
modules/link.ld

@@ -13,4 +13,8 @@ SECTIONS
 	{
 		*(.bss*)
 	}
+	.moddeps :
+	{
+		*(.moddeps)
+	}
 }

+ 1 - 0
modules/test.c

@@ -48,4 +48,5 @@ static int goodbye(void) {
 }
 
 MODULE_DEF(test, hello, goodbye);
+MODULE_DEPENDS(debugshell);
 

+ 1 - 0
modules/testb.c

@@ -17,4 +17,5 @@ static int goodbye(void) {
 }
 
 MODULE_DEF(testb, hello, goodbye);
+MODULE_DEPENDS(test);