aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Bucur <stefanb@zytor.com>2008-07-01 17:03:46 +0300
committerStefan Bucur <stefan@stefan-ubumac.(none)>2009-03-15 10:03:13 +0200
commit096c21fc8d76c3a9dc97f1ed5ba3abc8c51481cd (patch)
tree9aa0d46c1687856dd4c11170d45a220c5b0e2db0
parent7bb46a5400abb256e96ba3b637db8afe7bb321e9 (diff)
downloadsyslinux-elf-096c21fc8d76c3a9dc97f1ed5ba3abc8c51481cd.tar.gz
syslinux-elf-096c21fc8d76c3a9dc97f1ed5ba3abc8c51481cd.tar.xz
syslinux-elf-096c21fc8d76c3a9dc97f1ed5ba3abc8c51481cd.zip
Moved the module loading code onto SYSLINUX, as a COM32 module.
The code does nothing for now. It simply compiles the code and ensures all the dependencies are satisfied.
-rw-r--r--com32/Makefile3
-rw-r--r--com32/elflink/Makefile104
-rw-r--r--com32/elflink/Makefile.user (renamed from elf/Makefile)3
-rw-r--r--com32/elflink/README (renamed from elf/README)0
-rw-r--r--com32/elflink/TODO1
-rw-r--r--com32/elflink/elf_module.c (renamed from elf/elf_module.c)359
-rw-r--r--com32/elflink/elf_module.h (renamed from elf/elf_module.h)0
-rw-r--r--com32/elflink/elf_utils.c70
-rw-r--r--com32/elflink/elf_utils.h (renamed from elf/elf_utils.h)8
-rw-r--r--com32/elflink/elflink.c6
-rw-r--r--com32/elflink/elftest.c (renamed from elf/elftest.c)0
-rw-r--r--com32/elflink/hello_def.c (renamed from elf/hello_def.c)0
-rw-r--r--com32/elflink/hello_ref.c (renamed from elf/hello_ref.c)0
-rw-r--r--com32/elflink/linux_list.h (renamed from elf/linux_list.h)0
-rw-r--r--com32/include/sys/elfcommon.h229
-rw-r--r--elf/TODO3
-rw-r--r--elf/elf_utils.c27
17 files changed, 577 insertions, 236 deletions
diff --git a/com32/Makefile b/com32/Makefile
index 64049d07..22bbbc16 100644
--- a/com32/Makefile
+++ b/com32/Makefile
@@ -1,3 +1,4 @@
-SUBDIRS = lib gpllib libutil modules menu samples rosh cmenu hdt
+SUBDIRS = lib gpllib libutil modules menu samples elflink rosh cmenu hdt
+
all tidy dist clean spotless install:
set -e; for d in $(SUBDIRS); do $(MAKE) -C $$d $@; done
diff --git a/com32/elflink/Makefile b/com32/elflink/Makefile
new file mode 100644
index 00000000..1151c677
--- /dev/null
+++ b/com32/elflink/Makefile
@@ -0,0 +1,104 @@
+## -----------------------------------------------------------------------
+##
+## Copyright 2001-2008 H. Peter Anvin - All Rights Reserved
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+## Boston MA 02111-1307, USA; either version 2 of the License, or
+## (at your option) any later version; incorporated herein by reference.
+##
+## -----------------------------------------------------------------------
+
+##
+## COM32 standard modules
+##
+
+TMPFILE = $(shell mktemp /tmp/gcc_ok.XXXXXX)
+CC = gcc
+
+gcc_ok = $(shell tmpf=$(TMPFILE); if $(CC) $(1) -c -x c /dev/null -o $$tmpf 2>/dev/null; \
+ then echo $(1); else echo $(2); fi; rm -f $$tmpf)
+
+M32 := $(call gcc_ok,-m32,) $(call gcc_ok,-fno-stack-protector,)
+
+LD = ld -m elf_i386
+AR = ar
+NASM = nasm
+NASMOPT = -O9999
+RANLIB = ranlib
+CFLAGS = $(M32) -mregparm=3 -DREGPARM=3 -W -Wall -march=i386 -Os \
+ -fomit-frame-pointer -D__COM32__ \
+ -nostdinc -iwithprefix include \
+ -I../libutil/include -I../include \
+ -Wp,-MT,$@,-MD,$(dir $@).$(notdir $@).d
+LNXCFLAGS = -W -Wall -O -g -I../libutil/include
+LNXSFLAGS = -g
+LNXLDFLAGS = -g
+SFLAGS = -D__COM32__ -march=i386
+LDFLAGS = -T ../lib/com32.ld
+OBJCOPY = objcopy
+PPMTOLSS16 = ../ppmtolss16
+LIBGCC := $(shell $(CC) --print-libgcc)
+LIBS = ../libutil/libutil_com.a ../lib/libcom32.a $(LIBGCC)
+LNXLIBS = ../libutil/libutil_lnx.a
+
+.SUFFIXES: .lss .c .o .elf .c32 .lnx
+
+BINDIR = /usr/bin
+LIBDIR = /usr/lib
+DATADIR = /usr/share
+AUXDIR = $(DATADIR)/syslinux
+INCDIR = /usr/include
+COM32DIR = $(AUXDIR)/com32
+
+MODULES = elflink.c32
+
+TESTFILES =
+
+all: $(MODULES) $(TESTFILES)
+
+.PRECIOUS: %.o
+%.o: %.S
+ $(CC) $(SFLAGS) -c -o $@ $<
+
+.PRECIOUS: %.o
+%.o: %.c
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+.PRECIOUS: %.elf
+%.elf: %.o $(LIBS)
+ $(LD) $(LDFLAGS) -o $@ $^
+
+.PRECIOUS: %.lo
+%.lo: %.S
+ $(CC) $(LNXSFLAGS) -c -o $@ $<
+
+.PRECIOUS: %.lo
+%.lo: %.c
+ $(CC) $(LNXCFLAGS) -c -o $@ $<
+
+.PRECIOUS: %.lnx
+%.lnx: %.lo $(LNXLIBS)
+ $(CC) $(LNXLDFLAGS) -o $@ $^
+
+%.c32: %.elf
+ $(OBJCOPY) -O binary $< $@
+
+elflink.elf : elflink.o elf_module.o elf_utils.o $(LIBS)
+ $(LD) $(LDFLAGS) -o $@ $^
+
+tidy dist:
+ rm -f *.o *.lo *.a *.lst *.elf .*.d
+
+clean: tidy
+ rm -f *.lss *.c32 *.lnx *.com
+
+spotless: clean
+ rm -f *~ \#*
+
+install: all
+ mkdir -m 755 -p $(INSTALLROOT)$(AUXDIR)
+ install -m 644 $(MODULES) $(INSTALLROOT)$(AUXDIR)
+
+-include .*.d
diff --git a/elf/Makefile b/com32/elflink/Makefile.user
index e7d0ba64..e800d6c6 100644
--- a/elf/Makefile
+++ b/com32/elflink/Makefile.user
@@ -1,3 +1,6 @@
+## Builds a simple user-space application that tests the basic functionality
+## of the ELF linking routines.
+
## License would go here
########
diff --git a/elf/README b/com32/elflink/README
index 324a8c25..324a8c25 100644
--- a/elf/README
+++ b/com32/elflink/README
diff --git a/com32/elflink/TODO b/com32/elflink/TODO
new file mode 100644
index 00000000..19cc04ac
--- /dev/null
+++ b/com32/elflink/TODO
@@ -0,0 +1 @@
+* Create a macro for reporting debugging information.
diff --git a/elf/elf_module.c b/com32/elflink/elf_module.c
index 24137402..000ec0b1 100644
--- a/elf/elf_module.c
+++ b/com32/elflink/elf_module.c
@@ -19,14 +19,14 @@
#define MAX(x,y) (((x) > (y)) ? (x) : (y))
// The list of loaded modules
-static LIST_HEAD(modules);
+static LIST_HEAD(modules);
// User-space debugging routines
#ifdef ELF_USERSPACE_TEST
static void print_elf_ehdr(Elf32_Ehdr *ehdr) {
int i;
-
+
printf("Identification:\t");
for (i=0; i < EI_NIDENT; i++) {
printf("%d ", ehdr->e_ident[i]);
@@ -48,18 +48,18 @@ static void print_elf_symbols(struct elf_module *module) {
Elf32_Word *chn = module->hash_table + 2 + module->hash_table[0];
Elf32_Word i, crt_index;
Elf32_Sym *crt_sym;
-
+
printf("Bucket count: %d \n", module->hash_table[0]);
printf("Chain count: %d (Non GNU-Hash: %d)\n", module->hash_table[1],
module->ghash_table[1]);
-
+
for (i = 0; i < module->hash_table[0]; i++) {
printf("Bucket %d:\n", i);
crt_index = bkt[i];
-
+
while (crt_index != STN_UNDEF) {
crt_sym = (Elf32_Sym*)(module->sym_table + crt_index*module->syment_size);
-
+
printf("%s\n", module->str_table + crt_sym->st_name);
crt_index = chn[crt_index];
}
@@ -69,27 +69,27 @@ static void print_elf_symbols(struct elf_module *module) {
static int image_load(struct elf_module *module) {
char file_name[MODULE_NAME_SIZE+3]; // Include the extension
-
+
strcpy(file_name, module->name);
strcat(file_name, ".so");
-
+
module->_file = fopen(file_name, "rb");
-
+
if (module->_file == NULL) {
perror("Could not open object file");
goto error;
}
module->_cr_offset = 0;
-
+
return 0;
-
+
error:
if (module->_file != NULL) {
fclose(module->_file);
module->_file = NULL;
}
-
+
return -1;
}
@@ -100,16 +100,16 @@ static int image_unload(struct elf_module *module) {
module->_file = NULL;
}
module->_cr_offset = 0;
-
+
return 0;
}
static int image_read(void *buff, size_t size, struct elf_module *module) {
size_t result = fread(buff, size, 1, module->_file);
-
+
if (result < 1)
return -1;
-
+
printf("[DBG] Read %u\n", size);
module->_cr_offset += size;
return 0;
@@ -118,17 +118,17 @@ static int image_read(void *buff, size_t size, struct elf_module *module) {
static 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->_file);
free(skip_buff);
-
+
if (result < 1)
return -1;
-
+
printf("[DBG] Skipped %u\n", size);
module->_cr_offset += size;
return 0;
@@ -137,7 +137,7 @@ static int image_skip(size_t size, struct elf_module *module) {
static int image_seek(Elf32_Off offset, struct elf_module *module) {
if (offset < module->_cr_offset) // Cannot seek backwards
return -1;
-
+
return image_skip(offset - module->_cr_offset, module);
}
@@ -149,42 +149,42 @@ int modules_init() {
// Termination of the module subsystem
void modules_term() {
-
+
}
// 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;
}
static 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;
-
+
list_for_each_entry(cr_module, &modules, list) {
if (strcmp(cr_module->name, name) == 0)
return cr_module;
}
-
+
return NULL;
}
@@ -196,48 +196,48 @@ static int check_header(Elf32_Ehdr *elf_hdr) {
elf_hdr->e_ident[EI_MAG1] != ELFMAG1 ||
elf_hdr->e_ident[EI_MAG2] != ELFMAG2 ||
elf_hdr->e_ident[EI_MAG3] != ELFMAG3) {
-
+
fprintf(stderr, "The file is not an ELF object\n");
return -1;
}
-
+
if (elf_hdr->e_ident[EI_CLASS] != MODULE_ELF_CLASS) {
fprintf(stderr, "Invalid ELF class code\n");
return -1;
}
-
+
if (elf_hdr->e_ident[EI_DATA] != MODULE_ELF_DATA) {
fprintf(stderr, "Invalid ELF data encoding\n");
return -1;
}
-
+
if (elf_hdr->e_ident[EI_VERSION] != MODULE_ELF_VERSION ||
elf_hdr->e_version != MODULE_ELF_VERSION) {
fprintf(stderr, "Invalid ELF file version\n");
return -1;
}
-
+
if (elf_hdr->e_type != MODULE_ELF_TYPE) {
fprintf(stderr, "The ELF file must be a shared object\n");
return -1;
}
-
-
+
+
if (elf_hdr->e_machine != MODULE_ELF_MACHINE) {
fprintf(stderr, "Invalid ELF architecture\n");
return -1;
}
-
+
if (elf_hdr->e_phoff == 0x00000000) {
fprintf(stderr, "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.
@@ -247,33 +247,33 @@ static int load_segments(struct elf_module *module, Elf32_Ehdr *elf_hdr) {
int res = 0;
void *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:
+ 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;
@@ -285,44 +285,44 @@ static int load_segments(struct elf_module *module, Elf32_Ehdr *elf_hdr) {
break;
}
}
-
+
if (max_addr - min_addr == 0) {
// No loadable segments
fprintf(stderr, "No loadable segments found\n");
goto out;
}
-
+
if (dyn_addr == 0) {
fprintf(stderr, "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 (posix_memalign(&module->module_addr,
- max_align,
+
+
+ if (elf_malloc(&module->module_addr,
+ max_align,
max_alloc-min_alloc) != 0) {
-
+
fprintf(stderr, "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->_cr_offset) {
@@ -330,7 +330,7 @@ static int load_segments(struct elf_module *module, Elf32_Ehdr *elf_hdr) {
// It can be discarded without worry - it would contain only
// headers
Elf32_Off aux_off = module->_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) {
res = -1;
@@ -341,58 +341,58 @@ static int load_segments(struct elf_module *module, Elf32_Ehdr *elf_hdr) {
res = -1;
goto out;
}
-
- if (image_read(module_get_absolute(cr_pht->p_vaddr, module),
+
+ if (image_read(module_get_absolute(cr_pht->p_vaddr, module),
cr_pht->p_filesz, module) < 0) {
res = -1;
goto out;
}
}
-
+
printf("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);
-
+
printf("Base address: 0x%08x, aligned at 0x%08x\n", module->base_addr,
max_align);
printf("Module size: 0x%08x\n", module->module_size);
-
+
out:
// Free up allocated memory
if (pht != NULL)
free(pht);
-
+
return res;
}
-static int prepare_dynlinking(struct elf_module *module) {
+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:
// TODO: Manage dependencies here
break;
case DT_HASH:
- module->hash_table =
+ module->hash_table =
(Elf32_Word*)module_get_absolute(dyn_entry->d_un.d_ptr, module);
break;
case DT_GNU_HASH: // TODO: Add support for this one, too (50% faster)
- module->ghash_table =
+ module->ghash_table =
(Elf32_Word*)module_get_absolute(dyn_entry->d_un.d_ptr, module);
break;
case DT_STRTAB:
- module->str_table =
+ module->str_table =
(char*)module_get_absolute(dyn_entry->d_un.d_ptr, module);
break;
case DT_SYMTAB:
- module->sym_table =
+ module->sym_table =
module_get_absolute(dyn_entry->d_un.d_ptr, module);
break;
case DT_STRSZ:
@@ -405,91 +405,91 @@ static int prepare_dynlinking(struct elf_module *module) {
module->got = module_get_absolute(dyn_entry->d_un.d_ptr, module);
break;
}
-
+
dyn_entry++;
}
-
-
+
+
return 0;
}
static 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;
}
static 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;
}
static int perform_relocation(struct elf_module *module, Elf32_Rel *rel) {
Elf32_Word *dest = module_get_absolute(rel->r_offset, module);
-
+
// The symbol reference index
Elf32_Word sym = ELF32_R_SYM(rel->r_info);
unsigned char type = ELF32_R_TYPE(rel->r_info);
-
+
// The symbol definition (if applicable)
Elf32_Sym *sym_def = NULL;
struct elf_module *sym_module = NULL;
Elf32_Addr sym_addr = 0x0;
-
+
if (sym > 0) {
// Find out details about the symbol
-
+
// The symbol reference
- Elf32_Sym *sym_ref =
+ Elf32_Sym *sym_ref =
(Elf32_Sym*)(module->sym_table + sym * module->syment_size);
-
+
// The symbol definition
sym_def =
global_find_symbol(module->str_table + sym_ref->st_name,
&sym_module);
-
+
if (sym_def == NULL) {
// This should never happen
fprintf(stderr, "Warning: Cannot perform relocation for symbol %s\n",
@@ -497,16 +497,16 @@ static int perform_relocation(struct elf_module *module, Elf32_Rel *rel) {
// TODO: Return an error
return 0;
}
-
+
// 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
@@ -534,27 +534,28 @@ static int perform_relocation(struct elf_module *module, Elf32_Rel *rel) {
fprintf(stderr, "Warning: Relocation type %d not supported\n", type);
break;
}
-
+
return 0;
}
static int resolve_symbols(struct elf_module *module) {
Elf32_Dyn *dyn_entry = module->dyn_table;
- int i, res;
-
+ unsigned int i;
+ int res;
+
Elf32_Word plt_rel_size = 0;
void *plt_rel = NULL;
-
+
void *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;
@@ -567,7 +568,7 @@ static int resolve_symbols(struct elf_module *module) {
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);
@@ -578,7 +579,7 @@ static int resolve_symbols(struct elf_module *module) {
case DT_RELENT:
rel_entry = dyn_entry->d_un.d_val;
break;
-
+
// Module initialization and termination
case DT_INIT:
// TODO Implement initialization functions
@@ -587,59 +588,59 @@ static int resolve_symbols(struct elf_module *module) {
// 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;
}
static int check_symbols(struct elf_module *module) {
- int i;
+ unsigned int i;
Elf32_Sym *crt_sym, *ref_sym;
char *crt_name;
struct elf_module *crt_module;
-
+
int strong_count;
int weak_count;
-
+
// The chain count gives the number of symbols
for (i = 1; i < module->hash_table[1]; i++) {
crt_sym = (Elf32_Sym*)(module->sym_table + i * module->syment_size);
crt_name = module->str_table + crt_sym->st_name;
-
+
strong_count = 0;
weak_count = 0;
-
+
list_for_each_entry(crt_module, &modules, list) {
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)) {
@@ -652,7 +653,7 @@ static int check_symbols(struct elf_module *module) {
}
}
}
-
+
if (crt_sym->st_shndx == SHN_UNDEF) {
// We have an undefined symbol
if (strong_count == 0 && weak_count == 0) {
@@ -667,7 +668,7 @@ static int check_symbols(struct elf_module *module) {
}
}
}
-
+
return 0;
}
@@ -675,56 +676,60 @@ static int check_symbols(struct elf_module *module) {
int module_load(struct elf_module *module) {
int res;
Elf32_Ehdr elf_hdr;
-
+
// Get a mapping/copy of the ELF file in memory
res = image_load(module);
-
+
if (res < 0) {
return res;
}
-
+
CHECKED(res, image_read(&elf_hdr, sizeof(Elf32_Ehdr), module), error);
-
+
// Checking the header signature and members
CHECKED(res, check_header(&elf_hdr), error);
// DEBUG
+#ifdef ELF_USERSPACE_TEST
print_elf_ehdr(&elf_hdr);
-
+#endif // ELF_USERSPACE_TEST
+
// Load the segments in the memory
CHECKED(res, load_segments(module, &elf_hdr), error);
// Obtain dynamic linking information
CHECKED(res, prepare_dynlinking(module), error);
-
+
// DEBUG
+#ifdef ELF_USERSPACE_TEST
print_elf_symbols(module);
-
+#endif // ELF_USERSPACE_TEST
+
// Check the symbols for duplicates / missing definitions
CHECKED(res, check_symbols(module), error);
-
+
// Add the module at the beginning of the module list
list_add(&module->list, &modules);
-
+
// Perform the relocations
resolve_symbols(module);
-
+
// The file image is no longer needed
image_unload(module);
-
-
+
+
return 0;
-
+
error:
// Remove the module from the module list (if applicable)
list_del_init(&module->list);
-
+
if (module->module_addr != NULL) {
- free(module->module_addr);
+ elf_free(module->module_addr);
module->module_addr = NULL;
}
-
+
image_unload(module);
-
+
return res;
}
@@ -736,20 +741,20 @@ int module_unload(struct elf_module *module) {
fprintf(stderr, "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
- free(module->module_addr);
+ elf_free(module->module_addr);
// Release the module structure
free(module);
-
+
return 0;
}
@@ -757,76 +762,76 @@ int module_unload(struct elf_module *module) {
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) {
fprintf(stderr, "Warning: 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) &
+ 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 +
+ 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;
}
@@ -834,19 +839,19 @@ static Elf32_Sym *module_find_symbol_gnu(const char *name, struct elf_module *mo
} while ((*hasharr++ & 1u) == 0);
}
}
-
+
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)
result = module_find_symbol_sysv(name, module);
-
+
return result;
}
@@ -854,10 +859,10 @@ 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;
-
+
list_for_each_entry(crt_module, &modules, list) {
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:
@@ -877,6 +882,6 @@ Elf32_Sym *global_find_symbol(const char *name, struct elf_module **module) {
}
}
}
-
+
return result;
}
diff --git a/elf/elf_module.h b/com32/elflink/elf_module.h
index 1454ee71..1454ee71 100644
--- a/elf/elf_module.h
+++ b/com32/elflink/elf_module.h
diff --git a/com32/elflink/elf_utils.c b/com32/elflink/elf_utils.c
new file mode 100644
index 00000000..be320772
--- /dev/null
+++ b/com32/elflink/elf_utils.c
@@ -0,0 +1,70 @@
+#include <stdlib.h>
+#include <errno.h>
+
+#include "elf_utils.h"
+
+unsigned long elf_hash(const unsigned char *name) {
+ unsigned long h = 0;
+ unsigned long g;
+
+ while (*name) {
+ h = (h << 4) + *name++;
+ if ((g = h & 0xF0000000))
+ h ^= g >> 24;
+
+ h &= ~g;
+ }
+
+ return h;
+}
+
+unsigned long elf_gnu_hash(const unsigned char *name) {
+ unsigned long h = 5381;
+ unsigned char c;
+
+ for (c = *name; c != '\0'; c = *++name) {
+ h = h * 33 + c;
+ }
+
+ return h & 0xFFFFFFFF;
+}
+
+
+struct memalign_info {
+ void *start_addr;
+ char data[0];
+};
+
+int elf_malloc(void **memptr, size_t alignment, size_t size) {
+ void *start_addr = NULL;
+ struct memalign_info *info;
+
+ if ((alignment & (alignment - 1)) != 0)
+ return EINVAL;
+ if (alignment % sizeof(void*) != 0)
+ return EINVAL;
+
+ start_addr = malloc(size + (alignment > sizeof(struct memalign_info) ?
+ alignment : sizeof(struct memalign_info)));
+
+ if (start_addr == NULL)
+ return ENOMEM;
+
+
+ info = (struct memalign_info*)(start_addr -
+ ((unsigned long)start_addr % alignment) +
+ alignment - sizeof(struct memalign_info));
+
+ info->start_addr = start_addr;
+
+ *memptr = info->data;
+
+ return 0;
+}
+
+void elf_free(void *memptr) {
+ struct memalign_info *info = (struct memalign_info*)(memptr -
+ sizeof(struct memalign_info));
+
+ free(info->start_addr);
+}
diff --git a/elf/elf_utils.h b/com32/elflink/elf_utils.h
index 888d912a..b8df660e 100644
--- a/elf/elf_utils.h
+++ b/com32/elflink/elf_utils.h
@@ -2,6 +2,7 @@
#define ELF_UTILS_H_
#include <elf.h>
+#include <stdlib.h>
// Returns a pointer to the ELF header structure
static inline Elf32_Ehdr *elf_get_header(void *elf_image) {
@@ -11,7 +12,7 @@ static inline Elf32_Ehdr *elf_get_header(void *elf_image) {
// Returns a pointer to the first entry in the Program Header Table
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);
}
@@ -19,11 +20,14 @@ static inline Elf32_Phdr *elf_get_pht(void *elf_image) {
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);
}
extern unsigned long elf_hash(const unsigned char *name);
extern unsigned long elf_gnu_hash(const unsigned char *name);
+extern int elf_malloc(void **memptr, size_t alignment, size_t size);
+extern void elf_free(void *memptr);
+
#endif /*ELF_UTILS_H_*/
diff --git a/com32/elflink/elflink.c b/com32/elflink/elflink.c
new file mode 100644
index 00000000..22b0db5d
--- /dev/null
+++ b/com32/elflink/elflink.c
@@ -0,0 +1,6 @@
+#include "elf_module.h"
+
+int main(int argc, char **argv) {
+ return 0;
+}
+
diff --git a/elf/elftest.c b/com32/elflink/elftest.c
index 0a38bbe6..0a38bbe6 100644
--- a/elf/elftest.c
+++ b/com32/elflink/elftest.c
diff --git a/elf/hello_def.c b/com32/elflink/hello_def.c
index 2ad60233..2ad60233 100644
--- a/elf/hello_def.c
+++ b/com32/elflink/hello_def.c
diff --git a/elf/hello_ref.c b/com32/elflink/hello_ref.c
index f7b798b4..f7b798b4 100644
--- a/elf/hello_ref.c
+++ b/com32/elflink/hello_ref.c
diff --git a/elf/linux_list.h b/com32/elflink/linux_list.h
index 3b92e254..3b92e254 100644
--- a/elf/linux_list.h
+++ b/com32/elflink/linux_list.h
diff --git a/com32/include/sys/elfcommon.h b/com32/include/sys/elfcommon.h
index cc8f9235..8d6ddb05 100644
--- a/com32/include/sys/elfcommon.h
+++ b/com32/include/sys/elfcommon.h
@@ -59,32 +59,108 @@
#define EM_S390_OLD 0xA390 /* Obsolete interrim value for S/390 */
/* Dynamic type values */
-#define DT_NULL 0
-#define DT_NEEDED 1
-#define DT_PLTRELSZ 2
-#define DT_PLTGOT 3
-#define DT_HASH 4
-#define DT_STRTAB 5
-#define DT_SYMTAB 6
-#define DT_RELA 7
-#define DT_RELASZ 8
-#define DT_RELAENT 9
-#define DT_STRSZ 10
-#define DT_SYMENT 11
-#define DT_INIT 12
-#define DT_FINI 13
-#define DT_SONAME 14
-#define DT_RPATH 15
-#define DT_SYMBOLIC 16
-#define DT_REL 17
-#define DT_RELSZ 18
-#define DT_RELENT 19
-#define DT_PLTREL 20
-#define DT_DEBUG 21
-#define DT_TEXTREL 22
-#define DT_JMPREL 23
-#define DT_LOPROC 0x70000000
-#define DT_HIPROC 0x7fffffff
+#define DT_NULL 0 /* Marks end of dynamic section */
+#define DT_NEEDED 1 /* Name of needed library */
+#define DT_PLTRELSZ 2 /* Size in bytes of PLT relocs */
+#define DT_PLTGOT 3 /* Processor defined value */
+#define DT_HASH 4 /* Address of symbol hash table */
+#define DT_STRTAB 5 /* Address of string table */
+#define DT_SYMTAB 6 /* Address of symbol table */
+#define DT_RELA 7 /* Address of Rela relocs */
+#define DT_RELASZ 8 /* Total size of Rela relocs */
+#define DT_RELAENT 9 /* Size of one Rela reloc */
+#define DT_STRSZ 10 /* Size of string table */
+#define DT_SYMENT 11 /* Size of one symbol table entry */
+#define DT_INIT 12 /* Address of init function */
+#define DT_FINI 13 /* Address of termination function */
+#define DT_SONAME 14 /* Name of shared object */
+#define DT_RPATH 15 /* Library search path (deprecated) */
+#define DT_SYMBOLIC 16 /* Start symbol search here */
+#define DT_REL 17 /* Address of Rel relocs */
+#define DT_RELSZ 18 /* Total size of Rel relocs */
+#define DT_RELENT 19 /* Size of one Rel reloc */
+#define DT_PLTREL 20 /* Type of reloc in PLT */
+#define DT_DEBUG 21 /* For debugging; unspecified */
+#define DT_TEXTREL 22 /* Reloc might modify .text */
+#define DT_JMPREL 23 /* Address of PLT relocs */
+#define DT_BIND_NOW 24 /* Process relocations of object */
+#define DT_INIT_ARRAY 25 /* Array with addresses of init fct */
+#define DT_FINI_ARRAY 26 /* Array with addresses of fini fct */
+#define DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */
+#define DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */
+#define DT_RUNPATH 29 /* Library search path */
+#define DT_FLAGS 30 /* Flags for the object being loaded */
+#define DT_ENCODING 32 /* Start of encoded range */
+#define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/
+#define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */
+#define DT_NUM 34 /* Number used */
+#define DT_LOOS 0x6000000d /* Start of OS-specific */
+#define DT_HIOS 0x6ffff000 /* End of OS-specific */
+#define DT_LOPROC 0x70000000 /* Start of processor-specific */
+#define DT_HIPROC 0x7fffffff /* End of processor-specific */
+
+#define DT_VALRNGLO 0x6ffffd00
+#define DT_GNU_PRELINKED 0x6ffffdf5 /* Prelinking timestamp */
+#define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* Size of conflict section */
+#define DT_GNU_LIBLISTSZ 0x6ffffdf7 /* Size of library list */
+#define DT_CHECKSUM 0x6ffffdf8
+#define DT_PLTPADSZ 0x6ffffdf9
+#define DT_MOVEENT 0x6ffffdfa
+#define DT_MOVESZ 0x6ffffdfb
+#define DT_FEATURE_1 0x6ffffdfc /* Feature selection (DTF_*). */
+#define DT_POSFLAG_1 0x6ffffdfd /* Flags for DT_* entries, effecting
+ the following DT_* entry. */
+#define DT_SYMINSZ 0x6ffffdfe /* Size of syminfo table (in bytes) */
+#define DT_SYMINENT 0x6ffffdff /* Entry size of syminfo */
+#define DT_VALRNGHI 0x6ffffdff
+#define DT_VALTAGIDX(tag) (DT_VALRNGHI - (tag)) /* Reverse order! */
+#define DT_VALNUM 12
+
+/* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the
+ Dyn.d_un.d_ptr field of the Elf*_Dyn structure.
+
+ If any adjustment is made to the ELF object after it has been
+ built these entries will need to be adjusted. */
+#define DT_ADDRRNGLO 0x6ffffe00
+#define DT_GNU_HASH 0x6ffffef5 /* GNU-style hash table. */
+#define DT_TLSDESC_PLT 0x6ffffef6
+#define DT_TLSDESC_GOT 0x6ffffef7
+#define DT_GNU_CONFLICT 0x6ffffef8 /* Start of conflict section */
+#define DT_GNU_LIBLIST 0x6ffffef9 /* Library list */
+#define DT_CONFIG 0x6ffffefa /* Configuration information. */
+#define DT_DEPAUDIT 0x6ffffefb /* Dependency auditing. */
+#define DT_AUDIT 0x6ffffefc /* Object auditing. */
+#define DT_PLTPAD 0x6ffffefd /* PLT padding. */
+#define DT_MOVETAB 0x6ffffefe /* Move table. */
+#define DT_SYMINFO 0x6ffffeff /* Syminfo table. */
+#define DT_ADDRRNGHI 0x6ffffeff
+#define DT_ADDRTAGIDX(tag) (DT_ADDRRNGHI - (tag)) /* Reverse order! */
+#define DT_ADDRNUM 11
+
+/* The versioning entry types. The next are defined as part of the
+ GNU extension. */
+#define DT_VERSYM 0x6ffffff0
+
+#define DT_RELACOUNT 0x6ffffff9
+#define DT_RELCOUNT 0x6ffffffa
+
+/* These were chosen by Sun. */
+#define DT_FLAGS_1 0x6ffffffb /* State flags, see DF_1_* below. */
+#define DT_VERDEF 0x6ffffffc /* Address of version definition
+ table */
+#define DT_VERDEFNUM 0x6ffffffd /* Number of version definitions */
+#define DT_VERNEED 0x6ffffffe /* Address of table with needed
+ versions */
+#define DT_VERNEEDNUM 0x6fffffff /* Number of needed versions */
+#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */
+#define DT_VERSIONTAGNUM 16
+
+/* Sun added these machine-independent extensions in the "processor-specific"
+ range. Be compatible. */
+#define DT_AUXILIARY 0x7ffffffd /* Shared object to load before self */
+#define DT_FILTER 0x7fffffff /* Shared object to get values from */
+#define DT_EXTRATAGIDX(tag) ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1)
+#define DT_EXTRANUM 3
/* Auxilliary table entries */
#define AT_NULL 0 /* end of vector */
@@ -147,6 +223,52 @@
#define SHN_COMMON 0xfff2
#define SHN_HIRESERVE 0xffff
+/* Symbol table definitions */
+
+/* How to extract and insert information held in the st_info field. */
+
+#define ELF32_ST_BIND(val) (((unsigned char) (val)) >> 4)
+#define ELF32_ST_TYPE(val) ((val) & 0xf)
+#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
+
+/* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field. */
+#define ELF64_ST_BIND(val) ELF32_ST_BIND (val)
+#define ELF64_ST_TYPE(val) ELF32_ST_TYPE (val)
+#define ELF64_ST_INFO(bind, type) ELF32_ST_INFO ((bind), (type))
+
+/* Legal values for ST_BIND subfield of st_info (symbol binding). */
+
+#define STB_LOCAL 0 /* Local symbol */
+#define STB_GLOBAL 1 /* Global symbol */
+#define STB_WEAK 2 /* Weak symbol */
+#define STB_NUM 3 /* Number of defined types. */
+#define STB_LOOS 10 /* Start of OS-specific */
+#define STB_HIOS 12 /* End of OS-specific */
+#define STB_LOPROC 13 /* Start of processor-specific */
+#define STB_HIPROC 15 /* End of processor-specific */
+
+/* Legal values for ST_TYPE subfield of st_info (symbol type). */
+
+#define STT_NOTYPE 0 /* Symbol type is unspecified */
+#define STT_OBJECT 1 /* Symbol is a data object */
+#define STT_FUNC 2 /* Symbol is a code object */
+#define STT_SECTION 3 /* Symbol associated with a section */
+#define STT_FILE 4 /* Symbol's name is file name */
+#define STT_COMMON 5 /* Symbol is a common data object */
+#define STT_TLS 6 /* Symbol is thread-local data object*/
+#define STT_NUM 7 /* Number of defined types. */
+#define STT_LOOS 10 /* Start of OS-specific */
+#define STT_HIOS 12 /* End of OS-specific */
+#define STT_LOPROC 13 /* Start of processor-specific */
+#define STT_HIPROC 15 /* End of processor-specific */
+
+
+/* Symbol table indices are found in the hash buckets and chain table
+ of a symbol hash table section. This special index value indicates
+ the end of a chain, meaning no further symbols are found in that bucket. */
+
+#define STN_UNDEF 0 /* End of a chain. */
+
/* Lenght of magic at the start of a file */
#define EI_NIDENT 16
@@ -184,4 +306,59 @@
#define ELFOSABI_NONE 0
#define ELFOSABI_LINUX 3
+/* Intel 80386 specific definitions. */
+
+/* i386 relocs. */
+
+#define R_386_NONE 0 /* No reloc */
+#define R_386_32 1 /* Direct 32 bit */
+#define R_386_PC32 2 /* PC relative 32 bit */
+#define R_386_GOT32 3 /* 32 bit GOT entry */
+#define R_386_PLT32 4 /* 32 bit PLT address */
+#define R_386_COPY 5 /* Copy symbol at runtime */
+#define R_386_GLOB_DAT 6 /* Create GOT entry */
+#define R_386_JMP_SLOT 7 /* Create PLT entry */
+#define R_386_RELATIVE 8 /* Adjust by program base */
+#define R_386_GOTOFF 9 /* 32 bit offset to GOT */
+#define R_386_GOTPC 10 /* 32 bit PC relative offset to GOT */
+#define R_386_32PLT 11
+#define R_386_TLS_TPOFF 14 /* Offset in static TLS block */
+#define R_386_TLS_IE 15 /* Address of GOT entry for static TLS
+ block offset */
+#define R_386_TLS_GOTIE 16 /* GOT entry for static TLS block
+ offset */
+#define R_386_TLS_LE 17 /* Offset relative to static TLS
+ block */
+#define R_386_TLS_GD 18 /* Direct 32 bit for GNU version of
+ general dynamic thread local data */
+#define R_386_TLS_LDM 19 /* Direct 32 bit for GNU version of
+ local dynamic thread local data
+ in LE code */
+#define R_386_16 20
+#define R_386_PC16 21
+#define R_386_8 22
+#define R_386_PC8 23
+#define R_386_TLS_GD_32 24 /* Direct 32 bit for general dynamic
+ thread local data */
+#define R_386_TLS_GD_PUSH 25 /* Tag for pushl in GD TLS code */
+#define R_386_TLS_GD_CALL 26 /* Relocation for call to
+ __tls_get_addr() */
+#define R_386_TLS_GD_POP 27 /* Tag for popl in GD TLS code */
+#define R_386_TLS_LDM_32 28 /* Direct 32 bit for local dynamic
+ thread local data in LE code */
+#define R_386_TLS_LDM_PUSH 29 /* Tag for pushl in LDM TLS code */
+#define R_386_TLS_LDM_CALL 30 /* Relocation for call to
+ __tls_get_addr() in LDM code */
+#define R_386_TLS_LDM_POP 31 /* Tag for popl in LDM TLS code */
+#define R_386_TLS_LDO_32 32 /* Offset relative to TLS block */
+#define R_386_TLS_IE_32 33 /* GOT entry for negated static TLS
+ block offset */
+#define R_386_TLS_LE_32 34 /* Negated offset relative to static
+ TLS block */
+#define R_386_TLS_DTPMOD32 35 /* ID of module containing symbol */
+#define R_386_TLS_DTPOFF32 36 /* Offset in TLS block */
+#define R_386_TLS_TPOFF32 37 /* Negated offset in static TLS block */
+/* Keep this the last entry. */
+#define R_386_NUM 38
+
#endif /* _SYS_ELFCOMMON_H */
diff --git a/elf/TODO b/elf/TODO
deleted file mode 100644
index 9dc92fe3..00000000
--- a/elf/TODO
+++ /dev/null
@@ -1,3 +0,0 @@
-* Check to see whether the module is already inserted.
-* Perform unloading cleanup properly.
-* Create a macro for reporting debugging information.
diff --git a/elf/elf_utils.c b/elf/elf_utils.c
deleted file mode 100644
index 157dc2a8..00000000
--- a/elf/elf_utils.c
+++ /dev/null
@@ -1,27 +0,0 @@
-#include "elf_utils.h"
-
-unsigned long elf_hash(const unsigned char *name) {
- unsigned long h = 0;
- unsigned long g;
-
- while (*name) {
- h = (h << 4) + *name++;
- if ((g = h & 0xF0000000))
- h ^= g >> 24;
-
- h &= ~g;
- }
-
- return h;
-}
-
-unsigned long elf_gnu_hash(const unsigned char *name) {
- unsigned long h = 5381;
- unsigned char c;
-
- for (c = *name; c != '\0'; c = *++name) {
- h = h * 33 + c;
- }
-
- return h & 0xFFFFFFFF;
-}