aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Bucur <stefanb@zytor.com>2008-06-12 20:25:47 +0300
committerStefan Bucur <stefan@stefan-ubumac.(none)>2009-03-15 10:02:14 +0200
commitc452160ab1e3f591f50dde0a7168d5275e17efb8 (patch)
treeb3967a3aa4a56cf5a564487e48b27fd4ae8a9c7e
parentc43ab81a5f04e294edf3fbb4691647a0174bf310 (diff)
downloadsyslinux-elf-c452160ab1e3f591f50dde0a7168d5275e17efb8.tar.gz
syslinux-elf-c452160ab1e3f591f50dde0a7168d5275e17efb8.tar.xz
syslinux-elf-c452160ab1e3f591f50dde0a7168d5275e17efb8.zip
The first functional prototype of module linking.
Although the code is currently a little messy, one could see that when she loads hello_def and hello_ref modules (in that order), the functions that handle the shared symbol perform correctly when tested by the main program. There is one initialization function that stores 100 in the symbol, and a second one that reads the symbol, returns its value and increments it.
-rw-r--r--elf/Makefile15
-rw-r--r--elf/TODO3
-rw-r--r--elf/elf_module.c73
-rw-r--r--elf/elftest.c65
-rw-r--r--elf/hello_def.c16
-rw-r--r--elf/hello_ref.c (renamed from elf/hello.c)8
6 files changed, 129 insertions, 51 deletions
diff --git a/elf/Makefile b/elf/Makefile
index e5edfaa3..e7d0ba64 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -10,7 +10,7 @@ RM = rm -f
################
# Build options
-CFLAGS = -Wall -DELF_USERSPACE_TEST
+CFLAGS = -g3 -O0 -Wall -DELF_USERSPACE_TEST
LDFLAGS =
@@ -20,8 +20,6 @@ LDFLAGS =
# Test executable name
TESTPROG = elftest
-# Test module name
-TESTMODULE = hello.so
###############
# Make targets
@@ -38,10 +36,13 @@ $(TESTPROG): elftest.o elf_module.o elf_utils.o
# The shared module to test on
-test-module: $(TESTMODULE)
+test-module: hello_def.so hello_ref.so
-# $(TESTMODULE): CFLAGS += -fPIC
-$(TESTMODULE): hello.o
+
+hello_def.so: hello_def.o
+ $(CC) -shared -o $@ $^
+
+hello_ref.so: hello_ref.o
$(CC) -shared -o $@ $^
@@ -49,5 +50,5 @@ $(TESTMODULE): hello.o
clean:
-$(RM) *.o
-$(RM) $(TESTPROG)
- -$(RM) $(TESTMODULE)
+ -$(RM) *.so
diff --git a/elf/TODO b/elf/TODO
new file mode 100644
index 00000000..9dc92fe3
--- /dev/null
+++ b/elf/TODO
@@ -0,0 +1,3 @@
+* Check to see whether the module is already inserted.
+* Perform unloading cleanup properly.
+* Create a macro for reporting debugging information.
diff --git a/elf/elf_module.c b/elf/elf_module.c
index 7e3b7dde..a91b1f1b 100644
--- a/elf/elf_module.c
+++ b/elf/elf_module.c
@@ -364,29 +364,60 @@ static int prepare_dynlinking(struct elf_module *module) {
static int perform_relocation(struct elf_module *module, Elf32_Rel *rel) {
Elf32_Word *dest = module_get_absolute(rel->r_offset, module);
+ // The symbol reference index
Elf32_Word sym = ELF32_R_SYM(rel->r_info);
unsigned char type = ELF32_R_TYPE(rel->r_info);
+ // The symbol definition (if applicable)
+ Elf32_Sym *sym_def = NULL;
+ struct elf_module *sym_module = NULL;
+ Elf32_Addr sym_addr = 0x0;
+
+ if (sym > 0) {
+ // Find out details about the symbol
+
+ // The symbol reference
+ Elf32_Sym *sym_ref =
+ (Elf32_Sym*)(module->sym_table + sym * module->syment_size);
+
+ // The symbol definition
+ sym_def =
+ global_find_symbol(module->str_table + sym_ref->st_name,
+ &sym_module);
+
+ if (sym_def == NULL) {
+ fprintf(stderr, "Cannot perform relocation for symbol %s\n",
+ module->str_table + sym_ref->st_name);
+ return 0;
+ }
+
+ // Compute the absolute symbol virtual address
+ sym_addr = (Elf32_Addr)module_get_absolute(sym_def->st_value, sym_module);
+
+ }
+
switch (type) {
case R_386_NONE:
// Do nothing
break;
case R_386_32:
+ *dest += sym_addr;
break;
case R_386_PC32:
+ *dest += sym_addr - (Elf32_Addr)dest;
break;
case R_386_COPY:
+ if (sym_addr > 0) {
+ memcpy((void*)dest, (void*)sym_addr, sym_def->st_size);
+ }
break;
case R_386_GLOB_DAT:
- break;
case R_386_JMP_SLOT:
+ // Maybe TODO: Keep track of the GOT entries allocations
+ *dest = sym_addr;
break;
case R_386_RELATIVE:
- *dest = module->base_addr + *dest;
- break;
- case R_386_GOTOFF:
- break;
- case R_386_GOTPC:
+ *dest += module->base_addr;
break;
default:
fprintf(stderr, "Relocation type %d not supported\n", type);
@@ -488,7 +519,7 @@ static int check_symbols(struct elf_module *module) {
int weak_count;
// The chain count gives the number of symbols
- for (i = 0; i < module->hash_table[1]; i++) {
+ for (i = 1; i < module->hash_table[1]; i++) {
crt_sym = (Elf32_Sym*)(module->sym_table + i * module->syment_size);
crt_name = module->str_table + crt_sym->st_name;
@@ -515,12 +546,12 @@ static int check_symbols(struct elf_module *module) {
// We have an undefined symbol
if (strong_count == 0 && weak_count == 0) {
fprintf(stderr, "Symbol %s is undefined\n", crt_name);
- return -1;
+ //return -1;
}
} else {
if (strong_count > 0 && ELF32_ST_BIND(ref_sym->st_info) == STB_GLOBAL) {
- fprintf(stderr, "Symbol %s is defined more than once\n", crt_name);
- return -1;
+ fprintf(stderr, "Warning: Symbol %s is defined more than once\n", crt_name);
+ //return -1;
}
}
}
@@ -553,12 +584,21 @@ int module_load(struct elf_module *module) {
// DEBUG
print_elf_ehdr(elf_hdr);
+ // Load the segments in the memory
CHECKED(res, load_segments(module), error);
+ // Obtain dynamic linking information
CHECKED(res, prepare_dynlinking(module), error);
// DEBUG
print_elf_symbols(module);
+ // Check the symbols for duplicates / missing definitions
+ CHECKED(res, check_symbols(module), error);
+
+ // Add the module at the beginning of the module list
+ list_add(&module->list, &modules);
+
+ // Perform the relocations
CHECKED(res, resolve_symbols(module), error);
// The file image is no longer needed
@@ -606,8 +646,8 @@ Elf32_Sym *module_find_symbol(const char *name, struct elf_module *module) {
Elf32_Sym *global_find_symbol(const char *name, struct elf_module **module) {
struct elf_module *crt_module;
- Elf32_Sym *crt_sym;
- Elf32_Sym *result;
+ Elf32_Sym *crt_sym = NULL;
+ Elf32_Sym *result = NULL;
list_for_each_entry(crt_module, &modules, list) {
crt_sym = module_find_symbol(name, crt_module);
@@ -620,10 +660,13 @@ Elf32_Sym *global_find_symbol(const char *name, struct elf_module **module) {
}
return crt_sym;
case STB_WEAK:
- if (module != NULL) {
- *module = crt_module;
+ // Consider only the first weak symbol
+ if (result == NULL) {
+ if (module != NULL) {
+ *module = crt_module;
+ }
+ result = crt_sym;
}
- result = crt_sym;
break;
}
}
diff --git a/elf/elftest.c b/elf/elftest.c
index 3495ad11..7013938e 100644
--- a/elf/elftest.c
+++ b/elf/elftest.c
@@ -11,7 +11,28 @@
void print_usage() {
fprintf(stderr, "Usage:\n");
- fprintf(stderr, "\telftest objfile [symbol ...]\n");
+ fprintf(stderr, "\telftest objfile ...\n");
+}
+
+void test_hello() {
+ int i;
+
+ struct elf_module *module;
+ Elf32_Sym *symbol;
+
+ symbol = global_find_symbol("undef_func", &module);
+
+ void (*undef_func)(int) = module_get_absolute(symbol->st_value, module);
+
+ symbol = global_find_symbol("test_func", &module);
+
+ int (*test_func)(void) = module_get_absolute(symbol->st_value, module);
+
+ undef_func(0);
+
+ for (i=0; i < 10; i++) {
+ printf("%d\n", test_func());
+ }
}
int main(int argc, char **argv) {
@@ -28,45 +49,35 @@ int main(int argc, char **argv) {
return 1;
}
- module_name = argv[0];
-
res = modules_init();
-
+
if (res < 0) {
fprintf(stderr, "Could not initialize module subsystem\n");
exit(1);
}
- module = module_alloc(module_name);
-
- if (module == NULL) {
- fprintf(stderr, "Could not allocate the module\n");
- goto error;
- }
-
- res = module_load(module);
-
- if (res < 0) {
- fprintf(stderr, "Could not load the module\n");
- goto error;
- }
-
- argc--;
- argv++;
-
while (argc > 0) {
- if (module_find_symbol(argv[0], module) != NULL) {
- printf("Symbol %s found\n", argv[0]);
- } else {
- printf("Symbol %s not found\n", argv[0]);
+ module_name = argv[0];
+
+ module = module_alloc(module_name);
+
+ if (module == NULL) {
+ fprintf(stderr, "Could not allocate the module\n");
+ goto error;
+ }
+
+ res = module_load(module);
+
+ if (res < 0) {
+ fprintf(stderr, "Could not load the module\n");
+ goto error;
}
argc--;
argv++;
}
-
- module_unload(module);
+ test_hello();
modules_term();
diff --git a/elf/hello_def.c b/elf/hello_def.c
new file mode 100644
index 00000000..2ad60233
--- /dev/null
+++ b/elf/hello_def.c
@@ -0,0 +1,16 @@
+
+int undef_symbol;
+
+void undef_func(int param) {
+ undef_symbol = 100;
+}
+
+static int hello_init(void) {
+ // Do nothing
+
+ return 0;
+}
+
+static void hello_exit(void) {
+ // Do nothing
+}
diff --git a/elf/hello.c b/elf/hello_ref.c
index 1dd46d92..f7b798b4 100644
--- a/elf/hello.c
+++ b/elf/hello_ref.c
@@ -11,12 +11,16 @@ int exported_symbol;
// Undefined function
extern void undef_func(int param);
-int hello_init() {
+int test_func(void) {
+ return undef_symbol++;
+}
+
+static int hello_init(void) {
undef_symbol++;
return 0;
}
-void hello_exit() {
+static void hello_exit(void) {
undef_func(undef_symbol);
}