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/Makefile24
-rw-r--r--mdk-stage1/dietlibc/libdl/README6
-rw-r--r--mdk-stage1/dietlibc/libdl/_dl_int.h31
-rw-r--r--mdk-stage1/dietlibc/libdl/_dl_jump.S8
-rw-r--r--mdk-stage1/dietlibc/libdl/_dl_open.c207
-rw-r--r--mdk-stage1/dietlibc/libdl/_dl_search.c84
-rw-r--r--mdk-stage1/dietlibc/libdl/dlclose.c14
-rw-r--r--mdk-stage1/dietlibc/libdl/dlerror.c4
-rw-r--r--mdk-stage1/dietlibc/libdl/dlopen.c21
-rw-r--r--mdk-stage1/dietlibc/libdl/dlsym.c7
-rw-r--r--mdk-stage1/dietlibc/libdl/elf_hash.c12
11 files changed, 418 insertions, 0 deletions
diff --git a/mdk-stage1/dietlibc/libdl/Makefile b/mdk-stage1/dietlibc/libdl/Makefile
new file mode 100644
index 000000000..c0463f887
--- /dev/null
+++ b/mdk-stage1/dietlibc/libdl/Makefile
@@ -0,0 +1,24 @@
+# local "test" make file
+
+SRC = $(wildcard *.c) test/test.c
+OBJ = _dl_jump.o $(SRC:.c=.o)
+
+#CFLAGS = -Wall -O2
+CFLAGS = -g
+
+%.o : %.S
+ $(HOME)/bin/diet gcc $(CFLAGS) -c -o $@ $^
+
+%.o : %.c
+ $(HOME)/bin/diet gcc $(CFLAGS) -c -o $@ $^
+
+all: test.out
+
+test.g: test.c
+ gcc -o $@ $^ -ldl
+
+test.out: $(OBJ)
+ $(HOME)/bin/diet gcc -o $@ $^
+
+clean:
+ $(RM) *.o *.a *.out *~ # *.so
diff --git a/mdk-stage1/dietlibc/libdl/README b/mdk-stage1/dietlibc/libdl/README
new file mode 100644
index 000000000..5d77bde34
--- /dev/null
+++ b/mdk-stage1/dietlibc/libdl/README
@@ -0,0 +1,6 @@
+this is the experimental libdl test-pre-pre-alpha code
+
+written by Olaf Dreesen
+
+Shouldn't work yet had some problems with the elf specs...
+and more inconsistencies...
diff --git a/mdk-stage1/dietlibc/libdl/_dl_int.h b/mdk-stage1/dietlibc/libdl/_dl_int.h
new file mode 100644
index 000000000..659e6ee0f
--- /dev/null
+++ b/mdk-stage1/dietlibc/libdl/_dl_int.h
@@ -0,0 +1,31 @@
+#ifndef ___DL_INT_H__
+#define ___DL_INT_H__
+
+#include <elf.h>
+
+struct _dl_handle {
+ /* basic */
+ void * mem_base; /* base address of maped *.so */
+ unsigned long mem_size; /* len of mem block */
+ unsigned int lnk_count; /* reference count */
+
+ /* symbol resolve helper */
+ unsigned long*hash_tab; /* hash table */
+ Elf32_Sym * dyn_sym_tab; /* dynamic symbol table */
+ char * dyn_str_tab; /* dyn_name table */
+
+ Elf32_Rel * plt_rel; /* PLT relocation table */
+
+ /* FINI */
+ void (*fini)(void);
+};
+
+#define HASH_BUCKET_LEN(p) ((p))
+#define HASH_BUCKET(p) ((p)+2)
+
+#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);
+
+#endif
diff --git a/mdk-stage1/dietlibc/libdl/_dl_jump.S b/mdk-stage1/dietlibc/libdl/_dl_jump.S
new file mode 100644
index 000000000..134f31ea5
--- /dev/null
+++ b/mdk-stage1/dietlibc/libdl/_dl_jump.S
@@ -0,0 +1,8 @@
+.text
+.global _dl_jump
+_dl_jump:
+ call do_rel
+ pop %edx
+ pop %edx
+ jmp *%eax
+
diff --git a/mdk-stage1/dietlibc/libdl/_dl_open.c b/mdk-stage1/dietlibc/libdl/_dl_open.c
new file mode 100644
index 000000000..1f907db21
--- /dev/null
+++ b/mdk-stage1/dietlibc/libdl/_dl_open.c
@@ -0,0 +1,207 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <dlfcn.h>
+#include <linux/elf.h>
+
+#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;
+ }
+ }
+
+ 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();
+ }
+ printf("_dl_open post resolv, init\n");
+
+ close(fd);
+ return ret;
+}
diff --git a/mdk-stage1/dietlibc/libdl/_dl_search.c b/mdk-stage1/dietlibc/libdl/_dl_search.c
new file mode 100644
index 000000000..5e3217d46
--- /dev/null
+++ b/mdk-stage1/dietlibc/libdl/_dl_search.c
@@ -0,0 +1,84 @@
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dlfcn.h>
+
+#include <fcntl.h>
+#include <stdio.h>
+
+#define WANT_LD_SO_CONF_SEARCH
+
+static const char *_dl_search_rpath=0;
+void _dl_set_rpath(const char *path) { _dl_search_rpath=path; }
+
+/* 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;
+
+ if (path) {
+ for (c=path; c<pe; c+=i) {
+ if ((*c==':')||(*c==';')) ++c;
+ i=strcspn(c,":;");
+ if (i) {
+ strncpy(buf, c, i); buf[i]=0;
+ l-=i;
+ strncat(buf, "/", l);
+ }
+ else
+ buf[0]=0;
+ strncat(buf, filename, --l);
+// printf("_dl_search: %s\n",buf);
+ if ((fd=open(buf,O_RDONLY))!=-1) return fd;
+ }
+ }
+ 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)
+{
+ char ld_so_conf[1024];
+ int i,l,fd=open(conf,O_RDONLY);
+ if (fd!=-1) {
+ l=read(fd,ld_so_conf,sizeof(ld_so_conf)-1);
+ ld_so_conf[sizeof(ld_so_conf)-1]=0;
+ 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;
+ }
+ return -1;
+}
+
+int _dl_search(char *buf, int len, const char *filename)
+{
+ int fd;
+
+ /* 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()) {
+ char *p=getenv("LD_LIBRARY_PATH");
+ if (p)
+ if ((fd=_dl_search_path(buf,len,p,strlen(p),filename))!=-1) return fd;
+ }
+
+ /* 3. search all pathes in the the /etc/diet.ld.conf, a dietlibc extension :) */
+ if ((fd=_dl_search_conf(buf,len,"/etc/diet.ld.conf",filename))!=-1) return fd;
+
+#ifdef WANT_LD_SO_CONF_SEARCH
+ /* 4. search all pathes in the the /etc/ld.so.conf / can't handle this ...=lib?? crap */
+ if ((fd=_dl_search_conf(buf,len,"/etc/ld.so.conf",filename))!=-1) return fd;
+#endif
+
+ /* default path search */
+ {
+ 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
new file mode 100644
index 000000000..384550c47
--- /dev/null
+++ b/mdk-stage1/dietlibc/libdl/dlclose.c
@@ -0,0 +1,14 @@
+#include "_dl_int.h"
+
+int dlclose (void *handle)
+{
+ if (handle) {
+ struct _dl_handle *h = handle;
+ if (h->lnk_count) {
+ --h->lnk_count;
+ return -1;
+ }
+ if (munmap(h->mem_base,h->mem_size)!=0) return -1;
+ }
+ return 0;
+}
diff --git a/mdk-stage1/dietlibc/libdl/dlerror.c b/mdk-stage1/dietlibc/libdl/dlerror.c
new file mode 100644
index 000000000..1e31bae54
--- /dev/null
+++ b/mdk-stage1/dietlibc/libdl/dlerror.c
@@ -0,0 +1,4 @@
+const char *dlerror(void)
+{
+ return "HAE ?!?";
+}
diff --git a/mdk-stage1/dietlibc/libdl/dlopen.c b/mdk-stage1/dietlibc/libdl/dlopen.c
new file mode 100644
index 000000000..1693d889f
--- /dev/null
+++ b/mdk-stage1/dietlibc/libdl/dlopen.c
@@ -0,0 +1,21 @@
+#include <fcntl.h>
+#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);
+
+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);
+ }
+
+ return _dl_open(p,fd,flag);
+}
diff --git a/mdk-stage1/dietlibc/libdl/dlsym.c b/mdk-stage1/dietlibc/libdl/dlsym.c
new file mode 100644
index 000000000..2af940837
--- /dev/null
+++ b/mdk-stage1/dietlibc/libdl/dlsym.c
@@ -0,0 +1,7 @@
+#include "_dl_int.h"
+
+void *dlsym(void *handle, char *symbol)
+{
+ printf("dlsym(%08x,%s) -> %08x\n",handle,symbol,elf_hash(symbol)%17);
+ return 0;
+}
diff --git a/mdk-stage1/dietlibc/libdl/elf_hash.c b/mdk-stage1/dietlibc/libdl/elf_hash.c
new file mode 100644
index 000000000..463dba0dd
--- /dev/null
+++ b/mdk-stage1/dietlibc/libdl/elf_hash.c
@@ -0,0 +1,12 @@
+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;
+}