summaryrefslogtreecommitdiff
path: root/com32/lib/sys
diff options
context:
space:
mode:
authorMatt Fleming <matt.fleming@intel.com>2012-07-27 10:41:30 +0100
committerMatt Fleming <matt.fleming@intel.com>2012-07-30 09:51:36 +0100
commit0d6f330878173c7ba45b884f3e41ce40b917c73c (patch)
tree0a887066d35d8b01914330d6ab6818fe015a5a9d /com32/lib/sys
parent0fcd9a48603497dcc2727570a50a4401bb0fd085 (diff)
parentf0bbf9dd40f37f8c4870a33784996efd56955a75 (diff)
downloadsyslinux-0d6f330878173c7ba45b884f3e41ce40b917c73c.tar.gz
Merge remote-tracking branch 'mfleming/elflink' into for-hpa/elflink/firmware
Conflicts: Makefile com32/elflink/ldlinux/adv.c com32/elflink/ldlinux/kernel.c com32/elflink/ldlinux/ldlinux.c com32/include/bitsize/stddef.h com32/include/bitsize/stdint.h com32/include/stdint.h com32/include/sys/module.h com32/include/sys/x86_64/bitops.h com32/include/syslinux/linux.h com32/lib/Makefile com32/lib/sys/ansicon_write.c com32/lib/sys/module/elfutils.h com32/lib/sys/vesa/efi/fill.h com32/lib/syslinux/load_linux.c com32/lib/syslinux/serial.c com32/lib/syslinux/shuffle.c core/conio.c core/elflink/config.c core/elflink/load_env32.c core/graphics.c core/include/graphics.h core/init.c core/pxelinux.asm mk/elf.mk mk/lib.mk
Diffstat (limited to 'com32/lib/sys')
-rw-r--r--com32/lib/sys/ansicon_write.c115
-rw-r--r--com32/lib/sys/fileclose.c1
-rw-r--r--com32/lib/sys/fileread.c1
-rw-r--r--com32/lib/sys/gpxe.c19
-rw-r--r--com32/lib/sys/module/common.c115
-rw-r--r--com32/lib/sys/module/common.h14
-rw-r--r--com32/lib/sys/module/elf_module.c169
-rw-r--r--com32/lib/sys/module/elfutils.c4
-rw-r--r--com32/lib/sys/module/elfutils.h72
-rw-r--r--com32/lib/sys/module/exec.c87
-rw-r--r--com32/lib/sys/module/i386/common.c571
-rw-r--r--com32/lib/sys/module/i386/elf_module.c176
-rw-r--r--com32/lib/sys/module/i386/elfutils.h64
-rw-r--r--com32/lib/sys/module/shallow_module.c8
-rw-r--r--com32/lib/sys/module/x86_64/common.c567
-rw-r--r--com32/lib/sys/module/x86_64/elf_module.c190
-rw-r--r--com32/lib/sys/open.c1
-rw-r--r--com32/lib/sys/rawcon_read.c35
-rw-r--r--com32/lib/sys/rawcon_write.c8
-rw-r--r--com32/lib/sys/serial_write.c8
-rw-r--r--com32/lib/sys/stdcon_write.c15
-rw-r--r--com32/lib/sys/xserial_write.c8
22 files changed, 513 insertions, 1735 deletions
diff --git a/com32/lib/sys/ansicon_write.c b/com32/lib/sys/ansicon_write.c
index a963923d..74add717 100644
--- a/com32/lib/sys/ansicon_write.c
+++ b/com32/lib/sys/ansicon_write.c
@@ -35,7 +35,6 @@
#include <errno.h>
#include <string.h>
-#include <com32.h>
#include <minmax.h>
#include <colortbl.h>
#include <klibc/compiler.h>
@@ -43,6 +42,7 @@
#include "file.h"
#include "ansi.h"
#include <syslinux/firmware.h>
+#include "graphics.h"
static void ansicon_erase(const struct term_state *, int, int, int, int);
static void ansicon_write_char(int, int, uint8_t, const struct term_state *);
@@ -66,53 +66,15 @@ static struct term_info ti = {
.op = &__ansicon_ops
};
-#define BIOS_CURXY ((struct curxy *)0x450) /* Array for each page */
-#define BIOS_ROWS (*(uint8_t *)0x484) /* Minus one; if zero use 24 (= 25 lines) */
-#define BIOS_COLS (*(uint16_t *)0x44A)
-#define BIOS_PAGE (*(uint8_t *)0x462)
-
#define TEXT_MODE 0x0005
/* Reference counter to the screen, to keep track of if we need
reinitialization. */
static int ansicon_counter = 0;
-static uint16_t cursor_type; /* Saved cursor pattern */
-
-void bios_set_mode(uint16_t mode)
-{
- com32sys_t ireg;
-
- ireg.eax.w[0] = mode;
- __intcall(0x22, &ireg, NULL);
-}
-
-void bios_get_mode(int *cols, int *rows)
-{
- *rows = BIOS_ROWS ? BIOS_ROWS + 1 : 25;
- *cols = BIOS_COLS;
-}
-
-void bios_get_cursor(int *x, int *y)
-{
- com32sys_t ireg, oreg;
-
- memset(&ireg, 0, sizeof(ireg));
-
- ireg.eax.b[1] = 0x03;
- ireg.ebx.b[1] = BIOS_PAGE;
- __intcall(0x10, &ireg, &oreg);
- cursor_type = oreg.ecx.w[0];
- *x = oreg.edx.b[0];
- *y = oreg.edx.b[1];
-}
-
/* Common setup */
int __ansicon_open(struct file_info *fp)
{
- static com32sys_t ireg; /* Auto-initalized to all zero */
- com32sys_t oreg;
-
if (!ansicon_counter) {
/* Are we disabled? */
if (syslinux_serial_console_info()->flowctl & 0x8000) {
@@ -175,19 +137,6 @@ static uint8_t ansicon_attribute(const struct term_state *st)
return (bg << 4) | fg;
}
-void bios_erase(int x0, int y0, int x1, int y1, uint8_t attribute)
-{
- static com32sys_t ireg;
-
- ireg.eax.w[0] = 0x0600; /* Clear window */
- ireg.ebx.b[1] = attribute;
- ireg.ecx.b[0] = x0;
- ireg.ecx.b[1] = y0;
- ireg.edx.b[0] = x1;
- ireg.edx.b[1] = y1;
- __intcall(0x10, &ireg, NULL);
-}
-
/* Erase a region of the screen */
static void ansicon_erase(const struct term_state *st,
int x0, int y0, int x1, int y1)
@@ -198,37 +147,10 @@ static void ansicon_erase(const struct term_state *st,
firmware->o_ops->erase(x0, y0, x1, y1, attribute);
}
-void bios_showcursor(uint16_t cursor)
-{
- static com32sys_t ireg;
-
- ireg.eax.b[1] = 0x01;
- ireg.ecx.w[0] = cursor;
- __intcall(0x10, &ireg, NULL);
-}
-
/* Show or hide the cursor */
static void ansicon_showcursor(const struct term_state *st)
{
- uint16_t cursor = st->cursor ? cursor_type : 0x2020;
- firmware->o_ops->showcursor(cursor);
-}
-
-void bios_set_cursor(int x, int y, bool visible)
-{
- const int page = BIOS_PAGE;
- struct curxy xy = BIOS_CURXY[page];
- static com32sys_t ireg;
-
- (void)visible;
-
- if (xy.x != x || xy.y != y) {
- ireg.eax.b[1] = 0x02;
- ireg.ebx.b[1] = page;
- ireg.edx.b[1] = y;
- ireg.edx.b[0] = x;
- __intcall(0x10, &ireg, NULL);
- }
+ firmware->o_ops->showcursor(st);
}
static void ansicon_set_cursor(int x, int y, bool visible)
@@ -236,18 +158,6 @@ static void ansicon_set_cursor(int x, int y, bool visible)
firmware->o_ops->set_cursor(x, y, visible);
}
-void bios_write_char(uint8_t ch, uint8_t attribute)
-{
- static com32sys_t ireg;
-
- ireg.eax.b[1] = 0x09;
- ireg.eax.b[0] = ch;
- ireg.ebx.b[1] = BIOS_PAGE;
- ireg.ebx.b[0] = attribute;
- ireg.ecx.w[0] = 1;
- __intcall(0x10, &ireg, NULL);
-}
-
static void ansicon_write_char(int x, int y, uint8_t ch,
const struct term_state *st)
{
@@ -257,18 +167,6 @@ static void ansicon_write_char(int x, int y, uint8_t ch,
firmware->o_ops->write_char(ch, attribute);
}
-void bios_scroll_up(uint8_t cols, uint8_t rows, uint8_t attribute)
-{
- static com32sys_t ireg;
-
- ireg.eax.w[0] = 0x0601;
- ireg.ebx.b[1] = attribute;
- ireg.ecx.w[0] = 0;
- ireg.edx.b[1] = rows;
- ireg.edx.b[0] = cols;
- __intcall(0x10, &ireg, NULL); /* Scroll */
-}
-
static void ansicon_scroll_up(const struct term_state *st)
{
uint8_t rows, cols, attribute;
@@ -302,15 +200,6 @@ ssize_t __ansicon_write(struct file_info *fp, const void *buf, size_t count)
return n;
}
-void bios_beep(void)
-{
- static com32sys_t ireg;
-
- ireg.eax.w[0] = 0x0e07;
- ireg.ebx.b[1] = BIOS_PAGE;
- __intcall(0x10, &ireg, NULL);
-}
-
void __ansicon_beep(void)
{
if (firmware->o_ops->beep)
diff --git a/com32/lib/sys/fileclose.c b/com32/lib/sys/fileclose.c
index 26e15082..699dbe32 100644
--- a/com32/lib/sys/fileclose.c
+++ b/com32/lib/sys/fileclose.c
@@ -34,6 +34,7 @@
#include <errno.h>
#include <com32.h>
#include <string.h>
+#include <fs.h>
#include "file.h"
int __file_close(struct file_info *fp)
diff --git a/com32/lib/sys/fileread.c b/com32/lib/sys/fileread.c
index 7d9e1b91..26b0ceb6 100644
--- a/com32/lib/sys/fileread.c
+++ b/com32/lib/sys/fileread.c
@@ -34,6 +34,7 @@
#include <errno.h>
#include <string.h>
#include <com32.h>
+#include <pmapi.h>
#include <syslinux/pmapi.h>
#include <minmax.h>
#include "file.h"
diff --git a/com32/lib/sys/gpxe.c b/com32/lib/sys/gpxe.c
index d86da42a..3cc2b845 100644
--- a/com32/lib/sys/gpxe.c
+++ b/com32/lib/sys/gpxe.c
@@ -1,13 +1,15 @@
+#include <string.h>
+
#include <sys/gpxe.h>
#include <syslinux/config.h>
-#include <string.h>
+#include <syslinux/pxe_api.h>
bool is_gpxe(void)
{
const struct syslinux_version *sv;
- com32sys_t reg;
struct s_PXENV_FILE_CHECK_API *fca;
bool gpxe;
+ int err;
sv = syslinux_version();
if (sv->filesystem != SYSLINUX_FS_PXELINUX)
@@ -16,23 +18,18 @@ bool is_gpxe(void)
fca = lzalloc(sizeof *fca);
if (!fca)
return false;
+
fca->Size = sizeof *fca;
fca->Magic = 0x91d447b2;
- memset(&reg, 0, sizeof reg);
- reg.eax.w[0] = 0x0009;
- reg.ebx.w[0] = 0x00e6; /* PXENV_FILE_API_CHECK */
- /* reg.edi.w[0] = OFFS(fca); */
- reg.es = SEG(fca);
-
- __intcall(0x22, &reg, &reg);
+ err = pxe_call(PXENV_FILE_API_CHECK, fca);
gpxe = true;
- if (reg.eflags.l & EFLAGS_CF)
+ if (err)
gpxe = false; /* Cannot invoke PXE stack */
- if (reg.eax.w[0] || fca->Status)
+ if (fca->Status)
gpxe = false; /* PXE failure */
if (fca->Magic != 0xe9c17b20)
diff --git a/com32/lib/sys/module/common.c b/com32/lib/sys/module/common.c
index 1e33db8e..bc058a66 100644
--- a/com32/lib/sys/module/common.c
+++ b/com32/lib/sys/module/common.c
@@ -23,7 +23,7 @@ LIST_HEAD(modules_head);
// User-space debugging routines
#ifdef ELF_DEBUG
-void print_elf_ehdr(Elf32_Ehdr *ehdr) {
+void print_elf_ehdr(Elf_Ehdr *ehdr) {
int i;
fprintf(stderr, "Identification:\t");
@@ -38,18 +38,18 @@ void print_elf_ehdr(Elf32_Ehdr *ehdr) {
fprintf(stderr, "PHT Offset:\t0x%08x\n", ehdr->e_phoff);
fprintf(stderr, "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(Elf32_Ehdr));
+ //fprintf(stderr, "Header size:\t%u (Structure size: %u)\n", ehdr->e_ehsize,sizeof(Elf_Ehdr));
fprintf(stderr, "phnum: %d shnum: %d\n", ehdr->e_phnum,
ehdr->e_shnum);
}
void print_elf_symbols(struct elf_module *module) {
unsigned int i;
- Elf32_Sym *crt_sym;
+ Elf_Sym *crt_sym;
for (i = 1; i < module->symtable_size; i++)
{
- crt_sym = (Elf32_Sym*)(module->sym_table + i*module->syment_size);
+ crt_sym = (Elf_Sym*)(module->sym_table + i*module->syment_size);
fprintf(stderr,"%s %d\n", module->str_table + crt_sym->st_name, crt_sym->st_value);
@@ -64,6 +64,10 @@ static FILE *findpath(char *name)
char *p, *n;
int i;
+ f = fopen(name, "rb"); /* for full path */
+ if (f)
+ return f;
+
p = PATH;
again:
i = 0;
@@ -74,15 +78,6 @@ again:
if (*p == ':')
p++;
- if (!strcmp(path, ".")) {
- if (!core_getcwd(path, sizeof(path))) {
- DBG_PRINT("Could not get cwd\n");
- return NULL;
- }
-
- i = strlen(path);
- }
-
n = name;
while (*n && i < FILENAME_MAX)
path[i++] = *n++;
@@ -164,7 +159,7 @@ int image_skip(size_t size, struct elf_module *module) {
return 0;
}
-int image_seek(Elf32_Off offset, struct elf_module *module) {
+int image_seek(Elf_Off offset, struct elf_module *module) {
if (offset < module->u.l._cr_offset) // Cannot seek backwards
return -1;
@@ -226,7 +221,7 @@ struct elf_module *module_find(const char *name) {
//
// Performs verifications on ELF header to assure that the open file is a
// valid SYSLINUX ELF module.
-int check_header_common(Elf32_Ehdr *elf_hdr) {
+int check_header_common(Elf_Ehdr *elf_hdr) {
// Check the header magic
if (elf_hdr->e_ident[EI_MAG0] != ELFMAG0 ||
elf_hdr->e_ident[EI_MAG1] != ELFMAG1 ||
@@ -237,7 +232,7 @@ int check_header_common(Elf32_Ehdr *elf_hdr) {
return -1;
}
- if (elf_hdr->e_ident[EI_CLASS] != ELFCLASS32 ||
+ if (elf_hdr->e_ident[EI_CLASS] != ELFCLASS32 &&
elf_hdr->e_ident[EI_CLASS] != ELFCLASS64) {
DBG_PRINT("Invalid ELF class code\n");
return -1;
@@ -254,15 +249,17 @@ int check_header_common(Elf32_Ehdr *elf_hdr) {
return -1;
}
- if (elf_hdr->e_machine != EM_386 ||
+ if (elf_hdr->e_machine != EM_386 &&
elf_hdr->e_machine != EM_X86_64) {
DBG_PRINT("Invalid ELF architecture\n");
return -1;
+ }
return 0;
}
+
int enforce_dependency(struct elf_module *req, struct elf_module *dep) {
struct module_dep *crt_dep;
struct module_dep *new_dep;
@@ -319,7 +316,7 @@ int clear_dependency(struct elf_module *req, struct elf_module *dep) {
int check_symbols(struct elf_module *module)
{
unsigned int i;
- Elf32_Sym *crt_sym = NULL, *ref_sym = NULL;
+ Elf_Sym *crt_sym = NULL, *ref_sym = NULL;
char *crt_name;
struct elf_module *crt_module;
@@ -328,11 +325,11 @@ int check_symbols(struct elf_module *module)
for(i = 1; i < module->symtable_size; i++)
{
- crt_sym = (Elf32_Sym*)(module->sym_table + i * module->syment_size);
+ crt_sym = symbol_get_entry(module, i);
crt_name = module->str_table + crt_sym->st_name;
strong_count = 0;
- weak_count = 0;
+ weak_count = (ELF32_ST_BIND(crt_sym->st_info) == STB_WEAK);
for_each_module(crt_module)
{
@@ -356,10 +353,17 @@ int check_symbols(struct elf_module *module)
if (crt_sym->st_shndx == SHN_UNDEF)
{
// We have an undefined symbol
+ //
+ // We use the weak_count to differentiate
+ // between Syslinux-derivative-specific
+ // functions. For example, unload_pxe() is
+ // only provided by PXELINUX, so we mark it as
+ // __weak and replace it with a reference to
+ // undefined_symbol() on SYSLINUX, EXTLINUX,
+ // and ISOLINUX. See perform_relocations().
if (strong_count == 0 && weak_count == 0)
{
DBG_PRINT("Symbol %s is undefined\n", crt_name);
- printf("Undef symbol FAIL: %s\n",crt_name);
return -1;
}
}
@@ -387,7 +391,7 @@ int module_unloadable(struct elf_module *module) {
// Unloads the module from the system and releases all the associated memory
-int module_unload(struct elf_module *module) {
+int _module_unload(struct elf_module *module) {
struct module_dep *crt_dep, *tmp;
// Make sure nobody needs us
if (!module_unloadable(module)) {
@@ -416,23 +420,31 @@ int module_unload(struct elf_module *module) {
return 0;
}
+int module_unload(struct elf_module *module) {
+ module_ctor_t *dtor;
+
+ for (dtor = module->dtors; *dtor; dtor++)
+ (*dtor) ();
+
+ return _module_unload(module);
+}
-static Elf32_Sym *module_find_symbol_sysv(const char *name, struct elf_module *module) {
+static Elf_Sym *module_find_symbol_sysv(const char *name, struct elf_module *module) {
unsigned long h = elf_hash((const unsigned char*)name);
- Elf32_Word *cr_word = module->hash_table;
+ Elf_Word *cr_word = module->hash_table;
- Elf32_Word nbucket = *cr_word++;
+ Elf_Word nbucket = *cr_word++;
cr_word++; // Skip nchain
- Elf32_Word *bkt = cr_word;
- Elf32_Word *chn = cr_word + nbucket;
+ Elf_Word *bkt = cr_word;
+ Elf_Word *chn = cr_word + nbucket;
- Elf32_Word crt_index = bkt[h % module->hash_table[0]];
- Elf32_Sym *crt_sym;
+ Elf_Word crt_index = bkt[h % module->hash_table[0]];
+ Elf_Sym *crt_sym;
while (crt_index != STN_UNDEF) {
- crt_sym = (Elf32_Sym*)(module->sym_table + crt_index*module->syment_size);
+ crt_sym = symbol_get_entry(module, crt_index);
if (strcmp(name, module->str_table + crt_sym->st_name) == 0)
return crt_sym;
@@ -443,32 +455,32 @@ static Elf32_Sym *module_find_symbol_sysv(const char *name, struct elf_module *m
return NULL;
}
-static Elf32_Sym *module_find_symbol_gnu(const char *name, struct elf_module *module) {
+static Elf_Sym *module_find_symbol_gnu(const char *name, struct elf_module *module) {
unsigned long h = elf_gnu_hash((const unsigned char*)name);
// Setup code (TODO: Optimize this by computing only once)
- Elf32_Word *cr_word = module->ghash_table;
- Elf32_Word nbucket = *cr_word++;
- Elf32_Word symbias = *cr_word++;
- Elf32_Word bitmask_nwords = *cr_word++;
+ Elf_Word *cr_word = module->ghash_table;
+ Elf_Word nbucket = *cr_word++;
+ Elf_Word symbias = *cr_word++;
+ Elf_Word bitmask_nwords = *cr_word++;
if ((bitmask_nwords & (bitmask_nwords - 1)) != 0) {
DBG_PRINT("Invalid GNU Hash structure\n");
return NULL;
}
- Elf32_Word gnu_shift = *cr_word++;
+ Elf_Word gnu_shift = *cr_word++;
- Elf32_Addr *gnu_bitmask = (Elf32_Addr*)cr_word;
+ Elf_Addr *gnu_bitmask = (Elf_Addr*)cr_word;
cr_word += MODULE_ELF_CLASS_SIZE / 32 * bitmask_nwords;
- Elf32_Word *gnu_buckets = cr_word;
+ Elf_Word *gnu_buckets = cr_word;
cr_word += nbucket;
- Elf32_Word *gnu_chain_zero = cr_word - symbias;
+ Elf_Word *gnu_chain_zero = cr_word - symbias;
// Computations
- Elf32_Word bitmask_word = gnu_bitmask[(h / MODULE_ELF_CLASS_SIZE) &
+ Elf_Bword bitmask_word = gnu_bitmask[(h / MODULE_ELF_CLASS_SIZE) &
(bitmask_nwords - 1)];
unsigned int hashbit1 = h & (MODULE_ELF_CLASS_SIZE - 1);
@@ -476,19 +488,18 @@ static Elf32_Sym *module_find_symbol_gnu(const char *name, struct elf_module *mo
if ((bitmask_word >> hashbit1) & (bitmask_word >> hashbit2) & 1) {
unsigned long rem;
- Elf32_Word bucket;
+ Elf_Word bucket;
rem = h % nbucket;
bucket = gnu_buckets[rem];
if (bucket != 0) {
- const Elf32_Word* hasharr = &gnu_chain_zero[bucket];
+ const Elf_Word* hasharr = &gnu_chain_zero[bucket];
do {
if (((*hasharr ^ h ) >> 1) == 0) {
- Elf32_Sym *crt_sym = (Elf32_Sym*)(module->sym_table +
- (hasharr - gnu_chain_zero) * module->syment_size);
+ Elf_Sym *crt_sym = symbol_get_entry(module, (hasharr - gnu_chain_zero));
if (strcmp(name, module->str_table + crt_sym->st_name) == 0) {
return crt_sym;
@@ -501,15 +512,15 @@ static Elf32_Sym *module_find_symbol_gnu(const char *name, struct elf_module *mo
return NULL;
}
-static Elf32_Sym *module_find_symbol_iterate(const char *name,struct elf_module *module)
+static Elf_Sym *module_find_symbol_iterate(const char *name,struct elf_module *module)
{
unsigned int i;
- Elf32_Sym *crt_sym;
+ Elf_Sym *crt_sym;
for (i=1; i < module->symtable_size; i++)
{
- crt_sym = (Elf32_Sym*)(module->sym_table + i*module->syment_size);
+ crt_sym = symbol_get_entry(module, i);
if (strcmp(name, module->str_table + crt_sym->st_name) == 0)
{
return crt_sym;
@@ -519,8 +530,8 @@ static Elf32_Sym *module_find_symbol_iterate(const char *name,struct elf_module
return NULL;
}
-Elf32_Sym *module_find_symbol(const char *name, struct elf_module *module) {
- Elf32_Sym *result = NULL;
+Elf_Sym *module_find_symbol(const char *name, struct elf_module *module) {
+ Elf_Sym *result = NULL;
if (module->ghash_table != NULL)
result = module_find_symbol_gnu(name, module);
@@ -542,10 +553,10 @@ Elf32_Sym *module_find_symbol(const char *name, struct elf_module *module) {
return result;
}
-Elf32_Sym *global_find_symbol(const char *name, struct elf_module **module) {
+Elf_Sym *global_find_symbol(const char *name, struct elf_module **module) {
struct elf_module *crt_module;
- Elf32_Sym *crt_sym = NULL;
- Elf32_Sym *result = NULL;
+ Elf_Sym *crt_sym = NULL;
+ Elf_Sym *result = NULL;
for_each_module(crt_module) {
crt_sym = module_find_symbol(name, crt_module);
diff --git a/com32/lib/sys/module/common.h b/com32/lib/sys/module/common.h
index 928fe139..652c9735 100644
--- a/com32/lib/sys/module/common.h
+++ b/com32/lib/sys/module/common.h
@@ -26,6 +26,14 @@
#define MIN(x,y) (((x) < (y)) ? (x) : (y))
#define MAX(x,y) (((x) > (y)) ? (x) : (y))
+static inline Elf_Sym *symbol_get_entry(struct elf_module *module, int entry)
+{
+ char *sym_table = (char *)module->sym_table;
+ int index = entry * module->syment_size;
+
+ return (Elf_Sym *)(sym_table + index);
+}
+
//#define ELF_DEBUG
#ifdef ELF_DEBUG
@@ -36,7 +44,7 @@
// User-space debugging routines
#ifdef ELF_DEBUG
-extern void print_elf_ehdr(Elf32_Ehdr *ehdr);
+extern void print_elf_ehdr(Elf_Ehdr *ehdr);
extern void print_elf_symbols(struct elf_module *module);
#endif //ELF_DEBUG
@@ -49,11 +57,11 @@ 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 int image_seek(Elf_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 check_header_common(Elf_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);
diff --git a/com32/lib/sys/module/elf_module.c b/com32/lib/sys/module/elf_module.c
index 7d8dad42..b220e1ad 100644
--- a/com32/lib/sys/module/elf_module.c
+++ b/com32/lib/sys/module/elf_module.c
@@ -5,21 +5,21 @@
* 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
-
static int check_header(Elf32_Ehdr *elf_hdr) {
int res;
@@ -50,7 +50,7 @@ static int check_header(Elf32_Ehdr *elf_hdr) {
static int load_segments(struct elf_module *module, Elf32_Ehdr *elf_hdr) {
int i;
int res = 0;
- void *pht = NULL;
+ char *pht = NULL;
Elf32_Phdr *cr_pht;
Elf32_Addr min_addr = 0x00000000; // Min. ELF vaddr
@@ -136,8 +136,8 @@ static int load_segments(struct elf_module *module, Elf32_Ehdr *elf_hdr) {
// headers
Elf32_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 Elf32_Word needed[MAX_NR_DEPS];;
-
static int prepare_dynlinking(struct elf_module *module) {
Elf32_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, Elf32_Rel *rel) {
Elf32_Word *dest = module_get_absolute(rel->r_offset, module);
@@ -259,8 +261,7 @@ static int perform_relocation(struct elf_module *module, Elf32_Rel *rel) {
// Find out details about the symbol
// The symbol reference
- Elf32_Sym *sym_ref =
- (Elf32_Sym*)(module->sym_table + sym * module->syment_size);
+ Elf32_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, Elf32_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 (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
@@ -321,9 +327,9 @@ static int resolve_symbols(struct elf_module *module) {
int res;
Elf32_Word plt_rel_size = 0;
- void *plt_rel = NULL;
+ char *plt_rel = NULL;
- void *rel = NULL;
+ char *rel = NULL;
Elf32_Word rel_size = 0;
Elf32_Word rel_entry = 0;
@@ -398,32 +404,70 @@ 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);
-static int extract_operations(struct elf_module *module) {
- Elf32_Sym *init_sym = module_find_symbol(MODULE_ELF_INIT_PTR, module);
- Elf32_Sym *exit_sym = module_find_symbol(MODULE_ELF_EXIT_PTR, module);
- Elf32_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;
+
+ 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 (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;
+ 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;
}
- }
- if (main_sym)
- module->main_func =
- module_get_absolute(main_sym->st_value, module);
+ memset(dtors, 0, size);
+ for (i = 0; i < nr_dtors; i++)
+ dtors[i] = start[i];
+
+ module->dtors = dtors;
+ }
return 0;
}
@@ -431,12 +475,14 @@ 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;
+ 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
@@ -462,42 +508,35 @@ int module_load(struct elf_module *module) {
CHECKED(res, load_segments(module, &elf_hdr), error);
//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);
}
}
@@ -505,8 +544,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
@@ -515,6 +557,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);
@@ -529,6 +574,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:
diff --git a/com32/lib/sys/module/elfutils.c b/com32/lib/sys/module/elfutils.c
index 64be0770..b7d760b4 100644
--- a/com32/lib/sys/module/elfutils.c
+++ b/com32/lib/sys/module/elfutils.c
@@ -37,7 +37,7 @@ struct memalign_info {
};
int elf_malloc(void **memptr, size_t alignment, size_t size) {
- void *start_addr = NULL;
+ char *start_addr = NULL;
struct memalign_info *info;
if ((alignment & (alignment - 1)) != 0)
@@ -63,7 +63,7 @@ int elf_malloc(void **memptr, size_t alignment, size_t size) {
return 0;
}
-void elf_free(void *memptr) {
+void elf_free(char *memptr) {
struct memalign_info *info = (struct memalign_info*)(memptr -
sizeof(struct memalign_info));
diff --git a/com32/lib/sys/module/elfutils.h b/com32/lib/sys/module/elfutils.h
index b6750ae7..91bdcb3f 100644
--- a/com32/lib/sys/module/elfutils.h
+++ b/com32/lib/sys/module/elfutils.h
@@ -1,7 +1,65 @@
-#if __SIZEOF_POINTER__ == 4
-#include <i386/elfutils.h>
-#elif __SIZEOF_POINTER__ == 8
-#include <x86_64/elfutils.h>
-#else
-#error "unsupported architecture"
-#endif
+#ifndef ELF_UTILS_H_
+#define ELF_UTILS_H_
+
+#include <elf.h>
+#include <stdlib.h>
+#include <sys/module.h>
+
+/**
+ * elf_get_header - Returns a pointer to the ELF header structure.
+ * @elf_image: pointer to the ELF file image in memory
+ */
+static inline Elf_Ehdr *elf_get_header(void *elf_image) {
+ return (Elf_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 Elf_Phdr *elf_get_pht(void *elf_image) {
+ Elf_Ehdr *elf_hdr = elf_get_header(elf_image);
+
+ return (Elf_Phdr*)((Elf_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 Elf_Phdr *elf_get_ph(void *elf_image, int index) {
+ Elf_Phdr *elf_pht = elf_get_pht(elf_image);
+ Elf_Ehdr *elf_hdr = elf_get_header(elf_image);
+
+ return (Elf_Phdr*)((Elf_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(char *memptr);
+
+#endif /*ELF_UTILS_H_*/
diff --git a/com32/lib/sys/module/exec.c b/com32/lib/sys/module/exec.c
index 71d31929..29d0a2fd 100644
--- a/com32/lib/sys/module/exec.c
+++ b/com32/lib/sys/module/exec.c
@@ -47,64 +47,7 @@ int exec_init(void)
int get_module_type(struct elf_module *module)
{
if(module->main_func) return EXEC_MODULE;
- else if(module->init_func) return LIB_MODULE;
- return UNKNOWN_MODULE;
-}
-
-int load_library(const char *name)
-{
- int res;
- struct elf_module *module = module_alloc(name);
-
- if (module == NULL)
- return -1;
-
- res = module_load(module);
- if (res != 0) {
- module_unload(module);
- return res;
- }
-
- if (module->main_func != NULL) {
- DBG_PRINT("Cannot load executable module as library.\n");
- module_unload(module);
- return -1;
- }
-
- if (module->init_func != NULL) {
- res = (*(module->init_func))();
- if (res)
- DBG_PRINT("Initialization error! function returned: %d\n", res);
- } else {
- DBG_PRINT("No initialization function present.\n");
- }
-
- if (res != 0) {
- module_unload(module);
- return res;
- }
-
- return 0;
-}
-
-int unload_library(const char *name)
-{
- int res;
- struct elf_module *module = module_find(name);
-
- if (module == NULL)
- return -1;
-
- if (!module_unloadable(module)) {
- return -1;
- }
-
- if (module->exit_func != NULL) {
- (*(module->exit_func))();
- }
-
- res = module_unload(module);
- return res;
+ return LIB_MODULE;
}
jmp_buf __process_exit_jmp;
@@ -243,7 +186,6 @@ int spawn_load(const char *name, int argc, char **argv)
//malloc_tag_t prev_mem_tag;
struct elf_module *module = module_alloc(name);
struct elf_module *prev_module;
-
int type;
dprintf("enter: name = %s", name);
@@ -277,7 +219,7 @@ int spawn_load(const char *name, int argc, char **argv)
res = module_load(module);
if (res != 0) {
- module_unload(module);
+ _module_unload(module);
return res;
}
@@ -288,23 +230,7 @@ int spawn_load(const char *name, int argc, char **argv)
dprintf("type = %d, prev = %s, cur = %s",
type, prev_module->name, cur_module->name);
- if(type==LIB_MODULE)
- {
- if (module->init_func != NULL) {
- res = (*(module->init_func))();
- DBG_PRINT("Initialization function returned: %d\n", res);
- } else {
- DBG_PRINT("No initialization function present.\n");
- }
-
- if (res != 0) {
- cur_module = prev_module;
- module_unload(module);
- return res;
- }
- return 0;
- }
- else if(type==EXEC_MODULE)
+ if(type==EXEC_MODULE)
{
previous = __syslinux_current;
//prev_mem_tag = __mem_get_tag_global();
@@ -323,7 +249,6 @@ int spawn_load(const char *name, int argc, char **argv)
else
exit((module->main_func)(argc, argv)); /* Actually run! */
-
// Clean up the allocation context
//__free_tagged(module);
// Restore the allocation context
@@ -340,10 +265,8 @@ int spawn_load(const char *name, int argc, char **argv)
return ((unsigned int)ret_val & 0xFF);
}
- /*
- module_unload(module);
- return -1;
- */
+
+ return 0;
}
void exec_term(void)
diff --git a/com32/lib/sys/module/i386/common.c b/com32/lib/sys/module/i386/common.c
deleted file mode 100644
index 41e71e83..00000000
--- a/com32/lib/sys/module/i386/common.c
+++ /dev/null
@@ -1,571 +0,0 @@
-/*
- * common.c
- *
- * Created on: Aug 11, 2008
- * Author: Stefan Bucur <stefanb@zytor.com>
- */
-
-#include <stdio.h>
-#include <elf.h>
-#include <string.h>
-#include <fs.h>
-
-#include <linux/list.h>
-#include <sys/module.h>
-
-#include "elfutils.h"
-#include "common.h"
-
-/**
- * The one and only list of loaded modules
- */
-LIST_HEAD(modules_head);
-
-// User-space debugging routines
-#ifdef ELF_DEBUG
-void print_elf_ehdr(Elf32_Ehdr *ehdr) {
- int i;
-
- fprintf(stderr, "Identification:\t");
- for (i=0; i < EI_NIDENT; i++) {
- printf("%d ", ehdr->e_ident[i]);
- }
- fprintf(stderr, "\n");
- fprintf(stderr, "Type:\t\t%u\n", ehdr->e_type);
- fprintf(stderr, "Machine:\t%u\n", ehdr->e_machine);
- fprintf(stderr, "Version:\t%u\n", ehdr->e_version);
- fprintf(stderr, "Entry:\t\t0x%08x\n", ehdr->e_entry);
- fprintf(stderr, "PHT Offset:\t0x%08x\n", ehdr->e_phoff);
- fprintf(stderr, "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(Elf32_Ehdr));
- fprintf(stderr, "phnum: %d shnum: %d\n", ehdr->e_phnum,
- ehdr->e_shnum);
-}
-
-void print_elf_symbols(struct elf_module *module) {
- unsigned int i;
- Elf32_Sym *crt_sym;
-
- for (i = 1; i < module->symtable_size; i++)
- {
- crt_sym = (Elf32_Sym*)(module->sym_table + i*module->syment_size);
-
- fprintf(stderr,"%s %d\n", module->str_table + crt_sym->st_name, crt_sym->st_value);
-
- }
-}
-#endif //ELF_DEBUG
-
-static FILE *findpath(char *name)
-{
- char path[FILENAME_MAX];
- FILE *f;
- char *p, *n;
- int i;
-
- p = PATH;
-again:
- memset(path, '\0', sizeof(path));
- i = 0;
- while (*p && *p != ':' && i < FILENAME_MAX) {
- path[i++] = *p++;
- }
- //path[i] = '\0'; // without null the strcmp will fail
-
- if (*p == ':')
- p++;
-
- if (!strcmp(path, ".")) {
- if (!core_getcwd(path, sizeof(path))) {
- DBG_PRINT("Could not get cwd\n");
- return NULL;
- }
- i = strlen(path);
- }
-
- n = name;
- while (*n && i < FILENAME_MAX)
- path[i++] = *n++;
- path[i] = '\0';
-
- f = fopen(path, "rb");
- if (f)
- return f;
-
- if (p >= PATH && p < PATH + strlen(PATH))
- goto again;
-
- return NULL;
-}
-
-/*
- * Image files manipulation routines
- */
-
-int image_load(struct elf_module *module)
-{
- module->u.l._file = findpath(module->name);
-
- if (module->u.l._file == NULL) {
- DBG_PRINT("Could not open object file '%s'\n", module->name);
- goto error;
- }
-
- module->u.l._cr_offset = 0;
-
- return 0;
-
-error:
- if (module->u.l._file != NULL) {
- fclose(module->u.l._file);
- module->u.l._file = NULL;
- }
-
- return -1;
-}
-
-
-int image_unload(struct elf_module *module) {
- if (module->u.l._file != NULL) {
- fclose(module->u.l._file);
- module->u.l._file = NULL;
-
- }
- module->u.l._cr_offset = 0;
-
- return 0;
-}
-
-int image_read(void *buff, size_t size, struct elf_module *module) {
- size_t result = fread(buff, size, 1, module->u.l._file);
-
- if (result < 1)
- return -1;
-
- module->u.l._cr_offset += size;
- return 0;
-}
-
-int image_skip(size_t size, struct elf_module *module) {
- void *skip_buff = NULL;
- size_t result;
-
- if (size == 0)
- return 0;
-
- skip_buff = malloc(size);
- result = fread(skip_buff, size, 1, module->u.l._file);
- free(skip_buff);
-
- if (result < 1)
- return -1;
-
- module->u.l._cr_offset += size;
- return 0;
-}
-
-int image_seek(Elf32_Off offset, struct elf_module *module) {
- if (offset < module->u.l._cr_offset) // Cannot seek backwards
- return -1;
-
- return image_skip(offset - module->u.l._cr_offset, module);
-}
-
-
-// Initialization of the module subsystem
-int modules_init(void) {
- return 0;
-}
-
-// Termination of the module subsystem
-void modules_term(void) {
-
-}
-
-// Allocates the structure for a new module
-struct elf_module *module_alloc(const char *name) {
- struct elf_module *result = malloc(sizeof(struct elf_module));
-
- memset(result, 0, sizeof(struct elf_module));
-
- INIT_LIST_HEAD(&result->list);
- INIT_LIST_HEAD(&result->required);
- INIT_LIST_HEAD(&result->dependants);
-
- strncpy(result->name, name, MODULE_NAME_SIZE);
-
- return result;
-}
-
-struct module_dep *module_dep_alloc(struct elf_module *module) {
- struct module_dep *result = malloc(sizeof(struct module_dep));
-
- INIT_LIST_HEAD (&result->list);
-
- result->module = module;
-
- return result;
-}
-
-struct elf_module *module_find(const char *name) {
- struct elf_module *cr_module;
-
- for_each_module(cr_module) {
- if (strcmp(cr_module->name, name) == 0)
- return cr_module;
- }
-
- return NULL;
-}
-
-
-// Performs verifications on ELF header to assure that the open file is a
-// valid SYSLINUX ELF module.
-int check_header_common(Elf32_Ehdr *elf_hdr) {
- // Check the header magic
- if (elf_hdr->e_ident[EI_MAG0] != ELFMAG0 ||
- elf_hdr->e_ident[EI_MAG1] != ELFMAG1 ||
- elf_hdr->e_ident[EI_MAG2] != ELFMAG2 ||
- elf_hdr->e_ident[EI_MAG3] != ELFMAG3) {
-
- DBG_PRINT("The file is not an ELF object\n");
- return -1;
- }
-
- if (elf_hdr->e_ident[EI_CLASS] != MODULE_ELF_CLASS) {
- DBG_PRINT("Invalid ELF class code\n");
- return -1;
- }
-
- if (elf_hdr->e_ident[EI_DATA] != MODULE_ELF_DATA) {
- DBG_PRINT("Invalid ELF data encoding\n");
- return -1;
- }
-
- if (elf_hdr->e_ident[EI_VERSION] != MODULE_ELF_VERSION ||
- elf_hdr->e_version != MODULE_ELF_VERSION) {
- DBG_PRINT("Invalid ELF file version\n");
- return -1;
- }
-
- if (elf_hdr->e_machine != MODULE_ELF_MACHINE) {
- DBG_PRINT("Invalid ELF architecture\n");
- return -1;
- }
-
- return 0;
-}
-
-
-int enforce_dependency(struct elf_module *req, struct elf_module *dep) {
- struct module_dep *crt_dep;
- struct module_dep *new_dep;
-
- list_for_each_entry(crt_dep, &req->dependants, list) {
- if (crt_dep->module == dep) {
- // The dependency is already enforced
- return 0;
- }
- }
-
- new_dep = module_dep_alloc(req);
- list_add(&new_dep->list, &dep->required);
-
- new_dep = module_dep_alloc(dep);
- list_add(&new_dep->list, &req->dependants);
-
- return 0;
-}
-
-int clear_dependency(struct elf_module *req, struct elf_module *dep) {
- struct module_dep *crt_dep = NULL;
- int found = 0;
-
- list_for_each_entry(crt_dep, &req->dependants, list) {
- if (crt_dep->module == dep) {
- found = 1;
- break;
- }
- }
-
- if (found) {
- list_del(&crt_dep->list);
- free(crt_dep);
- }
-
- found = 0;
-
- list_for_each_entry(crt_dep, &dep->required, list) {
- if (crt_dep->module == req) {
- found = 1;
- break;
- }
- }
-
- if (found) {
- list_del(&crt_dep->list);
- free(crt_dep);
- }
-
- return 0;
-}
-
-int check_symbols(struct elf_module *module)
-{
- unsigned int i;
- Elf32_Sym *crt_sym = NULL, *ref_sym = NULL;
- char *crt_name;
- struct elf_module *crt_module;
-
- int strong_count;
- int weak_count;
-
- for(i = 1; i < module->symtable_size; i++)
- {
- crt_sym = (Elf32_Sym*)(module->sym_table + i * module->syment_size);
- crt_name = module->str_table + crt_sym->st_name;
-
- strong_count = 0;
- weak_count = 0;
-
- for_each_module(crt_module)
- {
- ref_sym = module_find_symbol(crt_name, crt_module);
-
- // If we found a definition for our symbol...
- if (ref_sym != NULL && ref_sym->st_shndx != SHN_UNDEF)
- {
- switch (ELF32_ST_BIND(ref_sym->st_info))
- {
- case STB_GLOBAL:
- strong_count++;
- break;
- case STB_WEAK:
- weak_count++;
- break;
- }
- }
- }
-
- if (crt_sym->st_shndx == SHN_UNDEF)
- {
- // We have an undefined symbol
- if (strong_count == 0 && weak_count == 0)
- {
- DBG_PRINT("Symbol %s is undefined\n", crt_name);
- //printf("Undef symbol FAIL: %s\n",crt_name);
- return -1;
- }
- }
- else
- {
- if (strong_count > 0 && ELF32_ST_BIND(ref_sym->st_info) == STB_GLOBAL)
- {
- // It's not an error - at relocation, the most recent symbol
- // will be considered
- DBG_PRINT("Info: Symbol %s is defined more than once\n", crt_name);
- }
- }
- //printf("symbol %s laoded from %d\n",crt_name,crt_sym->st_value);
- }
-
- return 0;
-}
-
-int module_unloadable(struct elf_module *module) {
- if (!list_empty(&module->dependants))
- return 0;
-
- return 1;
-}
-
-
-// Unloads the module from the system and releases all the associated memory
-int module_unload(struct elf_module *module) {
- struct module_dep *crt_dep, *tmp;
- // Make sure nobody needs us
- if (!module_unloadable(module)) {
- DBG_PRINT("Module is required by other modules.\n");
- return -1;
- }
-
- // Remove any dependency information
- list_for_each_entry_safe(crt_dep, tmp, &module->required, list) {
- clear_dependency(crt_dep->module, module);
- }
-
- // Remove the module from the module list
- list_del_init(&module->list);
-
- // Release the loaded segments or sections
- if (module->module_addr != NULL) {
- elf_free(module->module_addr);
-
- DBG_PRINT("%s MODULE %s UNLOADED\n", module->shallow ? "SHALLOW" : "",
- module->name);
- }
- // Release the module structure
- free(module);
-
- return 0;
-}
-
-
-static Elf32_Sym *module_find_symbol_sysv(const char *name, struct elf_module *module) {
- unsigned long h = elf_hash((const unsigned char*)name);
- Elf32_Word *cr_word = module->hash_table;
-
- Elf32_Word nbucket = *cr_word++;
- cr_word++; // Skip nchain
-
- Elf32_Word *bkt = cr_word;
- Elf32_Word *chn = cr_word + nbucket;
-
- Elf32_Word crt_index = bkt[h % module->hash_table[0]];
- Elf32_Sym *crt_sym;
-
-
- while (crt_index != STN_UNDEF) {
- crt_sym = (Elf32_Sym*)(module->sym_table + crt_index*module->syment_size);
-
- if (strcmp(name, module->str_table + crt_sym->st_name) == 0)
- return crt_sym;
-
- crt_index = chn[crt_index];
- }
-
- return NULL;
-}
-
-static Elf32_Sym *module_find_symbol_gnu(const char *name, struct elf_module *module) {
- unsigned long h = elf_gnu_hash((const unsigned char*)name);
-
- // Setup code (TODO: Optimize this by computing only once)
- Elf32_Word *cr_word = module->ghash_table;
- Elf32_Word nbucket = *cr_word++;
- Elf32_Word symbias = *cr_word++;
- Elf32_Word bitmask_nwords = *cr_word++;
-
-
- if ((bitmask_nwords & (bitmask_nwords - 1)) != 0) {
- DBG_PRINT("Invalid GNU Hash structure\n");
- return NULL;
- }
-
- Elf32_Word gnu_shift = *cr_word++;
-
- Elf32_Addr *gnu_bitmask = (Elf32_Addr*)cr_word;
- cr_word += MODULE_ELF_CLASS_SIZE / 32 * bitmask_nwords;
-
- Elf32_Word *gnu_buckets = cr_word;
- cr_word += nbucket;
-
- Elf32_Word *gnu_chain_zero = cr_word - symbias;
-
- // Computations
- Elf32_Word bitmask_word = gnu_bitmask[(h / MODULE_ELF_CLASS_SIZE) &
- (bitmask_nwords - 1)];
-
- unsigned int hashbit1 = h & (MODULE_ELF_CLASS_SIZE - 1);
- unsigned int hashbit2 = (h >> gnu_shift) & (MODULE_ELF_CLASS_SIZE - 1);
-
- if ((bitmask_word >> hashbit1) & (bitmask_word >> hashbit2) & 1) {
- unsigned long rem;
- Elf32_Word bucket;
-
- rem = h % nbucket;
-
- bucket = gnu_buckets[rem];
-
- if (bucket != 0) {
- const Elf32_Word* hasharr = &gnu_chain_zero[bucket];
-
- do {
- if (((*hasharr ^ h ) >> 1) == 0) {
- Elf32_Sym *crt_sym = (Elf32_Sym*)(module->sym_table +
- (hasharr - gnu_chain_zero) * module->syment_size);
-
- if (strcmp(name, module->str_table + crt_sym->st_name) == 0) {
- return crt_sym;
- }
- }
- } while ((*hasharr++ & 1u) == 0);
- }
- }
-
- return NULL;
-}
-
-static Elf32_Sym *module_find_symbol_iterate(const char *name,struct elf_module *module)
-{
-
- unsigned int i;
- Elf32_Sym *crt_sym;
-
- for (i=1; i < module->symtable_size; i++)
- {
- crt_sym = (Elf32_Sym*)(module->sym_table + i*module->syment_size);
- if (strcmp(name, module->str_table + crt_sym->st_name) == 0)
- {
- return crt_sym;
- }
- }
-
- return NULL;
-}
-
-Elf32_Sym *module_find_symbol(const char *name, struct elf_module *module) {
- Elf32_Sym *result = NULL;
-
-
- if (module->ghash_table != NULL)
- result = module_find_symbol_gnu(name, module);
-
- if (result == NULL)
- {
- if (module->hash_table != NULL)
- {
- //printf("Attempting SYSV Symbol search\n");
- result = module_find_symbol_sysv(name, module);
- }
- else
- {
- //printf("Attempting Iterative Symbol search\n");
- result = module_find_symbol_iterate(name, module);
- }
- }
-
- return result;
-}
-
-Elf32_Sym *global_find_symbol(const char *name, struct elf_module **module) {
- struct elf_module *crt_module;
- Elf32_Sym *crt_sym = NULL;
- Elf32_Sym *result = NULL;
-
- for_each_module(crt_module) {
- crt_sym = module_find_symbol(name, crt_module);
-
- if (crt_sym != NULL && crt_sym->st_shndx != SHN_UNDEF) {
- switch (ELF32_ST_BIND(crt_sym->st_info)) {
- case STB_GLOBAL:
- if (module != NULL) {
- *module = crt_module;
- }
- return crt_sym;
- case STB_WEAK:
- // Consider only the first weak symbol
- if (result == NULL) {
- if (module != NULL) {
- *module = crt_module;
- }
- result = crt_sym;
- }
- break;
- }
- }
- }
-
- return result;
-}
diff --git a/com32/lib/sys/module/i386/elf_module.c b/com32/lib/sys/module/i386/elf_module.c
index 864344a7..f4a8618a 100644
--- a/com32/lib/sys/module/i386/elf_module.c
+++ b/com32/lib/sys/module/i386/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(Elf32_Ehdr *elf_hdr) {
int res;
@@ -50,7 +50,7 @@ static int check_header(Elf32_Ehdr *elf_hdr) {
static int load_segments(struct elf_module *module, Elf32_Ehdr *elf_hdr) {
int i;
int res = 0;
- void *pht = NULL;
+ char *pht = NULL;
Elf32_Phdr *cr_pht;
Elf32_Addr min_addr = 0x00000000; // Min. ELF vaddr
@@ -136,8 +136,8 @@ static int load_segments(struct elf_module *module, Elf32_Ehdr *elf_hdr) {
// headers
Elf32_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 Elf32_Word needed[MAX_NR_DEPS];;
-
static int prepare_dynlinking(struct elf_module *module) {
Elf32_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, Elf32_Rel *rel) {
Elf32_Word *dest = module_get_absolute(rel->r_offset, module);
@@ -259,8 +261,7 @@ static int perform_relocation(struct elf_module *module, Elf32_Rel *rel) {
// Find out details about the symbol
// The symbol reference
- Elf32_Sym *sym_ref =
- (Elf32_Sym*)(module->sym_table + sym * module->syment_size);
+ Elf32_Sym *sym_ref = symbol_get_entry(module, sym);
// The symbol definition
sym_def =
@@ -268,15 +269,16 @@ static int perform_relocation(struct elf_module *module, Elf32_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);
- /*
- printf("Cannot perform relocation for symbol %s\n",
- module->str_table + sym_ref->st_name);
- */
- return -1;
+ 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
@@ -325,9 +327,9 @@ static int resolve_symbols(struct elf_module *module) {
int res;
Elf32_Word plt_rel_size = 0;
- void *plt_rel = NULL;
+ char *plt_rel = NULL;
- void *rel = NULL;
+ char *rel = NULL;
Elf32_Word rel_size = 0;
Elf32_Word rel_entry = 0;
@@ -346,7 +348,6 @@ static int resolve_symbols(struct elf_module *module) {
DBG_PRINT("Unsupported PLT relocation\n");
return -1;
}
- //break; // mouli: wasn't there before
case DT_JMPREL:
plt_rel = module_get_absolute(dyn_entry->d_un.d_ptr, module);
break;
@@ -403,32 +404,70 @@ 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);
-static int extract_operations(struct elf_module *module) {
- Elf32_Sym *init_sym = module_find_symbol(MODULE_ELF_INIT_PTR, module);
- Elf32_Sym *exit_sym = module_find_symbol(MODULE_ELF_EXIT_PTR, module);
- Elf32_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;
+
+ 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 (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;
+ 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;
}
- }
- if (main_sym)
- module->main_func =
- module_get_absolute(main_sym->st_value, module);
+ memset(dtors, 0, size);
+ for (i = 0; i < nr_dtors; i++)
+ dtors[i] = start[i];
+
+ module->dtors = dtors;
+ }
return 0;
}
@@ -436,12 +475,14 @@ 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;
+ 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
@@ -467,42 +508,35 @@ int module_load(struct elf_module *module) {
CHECKED(res, load_segments(module, &elf_hdr), error);
//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);
}
}
@@ -510,8 +544,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
@@ -520,6 +557,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);
@@ -534,6 +574,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:
diff --git a/com32/lib/sys/module/i386/elfutils.h b/com32/lib/sys/module/i386/elfutils.h
deleted file mode 100644
index b18968f3..00000000
--- a/com32/lib/sys/module/i386/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 Elf32_Ehdr *elf_get_header(void *elf_image) {
- return (Elf32_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 Elf32_Phdr *elf_get_pht(void *elf_image) {
- Elf32_Ehdr *elf_hdr = elf_get_header(elf_image);
-
- return (Elf32_Phdr*)((Elf32_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 Elf32_Phdr *elf_get_ph(void *elf_image, int index) {
- Elf32_Phdr *elf_pht = elf_get_pht(elf_image);
- Elf32_Ehdr *elf_hdr = elf_get_header(elf_image);
-
- return (Elf32_Phdr*)((Elf32_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/com32/lib/sys/module/shallow_module.c b/com32/lib/sys/module/shallow_module.c
index fbcf781b..8a88e403 100644
--- a/com32/lib/sys/module/shallow_module.c
+++ b/com32/lib/sys/module/shallow_module.c
@@ -32,8 +32,8 @@ static int check_header_shallow(Elf32_Ehdr *elf_hdr) {
static int load_shallow_sections(struct elf_module *module, Elf32_Ehdr *elf_hdr) {
int i;
int res = 0;
- void *sht = NULL;
- void *buffer = NULL;
+ char *sht = NULL;
+ char *buffer = NULL;
Elf32_Shdr *crt_sht;
Elf32_Off buff_offset;
@@ -100,8 +100,8 @@ static int load_shallow_sections(struct elf_module *module, Elf32_Ehdr *elf_hdr)
// Setup module information
module->module_size = max_offset - min_offset;
- module->str_table = (char*)(module->module_addr + (str_offset - min_offset));
- module->sym_table = module->module_addr + (sym_offset - min_offset);
+ module->str_table = (char *)module->module_addr + (str_offset - min_offset);
+ module->sym_table = (char *)module->module_addr + (sym_offset - min_offset);
out:
// Release the SHT
diff --git a/com32/lib/sys/module/x86_64/common.c b/com32/lib/sys/module/x86_64/common.c
deleted file mode 100644
index ba4dbedc..00000000
--- a/com32/lib/sys/module/x86_64/common.c
+++ /dev/null
@@ -1,567 +0,0 @@
-/*
- * common.c
- *
- * Created on: Aug 11, 2008
- * Author: Stefan Bucur <stefanb@zytor.com>
- */
-
-#include <stdio.h>
-#include <elf.h>
-#include <string.h>
-#include <fs.h>
-
-#include <linux/list.h>
-#include <sys/module.h>
-
-#include "elfutils.h"
-#include "common.h"
-
-/**
- * The one and only list of loaded modules
- */
-LIST_HEAD(modules_head);
-
-// User-space debugging routines
-#ifdef ELF_DEBUG
-void print_elf_ehdr(Elf64_Ehdr *ehdr) {
- int i;
-
- fprintf(stderr, "Identification:\t");
- for (i=0; i < EI_NIDENT; i++) {
- printf("%d ", ehdr->e_ident[i]);
- }
- fprintf(stderr, "\n");
- fprintf(stderr, "Type:\t\t%u\n", ehdr->e_type);
- fprintf(stderr, "Machine:\t%u\n", ehdr->e_machine);
- fprintf(stderr, "Version:\t%u\n", ehdr->e_version);
- fprintf(stderr, "Entry:\t\t0x%08x\n", ehdr->e_entry);
- fprintf(stderr, "PHT Offset:\t0x%08x\n", ehdr->e_phoff);
- fprintf(stderr, "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));
- fprintf(stderr, "phnum: %d shnum: %d\n", ehdr->e_phnum,
- ehdr->e_shnum);
-}
-
-void print_elf_symbols(struct elf_module *module) {
- unsigned int i;
- Elf64_Sym *crt_sym;
-
- for (i = 1; i < module->symtable_size; i++)
- {
- crt_sym = (Elf64_Sym*)(module->sym_table + i*module->syment_size);
-
- fprintf(stderr,"%s %d\n", module->str_table + crt_sym->st_name, crt_sym->st_value);
-
- }
-}
-#endif //ELF_DEBUG
-
-static FILE *findpath(char *name)
-{
- char path[FILENAME_MAX];
- FILE *f;
- char *p, *n;
- int i;
-
- p = PATH;
-again:
- memset(path, '\0', sizeof(path));
- i = 0;
- while (*p && *p != ':' && i < FILENAME_MAX) {
- path[i++] = *p++;
- }
-
- if (*p == ':')
- p++;
-
- if (!strcmp(path, ".")) {
- if (!core_getcwd(path, sizeof(path))) {
- DBG_PRINT("Could not get cwd\n");
- return NULL;
- }
- i = strlen(path);
- }
-
- n = name;
- while (*n && i < FILENAME_MAX)
- path[i++] = *n++;
- path[i] = '\0';
-
- f = fopen(path, "rb");
- if (f)
- return f;
-
- if (p >= PATH && p < PATH + strlen(PATH))
- goto again;
-
- return NULL;
-}
-
-/*
- * Image files manipulation routines
- */
-
-int image_load(struct elf_module *module)
-{
- module->u.l._file = findpath(module->name);
-
- if (module->u.l._file == NULL) {
- DBG_PRINT("Could not open object file '%s'\n", module->name);
- goto error;
- }
-
- module->u.l._cr_offset = 0;
-
- return 0;
-
-error:
- if (module->u.l._file != NULL) {
- fclose(module->u.l._file);
- module->u.l._file = NULL;
- }
-
- return -1;
-}
-
-
-int image_unload(struct elf_module *module) {
- if (module->u.l._file != NULL) {
- fclose(module->u.l._file);
- module->u.l._file = NULL;
-
- }
- module->u.l._cr_offset = 0;
-
- return 0;
-}
-
-int image_read(void *buff, size_t size, struct elf_module *module) {
- size_t result = fread(buff, size, 1, module->u.l._file);
-
- if (result < 1)
- return -1;
-
- module->u.l._cr_offset += size;
- return 0;
-}
-
-int image_skip(size_t size, struct elf_module *module) {
- void *skip_buff = NULL;
- size_t result;
-
- if (size == 0)
- return 0;
-
- skip_buff = malloc(size);
- result = fread(skip_buff, size, 1, module->u.l._file);
- free(skip_buff);
-
- if (result < 1)
- return -1;
-
- module->u.l._cr_offset += size;
- return 0;
-}
-
-int image_seek(Elf64_Off offset, struct elf_module *module) {
- if (offset < module->u.l._cr_offset) // Cannot seek backwards
- return -1;
-
- return image_skip(offset - module->u.l._cr_offset, module);
-}
-
-
-// Initialization of the module subsystem
-int modules_init(void) {
- return 0;
-}
-
-// Termination of the module subsystem
-void modules_term(void) {
-
-}
-
-// Allocates the structure for a new module
-struct elf_module *module_alloc(const char *name) {
- struct elf_module *result = malloc(sizeof(struct elf_module));
-
- memset(result, 0, sizeof(struct elf_module));
-
- INIT_LIST_HEAD(&result->list);
- INIT_LIST_HEAD(&result->required);
- INIT_LIST_HEAD(&result->dependants);
-
- strncpy(result->name, name, MODULE_NAME_SIZE);
-
- return result;
-}
-
-struct module_dep *module_dep_alloc(struct elf_module *module) {
- struct module_dep *result = malloc(sizeof(struct module_dep));
-
- INIT_LIST_HEAD (&result->list);
-
- result->module = module;
-
- return result;
-}
-
-struct elf_module *module_find(const char *name) {
- struct elf_module *cr_module;
-
- for_each_module(cr_module) {
- if (strcmp(cr_module->name, name) == 0)
- return cr_module;
- }
-
- return NULL;
-}
-
-
-// Performs verifications on ELF header to assure that the open file is a
-// valid SYSLINUX ELF module.
-int check_header_common(Elf64_Ehdr *elf_hdr) {
- // Check the header magic
- if (elf_hdr->e_ident[EI_MAG0] != ELFMAG0 ||
- elf_hdr->e_ident[EI_MAG1] != ELFMAG1 ||
- elf_hdr->e_ident[EI_MAG2] != ELFMAG2 ||
- elf_hdr->e_ident[EI_MAG3] != ELFMAG3) {
-
- DBG_PRINT("The file is not an ELF object\n");
- return -1;
- }
-
- if (elf_hdr->e_ident[EI_CLASS] != MODULE_ELF_CLASS) {
- DBG_PRINT("Invalid ELF class code\n");
- return -1;
- }
-
- if (elf_hdr->e_ident[EI_DATA] != MODULE_ELF_DATA) {
- DBG_PRINT("Invalid ELF data encoding\n");
- return -1;
- }
-
- if (elf_hdr->e_ident[EI_VERSION] != MODULE_ELF_VERSION ||
- elf_hdr->e_version != MODULE_ELF_VERSION) {
- DBG_PRINT("Invalid ELF file version\n");
- return -1;
- }
-
- if (elf_hdr->e_machine != MODULE_ELF_MACHINE) {
- DBG_PRINT("Invalid ELF architecture\n");
- return -1;
- }
-
- return 0;
-}
-
-
-int enforce_dependency(struct elf_module *req, struct elf_module *dep) {
- struct module_dep *crt_dep;
- struct module_dep *new_dep;
-
- list_for_each_entry(crt_dep, &req->dependants, list) {
- if (crt_dep->module == dep) {
- // The dependency is already enforced
- return 0;
- }
- }
-
- new_dep = module_dep_alloc(req);
- list_add(&new_dep->list, &dep->required);
-
- new_dep = module_dep_alloc(dep);
- list_add(&new_dep->list, &req->dependants);
-
- return 0;
-}
-
-int clear_dependency(struct elf_module *req, struct elf_module *dep) {
- struct module_dep *crt_dep = NULL;
- int found = 0;
-
- list_for_each_entry(crt_dep, &req->dependants, list) {
- if (crt_dep->module == dep) {
- found = 1;
- break;
- }
- }
-
- if (found) {
- list_del(&crt_dep->list);
- free(crt_dep);
- }
-
- found = 0;
-
- list_for_each_entry(crt_dep, &dep->required, list) {
- if (crt_dep->module == req) {
- found = 1;
- break;
- }
- }
-
- if (found) {
- list_del(&crt_dep->list);
- free(crt_dep);
- }
-
- return 0;
-}
-
-int check_symbols(struct elf_module *module)
-{
- unsigned int i;
- Elf64_Sym *crt_sym = NULL, *ref_sym = NULL;
- char *crt_name;
- struct elf_module *crt_module;
-
- int strong_count;
- int weak_count;
-
- for(i = 1; i < module->symtable_size; i++)
- {
- crt_sym = (Elf64_Sym*)(module->sym_table + i * module->syment_size);
- crt_name = module->str_table + crt_sym->st_name;
-
- strong_count = 0;
- weak_count = 0;
-
- for_each_module(crt_module)
- {
- ref_sym = module_find_symbol(crt_name, crt_module);
-
- // If we found a definition for our symbol...
- if (ref_sym != NULL && ref_sym->st_shndx != SHN_UNDEF)
- {
- switch (ELF64_ST_BIND(ref_sym->st_info))
- {
- case STB_GLOBAL:
- strong_count++;
- break;
- case STB_WEAK:
- weak_count++;
- break;
- }
- }
- }
-
- if (crt_sym->st_shndx == SHN_UNDEF)
- {
- // We have an undefined symbol
- if (strong_count == 0 && weak_count == 0)
- {
- DBG_PRINT("Symbol %s is undefined\n", crt_name);
- //printf("Undef symbol FAIL: %s\n",crt_name);
- return -1;
- }
- }
- else
- {
- if (strong_count > 0 && ELF64_ST_BIND(ref_sym->st_info) == STB_GLOBAL)
- {
- // It's not an error - at relocation, the most recent symbol
- // will be considered
- DBG_PRINT("Info: Symbol %s is defined more than once\n", crt_name);
- }
- }
- //printf("symbol %s laoded from %d\n",crt_name,crt_sym->st_value);
- }
-
- return 0;
-}
-
-int module_unloadable(struct elf_module *module) {
- if (!list_empty(&module->dependants))
- return 0;
-
- return 1;
-}
-
-
-// Unloads the module from the system and releases all the associated memory
-int module_unload(struct elf_module *module) {
- struct module_dep *crt_dep, *tmp;
- // Make sure nobody needs us
- if (!module_unloadable(module)) {
- DBG_PRINT("Module is required by other modules.\n");
- return -1;
- }
-
- // Remove any dependency information
- list_for_each_entry_safe(crt_dep, tmp, &module->required, list) {
- clear_dependency(crt_dep->module, module);
- }
-
- // Remove the module from the module list
- list_del_init(&module->list);
-
- // Release the loaded segments or sections
- if (module->module_addr != NULL) {
- elf_free(module->module_addr);
-
- DBG_PRINT("%s MODULE %s UNLOADED\n", module->shallow ? "SHALLOW" : "",
- module->name);
- }
- // Release the module structure
- free(module);
-
- return 0;
-}
-
-
-static Elf64_Sym *module_find_symbol_sysv(const char *name, struct elf_module *module) {
- unsigned long h = elf_hash((const unsigned char*)name);
- Elf64_Word *cr_word = module->hash_table;
-
- Elf64_Word nbucket = *cr_word++;
- cr_word++; // Skip nchain
-
- Elf64_Word *bkt = cr_word;
- Elf64_Word *chn = cr_word + nbucket;
-
- Elf64_Word crt_index = bkt[h % module->hash_table[0]];
- Elf64_Sym *crt_sym;
-
-
- while (crt_index != STN_UNDEF) {
- crt_sym = (Elf64_Sym*)(module->sym_table + crt_index*module->syment_size);
-
- if (strcmp(name, module->str_table + crt_sym->st_name) == 0)
- return crt_sym;
-
- crt_index = chn[crt_index];
- }
-
- return NULL;
-}
-
-static Elf64_Sym *module_find_symbol_gnu(const char *name, struct elf_module *module) {
- unsigned long h = elf_gnu_hash((const unsigned char*)name);
-
- // Setup code (TODO: Optimize this by computing only once)
- Elf64_Word *cr_word = module->ghash_table;
- Elf64_Word nbucket = *cr_word++;
- Elf64_Word symbias = *cr_word++;
- Elf64_Word bitmask_nwords = *cr_word++;
-
- if ((bitmask_nwords & (bitmask_nwords - 1)) != 0) {
- DBG_PRINT("Invalid GNU Hash structure\n");
- return NULL;
- }
-
- Elf64_Word gnu_shift = *cr_word++;
-
- Elf64_Addr *gnu_bitmask = cr_word;
- cr_word += MODULE_ELF_CLASS_SIZE / 32 * bitmask_nwords;
-
- Elf64_Word *gnu_buckets = cr_word;
- cr_word += nbucket;
-
- Elf64_Word *gnu_chain_zero = cr_word - symbias;
-
- // Computations
- /* bitask words are 64bit for ELFCLASS64 modules */
- Elf64_Xword bitmask_word = gnu_bitmask[(h / MODULE_ELF_CLASS_SIZE) &
- (bitmask_nwords - 1)];
-
- unsigned int hashbit1 = h & (MODULE_ELF_CLASS_SIZE - 1);
- unsigned int hashbit2 = (h >> gnu_shift) & (MODULE_ELF_CLASS_SIZE - 1);
-
- if ((bitmask_word >> hashbit1) & (bitmask_word >> hashbit2) & 1) {
- unsigned long rem;
- Elf64_Word bucket;
-
- rem = h % nbucket;
-
- bucket = gnu_buckets[rem];
-
- if (bucket != 0) {
- const Elf64_Word* hasharr = &gnu_chain_zero[bucket];
-
- do {
- if (((*hasharr ^ h ) >> 1) == 0) {
- Elf64_Sym *crt_sym = (Elf64_Sym*)(module->sym_table +
- (hasharr - gnu_chain_zero) * module->syment_size);
-
- if (strcmp(name, module->str_table + crt_sym->st_name) == 0) {
- return crt_sym;
- }
- }
- } while ((*hasharr++ & 1u) == 0);
- }
- }
-
- return NULL;
-}
-
-static Elf64_Sym *module_find_symbol_iterate(const char *name,struct elf_module *module)
-{
-
- unsigned int i;
- Elf64_Sym *crt_sym;
-
- for (i=1; i < module->symtable_size; i++)
- {
- crt_sym = (Elf64_Sym*)(module->sym_table + i*module->syment_size);
- if (strcmp(name, module->str_table + crt_sym->st_name) == 0)
- {
- return crt_sym;
- }
- }
-
- return NULL;
-}
-
-Elf64_Sym *module_find_symbol(const char *name, struct elf_module *module) {
- Elf64_Sym *result = NULL;
-
- if (module->ghash_table != NULL)
- result = module_find_symbol_gnu(name, module);
-
- if (result == NULL)
- {
- if (module->hash_table != NULL)
- {
- result = module_find_symbol_sysv(name, module);
- }
- else
- {
- result = module_find_symbol_iterate(name, module);
- }
- }
-
- return result;
-}
-
-Elf64_Sym *global_find_symbol(const char *name, struct elf_module **module) {
- struct elf_module *crt_module;
- Elf64_Sym *crt_sym = NULL;
- Elf64_Sym *result = NULL;
-
- for_each_module(crt_module) {
- crt_sym = module_find_symbol(name, crt_module);
-
- if (crt_sym != NULL && crt_sym->st_shndx != SHN_UNDEF) {
- switch (ELF64_ST_BIND(crt_sym->st_info)) {
- case STB_GLOBAL:
- if (module != NULL) {
- *module = crt_module;
- }
- return crt_sym;
- case STB_WEAK:
- // Consider only the first weak symbol
- if (result == NULL) {
- if (module != NULL) {
- *module = crt_module;
- }
- result = crt_sym;
- }
- break;
- }
- }
- }
-
- return result;
-}
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:
diff --git a/com32/lib/sys/open.c b/com32/lib/sys/open.c
index a0ef1597..3221bb60 100644
--- a/com32/lib/sys/open.c
+++ b/com32/lib/sys/open.c
@@ -30,6 +30,7 @@
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
+#include <fs.h>
#include "file.h"
/*
diff --git a/com32/lib/sys/rawcon_read.c b/com32/lib/sys/rawcon_read.c
index e6635909..7eae95f1 100644
--- a/com32/lib/sys/rawcon_read.c
+++ b/com32/lib/sys/rawcon_read.c
@@ -35,51 +35,38 @@
#include <errno.h>
#include <string.h>
#include <com32.h>
+#include <core.h>
#include <minmax.h>
#include "file.h"
/* Global, since it's used by stdcon_read */
-#ifndef SYSLINUX_EFI
ssize_t __rawcon_read(struct file_info *fp, void *buf, size_t count)
{
- com32sys_t ireg, oreg;
char *bufp = buf;
size_t n = 0;
+ char hi = 0;
-printf("__rawcon_read... enter\n");
(void)fp;
- memset(&ireg, 0, sizeof ireg);
-
while (n < count) {
+ if (hi) {
+ *bufp++ = hi;
+ n++;
+ hi = 0;
+ continue;
+ }
+
/* Poll */
- ireg.eax.b[1] = 0x0B;
- __intcall(0x21, &ireg, &oreg);
- if (!oreg.eax.b[0])
+ if (!pollchar())
break;
/* We have data, go get it */
- ireg.eax.b[1] = 0x08;
- __intcall(0x21, &ireg, &oreg);
- *bufp++ = oreg.eax.b[0];
+ *bufp++ = getchar(&hi);
n++;
}
return n;
}
-#else
-ssize_t __rawcon_read(struct file_info *fp, void *buf, size_t count)
-{
- extern char getchar();
- char *bufp = buf;
- size_t n = 0;
- while (n < count) {
- *bufp++ = getchar();
- n++;
- }
- return n;
-}
-#endif
const struct input_dev dev_rawcon_r = {
.dev_magic = __DEV_MAGIC,
diff --git a/com32/lib/sys/rawcon_write.c b/com32/lib/sys/rawcon_write.c
index 2d45a7b2..1f7920b2 100644
--- a/com32/lib/sys/rawcon_write.c
+++ b/com32/lib/sys/rawcon_write.c
@@ -34,24 +34,20 @@
#include <errno.h>
#include <string.h>
#include <com32.h>
+#include <core.h>
#include <minmax.h>
#include "file.h"
static ssize_t __rawcon_write(struct file_info *fp, const void *buf,
size_t count)
{
- com32sys_t ireg;
const char *bufp = buf;
size_t n = 0;
(void)fp;
- memset(&ireg, 0, sizeof ireg);
- ireg.eax.b[1] = 0x02;
-
while (count--) {
- ireg.edx.b[0] = *bufp++;
- __intcall(0x21, &ireg, NULL);
+ writechr(*bufp++);
n++;
}
diff --git a/com32/lib/sys/serial_write.c b/com32/lib/sys/serial_write.c
index fa0f4f4d..3f949fb7 100644
--- a/com32/lib/sys/serial_write.c
+++ b/com32/lib/sys/serial_write.c
@@ -34,13 +34,13 @@
#include <errno.h>
#include <string.h>
#include <com32.h>
+#include <core.h>
#include <minmax.h>
#include <syslinux/config.h>
#include "file.h"
ssize_t __serial_write(struct file_info *fp, const void *buf, size_t count)
{
- com32sys_t ireg;
const char *bufp = buf;
size_t n = 0;
@@ -49,12 +49,8 @@ ssize_t __serial_write(struct file_info *fp, const void *buf, size_t count)
if (!syslinux_serial_console_info()->iobase)
return count; /* Nothing to do */
- memset(&ireg, 0, sizeof ireg);
- ireg.eax.b[1] = 0x04;
-
while (count--) {
- ireg.edx.b[0] = *bufp++;
- __intcall(0x21, &ireg, NULL);
+ write_serial(*bufp++);
n++;
}
diff --git a/com32/lib/sys/stdcon_write.c b/com32/lib/sys/stdcon_write.c
index 9cb2f7db..9bd225f9 100644
--- a/com32/lib/sys/stdcon_write.c
+++ b/com32/lib/sys/stdcon_write.c
@@ -34,6 +34,7 @@
#include <errno.h>
#include <string.h>
#include <com32.h>
+#include <core.h>
#include <minmax.h>
#include "file.h"
@@ -57,22 +58,16 @@ static int __stdcon_open(struct file_info *fp)
static ssize_t __stdcon_write(struct file_info *fp, const void *buf,
size_t count)
{
- com32sys_t ireg;
const char *bufp = buf;
size_t n = 0;
(void)fp;
- memset(&ireg, 0, sizeof ireg);
- ireg.eax.b[1] = 0x02;
-
while (count--) {
- if (*bufp == '\n') {
- ireg.edx.b[0] = '\r';
- __intcall(0x21, &ireg, NULL);
- }
- ireg.edx.b[0] = *bufp++;
- __intcall(0x21, &ireg, NULL);
+ if (*bufp == '\n')
+ writechr('\r');
+
+ writechr(*bufp++);
n++;
}
diff --git a/com32/lib/sys/xserial_write.c b/com32/lib/sys/xserial_write.c
index e399f5fc..8a4fb9e0 100644
--- a/com32/lib/sys/xserial_write.c
+++ b/com32/lib/sys/xserial_write.c
@@ -35,6 +35,7 @@
#include <errno.h>
#include <string.h>
#include <com32.h>
+#include <core.h>
#include <minmax.h>
#include <colortbl.h>
#include <syslinux/config.h>
@@ -42,12 +43,7 @@
static void emit(char ch)
{
- static com32sys_t ireg; /* Zeroed with the BSS */
-
- ireg.eax.b[1] = 0x04;
- ireg.edx.b[0] = ch;
-
- __intcall(0x21, &ireg, NULL);
+ write_serial(ch);
}
ssize_t __xserial_write(struct file_info *fp, const void *buf, size_t count)