aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Fleming <matt.fleming@intel.com>2012-08-13 18:25:07 +0100
committerMatt Fleming <matt.fleming@intel.com>2012-08-13 19:21:14 +0100
commita98721fcd284bfc73bf5b5c422760817f0ba8bb2 (patch)
tree6481745c1f021d4a113a5bf5c9b8558e555a9ef0
parente2722c1c2fdc3ff6a25a95922d1333bba950b02c (diff)
downloadsyslinux-a98721fcd284bfc73bf5b5c422760817f0ba8bb2.tar.gz
syslinux-a98721fcd284bfc73bf5b5c422760817f0ba8bb2.tar.xz
syslinux-a98721fcd284bfc73bf5b5c422760817f0ba8bb2.zip
module: Consolidate lots of 32/64-bit code
Only carry different code for i386/x86-64 if we really need it. There's plenty of code that can be shared between the two which eases the maintenance burden and also makes it easier to merge code from other branches which don't have the 32/64 split. Signed-off-by: Matt Fleming <matt.fleming@intel.com>
-rw-r--r--com32/lib/sys/module/elf_module.c311
-rw-r--r--com32/lib/sys/module/i386/common.h65
-rw-r--r--com32/lib/sys/module/i386/elf_module.c285
-rw-r--r--com32/lib/sys/module/x86_64/common.h64
-rw-r--r--com32/lib/sys/module/x86_64/elf_module.c286
-rw-r--r--com32/lib/sys/module/x86_64/elfutils.h64
-rw-r--r--mk/lib.mk2
7 files changed, 19 insertions, 1058 deletions
diff --git a/com32/lib/sys/module/elf_module.c b/com32/lib/sys/module/elf_module.c
index b220e1ad..d9732729 100644
--- a/com32/lib/sys/module/elf_module.c
+++ b/com32/lib/sys/module/elf_module.c
@@ -20,7 +20,7 @@
#include "elfutils.h"
#include "common.h"
-static int check_header(Elf32_Ehdr *elf_hdr) {
+static int check_header(Elf_Ehdr *elf_hdr) {
int res;
res = check_header_common(elf_hdr);
@@ -47,141 +47,10 @@ static int check_header(Elf32_Ehdr *elf_hdr) {
* in the PHT sorted by their offsets, so that only forward seeks would
* be necessary.
*/
-static int load_segments(struct elf_module *module, Elf32_Ehdr *elf_hdr) {
- int i;
- int res = 0;
- char *pht = NULL;
- Elf32_Phdr *cr_pht;
-
- Elf32_Addr min_addr = 0x00000000; // Min. ELF vaddr
- Elf32_Addr max_addr = 0x00000000; // Max. ELF vaddr
- Elf32_Word max_align = sizeof(void*); // Min. align of posix_memalign()
- Elf32_Addr min_alloc, max_alloc; // Min. and max. aligned allocables
-
- Elf32_Addr dyn_addr = 0x00000000;
-
- // Get to the PHT
- image_seek(elf_hdr->e_phoff, module);
-
- // Load the PHT
- pht = malloc(elf_hdr->e_phnum * elf_hdr->e_phentsize);
- image_read(pht, elf_hdr->e_phnum * elf_hdr->e_phentsize, module);
-
- // Compute the memory needings of the module
- for (i=0; i < elf_hdr->e_phnum; i++) {
- cr_pht = (Elf32_Phdr*)(pht + i * elf_hdr->e_phentsize);
-
- switch (cr_pht->p_type) {
- case PT_LOAD:
- if (i == 0) {
- min_addr = cr_pht->p_vaddr;
- } else {
- min_addr = MIN(min_addr, cr_pht->p_vaddr);
- }
-
- max_addr = MAX(max_addr, cr_pht->p_vaddr + cr_pht->p_memsz);
- max_align = MAX(max_align, cr_pht->p_align);
- break;
- case PT_DYNAMIC:
- dyn_addr = cr_pht->p_vaddr;
- break;
- default:
- // Unsupported - ignore
- break;
- }
- }
-
- if (max_addr - min_addr == 0) {
- // No loadable segments
- DBG_PRINT("No loadable segments found\n");
- goto out;
- }
-
- if (dyn_addr == 0) {
- DBG_PRINT("No dynamic information segment found\n");
- goto out;
- }
-
- // The minimum address that should be allocated
- min_alloc = min_addr - (min_addr % max_align);
-
- // The maximum address that should be allocated
- max_alloc = max_addr - (max_addr % max_align);
- if (max_addr % max_align > 0)
- max_alloc += max_align;
-
-
- if (elf_malloc(&module->module_addr,
- max_align,
- max_alloc-min_alloc) != 0) {
-
- DBG_PRINT("Could not allocate segments\n");
- goto out;
- }
-
- module->base_addr = (Elf32_Addr)(module->module_addr) - min_alloc;
- module->module_size = max_alloc - min_alloc;
-
- // Zero-initialize the memory
- memset(module->module_addr, 0, module->module_size);
-
- for (i = 0; i < elf_hdr->e_phnum; i++) {
- cr_pht = (Elf32_Phdr*)(pht + i * elf_hdr->e_phentsize);
-
- if (cr_pht->p_type == PT_LOAD) {
- // Copy the segment at its destination
- if (cr_pht->p_offset < module->u.l._cr_offset) {
- // The segment contains data before the current offset
- // It can be discarded without worry - it would contain only
- // headers
- Elf32_Off aux_off = module->u.l._cr_offset - cr_pht->p_offset;
-
- 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;
- }
- } else {
- if (image_seek(cr_pht->p_offset, module) < 0) {
- res = -1;
- goto out;
- }
-
- if (image_read(module_get_absolute(cr_pht->p_vaddr, module),
- cr_pht->p_filesz, module) < 0) {
- res = -1;
- goto out;
- }
- }
-
- /*
- DBG_PRINT("Loadable segment of size 0x%08x copied from vaddr 0x%08x at 0x%08x\n",
- cr_pht->p_filesz,
- cr_pht->p_vaddr,
- (Elf32_Addr)module_get_absolute(cr_pht->p_vaddr, module));
- */
- }
- }
-
- // Setup dynamic segment location
- module->dyn_table = module_get_absolute(dyn_addr, module);
-
- /*
- DBG_PRINT("Base address: 0x%08x, aligned at 0x%08x\n", module->base_addr,
- max_align);
- DBG_PRINT("Module size: 0x%08x\n", module->module_size);
- */
-
-out:
- // Free up allocated memory
- if (pht != NULL)
- free(pht);
-
- return res;
-}
+extern int load_segments(struct elf_module *module, Elf_Ehdr *elf_hdr);
static int prepare_dynlinking(struct elf_module *module) {
- Elf32_Dyn *dyn_entry = module->dyn_table;
+ Elf_Dyn *dyn_entry = module->dyn_table;
while (dyn_entry->d_tag != DT_NULL) {
switch (dyn_entry->d_tag) {
@@ -201,11 +70,11 @@ static int prepare_dynlinking(struct elf_module *module) {
break;
case DT_HASH:
module->hash_table =
- (Elf32_Word*)module_get_absolute(dyn_entry->d_un.d_ptr, module);
+ (Elf_Word*)module_get_absolute(dyn_entry->d_un.d_ptr, module);
break;
case DT_GNU_HASH:
module->ghash_table =
- (Elf32_Word*)module_get_absolute(dyn_entry->d_un.d_ptr, module);
+ (Elf_Word*)module_get_absolute(dyn_entry->d_un.d_ptr, module);
break;
case DT_STRTAB:
module->str_table =
@@ -245,168 +114,12 @@ void undefined_symbol(void)
kaboom();
}
-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 = symbol_get_entry(module, sym);
-
- // The symbol definition
- sym_def =
- global_find_symbol(module->str_table + sym_ref->st_name,
- &sym_module);
-
- if (sym_def == NULL) {
- DBG_PRINT("Cannot perform relocation for symbol %s\n",
- module->str_table + sym_ref->st_name);
-
- if (ELF32_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
- sym_addr = (Elf32_Addr)module_get_absolute(sym_def->st_value, sym_module);
-
- if (sym_module != module) {
- // Create a dependency
- enforce_dependency(sym_module, 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:
- 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;
- break;
- default:
- DBG_PRINT("Relocation type %d not supported\n", type);
- return -1;
- }
-
- return 0;
-}
-
-static int resolve_symbols(struct elf_module *module) {
- Elf32_Dyn *dyn_entry = module->dyn_table;
- unsigned int i;
- int res;
-
- Elf32_Word plt_rel_size = 0;
- char *plt_rel = NULL;
-
- char *rel = NULL;
- Elf32_Word rel_size = 0;
- Elf32_Word rel_entry = 0;
-
- // The current relocation
- Elf32_Rel *crt_rel;
-
- while (dyn_entry->d_tag != DT_NULL) {
- switch(dyn_entry->d_tag) {
-
- // PLT relocation information
- case DT_PLTRELSZ:
- plt_rel_size = dyn_entry->d_un.d_val;
- break;
- case DT_PLTREL:
- if (dyn_entry->d_un.d_val != DT_REL) {
- DBG_PRINT("Unsupported PLT relocation\n");
- return -1;
- }
- case DT_JMPREL:
- plt_rel = module_get_absolute(dyn_entry->d_un.d_ptr, module);
- break;
-
- // Standard relocation information
- case DT_REL:
- rel = module_get_absolute(dyn_entry->d_un.d_ptr, module);
- break;
- case DT_RELSZ:
- rel_size = dyn_entry->d_un.d_val;
- break;
- case DT_RELENT:
- rel_entry = dyn_entry->d_un.d_val;
- break;
-
- // Module initialization and termination
- case DT_INIT:
- // TODO Implement initialization functions
- break;
- case DT_FINI:
- // TODO Implement finalization functions
- break;
- }
-
- dyn_entry++;
- }
-
- if (rel_size > 0) {
- // Process standard relocations
- for (i = 0; i < rel_size/rel_entry; i++) {
- crt_rel = (Elf32_Rel*)(rel + i*rel_entry);
-
- res = perform_relocation(module, crt_rel);
-
- if (res < 0)
- return res;
- }
-
- }
-
- if (plt_rel_size > 0) {
- // TODO: Permit this lazily
- // Process PLT relocations
- for (i = 0; i < plt_rel_size/sizeof(Elf32_Rel); i++) {
- crt_rel = (Elf32_Rel*)(plt_rel + i*sizeof(Elf32_Rel));
-
- res = perform_relocation(module, crt_rel);
-
- if (res < 0)
- return res;
- }
- }
-
- return 0;
-}
+extern int perform_relocation(struct elf_module *module, Elf_Rel *rel);
+extern int resolve_symbols(struct elf_module *module);
static int extract_operations(struct elf_module *module) {
- Elf32_Sym *ctors_start, *ctors_end;
- Elf32_Sym *dtors_start, *dtors_end;
+ Elf_Sym *ctors_start, *ctors_end;
+ Elf_Sym *dtors_start, *dtors_end;
module_ctor_t *ctors = NULL;
module_ctor_t *dtors = NULL;
@@ -475,8 +188,8 @@ static int extract_operations(struct elf_module *module) {
// Loads the module into the system
int module_load(struct elf_module *module) {
int res;
- Elf32_Sym *main_sym;
- Elf32_Ehdr elf_hdr;
+ Elf_Sym *main_sym;
+ Elf_Ehdr elf_hdr;
module_ctor_t *ctor;
// Do not allow duplicate modules
@@ -495,7 +208,7 @@ int module_load(struct elf_module *module) {
// The module is a fully featured dynamic library
module->shallow = 0;
- CHECKED(res, image_read(&elf_hdr, sizeof(Elf32_Ehdr), module), error);
+ CHECKED(res, image_read(&elf_hdr, sizeof(Elf_Ehdr), module), error);
//printf("check... 1\n");
//print_elf_ehdr(&elf_hdr);
diff --git a/com32/lib/sys/module/i386/common.h b/com32/lib/sys/module/i386/common.h
deleted file mode 100644
index 6259df51..00000000
--- a/com32/lib/sys/module/i386/common.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * common.h - Common internal operations performed by the module subsystem
- *
- * Created on: Aug 11, 2008
- * Author: Stefan Bucur <stefanb@zytor.com>
- */
-
-#ifndef COMMON_H_
-#define COMMON_H_
-
-#include <stdio.h>
-
-#include <sys/module.h>
-#include <linux/list.h>
-
-#include "elfutils.h"
-
-
-// Performs an operation and jumps to a given label if an error occurs
-#define CHECKED(res, expr, error) \
- do { \
- (res) = (expr); \
- if ((res) < 0) \
- goto error; \
- } while (0)
-
-#define MIN(x,y) (((x) < (y)) ? (x) : (y))
-#define MAX(x,y) (((x) > (y)) ? (x) : (y))
-
-//#define ELF_DEBUG
-
-#ifdef ELF_DEBUG
-#define DBG_PRINT(fmt, args...) fprintf(stderr, "[ELF] " fmt, ##args)
-#else
-#define DBG_PRINT(fmt, args...) // Expand to nothing
-#endif
-
-// User-space debugging routines
-#ifdef ELF_DEBUG
-extern void print_elf_ehdr(Elf32_Ehdr *ehdr);
-extern void print_elf_symbols(struct elf_module *module);
-#endif //ELF_DEBUG
-
-
-/*
- * Image files manipulation routines
- */
-
-extern int image_load(struct elf_module *module);
-extern int image_unload(struct elf_module *module);
-extern int image_read(void *buff, size_t size, struct elf_module *module);
-extern int image_skip(size_t size, struct elf_module *module);
-extern int image_seek(Elf32_Off offset, struct elf_module *module);
-
-extern struct module_dep *module_dep_alloc(struct elf_module *module);
-
-extern int check_header_common(Elf32_Ehdr *elf_hdr);
-
-extern int enforce_dependency(struct elf_module *req, struct elf_module *dep);
-extern int clear_dependency(struct elf_module *req, struct elf_module *dep);
-
-extern int check_symbols(struct elf_module *module);
-
-
-#endif /* COMMON_H_ */
diff --git a/com32/lib/sys/module/i386/elf_module.c b/com32/lib/sys/module/i386/elf_module.c
index f4a8618a..d0eb1a8e 100644
--- a/com32/lib/sys/module/i386/elf_module.c
+++ b/com32/lib/sys/module/i386/elf_module.c
@@ -20,34 +20,13 @@
#include "elfutils.h"
#include "../common.h"
-static int check_header(Elf32_Ehdr *elf_hdr) {
- int res;
-
- res = check_header_common(elf_hdr);
-
- if (res != 0)
- return res;
-
- if (elf_hdr->e_type != MODULE_ELF_TYPE) {
- DBG_PRINT("The ELF file must be a shared object\n");
- return -1;
- }
-
- if (elf_hdr->e_phoff == 0x00000000) {
- DBG_PRINT("PHT missing\n");
- return -1;
- }
-
- return 0;
-}
-
/*
*
* The implementation assumes that the loadable segments are present
* in the PHT sorted by their offsets, so that only forward seeks would
* be necessary.
*/
-static int load_segments(struct elf_module *module, Elf32_Ehdr *elf_hdr) {
+int load_segments(struct elf_module *module, Elf_Ehdr *elf_hdr) {
int i;
int res = 0;
char *pht = NULL;
@@ -180,72 +159,7 @@ out:
return res;
}
-static int prepare_dynlinking(struct elf_module *module) {
- Elf32_Dyn *dyn_entry = module->dyn_table;
-
- while (dyn_entry->d_tag != DT_NULL) {
- switch (dyn_entry->d_tag) {
- case DT_NEEDED:
- /*
- * It's unlikely there'll be more than
- * MAX_NR_DEPS DT_NEEDED entries but if there
- * are then inform the user that we ran out of
- * space.
- */
- 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;
- }
- break;
- case DT_HASH:
- module->hash_table =
- (Elf32_Word*)module_get_absolute(dyn_entry->d_un.d_ptr, module);
- break;
- case DT_GNU_HASH:
- module->ghash_table =
- (Elf32_Word*)module_get_absolute(dyn_entry->d_un.d_ptr, module);
- break;
- case DT_STRTAB:
- module->str_table =
- (char*)module_get_absolute(dyn_entry->d_un.d_ptr, module);
- break;
- case DT_SYMTAB:
- module->sym_table =
- module_get_absolute(dyn_entry->d_un.d_ptr, module);
- break;
- case DT_STRSZ:
- module->strtable_size = dyn_entry->d_un.d_val;
- break;
- case DT_SYMENT:
- module->syment_size = dyn_entry->d_un.d_val;
- break;
- case DT_PLTGOT: // The first entry in the GOT
- module->got = module_get_absolute(dyn_entry->d_un.d_ptr, module);
- break;
- }
-
- dyn_entry++;
- }
-
- // Now compute the number of symbols in the symbol table
- if (module->ghash_table != NULL) {
- module->symtable_size = module->ghash_table[1];
- } else {
- module->symtable_size = module->hash_table[1];
- }
-
- return 0;
-}
-
-void undefined_symbol(void)
-{
- printf("Error: An undefined symbol was referenced\n");
- kaboom();
-}
-
-static int perform_relocation(struct elf_module *module, Elf32_Rel *rel) {
+int perform_relocation(struct elf_module *module, Elf_Rel *rel) {
Elf32_Word *dest = module_get_absolute(rel->r_offset, module);
// The symbol reference index
@@ -321,7 +235,7 @@ static int perform_relocation(struct elf_module *module, Elf32_Rel *rel) {
return 0;
}
-static int resolve_symbols(struct elf_module *module) {
+int resolve_symbols(struct elf_module *module) {
Elf32_Dyn *dyn_entry = module->dyn_table;
unsigned int i;
int res;
@@ -404,196 +318,3 @@ static int resolve_symbols(struct elf_module *module) {
return 0;
}
-static int extract_operations(struct elf_module *module) {
- Elf32_Sym *ctors_start, *ctors_end;
- Elf32_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);
-
- 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;
-
- 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;
- }
-
- dtors_start = module_find_symbol("__dtors_start", module);
- dtors_end = module_find_symbol("__dtors_end", module);
-
- if (dtors_start && dtors_end) {
- module_ctor_t *start, *end;
- int nr_dtors = 0;
- int i, size;
-
- 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;
- }
-
- memset(dtors, 0, size);
- for (i = 0; i < nr_dtors; i++)
- dtors[i] = start[i];
-
- module->dtors = dtors;
- }
-
- return 0;
-}
-
-// Loads the module into the system
-int module_load(struct elf_module *module) {
- int res;
- Elf32_Sym *main_sym;
- Elf32_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 EEXIST;
- }
-
- // Get a mapping/copy of the ELF file in memory
- res = image_load(module);
-
- if (res < 0) {
- return res;
- }
-
- // The module is a fully featured dynamic library
- module->shallow = 0;
-
- CHECKED(res, image_read(&elf_hdr, sizeof(Elf32_Ehdr), module), error);
- //printf("check... 1\n");
-
- //print_elf_ehdr(&elf_hdr);
-
- // Checking the header signature and members
- CHECKED(res, check_header(&elf_hdr), error);
- //printf("check... 2\n");
-
- // Load the segments in the memory
- CHECKED(res, load_segments(module, &elf_hdr), error);
- //printf("bleah... 3\n");
- // Obtain dynamic linking information
- CHECKED(res, prepare_dynlinking(module), error);
- //printf("check... 4\n");
-
- /* Find modules we need to load as dependencies */
- if (module->str_table) {
- int i;
-
- /*
- * Note that we have to load the dependencies in
- * reverse order.
- */
- for (i = module->nr_needed - 1; i >= 0; i--) {
- char *dep, *p;
- char *argv[2] = { NULL, NULL };
-
- dep = module->str_table + module->needed[i];
-
- /* strip everything but the last component */
- if (!strlen(dep))
- continue;
-
- if (strchr(dep, '/')) {
- p = strrchr(dep, '/');
- p++;
- } else
- p = dep;
-
- argv[0] = p;
- spawn_load(p, 1, argv);
- }
- }
-
- // Check the symbols for duplicates / missing definitions
- CHECKED(res, check_symbols(module), error);
- //printf("check... 5\n");
-
- 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
- list_add(&module->list, &modules_head);
-
- // 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);
-
- // The file image is no longer needed
- image_unload(module);
-
- /*
- DBG_PRINT("MODULE %s LOADED SUCCESSFULLY (main@%p, init@%p, exit@%p)\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));
- */
-
- for (ctor = module->ctors; *ctor; ctor++)
- (*ctor) ();
-
- return 0;
-
-error:
- // Remove the module from the module list (if applicable)
- list_del_init(&module->list);
-
- if (module->module_addr != NULL) {
- elf_free(module->module_addr);
- module->module_addr = NULL;
- }
-
- image_unload(module);
-
- // Clear the execution part of the module buffer
- memset(&module->u, 0, sizeof module->u);
-
- return res;
-}
-
diff --git a/com32/lib/sys/module/x86_64/common.h b/com32/lib/sys/module/x86_64/common.h
deleted file mode 100644
index e7946f91..00000000
--- a/com32/lib/sys/module/x86_64/common.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * common.h - Common internal operations performed by the module subsystem
- *
- * Created on: Aug 11, 2008
- * Author: Stefan Bucur <stefanb@zytor.com>
- */
-
-#ifndef COMMON_H_
-#define COMMON_H_
-
-#include <stdio.h>
-
-#include <sys/module.h>
-#include <linux/list.h>
-
-#include "elfutils.h"
-
-// Performs an operation and jumps to a given label if an error occurs
-#define CHECKED(res, expr, error) \
- do { \
- (res) = (expr); \
- if ((res) < 0) \
- goto error; \
- } while (0)
-
-#define MIN(x,y) (((x) < (y)) ? (x) : (y))
-#define MAX(x,y) (((x) > (y)) ? (x) : (y))
-
-//#define ELF_DEBUG
-
-#ifdef ELF_DEBUG
-#define DBG_PRINT(fmt, args...) fprintf(stderr, "[ELF] " fmt, ##args)
-#else
-#define DBG_PRINT(fmt, args...) // Expand to nothing
-#endif
-
-// User-space debugging routines
-#ifdef ELF_DEBUG
-extern void print_elf_ehdr(Elf64_Ehdr *ehdr);
-extern void print_elf_symbols(struct elf_module *module);
-#endif //ELF_DEBUG
-
-
-/*
- * Image files manipulation routines
- */
-
-extern int image_load(struct elf_module *module);
-extern int image_unload(struct elf_module *module);
-extern int image_read(void *buff, size_t size, struct elf_module *module);
-extern int image_skip(size_t size, struct elf_module *module);
-extern int image_seek(Elf64_Off offset, struct elf_module *module);
-
-extern struct module_dep *module_dep_alloc(struct elf_module *module);
-
-extern int check_header_common(Elf64_Ehdr *elf_hdr);
-
-extern int enforce_dependency(struct elf_module *req, struct elf_module *dep);
-extern int clear_dependency(struct elf_module *req, struct elf_module *dep);
-
-extern int check_symbols(struct elf_module *module);
-
-
-#endif /* COMMON_H_ */
diff --git a/com32/lib/sys/module/x86_64/elf_module.c b/com32/lib/sys/module/x86_64/elf_module.c
index 3c164996..9300f989 100644
--- a/com32/lib/sys/module/x86_64/elf_module.c
+++ b/com32/lib/sys/module/x86_64/elf_module.c
@@ -20,34 +20,13 @@
#include "elfutils.h"
#include "../common.h"
-static int check_header(Elf64_Ehdr *elf_hdr) {
- int res;
-
- res = check_header_common(elf_hdr);
-
- if (res != 0)
- return res;
-
- if (elf_hdr->e_type != MODULE_ELF_TYPE) {
- DBG_PRINT("The ELF file must be a shared object\n");
- return -1;
- }
-
- if (elf_hdr->e_phoff == 0x00000000) {
- DBG_PRINT("PHT missing\n");
- return -1;
- }
-
- return 0;
-}
-
/*
*
* The implementation assumes that the loadable segments are present
* in the PHT sorted by their offsets, so that only forward seeks would
* be necessary.
*/
-static int load_segments(struct elf_module *module, Elf64_Ehdr *elf_hdr) {
+int load_segments(struct elf_module *module, Elf_Ehdr *elf_hdr) {
int i;
int res = 0;
char *pht = NULL;
@@ -180,72 +159,7 @@ out:
return res;
}
-static int prepare_dynlinking(struct elf_module *module) {
- Elf64_Dyn *dyn_entry = module->dyn_table;
-
- while (dyn_entry->d_tag != DT_NULL) {
- switch (dyn_entry->d_tag) {
- case DT_NEEDED:
- /*
- * It's unlikely there'll be more than
- * MAX_NR_DEPS DT_NEEDED entries but if there
- * are then inform the user that we ran out of
- * space.
- */
- 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;
- }
- break;
- case DT_HASH:
- module->hash_table =
- (Elf64_Word*)module_get_absolute(dyn_entry->d_un.d_ptr, module);
- break;
- case DT_GNU_HASH:
- module->ghash_table =
- (Elf64_Word*)module_get_absolute(dyn_entry->d_un.d_ptr, module);
- break;
- case DT_STRTAB:
- module->str_table =
- (char*)module_get_absolute(dyn_entry->d_un.d_ptr, module);
- break;
- case DT_SYMTAB:
- module->sym_table =
- module_get_absolute(dyn_entry->d_un.d_ptr, module);
- break;
- case DT_STRSZ:
- module->strtable_size = dyn_entry->d_un.d_val;
- break;
- case DT_SYMENT:
- module->syment_size = dyn_entry->d_un.d_val;
- break;
- case DT_PLTGOT: // The first entry in the GOT
- module->got = module_get_absolute(dyn_entry->d_un.d_ptr, module);
- break;
- }
-
- dyn_entry++;
- }
-
- // Now compute the number of symbols in the symbol table
- if (module->ghash_table != NULL) {
- module->symtable_size = module->ghash_table[1];
- } else {
- module->symtable_size = module->hash_table[1];
- }
-
- 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) {
+int perform_relocation(struct elf_module *module, Elf_Rel *rel) {
Elf64_Xword *dest = module_get_absolute(rel->r_offset, module);
// The symbol reference index
@@ -321,7 +235,7 @@ static int perform_relocation(struct elf_module *module, Elf64_Rel *rel) {
return 0;
}
-static int resolve_symbols(struct elf_module *module) {
+int resolve_symbols(struct elf_module *module) {
Elf64_Dyn *dyn_entry = module->dyn_table;
unsigned int i;
int res;
@@ -435,197 +349,3 @@ static int resolve_symbols(struct elf_module *module) {
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);
-
- 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;
-
- 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;
- }
-
- dtors_start = module_find_symbol("__dtors_start", module);
- dtors_end = module_find_symbol("__dtors_end", module);
-
- if (dtors_start && dtors_end) {
- module_ctor_t *start, *end;
- int nr_dtors = 0;
- int i, size;
-
- 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;
- }
-
- memset(dtors, 0, size);
- for (i = 0; i < nr_dtors; i++)
- dtors[i] = start[i];
-
- module->dtors = dtors;
- }
-
- 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 EEXIST;
- }
-
- // Get a mapping/copy of the ELF file in memory
- res = image_load(module);
-
- if (res < 0) {
- return res;
- }
-
- // The module is a fully featured dynamic library
- module->shallow = 0;
-
- CHECKED(res, image_read(&elf_hdr, sizeof(Elf64_Ehdr), module), error);
- //printf("check... 1\n");
-
- //print_elf_ehdr(&elf_hdr);
-
- // Checking the header signature and members
- CHECKED(res, check_header(&elf_hdr), error);
- //printf("check... 2\n");
-
- // Load the segments in the memory
- CHECKED(res, load_segments(module, &elf_hdr), error);
- //printf("bleah... 3\n");
- // Obtain dynamic linking information
- CHECKED(res, prepare_dynlinking(module), error);
- //printf("check... 4\n");
-
- /* Find modules we need to load as dependencies */
- if (module->str_table) {
- int i;
-
- /*
- * Note that we have to load the dependencies in
- * reverse order.
- */
- for (i = module->nr_needed - 1; i >= 0; i--) {
- char *dep, *p;
- char *argv[2] = { NULL, NULL };
-
- dep = module->str_table + module->needed[i];
-
- /* strip everything but the last component */
- if (!strlen(dep))
- continue;
-
- if (strchr(dep, '/')) {
- p = strrchr(dep, '/');
- p++;
- } else
- p = dep;
-
- argv[0] = p;
- spawn_load(p, 1, argv);
- }
- }
-
- // Check the symbols for duplicates / missing definitions
- CHECKED(res, check_symbols(module), error);
- //printf("check... 5\n");
-
- 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
- list_add(&module->list, &modules_head);
-
- // 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);
-
- // The file image is no longer needed
- image_unload(module);
-
- /*
- DBG_PRINT("MODULE %s LOADED SUCCESSFULLY (main@%p, init@%p, exit@%p)\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));
- */
-
- for (ctor = module->ctors; *ctor; ctor++)
- (*ctor) ();
-
- return 0;
-
-error:
- // Remove the module from the module list (if applicable)
- list_del_init(&module->list);
-
- if (module->module_addr != NULL) {
- elf_free(module->module_addr);
- module->module_addr = NULL;
- }
-
- image_unload(module);
-
- // Clear the execution part of the module buffer
- memset(&module->u, 0, sizeof module->u);
-
- return res;
-}
-
diff --git a/com32/lib/sys/module/x86_64/elfutils.h b/com32/lib/sys/module/x86_64/elfutils.h
deleted file mode 100644
index dbfc7608..00000000
--- a/com32/lib/sys/module/x86_64/elfutils.h
+++ /dev/null
@@ -1,64 +0,0 @@
-#ifndef ELF_UTILS_H_
-#define ELF_UTILS_H_
-
-#include <elf.h>
-#include <stdlib.h>
-
-/**
- * elf_get_header - Returns a pointer to the ELF header structure.
- * @elf_image: pointer to the ELF file image in memory
- */
-static inline Elf64_Ehdr *elf_get_header(void *elf_image) {
- return (Elf64_Ehdr*)elf_image;
-}
-
-/**
- * elf_get_pht - Returns a pointer to the first entry in the PHT.
- * @elf_image: pointer to the ELF file image in memory
- */
-static inline Elf64_Phdr *elf_get_pht(void *elf_image) {
- Elf64_Ehdr *elf_hdr = elf_get_header(elf_image);
-
- return (Elf64_Phdr*)((Elf64_Off)elf_hdr + elf_hdr->e_phoff);
-}
-
-//
-/**
- * elf_get_ph - Returns the element with the given index in the PTH
- * @elf_image: pointer to the ELF file image in memory
- * @index: the index of the PHT entry to look for
- */
-static inline Elf64_Phdr *elf_get_ph(void *elf_image, int index) {
- Elf64_Phdr *elf_pht = elf_get_pht(elf_image);
- Elf64_Ehdr *elf_hdr = elf_get_header(elf_image);
-
- return (Elf64_Phdr*)((Elf64_Off)elf_pht + index * elf_hdr->e_phentsize);
-}
-
-/**
- * elf_hash - Returns the index in a SysV hash table for the symbol name.
- * @name: the name of the symbol to look for
- */
-extern unsigned long elf_hash(const unsigned char *name);
-
-/**
- * elf_gnu_hash - Returns the index in a GNU hash table for the symbol name.
- * @name: the name of the symbol to look for
- */
-extern unsigned long elf_gnu_hash(const unsigned char *name);
-
-/**
- * elf_malloc - Allocates memory to be used by ELF module contents.
- * @memptr: pointer to a variable to hold the address of the allocated block.
- * @alignment: alignment constraints of the block
- * @size: the required size of the block
- */
-extern int elf_malloc(void **memptr, size_t alignment, size_t size);
-
-/**
- * elf_free - Releases memory previously allocated by elf_malloc.
- * @memptr: the address of the allocated block
- */
-extern void elf_free(void *memptr);
-
-#endif /*ELF_UTILS_H_*/
diff --git a/mk/lib.mk b/mk/lib.mk
index 14bb327f..d2780b2b 100644
--- a/mk/lib.mk
+++ b/mk/lib.mk
@@ -171,7 +171,7 @@ LIBLOAD_OBJS = \
LIBMODULE_OBJS = \
sys/module/common.o sys/module/$(ARCH)/elf_module.o \
sys/module/$(ARCH)/shallow_module.o sys/module/elfutils.o \
- sys/module/exec.o
+ sys/module/exec.o sys/module/elf_module.o
# ZIP library object files
LIBZLIB_OBJS = \