aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Bucur <stefanb@zytor.com>2008-08-14 22:08:12 +0300
committerStefan Bucur <stefan@stefan-ubumac.(none)>2009-03-15 10:10:51 +0200
commitad765d63f72c193972629de32f930a669ca2e361 (patch)
treeabbec72c085ba87d23540f15ff00440bda9fc3dd
parent83955ce691dfcf8afaccb4c36d800ae7ab50a1e0 (diff)
downloadsyslinux-elf-ad765d63f72c193972629de32f930a669ca2e361.tar.gz
syslinux-elf-ad765d63f72c193972629de32f930a669ca2e361.tar.xz
syslinux-elf-ad765d63f72c193972629de32f930a669ca2e361.zip
Added a new execution API on top of the module API.
-rw-r--r--com32/elflink/Makefile4
-rw-r--r--com32/elflink/exec.c147
-rw-r--r--com32/elflink/exec.h48
-rw-r--r--com32/elflink/modules/hello.c10
-rw-r--r--com32/include/sys/module.h13
-rw-r--r--com32/lib/elf32.ld9
-rw-r--r--com32/lib/sys/module/common.h2
-rw-r--r--com32/lib/sys/module/elf_module.c12
8 files changed, 227 insertions, 18 deletions
diff --git a/com32/elflink/Makefile b/com32/elflink/Makefile
index 5691d66e..6f846d51 100644
--- a/com32/elflink/Makefile
+++ b/com32/elflink/Makefile
@@ -86,8 +86,8 @@ test_memalign.elf : test_memalign.o $(LIBS)
$(LD) $(LDFLAGS) -o $@ $^
test_com32.elf: CFLAGS += -DELF_DEBUG
-test_com32.elf: test_com32.o ../libutil/libutil_com.a ../lib/libcom32min.a $(LIBGCC)
- $(LD) -n $(LDFLAGS) -o $@ test_com32.o ../libutil/libutil_com.a $(LIBGCC) --whole-archive ../lib/libcom32min.a
+test_com32.elf: test_com32.o exec.o ../libutil/libutil_com.a ../lib/libcom32min.a $(LIBGCC)
+ $(LD) -n $(LDFLAGS) -o $@ test_com32.o exec.o ../libutil/libutil_com.a $(LIBGCC) --whole-archive ../lib/libcom32min.a
$(OBJCOPY) --extract-symbol $@ _root_.dyn
tidy dist:
diff --git a/com32/elflink/exec.c b/com32/elflink/exec.c
new file mode 100644
index 00000000..58f04b45
--- /dev/null
+++ b/com32/elflink/exec.c
@@ -0,0 +1,147 @@
+/*
+ * exec.c
+ *
+ * Created on: Aug 14, 2008
+ * Author: Stefan Bucur <stefanb@zytor.com>
+ */
+
+#include <sys/module.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "exec.h"
+
+#define DBG_PRINT(fmt, args...) fprintf(stderr, "[EXEC] " fmt, ##args)
+
+
+static struct elf_module *mod_root = NULL;
+
+static char *module_get_fullname(const char *name) {
+ static char name_buff[MODULE_NAME_SIZE];
+
+ strcpy(name_buff, EXEC_DIRECTORY);
+ strcat(name_buff, name);
+
+ return name_buff;
+}
+
+int exec_init() {
+ int res;
+
+ res = modules_init();
+
+ if (res != 0)
+ return res;
+
+ // Load the root module
+ mod_root = module_alloc(module_get_fullname(EXEC_ROOT_NAME));
+
+ if (mod_root == NULL)
+ return -1;
+
+ res = module_load_shallow(mod_root);
+
+ if (res != 0) {
+ mod_root = NULL;
+ return res;
+ }
+
+ return 0;
+}
+
+int load_library(const char *name) {
+ int res;
+ struct elf_module *module = module_alloc(module_get_fullname(name));
+
+ if (module == NULL)
+ return -1;
+
+ res = module_load(module);
+
+
+ if (res != 0) {
+ return res;
+ }
+
+ if (*(module->init_func) != NULL) {
+ res = (*(module->init_func))();
+ DBG_PRINT("Initialization function returned: %d\n", res);
+ } else {
+ DBG_PRINT("No initialization function present.\n");
+ }
+
+ if (res != 0) {
+ module_unload(module);
+ return res;
+ }
+
+ return 0;
+}
+
+int unload_library(const char *name) {
+ int res;
+ struct elf_module *module = module_find(module_get_fullname(name));
+
+ if (module == NULL)
+ return -1;
+
+ if (*(module->exit_func) != NULL) {
+ (*(module->exit_func))();
+ }
+
+ res = module_unload(module);
+
+ return res;
+}
+
+int spawnv(const char *name, const char **argv) {
+ int res, ret_val;
+
+ struct elf_module *module = module_alloc(module_get_fullname(name));
+
+ if (module == NULL)
+ return -1;
+
+ res = module_load(module);
+
+ if (res != 0) {
+ return res;
+ }
+
+ if (*(module->main_func) != NULL) {
+ const char **last_arg = argv;
+ while (*last_arg != NULL)
+ last_arg++;
+
+ ret_val = (*(module->main_func))(last_arg - argv, argv);
+ } else {
+ // We can't execute without a main function
+ module_unload(module);
+ return -1;
+ }
+
+ res = module_unload(module);
+
+ if (res != 0) {
+ return res;
+ }
+
+ return ((unsigned int)ret_val & 0xFF);
+}
+
+int spawnl(const char *name, const char *arg, ...) {
+ /*
+ * NOTE: We assume the standard ABI specification for the i386
+ * architecture. This code may not work if used in other
+ * circumstances, including non-variadic functions, different
+ * architectures and calling conventions.
+ */
+
+ return spawnv(name, &arg);
+}
+
+
+void exec_term() {
+ modules_term();
+}
diff --git a/com32/elflink/exec.h b/com32/elflink/exec.h
new file mode 100644
index 00000000..e2be29b0
--- /dev/null
+++ b/com32/elflink/exec.h
@@ -0,0 +1,48 @@
+/*
+ * exec.h
+ *
+ * Created on: Aug 14, 2008
+ * Author: Stefan Bucur <stefanb@zytor.com>
+ */
+
+#ifndef EXEC_H_
+#define EXEC_H_
+
+#include <sys/module.h>
+
+#define EXEC_ROOT_NAME "_root_.dyn"
+
+#define EXEC_DIRECTORY "/dyn/"
+
+/**
+ * exec_init - Initialize the dynamic execution environment.
+ */
+extern int exec_init();
+
+/**
+ * load_library - Loads a dynamic library into the environment.
+ */
+extern int load_library(const char *name);
+
+/**
+ * unload_library - unloads a library from the environment.
+ */
+extern int unload_library(const char *name);
+
+/**
+ * spawnv - Executes a program in the current environment.
+ */
+extern int spawnv(const char *name, const char **argv);
+
+/**
+ * spawnl - Executes a program in the current environment.
+ */
+extern int spawnl(const char *name, const char *arg, ...);
+
+/**
+ * exec_term - Releases the resources of the execution environment.
+ */
+extern void exec_term();
+
+
+#endif /* EXEC_H_ */
diff --git a/com32/elflink/modules/hello.c b/com32/elflink/modules/hello.c
index 2386ecb3..dc87004d 100644
--- a/com32/elflink/modules/hello.c
+++ b/com32/elflink/modules/hello.c
@@ -16,11 +16,11 @@
#define MAX_NUM 100
-static int hello_init(void) {
+static int hello_main(int argc, char **argv) {
int *nums = NULL;
int i;
- printf("Hello, world, from 0x%08X!\n", (unsigned int)&hello_init);
+ printf("Hello, world, from 0x%08X!\n", (unsigned int)&hello_main);
nums = malloc(NUM_COUNT*sizeof(int));
@@ -47,9 +47,5 @@ static int hello_init(void) {
return 0;
}
-static void hello_exit(void) {
- printf("Good bye, cruel world!\n");
-}
-MODULE_INIT(hello_init);
-MODULE_EXIT(hello_exit);
+MODULE_MAIN(hello_main);
diff --git a/com32/include/sys/module.h b/com32/include/sys/module.h
index fc712695..66008d2f 100644
--- a/com32/include/sys/module.h
+++ b/com32/include/sys/module.h
@@ -42,6 +42,8 @@ typedef int (*module_init_t)(void);
*/
typedef void (*module_exit_t)(void);
+typedef int (*module_main_t)(int, char**);
+
/**
* struct elf_module - structure encapsulating a module loaded in memory.
@@ -80,6 +82,7 @@ struct elf_module {
module_init_t *init_func; // The initialization entry point
module_exit_t *exit_func; // The module finalization code
+ module_main_t *main_func; // The main function (for executable modules)
void *module_addr; // The module location in the memory
@@ -123,13 +126,14 @@ struct module_dep {
* This portion is included by dynamic (ELF) module source files.
*/
-
-
#define MODULE_INIT(fn) static module_init_t __module_init \
- __used __attribute__((section(".ctors_module"))) = fn
+ __used __attribute__((section(".ctors_modinit"))) = fn
#define MODULE_EXIT(fn) static module_exit_t __module_exit \
- __used __attribute__((section(".dtors_module"))) = fn
+ __used __attribute__((section(".dtors_modexit"))) = fn
+
+#define MODULE_MAIN(fn) static module_main_t __module_main \
+ __used __attribute__((section(".ctors_modmain"))) = fn
#else
@@ -153,6 +157,7 @@ struct module_dep {
*/
#define MODULE_ELF_INIT_PTR "__module_init_ptr" // Initialization pointer symbol name
#define MODULE_ELF_EXIT_PTR "__module_exit_ptr" // Finalization pointer symbol name
+#define MODULE_ELF_MAIN_PTR "__module_main_ptr" // Entry pointer symbol name
/**
* modules_init - initialize the module subsystem.
diff --git a/com32/lib/elf32.ld b/com32/lib/elf32.ld
index 3704ff10..e41f9c91 100644
--- a/com32/lib/elf32.ld
+++ b/com32/lib/elf32.ld
@@ -91,8 +91,12 @@ SECTIONS
__ctors_start = .;
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
+ LONG(0x00000000)
__module_init_ptr = .;
- KEEP (*(.ctors_module))
+ KEEP (*(.ctors_modinit))
+ LONG(0x00000000)
+ __module_main_ptr = .;
+ KEEP (*(.ctors_modmain))
LONG(0x00000000)
}
@@ -101,8 +105,9 @@ SECTIONS
__dtors_start = .;
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
+ LONG(0x00000000)
__module_exit_ptr = .;
- KEEP (*(.dtors_module))
+ KEEP (*(.dtors_modexit))
LONG(0x00000000)
}
diff --git a/com32/lib/sys/module/common.h b/com32/lib/sys/module/common.h
index 9b13afca..d46dcc38 100644
--- a/com32/lib/sys/module/common.h
+++ b/com32/lib/sys/module/common.h
@@ -29,7 +29,7 @@
#ifdef ELF_DEBUG
-#define DBG_PRINT(fmt, args...) fprintf(stderr, "[DBG] " fmt, ##args)
+#define DBG_PRINT(fmt, args...) fprintf(stderr, "[ELF] " fmt, ##args)
#else
#define DBG_PRINT(fmt, args...) // Expand to nothing
#endif
diff --git a/com32/lib/sys/module/elf_module.c b/com32/lib/sys/module/elf_module.c
index 669c2533..0adba718 100644
--- a/com32/lib/sys/module/elf_module.c
+++ b/com32/lib/sys/module/elf_module.c
@@ -384,13 +384,18 @@ static int resolve_symbols(struct elf_module *module) {
static int extract_operations(struct elf_module *module) {
Elf32_Sym *init_sym = module_find_symbol(MODULE_ELF_INIT_PTR, module);
Elf32_Sym *exit_sym = module_find_symbol(MODULE_ELF_EXIT_PTR, module);
+ Elf32_Sym *main_sym = module_find_symbol(MODULE_ELF_MAIN_PTR, module);
if (init_sym == NULL) {
- DBG_PRINT("Cannot find initialization routine.\n");
+ DBG_PRINT("Cannot find initialization routine pointer.\n");
return -1;
}
if (exit_sym == NULL) {
- DBG_PRINT("Cannot find exit routine.\n");
+ DBG_PRINT("Cannot find exit routine pointer.\n");
+ return -1;
+ }
+ if (main_sym == NULL) {
+ DBG_PRINT("Cannot find main routine pointer.\n");
return -1;
}
@@ -400,6 +405,9 @@ static int extract_operations(struct elf_module *module) {
module->exit_func = (module_exit_t*)module_get_absolute(
exit_sym->st_value, module);
+ module->main_func = (module_main_t*)module_get_absolute(
+ main_sym->st_value, module);
+
return 0;
}