summaryrefslogtreecommitdiffstats
path: root/mdk-stage1/dietlibc/libdl
diff options
context:
space:
mode:
Diffstat (limited to 'mdk-stage1/dietlibc/libdl')
-rw-r--r--mdk-stage1/dietlibc/libdl/Makefile32
-rw-r--r--mdk-stage1/dietlibc/libdl/README82
-rw-r--r--mdk-stage1/dietlibc/libdl/_dl_alloc.c81
-rw-r--r--mdk-stage1/dietlibc/libdl/_dl_int.h138
-rw-r--r--mdk-stage1/dietlibc/libdl/_dl_jump.S53
-rw-r--r--mdk-stage1/dietlibc/libdl/_dl_load.c401
-rw-r--r--mdk-stage1/dietlibc/libdl/_dl_main.c1059
-rw-r--r--mdk-stage1/dietlibc/libdl/_dl_open.c228
-rw-r--r--mdk-stage1/dietlibc/libdl/_dl_queue.c39
-rw-r--r--mdk-stage1/dietlibc/libdl/_dl_rel.c42
-rw-r--r--mdk-stage1/dietlibc/libdl/_dl_rel.h25
-rw-r--r--mdk-stage1/dietlibc/libdl/_dl_relocate.c96
-rw-r--r--mdk-stage1/dietlibc/libdl/_dl_search.c81
-rw-r--r--mdk-stage1/dietlibc/libdl/dlclose.c40
-rw-r--r--mdk-stage1/dietlibc/libdl/dlerror.c57
-rw-r--r--mdk-stage1/dietlibc/libdl/dlopen.c31
-rw-r--r--mdk-stage1/dietlibc/libdl/dlsym.c93
-rw-r--r--mdk-stage1/dietlibc/libdl/elf_hash.c12
-rw-r--r--mdk-stage1/dietlibc/libdl/elf_hash.h10
-rw-r--r--mdk-stage1/dietlibc/libdl/test/test.c20
-rw-r--r--mdk-stage1/dietlibc/libdl/test/test_so.c11
21 files changed, 2340 insertions, 291 deletions
diff --git a/mdk-stage1/dietlibc/libdl/Makefile b/mdk-stage1/dietlibc/libdl/Makefile
index c0463f887..29164f105 100644
--- a/mdk-stage1/dietlibc/libdl/Makefile
+++ b/mdk-stage1/dietlibc/libdl/Makefile
@@ -1,24 +1,38 @@
# local "test" make file
-SRC = $(wildcard *.c) test/test.c
+CC = gcc
+DCC = diet $(CC)
+
+SRC = $(wildcard *.c) # test/test.c
OBJ = _dl_jump.o $(SRC:.c=.o)
-#CFLAGS = -Wall -O2
-CFLAGS = -g
+#CFLAGS = -Wall -D__OD_CLEAN_ROOM -DNODIETREF -fPIC -g -O
+CFLAGS = -Wall -O2 -D__OD_CLEAN_ROOM -DNODIETREF -fPIC -frerun-loop-opt -fschedule-insns2 $(DEB) # -fomit-frame-pointer
%.o : %.S
- $(HOME)/bin/diet gcc $(CFLAGS) -c -o $@ $^
+ $(DCC) $(CFLAGS) -c -o $@ $^
%.o : %.c
- $(HOME)/bin/diet gcc $(CFLAGS) -c -o $@ $^
+ $(DCC) $(CFLAGS) -c -o $@ $^
+
+it: t.out
+
+a.out: t.out
+ gcc -O -g test/a.c t.out -L/opt/diet/lib-i386 -lc -lgcc -o $@ -Wl,-dynamic-linker=`pwd`/t.out -nostdlib
+
+t.out: _dl_main.o
+ ld -shared -o $@ $? -soname=libdl.so
+
+all: test.out libdl.a
-all: test.out
+libdl.a: $(OBJ)
+ ar cru $@ $^
-test.g: test.c
+test.g: test/test.c
gcc -o $@ $^ -ldl
-test.out: $(OBJ)
- $(HOME)/bin/diet gcc -o $@ $^
+test.out: $(OBJ) test/test.o
+ diet gcc -o $@ $^
clean:
$(RM) *.o *.a *.out *~ # *.so
diff --git a/mdk-stage1/dietlibc/libdl/README b/mdk-stage1/dietlibc/libdl/README
index 5d77bde34..6f1d0e46e 100644
--- a/mdk-stage1/dietlibc/libdl/README
+++ b/mdk-stage1/dietlibc/libdl/README
@@ -1,6 +1,82 @@
-this is the experimental libdl test-pre-pre-alpha code
+this is the experimental libdl
written by Olaf Dreesen
-Shouldn't work yet had some problems with the elf specs...
-and more inconsistencies...
+Fri Nov 15 16:23:28 CET 2002
+
+ fixing the copy-relocation bug.
+
+ TODO as last time.... plus
+ - dlsym with RTLD_NEXT
+
+Wed Nov 6 19:08:00 CET 2002
+
+ Ups.. misunderstood the manual-page of dlopen.
+ now dlopen(0,...) works the way it is described in the susv2, BUT still not
+ complete.
+
+ TODO:
+ - gdb support
+
+ - RTLD_GLOBAL/RTLD_LOCAL
+ at the moment ALL are GLOBAL.
+
+ - open of a shared object ONCE
+ there is no library hard-, symlink detection yet.
+
+ - code for other archs then i386 and arm
+
+
+Fri Sep 13 16:28:42 CEST 2002
+
+ this unified libdl/dynlinker is now the default.
+
+
+Mon Mar 11 19:44:20 CET 2002
+
+ the unified libdl/dynlinker now seems to stand the NORMAL usage so I think
+ it should be tested outside my CLEANROOM :)
+
+ TODO: code for other archs than i386 and arm
+
+
+Thu Nov 1 18:41:36 MET 2001
+
+ ufffff.... now the libdl code can be used in the libdl.so :)
+ Status: it works in my clean room on i386, arm-code started
+
+ TODO: see below :)
+
+
+Wed Jul 4 11:55:00 MEST 2001
+
+ Uwe Ohse pointed to some flaws in my code, I have started to fix them....
+
+ TODO: rebuild the code in a more readable and consistent way.
+ TODO: code for other archs than i386
+
+
+Thu Jun 21 15:32:45 MEST 2001
+
+ It work good enough to make a libdietc.so possible.
+
+ TODO: rebuild the code in a more readable and consistent way.
+ TODO: code for other archs than i386
+
+
+Thu Jun 7 14:10:03 MEST 2001
+
+ Status: test-pre-alpha code
+ the code is now "testable" ...
+ I need a dyn-dietlibc specific ld.so. (in work)
+
+ TODO: rebuild the code in a more readable and consistent way.
+
+
+INITIAL May ? :
+
+ Status: test-pre-pre-alpha code
+
+ Shouldn't work yet. Had and have some problems with the elf specs...
+ and more inconsistencies...
+
diff --git a/mdk-stage1/dietlibc/libdl/_dl_alloc.c b/mdk-stage1/dietlibc/libdl/_dl_alloc.c
new file mode 100644
index 000000000..41d0d4671
--- /dev/null
+++ b/mdk-stage1/dietlibc/libdl/_dl_alloc.c
@@ -0,0 +1,81 @@
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+#include "_dl_int.h"
+
+#ifdef __DIET_LD_SO__
+static struct _dl_handle*_dl_root_handle=(struct _dl_handle*)0;
+static struct _dl_handle*_dl_top_handle=(struct _dl_handle*)0;
+static struct _dl_handle*_dl_free_list=(struct _dl_handle*)0;
+#else
+struct _dl_handle*_dl_root_handle=(struct _dl_handle*)0;
+struct _dl_handle*_dl_top_handle=(struct _dl_handle*)0;
+struct _dl_handle*_dl_free_list=(struct _dl_handle*)0;
+#endif
+
+#ifdef __DIET_LD_SO__
+static
+#endif
+void _dl_free_handle(struct _dl_handle*dh) {
+ if (_dl_root_handle==dh) _dl_root_handle=dh->next;
+ if (_dl_top_handle ==dh) _dl_top_handle=dh->prev;
+
+ if (dh->next) dh->next->prev=dh->prev;
+ if (dh->prev) dh->prev->next=dh->next;
+
+ if ((dh->flags&RTLD_NOSONAME) && dh->name) free(dh->name);
+ memset(dh,0,sizeof(struct _dl_handle));
+ dh->next=_dl_free_list;
+ _dl_free_list=dh;
+}
+
+#ifdef __DIET_LD_SO__
+static
+#endif
+struct _dl_handle*_dl_get_handle() {
+ struct _dl_handle*tmp;
+
+ if (_dl_free_list==0) {
+ register int i,m;
+#ifdef __DIET_LD_SO__
+ tmp = (struct _dl_handle*)_dl_sys_mmap(0,at_pagesize,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0);
+ m=at_pagesize/sizeof(struct _dl_handle);
+#else
+ int ps=getpagesize();
+ tmp = (struct _dl_handle*)mmap(0,ps,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0);
+ m=ps/sizeof(struct _dl_handle);
+#endif
+ for (i=m;i;) _dl_free_handle(tmp+(--i));
+ }
+
+ tmp = _dl_free_list;
+ _dl_free_list = tmp->next;
+
+ tmp->next=0;
+ if (_dl_root_handle) {
+ _dl_top_handle->next=tmp;
+ tmp->prev=_dl_top_handle;
+ } else
+ _dl_root_handle = tmp;
+
+ _dl_top_handle=tmp;
+
+ return tmp;
+}
+
+#ifdef __DIET_LD_SO__
+static
+#endif
+struct _dl_handle*_dl_find_lib(const char* name) {
+ if (name) {
+ if (_dl_root_handle) {
+ struct _dl_handle*tmp;
+ for (tmp=_dl_root_handle;tmp;tmp=tmp->next) {
+ if (!tmp->name) continue;
+ if (!strcmp(tmp->name,name)) return tmp;
+ }
+ }
+ }
+ return 0;
+}
diff --git a/mdk-stage1/dietlibc/libdl/_dl_int.h b/mdk-stage1/dietlibc/libdl/_dl_int.h
index 659e6ee0f..1bab10a92 100644
--- a/mdk-stage1/dietlibc/libdl/_dl_int.h
+++ b/mdk-stage1/dietlibc/libdl/_dl_int.h
@@ -1,31 +1,151 @@
#ifndef ___DL_INT_H__
#define ___DL_INT_H__
+#if defined(__alpha__) || defined(__sparc64__) || defined(__x86_64__)
+#define ELF_CLASS ELFCLASS64
+#else
+#define ELF_CLASS ELFCLASS32
+#endif
+
#include <elf.h>
+#include <dlfcn.h>
+
+#include "_dl_rel.h"
+
+#if ELF_CLASS == ELFCLASS32
+
+#define Elf_Addr Elf32_Addr
+
+#define Elf_Dyn Elf32_Dyn
+#define Elf_Ehdr Elf32_Ehdr
+#define Elf_Phdr Elf32_Phdr
+#define Elf_Rel Elf32_Rel
+#define Elf_Rela Elf32_Rela
+#define Elf_Sym Elf32_Sym
+
+#define ELF_R_SYM(x) ELF32_R_SYM((x))
+#define ELF_R_TYPE(x) ELF32_R_TYPE((x))
+
+#define ELF_ST_BIND(x) ELF32_ST_BIND((x))
+#define ELF_ST_TYPE(x) ELF32_ST_TYPE((x))
+
+#else
+
+#define Elf_Addr Elf64_Addr
+
+#define Elf_Dyn Elf64_Dyn
+#define Elf_Ehdr Elf64_Ehdr
+#define Elf_Phdr Elf64_Phdr
+#define Elf_Rel Elf64_Rel
+#define Elf_Rela Elf64_Rela
+#define Elf_Sym Elf64_Sym
+
+#define ELF_R_SYM(x) ELF64_R_SYM((x))
+#define ELF_R_TYPE(x) ELF64_R_TYPE((x))
+
+#define ELF_ST_BIND(x) ELF64_ST_BIND((x))
+#define ELF_ST_TYPE(x) ELF64_ST_TYPE((x))
+
+#endif
+
+//#define DEBUG
+#ifdef DEBUG
+#ifndef __DIET_LD_SO__
+#include <stdio.h>
+#define pf(s) write(2,s,strlen(s))
+#define ph(l) fdprintf(2,"%08lx",(l))
+#endif
+#endif
+
+#define RTLD_USER 0x10000000
+#define RTLD_NOSONAME 0x20000000
+#define LDSO_FLAGS (RTLD_LAZY|RTLD_GLOBAL|RTLD_NOSONAME)
struct _dl_handle {
+ char * mem_base; /* base address of maped *.so / or zero if program | Elf_Addr l_addr */
+ char * l_name; /* Abloslute filename of this object */
+ Elf_Dyn* dynamic; /* _DYNAMIC */
+
+ struct _dl_handle *next;
+ struct _dl_handle *prev;
+
+ unsigned int flags; /* FLAGS */
+
+ char * name; /* name of shared object */
+
/* basic */
- void * mem_base; /* base address of maped *.so */
unsigned long mem_size; /* len of mem block */
- unsigned int lnk_count; /* reference count */
+ unsigned long lnk_count; /* reference count (other libraries) */
+
+ /* lazy evaluator data */
+ unsigned long*pltgot; /* PLT/GOT */
/* symbol resolve helper */
unsigned long*hash_tab; /* hash table */
- Elf32_Sym * dyn_sym_tab; /* dynamic symbol table */
char * dyn_str_tab; /* dyn_name table */
+ Elf_Sym * dyn_sym_tab; /* dynamic symbol table */
+ _dl_rel_t* plt_rel; /* PLT relocation table */
- Elf32_Rel * plt_rel; /* PLT relocation table */
-
- /* FINI */
+ /* INIT / FINI */
void (*fini)(void);
};
-#define HASH_BUCKET_LEN(p) ((p))
+/* debug communication (GDB) (dyn-linker only) */
+struct r_debug {
+ int r_version;
+ struct _dl_handle* r_map;
+ unsigned long r_brk;
+ enum {
+ RT_CONSISTENT, /* mapping complete */
+ RT_ADD, /* begin add object */
+ RT_DELETE, /* begin del object */
+ } r_state;
+ unsigned long r_ldbase;
+};
+
+#define HASH_BUCKET_LEN(p) (*((p)))
#define HASH_BUCKET(p) ((p)+2)
-#define HASH_CHAIN_LEN(p) ((p)+1)
+#define HASH_CHAIN_LEN(p) (*((p)+1))
#define HASH_CHAIN(p) ((p)+2+HASH_BUCKET_LEN(p))
-unsigned long elf_hash(const unsigned char *name);
+/* _dl_alloc.c */
+extern struct _dl_handle* _dl_root_handle;
+extern struct _dl_handle* _dl_top_handle;
+extern struct _dl_handle* _dl_free_list;
+#ifndef __DIET_LD_SO__
+void _dl_free_handle(struct _dl_handle* dh);
+struct _dl_handle* _dl_get_handle();
+struct _dl_handle* _dl_find_lib(const char* name);
+
+/* _dl_open.c */
+void *_dl_open(const char* filename, int flags);
+
+/* _dl_load.c */
+void *_dl_load(const char* filename, const char*pathname, int fd, int flags);
+struct _dl_handle* _dl_dyn_scan(struct _dl_handle* dh, void* dyn_addr, int flags);
+
+/* _dl_search.c */
+void _dl_set_rpath(const char *path);
+const char* _dl_get_rpath();
+int _dl_search(char *buf, int len, const char *filename);
+
+/* dlsym.c */
+void *_dlsym(void*dh,char*symbol);
+void *_dl_sym_search_str(struct _dl_handle*h,char*name);
+void *_dl_sym(struct _dl_handle * h, int symbol);
+
+/* _dl_queue.c */
+int _dl_queue_lib(const char* name, int flags);
+int _dl_open_dep();
+
+/* _dl_relocate.c */
+int _dl_relocate(struct _dl_handle* dh, _dl_rel_t *rel, int num);
+
+/* dlerror.c */
+extern unsigned int _dl_error;
+extern const char* _dl_error_location;
+extern const char* _dl_error_data;
+#endif
#endif
diff --git a/mdk-stage1/dietlibc/libdl/_dl_jump.S b/mdk-stage1/dietlibc/libdl/_dl_jump.S
index 134f31ea5..bd7115258 100644
--- a/mdk-stage1/dietlibc/libdl/_dl_jump.S
+++ b/mdk-stage1/dietlibc/libdl/_dl_jump.S
@@ -1,8 +1,55 @@
.text
.global _dl_jump
_dl_jump:
+
+#ifdef __i386__
+.type _dl_jump,@function
+
+ pushl %eax # save register args...
+ pushl %ecx
+ pushl %edx
+
+ pushl %ebx
+
+ pushl 20(%esp) # 2. arg from plt
+ pushl 20(%esp) # 1. arg from plt
+
+#ifdef __DYN_LIB
+ call 1f
+1: popl %ebx
+ addl $_GLOBAL_OFFSET_TABLE_+[.-1b],%ebx
+ call do_rel@PLT
+#else
call do_rel
- pop %edx
- pop %edx
- jmp *%eax
+#endif
+ addl $8, %esp
+
+ popl %ebx
+
+ popl %edx # restore register args...
+ popl %ecx
+
+ xchgl %eax, (%esp) # restore eax and save function pointer (for return)
+
+ ret $8 # remove arguments from plt and jump to REAL function
+
+#endif
+
+#ifdef __arm__
+.type _dl_jump,function
+
+ stmdb sp!, {r0, r1, r2, r3}
+ sub r1, ip, lr
+ sub r1, r1, #4
+ add r1, r1, r1 /* dyntab entry */
+ ldr r0, [lr, #-4] /* dynlib handle */
+#ifdef __DYN_LIB
+ bl do_rel(PLT)
+#else
+ bl do_rel
+#endif
+ mov r12, r0
+ ldmia sp!, {r0, r1, r2, r3, lr}
+ mov pc, r12
+#endif
diff --git a/mdk-stage1/dietlibc/libdl/_dl_load.c b/mdk-stage1/dietlibc/libdl/_dl_load.c
new file mode 100644
index 000000000..49e8db0be
--- /dev/null
+++ b/mdk-stage1/dietlibc/libdl/_dl_load.c
@@ -0,0 +1,401 @@
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <dlfcn.h>
+#include <elf.h>
+
+#include "_dl_int.h"
+
+#define _ELF_DWN_ROUND(ps,n) ((n)&(~((ps)-1)))
+#define _ELF_UP_ROUND(ps,n) ((((n)&((ps)-1))?(ps):0)+ _ELF_DWN_ROUND((ps),(n)))
+#define _ELF_RST_ROUND(ps,n) ((n)&((ps)-1))
+
+/* this is an arch specific "return jump" for the relocation */
+void _dl_jump();
+
+/*
+ * this file is a Q. & D. hack ... don't think this is bug free or meaningfull
+ */
+
+static inline int map_flags(int flags)
+{
+ int perm = 0;
+ if (flags & PF_X) perm|=PROT_EXEC;
+ if (flags & PF_R) perm|=PROT_READ;
+ if (flags & PF_W) perm|=PROT_WRITE;
+ return perm;
+}
+
+static inline void *do_map_in(void *base, unsigned long length, int flags, int fd, unsigned long offset)
+{
+ register int op = MAP_PRIVATE;
+ if (base) op|=MAP_FIXED;
+ return mmap(base, length, map_flags(flags), op, fd, offset);
+}
+
+static struct _dl_handle *_dl_map_lib(const char*fn, const char*pathname, int fd, int flags)
+{
+ struct _dl_handle* ret=0;
+ int ps=getpagesize();
+ int i;
+ unsigned char buf[1024];
+ char *m=0,*d=0;
+
+ unsigned long l;
+ struct stat st;
+
+ Elf_Ehdr *eh;
+ Elf_Phdr *ph;
+
+ int ld_nr=0;
+ Elf_Phdr **ld=0;
+ Elf_Phdr *dyn=0;
+
+ if (fd==-1) return 0;
+
+#ifdef DEBUG
+ pf(__func__": "); pf(pathname); pf("\n");
+#endif
+
+ if (fstat(fd,&st)<0) {
+ close(fd);
+ _dl_error=2;
+ return 0;
+ }
+ else {
+ // use st_dev and st_ino for identification
+ }
+
+ if (read(fd, buf, 1024)<128) {
+ close(fd);
+ _dl_error=2;
+ return 0;
+ }
+
+ eh=(Elf_Ehdr*)buf;
+ ph=(Elf_Phdr*)&buf[eh->e_phoff];
+
+ for (i=0; i<eh->e_phnum; i++) {
+ if (ph[i].p_type==PT_LOAD) ++ld_nr;
+ }
+ ld=alloca(ld_nr*sizeof(Elf_Phdr));
+
+ for (ld_nr=i=0; i<eh->e_phnum; i++) {
+ if (ph[i].p_type==PT_LOAD) {
+ ld[ld_nr++]=ph+i;
+ }
+ if (ph[i].p_type==PT_DYNAMIC) {
+ dyn=ph+i;
+ }
+ }
+
+ if (ld_nr==1) {
+ unsigned long offset = _ELF_DWN_ROUND(ps,ld[0]->p_offset);
+ unsigned long off = _ELF_RST_ROUND(ps,ld[0]->p_offset);
+ unsigned long length = _ELF_UP_ROUND(ps,ld[0]->p_memsz+off);
+ ret = _dl_get_handle();
+
+ m = (char*)do_map_in(0, length, ld[0]->p_flags, fd, offset);
+ if (m==MAP_FAILED) { _dl_free_handle(ret); close(fd); return 0; }
+
+ /* zero pad bss */
+ l = ld[0]->p_offset+ld[0]->p_filesz;
+ memset(m+l,0,length-l);
+
+ ret->mem_base=m;
+ ret->mem_size=length;
+ }
+ else if (ld_nr==2) { /* aem... yes Quick & Really Dirty / for the avarage 99% */
+// unsigned long text_addr = _ELF_DWN_ROUND(ps,ld[0]->p_vaddr); /* do we need this ? */
+ unsigned long text_offset = _ELF_DWN_ROUND(ps,ld[0]->p_offset);
+ unsigned long text_off = _ELF_RST_ROUND(ps,ld[0]->p_offset);
+ unsigned long text_size = _ELF_UP_ROUND(ps,ld[0]->p_memsz+text_off);
+
+ unsigned long data_addr = _ELF_DWN_ROUND(ps,ld[1]->p_vaddr);
+ unsigned long data_offset = _ELF_DWN_ROUND(ps,ld[1]->p_offset);
+ unsigned long data_off = _ELF_RST_ROUND(ps,ld[1]->p_offset);
+ unsigned long data_size = _ELF_UP_ROUND(ps,ld[1]->p_memsz+data_off);
+ unsigned long data_fsize = _ELF_UP_ROUND(ps,ld[1]->p_filesz+data_off);
+
+ ret = _dl_get_handle();
+ /* mmap all mem_blocks for *.so */
+ m = (char*) do_map_in(0,text_size+data_size,ld[0]->p_flags,fd,text_offset);
+ if (m==MAP_FAILED) { _dl_free_handle(ret); close(fd); return 0; }
+
+ /* release data,bss part */
+ mprotect(m+data_addr, data_size, PROT_NONE);
+
+ /* mmap data,bss part */
+ d = (char*) do_map_in(m+data_addr,data_fsize,ld[1]->p_flags,fd,data_offset);
+
+ /* zero pad bss */
+ l = data_off+ld[1]->p_filesz;
+ memset(d+l,0,data_fsize-l);
+
+ /* more bss ? */
+ if (data_size>data_fsize) {
+ l = data_size-data_fsize;
+ mmap(d+data_fsize, l, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0);
+ }
+
+ ret->mem_base=m;
+ ret->mem_size=text_size+data_size;
+ }
+
+ if (ret) {
+ ret->lnk_count=1;
+ ret->name=strdup(fn);
+ ret->dyn_str_tab=(char*)m+dyn->p_vaddr; /* missuse of field */
+ }
+
+ close(fd);
+ return ret;
+}
+
+/* local alias */
+static struct _dl_handle* __dl_dyn_scan(struct _dl_handle* dh, void* dyn_addr, int flags)
+__attribute__ ((alias("_dl_dyn_scan")));
+
+struct _dl_handle* _dl_dyn_scan(struct _dl_handle* dh, void* dyn_addr, int flags)
+{
+ Elf_Dyn* dyn_tab = dyn_addr;
+
+ void (*init)()=0;
+ unsigned long* got=0;
+ void* jmprel=0;
+ int pltreltype=0;
+ int pltrelsize=0;
+ unsigned long rel=0;
+ int relent=0;
+ int relsize=0;
+
+ int i;
+
+#ifdef DEBUG
+ pf(__func__": pre dynamic scan "); ph((unsigned long)dh); pf("\n");
+#endif
+ dh->dyn_str_tab=0;
+ dh->flags=flags;
+
+ for(i=0;dyn_tab[i].d_tag;i++) {
+// DEBUG(printf("_dl_load dyn %d, %08lx\n",dyn_tab[i].d_tag, dyn_tab[i].d_un.d_val);)
+ if (dyn_tab[i].d_tag==DT_HASH) {
+ dh->hash_tab = (unsigned long*)(dh->mem_base+dyn_tab[i].d_un.d_ptr);
+#ifdef DEBUG
+ pf(__func__": have hash @ "); ph((long)dh->hash_tab); pf("\n");
+#endif
+ }
+ else if (dyn_tab[i].d_tag==DT_SYMTAB) {
+ dh->dyn_sym_tab = (Elf_Sym*)(dh->mem_base+dyn_tab[i].d_un.d_ptr);
+#ifdef DEBUG
+ pf(__func__": have dyn_sym_tab @ "); ph((long)dh->dyn_sym_tab); pf("\n");
+#endif
+ }
+ else if (dyn_tab[i].d_tag==DT_STRTAB) {
+ dh->dyn_str_tab = (char*)(dh->mem_base+dyn_tab[i].d_un.d_ptr);
+#ifdef DEBUG
+ pf(__func__": have dyn_str_tab @ "); ph((long)dh->dyn_str_tab); pf("\n");
+#endif
+ }
+
+ /* INIT / FINI */
+ else if (dyn_tab[i].d_tag==DT_FINI) {
+ dh->fini = (void(*)(void))(dh->mem_base+dyn_tab[i].d_un.d_val);
+#ifdef DEBUG
+ pf(__func__": have fini @ "); ph((long)dh->fini); pf("\n");
+#endif
+ }
+ else if (dyn_tab[i].d_tag==DT_INIT) {
+ init = (void(*)(void))(dh->mem_base+dyn_tab[i].d_un.d_val);
+#ifdef DEBUG
+ pf(__func__": have init @ "); ph((long)init); pf("\n");
+#endif
+ }
+
+ /* PLT / Relocation entries for PLT in GOT */
+ else if (dyn_tab[i].d_tag==DT_PLTGOT) {
+ got=(unsigned long*)(dh->mem_base+dyn_tab[i].d_un.d_val);
+ dh->pltgot=got;
+#ifdef DEBUG
+ pf(__func__": have plt got @ "); ph((long)dh->pltgot); pf("\n");
+#endif
+ }
+ else if (dyn_tab[i].d_tag==DT_PLTREL) {
+ pltreltype=dyn_tab[i].d_un.d_val;
+#ifdef DEBUG
+ pf(__func__": have pltreltype @ "); ph((long)pltreltype); pf("\n");
+#endif
+ }
+ else if (dyn_tab[i].d_tag==DT_PLTRELSZ) {
+ pltrelsize=dyn_tab[i].d_un.d_val;
+#ifdef DEBUG
+ pf(__func__": have pltrelsize @ "); ph((long)pltrelsize); pf("\n");
+#endif
+ }
+ else if (dyn_tab[i].d_tag==DT_JMPREL) {
+ jmprel=(dh->mem_base+dyn_tab[i].d_un.d_val);
+ dh->plt_rel=jmprel;
+#ifdef DEBUG
+ pf(__func__": have jmprel @ "); ph((long)jmprel); pf("\n");
+#endif
+ }
+
+ /* Relocation */
+ else if (dyn_tab[i].d_tag==DT_REL) {
+ rel=(unsigned long)(dh->mem_base+dyn_tab[i].d_un.d_val);
+#ifdef DEBUG
+ pf(__func__": have rel @ "); ph((long)rel); pf("\n");
+#endif
+ }
+ else if (dyn_tab[i].d_tag==DT_RELENT) {
+ relent=dyn_tab[i].d_un.d_val;
+#ifdef DEBUG
+ pf(__func__": have relent @ "); ph((long)relent); pf("\n");
+#endif
+ }
+ else if (dyn_tab[i].d_tag==DT_RELSZ) {
+ relsize=dyn_tab[i].d_un.d_val;
+#ifdef DEBUG
+ pf(__func__": have relsize @ "); ph((long)relsize); pf("\n");
+#endif
+ }
+
+ else if (dyn_tab[i].d_tag==DT_TEXTREL) {
+ _dl_free_handle(dh);
+ _dl_error = 3;
+ return 0;
+ }
+ }
+ /* extra scan for rpath (if program) ... */
+ if (dh->name==0) {
+ for(i=0;dyn_tab[i].d_tag;i++) {
+ if (dyn_tab[i].d_tag==DT_RPATH) {
+ char *rpath=dh->dyn_str_tab+dyn_tab[i].d_un.d_val;
+ _dl_set_rpath(rpath);
+#ifdef DEBUG
+ pf(__func__": have runpath: "); pf(rpath); pf("\n");
+#endif
+ }
+ }
+ }
+
+#ifdef DEBUG
+ pf(__func__": post dynamic scan "); ph((unsigned long)dh); pf("\n");
+#endif
+
+ if ((got=_dlsym(dh,"_GLOBAL_OFFSET_TABLE_"))) {
+#ifdef DEBUG
+ pf(__func__": found a GOT @ "); ph((unsigned long)got); pf("\n");
+#endif
+ /* GOT */
+ got[0]+=(unsigned long)dh->mem_base; /* reloc dynamic pointer */
+ got[1] =(unsigned long)dh;
+ got[2] =(unsigned long)(_dl_jump); /* sysdep jump to _dl_rel */
+ /* */
+ }
+ else {
+ if (dh) {
+ munmap(dh->mem_base,dh->mem_size);
+ _dl_free_handle(dh);
+ }
+ _dl_error = 3;
+ return 0;
+ }
+
+ /* load other libs */
+ for(i=0;dyn_tab[i].d_tag;i++) {
+ if (dyn_tab[i].d_tag==DT_NEEDED) {
+ char *lib_name=dh->dyn_str_tab+dyn_tab[i].d_un.d_val;
+#ifdef DEBUG
+ pf(__func__": needed for this lib: "); pf(lib_name); pf("\n");
+#endif
+ _dl_queue_lib(lib_name,flags);
+ }
+ }
+
+ if (_dl_open_dep()) {
+ _dl_error = 1;
+ return 0;
+ }
+
+ /* relocate */
+ if (rel) {
+#ifdef DEBUG
+ pf(__func__": try to relocate some values\n");
+#endif
+ if (_dl_relocate(dh,(Elf_Rel*)rel,relsize/relent)) {
+ munmap(dh->mem_base,dh->mem_size);
+ _dl_free_handle(dh);
+ return 0;
+ }
+ }
+
+ /* do PTL / GOT relocation */
+ if (pltreltype == DT_REL) {
+ Elf_Rel *tmp = jmprel;
+#ifdef DEBUG
+ pf(__func__": rel got\n");
+#endif
+ for (;(char*)tmp<(((char*)jmprel)+pltrelsize);(char*)tmp=((char*)tmp)+sizeof(Elf_Rel)) {
+ if ((flags&RTLD_NOW)) {
+ unsigned long sym=(unsigned long)_dl_sym(dh,ELF_R_SYM(tmp->r_info));
+ if (sym) *((unsigned long*)(dh->mem_base+tmp->r_offset))=sym;
+ else {
+ _dl_free_handle(dh);
+ _dl_error = 4;
+ return 0;
+ }
+ }
+ else
+ *((unsigned long*)(dh->mem_base+tmp->r_offset))+=(unsigned long)dh->mem_base;
+#if 0
+ DEBUG("_dl_load rel @ %08lx with type %d -> %d\n",(long)dh->mem_base+tmp->r_offset,ELF_R_TYPE(tmp->r_info),ELF_R_SYM(tmp->r_info));
+ DEBUG("_dl_load -> %08lx\n",*((unsigned long*)(dh->mem_base+tmp->r_offset)));
+#endif
+ }
+ }
+ if (pltreltype == DT_RELA) {
+ Elf_Rela *tmp = jmprel;
+#ifdef DEBUG
+ pf(__func__": rela got\n");
+#endif
+ for (;(char*)tmp<(((char*)jmprel)+pltrelsize);(char*)tmp=((char*)tmp)+sizeof(Elf_Rela)) {
+ if ((flags&RTLD_NOW)) {
+ unsigned long sym=(unsigned long)_dl_sym(dh,ELF_R_SYM(tmp->r_info));
+ if (sym) *((unsigned long*)(dh->mem_base+tmp->r_offset))=sym;
+ else {
+ _dl_free_handle(dh);
+ _dl_error = 4;
+ return 0;
+ }
+ }
+ else
+ *((unsigned long*)(dh->mem_base+tmp->r_offset))=(unsigned long)(dh->mem_base+tmp->r_addend);
+#if 0
+ DEBUG("_dl_load rela @ %08lx with type %d -> %d\n",(long)dh->mem_base+tmp->r_offset,ELF_R_TYPE(tmp->r_info),ELF_R_SYM(tmp->r_info));
+ DEBUG("_dl_load -> %08lx\n",*((unsigned long*)(dh->mem_base+tmp->r_offset)));
+#endif
+ }
+ }
+
+ /* _dl_load depending libs ... */
+#ifdef DEBUG
+ pf(__func__": post resolve, pre init\n");
+#endif
+ if (init) init();
+#ifdef DEBUG
+ pf(__func__": post init\n");
+#endif
+
+ return dh;
+}
+
+void *_dl_load(const char*fn, const char*pathname, int fd, int flags)
+{
+ struct _dl_handle* ret=0;
+ if ((ret=_dl_map_lib(fn,pathname,fd,flags))) {
+ ret=__dl_dyn_scan(ret,(void*)(ret->dyn_str_tab),flags);
+ }
+ return ret;
+}
diff --git a/mdk-stage1/dietlibc/libdl/_dl_main.c b/mdk-stage1/dietlibc/libdl/_dl_main.c
new file mode 100644
index 000000000..8ecf44f0b
--- /dev/null
+++ b/mdk-stage1/dietlibc/libdl/_dl_main.c
@@ -0,0 +1,1059 @@
+#ifdef __OD_CLEAN_ROOM
+
+#define __DIET_LD_SO__
+
+/*
+ * this is the dietlibc libdl & dynamic-linker
+ *
+ * NEED to be compiled with -fPIC ...
+ */
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include "_dl_int.h"
+#include "_dl_rel.h"
+
+void _start(void); /* entry of lib... */
+
+static void (*fini_entry)(void)=0;
+static char **_dl_environ=0;
+static unsigned long loadaddr=0;
+static unsigned long prog_entry=0;
+
+static Elf_Phdr*prog_ph;
+static unsigned long prog_ph_size;
+static unsigned long prog_ph_num;
+
+static unsigned long at_uid;
+static unsigned long at_euid;
+static unsigned long at_gid;
+static unsigned long at_egid;
+static unsigned long at_pagesize;
+
+/* this are the "local syscalls" */
+void _dl_sys_exit(int val);
+int _dl_sys_read(int fd,char*buf,unsigned long len);
+int _dl_sys_write(int fd,char*buf,unsigned long len);
+int _dl_sys_open(const char*filename,int flags,int mode);
+int _dl_sys_close(int fd);
+void*_dl_sys_mmap(void*start,unsigned long length,int prot,int flags,int fd,unsigned long offset);
+int _dl_sys_munmap(void*start,unsigned long length);
+int _dl_sys_mprotect(const void*addr,unsigned long len,int prot);
+int _dl_sys_fstat(int filedes, struct stat *buf);
+
+extern char*strdup(const char*s);
+
+#ifdef __i386__
+
+asm(".text \n"
+".type _start,@function \n"
+"_start: \n"
+" movl %esp, %ebp # save stack \n"
+" movl (%ebp), %ecx # argc \n"
+" leal 4(%ebp), %esi # argv \n"
+" leal 4(%esi,%ecx,4), %eax # envp \n"
+
+"# PIC code \n"
+" call getpic \n"
+" addl $_GLOBAL_OFFSET_TABLE_, %ebx \n"
+
+"# for calculation of load addr, get 'relocated' address of _DYNAMIC \n"
+" leal _DYNAMIC@GOTOFF(%ebx), %edx \n"
+
+"# put parameter on stack and call _dl_main \n"
+" pushl %edx \n"
+" pushl %eax \n"
+" pushl %esi \n"
+" pushl %ecx \n"
+" call _dl_main \n"
+
+"# restore stack \n"
+" movl %ebp, %esp \n"
+
+"# get fini pointer \n"
+" movl fini_entry@GOTOFF(%ebx), %edx \n"
+
+"# clear callee-save-register like kernel \n"
+" xorl %ebx, %ebx \n"
+" xorl %ebp, %ebp \n"
+" xorl %edi, %edi \n"
+" xorl %esi, %esi \n"
+
+"# jump to program entry point \n"
+" jmp *%eax \n"
+
+"_dl_sys_read: \n"
+" movb $3,%al \n"
+" jmp _dl_sys_call3 \n"
+"_dl_sys_write: \n"
+" movb $4,%al \n"
+" jmp _dl_sys_call3 \n"
+"_dl_sys_open: \n"
+" movb $5,%al \n"
+" jmp _dl_sys_call3 \n"
+"_dl_sys_close: \n"
+" movb $6,%al \n"
+" jmp _dl_sys_call3 \n"
+"_dl_sys_mmap: \n"
+" movb $90,%al \n"
+" leal 4(%esp),%edx \n"
+" pushl %edx \n"
+" call _dl_sys_call3 \n"
+" popl %ecx \n"
+" ret \n"
+"_dl_sys_munmap: \n"
+" movb $91,%al \n"
+" jmp _dl_sys_call3 \n"
+"_dl_sys_fstat: \n"
+" movb $108,%al \n"
+" jmp _dl_sys_call3 \n"
+"_dl_sys_mprotect: \n"
+" movb $125,%al \n"
+" jmp _dl_sys_call3 \n"
+"_dl_sys_exit: \n"
+" movb $1,%al \n"
+"_dl_sys_call3: \n"
+" movzbl %al,%eax \n"
+" pushl %ebx \n"
+" movl %esp,%ebx \n"
+" movl 16(%ebx),%edx \n"
+" movl 12(%ebx),%ecx \n"
+" movl 8(%ebx),%ebx \n"
+" int $0x80 \n"
+" popl %ebx \n"
+" ret \n"
+
+".type _dl_jump,@function \n"
+"_dl_jump: \n"
+" pushl %eax # save register args... \n"
+" pushl %ecx \n"
+" pushl %edx \n"
+
+" push 16(%esp) # 2. arg from plt \n"
+" push 16(%esp) # 1. arg from plt \n"
+" call do_resolve \n"
+" add $8, %esp \n"
+
+" popl %edx # restore register args... \n"
+" popl %ecx \n"
+" xchgl %eax, (%esp) # restore eax and save function pointer (for return) \n"
+" ret $8 # remove arguments from plt and jump to REAL function \n"
+
+"# GET Position In Code :) \n"
+"getpic: movl (%esp), %ebx \n"
+" ret");
+
+static inline unsigned long* get_got(void) {
+ register unsigned long *got asm ("%ebx");
+ return got;
+}
+
+static inline int work_on_pltgot(struct _dl_handle*dh) {
+ /* declare _dl_jump static otherwise we have a GOT access BEFOR we have the resolver */
+ static void _dl_jump(void);
+ if ((dh->plt_rel)&&(!(dh->flags&RTLD_NOW))) {
+ unsigned long*tmp=dh->pltgot;
+ /* GOT */
+ tmp[0]+=(unsigned long)dh->mem_base; /* reloc dynamic pointer */
+ tmp[1] =(unsigned long)dh; /* the handle */
+ tmp[2] =(unsigned long)(_dl_jump); /* sysdep jump to do_resolve */
+ }
+ return 0;
+}
+
+#elif __arm__
+
+asm(".text \n"
+".type _start,function \n"
+"_start: \n"
+" mov r4, sp \n"
+" mov fp, #0 @ start new stack frame \n"
+
+" ldr a1, [sp], #4 @ argc \n"
+" mov a2, sp @ argv \n"
+
+" add a3, a2, a1, lsl #2 @ envp \n"
+" add a3, a3, #4 \n"
+
+" ldr sl, .L_got @ PIC code \n"
+"1: add sl, pc, sl \n"
+
+" ldr a4, .L_la @ get 'relocated' address of _DYNAMIC \n"
+" add a4, a4, sl \n"
+
+" bl _dl_main @ call _dl_main \n"
+
+" mov sp, r4 \n"
+
+" mov lr, a1 @ save program entry point \n"
+
+" ldr a1, [pc, #.L_fe-(.+8)] @ agrument 1: global fini entry \n"
+" ldr a1, [sl, a1] \n"
+
+" mov pc, lr \n"
+
+".L_got: .long _GLOBAL_OFFSET_TABLE_-(1b+8) \n"
+".L_la: .long _DYNAMIC(GOTOFF) \n"
+".L_fe: .long fini_entry(GOTOFF) \n"
+
+"_dl_sys_exit: \n"
+" swi #0x900001 @ exit \n"
+" eor pc, lr, lr @ OR DIE ! \n"
+" mov pc, lr \n"
+
+"_dl_sys_read: \n"
+" swi #0x900003 @ read \n"
+" mov pc, lr \n"
+"_dl_sys_write: \n"
+" swi #0x900004 @ write \n"
+" mov pc, lr \n"
+"_dl_sys_open: \n"
+" swi #0x900005 @ open \n"
+" mov pc, lr \n"
+"_dl_sys_close: \n"
+" swi #0x900006 @ close \n"
+" mov pc, lr \n"
+"_dl_sys_mmap: \n"
+" stmdb sp!,{r0,r1,r2,r3} \n"
+" mov r0, sp \n"
+" swi #0x900090 @ mmap \n"
+" add sp, sp, #16 \n"
+" mov pc, lr \n"
+"_dl_sys_munmap: \n"
+" swi #0x900091 @ munmap \n"
+" mov pc, lr \n"
+"_dl_sys_fstat: \n"
+" swi #0x900108 @ fstat \n"
+" mov pc, lr \n"
+"_dl_sys_mprotect: \n"
+" swi #0x900125 @ mprotect \n"
+" mov pc, lr \n"
+
+".type _dl_jump,function \n"
+"_dl_jump: \n"
+" stmdb sp!, {r0, r1, r2, r3} @ save arguments \n"
+
+" sub r1, ip, lr @ dyntab entry \n"
+" sub r1, r1, #4 \n"
+" add r1, r1, r1 \n"
+
+" ldr r0, [lr, #-4] @ dynlib handle \n"
+
+" bl do_resolve \n"
+
+" mov r12, r0 \n"
+" ldmia sp!, {r0, r1, r2, r3, lr} @ restore arguments \n"
+" mov pc, r12");
+
+static inline unsigned long* get_got(void) {
+ register unsigned long *got asm ("sl");
+ return got;
+}
+
+static inline int work_on_pltgot(struct _dl_handle*dh) {
+ /* declare _dl_jump static otherwise we have a GOT access BEFOR we have the resolver */
+ static void _dl_jump(void);
+ if ((dh->plt_rel)&&(!(dh->flags&RTLD_NOW))) {
+ unsigned long*tmp=dh->pltgot;
+ /* GOT */
+ tmp[0]+=(unsigned long)dh->mem_base; /* reloc dynamic pointer */
+ tmp[1] =(unsigned long)dh; /* the handle */
+ tmp[2] =(unsigned long)(_dl_jump); /* sysdep jump to do_resolve */
+ }
+ return 0;
+}
+
+#else
+#error "libdl: arch not supported"
+#endif
+
+static void*_dl_load(const char*fn,const char*pathname,int fd,int flags);
+
+/* here do the code includes */
+
+/* strncpy */
+static char*strncpy(register char*s,register const char*t,register unsigned long n) {
+ char *dest=s;
+ for(;n;--n) {
+ char ch=*t;
+ *s=ch;
+ if (ch==0) return dest;
+ ++s; ++t;
+ }
+ return 0;
+}
+
+/* strlen.c */
+static unsigned long strlen(register const char*s) {
+ register unsigned long i;
+ if (!s) return 0;
+ for (i=0; *s; ++s) ++i;
+ return i;
+}
+
+/* strcmp.c */
+static int strcmp(register const unsigned char*s,register const unsigned char*t) {
+ register char x;
+ for (;;) {
+ x = *s; if (x != *t) break; if (!x) break; ++s; ++t;
+ }
+ return ((int)(unsigned int)x) - ((int)(unsigned int)*t);
+}
+
+/* strcspn.c */
+static unsigned long strcspn(const char*s,const char*reject) {
+ unsigned long l=0;
+ int a=1,i,al=strlen(reject);
+ while((a)&&(*s)) {
+ for(i=0;(a)&&(i<al);++i) if (*s==reject[i]) a=0;
+ if (a) ++l;
+ ++s;
+ }
+ return l;
+}
+
+/* memcpy.c */
+static void*memcpy(void*dst,const void*src,unsigned long count) {
+ register char *d=dst;
+ register const char *s=src;
+ ++count;
+ while (--count) {
+ *d = *s;
+ ++d; ++s;
+ }
+ return dst;
+}
+
+/* memset.c */
+static void*memset(void*dst,int ch,unsigned long count) {
+ register char *d=dst;
+ ++count;
+ while (--count) {
+ *d=ch;
+ ++d;
+ }
+ return dst;
+}
+
+/* memcmp.c */
+static int memcmp(register const unsigned char*s,register const unsigned char*t,unsigned long count) {
+ register int r;
+ ++count;
+ while(--count) {
+ if ((r=(*s-*t))) return r;
+ ++s;
+ ++t;
+ }
+ return 0;
+}
+
+/* getenv.c */
+static char*getenv(const char*env) {
+ unsigned int i,len=strlen(env);
+ for (i=0;_dl_environ[i];++i) {
+ if ((memcmp(_dl_environ[i],env,len)==0) && (_dl_environ[i][len]=='='))
+ return _dl_environ[i]+len+1;
+ }
+ return 0;
+}
+
+/* basic debug output functions */
+static void pf(const char*s) { _dl_sys_write(2,(void*)s,strlen(s)); }
+static void ph(unsigned long l) {
+ const int max=(sizeof(unsigned long)<<1);
+ unsigned char buf[16];
+ int i;
+ for (i=max;i;l>>=4) {
+ register unsigned long v='0'|(l&15);
+ if (v>'9') v+=0x27;
+ buf[--i]=v;
+ }
+ _dl_sys_write(2,buf,max);
+}
+
+/* the never free strdup (internal) */
+static unsigned long _dl_lib_strdup_len=0;
+static char*_dl_lib_strdup_str;
+static char*_dl_lib_strdup(const char*s) {
+ char*ret=_dl_lib_strdup_str;
+ unsigned long l=strlen(s)+1;
+ if (_dl_lib_strdup_len<l) {
+ ret=(char*)_dl_sys_mmap(0,at_pagesize,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0);
+ _dl_lib_strdup_len=at_pagesize;
+ }
+ _dl_lib_strdup_str=ret+l;
+ _dl_lib_strdup_len-=l;
+ memcpy(ret,s,l);
+ return ret;
+}
+
+#ifdef __GDB_SUPPORT__
+volatile void _dl_debug_state(void);
+/* gdb debug break point */
+void _dl_debug_state() {}
+
+/* gdb debug init stuff */
+struct r_debug _r_debug;
+static struct r_debug* _dl_debug_init(Elf_Addr dl_base) {
+ if (_r_debug.r_brk==0) {
+ _r_debug.r_version = 1;
+ _r_debug.r_ldbase = dl_base;
+ _r_debug.r_map = _dl_root_handle; /* this my be wrong */
+ _r_debug.r_brk = (Elf_Addr)&_dl_debug_state;
+ }
+ return &_r_debug;
+}
+#endif
+
+/* now reuse some unchanged sources */
+#include "dlerror.c"
+#include "_dl_alloc.c"
+
+#include "dlsym.c"
+
+#include "_dl_search.c"
+
+#include "_dl_open.c"
+#include "dlopen.c"
+
+#include "_dl_relocate.c"
+#include "_dl_queue.c"
+
+#include "dlclose.c"
+
+/* back to the "new" implementation */
+static void tt_fini(void) {
+ struct _dl_handle*tmp;
+#ifdef DEBUG
+ pf("dyn fini\n");
+#endif
+ for(tmp=_dl_root_handle;tmp;tmp=tmp->next)
+ if (tmp->fini) tmp->fini();
+}
+
+/* exit ! */
+static void _DIE_() { _dl_sys_exit(213); }
+
+/* lazy function resolver */
+static unsigned long do_resolve(struct _dl_handle*dh,unsigned long off) {
+ _dl_rel_t *tmp = ((void*)dh->plt_rel)+off;
+ int sym=ELF_R_SYM(tmp->r_info);
+ register unsigned long sym_val;
+
+ if (0) sym_val=(unsigned long)do_resolve; /* TRICK: no warning */
+
+ /* modify GOT for REAL symbol */
+ sym_val=(unsigned long)_dl_sym(dh,sym);
+ *((unsigned long*)(dh->mem_base+tmp->r_offset))=sym_val;
+
+ /* JUMP (arg sysdep...) */
+ if (sym_val) return sym_val;
+ /* can't find symbol */
+ return (unsigned long)_DIE_;
+}
+
+/* library loader */
+
+/* ELF -> MMAP permissions */
+static inline int map_flags(int flags) {
+ int perm = 0;
+ if (flags & PF_X) perm|=PROT_EXEC;
+ if (flags & PF_R) perm|=PROT_READ;
+ if (flags & PF_W) perm|=PROT_WRITE;
+ return perm;
+}
+
+/* a simple mmap wrapper */
+static inline void*do_map_in(void*base,unsigned long length,int flags,int fd,unsigned long offset) {
+ register int op = MAP_PRIVATE;
+ if (base) op|=MAP_FIXED;
+ return _dl_sys_mmap(base, length, map_flags(flags), op, fd, offset);
+}
+
+/* map a library into memory */
+#define _ELF_DWN_ROUND(ps,n) ((n)&(~((ps)-1)))
+#define _ELF_UP_ROUND(ps,n) ((((n)&((ps)-1))?(ps):0)+_ELF_DWN_ROUND((ps),(n)))
+#define _ELF_RST_ROUND(ps,n) ((n)&((ps)-1))
+static struct _dl_handle*_dl_map_lib(const char*fn,const char*pathname,int fd,int flags) {
+ struct _dl_handle*ret=0;
+ int i;
+ unsigned char buf[1024];
+ char *m=0,*d=0;
+
+ unsigned long l;
+ struct stat st;
+
+ Elf_Ehdr*eeh;
+ Elf_Phdr*eph;
+
+ int ld_nr=0;
+ Elf_Phdr*ld[4]={0,0,0,0};
+ Elf_Phdr*dyn=0;
+
+ if (0) { pathname=0; } /* no unused parameter */
+ if (fd==-1) return 0;
+
+ if (_dl_sys_fstat(fd,&st)<0) {
+err_out_close:
+ _dl_sys_close(fd);
+ _dl_error_data=fn;
+ _dl_error=2;
+ return 0;
+ } else {
+ /* use st_dev and st_ino for identification */
+ }
+
+ if (_dl_sys_read(fd,buf,1024)<128) goto err_out_close;
+
+ eeh=(Elf_Ehdr*)buf;
+ eph=(Elf_Phdr*)&buf[eeh->e_phoff];
+
+ for (i=0;i<eeh->e_phnum;++i) {
+ if (eph[i].p_type==PT_LOAD) {
+ if (ld_nr>3) goto err_out_close;
+ ld[ld_nr++]=eph+i;
+ }
+ if (eph[i].p_type==PT_DYNAMIC) {
+ dyn=eph+i;
+ }
+ }
+
+ if (ld_nr==1) {
+ unsigned long offset=_ELF_DWN_ROUND(at_pagesize,ld[0]->p_offset);
+ unsigned long off =_ELF_RST_ROUND(at_pagesize,ld[0]->p_offset);
+ unsigned long length=_ELF_UP_ROUND(at_pagesize,ld[0]->p_memsz+off);
+ ret=_dl_get_handle();
+ m=(char*)do_map_in(0,length,ld[0]->p_flags,fd,offset);
+ if (m==MAP_FAILED) goto err_out_free;
+ /* zero pad bss */
+ l=ld[0]->p_offset+ld[0]->p_filesz;
+ memset(m+l,0,length-l);
+
+ ret->mem_base=m;
+ ret->mem_size=length;
+ }
+ else if (ld_nr==2) { /* aem... yes Quick & Really Dirty / for the avarage 99% */
+// unsigned long text_addr = _ELF_DWN_ROUND(at_pagesize,ld[0]->p_vaddr); /* do we need this ? */
+ unsigned long text_offset=_ELF_DWN_ROUND(at_pagesize,ld[0]->p_offset);
+ unsigned long text_off =_ELF_RST_ROUND(at_pagesize,ld[0]->p_offset);
+ unsigned long text_size =_ELF_UP_ROUND(at_pagesize,ld[0]->p_memsz+text_off);
+
+ unsigned long data_addr =_ELF_DWN_ROUND(at_pagesize,ld[1]->p_vaddr);
+ unsigned long data_offset=_ELF_DWN_ROUND(at_pagesize,ld[1]->p_offset);
+ unsigned long data_off =_ELF_RST_ROUND(at_pagesize,ld[1]->p_offset);
+ unsigned long data_size =_ELF_UP_ROUND(at_pagesize,ld[1]->p_memsz+data_off);
+ unsigned long data_fsize =_ELF_UP_ROUND(at_pagesize,ld[1]->p_filesz+data_off);
+
+ ret=_dl_get_handle();
+ /* mmap all mem_blocks for *.so */
+ m=(char*)do_map_in(0,text_size+data_size,ld[0]->p_flags,fd,text_offset);
+ if (m==MAP_FAILED) {
+err_out_free:
+ _dl_free_handle(ret);
+ _dl_sys_close(fd);
+ return 0;
+ }
+
+ /* release data,bss part */
+ _dl_sys_mprotect(m+data_addr,data_size,PROT_NONE);
+
+ /* mmap data,bss part */
+ d=(char*)do_map_in(m+data_addr,data_fsize,ld[1]->p_flags,fd,data_offset);
+
+ /* zero pad bss */
+ l=data_off+ld[1]->p_filesz;
+ memset(d+l,0,data_fsize-l);
+ /* more bss ? */
+ if (data_size>data_fsize) {
+ l=data_size-data_fsize;
+ _dl_sys_mmap(d+data_fsize,l,PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS,-1,0);
+ }
+
+ ret->mem_base=m;
+ ret->mem_size=text_size+data_size;
+ }
+ else {
+ _dl_error_data=fn;
+ _dl_error=7;
+ }
+
+ if (ret) {
+ ++ret->lnk_count;
+ if (flags&RTLD_USER)
+ ret->name=strdup(fn);
+ else
+ ret->name=_dl_lib_strdup(fn);
+ ret->flags=flags;
+ ret->dynamic=(Elf_Dyn*)(m+dyn->p_vaddr);
+ }
+
+ _dl_sys_close(fd);
+ return ret;
+}
+
+/* dynamic section parser */
+static struct _dl_handle* _dl_dyn_scan(struct _dl_handle*dh,Elf_Dyn*_dynamic) {
+ void(*init)(void)=0;
+
+ _dl_rel_t* plt_rel=0;
+ unsigned long plt_relsz=0;
+
+ _dl_rel_t* rel=0;
+ unsigned long relent=0;
+ unsigned long relsize=0;
+
+ int i;
+
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": pre dynamic scan "); ph((unsigned long)dh); pf("\n");
+#endif
+ for(i=0;_dynamic[i].d_tag;++i) {
+ switch(_dynamic[i].d_tag) {
+ /* this depends on dyn_str_tab -> second run */
+ case DT_NEEDED:
+ case DT_SONAME:
+ break;
+
+ /* BASIC DYNAMIC STUFF */
+ case DT_HASH:
+ dh->hash_tab = (unsigned long*)(dh->mem_base+_dynamic[i].d_un.d_ptr);
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": have hash @ "); ph((long)dh->hash_tab); pf("\n");
+#endif
+ break;
+ case DT_SYMTAB:
+ dh->dyn_sym_tab = (Elf_Sym*)(dh->mem_base+_dynamic[i].d_un.d_ptr);
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": have dyn_sym_tab @ "); ph((long)dh->dyn_sym_tab); pf("\n");
+#endif
+ break;
+ case DT_STRTAB:
+ dh->dyn_str_tab = (char*)(dh->mem_base+_dynamic[i].d_un.d_ptr);
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": have dyn_str_tab @ "); ph((long)dh->dyn_str_tab); pf("\n");
+#endif
+ break;
+
+ /* DYNAMIC INIT/FINI (constructors/destructors) */
+ case DT_FINI:
+ dh->fini = (void(*)(void))(dh->mem_base+_dynamic[i].d_un.d_val);
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": have fini @ "); ph((long)dh->fini); pf("\n");
+#endif
+ break;
+ case DT_INIT:
+ init = (void(*)(void))(dh->mem_base+_dynamic[i].d_un.d_val);
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": have init @ "); ph((long)init); pf("\n");
+#endif
+ break;
+
+ /* PLT RELOCATION */
+ case DT_PLTGOT:
+ dh->pltgot = (unsigned long*)(dh->mem_base+_dynamic[i].d_un.d_val);
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": have plt/got @ "); ph((long)dh->pltgot); pf("\n");
+#endif
+ break;
+ case DT_PLTREL:
+ if (_dynamic[i].d_un.d_val!=_DL_REL_T) {
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": have incompatible relocation type\n");
+#endif
+ _dl_error_data=dh->name;
+ _dl_error=6;
+ return 0;
+ }
+ break;
+ case DT_JMPREL:
+ plt_rel = (_dl_rel_t*)(dh->mem_base+_dynamic[i].d_un.d_val);
+ dh->plt_rel = plt_rel;
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": have jmprel @ "); ph((long)plt_rel); pf("\n");
+#endif
+ break;
+ case DT_PLTRELSZ:
+ plt_relsz = _dynamic[i].d_un.d_val;
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": have pltrelsize @ "); ph((long)plt_relsz); pf("\n");
+#endif
+ break;
+
+ /* BASIC RELOCATION */
+ case DT_REL:
+ rel = (_dl_rel_t*)(dh->mem_base+_dynamic[i].d_un.d_val);
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": have rel @ "); ph((long)rel); pf("\n");
+#endif
+ break;
+ case DT_RELENT:
+ relent=_dynamic[i].d_un.d_val;
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": have relent @ "); ph((long)relent); pf("\n");
+#endif
+ break;
+ case DT_RELSZ:
+ relsize=_dynamic[i].d_un.d_val;
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": have relsize @ "); ph((long)relsize); pf("\n");
+#endif
+ break;
+
+
+ /* TEXT RELOCATIONS POSSIBLE -> NO SHARED OBJECT */
+ case DT_TEXTREL:
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": found possible textrelocation -> "); pf(dh->name); pf(" is not compiled as a shared library\n");
+#endif
+ _dl_error_data=dh->name;
+ _dl_error=3;
+ return 0;
+ break;
+
+ /* OTHERS */
+ default:
+#ifdef DEBUG
+#if 0
+ pf(__FUNCTION__); pf(": unknown "); ph(_dynamic[i].d_tag); pf(", "); ph(_dynamic[i].d_un.d_val); pf("\n");
+#endif
+#endif
+ break;
+ }
+ }
+
+ for(i=0;_dynamic[i].d_tag;i++) {
+ if (dh->name) { /* librabry can have a SONAME */
+ if (_dynamic[i].d_tag==DT_SONAME) {
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": pre soname: "); pf(dh->name); pf("\n");
+#endif
+ if (dh->flags&RTLD_USER) free(dh->name);
+ dh->flags&=~RTLD_NOSONAME;
+ dh->name = dh->dyn_str_tab+_dynamic[i].d_un.d_val;
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": have soname: "); pf(dh->name); pf("\n");
+#endif
+ }
+ }
+ else { /* programs can have a LD_RUN_PATH */
+ if (_dynamic[i].d_tag==DT_RPATH) {
+ register char *rpath=dh->dyn_str_tab+_dynamic[i].d_un.d_val;
+ _dl_search_rpath=rpath;
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": have runpath: "); pf(rpath); pf("\n");
+#endif
+ }
+ }
+ }
+
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": post dynamic scan "); ph((unsigned long)dh); pf("\n");
+#endif
+
+ if (work_on_pltgot(dh)) {
+ _dl_error_data=dh->name;
+ _dl_error=3;
+ return 0;
+ }
+
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": pre load depending libraries "); ph((unsigned long)dh); pf("\n");
+#endif
+ /* load depending libs */
+ for(i=0;_dynamic[i].d_tag;++i) {
+ if (_dynamic[i].d_tag==DT_NEEDED) {
+ char *lib_name=dh->dyn_str_tab+_dynamic[i].d_un.d_val;
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": needed for this lib: "); pf(lib_name); pf("\n");
+#endif
+ _dl_queue_lib(lib_name,dh->flags);
+ }
+ }
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": pre open depending libraries 2 "); ph((unsigned long)dh); pf("\n");
+#endif
+ if (_dl_open_dep()) {
+ return 0;
+ }
+
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": post load depending libraries, pre resolve "); ph((unsigned long)dh); pf("\n");
+#endif
+
+ /* relocation */
+ if (rel) {
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": try to relocate some values\n");
+#endif
+ if (_dl_relocate(dh,rel,relsize/relent)) return 0;
+ }
+
+ /* do PTL / GOT relocation */
+ if (plt_rel) {
+ _dl_rel_t *tmp,*max=((void*)plt_rel)+plt_relsz;
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": rel plt/got\n");
+#endif
+ for(tmp=plt_rel;tmp<max;(char*)tmp=((char*)tmp)+sizeof(_dl_rel_t)) {
+ if ((dh->flags&RTLD_NOW)) {
+ unsigned long sym=(unsigned long)_dl_sym(dh,ELF_R_SYM(tmp->r_info));
+ if (sym) *((unsigned long*)(dh->mem_base+tmp->r_offset))=sym;
+ else {
+ _dl_error_data=dh->name;
+ _dl_error=4;
+ return 0;
+ }
+ }
+ else
+ _DL_REL_PLT(dh->mem_base,tmp);
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": rel @ "); ph((long)dh->mem_base+tmp->r_offset); pf(" with type ");
+ ph(ELF_R_TYPE(tmp->r_info)); pf(" and sym "); ph(ELF_R_SYM(tmp->r_info));
+ pf(" -> "); ph(*((unsigned long*)(dh->mem_base+tmp->r_offset))); pf("\n");
+#endif
+ }
+ }
+
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": post resolve, pre init "); ph((unsigned long)dh); pf("\n");
+#endif
+ if (init) init();
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": post init "); ph((unsigned long)dh); pf("\n");
+#endif
+
+ return dh;
+}
+
+static void*_dl_load(const char*fn,const char*pathname,int fd,int flags) {
+ struct _dl_handle*ret=0;
+ if ((ret=_dl_map_lib(fn,pathname,fd,flags))) {
+ ret=_dl_dyn_scan(ret,ret->dynamic);
+ }
+ return ret;
+}
+
+
+/* ELF AUX parser */
+static void _dl_elfaux(register unsigned long*ui) {
+ register struct elf_aux {
+ unsigned long type;
+ unsigned long val;
+ } *ea;
+
+ while (*ui) ++ui;
+ /* now *ui points to the tailing NULL-pointer of the envirioment */
+
+ /* walk the elf_aux table */
+ for (ea=(struct elf_aux*)(ui+1); ea->type; ++ea) {
+ switch (ea->type) {
+ case AT_EXECFD: /* 2 */
+ /* DIE! DIE! DIE! */
+ pf("kernel gives us an unsupported binary load type...\n");
+ _dl_sys_exit(42);
+ break;
+
+ case AT_PHDR: /* 3 */
+ prog_ph=(Elf_Phdr*)ea->val;
+#ifdef DEBUG
+ pf("program header @ "); ph(ea->val); pf("\n");
+#endif
+ break;
+ case AT_PHENT: /* 4 */
+ prog_ph_size=ea->val;
+#ifdef DEBUG
+ pf("program header size "); ph(ea->val); pf("\n");
+#endif
+ break;
+ case AT_PHNUM: /* 5 */
+ prog_ph_num=ea->val;
+#ifdef DEBUG
+ pf("program header # "); ph(ea->val); pf("\n");
+#endif
+ break;
+
+ case AT_PAGESZ: /* 6 */
+ at_pagesize=ea->val;
+#ifdef DEBUG
+ pf("page size "); ph(ea->val); pf("\n");
+#endif
+ break;
+
+ case AT_BASE: /* 7 */
+ loadaddr=ea->val;
+#ifdef DEBUG
+ pf("interpreter base: "); ph(ea->val); pf("\n");
+#endif
+ break;
+
+#if 0
+ case AT_FLAGS: /* 8 */
+#ifdef DEBUG
+ pf("flags "); ph(ea->val); pf("\n");
+#endif
+ break;
+#endif
+
+ case AT_ENTRY: /* 9 */
+ prog_entry=ea->val;
+#ifdef DEBUG
+ pf("start program @ "); ph(ea->val); pf("\n");
+#endif
+ break;
+
+ case AT_NOTELF: /* 10 */
+ pf("this is an ELF-loader... and therefor can't handle anything else.\n");
+ _dl_sys_exit(42);
+ break;
+
+ case AT_UID: /* 11 */
+ at_uid=ea->val;
+#ifdef DEBUG
+ pf(" UID: "); ph(ea->val); pf("\n");
+#endif
+ break;
+ case AT_EUID: /* 12 */
+ at_euid=ea->val;
+#ifdef DEBUG
+ pf("EUID: "); ph(ea->val); pf("\n");
+#endif
+ break;
+ case AT_GID: /* 13 */
+ at_gid=ea->val;
+#ifdef DEBUG
+ pf(" GID: "); ph(ea->val); pf("\n");
+#endif
+ break;
+ case AT_EGID: /* 14 */
+ at_egid=ea->val;
+#ifdef DEBUG
+ pf("EGID: "); ph(ea->val); pf("\n");
+#endif
+ break;
+
+#if 0
+ case AT_PLATFORM: /* 15 */
+#ifdef DEBUG
+ pf("CPU: "); ph(ea->val); pf("\n");
+#endif
+ break;
+ case AT_HWCAP: /* 16 */
+#ifdef DEBUG
+ pf("CPU capabilities: "); ph(ea->val); pf("\n");
+#endif
+ break;
+ case AT_CLKTCK: /* 17 */
+#ifdef DEBUG
+ pf("CLK per sec "); ph( ea->val); pf("\n");
+#endif
+ break;
+ case AT_FPUCW: /* 18 */
+#ifdef DEBUG
+ pf("FPU control word "); ph( ea->val); pf("\n");
+#endif
+ break;
+#endif
+
+ default:
+ break;
+ }
+ }
+}
+
+
+/* start of libdl dynamic linker */
+static unsigned long _dl_main(int argc,char*argv[],char*envp[],unsigned long _dynamic) {
+ unsigned long*got;
+ struct _dl_handle*prog,*mydh;
+ struct _dl_handle my_dh;
+ Elf_Dyn*prog_dynamic=0;
+ unsigned int i;
+
+ if (0) _dl_main(argc,argv,envp,_dynamic); /* TRICK: no warning */
+
+ /* prepare to bootstarp the relocations */
+ got=get_got();
+ _dl_environ=envp;
+
+ /* run elf_aux (kernel provided misc data) */
+ _dl_elfaux((unsigned long*)envp);
+
+ if (loadaddr==0) {
+ pf("\ndiet libdl.so/dynamic-linker can't be started as a program !\n\n SORRY...\n\n");
+ return (unsigned long)_DIE_;
+ }
+
+ memset(&my_dh,0,sizeof(my_dh));
+ my_dh.mem_base=(char*)loadaddr;
+ my_dh.mem_size=0;
+ my_dh.lnk_count=1024;
+ my_dh.name="libdl.so";
+ my_dh.flags=LDSO_FLAGS;
+
+ got[1]=0; /* NOT YET (my_dh) */
+ got[2]=(unsigned long)_DIE_; /* NO lazy symbol resolver as long as we are not ready */
+
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": pre scan\n");
+#endif
+ /* bootstrap relocation */
+ if (_dl_dyn_scan(&my_dh,(Elf_Dyn*)_dynamic)==0) {
+ pf("error with dyn_scan myself\n");
+ return (unsigned long)_DIE_;
+ }
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": post scan\n");
+#endif
+
+ /* now we are save to use anything :) (hopefully) */
+
+ fini_entry=tt_fini;
+
+ prog=_dl_get_handle();
+
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": ugly, ugly, COPY pregenerated handle to real handle\n");
+#endif
+ mydh=_dl_get_handle();
+ {
+ register struct _dl_handle*tmp=mydh->prev;
+ memcpy(mydh,&my_dh,sizeof(struct _dl_handle));
+ mydh->prev=tmp;
+ }
+ got[1]=(unsigned long)mydh;
+
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": MORE ugly: prepare program...\n");
+#endif
+ for(i=0;(i<prog_ph_num);++i) {
+ if (prog_ph[i].p_type==PT_DYNAMIC) {
+ prog_dynamic=(Elf_Dyn*)prog_ph[i].p_vaddr;
+ break;
+ }
+ }
+ if (prog_dynamic==0) {
+ ph(0xe0000001);
+ pf(" error with program: no dynamic section ?\n");
+ return (unsigned long)_DIE_;
+ }
+ prog->name=0;
+ prog->lnk_count=1024;
+ prog->dynamic=prog_dynamic;
+ prog->flags=LDSO_FLAGS;
+
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": dyn_scan program...\n");
+#endif
+ if (_dl_dyn_scan(prog,(Elf_Dyn*)prog_dynamic)==0) {
+ _dl_error_location="error in dyn_scan the program";
+ pf(dlerror()); pf("\n");
+ return (unsigned long)_DIE_;
+ }
+
+ /* now start the program */
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": now jump to program entrypoint\n");
+#endif
+ return prog_entry;
+}
+
+#endif
diff --git a/mdk-stage1/dietlibc/libdl/_dl_open.c b/mdk-stage1/dietlibc/libdl/_dl_open.c
index 1f907db21..f7bd0af95 100644
--- a/mdk-stage1/dietlibc/libdl/_dl_open.c
+++ b/mdk-stage1/dietlibc/libdl/_dl_open.c
@@ -1,207 +1,35 @@
-#include <stdio.h>
-#include <unistd.h>
-#include <sys/mman.h>
+#include <fcntl.h>
#include <dlfcn.h>
-#include <linux/elf.h>
+#include <limits.h>
+#ifndef __DIET_LD_SO__
+#include <string.h>
+#endif
#include "_dl_int.h"
-struct _dl_handle dl_test;
-
-#define _ELF_DWN_ROUND(ps,n) ((n)&(~((ps)-1)))
-#define _ELF_UP_ROUND(ps,n) ((((n)&((ps)-1))?(ps):0)+ _ELF_DWN_ROUND((ps),(n)))
-#define _ELF_RST_ROUND(ps,n) ((n)&((ps)-1))
-
-void _dl_jump();
-
-/*
- * this file is a Q. & D. hack ... don't think this is bug free or meaningfull
- */
-
-static void *do_map_in(void *base, unsigned long length, int flags, int fd, unsigned long offset)
-{
- int perm = 0;
- if (flags & PF_X) perm|=PROT_EXEC;
- if (flags & PF_R) perm|=PROT_READ;
- if (flags & PF_W) perm|=PROT_WRITE;
- return mmap(base, length, perm, MAP_PRIVATE|((base)?MAP_FIXED:0), fd, offset);
-}
-
-unsigned long do_rel(struct _dl_handle * tmp_dl, unsigned long off)
-{
-// struct _dl_handle * tmp_dl = ((void*)*((&off)-1));
- Elf32_Rel *tmp = ((void*)tmp_dl->plt_rel)+off;
- int sym=ELF32_R_SYM(tmp->r_info);
- register unsigned long sym_val;
-
- printf("do_rel %08x %08x\n",tmp_dl,off);
-
- printf ("do_rel %08x+%x\n",tmp_dl->plt_rel,off);
- printf("do_rel @ %08x with type %d -> %d\n",tmp->r_offset,ELF32_R_TYPE(tmp->r_info),sym);
-
- printf("do_rel sym %08x\n",tmp_dl->dyn_sym_tab[sym].st_value);
-
- /* modify GOT for REAL symbol */
- sym_val=((unsigned long)(tmp_dl->mem_base+tmp_dl->dyn_sym_tab[sym].st_value));
- *((unsigned long*)(tmp_dl->mem_base+tmp->r_offset))=sym_val;
-
- printf("do_rel sym %08x\n",sym_val);
- /* HOWTO JUMP ?!? */
- return sym_val;
-}
-
-void *_dl_open(const char*pathname, int fd, int flag)
-{
- int ps=getpagesize();
- int i;
- unsigned char buf[1024];
- char *m=0,*d;
- struct _dl_handle *ret=0;
-
- unsigned long l;
-
- Elf32_Ehdr *eh;
- Elf32_Phdr *ph;
-
- int ld_nr=0;
- Elf32_Phdr *ld[4]={0,0,0,0};
- Elf32_Phdr *dyn=0;
-
- if (fd==-1) return 0;
-
- printf("_dl_open: %s\n",pathname);
-
- read(fd, buf, 1024);
- eh=(Elf32_Ehdr*)buf;
- ph=(Elf32_Phdr*)&buf[eh->e_phoff];
-
- for (i=0; i<eh->e_phnum; i++) {
- if (ph[i].p_type==PT_LOAD) {
- ld[ld_nr++]=ph+i;
- }
- if (ph[i].p_type==PT_DYNAMIC) {
- dyn=ph+i;
- }
+#ifdef __DIET_LD_SO__
+static
+#endif
+void*_dl_open(const char*filename,int flags) {
+ int fd;
+ char buf[PATH_MAX];
+ const char*p=0;
+
+ for (fd=0;filename[fd] && (p==0);++fd) if (filename[fd]=='/') p=filename;
+ if (p) {
+#ifdef __DIET_LD_SO__
+ if ((fd=_dl_sys_open(p,O_RDONLY,0))<0) fd=-1;
+#else
+ fd=open(p,O_RDONLY);
+#endif
+ } else {
+ p=buf;
+ fd=_dl_search(buf,sizeof(buf)-1,filename);
}
-
- if (ld_nr==1) {
- unsigned long offset = _ELF_DWN_ROUND(ps,ld[0]->p_offset);
- unsigned long off = _ELF_RST_ROUND(ps,ld[0]->p_offset);
- unsigned long length = _ELF_UP_ROUND(ps,ld[0]->p_memsz+off);
- m = (char*)do_map_in(0, length, ld[0]->p_flags, fd, offset);
-
- /* zero pad bss */
- l = ld[0]->p_offset+ld[0]->p_filesz;
- memset(m+l,0,length-l);
-
- dl_test.mem_base=m;
- dl_test.mem_size=length;
- dl_test.lnk_count=0;
-
- ret = &dl_test;
- }
- else if (ld_nr==2) { /* aem... yes Quick & Really Dirty / for the avarage 99% */
- //unsigned long text_addr = _ELF_DWN_ROUND(ps,ld[0]->p_vaddr);
- unsigned long text_offset = _ELF_DWN_ROUND(ps,ld[0]->p_offset);
- unsigned long text_off = _ELF_RST_ROUND(ps,ld[0]->p_offset);
- unsigned long text_size = _ELF_UP_ROUND(ps,ld[0]->p_memsz+text_off);
-
- unsigned long data_addr = _ELF_DWN_ROUND(ps,ld[1]->p_vaddr);
- unsigned long data_offset = _ELF_DWN_ROUND(ps,ld[1]->p_offset);
- unsigned long data_off = _ELF_RST_ROUND(ps,ld[1]->p_offset);
- unsigned long data_size = _ELF_UP_ROUND(ps,ld[1]->p_memsz+data_off);
- unsigned long data_fsize = _ELF_UP_ROUND(ps,ld[1]->p_filesz+data_off);
-
- /* mmap all mem_blocks for *.so */
- l = text_size+data_size;
-
- dl_test.mem_size=l;
-
- m = (char*) do_map_in(0,l,ld[0]->p_flags,fd,text_offset);
-
- /* release data,bss part */
- mprotect(m+data_addr, data_size, PROT_NONE);
-
- /* mmap data,bss part */
- d = (char*) do_map_in(m+data_addr,data_fsize,ld[1]->p_flags,fd,data_offset);
-
- /* zero pad bss */
- l = data_off+ld[1]->p_filesz;
- memset(d+l,0,data_size-l);
-
- /* more bss ? */
- if (data_size>data_fsize) {
- l = data_size-data_fsize;
- mmap(d+data_fsize, l, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0);
- }
-
- dl_test.mem_base=m;
- dl_test.lnk_count=0;
- ret = &dl_test;
- }
-
- printf("_dl_open pre resolv\n");
- if (ret) {
- Elf32_Dyn* dyn_tab = (void*)m+dyn->p_vaddr;
- void (*init)();
- unsigned long* got=0;
- void* jmprel=0;
- int pltreltype=0;
- int pltrelsize=0;
-
- printf("_dl_open IN resolv\n");
- for(i=0;dyn_tab[i].d_tag;i++) {
- if (dyn_tab[i].d_tag==DT_HASH) {
- ret->hash_tab = (unsigned long*)(m+dyn_tab[i].d_un.d_ptr);
- }
- if (dyn_tab[i].d_tag==DT_SYMTAB) {
- ret->dyn_sym_tab = (Elf32_Sym*)(m+dyn_tab[i].d_un.d_ptr);
- }
- if (dyn_tab[i].d_tag==DT_STRTAB) {
- ret->dyn_str_tab = (char*)(m+dyn_tab[i].d_un.d_ptr);
- }
- if (dyn_tab[i].d_tag==DT_FINI) {
- ret->fini = (void(*)(void))(m+dyn_tab[i].d_un.d_val);
- }
- if (dyn_tab[i].d_tag==DT_INIT) {
- init = (void(*)(void))(m+dyn_tab[i].d_un.d_val);
- printf("init @ %08x\n",init);
- }
- if (dyn_tab[i].d_tag==DT_PLTGOT) {
- got=(unsigned long*)(m+dyn_tab[i].d_un.d_val);
- }
- if (dyn_tab[i].d_tag==DT_PLTREL) {
- pltreltype=dyn_tab[i].d_un.d_val;
- }
- if (dyn_tab[i].d_tag==DT_PLTRELSZ) {
- pltrelsize=dyn_tab[i].d_un.d_val;
- }
- if (dyn_tab[i].d_tag==DT_JMPREL) {
- jmprel=(m+dyn_tab[i].d_un.d_val);
- dl_test.plt_rel=jmprel;
- }
- }
- /* GOT */
- got[0]+=(unsigned long)m;
- got[1]=(unsigned long)&dl_test;
-// got[2]=(unsigned long)do_rel;
- got[2]=(unsigned long)(_dl_jump);
- /* */
-
- if (pltreltype == DT_REL) {
- Elf32_Rel *tmp = jmprel;
- for (;(char*)tmp<(((char*)jmprel)+pltrelsize);(char*)tmp=((char*)tmp)+sizeof(Elf32_Rel)) {
- *((unsigned long*)(m+tmp->r_offset))+=(unsigned long)m;
-// *((unsigned long*)(m+tmp->r_offset))+=(unsigned long)do_rel;
- printf("rel @ %08x with type %d -> %d\n",tmp->r_offset,ELF32_R_TYPE(tmp->r_info),ELF32_R_SYM(tmp->r_info));
- }
- }
-
- printf("_dl_open post resolv, pre init\n");
- init();
+ if (fd==-1) {
+ _dl_error_data=filename;
+ _dl_error=1;
+ return 0;
}
- printf("_dl_open post resolv, init\n");
-
- close(fd);
- return ret;
+ return _dl_load(filename,p,fd,flags);
}
diff --git a/mdk-stage1/dietlibc/libdl/_dl_queue.c b/mdk-stage1/dietlibc/libdl/_dl_queue.c
new file mode 100644
index 000000000..5e08020d5
--- /dev/null
+++ b/mdk-stage1/dietlibc/libdl/_dl_queue.c
@@ -0,0 +1,39 @@
+#include <dlfcn.h>
+#include "_dl_int.h"
+
+#define MAX_QUEUE 64
+
+static int _dl_queue_start=0;
+static int _dl_queue_stop=0;
+
+static struct {
+ const char*name;
+ int flags;
+} _dl_queue[MAX_QUEUE];
+
+#ifdef __DIET_LD_SO__
+static
+#endif
+int _dl_queue_lib(const char*name,int flags) {
+ if (_dl_find_lib(name)==0) {
+ register int tmp;
+ if ((tmp=_dl_queue_stop+1)>=MAX_QUEUE) tmp=0;
+ if (tmp==_dl_queue_start) return -1;
+ _dl_queue[_dl_queue_stop].name=name;
+ _dl_queue[_dl_queue_stop].flags=flags;
+ _dl_queue_stop=tmp;
+ }
+ return 0;
+}
+
+#ifdef __DIET_LD_SO__
+static
+#endif
+int _dl_open_dep() {
+ while (_dl_queue_start!=_dl_queue_stop) {
+ register int tmp=_dl_queue_start;
+ (++_dl_queue_start>=MAX_QUEUE)?_dl_queue_start=0:0;
+ if (!_dlopen(_dl_queue[tmp].name,_dl_queue[tmp].flags)) return 1;
+ }
+ return 0;
+}
diff --git a/mdk-stage1/dietlibc/libdl/_dl_rel.c b/mdk-stage1/dietlibc/libdl/_dl_rel.c
new file mode 100644
index 000000000..bc8717dc2
--- /dev/null
+++ b/mdk-stage1/dietlibc/libdl/_dl_rel.c
@@ -0,0 +1,42 @@
+#include <dlfcn.h>
+
+#include "_dl_int.h"
+
+static void exit_now(void) {
+#ifdef DEBUG
+ pf(__func__": symbol not found\n");
+#endif
+ _exit(213);
+}
+
+unsigned long do_rel(struct _dl_handle * tmp_dl, unsigned long off)
+{
+ Elf_Rel *tmp = ((void*)tmp_dl->plt_rel)+off;
+
+ int sym=ELF_R_SYM(tmp->r_info);
+
+ register unsigned long sym_val;
+
+#ifdef DEBUG
+ pf(__func__": "); ph((unsigned long)tmp_dl); pf(" "); ph(off); pf(" on ");
+ ph((long)tmp_dl->plt_rel); pf("\n");
+ pf(__func__": @ "); ph((long)tmp->r_offset); pf(" with type ");
+ ph(ELF_R_TYPE(tmp->r_info)); pf(" and sym "); ph(sym);
+ pf(" symval "); ph(tmp_dl->dyn_sym_tab[sym].st_value); pf("\n");
+#endif
+
+ /* modify GOT for REAL symbol */
+ //sym_val=((unsigned long)(tmp_dl->mem_base+tmp_dl->dyn_sym_tab[sym].st_value));
+ sym_val=(unsigned long)_dl_sym(tmp_dl,sym);
+ *((unsigned long*)(tmp_dl->mem_base+tmp->r_offset))=sym_val;
+
+#ifdef DEBUG
+ pf(__func__": sym "); ph(sym_val); pf("\n");
+#endif
+ /* JUMP (arg sysdep...) */
+ if (sym_val) return sym_val;
+ /* can't find symbol -> die now */
+ return (unsigned long)exit_now;
+}
+
+
diff --git a/mdk-stage1/dietlibc/libdl/_dl_rel.h b/mdk-stage1/dietlibc/libdl/_dl_rel.h
new file mode 100644
index 000000000..948aa5b79
--- /dev/null
+++ b/mdk-stage1/dietlibc/libdl/_dl_rel.h
@@ -0,0 +1,25 @@
+#ifndef ___DL_REL_H__
+#define ___DL_REL_H__
+
+#if defined(__arm__) || defined(__i386__) || defined(__mips__)
+/* this are REL only archs: arm, i386, mips */
+
+#define _dl_rel_t Elf_Rel
+#define _DL_REL_T DT_REL
+
+#define _DL_REL_PLT(b,r) (*(unsigned long*)((b)+(r)->r_offset)+=(unsigned long)(b))
+
+#elif defined(__alpha__) || defined(__hppa__) || defined(__ppc__) || defined(__sparc__) || defined(__s390__)
+/* this are RELA only archs: alpha, chris, hppa, ia64, m68k, ppc, sparc, sparc64, sh, s390 */
+
+#define _dl_rel_t Elf_Rela
+#define _DL_REL_T DT_RELA
+
+#define _DL_REL_PLT(b,r) (*(unsigned long*)((b)+(r)->r_offset)=(unsigned long)((b)+(r)->r_addend))
+
+#else
+/* there are no known linux supported arch with mixed relocation types ... */
+#error "_dl_rel.h: NOT SUPPORTED"
+#endif
+
+#endif
diff --git a/mdk-stage1/dietlibc/libdl/_dl_relocate.c b/mdk-stage1/dietlibc/libdl/_dl_relocate.c
new file mode 100644
index 000000000..e91e48ccf
--- /dev/null
+++ b/mdk-stage1/dietlibc/libdl/_dl_relocate.c
@@ -0,0 +1,96 @@
+#include "_dl_int.h"
+
+#include "_dl_rel.h"
+
+#if 0
+/*--- are other relocation types vital to shared objects ? ---*/
+
+ R_386_NONE 0 /* No reloc */
+ R_386_32 1 /* Direct 32 bit */
+ R_386_COPY 5 /* Copy symbol at runtime ?!? */
+ R_386_GLOB_DAT 6 /* Create GOT entry */
+ R_386_JMP_SLOT 7 /* Create PLT entry */
+ R_386_RELATIVE 8 /* Adjust by program base */
+
+ R_ARM_NONE 0 /* No reloc */
+ R_ARM_ABS32 2 /* Direct 32 bit */
+ R_ARM_COPY 20 /* Copy symbol at runtime */
+ R_ARM_GLOB_DAT 21 /* Create GOT entry */
+ R_ARM_JUMP_SLOT 22 /* Create PLT entry */
+ R_ARM_RELATIVE 23 /* Adjust by program base */
+
+#endif
+
+static int _dl_apply_relocate(struct _dl_handle*dh,_dl_rel_t*rel) {
+ int typ,ret=0;
+ Elf_Addr*loc;
+
+ loc=(Elf_Addr *)(dh->mem_base+rel->r_offset);
+
+#ifdef DEBUG
+#if 0
+ pf(__FUNCTION__); pf(": "); ph(ELF_R_TYPE(rel->r_info)); pf(" @ "); ph((unsigned long)loc);
+ pf(" preval "); ph(*(unsigned long*)loc); pf("\n");
+#endif
+#endif
+
+ typ=ELF_R_TYPE(rel->r_info);
+
+#ifdef __i386__
+ if (typ==R_386_32) { /* 1 */
+ *loc=(unsigned long)(dh->mem_base+dh->dyn_sym_tab[ELF_R_SYM(rel->r_info)].st_value);
+ } else if (typ==R_386_COPY) { /* 5 */
+ int len=dh->dyn_sym_tab[ELF_R_SYM(rel->r_info)].st_size;
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": R_386_COPY !\n");
+#endif
+ memcpy(loc,(void*)(unsigned long)_dl_sym(dh,ELF_R_SYM(rel->r_info)),len);
+ } else if (typ==R_386_GLOB_DAT) { /* 6 */
+ *loc=(unsigned long)_dl_sym(dh,ELF_R_SYM(rel->r_info));
+ } else if (typ==R_386_JMP_SLOT) { /* 7 */
+ *loc+=(unsigned long)dh->mem_base;
+ } else if (typ==R_386_RELATIVE) { /* 8 */
+ *loc+=(unsigned long)dh->mem_base;
+ } else if (typ==R_386_NONE) { /* 0 */
+ } else
+ ret=1;
+#endif
+#ifdef __arm__
+ if (typ==R_ARM_ABS32) { /* 2 */
+ *loc=(unsigned long)(dh->mem_base+dh->dyn_sym_tab[ELF_R_SYM(rel->r_info)].st_value);
+ } else if (typ==R_ARM_COPY) { /* 20 */
+ int len=dh->dyn_sym_tab[ELF_R_SYM(rel->r_info)].st_size;
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": R_ARM_COPY !\n");
+#endif
+ memcpy(loc,(void*)(unsigned long)_dl_sym(dh,ELF_R_SYM(rel->r_info)),len);
+ } else if (typ==R_ARM_GLOB_DAT) { /* 21 */
+ *loc=(unsigned long)_dl_sym(dh,ELF_R_SYM(rel->r_info));
+ } else if (typ==R_ARM_JUMP_SLOT) { /* 22 */
+ *loc+=(unsigned long)dh->mem_base;
+ } else if (typ==R_ARM_RELATIVE) { /* 23 */
+ *loc+=(unsigned long)dh->mem_base;
+ } else if (typ==R_ARM_NONE) { /* 0 */
+ } else
+ ret=1;
+#endif
+
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": @ "); ph((unsigned long)loc); pf(" val "); ph(*(unsigned long*)loc); pf("\n");
+#endif
+ return ret;
+}
+
+#ifdef __DIET_LD_SO__
+static
+#endif
+int _dl_relocate(struct _dl_handle*dh,_dl_rel_t *rel,int num) {
+ int i;
+ for (i=0;i<num;i++) {
+ if (_dl_apply_relocate(dh,rel+i)) {
+ _dl_error=4;
+ return 1;
+ }
+ }
+ return 0;
+}
diff --git a/mdk-stage1/dietlibc/libdl/_dl_search.c b/mdk-stage1/dietlibc/libdl/_dl_search.c
index 5e3217d46..ccf9c51c5 100644
--- a/mdk-stage1/dietlibc/libdl/_dl_search.c
+++ b/mdk-stage1/dietlibc/libdl/_dl_search.c
@@ -1,68 +1,95 @@
-#include <unistd.h>
#include <stdlib.h>
-#include <string.h>
#include <dlfcn.h>
#include <fcntl.h>
-#include <stdio.h>
+
+#include "_dl_int.h"
#define WANT_LD_SO_CONF_SEARCH
static const char *_dl_search_rpath=0;
+
+#ifndef __DIET_LD_SO__
+#include <unistd.h>
+#include <string.h>
void _dl_set_rpath(const char *path) { _dl_search_rpath=path; }
+const char* _dl_get_rpath() { return _dl_search_rpath; }
+#endif
/* search a colon (semicolon) seperated path for the libraray "filename" */
-static int _dl_search_path(char *buf, int len, const char*path, const int pathlen, const char *filename)
-{
- int fd,l=len,i=1;
- const char *c,*pe=path+pathlen;
+static int _dl_search_path(char*buf,int len,const char*path,const int pathlen,const char*filename) {
+ int fd,i=1,fl=strlen(filename),ml=len-fl;
+ const char*c,*pe=path+pathlen;
if (path) {
- for (c=path; c<pe; c+=i) {
+ for (c=path;c<pe;c+=i) {
+ int l=len-1;
if ((*c==':')||(*c==';')) ++c;
i=strcspn(c,":;");
if (i) {
- strncpy(buf, c, i); buf[i]=0;
- l-=i;
- strncat(buf, "/", l);
+ if (i>ml) continue; /* if len(path-entry)+len(filename)+2 is greater than the buffer ? SKIP */
+ memcpy(buf,c,i);
+ buf[i]='/';
+ l-=++i;
}
- else
- buf[0]=0;
- strncat(buf, filename, --l);
-// printf("_dl_search: %s\n",buf);
+ memcpy(buf+i,filename,fl);
+ buf[i+fl]=0;
+#ifdef DEBUG
+// pf(__func__": "); pf(buf); pf("\n");
+#endif
+#ifdef __DIET_LD_SO__
+ if ((fd=_dl_sys_open(buf,O_RDONLY,0))>-1) return fd;
+#else
if ((fd=open(buf,O_RDONLY))!=-1) return fd;
+#endif
}
}
return -1;
}
/* parse the SMALL file "conf" for lib directories (aem... hang me if you can :) ) */
-static int _dl_search_conf(char *buf, int len, const char *conf, const char *filename)
-{
+static int _dl_search_conf(char*buf,int len,const char*conf,const char*filename) {
char ld_so_conf[1024];
- int i,l,fd=open(conf,O_RDONLY);
- if (fd!=-1) {
+ int i,l,fd;
+#ifdef __DIET_LD_SO__
+ if ((fd=_dl_sys_open(conf,O_RDONLY,0))>-1) {
+ l=_dl_sys_read(fd,ld_so_conf,sizeof(ld_so_conf)-1);
+#else
+ if ((fd=open(conf,O_RDONLY))!=-1) {
l=read(fd,ld_so_conf,sizeof(ld_so_conf)-1);
+#endif
ld_so_conf[sizeof(ld_so_conf)-1]=0;
+#ifdef __DIET_LD_SO__
+ _dl_sys_close(fd);
+#else
close(fd);
- if (ld_so_conf[l-1]=='\n') ld_so_conf[--l]=0;
- for (i=0;i<l;i++) if (ld_so_conf[i]=='\n') ld_so_conf[i]=':';
- if ((fd=_dl_search_path(buf,len,ld_so_conf,l,filename))!=-1) return fd;
+#endif
+ if (l>0) {
+ if (ld_so_conf[l-1]=='\n') ld_so_conf[--l]=0;
+ for (i=0;i<l;i++) if (ld_so_conf[i]=='\n') ld_so_conf[i]=':';
+ if ((fd=_dl_search_path(buf,len,ld_so_conf,l,filename))!=-1) return fd;
+ }
}
return -1;
}
-int _dl_search(char *buf, int len, const char *filename)
-{
+#ifdef __DIET_LD_SO__
+static
+#endif
+int _dl_search(char*buf,int len,const char*filename) {
int fd;
- /* 1. search the LD_RUN_PATH (from the executable */
+ /* 1. search the LD_RUN_PATH (from the executable) */
if (_dl_search_rpath) {
if ((fd=_dl_search_path(buf,len,_dl_search_rpath,strlen(_dl_search_rpath),filename))!=-1) return fd;
}
/* 2. IF we have a "secure" enviroment THEN search LD_LIBRARY_PATH */
- if (getuid()==geteuid()) {
+#ifdef __DIET_LD_SO__
+ if ((at_uid==at_euid)&&(at_gid==at_egid)) {
+#else
+ if ((getuid()==geteuid())&&(getgid()==getegid())) {
+#endif
char *p=getenv("LD_LIBRARY_PATH");
if (p)
if ((fd=_dl_search_path(buf,len,p,strlen(p),filename))!=-1) return fd;
@@ -78,7 +105,7 @@ int _dl_search(char *buf, int len, const char *filename)
/* default path search */
{
- const char* def_path="/usr/lib:/lib";
+ const char def_path[]="/usr/lib:/lib";
return _dl_search_path(buf,len,def_path,strlen(def_path),filename);
}
}
diff --git a/mdk-stage1/dietlibc/libdl/dlclose.c b/mdk-stage1/dietlibc/libdl/dlclose.c
index 384550c47..6fafedcf5 100644
--- a/mdk-stage1/dietlibc/libdl/dlclose.c
+++ b/mdk-stage1/dietlibc/libdl/dlclose.c
@@ -1,14 +1,38 @@
+#include <sys/mman.h>
+
#include "_dl_int.h"
-int dlclose (void *handle)
-{
- if (handle) {
- struct _dl_handle *h = handle;
- if (h->lnk_count) {
- --h->lnk_count;
- return -1;
+static void dec_referenced_libs(struct _dl_handle*dh) {
+ Elf_Dyn* dyn_tab=dh->dynamic;
+ int i;
+ for(i=0;dyn_tab[i].d_tag;i++) {
+ if (dyn_tab[i].d_tag==DT_NEEDED) {
+ char *lib_name=dh->dyn_str_tab+dyn_tab[i].d_un.d_val;
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": lib: "); pf(lib_name); pf("\n");
+#endif
+ dlclose(_dl_find_lib(lib_name));
}
- if (munmap(h->mem_base,h->mem_size)!=0) return -1;
+ }
+}
+
+int dlclose(void*handle) {
+ _dl_error_location="dlclose";
+ if (handle) {
+ struct _dl_handle*dh=handle;
+ if (--(dh->lnk_count)) return 0; /* not yet unreferenced */
+
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": "); pf(dh->name); pf("\n");
+#endif
+ if (dh->fini) dh->fini();
+ dec_referenced_libs(dh);
+#ifdef __DIET_LD_SO__
+ if (_dl_sys_munmap(dh->mem_base,dh->mem_size)<0) return -1;
+#else
+ if (munmap(dh->mem_base,dh->mem_size)==-1) return -1;
+#endif
+ _dl_free_handle(handle);
}
return 0;
}
diff --git a/mdk-stage1/dietlibc/libdl/dlerror.c b/mdk-stage1/dietlibc/libdl/dlerror.c
index 1e31bae54..3fea0b75c 100644
--- a/mdk-stage1/dietlibc/libdl/dlerror.c
+++ b/mdk-stage1/dietlibc/libdl/dlerror.c
@@ -1,4 +1,55 @@
-const char *dlerror(void)
-{
- return "HAE ?!?";
+
+#include "_dl_int.h"
+
+#ifdef __DIET_LD_SO__
+static unsigned int _dl_error;
+static const char*_dl_error_location;
+static const char*_dl_error_data;
+#else
+#include <string.h>
+unsigned int _dl_error;
+const char*_dl_error_location;
+const char*_dl_error_data;
+#endif
+
+static struct _dl_err_msg {
+ char*msg;
+ int len;
+} _dl_error_msg[]={
+#define MSG(n) { (n), sizeof((n))-1 }
+ MSG("can't open: "), /* 1 */
+ MSG("can't stat: "), /* 2 */
+ MSG("shared object is not position independent: "), /* 3 */
+ MSG("can't resolve all symbols in: "), /* 4 */
+ MSG("can't find symbol: "), /* 5 */
+ MSG("invalid relocation type in: "), /* 6 */
+ MSG("internal error: layout not yet supported: "), /* 7 */
+};
+
+const char *dlerror(void) {
+ static char buf[1024],*p=buf;
+ register int l,len=sizeof(buf)-1;
+ if (_dl_error==0) return 0;
+
+ buf[0]=0;
+ buf[len]=0;
+ --_dl_error;
+
+ if (_dl_error>=(sizeof(_dl_error_msg)/sizeof(struct _dl_err_msg)))
+ return "HAE ?!?";
+
+ if (_dl_error_location) {
+ l=strlen(_dl_error_location);
+ strncpy(p,_dl_error_location,len); len-=l; p+=l;
+ strncpy(p,": ",len); len-=2; p+=2;
+ }
+ l=_dl_error_msg[_dl_error].len;
+ strncpy(p,_dl_error_msg[_dl_error].msg,len); len-=l; p+=l;
+ strncpy(p,_dl_error_data,len);
+
+ _dl_error_location=0;
+ _dl_error_data="";
+ _dl_error=0;
+
+ return buf;
}
diff --git a/mdk-stage1/dietlibc/libdl/dlopen.c b/mdk-stage1/dietlibc/libdl/dlopen.c
index 1693d889f..79fa7903c 100644
--- a/mdk-stage1/dietlibc/libdl/dlopen.c
+++ b/mdk-stage1/dietlibc/libdl/dlopen.c
@@ -2,20 +2,25 @@
#include <dlfcn.h>
#include <limits.h>
-int _dl_search(char*buf, int bufsize, const char*filename);
-void *_dl_open(const char*pathname, int fd, int flag);
+#include "_dl_int.h"
-void *dlopen (const char *filename, int flag)
-{
- int fd;
- char buf[PATH_MAX];
- const char *p;
- if (*filename=='/')
- fd=open(p=filename,O_RDONLY);
- else {
- p=buf;
- fd=_dl_search(buf,sizeof(buf),filename);
+#ifdef __DIET_LD_SO__
+static
+#endif
+void*_dlopen(const char *filename, int flags) {
+ struct _dl_handle* ret;
+ if (filename) {
+ if ((ret=_dl_find_lib(filename))) {
+ ++(ret->lnk_count); /* add a reference */
+ return ret;
+ }
+ return _dl_open(filename,flags);
}
+ /* return 1 as an indicator for dlsym to search ALL global objects */
+ return RTLD_DEFAULT;
+}
- return _dl_open(p,fd,flag);
+void*dlopen(const char *filename, int flags) {
+ _dl_error_location="dlopen";
+ return _dlopen(filename,flags|RTLD_USER|RTLD_NOSONAME);
}
diff --git a/mdk-stage1/dietlibc/libdl/dlsym.c b/mdk-stage1/dietlibc/libdl/dlsym.c
index 2af940837..c58bb4d11 100644
--- a/mdk-stage1/dietlibc/libdl/dlsym.c
+++ b/mdk-stage1/dietlibc/libdl/dlsym.c
@@ -1,7 +1,92 @@
#include "_dl_int.h"
-void *dlsym(void *handle, char *symbol)
-{
- printf("dlsym(%08x,%s) -> %08x\n",handle,symbol,elf_hash(symbol)%17);
- return 0;
+#include "elf_hash.h"
+
+#ifdef __DIET_LD_SO__
+static
+#endif
+void *_dlsym(void*handle,char*symbol) {
+ unsigned long*sym=0;
+ if (handle) {
+ struct _dl_handle*dh=(struct _dl_handle*)handle;
+ unsigned long hash =elf_hash(symbol);
+ unsigned long bhash=hash%HASH_BUCKET_LEN(dh->hash_tab);
+ unsigned long*chain=HASH_CHAIN(dh->hash_tab);
+ unsigned long ind;
+ char *name=dh->dyn_str_tab;
+
+#ifdef DEBUG
+// pf(__FUNCTION__); pf(": bucket("); ph(bhash); pf(",\""); pf(symbol); pf("\")\n");
+#endif
+
+ ind=HASH_BUCKET(dh->hash_tab)[bhash];
+#ifdef DEBUG
+// pf(__FUNCTION__); pf(": chain ("); ph(ind); pf(",\""); pf(symbol); pf("\")\n");
+#endif
+
+ while(ind) {
+ int ptr=dh->dyn_sym_tab[ind].st_name;
+#ifdef DEBUG
+// pf(__FUNCTION__); pf(": symbol(\""); pf(name+ptr); pf("\",\"); pf(symbol); pf("\")\n");
+#endif
+ if (strcmp(name+ptr,symbol)==0) {
+ if (ELF_ST_TYPE(dh->dyn_sym_tab[ind].st_shndx)!=0) {
+ sym=(long*)(dh->mem_base+dh->dyn_sym_tab[ind].st_value);
+ break; /* ok found ... */
+ }
+ }
+ ind=chain[ind];
+ }
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": symbol \""); pf(symbol); pf("\" @ "); ph((long)sym); pf("\n");
+#endif
+ }
+ return sym;
+}
+
+#ifdef __DIET_LD_SO__
+static
+#endif
+void*_dl_sym_search_str(struct _dl_handle*dh,char*name) {
+ void *sym=0;
+ struct _dl_handle*tmp;
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": search for: "); pf(name); pf("\n");
+#endif
+ for (tmp=_dl_root_handle;tmp && (!sym);tmp=tmp->next) {
+// if (!(tmp->flags&RTLD_GLOBAL)) continue;
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": searching in "); pf(tmp->name); pf("\n");
+#endif
+ sym=_dlsym((void*)tmp,name);
+#ifdef DEBUG
+ if (sym) { pf(__FUNCTION__); pf(": found: "); pf(name); pf(" @ "); ph((long)sym); pf("\n"); }
+#endif
+ }
+ return sym;
+}
+
+#ifdef __DIET_LD_SO__
+static
+#endif
+void*_dl_sym(struct _dl_handle*dh,int symbol) {
+ char *name=dh->dyn_str_tab+dh->dyn_sym_tab[symbol].st_name;
+ void*sym=_dl_sym_search_str(dh,name);
+#ifdef DEBUG
+ pf(__FUNCTION__); pf(": "); ph(symbol); pf(" -> "); ph((long)sym); pf("\n");
+#endif
+ return sym;
+}
+
+void*dlsym(void*handle,char*symbol) {
+ void*h;
+ if (handle==RTLD_DEFAULT || !handle /* RTLD_DEFAULT is NULL on glibc */ )
+ h=_dl_sym_search_str(0,symbol);
+ else h=_dlsym(handle,symbol);
+ if (h==0) {
+ _dl_error_location="dlsym";
+ _dl_error_data=symbol;
+ _dl_error=5;
+ }
+ return h;
}
diff --git a/mdk-stage1/dietlibc/libdl/elf_hash.c b/mdk-stage1/dietlibc/libdl/elf_hash.c
deleted file mode 100644
index 463dba0dd..000000000
--- a/mdk-stage1/dietlibc/libdl/elf_hash.c
+++ /dev/null
@@ -1,12 +0,0 @@
-unsigned long elf_hash(const unsigned char *name)
-{
- unsigned long h=0, g;
-
- while (*name)
- {
- h = (h<<4) + *(name++);
- if (g = h&0xf0000000) h ^= g>>24;
- h &= ~g;
- }
- return h;
-}
diff --git a/mdk-stage1/dietlibc/libdl/elf_hash.h b/mdk-stage1/dietlibc/libdl/elf_hash.h
new file mode 100644
index 000000000..be55982ea
--- /dev/null
+++ b/mdk-stage1/dietlibc/libdl/elf_hash.h
@@ -0,0 +1,10 @@
+static unsigned long elf_hash(const unsigned char *name) {
+ unsigned long h=0, g;
+
+ while (*name) {
+ h = (h<<4) + *(name++);
+ if ((g = h&0xf0000000)) h ^= g>>24;
+ h &= ~g;
+ }
+ return h;
+}
diff --git a/mdk-stage1/dietlibc/libdl/test/test.c b/mdk-stage1/dietlibc/libdl/test/test.c
new file mode 100644
index 000000000..d467134ba
--- /dev/null
+++ b/mdk-stage1/dietlibc/libdl/test/test.c
@@ -0,0 +1,20 @@
+#include <dlfcn.h>
+
+int main(int argc, char **argv)
+{
+ void *Hlib;
+
+// if (Hlib=dlopen("libtest.so", RTLD_LAZY)) {
+ if (Hlib=dlopen("libtest.so", RTLD_NOW)) {
+ void (*t)(void) = dlsym(Hlib,"test");
+ if (t) {
+ printf("test @ %08lx\n",(long)t);
+ t();
+ }
+ dlclose(Hlib);
+ }
+ else {
+ printf("%s\n",dlerror());
+ }
+ return 0;
+}
diff --git a/mdk-stage1/dietlibc/libdl/test/test_so.c b/mdk-stage1/dietlibc/libdl/test/test_so.c
new file mode 100644
index 000000000..09d243c56
--- /dev/null
+++ b/mdk-stage1/dietlibc/libdl/test/test_so.c
@@ -0,0 +1,11 @@
+
+int* test();
+
+int err
+=(int)test
+;
+
+int* test() {
+ write(1,"helo\n",5);
+ return &err;
+}