summaryrefslogtreecommitdiff
path: root/com32/lib/sys/module/x86_64/elf_module.c
diff options
context:
space:
mode:
Diffstat (limited to 'com32/lib/sys/module/x86_64/elf_module.c')
-rw-r--r--com32/lib/sys/module/x86_64/elf_module.c190
1 files changed, 109 insertions, 81 deletions
diff --git a/com32/lib/sys/module/x86_64/elf_module.c b/com32/lib/sys/module/x86_64/elf_module.c
index 2ff2e20b..3c164996 100644
--- a/com32/lib/sys/module/x86_64/elf_module.c
+++ b/com32/lib/sys/module/x86_64/elf_module.c
@@ -5,20 +5,20 @@
* Author: Stefan Bucur <stefanb@zytor.com>
*/
-
+#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <elf.h>
#include <dprintf.h>
+#include <core.h>
#include <linux/list.h>
#include <sys/module.h>
+#include <sys/exec.h>
#include "elfutils.h"
-#include "common.h"
-
-#define MAX_NR_DEPS 64
+#include "../common.h"
static int check_header(Elf64_Ehdr *elf_hdr) {
int res;
@@ -50,7 +50,7 @@ static int check_header(Elf64_Ehdr *elf_hdr) {
static int load_segments(struct elf_module *module, Elf64_Ehdr *elf_hdr) {
int i;
int res = 0;
- void *pht = NULL;
+ char *pht = NULL;
Elf64_Phdr *cr_pht;
Elf64_Addr min_addr = 0x0000000000000000; // Min. ELF vaddr
@@ -136,8 +136,8 @@ static int load_segments(struct elf_module *module, Elf64_Ehdr *elf_hdr) {
// headers
Elf64_Off aux_off = module->u.l._cr_offset - cr_pht->p_offset;
- if (image_read(module_get_absolute(cr_pht->p_vaddr, module) + aux_off,
- cr_pht->p_filesz - aux_off, module) < 0) {
+ if (image_read((char *)module_get_absolute(cr_pht->p_vaddr, module) + aux_off,
+ cr_pht->p_filesz - aux_off, module) < 0) {
res = -1;
goto out;
}
@@ -180,9 +180,6 @@ out:
return res;
}
-static int nr_needed;
-static Elf64_Word needed[MAX_NR_DEPS];;
-
static int prepare_dynlinking(struct elf_module *module) {
Elf64_Dyn *dyn_entry = module->dyn_table;
@@ -195,8 +192,8 @@ static int prepare_dynlinking(struct elf_module *module) {
* are then inform the user that we ran out of
* space.
*/
- if (nr_needed < MAX_NR_DEPS)
- needed[nr_needed++] = dyn_entry->d_un.d_ptr;
+ if (module->nr_needed < MAX_NR_DEPS)
+ module->needed[module->nr_needed++] = dyn_entry->d_un.d_ptr;
else {
printf("Too many dependencies!\n");
return -1;
@@ -242,6 +239,11 @@ static int prepare_dynlinking(struct elf_module *module) {
return 0;
}
+void undefined_symbol(void)
+{
+ printf("Error: An undefined symbol was referenced\n");
+ kaboom();
+}
static int perform_relocation(struct elf_module *module, Elf64_Rel *rel) {
Elf64_Xword *dest = module_get_absolute(rel->r_offset, module);
@@ -259,8 +261,7 @@ static int perform_relocation(struct elf_module *module, Elf64_Rel *rel) {
// Find out details about the symbol
// The symbol reference
- Elf64_Sym *sym_ref =
- (Elf64_Sym*)(module->sym_table + sym * module->syment_size);
+ Elf64_Sym *sym_ref = symbol_get_entry(module, sym);
// The symbol definition
sym_def =
@@ -268,11 +269,16 @@ static int perform_relocation(struct elf_module *module, Elf64_Rel *rel) {
&sym_module);
if (sym_def == NULL) {
- // This should never happen
DBG_PRINT("Cannot perform relocation for symbol %s\n",
module->str_table + sym_ref->st_name);
- return -1;
+ if (ELF64_ST_BIND(sym_ref->st_info) != STB_WEAK)
+ return -1;
+
+ // This must be a derivative-specific
+ // function. We're OK as long as we never
+ // execute the function.
+ sym_def = global_find_symbol("undefined_symbol", &sym_module);
}
// Compute the absolute symbol virtual address
@@ -422,73 +428,93 @@ static int resolve_symbols(struct elf_module *module) {
res = perform_relocation(module, crt_rel);
- if (res < 0) {
+ if (res < 0)
return res;
- }
}
}
return 0;
}
+static int extract_operations(struct elf_module *module) {
+ Elf64_Sym *ctors_start, *ctors_end;
+ Elf64_Sym *dtors_start, *dtors_end;
+ module_ctor_t *ctors = NULL;
+ module_ctor_t *dtors = NULL;
+ ctors_start = module_find_symbol("__ctors_start", module);
+ ctors_end = module_find_symbol("__ctors_end", module);
-static int extract_operations(struct elf_module *module) {
- Elf64_Sym *init_sym = module_find_symbol(MODULE_ELF_INIT_PTR, module);
- Elf64_Sym *exit_sym = module_find_symbol(MODULE_ELF_EXIT_PTR, module);
- Elf64_Sym *main_sym = module_find_symbol("main", module);
-
- if (init_sym) {
- module->init_func = (module_init_t*)module_get_absolute(
- init_sym->st_value, module);
- if (*(module->init_func) == NULL) {
- module->init_func = NULL;
- }
- }
+ if (ctors_start && ctors_end) {
+ module_ctor_t *start, *end;
+ int nr_ctors = 0;
+ int i, size;
+
+ start = module_get_absolute(ctors_start->st_value, module);
+ end = module_get_absolute(ctors_end->st_value, module);
+
+ nr_ctors = end - start;
- if (exit_sym) {
- module->exit_func = (module_exit_t*)module_get_absolute(
- exit_sym->st_value, module);
- if (*(module->exit_func) == NULL) {
- module->exit_func = NULL;
+ size = nr_ctors * sizeof(module_ctor_t);
+ size += sizeof(module_ctor_t); /* NULL entry */
+
+ ctors = malloc(size);
+ if (!ctors) {
+ printf("Unable to alloc memory for ctors\n");
+ return -1;
}
+
+ memset(ctors, 0, size);
+ for (i = 0; i < nr_ctors; i++)
+ ctors[i] = start[i];
+
+ module->ctors = ctors;
}
- if (main_sym)
- module->main_func =
- module_get_absolute(main_sym->st_value, module);
+ dtors_start = module_find_symbol("__dtors_start", module);
+ dtors_end = module_find_symbol("__dtors_end", module);
- return 0;
-}
+ if (dtors_start && dtors_end) {
+ module_ctor_t *start, *end;
+ int nr_dtors = 0;
+ int i, size;
-void print_elf_ehdr(Elf64_Ehdr *ehdr) {
- int i;
+ start = module_get_absolute(dtors_start->st_value, module);
+ end = module_get_absolute(dtors_end->st_value, module);
+
+ nr_dtors = end - start;
+
+ size = nr_dtors * sizeof(module_ctor_t);
+ size += sizeof(module_ctor_t); /* NULL entry */
+
+ dtors = malloc(size);
+ if (!dtors) {
+ printf("Unable to alloc memory for dtors\n");
+ free(ctors);
+ return -1;
+ }
- printf("Identification:\t");
- for (i=0; i < EI_NIDENT; i++) {
- printf("%d ", ehdr->e_ident[i]);
+ memset(dtors, 0, size);
+ for (i = 0; i < nr_dtors; i++)
+ dtors[i] = start[i];
+
+ module->dtors = dtors;
}
- printf("\n");
- printf("Type:\t\t%u\n", ehdr->e_type);
- printf("Machine:\t%u\n", ehdr->e_machine);
- printf("Version:\t%u\n", ehdr->e_version);
- printf("Entry:\t\t0x%08x\n", ehdr->e_entry);
- printf("PHT Offset:\t0x%08x\n", ehdr->e_phoff);
- printf("SHT Offset:\t0x%08x\n", ehdr->e_shoff);
- //fprintf(stderr, "Flags:\t\t%u\n", ehdr->e_flags);
- //fprintf(stderr, "Header size:\t%u (Structure size: %u)\n", ehdr->e_ehsize,sizeof(Elf64_Ehdr));
- printf("phnum: %d shnum: %d\n", ehdr->e_phnum,
- ehdr->e_shnum);
+
+ return 0;
}
+
// Loads the module into the system
int module_load(struct elf_module *module) {
int res;
+ Elf64_Sym *main_sym;
Elf64_Ehdr elf_hdr;
+ module_ctor_t *ctor;
// Do not allow duplicate modules
if (module_find(module->name) != NULL) {
DBG_PRINT("Module %s is already loaded.\n", module->name);
- return -1;
+ return EEXIST;
}
// Get a mapping/copy of the ELF file in memory
@@ -512,45 +538,37 @@ int module_load(struct elf_module *module) {
// Load the segments in the memory
CHECKED(res, load_segments(module, &elf_hdr), error);
- //!!!!! Passed load_segments....
//printf("bleah... 3\n");
// Obtain dynamic linking information
- nr_needed = 0;
CHECKED(res, prepare_dynlinking(module), error);
//printf("check... 4\n");
- //
- //dump_elf_module(module);
/* Find modules we need to load as dependencies */
if (module->str_table) {
- int i, n;
+ int i;
/*
- * nr_needed can be modified by recursive calls to
- * module_load() so keep a local copy on the stack.
+ * Note that we have to load the dependencies in
+ * reverse order.
*/
- n = nr_needed;
- for (i = 0; i < n; i++) {
- size_t len, j;
+ for (i = module->nr_needed - 1; i >= 0; i--) {
char *dep, *p;
+ char *argv[2] = { NULL, NULL };
- dep = module->str_table + needed[i];
+ dep = module->str_table + module->needed[i];
/* strip everything but the last component */
- j = len = strlen(dep);
- if (!len)
+ if (!strlen(dep))
continue;
- p = dep + len - 1;
- while (j > 0 && *p && *p != '/') {
- p--;
- j--;
- }
+ if (strchr(dep, '/')) {
+ p = strrchr(dep, '/');
+ p++;
+ } else
+ p = dep;
- if (*p++ == '/') {
- char argv[2] = { p, NULL };
- spawn_load(p, 1, argv);
- }
+ argv[0] = p;
+ spawn_load(p, 1, argv);
}
}
@@ -558,8 +576,11 @@ int module_load(struct elf_module *module) {
CHECKED(res, check_symbols(module), error);
//printf("check... 5\n");
- // Obtain constructors and destructors
- CHECKED(res, extract_operations(module), error);
+ main_sym = module_find_symbol("main", module);
+ if (main_sym)
+ module->main_func =
+ module_get_absolute(main_sym->st_value, module);
+
//printf("check... 6\n");
// Add the module at the beginning of the module list
@@ -568,6 +589,9 @@ int module_load(struct elf_module *module) {
// Perform the relocations
resolve_symbols(module);
+ // Obtain constructors and destructors
+ CHECKED(res, extract_operations(module), error);
+
//dprintf("module->symtable_size = %d\n", module->symtable_size);
//print_elf_symbols(module);
@@ -582,6 +606,10 @@ int module_load(struct elf_module *module) {
(module->init_func == NULL) ? NULL : *(module->init_func),
(module->exit_func == NULL) ? NULL : *(module->exit_func));
*/
+
+ for (ctor = module->ctors; *ctor; ctor++)
+ (*ctor) ();
+
return 0;
error: