diff options
Diffstat (limited to 'mdk-stage1/dietlibc/libdl')
-rw-r--r-- | mdk-stage1/dietlibc/libdl/Makefile | 32 | ||||
-rw-r--r-- | mdk-stage1/dietlibc/libdl/README | 82 | ||||
-rw-r--r-- | mdk-stage1/dietlibc/libdl/_dl_alloc.c | 81 | ||||
-rw-r--r-- | mdk-stage1/dietlibc/libdl/_dl_int.h | 138 | ||||
-rw-r--r-- | mdk-stage1/dietlibc/libdl/_dl_jump.S | 53 | ||||
-rw-r--r-- | mdk-stage1/dietlibc/libdl/_dl_load.c | 401 | ||||
-rw-r--r-- | mdk-stage1/dietlibc/libdl/_dl_main.c | 1059 | ||||
-rw-r--r-- | mdk-stage1/dietlibc/libdl/_dl_open.c | 228 | ||||
-rw-r--r-- | mdk-stage1/dietlibc/libdl/_dl_queue.c | 39 | ||||
-rw-r--r-- | mdk-stage1/dietlibc/libdl/_dl_rel.c | 42 | ||||
-rw-r--r-- | mdk-stage1/dietlibc/libdl/_dl_rel.h | 25 | ||||
-rw-r--r-- | mdk-stage1/dietlibc/libdl/_dl_relocate.c | 96 | ||||
-rw-r--r-- | mdk-stage1/dietlibc/libdl/_dl_search.c | 81 | ||||
-rw-r--r-- | mdk-stage1/dietlibc/libdl/dlclose.c | 40 | ||||
-rw-r--r-- | mdk-stage1/dietlibc/libdl/dlerror.c | 57 | ||||
-rw-r--r-- | mdk-stage1/dietlibc/libdl/dlopen.c | 31 | ||||
-rw-r--r-- | mdk-stage1/dietlibc/libdl/dlsym.c | 93 | ||||
-rw-r--r-- | mdk-stage1/dietlibc/libdl/elf_hash.c | 12 | ||||
-rw-r--r-- | mdk-stage1/dietlibc/libdl/elf_hash.h | 10 |
19 files changed, 2309 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; +} |