From 9097327dc1c667fc51b8e05cc7c0626fac96665d Mon Sep 17 00:00:00 2001 From: Guillaume Cottenceau Date: Mon, 14 May 2001 14:17:54 +0000 Subject: Initial revision --- mdk-stage1/dietlibc/libdl/Makefile | 24 ++++ mdk-stage1/dietlibc/libdl/README | 6 + mdk-stage1/dietlibc/libdl/_dl_int.h | 31 +++++ mdk-stage1/dietlibc/libdl/_dl_jump.S | 8 ++ mdk-stage1/dietlibc/libdl/_dl_open.c | 207 +++++++++++++++++++++++++++++++++ mdk-stage1/dietlibc/libdl/_dl_search.c | 84 +++++++++++++ mdk-stage1/dietlibc/libdl/dlclose.c | 14 +++ mdk-stage1/dietlibc/libdl/dlerror.c | 4 + mdk-stage1/dietlibc/libdl/dlopen.c | 21 ++++ mdk-stage1/dietlibc/libdl/dlsym.c | 7 ++ mdk-stage1/dietlibc/libdl/elf_hash.c | 12 ++ 11 files changed, 418 insertions(+) create mode 100644 mdk-stage1/dietlibc/libdl/Makefile create mode 100644 mdk-stage1/dietlibc/libdl/README create mode 100644 mdk-stage1/dietlibc/libdl/_dl_int.h create mode 100644 mdk-stage1/dietlibc/libdl/_dl_jump.S create mode 100644 mdk-stage1/dietlibc/libdl/_dl_open.c create mode 100644 mdk-stage1/dietlibc/libdl/_dl_search.c create mode 100644 mdk-stage1/dietlibc/libdl/dlclose.c create mode 100644 mdk-stage1/dietlibc/libdl/dlerror.c create mode 100644 mdk-stage1/dietlibc/libdl/dlopen.c create mode 100644 mdk-stage1/dietlibc/libdl/dlsym.c create mode 100644 mdk-stage1/dietlibc/libdl/elf_hash.c (limited to 'mdk-stage1/dietlibc/libdl') 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 + +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 +#include +#include +#include +#include + +#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; ie_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 +#include +#include +#include + +#include +#include + +#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; clnk_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 +#include +#include + +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; +} -- cgit v1.2.1