From bca6a155c79147f706242ed7c590a3538e407a40 Mon Sep 17 00:00:00 2001 From: Eric Andersen Date: Tue, 19 Aug 2003 06:05:34 +0000 Subject: Phase one of my evil plan to clean up ld.so... --- ldso/Makefile | 9 +- ldso/config.h | 53 --------- ldso/include/.cvsignore | 4 + ldso/include/dl-elf.h | 91 +++++++++++++++ ldso/include/dl-hash.h | 118 +++++++++++++++++++ ldso/include/dl-string.h | 281 +++++++++++++++++++++++++++++++++++++++++++++ ldso/include/dl-syscall.h | 157 +++++++++++++++++++++++++ ldso/include/dlfcn.h | 22 ++++ ldso/include/ld_elf.h | 91 +++++++++++++++ ldso/include/ld_hash.h | 118 +++++++++++++++++++ ldso/include/ld_string.h | 281 +++++++++++++++++++++++++++++++++++++++++++++ ldso/include/ld_syscall.h | 157 +++++++++++++++++++++++++ ldso/include/ldso.h | 11 ++ ldso/ldso/.cvsignore | 2 +- ldso/ldso/Makefile | 25 ++-- ldso/ldso/dl-elf.c | 16 +-- ldso/ldso/ld_hash.h | 151 ------------------------- ldso/ldso/ld_string.h | 283 ---------------------------------------------- ldso/ldso/ld_syscall.h | 155 ------------------------- ldso/ldso/ldso.c | 98 ++++++++-------- ldso/ldso/linuxelf.h | 69 ----------- ldso/ldso/readelflib1.c | 16 +-- ldso/libdl/Makefile | 15 ++- ldso/libdl/dlfcn.h | 41 ------- ldso/libdl/dlib.c | 91 ++++----------- ldso/libdl/libdl.c | 91 ++++----------- ldso/util/Makefile | 7 +- ldso/util/ldconfig.c | 4 +- 28 files changed, 1474 insertions(+), 983 deletions(-) delete mode 100644 ldso/config.h create mode 100644 ldso/include/.cvsignore create mode 100644 ldso/include/dl-elf.h create mode 100644 ldso/include/dl-hash.h create mode 100644 ldso/include/dl-string.h create mode 100644 ldso/include/dl-syscall.h create mode 100644 ldso/include/dlfcn.h create mode 100644 ldso/include/ld_elf.h create mode 100644 ldso/include/ld_hash.h create mode 100644 ldso/include/ld_string.h create mode 100644 ldso/include/ld_syscall.h create mode 100644 ldso/include/ldso.h delete mode 100644 ldso/ldso/ld_hash.h delete mode 100644 ldso/ldso/ld_string.h delete mode 100644 ldso/ldso/ld_syscall.h delete mode 100644 ldso/ldso/linuxelf.h delete mode 100644 ldso/libdl/dlfcn.h (limited to 'ldso') diff --git a/ldso/Makefile b/ldso/Makefile index d0a133bf7..dcf83be52 100644 --- a/ldso/Makefile +++ b/ldso/Makefile @@ -26,7 +26,7 @@ include $(TOPDIR)Rules.mak ALL_SUBDIRS = ldso libdl util -all: +all: headers ifeq ($(strip $(BUILD_UCLIBC_LDSO)),y) $(MAKE) -C ldso; else @@ -43,6 +43,13 @@ endif utils: $(MAKE) -C util; +headers: + ln -fs $(TOPDIR)../include/elf.h include/ + ln -fs ../ldso/$(TARGET_ARCH)/boot1_arch.h include/ + ln -fs ../ldso/$(TARGET_ARCH)/ld_syscalls.h include/ + ln -fs ../ldso/$(TARGET_ARCH)/ld_sysdep.h include/ + clean: set -e ; for d in $(ALL_SUBDIRS) ; do $(MAKE) -C $$d $@ ; done -find . -name '*~' | xargs rm -f + rm -f include/elf.h include/boot1_arch.h include/ld_syscalls.h include/ld_sysdep.h diff --git a/ldso/config.h b/ldso/config.h deleted file mode 100644 index 499101885..000000000 --- a/ldso/config.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifdef DEBUG -# define LDSO_IMAGE "../ld-so/ld.so" -# define LDSO_CONF "../util/ld.so.conf" -# define LDSO_CACHE "../util/ld.so.cache" -# define LDSO_PRELOAD "../util/ld.so.preload" -# define LDDSTUB "../util/lddstub" -#else -# define LDSO_IMAGE UCLIBC_TARGET_PREFIX "lib/ld.so" -# define LDSO_CONF UCLIBC_TARGET_PREFIX "etc/ld.so.conf" -# define LDSO_CACHE UCLIBC_TARGET_PREFIX "etc/ld.so.cache" -# define LDSO_PRELOAD UCLIBC_TARGET_PREFIX "etc/ld.so.preload" -# define LDDSTUB UCLIBC_TARGET_PREFIX "usr/lib/lddstub" -#endif - -#define LDD_ARGV0 "__LDD_ARGV0" -#define DIR_SEP ":, \t\n" -#define MAX_DIRS 32 - -typedef void (*loadptr)(int func, ...); -typedef void (*callbackptr)(int ver, int nlibs, char **libs, - int nmods, char **mods); - -#define CALLBACK_VER 1 - -#define LIB_ANY -1 -#define LIB_DLL 0 -#define LIB_ELF 1 -#define LIB_ELF_LIBC5 2 -#define LIB_ELF_LIBC6 3 -#define LIB_ELF64 0x80 - -#define FUNC_VERS 0 -#define FUNC_LDD 1 -#define FUNC_LINK 2 -#define FUNC_LINK_AND_CALLBACK 3 - -#define LDSO_CACHE_MAGIC "ld.so-" -#define LDSO_CACHE_MAGIC_LEN (sizeof LDSO_CACHE_MAGIC -1) -#define LDSO_CACHE_VER "1.7.0" -#define LDSO_CACHE_VER_LEN (sizeof LDSO_CACHE_VER -1) - -typedef struct { - char magic [LDSO_CACHE_MAGIC_LEN]; - char version [LDSO_CACHE_VER_LEN]; - int nlibs; -} header_t; - -typedef struct { - int flags; - int sooffset; - int liboffset; -} libentry_t; - diff --git a/ldso/include/.cvsignore b/ldso/include/.cvsignore new file mode 100644 index 000000000..b48ed1fa5 --- /dev/null +++ b/ldso/include/.cvsignore @@ -0,0 +1,4 @@ +elf.h +ld_syscalls.h +ld_sysdep.h +boot1_arch.h diff --git a/ldso/include/dl-elf.h b/ldso/include/dl-elf.h new file mode 100644 index 000000000..95de118f5 --- /dev/null +++ b/ldso/include/dl-elf.h @@ -0,0 +1,91 @@ +#ifndef LINUXELF_H +#define LINUXELF_H + +#include /* before elf.h to get ELF_USES_RELOCA right */ +#include +#include + +#ifdef DEBUG +# define LDSO_CONF "../util/ld.so.conf" +# define LDSO_CACHE "../util/ld.so.cache" +# define LDSO_PRELOAD "../util/ld.so.preload" +#else +# define LDSO_CONF UCLIBC_TARGET_PREFIX "etc/ld.so.conf" +# define LDSO_CACHE UCLIBC_TARGET_PREFIX "etc/ld.so.cache" +# define LDSO_PRELOAD UCLIBC_TARGET_PREFIX "etc/ld.so.preload" +#endif + + +#define LIB_ANY -1 +#define LIB_DLL 0 +#define LIB_ELF 1 +#define LIB_ELF_LIBC5 2 +#define LIB_ELF_LIBC6 3 +#define LIB_ELF64 0x80 + +/* Forward declarations for stuff defined in ld_hash.h */ +struct dyn_elf; +struct elf_resolve; + + +/* Definitions and prototypes for cache stuff */ +#ifdef USE_CACHE +extern int _dl_map_cache(void); +extern int _dl_unmap_cache(void); + +#define LDSO_CACHE_MAGIC "ld.so-" +#define LDSO_CACHE_MAGIC_LEN (sizeof LDSO_CACHE_MAGIC -1) +#define LDSO_CACHE_VER "1.7.0" +#define LDSO_CACHE_VER_LEN (sizeof LDSO_CACHE_VER -1) + +typedef struct { + char magic [LDSO_CACHE_MAGIC_LEN]; + char version [LDSO_CACHE_VER_LEN]; + int nlibs; +} header_t; + +typedef struct { + int flags; + int sooffset; + int liboffset; +} libentry_t; + +#else +static inline void _dl_map_cache(void) { } +static inline void _dl_unmap_cache(void) { } +#endif + + +/* Function prototypes for non-static stuff in readelflib1.c */ +int _dl_copy_fixups(struct dyn_elf * tpnt); +extern int _dl_parse_copy_information(struct dyn_elf *rpnt, + unsigned long rel_addr, unsigned long rel_size, int type); +extern void _dl_parse_lazy_relocation_information(struct elf_resolve *tpnt, + unsigned long rel_addr, unsigned long rel_size, int type); +extern int _dl_parse_relocation_information(struct elf_resolve *tpnt, + unsigned long rel_addr, unsigned long rel_size, int type); +extern struct elf_resolve * _dl_load_shared_library(int secure, + struct dyn_elf **rpnt, struct elf_resolve *tpnt, char *full_libname); +extern struct elf_resolve * _dl_load_elf_shared_library(int secure, + struct dyn_elf **rpnt, char *libname); +extern int _dl_linux_resolve(void); + + +/* + * Datatype of a relocation on this platform + */ +#ifdef ELF_USES_RELOCA +# define ELF_RELOC ElfW(Rela) +#else +# define ELF_RELOC ElfW(Rel) +#endif + + +/* Convert between the Linux flags for page protections and the + ones specified in the ELF standard. */ +#define LXFLAGS(X) ( (((X) & PF_R) ? PROT_READ : 0) | \ + (((X) & PF_W) ? PROT_WRITE : 0) | \ + (((X) & PF_X) ? PROT_EXEC : 0)) + + +#endif /* LINUXELF_H */ diff --git a/ldso/include/dl-hash.h b/ldso/include/dl-hash.h new file mode 100644 index 000000000..d7ed5ab2c --- /dev/null +++ b/ldso/include/dl-hash.h @@ -0,0 +1,118 @@ +#ifndef _LD_HASH_H_ +#define _LD_HASH_H_ + +#ifndef RTLD_NEXT +#define RTLD_NEXT ((void*)-1) +#endif + +struct dyn_elf{ + unsigned long flags; + struct elf_resolve * dyn; + struct dyn_elf * next_handle; /* Used by dlopen et al. */ + struct dyn_elf * next; + struct dyn_elf * prev; +}; + +struct elf_resolve{ + /* These entries must be in this order to be compatible with the interface used + by gdb to obtain the list of symbols. */ + char * loadaddr; + char * libname; + unsigned long dynamic_addr; + struct elf_resolve * next; + struct elf_resolve * prev; + /* Nothing after this address is used by gdb. */ + enum {elf_lib, elf_executable,program_interpreter, loaded_file} libtype; + struct dyn_elf * symbol_scope; + unsigned short usage_count; + unsigned short int init_flag; + unsigned int nbucket; + unsigned long * elf_buckets; + /* + * These are only used with ELF style shared libraries + */ + unsigned long nchain; + unsigned long * chains; + unsigned long dynamic_info[24]; + + unsigned long dynamic_size; + unsigned long n_phent; + Elf32_Phdr * ppnt; + +#if defined(__mips__) + /* Needed for MIPS relocation */ + unsigned long mips_gotsym; + unsigned long mips_local_gotno; + unsigned long mips_symtabno; +#endif + +#ifdef __powerpc__ + /* this is used to store the address of relocation data words, so + * we don't have to calculate it every time, which requires a divide */ + unsigned long data_words; +#endif +}; + +#if 0 +/* + * The DT_DEBUG entry in the .dynamic section is given the address of this structure. + * gdb can pick this up to obtain the correct list of loaded modules. + */ + +struct r_debug{ + int r_version; + struct elf_resolve * link_map; + unsigned long brk_fun; + enum {RT_CONSISTENT, RT_ADD, RT_DELETE}; + unsigned long ldbase; +}; +#endif + +#define COPY_RELOCS_DONE 1 +#define RELOCS_DONE 2 +#define JMP_RELOCS_DONE 4 +#define INIT_FUNCS_CALLED 8 + +extern struct dyn_elf * _dl_symbol_tables; +extern struct elf_resolve * _dl_loaded_modules; +extern struct dyn_elf * _dl_handles; + +extern struct elf_resolve * _dl_check_hashed_files(const char * libname); +extern struct elf_resolve * _dl_add_elf_hash_table(const char * libname, + char * loadaddr, unsigned long * dynamic_info, + unsigned long dynamic_addr, unsigned long dynamic_size); + +enum caller_type{symbolrel=0,copyrel=1,resolver=2}; +extern char * _dl_find_hash(const char * name, struct dyn_elf * rpnt1, + struct elf_resolve * f_tpnt, enum caller_type); + +extern int _dl_linux_dynamic_link(void); + +extern char * _dl_library_path; +extern char * _dl_not_lazy; +extern unsigned long _dl_elf_hash(const char * name); + +static inline int _dl_symbol(char * name) +{ + if(name[0] != '_' || name[1] != 'd' || name[2] != 'l' || name[3] != '_') + return 0; + return 1; +} + + +#define LD_ERROR_NOFILE 1 +#define LD_ERROR_NOZERO 2 +#define LD_ERROR_NOTELF 3 +#define LD_ERROR_NOTMAGIC 4 +#define LD_ERROR_NOTDYN 5 +#define LD_ERROR_MMAP_FAILED 6 +#define LD_ERROR_NODYNAMIC 7 +#define LD_WRONG_RELOCS 8 +#define LD_BAD_HANDLE 9 +#define LD_NO_SYMBOL 10 + + + +#endif /* _LD_HASH_H_ */ + + diff --git a/ldso/include/dl-string.h b/ldso/include/dl-string.h new file mode 100644 index 000000000..647ab1efd --- /dev/null +++ b/ldso/include/dl-string.h @@ -0,0 +1,281 @@ +#ifndef _LINUX_STRING_H_ +#define _LINUX_STRING_H_ + +extern void *_dl_malloc(int size); +extern char *_dl_getenv(const char *symbol, char **envp); +extern void _dl_unsetenv(const char *symbol, char **envp); +extern char *_dl_strdup(const char *string); +extern void _dl_dprintf(int, const char *, ...); + + +static size_t _dl_strlen(const char * str); +static char *_dl_strcat(char *dst, const char *src); +static char * _dl_strcpy(char * dst,const char *src); +static int _dl_strcmp(const char * s1,const char * s2); +static int _dl_strncmp(const char * s1,const char * s2,size_t len); +static char * _dl_strchr(const char * str,int c); +static char *_dl_strrchr(const char *str, int c); +static char *_dl_strstr(const char *s1, const char *s2); +static void * _dl_memcpy(void * dst, const void * src, size_t len); +static int _dl_memcmp(const void * s1,const void * s2,size_t len); +static void *_dl_memset(void * str,int c,size_t len); +static char *_dl_get_last_path_component(char *path); +static char *_dl_simple_ltoa(char * local, unsigned long i); +static char *_dl_simple_ltoahex(char * local, unsigned long i); + +#ifndef NULL +#define NULL ((void *) 0) +#endif + +static inline size_t _dl_strlen(const char * str) +{ + register char *ptr = (char *) str; + + while (*ptr) + ptr++; + return (ptr - str); +} + +static inline char *_dl_strcat(char *dst, const char *src) +{ + register char *ptr = dst; + + while (*ptr) + ptr++; + + while (*src) + *ptr++ = *src++; + *ptr = '\0'; + + return dst; +} + +static inline char * _dl_strcpy(char * dst,const char *src) +{ + register char *ptr = dst; + + while (*src) + *dst++ = *src++; + *dst = '\0'; + + return ptr; +} + +static inline int _dl_strcmp(const char * s1,const char * s2) +{ + register unsigned char c1, c2; + + do { + c1 = (unsigned char) *s1++; + c2 = (unsigned char) *s2++; + if (c1 == '\0') + return c1 - c2; + } + while (c1 == c2); + + return c1 - c2; +} + +static inline int _dl_strncmp(const char * s1,const char * s2,size_t len) +{ + register unsigned char c1 = '\0'; + register unsigned char c2 = '\0'; + + while (len > 0) { + c1 = (unsigned char) *s1++; + c2 = (unsigned char) *s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + len--; + } + + return c1 - c2; +} + +static inline char * _dl_strchr(const char * str,int c) +{ + register char ch; + + do { + if ((ch = *str) == c) + return (char *) str; + str++; + } + while (ch); + + return 0; +} + +static inline char *_dl_strrchr(const char *str, int c) +{ + register char *prev = 0; + register char *ptr = (char *) str; + + while (*ptr != '\0') { + if (*ptr == c) + prev = ptr; + ptr++; + } + if (c == '\0') + return(ptr); + return(prev); +} + + +static inline char *_dl_strstr(const char *s1, const char *s2) +{ + register const char *s = s1; + register const char *p = s2; + + do { + if (!*p) { + return (char *) s1;; + } + if (*p == *s) { + ++p; + ++s; + } else { + p = s2; + if (!*s) { + return NULL; + } + s = ++s1; + } + } while (1); +} + +static inline void * _dl_memcpy(void * dst, const void * src, size_t len) +{ + register char *a = dst; + register const char *b = src; + + while (len--) + *a++ = *b++; + + return dst; +} + + +static inline int _dl_memcmp(const void * s1,const void * s2,size_t len) +{ + unsigned char *c1 = (unsigned char *)s1; + unsigned char *c2 = (unsigned char *)s2; + + while (len--) { + if (*c1 != *c2) + return *c1 - *c2; + c1++; + c2++; + } + return 0; +} + +static inline void * _dl_memset(void * str,int c,size_t len) +{ + register char *a = str; + + while (len--) + *a++ = c; + + return str; +} + +static inline char *_dl_get_last_path_component(char *path) +{ + char *s; + register char *ptr = path; + register char *prev = 0; + + while (*ptr) + ptr++; + s = ptr - 1; + + /* strip trailing slashes */ + while (s != path && *s == '/') { + *s-- = '\0'; + } + + /* find last component */ + ptr = path; + while (*ptr != '\0') { + if (*ptr == '/') + prev = ptr; + ptr++; + } + s = prev; + + if (s == NULL || s[1] == '\0') + return path; + else + return s+1; +} + +/* Early on, we can't call printf, so use this to print out + * numbers using the SEND_STDERR() macro */ +static inline char *_dl_simple_ltoa(char * local, unsigned long i) +{ + /* 21 digits plus null terminator, good for 64-bit or smaller ints */ + char *p = &local[22]; + *p-- = '\0'; + do { + *p-- = '0' + i % 10; + i /= 10; + } while (i > 0); + return p + 1; +} + +static inline char *_dl_simple_ltoahex(char * local, unsigned long i) +{ + /* 21 digits plus null terminator, good for 64-bit or smaller ints */ + char *p = &local[22]; + *p-- = '\0'; + do { + char temp = i % 0x10; + if (temp <= 0x09) + *p-- = '0' + temp; + else + *p-- = 'a' - 0x0a + temp; + i /= 0x10; + } while (i > 0); + *p-- = 'x'; + *p-- = '0'; + return p + 1; +} + + +#if defined mc68000 || defined __arm__ || defined __mips__ || defined __sh__ +/* On some arches constant strings are referenced through the GOT. */ +/* XXX Requires load_addr to be defined. */ +#define SEND_STDERR(X) \ + { const char *__s = (X); \ + if (__s < (const char *) load_addr) __s += load_addr; \ + _dl_write (2, __s, _dl_strlen (__s)); \ + } +#else +#define SEND_STDERR(X) _dl_write(2, X, _dl_strlen(X)); +#endif + +#define SEND_ADDRESS_STDERR(X, add_a_newline) { \ + char tmp[22], *tmp1; \ + _dl_memset(tmp, 0, sizeof(tmp)); \ + tmp1=_dl_simple_ltoahex( tmp, (unsigned long)(X)); \ + _dl_write(2, tmp1, _dl_strlen(tmp1)); \ + if (add_a_newline) { \ + tmp[0]='\n'; \ + _dl_write(2, tmp, 1); \ + } \ +}; + +#define SEND_NUMBER_STDERR(X, add_a_newline) { \ + char tmp[22], *tmp1; \ + _dl_memset(tmp, 0, sizeof(tmp)); \ + tmp1=_dl_simple_ltoa( tmp, (unsigned long)(X)); \ + _dl_write(2, tmp1, _dl_strlen(tmp1)); \ + if (add_a_newline) { \ + tmp[0]='\n'; \ + _dl_write(2, tmp, 1); \ + } \ +}; + + +#endif diff --git a/ldso/include/dl-syscall.h b/ldso/include/dl-syscall.h new file mode 100644 index 000000000..72574b9a9 --- /dev/null +++ b/ldso/include/dl-syscall.h @@ -0,0 +1,157 @@ +#ifndef _LD_SYSCALL_H_ +#define _LD_SYSCALL_H_ + +/* Pull in the arch specific syscall implementation */ +#include +/* For MAP_ANONYMOUS -- differs between platforms */ +#include +/* Pull in whatever this particular arch's kernel thinks the kernel version of + * struct stat should look like. It turns out that each arch has a different + * opinion on the subject, and different kernel revs use different names... */ +#define kernel_stat stat +#include + + +/* Encoding of the file mode. */ +#define S_IFMT 0170000 /* These bits determine file type. */ + +/* File types. */ +#define S_IFDIR 0040000 /* Directory. */ +#define S_IFCHR 0020000 /* Character device. */ +#define S_IFBLK 0060000 /* Block device. */ +#define S_IFREG 0100000 /* Regular file. */ +#define S_IFIFO 0010000 /* FIFO. */ +#define S_IFLNK 0120000 /* Symbolic link. */ +#define S_IFSOCK 0140000 /* Socket. */ + +/* Protection bits. */ + +#define S_ISUID 04000 /* Set user ID on execution. */ +#define S_ISGID 02000 /* Set group ID on execution. */ +#define S_ISVTX 01000 /* Save swapped text after use (sticky). */ +#define S_IREAD 0400 /* Read by owner. */ +#define S_IWRITE 0200 /* Write by owner. */ +#define S_IEXEC 0100 /* Execute by owner. */ + + +/* Here are the definitions for some syscalls that are used + by the dynamic linker. The idea is that we want to be able + to call these before the errno symbol is dynamicly linked, so + we use our own version here. Note that we cannot assume any + dynamic linking at all, so we cannot return any error codes. + We just punt if there is an error. */ + + +#define __NR__dl_exit __NR_exit +static inline _syscall1(void, _dl_exit, int, status); + + +#define __NR__dl_close __NR_close +static inline _syscall1(int, _dl_close, int, fd); + + +#if defined(__powerpc__) || defined(__mips__) || defined(__sh__) +/* PowerPC, MIPS and SuperH have a different calling convention for mmap(). */ +#define __NR__dl_mmap __NR_mmap +static inline _syscall6(void *, _dl_mmap, void *, start, size_t, length, + int, prot, int, flags, int, fd, off_t, offset); +#else +#define __NR__dl_mmap_real __NR_mmap +static inline _syscall1(void *, _dl_mmap_real, unsigned long *, buffer); + +static inline void * _dl_mmap(void * addr, unsigned long size, int prot, + int flags, int fd, unsigned long offset) +{ + unsigned long buffer[6]; + + buffer[0] = (unsigned long) addr; + buffer[1] = (unsigned long) size; + buffer[2] = (unsigned long) prot; + buffer[3] = (unsigned long) flags; + buffer[4] = (unsigned long) fd; + buffer[5] = (unsigned long) offset; + return (void *) _dl_mmap_real(buffer); +} +#endif + +#ifndef _dl_MAX_ERRNO +#define _dl_MAX_ERRNO 4096 +#endif +#define _dl_mmap_check_error(__res) \ + (((int)__res) < 0 && ((int)__res) >= -_dl_MAX_ERRNO) +#ifndef MAP_ANONYMOUS +#ifdef __sparc__ +#define MAP_ANONYMOUS 0x20 +#else +#error MAP_ANONYMOUS not defined and suplementary value not known +#endif +#endif + + +#define __NR__dl_open __NR_open +#define O_RDONLY 0x0000 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +static inline _syscall2(int, _dl_open, const char *, fn, int, flags); + +#define __NR__dl_write __NR_write +static inline _syscall3(unsigned long, _dl_write, int, fd, + const void *, buf, unsigned long, count); + + +#define __NR__dl_read __NR_read +static inline _syscall3(unsigned long, _dl_read, int, fd, + const void *, buf, unsigned long, count); + +#define __NR__dl_mprotect __NR_mprotect +static inline _syscall3(int, _dl_mprotect, const void *, addr, unsigned long, len, int, prot); + + + +#define __NR__dl_stat __NR_stat +static inline _syscall2(int, _dl_stat, const char *, file_name, struct stat *, buf); + + +#define __NR__dl_munmap __NR_munmap +static inline _syscall2(int, _dl_munmap, void *, start, unsigned long, length); + +#define __NR__dl_getuid __NR_getuid +static inline _syscall0(uid_t, _dl_getuid); + +#define __NR__dl_geteuid __NR_geteuid +static inline _syscall0(uid_t, _dl_geteuid); + +#define __NR__dl_getgid __NR_getgid +static inline _syscall0(gid_t, _dl_getgid); + +#define __NR__dl_getegid __NR_getegid +static inline _syscall0(gid_t, _dl_getegid); + +#define __NR__dl_getpid __NR_getpid +static inline _syscall0(gid_t, _dl_getpid); + +/* + * Not an actual syscall, but we need something in assembly to say whether + * this is OK or not. + */ +static inline int _dl_suid_ok(void) +{ + uid_t uid, euid, gid, egid; + + uid = _dl_getuid(); + euid = _dl_geteuid(); + gid = _dl_getgid(); + egid = _dl_getegid(); + + if(uid == euid && gid == egid) + return 1; + else + return 0; +} + +#define __NR__dl_readlink __NR_readlink +static inline _syscall3(int, _dl_readlink, const char *, path, char *, buf, size_t, bufsiz); + +#endif /* _LD_SYSCALL_H_ */ + diff --git a/ldso/include/dlfcn.h b/ldso/include/dlfcn.h new file mode 100644 index 000000000..484558d83 --- /dev/null +++ b/ldso/include/dlfcn.h @@ -0,0 +1,22 @@ +/* User functions for run-time dynamic loading. libdl version */ +#ifndef _DLFCN_H +#define _DLFCN_H 1 + +#include +#include + +#define RTLD_NEXT ((void *) -1l) +#define RTLD_DEFAULT ((void *) 0) + +/* Structure containing information about object searched using + `dladdr'. */ +typedef struct +{ + __const char *dli_fname; /* File name of defining object. */ + void *dli_fbase; /* Load address of that object. */ + __const char *dli_sname; /* Name of nearest symbol. */ + void *dli_saddr; /* Exact value of nearest symbol. */ +} Dl_info; + + +#endif /* dlfcn.h */ diff --git a/ldso/include/ld_elf.h b/ldso/include/ld_elf.h new file mode 100644 index 000000000..95de118f5 --- /dev/null +++ b/ldso/include/ld_elf.h @@ -0,0 +1,91 @@ +#ifndef LINUXELF_H +#define LINUXELF_H + +#include /* before elf.h to get ELF_USES_RELOCA right */ +#include +#include + +#ifdef DEBUG +# define LDSO_CONF "../util/ld.so.conf" +# define LDSO_CACHE "../util/ld.so.cache" +# define LDSO_PRELOAD "../util/ld.so.preload" +#else +# define LDSO_CONF UCLIBC_TARGET_PREFIX "etc/ld.so.conf" +# define LDSO_CACHE UCLIBC_TARGET_PREFIX "etc/ld.so.cache" +# define LDSO_PRELOAD UCLIBC_TARGET_PREFIX "etc/ld.so.preload" +#endif + + +#define LIB_ANY -1 +#define LIB_DLL 0 +#define LIB_ELF 1 +#define LIB_ELF_LIBC5 2 +#define LIB_ELF_LIBC6 3 +#define LIB_ELF64 0x80 + +/* Forward declarations for stuff defined in ld_hash.h */ +struct dyn_elf; +struct elf_resolve; + + +/* Definitions and prototypes for cache stuff */ +#ifdef USE_CACHE +extern int _dl_map_cache(void); +extern int _dl_unmap_cache(void); + +#define LDSO_CACHE_MAGIC "ld.so-" +#define LDSO_CACHE_MAGIC_LEN (sizeof LDSO_CACHE_MAGIC -1) +#define LDSO_CACHE_VER "1.7.0" +#define LDSO_CACHE_VER_LEN (sizeof LDSO_CACHE_VER -1) + +typedef struct { + char magic [LDSO_CACHE_MAGIC_LEN]; + char version [LDSO_CACHE_VER_LEN]; + int nlibs; +} header_t; + +typedef struct { + int flags; + int sooffset; + int liboffset; +} libentry_t; + +#else +static inline void _dl_map_cache(void) { } +static inline void _dl_unmap_cache(void) { } +#endif + + +/* Function prototypes for non-static stuff in readelflib1.c */ +int _dl_copy_fixups(struct dyn_elf * tpnt); +extern int _dl_parse_copy_information(struct dyn_elf *rpnt, + unsigned long rel_addr, unsigned long rel_size, int type); +extern void _dl_parse_lazy_relocation_information(struct elf_resolve *tpnt, + unsigned long rel_addr, unsigned long rel_size, int type); +extern int _dl_parse_relocation_information(struct elf_resolve *tpnt, + unsigned long rel_addr, unsigned long rel_size, int type); +extern struct elf_resolve * _dl_load_shared_library(int secure, + struct dyn_elf **rpnt, struct elf_resolve *tpnt, char *full_libname); +extern struct elf_resolve * _dl_load_elf_shared_library(int secure, + struct dyn_elf **rpnt, char *libname); +extern int _dl_linux_resolve(void); + + +/* + * Datatype of a relocation on this platform + */ +#ifdef ELF_USES_RELOCA +# define ELF_RELOC ElfW(Rela) +#else +# define ELF_RELOC ElfW(Rel) +#endif + + +/* Convert between the Linux flags for page protections and the + ones specified in the ELF standard. */ +#define LXFLAGS(X) ( (((X) & PF_R) ? PROT_READ : 0) | \ + (((X) & PF_W) ? PROT_WRITE : 0) | \ + (((X) & PF_X) ? PROT_EXEC : 0)) + + +#endif /* LINUXELF_H */ diff --git a/ldso/include/ld_hash.h b/ldso/include/ld_hash.h new file mode 100644 index 000000000..d7ed5ab2c --- /dev/null +++ b/ldso/include/ld_hash.h @@ -0,0 +1,118 @@ +#ifndef _LD_HASH_H_ +#define _LD_HASH_H_ + +#ifndef RTLD_NEXT +#define RTLD_NEXT ((void*)-1) +#endif + +struct dyn_elf{ + unsigned long flags; + struct elf_resolve * dyn; + struct dyn_elf * next_handle; /* Used by dlopen et al. */ + struct dyn_elf * next; + struct dyn_elf * prev; +}; + +struct elf_resolve{ + /* These entries must be in this order to be compatible with the interface used + by gdb to obtain the list of symbols. */ + char * loadaddr; + char * libname; + unsigned long dynamic_addr; + struct elf_resolve * next; + struct elf_resolve * prev; + /* Nothing after this address is used by gdb. */ + enum {elf_lib, elf_executable,program_interpreter, loaded_file} libtype; + struct dyn_elf * symbol_scope; + unsigned short usage_count; + unsigned short int init_flag; + unsigned int nbucket; + unsigned long * elf_buckets; + /* + * These are only used with ELF style shared libraries + */ + unsigned long nchain; + unsigned long * chains; + unsigned long dynamic_info[24]; + + unsigned long dynamic_size; + unsigned long n_phent; + Elf32_Phdr * ppnt; + +#if defined(__mips__) + /* Needed for MIPS relocation */ + unsigned long mips_gotsym; + unsigned long mips_local_gotno; + unsigned long mips_symtabno; +#endif + +#ifdef __powerpc__ + /* this is used to store the address of relocation data words, so + * we don't have to calculate it every time, which requires a divide */ + unsigned long data_words; +#endif +}; + +#if 0 +/* + * The DT_DEBUG entry in the .dynamic section is given the address of this structure. + * gdb can pick this up to obtain the correct list of loaded modules. + */ + +struct r_debug{ + int r_version; + struct elf_resolve * link_map; + unsigned long brk_fun; + enum {RT_CONSISTENT, RT_ADD, RT_DELETE}; + unsigned long ldbase; +}; +#endif + +#define COPY_RELOCS_DONE 1 +#define RELOCS_DONE 2 +#define JMP_RELOCS_DONE 4 +#define INIT_FUNCS_CALLED 8 + +extern struct dyn_elf * _dl_symbol_tables; +extern struct elf_resolve * _dl_loaded_modules; +extern struct dyn_elf * _dl_handles; + +extern struct elf_resolve * _dl_check_hashed_files(const char * libname); +extern struct elf_resolve * _dl_add_elf_hash_table(const char * libname, + char * loadaddr, unsigned long * dynamic_info, + unsigned long dynamic_addr, unsigned long dynamic_size); + +enum caller_type{symbolrel=0,copyrel=1,resolver=2}; +extern char * _dl_find_hash(const char * name, struct dyn_elf * rpnt1, + struct elf_resolve * f_tpnt, enum caller_type); + +extern int _dl_linux_dynamic_link(void); + +extern char * _dl_library_path; +extern char * _dl_not_lazy; +extern unsigned long _dl_elf_hash(const char * name); + +static inline int _dl_symbol(char * name) +{ + if(name[0] != '_' || name[1] != 'd' || name[2] != 'l' || name[3] != '_') + return 0; + return 1; +} + + +#define LD_ERROR_NOFILE 1 +#define LD_ERROR_NOZERO 2 +#define LD_ERROR_NOTELF 3 +#define LD_ERROR_NOTMAGIC 4 +#define LD_ERROR_NOTDYN 5 +#define LD_ERROR_MMAP_FAILED 6 +#define LD_ERROR_NODYNAMIC 7 +#define LD_WRONG_RELOCS 8 +#define LD_BAD_HANDLE 9 +#define LD_NO_SYMBOL 10 + + + +#endif /* _LD_HASH_H_ */ + + diff --git a/ldso/include/ld_string.h b/ldso/include/ld_string.h new file mode 100644 index 000000000..647ab1efd --- /dev/null +++ b/ldso/include/ld_string.h @@ -0,0 +1,281 @@ +#ifndef _LINUX_STRING_H_ +#define _LINUX_STRING_H_ + +extern void *_dl_malloc(int size); +extern char *_dl_getenv(const char *symbol, char **envp); +extern void _dl_unsetenv(const char *symbol, char **envp); +extern char *_dl_strdup(const char *string); +extern void _dl_dprintf(int, const char *, ...); + + +static size_t _dl_strlen(const char * str); +static char *_dl_strcat(char *dst, const char *src); +static char * _dl_strcpy(char * dst,const char *src); +static int _dl_strcmp(const char * s1,const char * s2); +static int _dl_strncmp(const char * s1,const char * s2,size_t len); +static char * _dl_strchr(const char * str,int c); +static char *_dl_strrchr(const char *str, int c); +static char *_dl_strstr(const char *s1, const char *s2); +static void * _dl_memcpy(void * dst, const void * src, size_t len); +static int _dl_memcmp(const void * s1,const void * s2,size_t len); +static void *_dl_memset(void * str,int c,size_t len); +static char *_dl_get_last_path_component(char *path); +static char *_dl_simple_ltoa(char * local, unsigned long i); +static char *_dl_simple_ltoahex(char * local, unsigned long i); + +#ifndef NULL +#define NULL ((void *) 0) +#endif + +static inline size_t _dl_strlen(const char * str) +{ + register char *ptr = (char *) str; + + while (*ptr) + ptr++; + return (ptr - str); +} + +static inline char *_dl_strcat(char *dst, const char *src) +{ + register char *ptr = dst; + + while (*ptr) + ptr++; + + while (*src) + *ptr++ = *src++; + *ptr = '\0'; + + return dst; +} + +static inline char * _dl_strcpy(char * dst,const char *src) +{ + register char *ptr = dst; + + while (*src) + *dst++ = *src++; + *dst = '\0'; + + return ptr; +} + +static inline int _dl_strcmp(const char * s1,const char * s2) +{ + register unsigned char c1, c2; + + do { + c1 = (unsigned char) *s1++; + c2 = (unsigned char) *s2++; + if (c1 == '\0') + return c1 - c2; + } + while (c1 == c2); + + return c1 - c2; +} + +static inline int _dl_strncmp(const char * s1,const char * s2,size_t len) +{ + register unsigned char c1 = '\0'; + register unsigned char c2 = '\0'; + + while (len > 0) { + c1 = (unsigned char) *s1++; + c2 = (unsigned char) *s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + len--; + } + + return c1 - c2; +} + +static inline char * _dl_strchr(const char * str,int c) +{ + register char ch; + + do { + if ((ch = *str) == c) + return (char *) str; + str++; + } + while (ch); + + return 0; +} + +static inline char *_dl_strrchr(const char *str, int c) +{ + register char *prev = 0; + register char *ptr = (char *) str; + + while (*ptr != '\0') { + if (*ptr == c) + prev = ptr; + ptr++; + } + if (c == '\0') + return(ptr); + return(prev); +} + + +static inline char *_dl_strstr(const char *s1, const char *s2) +{ + register const char *s = s1; + register const char *p = s2; + + do { + if (!*p) { + return (char *) s1;; + } + if (*p == *s) { + ++p; + ++s; + } else { + p = s2; + if (!*s) { + return NULL; + } + s = ++s1; + } + } while (1); +} + +static inline void * _dl_memcpy(void * dst, const void * src, size_t len) +{ + register char *a = dst; + register const char *b = src; + + while (len--) + *a++ = *b++; + + return dst; +} + + +static inline int _dl_memcmp(const void * s1,const void * s2,size_t len) +{ + unsigned char *c1 = (unsigned char *)s1; + unsigned char *c2 = (unsigned char *)s2; + + while (len--) { + if (*c1 != *c2) + return *c1 - *c2; + c1++; + c2++; + } + return 0; +} + +static inline void * _dl_memset(void * str,int c,size_t len) +{ + register char *a = str; + + while (len--) + *a++ = c; + + return str; +} + +static inline char *_dl_get_last_path_component(char *path) +{ + char *s; + register char *ptr = path; + register char *prev = 0; + + while (*ptr) + ptr++; + s = ptr - 1; + + /* strip trailing slashes */ + while (s != path && *s == '/') { + *s-- = '\0'; + } + + /* find last component */ + ptr = path; + while (*ptr != '\0') { + if (*ptr == '/') + prev = ptr; + ptr++; + } + s = prev; + + if (s == NULL || s[1] == '\0') + return path; + else + return s+1; +} + +/* Early on, we can't call printf, so use this to print out + * numbers using the SEND_STDERR() macro */ +static inline char *_dl_simple_ltoa(char * local, unsigned long i) +{ + /* 21 digits plus null terminator, good for 64-bit or smaller ints */ + char *p = &local[22]; + *p-- = '\0'; + do { + *p-- = '0' + i % 10; + i /= 10; + } while (i > 0); + return p + 1; +} + +static inline char *_dl_simple_ltoahex(char * local, unsigned long i) +{ + /* 21 digits plus null terminator, good for 64-bit or smaller ints */ + char *p = &local[22]; + *p-- = '\0'; + do { + char temp = i % 0x10; + if (temp <= 0x09) + *p-- = '0' + temp; + else + *p-- = 'a' - 0x0a + temp; + i /= 0x10; + } while (i > 0); + *p-- = 'x'; + *p-- = '0'; + return p + 1; +} + + +#if defined mc68000 || defined __arm__ || defined __mips__ || defined __sh__ +/* On some arches constant strings are referenced through the GOT. */ +/* XXX Requires load_addr to be defined. */ +#define SEND_STDERR(X) \ + { const char *__s = (X); \ + if (__s < (const char *) load_addr) __s += load_addr; \ + _dl_write (2, __s, _dl_strlen (__s)); \ + } +#else +#define SEND_STDERR(X) _dl_write(2, X, _dl_strlen(X)); +#endif + +#define SEND_ADDRESS_STDERR(X, add_a_newline) { \ + char tmp[22], *tmp1; \ + _dl_memset(tmp, 0, sizeof(tmp)); \ + tmp1=_dl_simple_ltoahex( tmp, (unsigned long)(X)); \ + _dl_write(2, tmp1, _dl_strlen(tmp1)); \ + if (add_a_newline) { \ + tmp[0]='\n'; \ + _dl_write(2, tmp, 1); \ + } \ +}; + +#define SEND_NUMBER_STDERR(X, add_a_newline) { \ + char tmp[22], *tmp1; \ + _dl_memset(tmp, 0, sizeof(tmp)); \ + tmp1=_dl_simple_ltoa( tmp, (unsigned long)(X)); \ + _dl_write(2, tmp1, _dl_strlen(tmp1)); \ + if (add_a_newline) { \ + tmp[0]='\n'; \ + _dl_write(2, tmp, 1); \ + } \ +}; + + +#endif diff --git a/ldso/include/ld_syscall.h b/ldso/include/ld_syscall.h new file mode 100644 index 000000000..72574b9a9 --- /dev/null +++ b/ldso/include/ld_syscall.h @@ -0,0 +1,157 @@ +#ifndef _LD_SYSCALL_H_ +#define _LD_SYSCALL_H_ + +/* Pull in the arch specific syscall implementation */ +#include +/* For MAP_ANONYMOUS -- differs between platforms */ +#include +/* Pull in whatever this particular arch's kernel thinks the kernel version of + * struct stat should look like. It turns out that each arch has a different + * opinion on the subject, and different kernel revs use different names... */ +#define kernel_stat stat +#include + + +/* Encoding of the file mode. */ +#define S_IFMT 0170000 /* These bits determine file type. */ + +/* File types. */ +#define S_IFDIR 0040000 /* Directory. */ +#define S_IFCHR 0020000 /* Character device. */ +#define S_IFBLK 0060000 /* Block device. */ +#define S_IFREG 0100000 /* Regular file. */ +#define S_IFIFO 0010000 /* FIFO. */ +#define S_IFLNK 0120000 /* Symbolic link. */ +#define S_IFSOCK 0140000 /* Socket. */ + +/* Protection bits. */ + +#define S_ISUID 04000 /* Set user ID on execution. */ +#define S_ISGID 02000 /* Set group ID on execution. */ +#define S_ISVTX 01000 /* Save swapped text after use (sticky). */ +#define S_IREAD 0400 /* Read by owner. */ +#define S_IWRITE 0200 /* Write by owner. */ +#define S_IEXEC 0100 /* Execute by owner. */ + + +/* Here are the definitions for some syscalls that are used + by the dynamic linker. The idea is that we want to be able + to call these before the errno symbol is dynamicly linked, so + we use our own version here. Note that we cannot assume any + dynamic linking at all, so we cannot return any error codes. + We just punt if there is an error. */ + + +#define __NR__dl_exit __NR_exit +static inline _syscall1(void, _dl_exit, int, status); + + +#define __NR__dl_close __NR_close +static inline _syscall1(int, _dl_close, int, fd); + + +#if defined(__powerpc__) || defined(__mips__) || defined(__sh__) +/* PowerPC, MIPS and SuperH have a different calling convention for mmap(). */ +#define __NR__dl_mmap __NR_mmap +static inline _syscall6(void *, _dl_mmap, void *, start, size_t, length, + int, prot, int, flags, int, fd, off_t, offset); +#else +#define __NR__dl_mmap_real __NR_mmap +static inline _syscall1(void *, _dl_mmap_real, unsigned long *, buffer); + +static inline void * _dl_mmap(void * addr, unsigned long size, int prot, + int flags, int fd, unsigned long offset) +{ + unsigned long buffer[6]; + + buffer[0] = (unsigned long) addr; + buffer[1] = (unsigned long) size; + buffer[2] = (unsigned long) prot; + buffer[3] = (unsigned long) flags; + buffer[4] = (unsigned long) fd; + buffer[5] = (unsigned long) offset; + return (void *) _dl_mmap_real(buffer); +} +#endif + +#ifndef _dl_MAX_ERRNO +#define _dl_MAX_ERRNO 4096 +#endif +#define _dl_mmap_check_error(__res) \ + (((int)__res) < 0 && ((int)__res) >= -_dl_MAX_ERRNO) +#ifndef MAP_ANONYMOUS +#ifdef __sparc__ +#define MAP_ANONYMOUS 0x20 +#else +#error MAP_ANONYMOUS not defined and suplementary value not known +#endif +#endif + + +#define __NR__dl_open __NR_open +#define O_RDONLY 0x0000 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +static inline _syscall2(int, _dl_open, const char *, fn, int, flags); + +#define __NR__dl_write __NR_write +static inline _syscall3(unsigned long, _dl_write, int, fd, + const void *, buf, unsigned long, count); + + +#define __NR__dl_read __NR_read +static inline _syscall3(unsigned long, _dl_read, int, fd, + const void *, buf, unsigned long, count); + +#define __NR__dl_mprotect __NR_mprotect +static inline _syscall3(int, _dl_mprotect, const void *, addr, unsigned long, len, int, prot); + + + +#define __NR__dl_stat __NR_stat +static inline _syscall2(int, _dl_stat, const char *, file_name, struct stat *, buf); + + +#define __NR__dl_munmap __NR_munmap +static inline _syscall2(int, _dl_munmap, void *, start, unsigned long, length); + +#define __NR__dl_getuid __NR_getuid +static inline _syscall0(uid_t, _dl_getuid); + +#define __NR__dl_geteuid __NR_geteuid +static inline _syscall0(uid_t, _dl_geteuid); + +#define __NR__dl_getgid __NR_getgid +static inline _syscall0(gid_t, _dl_getgid); + +#define __NR__dl_getegid __NR_getegid +static inline _syscall0(gid_t, _dl_getegid); + +#define __NR__dl_getpid __NR_getpid +static inline _syscall0(gid_t, _dl_getpid); + +/* + * Not an actual syscall, but we need something in assembly to say whether + * this is OK or not. + */ +static inline int _dl_suid_ok(void) +{ + uid_t uid, euid, gid, egid; + + uid = _dl_getuid(); + euid = _dl_geteuid(); + gid = _dl_getgid(); + egid = _dl_getegid(); + + if(uid == euid && gid == egid) + return 1; + else + return 0; +} + +#define __NR__dl_readlink __NR_readlink +static inline _syscall3(int, _dl_readlink, const char *, path, char *, buf, size_t, bufsiz); + +#endif /* _LD_SYSCALL_H_ */ + diff --git a/ldso/include/ldso.h b/ldso/include/ldso.h new file mode 100644 index 000000000..b5ccbfaef --- /dev/null +++ b/ldso/include/ldso.h @@ -0,0 +1,11 @@ +#include +/* Pull in compiler and arch stuff */ +#include +#include +/* Pull in the arch specific type information */ +#include +/* Now the ldso specific headers */ +#include +#include +#include +#include diff --git a/ldso/ldso/.cvsignore b/ldso/ldso/.cvsignore index ed93c7d9c..cc73e174c 100644 --- a/ldso/ldso/.cvsignore +++ b/ldso/ldso/.cvsignore @@ -1,2 +1,2 @@ ld-uclibc.so* -ldso.h +_dl_progname.h diff --git a/ldso/ldso/Makefile b/ldso/ldso/Makefile index 13063616f..5b5ae90ca 100644 --- a/ldso/ldso/Makefile +++ b/ldso/ldso/Makefile @@ -27,10 +27,12 @@ include $(TOPDIR)Rules.mak LDSO_FULLNAME=ld-uClibc-$(MAJOR_VERSION).$(MINOR_VERSION).$(SUBLEVEL).so - -XXFLAGS+=-DUCLIBC_TARGET_PREFIX=\"$(TARGET_PREFIX)\" \ +XXFLAGS=$(XWARNINGS) $(OPTIMIZATION) $(XARCH_CFLAGS) $(CPU_CFLAGS) $(PICFLAG) \ + -DUCLIBC_TARGET_PREFIX=\"$(TARGET_PREFIX)\" \ -DUCLIBC_DEVEL_PREFIX=\"$(DEVEL_PREFIX)\" \ - -DUCLIBC_BUILD_DIR=\"$(shell cd $(TOPDIR) && pwd)\" + -DUCLIBC_BUILD_DIR=\"$(shell cd $(TOPDIR) && pwd)\" \ + -fno-builtin -nostdinc -I$(TOPDIR)ldso/include -I. -I$(TOPDIR)include +XXFLAGS+=$(shell $(CC) -print-search-dirs | sed -ne "s/install: *\(.*\)/-I\1include/gp") LDFLAGS=$(CPU_LDFLAGS-y) -shared --warn-common --export-dynamic --sort-common \ -z combreloc --discard-locals --discard-all CSRC= ldso.c #hash.c readelflib1.c $(TARGET_ARCH)/elfinterp.c @@ -61,29 +63,28 @@ endif all: lib -lib:: ldso.h $(OBJS) $(DLINK_OBJS) +lib:: _dl_progname.h $(OBJS) $(DLINK_OBJS) $(LD) $(LDFLAGS) -e _dl_boot -soname=$(UCLIBC_LDSO) \ -o $(LDSO_FULLNAME) $(OBJS) $(LIBGCC); install -d $(TOPDIR)lib install -m 755 $(LDSO_FULLNAME) $(TOPDIR)lib (cd $(TOPDIR)lib && ln -sf $(LDSO_FULLNAME) $(UCLIBC_LDSO)) -ldso.h: Makefile - echo "const char *_dl_progname=\""$(UCLIBC_LDSO)"\";" > ldso.h - echo "#include \"$(TARGET_ARCH)/elfinterp.c\"" >> ldso.h +_dl_progname.h: Makefile + echo "const char *_dl_progname=\""$(UCLIBC_LDSO)"\";" > _dl_progname.h + echo "#include \"$(TARGET_ARCH)/elfinterp.c\"" >> _dl_progname.h $(COBJS): %.o : %.c - $(CC) $(CFLAGS) $(XXFLAGS) -I. -I./$(TARGET_ARCH) -I../libdl -c $< -o $@ + $(CC) $(XXFLAGS) -I../libdl -c $< -o $@ $(STRIPTOOL) -x -R .note -R .comment $*.o $(AOBJS): %.o : %.S - $(CC) $(CFLAGS) -I. -I./$(TARGET_ARCH) -I../libdl -c $< -o $@ + $(CC) $(XXFLAGS) -I../libdl -c $< -o $@ $(STRIPTOOL) -x -R .note -R .comment $*.o -ldso.o: ldso.c hash.c readelflib1.c $(TARGET_ARCH)/elfinterp.c \ - ld_hash.h ld_string.h ld_syscall.h ldso.h linuxelf.h +ldso.o: ldso.c hash.c readelflib1.c $(TARGET_ARCH)/elfinterp.c _dl_progname.h clean:: - $(RM) -f $(UCLIBC_LDSO)* $(OBJS) $(LDSO_FULLNAME)* core *.o *.a *.s *.i ldso.h *~ + $(RM) -f $(UCLIBC_LDSO)* $(OBJS) $(LDSO_FULLNAME)* core *.o *.a *.s *.i _dl_progname.h *~ diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c index 0290d6ccf..dd3d9a293 100644 --- a/ldso/ldso/dl-elf.c +++ b/ldso/ldso/dl-elf.c @@ -4,7 +4,7 @@ * * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, * David Engel, Hongjiu Lu and Mitch D'Souza - * Copyright (C) 2001-2002, Erik Andersen + * Copyright (C) 2001-2003, Erik Andersen * * All rights reserved. * @@ -316,12 +316,12 @@ goof: struct elf_resolve *_dl_load_elf_shared_library(int secure, struct dyn_elf **rpnt, char *libname) { - elfhdr *epnt; + ElfW(Ehdr) *epnt; unsigned long dynamic_addr = 0; unsigned long dynamic_size = 0; Elf32_Dyn *dpnt; struct elf_resolve *tpnt; - elf_phdr *ppnt; + ElfW(Phdr) *ppnt; char *status; char header[4096]; unsigned long dynamic_info[24]; @@ -371,7 +371,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, } _dl_read(infile, header, sizeof(header)); - epnt = (elfhdr *) (intptr_t) header; + epnt = (ElfW(Ehdr) *) (intptr_t) header; if (epnt->e_ident[0] != 0x7f || epnt->e_ident[1] != 'E' || epnt->e_ident[2] != 'L' || @@ -398,7 +398,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, return NULL; }; - ppnt = (elf_phdr *)(intptr_t) & header[epnt->e_phoff]; + ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff]; piclib = 1; for (i = 0; i < epnt->e_phnum; i++) { @@ -446,7 +446,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, flags |= MAP_FIXED; /* Get the memory to store the library */ - ppnt = (elf_phdr *)(intptr_t) & header[epnt->e_phoff]; + ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff]; for (i = 0; i < epnt->e_phnum; i++) { if (ppnt->p_type == PT_LOAD) { @@ -577,7 +577,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, if (dynamic_info[DT_TEXTREL]) { #ifndef FORCE_SHAREABLE_TEXT_SEGMENTS - ppnt = (elf_phdr *)(intptr_t) & header[epnt->e_phoff]; + ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff]; for (i = 0; i < epnt->e_phnum; i++, ppnt++) { if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W)) _dl_mprotect((void *) ((piclib ? libaddr : 0) + @@ -594,7 +594,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, tpnt = _dl_add_elf_hash_table(libname, (char *) libaddr, dynamic_info, dynamic_addr, dynamic_size); - tpnt->ppnt = (elf_phdr *)(intptr_t) (tpnt->loadaddr + epnt->e_phoff); + tpnt->ppnt = (ElfW(Phdr) *)(intptr_t) (tpnt->loadaddr + epnt->e_phoff); tpnt->n_phent = epnt->e_phnum; /* diff --git a/ldso/ldso/ld_hash.h b/ldso/ldso/ld_hash.h deleted file mode 100644 index 0632ce2c9..000000000 --- a/ldso/ldso/ld_hash.h +++ /dev/null @@ -1,151 +0,0 @@ -#ifndef _HASH_H_ -#define _HASH_H_ - -#include "linuxelf.h" - -/* Header file that describes the internal data structures used by the - * ELF dynamic linker. */ - -struct link_map -{ - /* These entries must be in this order to be compatible with the - * interface used by gdb to obtain the list of symbols. */ - Elf32_Addr l_addr; /* address at which object is mapped */ - char *l_name; /* full name of loaded object */ - Elf32_Dyn *l_ld; /* dynamic structure of object */ - struct link_map *l_next; - struct link_map *l_prev; -}; - -/* The DT_DEBUG entry in the .dynamic section is given the address of - * this structure. gdb can pick this up to obtain the correct list of - * loaded modules. */ -struct r_debug -{ - int r_version; /* debugging info version no */ - struct link_map *r_map; /* address of link_map */ - unsigned long r_brk; /* address of update routine */ - enum - { - RT_CONSISTENT, - RT_ADD, - RT_DELETE - } r_state; - unsigned long r_ldbase; /* base addr of ld.so */ -}; - -#ifndef RTLD_NEXT -#define RTLD_NEXT ((void*)-1) -#endif - -struct dyn_elf{ - unsigned long flags; - struct elf_resolve * dyn; - struct dyn_elf * next_handle; /* Used by dlopen et al. */ - struct dyn_elf * next; - struct dyn_elf * prev; -}; - -struct elf_resolve{ - /* These entries must be in this order to be compatible with the interface used - by gdb to obtain the list of symbols. */ - char * loadaddr; - char * libname; - unsigned long dynamic_addr; - struct elf_resolve * next; - struct elf_resolve * prev; - /* Nothing after this address is used by gdb. */ - enum {elf_lib, elf_executable,program_interpreter, loaded_file} libtype; - struct dyn_elf * symbol_scope; - unsigned short usage_count; - unsigned short int init_flag; - unsigned int nbucket; - unsigned long * elf_buckets; - /* - * These are only used with ELF style shared libraries - */ - unsigned long nchain; - unsigned long * chains; - unsigned long dynamic_info[24]; - - unsigned long dynamic_size; - unsigned long n_phent; - Elf32_Phdr * ppnt; - -#if defined(__mips__) - /* Needed for MIPS relocation */ - unsigned long mips_gotsym; - unsigned long mips_local_gotno; - unsigned long mips_symtabno; -#endif - -#ifdef __powerpc__ - /* this is used to store the address of relocation data words, so - * we don't have to calculate it every time, which requires a divide */ - unsigned long data_words; -#endif -}; - -#if 0 -/* - * The DT_DEBUG entry in the .dynamic section is given the address of this structure. - * gdb can pick this up to obtain the correct list of loaded modules. - */ - -struct r_debug{ - int r_version; - struct elf_resolve * link_map; - unsigned long brk_fun; - enum {RT_CONSISTENT, RT_ADD, RT_DELETE}; - unsigned long ldbase; -}; -#endif - -#define COPY_RELOCS_DONE 1 -#define RELOCS_DONE 2 -#define JMP_RELOCS_DONE 4 -#define INIT_FUNCS_CALLED 8 - -extern struct dyn_elf * _dl_symbol_tables; -extern struct elf_resolve * _dl_loaded_modules; -extern struct dyn_elf * _dl_handles; - -extern struct elf_resolve * _dl_check_hashed_files(const char * libname); -extern struct elf_resolve * _dl_add_elf_hash_table(const char * libname, - char * loadaddr, unsigned long * dynamic_info, - unsigned long dynamic_addr, unsigned long dynamic_size); - -enum caller_type{symbolrel=0,copyrel=1,resolver=2}; -extern char * _dl_find_hash(const char * name, struct dyn_elf * rpnt1, - struct elf_resolve * f_tpnt, enum caller_type); - -extern int _dl_linux_dynamic_link(void); - -extern char * _dl_library_path; -extern char * _dl_not_lazy; -extern unsigned long _dl_elf_hash(const char * name); - -static inline int _dl_symbol(char * name) -{ - if(name[0] != '_' || name[1] != 'd' || name[2] != 'l' || name[3] != '_') - return 0; - return 1; -} - - -#define LD_ERROR_NOFILE 1 -#define LD_ERROR_NOZERO 2 -#define LD_ERROR_NOTELF 3 -#define LD_ERROR_NOTMAGIC 4 -#define LD_ERROR_NOTDYN 5 -#define LD_ERROR_MMAP_FAILED 6 -#define LD_ERROR_NODYNAMIC 7 -#define LD_WRONG_RELOCS 8 -#define LD_BAD_HANDLE 9 -#define LD_NO_SYMBOL 10 - - - -#endif /* _HASH_H_ */ - - diff --git a/ldso/ldso/ld_string.h b/ldso/ldso/ld_string.h deleted file mode 100644 index 3eaad8f24..000000000 --- a/ldso/ldso/ld_string.h +++ /dev/null @@ -1,283 +0,0 @@ -#ifndef _LINUX_STRING_H_ -#define _LINUX_STRING_H_ - -#include /* for size_t */ - -extern void *_dl_malloc(int size); -extern char *_dl_getenv(const char *symbol, char **envp); -extern void _dl_unsetenv(const char *symbol, char **envp); -extern char *_dl_strdup(const char *string); -extern void _dl_dprintf(int, const char *, ...); - - -static size_t _dl_strlen(const char * str); -static char *_dl_strcat(char *dst, const char *src); -static char * _dl_strcpy(char * dst,const char *src); -static int _dl_strcmp(const char * s1,const char * s2); -static int _dl_strncmp(const char * s1,const char * s2,size_t len); -static char * _dl_strchr(const char * str,int c); -static char *_dl_strrchr(const char *str, int c); -static char *_dl_strstr(const char *s1, const char *s2); -static void * _dl_memcpy(void * dst, const void * src, size_t len); -static int _dl_memcmp(const void * s1,const void * s2,size_t len); -static void *_dl_memset(void * str,int c,size_t len); -static char *_dl_get_last_path_component(char *path); -static char *_dl_simple_ltoa(char * local, unsigned long i); -static char *_dl_simple_ltoahex(char * local, unsigned long i); - -#ifndef NULL -#define NULL ((void *) 0) -#endif - -static inline size_t _dl_strlen(const char * str) -{ - register char *ptr = (char *) str; - - while (*ptr) - ptr++; - return (ptr - str); -} - -static inline char *_dl_strcat(char *dst, const char *src) -{ - register char *ptr = dst; - - while (*ptr) - ptr++; - - while (*src) - *ptr++ = *src++; - *ptr = '\0'; - - return dst; -} - -static inline char * _dl_strcpy(char * dst,const char *src) -{ - register char *ptr = dst; - - while (*src) - *dst++ = *src++; - *dst = '\0'; - - return ptr; -} - -static inline int _dl_strcmp(const char * s1,const char * s2) -{ - register unsigned char c1, c2; - - do { - c1 = (unsigned char) *s1++; - c2 = (unsigned char) *s2++; - if (c1 == '\0') - return c1 - c2; - } - while (c1 == c2); - - return c1 - c2; -} - -static inline int _dl_strncmp(const char * s1,const char * s2,size_t len) -{ - register unsigned char c1 = '\0'; - register unsigned char c2 = '\0'; - - while (len > 0) { - c1 = (unsigned char) *s1++; - c2 = (unsigned char) *s2++; - if (c1 == '\0' || c1 != c2) - return c1 - c2; - len--; - } - - return c1 - c2; -} - -static inline char * _dl_strchr(const char * str,int c) -{ - register char ch; - - do { - if ((ch = *str) == c) - return (char *) str; - str++; - } - while (ch); - - return 0; -} - -static inline char *_dl_strrchr(const char *str, int c) -{ - register char *prev = 0; - register char *ptr = (char *) str; - - while (*ptr != '\0') { - if (*ptr == c) - prev = ptr; - ptr++; - } - if (c == '\0') - return(ptr); - return(prev); -} - - -static inline char *_dl_strstr(const char *s1, const char *s2) -{ - register const char *s = s1; - register const char *p = s2; - - do { - if (!*p) { - return (char *) s1;; - } - if (*p == *s) { - ++p; - ++s; - } else { - p = s2; - if (!*s) { - return NULL; - } - s = ++s1; - } - } while (1); -} - -static inline void * _dl_memcpy(void * dst, const void * src, size_t len) -{ - register char *a = dst; - register const char *b = src; - - while (len--) - *a++ = *b++; - - return dst; -} - - -static inline int _dl_memcmp(const void * s1,const void * s2,size_t len) -{ - unsigned char *c1 = (unsigned char *)s1; - unsigned char *c2 = (unsigned char *)s2; - - while (len--) { - if (*c1 != *c2) - return *c1 - *c2; - c1++; - c2++; - } - return 0; -} - -static inline void * _dl_memset(void * str,int c,size_t len) -{ - register char *a = str; - - while (len--) - *a++ = c; - - return str; -} - -static inline char *_dl_get_last_path_component(char *path) -{ - char *s; - register char *ptr = path; - register char *prev = 0; - - while (*ptr) - ptr++; - s = ptr - 1; - - /* strip trailing slashes */ - while (s != path && *s == '/') { - *s-- = '\0'; - } - - /* find last component */ - ptr = path; - while (*ptr != '\0') { - if (*ptr == '/') - prev = ptr; - ptr++; - } - s = prev; - - if (s == NULL || s[1] == '\0') - return path; - else - return s+1; -} - -/* Early on, we can't call printf, so use this to print out - * numbers using the SEND_STDERR() macro */ -static inline char *_dl_simple_ltoa(char * local, unsigned long i) -{ - /* 21 digits plus null terminator, good for 64-bit or smaller ints */ - char *p = &local[22]; - *p-- = '\0'; - do { - *p-- = '0' + i % 10; - i /= 10; - } while (i > 0); - return p + 1; -} - -static inline char *_dl_simple_ltoahex(char * local, unsigned long i) -{ - /* 21 digits plus null terminator, good for 64-bit or smaller ints */ - char *p = &local[22]; - *p-- = '\0'; - do { - char temp = i % 0x10; - if (temp <= 0x09) - *p-- = '0' + temp; - else - *p-- = 'a' - 0x0a + temp; - i /= 0x10; - } while (i > 0); - *p-- = 'x'; - *p-- = '0'; - return p + 1; -} - - -#if defined mc68000 || defined __arm__ || defined __mips__ || defined __sh__ -/* On some arches constant strings are referenced through the GOT. */ -/* XXX Requires load_addr to be defined. */ -#define SEND_STDERR(X) \ - { const char *__s = (X); \ - if (__s < (const char *) load_addr) __s += load_addr; \ - _dl_write (2, __s, _dl_strlen (__s)); \ - } -#else -#define SEND_STDERR(X) _dl_write(2, X, _dl_strlen(X)); -#endif - -#define SEND_ADDRESS_STDERR(X, add_a_newline) { \ - char tmp[22], *tmp1; \ - _dl_memset(tmp, 0, sizeof(tmp)); \ - tmp1=_dl_simple_ltoahex( tmp, (unsigned long)(X)); \ - _dl_write(2, tmp1, _dl_strlen(tmp1)); \ - if (add_a_newline) { \ - tmp[0]='\n'; \ - _dl_write(2, tmp, 1); \ - } \ -}; - -#define SEND_NUMBER_STDERR(X, add_a_newline) { \ - char tmp[22], *tmp1; \ - _dl_memset(tmp, 0, sizeof(tmp)); \ - tmp1=_dl_simple_ltoa( tmp, (unsigned long)(X)); \ - _dl_write(2, tmp1, _dl_strlen(tmp1)); \ - if (add_a_newline) { \ - tmp[0]='\n'; \ - _dl_write(2, tmp, 1); \ - } \ -}; - - -#endif diff --git a/ldso/ldso/ld_syscall.h b/ldso/ldso/ld_syscall.h deleted file mode 100644 index 23f4c0141..000000000 --- a/ldso/ldso/ld_syscall.h +++ /dev/null @@ -1,155 +0,0 @@ -/* Pull in compiler and arch stuff */ -#include -/* Pull in the arch specific type information */ -#include -/* Pull in the arch specific syscall implementation */ -#include "ld_syscalls.h" -/* For MAP_ANONYMOUS -- differs between platforms */ -#include -/* Pull in whatever this particular arch's kernel thinks the kernel version of - * struct stat should look like. It turns out that each arch has a different - * opinion on the subject, and different kernel revs use different names... */ -#define kernel_stat stat -#include - - -/* Encoding of the file mode. */ -#define S_IFMT 0170000 /* These bits determine file type. */ - -/* File types. */ -#define S_IFDIR 0040000 /* Directory. */ -#define S_IFCHR 0020000 /* Character device. */ -#define S_IFBLK 0060000 /* Block device. */ -#define S_IFREG 0100000 /* Regular file. */ -#define S_IFIFO 0010000 /* FIFO. */ -#define S_IFLNK 0120000 /* Symbolic link. */ -#define S_IFSOCK 0140000 /* Socket. */ - -/* Protection bits. */ - -#define S_ISUID 04000 /* Set user ID on execution. */ -#define S_ISGID 02000 /* Set group ID on execution. */ -#define S_ISVTX 01000 /* Save swapped text after use (sticky). */ -#define S_IREAD 0400 /* Read by owner. */ -#define S_IWRITE 0200 /* Write by owner. */ -#define S_IEXEC 0100 /* Execute by owner. */ - - -/* Here are the definitions for some syscalls that are used - by the dynamic linker. The idea is that we want to be able - to call these before the errno symbol is dynamicly linked, so - we use our own version here. Note that we cannot assume any - dynamic linking at all, so we cannot return any error codes. - We just punt if there is an error. */ - - -#define __NR__dl_exit __NR_exit -static inline _syscall1(void, _dl_exit, int, status); - - -#define __NR__dl_close __NR_close -static inline _syscall1(int, _dl_close, int, fd); - - -#if defined(__powerpc__) || defined(__mips__) || defined(__sh__) -/* PowerPC, MIPS and SuperH have a different calling convention for mmap(). */ -#define __NR__dl_mmap __NR_mmap -static inline _syscall6(void *, _dl_mmap, void *, start, size_t, length, - int, prot, int, flags, int, fd, off_t, offset); -#else -#define __NR__dl_mmap_real __NR_mmap -static inline _syscall1(void *, _dl_mmap_real, unsigned long *, buffer); - -static inline void * _dl_mmap(void * addr, unsigned long size, int prot, - int flags, int fd, unsigned long offset) -{ - unsigned long buffer[6]; - - buffer[0] = (unsigned long) addr; - buffer[1] = (unsigned long) size; - buffer[2] = (unsigned long) prot; - buffer[3] = (unsigned long) flags; - buffer[4] = (unsigned long) fd; - buffer[5] = (unsigned long) offset; - return (void *) _dl_mmap_real(buffer); -} -#endif - -#ifndef _dl_MAX_ERRNO -#define _dl_MAX_ERRNO 4096 -#endif -#define _dl_mmap_check_error(__res) \ - (((int)__res) < 0 && ((int)__res) >= -_dl_MAX_ERRNO) -#ifndef MAP_ANONYMOUS -#ifdef __sparc__ -#define MAP_ANONYMOUS 0x20 -#else -#error MAP_ANONYMOUS not defined and suplementary value not known -#endif -#endif - - -#define __NR__dl_open __NR_open -#define O_RDONLY 0x0000 -#define O_WRONLY 01 -#define O_RDWR 02 -#define O_CREAT 0100 /* not fcntl */ -static inline _syscall2(int, _dl_open, const char *, fn, int, flags); - -#define __NR__dl_write __NR_write -static inline _syscall3(unsigned long, _dl_write, int, fd, - const void *, buf, unsigned long, count); - - -#define __NR__dl_read __NR_read -static inline _syscall3(unsigned long, _dl_read, int, fd, - const void *, buf, unsigned long, count); - -#define __NR__dl_mprotect __NR_mprotect -static inline _syscall3(int, _dl_mprotect, const void *, addr, unsigned long, len, int, prot); - - - -#define __NR__dl_stat __NR_stat -static inline _syscall2(int, _dl_stat, const char *, file_name, struct stat *, buf); - - -#define __NR__dl_munmap __NR_munmap -static inline _syscall2(int, _dl_munmap, void *, start, unsigned long, length); - -#define __NR__dl_getuid __NR_getuid -static inline _syscall0(uid_t, _dl_getuid); - -#define __NR__dl_geteuid __NR_geteuid -static inline _syscall0(uid_t, _dl_geteuid); - -#define __NR__dl_getgid __NR_getgid -static inline _syscall0(gid_t, _dl_getgid); - -#define __NR__dl_getegid __NR_getegid -static inline _syscall0(gid_t, _dl_getegid); - -#define __NR__dl_getpid __NR_getpid -static inline _syscall0(gid_t, _dl_getpid); - -/* - * Not an actual syscall, but we need something in assembly to say whether - * this is OK or not. - */ -static inline int _dl_suid_ok(void) -{ - uid_t uid, euid, gid, egid; - - uid = _dl_getuid(); - euid = _dl_geteuid(); - gid = _dl_getgid(); - egid = _dl_getegid(); - - if(uid == euid && gid == egid) - return 1; - else - return 0; -} - -#define __NR__dl_readlink __NR_readlink -static inline _syscall3(int, _dl_readlink, const char *, path, char *, buf, size_t, bufsiz); diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c index 2c1d3e33c..7bfe24947 100644 --- a/ldso/ldso/ldso.c +++ b/ldso/ldso/ldso.c @@ -105,12 +105,8 @@ * application. */ -#include "ld_syscall.h" -#include "linuxelf.h" -#include "ld_hash.h" -#include "ld_string.h" -#include "dlfcn.h" -#include "../config.h" +#include "ldso.h" + #define ALLOW_ZERO_PLTGOT @@ -129,7 +125,7 @@ char *_dl_library_path = 0; /* Where we look for libraries */ char *_dl_preload = 0; /* Things to be loaded before the libs. */ char *_dl_ldsopath = 0; -static char *_dl_not_lazy = 0; +static int _dl_be_lazy = 1; #ifdef __SUPPORT_LD_DEBUG__ static char *_dl_debug = 0; static char *_dl_debug_symbols = 0; @@ -150,15 +146,15 @@ static int (*_dl_elf_init) (void); struct r_debug *_dl_debug_addr = NULL; unsigned long *_dl_brkp; unsigned long *_dl_envp; -int _dl_fixup(struct elf_resolve *tpnt); +int _dl_fixup(struct elf_resolve *tpnt, int lazy); void _dl_debug_state(void); char *_dl_get_last_path_component(char *path); static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *app_tpnt, unsigned long load_addr, unsigned long *hash_addr, Elf32_auxv_t auxvt[AT_EGID + 1], char **envp, struct r_debug *debug_addr); -#include "boot1_arch.h" -#include "ldso.h" /* Pull in the name of ld.so */ +#include "boot1_arch.h" +#include "_dl_progname.h" /* Pull in the value of _dl_progname */ /* When we enter this piece of code, the program stack looks like this: argc argument counter (integer) @@ -202,7 +198,7 @@ LD_BOOT(unsigned long args) unsigned long *got; unsigned long *aux_dat; int goof = 0; - elfhdr *header; + ElfW(Ehdr) *header; struct elf_resolve *tpnt; struct elf_resolve *app_tpnt; Elf32_auxv_t auxvt[AT_EGID + 1]; @@ -253,7 +249,7 @@ LD_BOOT(unsigned long args) /* locate the ELF header. We need this done as soon as possible * (esp since SEND_STDERR() needs this on some platforms... */ load_addr = auxvt[AT_BASE].a_un.a_val; - header = (elfhdr *) auxvt[AT_BASE].a_un.a_ptr; + header = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_ptr; /* Check the ELF header to make sure everything looks ok. */ if (!header || header->e_ident[EI_CLASS] != ELFCLASS32 || @@ -406,10 +402,10 @@ LD_BOOT(unsigned long args) } { - elf_phdr *ppnt; + ElfW(Phdr) *ppnt; int i; - ppnt = (elf_phdr *) auxvt[AT_PHDR].a_un.a_ptr; + ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr; for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) if (ppnt->p_type == PT_DYNAMIC) { dpnt = (Elf32_Dyn *) ppnt->p_vaddr; @@ -467,7 +463,7 @@ LD_BOOT(unsigned long args) protection back again once we are done */ { - elf_phdr *ppnt; + ElfW(Phdr) *ppnt; int i; #ifdef __SUPPORT_LD_DEBUG_EARLY__ @@ -476,8 +472,8 @@ LD_BOOT(unsigned long args) /* First cover the shared library/dynamic linker. */ if (tpnt->dynamic_info[DT_TEXTREL]) { - header = (elfhdr *) auxvt[AT_BASE].a_un.a_ptr; - ppnt = (elf_phdr *) ((int)auxvt[AT_BASE].a_un.a_ptr + + header = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_ptr; + ppnt = (ElfW(Phdr) *) ((int)auxvt[AT_BASE].a_un.a_ptr + header->e_phoff); for (i = 0; i < header->e_phnum; i++, ppnt++) { if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W)) { @@ -493,7 +489,7 @@ LD_BOOT(unsigned long args) #endif /* Now cover the application program. */ if (app_tpnt->dynamic_info[DT_TEXTREL]) { - ppnt = (elf_phdr *) auxvt[AT_PHDR].a_un.a_ptr; + ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr; for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) { if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W)) _dl_mprotect((void *) (ppnt->p_vaddr & PAGE_ALIGN), @@ -647,7 +643,7 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a unsigned long load_addr, unsigned long *hash_addr, Elf32_auxv_t auxvt[AT_EGID + 1], char **envp, struct r_debug *debug_addr) { - elf_phdr *ppnt; + ElfW(Phdr) *ppnt; char *lpntstr; int i, _dl_secure, goof = 0; struct dyn_elf *rpnt; @@ -685,13 +681,13 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a and load them properly. */ { - elfhdr *epnt; - elf_phdr *myppnt; + ElfW(Ehdr) *epnt; + ElfW(Phdr) *myppnt; int j; - epnt = (elfhdr *) auxvt[AT_BASE].a_un.a_ptr; + epnt = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_ptr; tpnt->n_phent = epnt->e_phnum; - tpnt->ppnt = myppnt = (elf_phdr *) (load_addr + epnt->e_phoff); + tpnt->ppnt = myppnt = (ElfW(Phdr) *) (load_addr + epnt->e_phoff); for (j = 0; j < epnt->e_phnum; j++, myppnt++) { if (myppnt->p_type == PT_DYNAMIC) { tpnt->dynamic_addr = myppnt->p_vaddr + load_addr; @@ -720,7 +716,7 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a and figure out which libraries are supposed to be called. Until we have this list, we will not be completely ready for dynamic linking */ - ppnt = (elf_phdr *) auxvt[AT_PHDR].a_un.a_ptr; + ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr; for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) { if (ppnt->p_type == PT_LOAD) { if (ppnt->p_vaddr + ppnt->p_memsz > brk_addr) @@ -751,7 +747,7 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a app_tpnt->dynamic_info, ppnt->p_vaddr, ppnt->p_filesz); #endif _dl_loaded_modules->libtype = elf_executable; - _dl_loaded_modules->ppnt = (elf_phdr *) auxvt[AT_PHDR].a_un.a_ptr; + _dl_loaded_modules->ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr; _dl_loaded_modules->n_phent = auxvt[AT_PHNUM].a_un.a_val; _dl_symbol_tables = rpnt = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf)); _dl_memset(rpnt, 0, sizeof(struct dyn_elf)); @@ -805,7 +801,8 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a /* Now we need to figure out what kind of options are selected. Note that for SUID programs we ignore the settings in LD_LIBRARY_PATH */ { - _dl_not_lazy = _dl_getenv("LD_BIND_NOW", envp); + if (_dl_getenv("LD_BIND_NOW", envp)) + _dl_be_lazy = 0; if ((auxvt[AT_UID].a_un.a_val == -1 && _dl_suid_ok()) || (auxvt[AT_UID].a_un.a_val != -1 && @@ -905,9 +902,7 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a libraries that should be loaded, and insert them on the list in the correct order. */ -#ifdef USE_CACHE _dl_map_cache(); -#endif if (_dl_preload) @@ -1124,9 +1119,7 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a } -#ifdef USE_CACHE _dl_unmap_cache(); -#endif /* * If the program interpreter is not in the module chain, add it. This will @@ -1187,7 +1180,7 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a * Now we go through and look for REL and RELA records that indicate fixups * to the GOT tables. We need to do this in reverse order so that COPY * directives work correctly */ - goof = _dl_loaded_modules ? _dl_fixup(_dl_loaded_modules) : 0; + goof = _dl_loaded_modules ? _dl_fixup(_dl_loaded_modules, _dl_be_lazy) : 0; /* Some flavors of SVr4 do not generate the R_*_COPY directive, @@ -1222,7 +1215,7 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a #ifndef FORCE_SHAREABLE_TEXT_SEGMENTS { unsigned int j; - elf_phdr *myppnt; + ElfW(Phdr) *myppnt; /* We had to set the protections of all pages to R/W for dynamic linking. Set text pages back to R/O */ @@ -1306,52 +1299,61 @@ void _dl_debug_state(void) { } -int _dl_fixup(struct elf_resolve *tpnt) +int _dl_fixup(struct elf_resolve *tpnt, int flag) { int goof = 0; if (tpnt->next) - goof += _dl_fixup(tpnt->next); + goof += _dl_fixup(tpnt->next, flag); #if defined (__SUPPORT_LD_DEBUG__) if(_dl_debug) _dl_dprintf(_dl_debug_file,"\nrelocation processing: %s", tpnt->libname); #endif if (tpnt->dynamic_info[DT_REL]) { #ifdef ELF_USES_RELOCA - _dl_dprintf(2, "%s: can't handle REL relocation records\n", - _dl_progname); - _dl_exit(17); +#if defined (__SUPPORT_LD_DEBUG__) + if(_dl_debug) _dl_dprintf(2, "%s: can't handle REL relocation records\n", _dl_progname); +#endif + goof++; + return goof; #else if (tpnt->init_flag & RELOCS_DONE) return goof; tpnt->init_flag |= RELOCS_DONE; - goof += _dl_parse_relocation_information(tpnt, tpnt->dynamic_info[DT_REL], + goof += _dl_parse_relocation_information(tpnt, + tpnt->dynamic_info[DT_REL], tpnt->dynamic_info[DT_RELSZ], 0); #endif } if (tpnt->dynamic_info[DT_RELA]) { -#ifdef ELF_USES_RELOCA +#ifndef ELF_USES_RELOCA +#if defined (__SUPPORT_LD_DEBUG__) + if(_dl_debug) _dl_dprintf(2, "%s: can't handle RELA relocation records\n", _dl_progname); +#endif + goof++; + return goof; +#else if (tpnt->init_flag & RELOCS_DONE) return goof; tpnt->init_flag |= RELOCS_DONE; - goof += _dl_parse_relocation_information(tpnt, tpnt->dynamic_info[DT_RELA], + goof += _dl_parse_relocation_information(tpnt, + tpnt->dynamic_info[DT_RELA], tpnt->dynamic_info[DT_RELASZ], 0); -#else - _dl_dprintf(2, "%s: can't handle RELA relocation records\n", - _dl_progname); - _dl_exit(18); #endif } if (tpnt->dynamic_info[DT_JMPREL]) { if (tpnt->init_flag & JMP_RELOCS_DONE) return goof; tpnt->init_flag |= JMP_RELOCS_DONE; - if (!_dl_not_lazy || *_dl_not_lazy == 0) - _dl_parse_lazy_relocation_information(tpnt, tpnt->dynamic_info[DT_JMPREL], + if (flag & RTLD_LAZY) { + _dl_parse_lazy_relocation_information(tpnt, + tpnt->dynamic_info[DT_JMPREL], tpnt->dynamic_info [DT_PLTRELSZ], 0); - else - goof += _dl_parse_relocation_information(tpnt, tpnt->dynamic_info[DT_JMPREL], + } else { + goof += _dl_parse_relocation_information(tpnt, + tpnt->dynamic_info[DT_JMPREL], tpnt->dynamic_info[DT_PLTRELSZ], 0); + } } #if defined (__SUPPORT_LD_DEBUG__) if(_dl_debug) { diff --git a/ldso/ldso/linuxelf.h b/ldso/ldso/linuxelf.h deleted file mode 100644 index aefc2f877..000000000 --- a/ldso/ldso/linuxelf.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef LINUXELF_H -#define LINUXELF_H - - -#include -#include "ld_sysdep.h" /* before elf.h to get ELF_USES_RELOCA right */ -#include - -/* Forward declarations for stuff defined in hash.h */ -struct dyn_elf; -struct elf_resolve; - - -/* Some function prototypes */ -extern int _dl_map_cache(void); -extern int _dl_unmap_cache(void); -int _dl_copy_fixups(struct dyn_elf * tpnt); -extern int _dl_parse_copy_information(struct dyn_elf *rpnt, - unsigned long rel_addr, unsigned long rel_size, int type); -extern void _dl_parse_lazy_relocation_information(struct elf_resolve *tpnt, - unsigned long rel_addr, unsigned long rel_size, int type); -extern int _dl_parse_relocation_information(struct elf_resolve *tpnt, - unsigned long rel_addr, unsigned long rel_size, int type); -extern struct elf_resolve * _dl_load_shared_library(int secure, - struct dyn_elf **rpnt, struct elf_resolve *tpnt, char *full_libname); -extern struct elf_resolve * _dl_load_elf_shared_library(int secure, - struct dyn_elf **rpnt, char *libname); -extern int _dl_linux_resolve(void); -#define ELF_CLASS ELFCLASS32 - - -#if ELF_CLASS == ELFCLASS32 - -#define elfhdr Elf32_Ehdr -#define elf_phdr Elf32_Phdr -#define elf_note Elf32_Nhdr -/* - * Datatype of a relocation on this platform - */ -#ifdef ELF_USES_RELOCA -# define ELF_RELOC Elf32_Rela -#else -# define ELF_RELOC Elf32_Rel -#endif - -#else - -#define elfhdr Elf64_Ehdr -#define elf_phdr Elf64_Phdr -#define elf_note Elf64_Nhdr -/* - * Datatype of a relocation on this platform - */ -#ifdef ELF_USES_RELOCA -# define ELF_RELOC Elf64_Rela -#else -# define ELF_RELOC Elf64_Rel -#endif - -#endif - - -/* Convert between the Linux flags for page protections and the - ones specified in the ELF standard. */ -#define LXFLAGS(X) ( (((X) & PF_R) ? PROT_READ : 0) | \ - (((X) & PF_W) ? PROT_WRITE : 0) | \ - (((X) & PF_X) ? PROT_EXEC : 0)) - -#endif /* LINUXELF_H */ diff --git a/ldso/ldso/readelflib1.c b/ldso/ldso/readelflib1.c index 0290d6ccf..dd3d9a293 100644 --- a/ldso/ldso/readelflib1.c +++ b/ldso/ldso/readelflib1.c @@ -4,7 +4,7 @@ * * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, * David Engel, Hongjiu Lu and Mitch D'Souza - * Copyright (C) 2001-2002, Erik Andersen + * Copyright (C) 2001-2003, Erik Andersen * * All rights reserved. * @@ -316,12 +316,12 @@ goof: struct elf_resolve *_dl_load_elf_shared_library(int secure, struct dyn_elf **rpnt, char *libname) { - elfhdr *epnt; + ElfW(Ehdr) *epnt; unsigned long dynamic_addr = 0; unsigned long dynamic_size = 0; Elf32_Dyn *dpnt; struct elf_resolve *tpnt; - elf_phdr *ppnt; + ElfW(Phdr) *ppnt; char *status; char header[4096]; unsigned long dynamic_info[24]; @@ -371,7 +371,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, } _dl_read(infile, header, sizeof(header)); - epnt = (elfhdr *) (intptr_t) header; + epnt = (ElfW(Ehdr) *) (intptr_t) header; if (epnt->e_ident[0] != 0x7f || epnt->e_ident[1] != 'E' || epnt->e_ident[2] != 'L' || @@ -398,7 +398,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, return NULL; }; - ppnt = (elf_phdr *)(intptr_t) & header[epnt->e_phoff]; + ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff]; piclib = 1; for (i = 0; i < epnt->e_phnum; i++) { @@ -446,7 +446,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, flags |= MAP_FIXED; /* Get the memory to store the library */ - ppnt = (elf_phdr *)(intptr_t) & header[epnt->e_phoff]; + ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff]; for (i = 0; i < epnt->e_phnum; i++) { if (ppnt->p_type == PT_LOAD) { @@ -577,7 +577,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, if (dynamic_info[DT_TEXTREL]) { #ifndef FORCE_SHAREABLE_TEXT_SEGMENTS - ppnt = (elf_phdr *)(intptr_t) & header[epnt->e_phoff]; + ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff]; for (i = 0; i < epnt->e_phnum; i++, ppnt++) { if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W)) _dl_mprotect((void *) ((piclib ? libaddr : 0) + @@ -594,7 +594,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, tpnt = _dl_add_elf_hash_table(libname, (char *) libaddr, dynamic_info, dynamic_addr, dynamic_size); - tpnt->ppnt = (elf_phdr *)(intptr_t) (tpnt->loadaddr + epnt->e_phoff); + tpnt->ppnt = (ElfW(Phdr) *)(intptr_t) (tpnt->loadaddr + epnt->e_phoff); tpnt->n_phent = epnt->e_phnum; /* diff --git a/ldso/libdl/Makefile b/ldso/libdl/Makefile index 1ac194400..12461d77e 100644 --- a/ldso/libdl/Makefile +++ b/ldso/libdl/Makefile @@ -21,9 +21,16 @@ TOPDIR=../../ include $(TOPDIR)Rules.mak -XXFLAGS+=-DUCLIBC_TARGET_PREFIX=\"$(TARGET_PREFIX)\" \ +XXFLAGS=$(XWARNINGS) $(OPTIMIZATION) $(XARCH_CFLAGS) $(CPU_CFLAGS) \ + -DUCLIBC_TARGET_PREFIX=\"$(TARGET_PREFIX)\" \ -DUCLIBC_DEVEL_PREFIX=\"$(DEVEL_PREFIX)\" \ - -DUCLIBC_BUILD_DIR=\"$(shell cd $(TOPDIR) && pwd)\" + -DUCLIBC_BUILD_DIR=\"$(shell cd $(TOPDIR) && pwd)\" \ + -fno-builtin -nostdinc -D_LIBC -I$(TOPDIR)ldso/include -I. -I$(TOPDIR)include +XXFLAGS+=$(shell $(CC) -print-search-dirs | sed -ne "s/install: *\(.*\)/-I\1include/gp") +XXFLAGS_NOPIC:=$(XXFLAGS) +ifeq ($(DOPIC),y) + XXFLAGS += $(PICFLAG) +endif ifeq ($(strip $(SUPPORT_LD_DEBUG)),y) XXFLAGS+=-D__SUPPORT_LD_DEBUG__ endif @@ -50,11 +57,11 @@ ar-target: $(OBJS) $(PIC_OBJS) dlib.o: dlib.c - $(CC) -I../ldso -I../ldso/$(TARGET_ARCH) $(CFLAGS_NOPIC) $(XXFLAGS) -c dlib.c -o dlib.o + $(CC) $(XXFLAGS_NOPIC) -c dlib.c -o dlib.o $(STRIPTOOL) -x -R .note -R .comment $*.o dlib_pic.o: dlib.c - $(CC) -I../ldso -I../ldso/$(TARGET_ARCH) $(CFLAGS) $(XXFLAGS) -c dlib.c -o dlib_pic.o + $(CC) $(XXFLAGS) -c dlib.c -o dlib_pic.o $(STRIPTOOL) -x -R .note -R .comment $*.o $(OBJ): Makefile diff --git a/ldso/libdl/dlfcn.h b/ldso/libdl/dlfcn.h deleted file mode 100644 index 620181173..000000000 --- a/ldso/libdl/dlfcn.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef DLFCN_H -#define DLFCN_H - -#include - -/* - * Various defines and so forth for the dynamic linker - */ - -/* For dlopen () */ -#define RTLD_LAZY 1 -#define RTLD_NOW 2 -#define RTLD_GLOBAL 0x100 - -/* For dlsym */ -#define RTLD_NEXT ((void *)-1) - -__BEGIN_DECLS - -/* The usual prototypes. We use void * instead of the actual - * datatype - the user does not manipulate the handles at all. - */ - -extern void * dlopen __P((__const char * __filename, int __flag)); -extern __const char * dlerror __P((void)); -extern void * dlsym __P((void *, __const char *)); -extern int dlclose __P((void *)); - -typedef struct -{ - const char * dli_fname; /* filename */ - void * dli_fbase; /* base address of object */ - const char * dli_sname; /* nearest symbol name */ - void * dli_saddr; /* nearest symbol address */ -} Dl_info; - -extern int dladdr __P((void * __address, Dl_info * __dlip )); - -__END_DECLS - -#endif diff --git a/ldso/libdl/dlib.c b/ldso/libdl/dlib.c index c2949c981..a15518230 100644 --- a/ldso/libdl/dlib.c +++ b/ldso/libdl/dlib.c @@ -4,27 +4,17 @@ * Functions required for dlopen et. al. */ -#include -#include -#include "dlfcn.h" -#include "linuxelf.h" -#include "ld_syscall.h" -#include "ld_hash.h" -#include "ld_string.h" +#include -extern struct r_debug *_dl_debug_addr; - -extern void *(*_dl_malloc_function) (size_t size); - -static int do_fixup(struct elf_resolve *tpnt, int flag); -static int do_dlclose(void *, int need_fini); +/* The public interfaces */ void *dlopen(const char *, int) __attribute__ ((__weak__, __alias__ ("_dlopen"))); -const char *dlerror(void) __attribute__ ((__weak__, __alias__ ("_dlerror"))); -void *dlsym(void *, const char *) __attribute__ ((__weak__, __alias__ ("_dlsym"))); int dlclose(void *) __attribute__ ((__weak__, __alias__ ("_dlclose"))); +void *dlsym(void *, const char *) __attribute__ ((__weak__, __alias__ ("_dlsym"))); +const char *dlerror(void) __attribute__ ((__weak__, __alias__ ("_dlerror"))); int dladdr(void *, Dl_info *) __attribute__ ((__weak__, __alias__ ("_dladdr"))); + #ifdef __PIC__ /* This is a real hack. We need access to the dynamic linker, but we also need to make it possible to link against this library without any @@ -43,10 +33,10 @@ extern char *_dl_find_hash(const char *, struct dyn_elf *, struct elf_resolve *, __attribute__ ((__weak__, __alias__ ("foobar"))); extern struct elf_resolve * _dl_load_shared_library(int, struct dyn_elf **, struct elf_resolve *, char *) __attribute__ ((__weak__, __alias__ ("foobar"))); -extern int _dl_parse_relocation_information(struct elf_resolve *, unsigned long, unsigned long, int) - __attribute__ ((__weak__, __alias__ ("foobar"))); -extern void _dl_parse_lazy_relocation_information(struct elf_resolve *, unsigned long, unsigned long, int) - __attribute__ ((__weak__, __alias__ ("foobar"))); +extern int _dl_fixup(struct elf_resolve *tpnt, int lazy) + __attribute__ ((__weak__, __alias__ ("foobar"))); +extern int _dl_copy_fixups(struct dyn_elf * tpnt) + __attribute__ ((__weak__, __alias__ ("foobar"))); #ifdef __mips__ extern void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt) __attribute__ ((__weak__, __alias__ ("foobar"))); @@ -62,6 +52,9 @@ extern struct elf_resolve *_dl_loaded_modules __attribute__ ((__weak__, __alias_ extern struct r_debug *_dl_debug_addr __attribute__ ((__weak__, __alias__ ("foobar1"))); extern unsigned long _dl_error_number __attribute__ ((__weak__, __alias__ ("foobar1"))); extern void *(*_dl_malloc_function)(size_t) __attribute__ ((__weak__, __alias__ ("foobar1"))); +#ifdef __SUPPORT_LD_DEBUG__ +#define _dl_debug_file 2 +#endif #else #ifdef __SUPPORT_LD_DEBUG__ static char *_dl_debug = 0; @@ -79,11 +72,16 @@ char *_dl_library_path = 0; char *_dl_ldsopath = 0; struct r_debug *_dl_debug_addr = NULL; static char *_dl_malloc_addr, *_dl_mmap_zero; -#include "../ldso/ldso.h" /* Pull in the name of ld.so */ +#include "../ldso/_dl_progname.h" /* Pull in the name of ld.so */ #include "../ldso/hash.c" #include "../ldso/readelflib1.c" +void *(*_dl_malloc_function) (size_t size); +int _dl_fixup(struct elf_resolve *tpnt, int lazy); #endif +static int do_dlclose(void *, int need_fini); + + static const char *dl_error_names[] = { "", "File not found", @@ -237,7 +235,7 @@ void *_dlopen(const char *libname, int flag) _dl_perform_mips_global_got_relocations(tpnt); #endif - if (do_fixup(tpnt, flag)) { + if (_dl_fixup(tpnt, (flag & RTLD_LAZY))) { _dl_error_number = LD_NO_SYMBOL; goto oops; } @@ -296,55 +294,6 @@ void *_dlopen(const char *libname, int flag) return NULL; } -static int do_fixup(struct elf_resolve *tpnt, int flag) -{ - int goof = 0; - - if (tpnt->next) - goof += do_fixup(tpnt->next, flag); - - if (tpnt->dynamic_info[DT_REL]) { -#ifdef ELF_USES_RELOCA - goof++; -#else - if (tpnt->init_flag & RELOCS_DONE) - return goof; - tpnt->init_flag |= RELOCS_DONE; - - goof += _dl_parse_relocation_information(tpnt, - tpnt->dynamic_info[DT_REL], tpnt->dynamic_info[DT_RELSZ], 0); -#endif - } - if (tpnt->dynamic_info[DT_RELA]) { -#ifdef ELF_USES_RELOCA - if (tpnt->init_flag & RELOCS_DONE) - return goof; - tpnt->init_flag |= RELOCS_DONE; - - goof += _dl_parse_relocation_information(tpnt, - tpnt->dynamic_info[DT_RELA], tpnt->dynamic_info[DT_RELASZ], 0); -#else - goof++; -#endif - } - if (tpnt->dynamic_info[DT_JMPREL]) { - if (tpnt->init_flag & JMP_RELOCS_DONE) - return goof; - tpnt->init_flag |= JMP_RELOCS_DONE; - - if (flag == RTLD_LAZY) { - _dl_parse_lazy_relocation_information(tpnt, - tpnt->dynamic_info[DT_JMPREL], - tpnt->dynamic_info[DT_PLTRELSZ], 0); - } else { - goof += _dl_parse_relocation_information(tpnt, - tpnt->dynamic_info[DT_JMPREL], - tpnt->dynamic_info[DT_PLTRELSZ], 0); - } - }; - return goof; -} - void *_dlsym(void *vhandle, const char *name) { struct elf_resolve *tpnt, *tfrom; @@ -408,7 +357,7 @@ static int do_dlclose(void *vhandle, int need_fini) { struct dyn_elf *rpnt, *rpnt1; struct dyn_elf *spnt, *spnt1; - elf_phdr *ppnt; + ElfW(Phdr) *ppnt; struct elf_resolve *tpnt; int (*dl_elf_fini) (void); void (*dl_brk) (void); diff --git a/ldso/libdl/libdl.c b/ldso/libdl/libdl.c index c2949c981..a15518230 100644 --- a/ldso/libdl/libdl.c +++ b/ldso/libdl/libdl.c @@ -4,27 +4,17 @@ * Functions required for dlopen et. al. */ -#include -#include -#include "dlfcn.h" -#include "linuxelf.h" -#include "ld_syscall.h" -#include "ld_hash.h" -#include "ld_string.h" +#include -extern struct r_debug *_dl_debug_addr; - -extern void *(*_dl_malloc_function) (size_t size); - -static int do_fixup(struct elf_resolve *tpnt, int flag); -static int do_dlclose(void *, int need_fini); +/* The public interfaces */ void *dlopen(const char *, int) __attribute__ ((__weak__, __alias__ ("_dlopen"))); -const char *dlerror(void) __attribute__ ((__weak__, __alias__ ("_dlerror"))); -void *dlsym(void *, const char *) __attribute__ ((__weak__, __alias__ ("_dlsym"))); int dlclose(void *) __attribute__ ((__weak__, __alias__ ("_dlclose"))); +void *dlsym(void *, const char *) __attribute__ ((__weak__, __alias__ ("_dlsym"))); +const char *dlerror(void) __attribute__ ((__weak__, __alias__ ("_dlerror"))); int dladdr(void *, Dl_info *) __attribute__ ((__weak__, __alias__ ("_dladdr"))); + #ifdef __PIC__ /* This is a real hack. We need access to the dynamic linker, but we also need to make it possible to link against this library without any @@ -43,10 +33,10 @@ extern char *_dl_find_hash(const char *, struct dyn_elf *, struct elf_resolve *, __attribute__ ((__weak__, __alias__ ("foobar"))); extern struct elf_resolve * _dl_load_shared_library(int, struct dyn_elf **, struct elf_resolve *, char *) __attribute__ ((__weak__, __alias__ ("foobar"))); -extern int _dl_parse_relocation_information(struct elf_resolve *, unsigned long, unsigned long, int) - __attribute__ ((__weak__, __alias__ ("foobar"))); -extern void _dl_parse_lazy_relocation_information(struct elf_resolve *, unsigned long, unsigned long, int) - __attribute__ ((__weak__, __alias__ ("foobar"))); +extern int _dl_fixup(struct elf_resolve *tpnt, int lazy) + __attribute__ ((__weak__, __alias__ ("foobar"))); +extern int _dl_copy_fixups(struct dyn_elf * tpnt) + __attribute__ ((__weak__, __alias__ ("foobar"))); #ifdef __mips__ extern void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt) __attribute__ ((__weak__, __alias__ ("foobar"))); @@ -62,6 +52,9 @@ extern struct elf_resolve *_dl_loaded_modules __attribute__ ((__weak__, __alias_ extern struct r_debug *_dl_debug_addr __attribute__ ((__weak__, __alias__ ("foobar1"))); extern unsigned long _dl_error_number __attribute__ ((__weak__, __alias__ ("foobar1"))); extern void *(*_dl_malloc_function)(size_t) __attribute__ ((__weak__, __alias__ ("foobar1"))); +#ifdef __SUPPORT_LD_DEBUG__ +#define _dl_debug_file 2 +#endif #else #ifdef __SUPPORT_LD_DEBUG__ static char *_dl_debug = 0; @@ -79,11 +72,16 @@ char *_dl_library_path = 0; char *_dl_ldsopath = 0; struct r_debug *_dl_debug_addr = NULL; static char *_dl_malloc_addr, *_dl_mmap_zero; -#include "../ldso/ldso.h" /* Pull in the name of ld.so */ +#include "../ldso/_dl_progname.h" /* Pull in the name of ld.so */ #include "../ldso/hash.c" #include "../ldso/readelflib1.c" +void *(*_dl_malloc_function) (size_t size); +int _dl_fixup(struct elf_resolve *tpnt, int lazy); #endif +static int do_dlclose(void *, int need_fini); + + static const char *dl_error_names[] = { "", "File not found", @@ -237,7 +235,7 @@ void *_dlopen(const char *libname, int flag) _dl_perform_mips_global_got_relocations(tpnt); #endif - if (do_fixup(tpnt, flag)) { + if (_dl_fixup(tpnt, (flag & RTLD_LAZY))) { _dl_error_number = LD_NO_SYMBOL; goto oops; } @@ -296,55 +294,6 @@ void *_dlopen(const char *libname, int flag) return NULL; } -static int do_fixup(struct elf_resolve *tpnt, int flag) -{ - int goof = 0; - - if (tpnt->next) - goof += do_fixup(tpnt->next, flag); - - if (tpnt->dynamic_info[DT_REL]) { -#ifdef ELF_USES_RELOCA - goof++; -#else - if (tpnt->init_flag & RELOCS_DONE) - return goof; - tpnt->init_flag |= RELOCS_DONE; - - goof += _dl_parse_relocation_information(tpnt, - tpnt->dynamic_info[DT_REL], tpnt->dynamic_info[DT_RELSZ], 0); -#endif - } - if (tpnt->dynamic_info[DT_RELA]) { -#ifdef ELF_USES_RELOCA - if (tpnt->init_flag & RELOCS_DONE) - return goof; - tpnt->init_flag |= RELOCS_DONE; - - goof += _dl_parse_relocation_information(tpnt, - tpnt->dynamic_info[DT_RELA], tpnt->dynamic_info[DT_RELASZ], 0); -#else - goof++; -#endif - } - if (tpnt->dynamic_info[DT_JMPREL]) { - if (tpnt->init_flag & JMP_RELOCS_DONE) - return goof; - tpnt->init_flag |= JMP_RELOCS_DONE; - - if (flag == RTLD_LAZY) { - _dl_parse_lazy_relocation_information(tpnt, - tpnt->dynamic_info[DT_JMPREL], - tpnt->dynamic_info[DT_PLTRELSZ], 0); - } else { - goof += _dl_parse_relocation_information(tpnt, - tpnt->dynamic_info[DT_JMPREL], - tpnt->dynamic_info[DT_PLTRELSZ], 0); - } - }; - return goof; -} - void *_dlsym(void *vhandle, const char *name) { struct elf_resolve *tpnt, *tfrom; @@ -408,7 +357,7 @@ static int do_dlclose(void *vhandle, int need_fini) { struct dyn_elf *rpnt, *rpnt1; struct dyn_elf *spnt, *spnt1; - elf_phdr *ppnt; + ElfW(Phdr) *ppnt; struct elf_resolve *tpnt; int (*dl_elf_fini) (void); void (*dl_brk) (void); diff --git a/ldso/util/Makefile b/ldso/util/Makefile index b7712f82a..482fed3ce 100644 --- a/ldso/util/Makefile +++ b/ldso/util/Makefile @@ -24,7 +24,7 @@ TOPDIR=../../ include $(TOPDIR)Rules.mak TARGET_CC = $(TOPDIR)extra/gcc-uClibc/$(TARGET_ARCH)-uclibc-gcc -TARGETS = elf_header ldd +TARGETS = ldd ifeq ($(OSTYPE),linux) TARGETS += readelf endif @@ -37,9 +37,6 @@ ifeq ($(strip $(LDSO_LDD_SUPPORT)),y) XXFLAGS=-D__LDSO_LDD_SUPPORT endif -elf_header: - ln -fs $(TOPDIR)include/elf.h - readelf: readelf.c $(HOSTCC) $(HOSTCFLAGS) -I . readelf.c -o $@ strip -x -R .note -R .comment $@ @@ -78,5 +75,5 @@ ldd.target: ldd.c $(STRIPTOOL) -x -R .note -R .comment $@ clean: - rm -f $(TARGETS) *.o *~ core ./elf.h *.target + rm -f $(TARGETS) *.o *~ core *.target diff --git a/ldso/util/ldconfig.c b/ldso/util/ldconfig.c index 4660bd458..f90cb073f 100644 --- a/ldso/util/ldconfig.c +++ b/ldso/util/ldconfig.c @@ -37,8 +37,7 @@ #include #include #include -#include "elf.h" -#include "../config.h" +#include #include "readsoname.h" struct exec @@ -546,6 +545,7 @@ void usage(void) exit(EXIT_FATAL); } +#define DIR_SEP ":, \t\n" int main(int argc, char **argv) { int i, c; -- cgit v1.2.3