aboutsummaryrefslogtreecommitdiffstats
path: root/elf
diff options
context:
space:
mode:
Diffstat (limited to 'elf')
-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);
}