aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Bucur <stefan@stefan-mac.(none)>2009-07-04 19:47:29 +0300
committerStefan Bucur <stefan@stefan-mac.(none)>2009-07-04 19:47:29 +0300
commit2ab2c16e359d266719ce8639ca0fa057d0f7a099 (patch)
treea3907756a1b2ed01e630ddbf114929d72ebd2631
parentc9d910a68845661946d1e040faaa4f46076fd64f (diff)
downloadsyslinux-elf-2ab2c16e359d266719ce8639ca0fa057d0f7a099.tar.gz
syslinux-elf-2ab2c16e359d266719ce8639ca0fa057d0f7a099.tar.xz
syslinux-elf-2ab2c16e359d266719ce8639ca0fa057d0f7a099.zip
Added support in shallow modules to offset symbols.
The symbol values can be offset so that they could match a memory region, in case it is created dynamically and the symbol table does not include the offsets.
-rw-r--r--com32/elflink/test_com32.c4
-rw-r--r--com32/include/sys/exec.h3
-rw-r--r--com32/include/sys/module.h2
-rw-r--r--com32/lib/sys/module/elf_module.c8
-rw-r--r--com32/lib/sys/module/exec.c4
-rw-r--r--com32/lib/sys/module/shallow_module.c25
6 files changed, 38 insertions, 8 deletions
diff --git a/com32/elflink/test_com32.c b/com32/elflink/test_com32.c
index 115bba87..20c19cf7 100644
--- a/com32/elflink/test_com32.c
+++ b/com32/elflink/test_com32.c
@@ -8,6 +8,8 @@
#define INFO_PRINT(fmt, args...) printf("[COM32] " fmt, ##args)
+#define COM32_OFFSET 0x110000
+
#define MAX_COMMAND_SIZE 80 // Maximum size of the cmd line
#define COMMAND_DELIM " \t\n" // Whitespace delimiters
#define MAX_COMMAND_ARGS (MAX_COMMAND_SIZE/2) // Maximum argument count for
@@ -179,7 +181,7 @@ int main(int argc, char **argv) {
// Open a standard r/w console
openconsole(&dev_stdcon_r, &dev_stdcon_w);
- res = exec_init();
+ res = exec_init(COM32_OFFSET);
if (res != 0) {
printf("Failed to initialize the execution environment.\n");
return res;
diff --git a/com32/include/sys/exec.h b/com32/include/sys/exec.h
index 7b3a9a0c..d76ae74c 100644
--- a/com32/include/sys/exec.h
+++ b/com32/include/sys/exec.h
@@ -9,6 +9,7 @@
#define EXEC_H_
#include <sys/module.h>
+#include <stdlib.h>
/**
* EXEC_ROOT_NAME - The name of the ELF module associated with the COM32 module.
@@ -41,7 +42,7 @@
* loaded by the lower module layer gets to be executed by the CPU,
* thus becoming part of the SYSLINUX environment.
*/
-extern int exec_init();
+extern int exec_init(size_t root_addr);
/**
diff --git a/com32/include/sys/module.h b/com32/include/sys/module.h
index e09f1bf8..97f7ce09 100644
--- a/com32/include/sys/module.h
+++ b/com32/include/sys/module.h
@@ -229,7 +229,7 @@ extern int module_load(struct elf_module *module);
* Its current use is to describe the root COM32 module to the rest of the
* module subsystem.
*/
-extern int module_load_shallow(struct elf_module *module);
+extern int module_load_shallow(struct elf_module *module, Elf32_Off offset);
/**
* module_unload - unloads the module from the system.
diff --git a/com32/lib/sys/module/elf_module.c b/com32/lib/sys/module/elf_module.c
index 4b1f2bbd..99b0c17b 100644
--- a/com32/lib/sys/module/elf_module.c
+++ b/com32/lib/sys/module/elf_module.c
@@ -417,6 +417,7 @@ static int extract_operations(struct elf_module *module) {
module->main_func = NULL;
}
+
return 0;
}
@@ -468,8 +469,11 @@ int module_load(struct elf_module *module) {
// The file image is no longer needed
image_unload(module);
- DBG_PRINT("MODULE %s LOADED SUCCESSFULLY (init@0x%08X, exit@0x%08X)\n",
- module->name, *(module->init_func), *(module->exit_func));
+ DBG_PRINT("MODULE %s LOADED SUCCESSFULLY (main@0x%08X, init@0x%08X, exit@0x%08X)\n",
+ module->name,
+ (module->main_func == NULL) ? NULL : *(module->main_func),
+ (module->init_func == NULL) ? NULL : *(module->init_func),
+ (module->exit_func == NULL) ? NULL : *(module->exit_func));
return 0;
diff --git a/com32/lib/sys/module/exec.c b/com32/lib/sys/module/exec.c
index 3cd53187..9da1d572 100644
--- a/com32/lib/sys/module/exec.c
+++ b/com32/lib/sys/module/exec.c
@@ -30,7 +30,7 @@ static char *module_get_fullname(const char *name) {
return name_buff;
}
-int exec_init() {
+int exec_init(size_t root_addr) {
int res;
res = modules_init();
@@ -44,7 +44,7 @@ int exec_init() {
if (mod_root == NULL)
return -1;
- res = module_load_shallow(mod_root);
+ res = module_load_shallow(mod_root, root_addr);
if (res != 0) {
mod_root = NULL;
diff --git a/com32/lib/sys/module/shallow_module.c b/com32/lib/sys/module/shallow_module.c
index f198c0db..f43582c4 100644
--- a/com32/lib/sys/module/shallow_module.c
+++ b/com32/lib/sys/module/shallow_module.c
@@ -115,8 +115,29 @@ out:
return res;
}
+static int offset_symbols(struct elf_module *module, Elf32_Off offset) {
+ unsigned int i;
+ Elf32_Sym *crt_sym = NULL;
+
+ for (i = 1; i < module->symtable_size; i++) {
+ crt_sym = (Elf32_Sym*)(module->sym_table + i*module->syment_size);
+
+ // Skip the undefined or absolute symbols
+ if (crt_sym->st_shndx == SHN_UNDEF || crt_sym->st_shndx == SHN_ABS)
+ continue;
+ // Also skip the non-local symbols
+ if (ELF32_ST_BIND(crt_sym->st_info) != STB_GLOBAL &&
+ ELF32_ST_BIND(crt_sym->st_info) != STB_WEAK)
+ continue;
+
+ crt_sym->st_value += offset;
+ }
+
+ return 0;
+}
+
-int module_load_shallow(struct elf_module *module) {
+int module_load_shallow(struct elf_module *module, Elf32_Off offset) {
int res;
Elf32_Ehdr elf_hdr;
@@ -143,6 +164,8 @@ int module_load_shallow(struct elf_module *module) {
// Check the symbols for duplicates / missing definitions
CHECKED(res, check_symbols(module), error);
+ CHECKED(res, offset_symbols(module, offset), error);
+
// Add the module at the beginning of the module list
list_add(&module->list, &modules_head);