diff options
author | Eric Andersen <andersen@codepoet.org> | 2003-08-19 06:05:34 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2003-08-19 06:05:34 +0000 |
commit | bca6a155c79147f706242ed7c590a3538e407a40 (patch) | |
tree | 17c7d7784edc61f3984fb3255672f3ecfe826d22 /ldso/ldso | |
parent | fd47fd4039cadf42620bbfce43c3a0338e23ee26 (diff) |
Phase one of my evil plan to clean up ld.so...
Diffstat (limited to 'ldso/ldso')
-rw-r--r-- | ldso/ldso/.cvsignore | 2 | ||||
-rw-r--r-- | ldso/ldso/Makefile | 25 | ||||
-rw-r--r-- | ldso/ldso/dl-elf.c | 16 | ||||
-rw-r--r-- | ldso/ldso/ld_hash.h | 151 | ||||
-rw-r--r-- | ldso/ldso/ld_string.h | 283 | ||||
-rw-r--r-- | ldso/ldso/ld_syscall.h | 155 | ||||
-rw-r--r-- | ldso/ldso/ldso.c | 98 | ||||
-rw-r--r-- | ldso/ldso/linuxelf.h | 69 | ||||
-rw-r--r-- | ldso/ldso/readelflib1.c | 16 |
9 files changed, 80 insertions, 735 deletions
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 <sys/types.h> /* 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 <stdarg.h> -/* Pull in the arch specific type information */ -#include <sys/types.h> -/* Pull in the arch specific syscall implementation */ -#include "ld_syscalls.h" -/* For MAP_ANONYMOUS -- differs between platforms */ -#include <asm/mman.h> -/* 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 <bits/kernel_stat.h> - - -/* 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 <sys/types.h> -#include "ld_sysdep.h" /* before elf.h to get ELF_USES_RELOCA right */ -#include <elf.h> - -/* 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; /* |