diff options
-rw-r--r-- | ldso/include/dl-hash.h | 15 | ||||
-rw-r--r-- | ldso/include/dl-syscall.h | 47 | ||||
-rw-r--r-- | ldso/include/ldso.h | 23 | ||||
-rw-r--r-- | ldso/include/unsecvars.h | 4 | ||||
-rw-r--r-- | ldso/ldso/dl-hash.c | 135 | ||||
-rw-r--r-- | ldso/ldso/dl-startup.c | 4 | ||||
-rw-r--r-- | ldso/ldso/dl-tls.c | 2 | ||||
-rw-r--r-- | ldso/ldso/ldso.c | 35 | ||||
-rw-r--r-- | ldso/ldso/sh/dl-syscalls.h | 8 | ||||
-rw-r--r-- | ldso/ldso/sh/elfinterp.c | 4 | ||||
-rw-r--r-- | ldso/libdl/Makefile.in | 3 | ||||
-rw-r--r-- | ldso/libdl/libdl.c | 58 |
12 files changed, 192 insertions, 146 deletions
diff --git a/ldso/include/dl-hash.h b/ldso/include/dl-hash.h index 758767f4d..81d6d3f3e 100644 --- a/ldso/include/dl-hash.h +++ b/ldso/include/dl-hash.h @@ -66,7 +66,7 @@ struct elf_resolve { unsigned short int init_flag; unsigned long rtld_flags; /* RTLD_GLOBAL, RTLD_NOW etc. */ Elf_Symndx nbucket; - + #ifdef __LDSO_GNU_HASH_SUPPORT__ /* Data needed to support GNU hash style */ Elf32_Word l_gnu_bitmask_idxbits; @@ -81,7 +81,7 @@ struct elf_resolve { #else Elf_Symndx *elf_buckets; #endif - + struct init_fini_list *init_fini; struct init_fini_list *rtld_local; /* keep tack of RTLD_LOCAL libs in same group */ /* @@ -95,10 +95,9 @@ struct elf_resolve { const Elf32_Word *l_gnu_buckets; const Elf_Symndx *chains; }; -#else +#else Elf_Symndx *chains; -#endif - +#endif unsigned long dynamic_info[DYNAMIC_SIZE]; unsigned long n_phent; @@ -148,7 +147,6 @@ static __always_inline char *_dl_find_hash(const char *name, struct dyn_elf *rpn #endif } - extern int _dl_linux_dynamic_link(void); extern char * _dl_library_path; @@ -156,12 +154,11 @@ extern char * _dl_not_lazy; static inline int _dl_symbol(char * name) { - if(name[0] != '_' || name[1] != 'd' || name[2] != 'l' || name[3] != '_') + 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 @@ -177,5 +174,3 @@ static inline int _dl_symbol(char * name) #endif /* _LD_HASH_H_ */ - - diff --git a/ldso/include/dl-syscall.h b/ldso/include/dl-syscall.h index 5b85fd230..d017866eb 100644 --- a/ldso/include/dl-syscall.h +++ b/ldso/include/dl-syscall.h @@ -11,11 +11,16 @@ /* Pull in the arch specific syscall implementation */ #include <dl-syscalls.h> /* For MAP_ANONYMOUS -- differs between platforms */ -#include <asm/mman.h> +#define _SYS_MMAN_H 1 +#include <bits/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... */ +#if defined(__sparc_v9__) && (__WORDSIZE == 64) +#define kernel_stat64 stat +#else #define kernel_stat stat +#endif #include <bits/kernel_stat.h> #include <bits/kernel_types.h> @@ -54,69 +59,69 @@ 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); +static __always_inline _syscall1(void, _dl_exit, int, status); #define __NR__dl_close __NR_close -static inline _syscall1(int, _dl_close, int, fd); +static __always_inline _syscall1(int, _dl_close, int, fd); #define __NR__dl_open __NR_open -static inline _syscall3(int, _dl_open, const char *, fn, int, flags, +static __always_inline _syscall3(int, _dl_open, const char *, fn, int, flags, __kernel_mode_t, mode); #define __NR__dl_write __NR_write -static inline _syscall3(unsigned long, _dl_write, int, fd, +static __always_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, +static __always_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, +static __always_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, +static __always_inline _syscall2(int, _dl_stat, const char *, file_name, struct stat *, buf); #define __NR__dl_fstat __NR_fstat -static inline _syscall2(int, _dl_fstat, int, fd, struct stat *, buf); +static __always_inline _syscall2(int, _dl_fstat, int, fd, struct stat *, buf); #define __NR__dl_munmap __NR_munmap -static inline _syscall2(int, _dl_munmap, void *, start, unsigned long, length); +static __always_inline _syscall2(int, _dl_munmap, void *, start, unsigned long, length); #ifdef __NR_getxuid # define __NR_getuid __NR_getxuid #endif #define __NR__dl_getuid __NR_getuid -static inline _syscall0(uid_t, _dl_getuid); +static __always_inline _syscall0(uid_t, _dl_getuid); #ifndef __NR_geteuid # define __NR_geteuid __NR_getuid #endif #define __NR__dl_geteuid __NR_geteuid -static inline _syscall0(uid_t, _dl_geteuid); +static __always_inline _syscall0(uid_t, _dl_geteuid); #ifdef __NR_getxgid # define __NR_getgid __NR_getxgid #endif #define __NR__dl_getgid __NR_getgid -static inline _syscall0(gid_t, _dl_getgid); +static __always_inline _syscall0(gid_t, _dl_getgid); #ifndef __NR_getegid # define __NR_getegid __NR_getgid #endif #define __NR__dl_getegid __NR_getegid -static inline _syscall0(gid_t, _dl_getegid); +static __always_inline _syscall0(gid_t, _dl_getegid); #ifdef __NR_getxpid # define __NR_getpid __NR_getxpid #endif #define __NR__dl_getpid __NR_getpid -static inline _syscall0(gid_t, _dl_getpid); +static __always_inline _syscall0(gid_t, _dl_getpid); #define __NR__dl_readlink __NR_readlink -static inline _syscall3(int, _dl_readlink, const char *, path, char *, buf, +static __always_inline _syscall3(int, _dl_readlink, const char *, path, char *, buf, size_t, bufsiz); #ifdef __UCLIBC_HAS_SSP__ @@ -145,14 +150,14 @@ static inline _syscall2(int, _dl_gettimeofday, struct timeval *, tv, #if defined(__UCLIBC_MMAP_HAS_6_ARGS__) && defined(__NR_mmap) # define __NR__dl_mmap __NR_mmap -static inline _syscall6(void *, _dl_mmap, void *, start, size_t, length, +static __always_inline _syscall6(void *, _dl_mmap, void *, start, size_t, length, int, prot, int, flags, int, fd, off_t, offset); /* then try mmap2() */ #elif defined(__NR_mmap2) # define __NR___syscall_mmap2 __NR_mmap2 -static inline _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr, size_t, len, +static __always_inline _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr, size_t, len, int, prot, int, flags, int, fd, off_t, offset); /* Some architectures always use 12 as page shift for mmap2() eventhough the @@ -163,7 +168,7 @@ static inline _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr, size_t, len, # define MMAP2_PAGE_SHIFT 12 #endif -static inline void * _dl_mmap(void * addr, unsigned long size, int prot, +static __always_inline void * _dl_mmap(void * addr, unsigned long size, int prot, int flags, int fd, unsigned long offset) { if (offset & ((1 << MMAP2_PAGE_SHIFT) - 1)) @@ -176,8 +181,8 @@ static inline void * _dl_mmap(void * addr, unsigned long size, int prot, #elif defined(__NR_mmap) # 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, +static __always_inline _syscall1(void *, _dl_mmap_real, unsigned long *, buffer); +static __always_inline void * _dl_mmap(void * addr, unsigned long size, int prot, int flags, int fd, unsigned long offset) { unsigned long buffer[6]; diff --git a/ldso/include/ldso.h b/ldso/include/ldso.h index 1e26b8022..3c0be40a3 100644 --- a/ldso/include/ldso.h +++ b/ldso/include/ldso.h @@ -11,7 +11,7 @@ #include <features.h> /* Prepare for the case that `__builtin_expect' is not available. */ -#if __GNUC__ == 2 && __GNUC_MINOR__ < 96 +#if defined __GNUC__ && __GNUC__ == 2 && __GNUC_MINOR__ < 96 #define __builtin_expect(x, expected_value) (x) #endif #ifndef likely @@ -70,19 +70,28 @@ extern int _dl_debug_file; _dl_dprintf(_dl_debug_file, "%s:%i: " fmt, __FUNCTION__, __LINE__, ## args); # define _dl_if_debug_dprint(fmt, args...) \ do { if (_dl_debug) __dl_debug_dprint(fmt, ## args); } while (0) -# define _dl_assert(expr) \ +#else +# define __dl_debug_dprint(fmt, args...) +# define _dl_if_debug_dprint(fmt, args...) +# define _dl_debug_file 2 +#endif /* __SUPPORT_LD_DEBUG__ */ + +#ifdef IS_IN_rtld +# ifdef __SUPPORT_LD_DEBUG__ +# define _dl_assert(expr) \ do { \ if (!(expr)) { \ __dl_debug_dprint("assert(%s)\n", #expr); \ _dl_exit(45); \ } \ } while (0) +# else +# define _dl_assert(expr) ((void)0) +# endif #else -# define __dl_debug_dprint(fmt, args...) -# define _dl_if_debug_dprint(fmt, args...) -# define _dl_assert(expr) -# define _dl_debug_file 2 -#endif /* __SUPPORT_LD_DEBUG__ */ +# include <assert.h> +# define _dl_assert(expr) assert(expr) +#endif #ifdef __SUPPORT_LD_DEBUG_EARLY__ # define _dl_debug_early(fmt, args...) __dl_debug_dprint(fmt, ## args) diff --git a/ldso/include/unsecvars.h b/ldso/include/unsecvars.h index 0ce3ebfea..f1ef381ee 100644 --- a/ldso/include/unsecvars.h +++ b/ldso/include/unsecvars.h @@ -5,7 +5,7 @@ * GNU Lesser General Public License version 2.1 or later. */ -/* +/* * Environment variable to be removed for SUID programs. The names are all * stuffed in a single string which means they have to be terminated with a * '\0' explicitly. @@ -19,7 +19,7 @@ "LD_TRACE_LOADED_OBJECTS\0" \ "TMPDIR\0" -/* +/* * LD_TRACE_LOADED_OBJECTS is not in glibc-2.3.5's unsecvars.h * though used by ldd * diff --git a/ldso/ldso/dl-hash.c b/ldso/ldso/dl-hash.c index ff4f22a6f..5ac47ecfc 100644 --- a/ldso/ldso/dl-hash.c +++ b/ldso/ldso/dl-hash.c @@ -4,7 +4,7 @@ * after resolving ELF shared library symbols * * Copyright (C) 2004 by Joakim Tjernlund <joakim.tjernlund@lumentis.se> - * Copyright (C) 2000-2004 by Erik Andersen <andersen@codepoet.org> + * Copyright (C) 2000-2006 by Erik Andersen <andersen@codepoet.org> * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, * David Engel, Hongjiu Lu and Mitch D'Souza * @@ -114,33 +114,32 @@ struct elf_resolve *_dl_add_elf_hash_table(const char *libname, _dl_memset(tpnt->next, 0, sizeof(struct elf_resolve)); tpnt->next->prev = tpnt; tpnt = tpnt->next; - }; + } tpnt->next = NULL; tpnt->init_flag = 0; tpnt->libname = _dl_strdup(libname); tpnt->dynamic_addr = (ElfW(Dyn) *)dynamic_addr; tpnt->libtype = loaded_file; - + #ifdef __LDSO_GNU_HASH_SUPPORT__ if (dynamic_info[DT_GNU_HASH_IDX] != 0) { - - Elf32_Word *hash32 = (Elf_Symndx*)dynamic_info[DT_GNU_HASH_IDX]; - - tpnt->nbucket = *hash32++; - Elf32_Word symbias = *hash32++; - Elf32_Word bitmask_nwords = *hash32++; - /* Must be a power of two. */ - _dl_assert ((bitmask_nwords & (bitmask_nwords - 1)) == 0); - tpnt->l_gnu_bitmask_idxbits = bitmask_nwords - 1; - tpnt->l_gnu_shift = *hash32++; - - tpnt->l_gnu_bitmask = (ElfW(Addr) *) hash32; - hash32 += __ELF_NATIVE_CLASS / 32 * bitmask_nwords; - - tpnt->l_gnu_buckets = hash32; - hash32 += tpnt->nbucket; - tpnt->l_gnu_chain_zero = hash32 - symbias; + Elf32_Word *hash32 = (Elf_Symndx*)dynamic_info[DT_GNU_HASH_IDX]; + + tpnt->nbucket = *hash32++; + Elf32_Word symbias = *hash32++; + Elf32_Word bitmask_nwords = *hash32++; + /* Must be a power of two. */ + _dl_assert ((bitmask_nwords & (bitmask_nwords - 1)) == 0); + tpnt->l_gnu_bitmask_idxbits = bitmask_nwords - 1; + tpnt->l_gnu_shift = *hash32++; + + tpnt->l_gnu_bitmask = (ElfW(Addr) *) hash32; + hash32 += __ELF_NATIVE_CLASS / 32 * bitmask_nwords; + + tpnt->l_gnu_buckets = hash32; + hash32 += tpnt->nbucket; + tpnt->l_gnu_chain_zero = hash32 - symbias; } else /* Fall using old SysV hash table if GNU hash is not present */ #endif @@ -162,7 +161,8 @@ struct elf_resolve *_dl_add_elf_hash_table(const char *libname, /* Routine to check whether the symbol matches. */ static __attribute_noinline__ const ElfW(Sym) * -check_match (const ElfW(Sym) *sym, char *strtab, const char* undef_name, int type_class) { +check_match (const ElfW(Sym) *sym, char *strtab, const char* undef_name, int type_class) +{ #if USE_TLS if((sym->st_value == 0 && (ELF_ST_TYPE(sym->st_info) != STT_TLS)) @@ -182,48 +182,49 @@ check_match (const ElfW(Sym) *sym, char *strtab, const char* undef_name, int typ if (type_class & (sym->st_shndx == SHN_UNDEF)) /* undefined symbol itself */ return NULL; - + if (sym->st_value == 0) /* No value */ return NULL; - - if (ELF_ST_TYPE(sym->st_info) > STT_FUNC) - /* Ignore all but STT_NOTYPE, STT_OBJECT and STT_FUNC - * entries since these are no code/data definitions. - */ - return NULL; + + if (ELF_ST_TYPE(sym->st_info) > STT_FUNC + && ELF_ST_TYPE(sym->st_info) != STT_COMMON) + /* Ignore all but STT_NOTYPE, STT_OBJECT, STT_FUNC + * and STT_COMMON entries since these are no + * code/data definitions + */ + return NULL; #endif - if (_dl_strcmp(strtab + sym->st_name, undef_name) != 0) - return NULL; + if (_dl_strcmp(strtab + sym->st_name, undef_name) != 0) + return NULL; - /* This is the matching symbol */ - return sym; + /* This is the matching symbol */ + return sym; } #ifdef __LDSO_GNU_HASH_SUPPORT__ -static __always_inline const ElfW(Sym) * -_dl_lookup_gnu_hash(struct elf_resolve *tpnt, ElfW(Sym) *symtab, unsigned long hash, - const char* undef_name, int type_class) { - +static __always_inline const ElfW(Sym) * +_dl_lookup_gnu_hash(struct elf_resolve *tpnt, ElfW(Sym) *symtab, unsigned long hash, + const char* undef_name, int type_class) +{ Elf_Symndx symidx; const ElfW(Sym) *sym; char *strtab; - + const ElfW(Addr) *bitmask = tpnt->l_gnu_bitmask; - ElfW(Addr) bitmask_word = bitmask[(hash / __ELF_NATIVE_CLASS) & tpnt->l_gnu_bitmask_idxbits]; + ElfW(Addr) bitmask_word = bitmask[(hash / __ELF_NATIVE_CLASS) & tpnt->l_gnu_bitmask_idxbits]; unsigned int hashbit1 = hash & (__ELF_NATIVE_CLASS - 1); unsigned int hashbit2 = ((hash >> tpnt->l_gnu_shift) & (__ELF_NATIVE_CLASS - 1)); _dl_assert (bitmask != NULL); - if (__builtin_expect ((bitmask_word >> hashbit1) & (bitmask_word >> hashbit2) & 1, 0)) { - + if (unlikely((bitmask_word >> hashbit1) & (bitmask_word >> hashbit2) & 1)) { Elf32_Word bucket = tpnt->l_gnu_buckets[hash % tpnt->nbucket]; - + if (bucket != 0) { const Elf32_Word *hasharr = &tpnt->l_gnu_chain_zero[bucket]; do { @@ -242,20 +243,20 @@ _dl_lookup_gnu_hash(struct elf_resolve *tpnt, ElfW(Sym) *symtab, unsigned long h } #endif -static __always_inline const ElfW(Sym) * -_dl_lookup_sysv_hash(struct elf_resolve *tpnt, ElfW(Sym) *symtab, unsigned long hash, const char* undef_name, int type_class) { - +static __always_inline const ElfW(Sym) * +_dl_lookup_sysv_hash(struct elf_resolve *tpnt, ElfW(Sym) *symtab, unsigned long hash, const char* undef_name, int type_class) +{ unsigned long hn; char *strtab; const ElfW(Sym) *sym; Elf_Symndx symidx; - + /* Avoid calling .urem here. */ do_rem(hn, hash, tpnt->nbucket); strtab = (char *) (tpnt->dynamic_info[DT_STRTAB]); - + _dl_assert(tpnt->elf_buckets != NULL); - + for (symidx = tpnt->elf_buckets[hn]; symidx != STN_UNDEF; symidx = tpnt->chains[symidx]) { sym = check_match (&symtab[symidx], strtab, undef_name, type_class); if (sym != NULL) @@ -264,7 +265,7 @@ _dl_lookup_sysv_hash(struct elf_resolve *tpnt, ElfW(Sym) *symtab, unsigned long } /* No symbol found into the current module*/ return NULL; -} +} /* * This function resolves externals, and this is either called when we process @@ -287,7 +288,7 @@ char *_dl_lookup_hash(const char *name, struct dyn_elf *rpnt, struct elf_resolve #ifdef __LDSO_GNU_HASH_SUPPORT__ unsigned long gnu_hash_number = _dl_gnu_hash((const unsigned char *)name); #endif - + for (; rpnt; rpnt = rpnt->next) { tpnt = rpnt->dyn; @@ -308,36 +309,37 @@ char *_dl_lookup_hash(const char *name, struct dyn_elf *rpnt, struct elf_resolve /* Don't search the executable when resolving a copy reloc. */ if ((type_class & ELF_RTYPE_CLASS_COPY) && tpnt->libtype == elf_executable) continue; - + /* If the hash table is empty there is nothing to do here. */ if (tpnt->nbucket == 0) continue; - - symtab = (ElfW(Sym) *) (intptr_t) (tpnt->dynamic_info[DT_SYMTAB]); - + + symtab = (ElfW(Sym) *) (intptr_t) (tpnt->dynamic_info[DT_SYMTAB]); + #ifdef __LDSO_GNU_HASH_SUPPORT__ /* Prefer GNU hash style, if any */ - if(tpnt->l_gnu_bitmask) { - if((sym = _dl_lookup_gnu_hash(tpnt, symtab, gnu_hash_number, name, type_class)) != NULL) + if (tpnt->l_gnu_bitmask) { + sym = _dl_lookup_gnu_hash(tpnt, symtab, gnu_hash_number, name, type_class); + if (sym != NULL) /* If sym has been found, do not search further */ - break; + break; } else { -#endif +#endif /* Use the old SysV-style hash table */ - + /* Calculate the old sysv hash number only once */ - if(elf_hash_number == 0xffffffff) + if (elf_hash_number == 0xffffffff) elf_hash_number = _dl_elf_hash((const unsigned char *)name); - - if((sym = _dl_lookup_sysv_hash(tpnt, symtab, elf_hash_number, name, type_class)) != NULL ) - break; -#ifdef __LDSO_GNU_HASH_SUPPORT__ + sym = _dl_lookup_sysv_hash(tpnt, symtab, elf_hash_number, name, type_class); + if (sym != NULL) + break; +#ifdef __LDSO_GNU_HASH_SUPPORT__ } -#endif +#endif } /* end of for (; rpnt; rpnt = rpnt->next) { */ - - if(sym) { + + if (sym) { /* At this point we have found the requested symbol, do binding */ #if USE_TLS if(ELF_ST_TYPE(sym->st_info) == STT_TLS) { @@ -356,7 +358,6 @@ char *_dl_lookup_hash(const char *name, struct dyn_elf *rpnt, struct elf_resolve if (!weak_result) weak_result = (char *)tpnt->loadaddr + sym->st_value; break; - #endif case STB_GLOBAL: return (char*)tpnt->loadaddr + sym->st_value; diff --git a/ldso/ldso/dl-startup.c b/ldso/ldso/dl-startup.c index 040d481fd..9fe8e06d3 100644 --- a/ldso/ldso/dl-startup.c +++ b/ldso/ldso/dl-startup.c @@ -4,7 +4,7 @@ * after resolving ELF shared library symbols * * Copyright (C) 2005 by Joakim Tjernlund - * Copyright (C) 2000-2004 by Erik Andersen <andersen@codepoet.org> + * Copyright (C) 2000-2006 by Erik Andersen <andersen@codepoet.org> * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, * David Engel, Hongjiu Lu and Mitch D'Souza * @@ -270,7 +270,7 @@ static void * __attribute_used__ _dl_start(unsigned long args) if (!indx && relative_count) { rel_size -= relative_count * sizeof(ELF_RELOC); elf_machine_relative(load_addr, rel_addr, relative_count); - rel_addr += relative_count * sizeof(ELF_RELOC);; + rel_addr += relative_count * sizeof(ELF_RELOC); } rpnt = (ELF_RELOC *) (rel_addr + load_addr); diff --git a/ldso/ldso/dl-tls.c b/ldso/ldso/dl-tls.c index 3e8ad1a18..95d7faf80 100644 --- a/ldso/ldso/dl-tls.c +++ b/ldso/ldso/dl-tls.c @@ -33,7 +33,7 @@ void *(*_dl_calloc_function) (size_t __nmemb, size_t __size) = NULL; void *(*_dl_realloc_function) (void *__ptr, size_t __size) = NULL; void *(*_dl_memalign_function) (size_t __boundary, size_t __size) = NULL; -void (*_dl_free_function) (void *__ptr) = NULL; +extern void (*_dl_free_function) (void *__ptr); void *_dl_memalign (size_t __boundary, size_t __size); struct link_map *_dl_update_slotinfo (unsigned long int req_modid); diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c index 39e56f8a7..5d36c8b62 100644 --- a/ldso/ldso/ldso.c +++ b/ldso/ldso/ldso.c @@ -4,7 +4,7 @@ * after resolving ELF shared library symbols * * Copyright (C) 2005 by Joakim Tjernlund - * Copyright (C) 2000-2004 by Erik Andersen <andersen@codepoet.org> + * Copyright (C) 2000-2006 by Erik Andersen <andersen@codepoet.org> * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, * David Engel, Hongjiu Lu and Mitch D'Souza * @@ -54,6 +54,7 @@ int _dl_errno = 0; /* We can't use the real errno in ldso */ size_t _dl_pagesize = 0; /* Store the page size for use later */ struct r_debug *_dl_debug_addr = NULL; /* Used to communicate with the gdb debugger */ void *(*_dl_malloc_function) (size_t size) = NULL; +void (*_dl_free_function) (void *p) = NULL; #ifdef __SUPPORT_LD_DEBUG__ char *_dl_debug = 0; @@ -79,9 +80,15 @@ static int _dl_suid_ok(void); * address mapping is changed in some way. */ void _dl_debug_state(void); -void _dl_debug_state() +rtld_hidden_proto(_dl_debug_state, noinline); +void _dl_debug_state(void) { + /* Make sure GCC doesn't recognize this function as pure, to avoid + * having the calls optimized away. + */ + __asm__(""); } +rtld_hidden_def(_dl_debug_state); static unsigned char *_dl_malloc_addr = 0; /* Lets _dl_malloc use the already allocated memory page */ static unsigned char *_dl_mmap_zero = 0; /* Also used by _dl_malloc */ @@ -181,7 +188,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, ElfW(auxv_t) auxvt[AT_EGID + 1], char **envp, char **argv) { - ElfW(Addr) app_loadaddr = NULL; + ElfW(Addr) app_mapaddr = 0; ElfW(Phdr) *ppnt; ElfW(Dyn) *dpnt; char *lpntstr; @@ -197,6 +204,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, unsigned long *_dl_envp; /* The environment address */ ElfW(Addr) relro_addr = 0; size_t relro_size = 0; + struct stat st; #if USE_TLS void *tcbp = NULL; #endif @@ -330,8 +338,8 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, relro_addr = ppnt->p_vaddr; relro_size = ppnt->p_memsz; } - if (!app_loadaddr && (ppnt->p_type == PT_LOAD)) { - app_loadaddr = ppnt->p_vaddr; + if (!app_mapaddr && (ppnt->p_type == PT_LOAD)) { + app_mapaddr = ppnt->p_vaddr; } if (ppnt->p_type == PT_DYNAMIC) { dpnt = (ElfW(Dyn) *) (ppnt->p_vaddr + app_tpnt->loadaddr); @@ -345,6 +353,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, _dl_debug_early("calling mprotect on the application program\n"); /* Now cover the application program. */ if (app_tpnt->dynamic_info[DT_TEXTREL]) { + ElfW(Phdr) *ppnt_outer = ppnt; ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val; for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) { if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W)) @@ -353,6 +362,12 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, (unsigned long) ppnt->p_filesz, PROT_READ | PROT_WRITE | PROT_EXEC); } + ppnt = ppnt_outer; + } +#else + if (app_tpnt->dynamic_info[DT_TEXTREL]) { + _dl_dprintf(_dl_debug_file, "Can't modify application's text section; use the GCC option -fPIE for position-independent executables.\n"); + _dl_exit(1); } #endif @@ -370,7 +385,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, _dl_symbol_tables = rpnt = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf)); _dl_memset(rpnt, 0, sizeof(struct dyn_elf)); rpnt->dyn = _dl_loaded_modules; - app_tpnt->mapaddr = app_loadaddr; + app_tpnt->mapaddr = app_mapaddr; app_tpnt->rtld_flags = unlazy | RTLD_GLOBAL; app_tpnt->usage_count++; app_tpnt->symbol_scope = _dl_symbol_tables; @@ -514,9 +529,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, debug_addr->r_brk = (unsigned long) &_dl_debug_state; _dl_debug_addr = debug_addr; - /* Notify the debugger we are in a consistant state */ - _dl_debug_addr->r_state = RT_CONSISTENT; - _dl_debug_state(); + /* Do not notify the debugger until the interpreter is in the list */ /* OK, we now have the application in the list, and we have some * basic stuff in place. Now search through the list for other shared @@ -783,6 +796,10 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, (unsigned long)tpnt->dynamic_addr, 0); + if (_dl_stat(tpnt->libname, &st) >= 0) { + tpnt->st_dev = st.st_dev; + tpnt->st_ino = st.st_ino; + } tpnt->n_phent = epnt->e_phnum; tpnt->ppnt = myppnt; for (j = 0; j < epnt->e_phnum; j++, myppnt++) { diff --git a/ldso/ldso/sh/dl-syscalls.h b/ldso/ldso/sh/dl-syscalls.h index 996bb87c6..d3672512f 100644 --- a/ldso/ldso/sh/dl-syscalls.h +++ b/ldso/ldso/sh/dl-syscalls.h @@ -4,3 +4,11 @@ extern int _dl_errno; #undef __set_errno #define __set_errno(X) {(_dl_errno) = (X);} + +#if __GNUC_PREREQ (4, 1) +#warning !!! gcc 4.1 and later have problems with __always_inline so redefined as inline +# ifdef __always_inline +# undef __always_inline +# define __always_inline inline +# endif +#endif diff --git a/ldso/ldso/sh/elfinterp.c b/ldso/ldso/sh/elfinterp.c index 92199ef13..5524c96d0 100644 --- a/ldso/ldso/sh/elfinterp.c +++ b/ldso/ldso/sh/elfinterp.c @@ -252,7 +252,7 @@ struct elf_resolve *tls_tpnt = NULL; } #if defined (__SUPPORT_LD_DEBUG__) if (_dl_debug_reloc && _dl_debug_detail) - _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", old_val, *reloc_addr, reloc_addr); + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x", old_val, *reloc_addr, reloc_addr); #endif return 0; @@ -289,7 +289,7 @@ _dl_do_lazy_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope, } #if defined (__SUPPORT_LD_DEBUG__) if (_dl_debug_reloc && _dl_debug_detail) - _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", old_val, *reloc_addr, reloc_addr); + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x", old_val, *reloc_addr, reloc_addr); #endif return 0; diff --git a/ldso/libdl/Makefile.in b/ldso/libdl/Makefile.in index b6384a22c..fd147b48f 100644 --- a/ldso/libdl/Makefile.in +++ b/ldso/libdl/Makefile.in @@ -1,7 +1,6 @@ # Makefile.in for uClibc # -# Copyright (C) 2000 by Lineo, inc. -# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org> +# Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> # # Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. # diff --git a/ldso/libdl/libdl.c b/ldso/libdl/libdl.c index c5033df2d..eaa953abb 100644 --- a/ldso/libdl/libdl.c +++ b/ldso/libdl/libdl.c @@ -59,24 +59,30 @@ extern void _dl_free (void *__ptr); extern struct r_debug *_dl_debug_addr; extern unsigned long _dl_error_number; extern void *(*_dl_malloc_function)(size_t); +extern void (*_dl_free_function) (void *p); extern void _dl_run_init_array(struct elf_resolve *); extern void _dl_run_fini_array(struct elf_resolve *); -# ifdef __LDSO_CACHE_SUPPORT__ +#ifdef __LDSO_CACHE_SUPPORT__ int _dl_map_cache(void); int _dl_unmap_cache(void); -# endif -# ifdef __mips__ +#endif +#ifdef __mips__ extern void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt, int lazy); -# endif -# ifdef __SUPPORT_LD_DEBUG__ +#endif +#ifdef __SUPPORT_LD_DEBUG__ extern char *_dl_debug; -# endif +#endif + + #else /* SHARED */ +#define _dl_malloc malloc +#define _dl_free free + /* When libdl is linked as a static library, we need to replace all * the symbols that otherwise would have been loaded in from ldso... */ -# ifdef __SUPPORT_LD_DEBUG__ +#ifdef __SUPPORT_LD_DEBUG__ /* Needed for 'strstr' prototype' */ #include <string.h> char *_dl_debug = 0; @@ -87,16 +93,17 @@ char *_dl_debug_detail = 0; char *_dl_debug_nofixups = 0; char *_dl_debug_bindings = 0; int _dl_debug_file = 2; -# endif +#endif const char *_dl_progname = ""; /* Program name */ +void *(*_dl_malloc_function)(size_t); +void (*_dl_free_function) (void *p); char *_dl_library_path = 0; /* Where we look for libraries */ char *_dl_ldsopath = 0; /* Location of the shared lib loader */ int _dl_errno = 0; /* We can't use the real errno in ldso */ size_t _dl_pagesize = PAGE_SIZE; /* Store the page size for use later */ /* This global variable is also to communicate with debuggers such as gdb. */ struct r_debug *_dl_debug_addr = NULL; -#define _dl_malloc malloc -#define _dl_free free + #include "../ldso/dl-debug.c" @@ -278,6 +285,7 @@ void *dlopen(const char *libname, int flag) struct init_fini_list *tmp, *runp, *runp2, *dep_list; unsigned int nlist, i; struct elf_resolve **init_fini_list; + static int _dl_init = 0; #if USE_TLS bool any_tls = false; #endif @@ -290,6 +298,11 @@ void *dlopen(const char *libname, int flag) from = (ElfW(Addr)) __builtin_return_address(0); + if (!_dl_init) { + _dl_init++; + _dl_malloc_function = malloc; + _dl_free_function = free; + } /* Cover the trivial case first */ if (!libname) return _dl_symbol_tables; @@ -310,7 +323,7 @@ void *dlopen(const char *libname, int flag) _dl_debug_bindings = strstr(_dl_debug, "bind"); } } -# endif +# endif #endif _dl_map_cache(); @@ -333,7 +346,7 @@ void *dlopen(const char *libname, int flag) tfrom = tpnt; } } - for(rpnt = _dl_symbol_tables; rpnt && rpnt->next; rpnt=rpnt->next); + for (rpnt = _dl_symbol_tables; rpnt && rpnt->next; rpnt=rpnt->next); relro_ptr = rpnt; now_flag = (flag & RTLD_NOW) ? RTLD_NOW : 0; @@ -343,8 +356,8 @@ void *dlopen(const char *libname, int flag) #ifndef SHARED /* When statically linked, the _dl_library_path is not yet initialized */ _dl_library_path = getenv("LD_LIBRARY_PATH"); -#endif - +#endif + /* Try to load the specified library */ _dl_if_debug_print("Trying to dlopen '%s', RTLD_GLOBAL:%d RTLD_NOW:%d\n", (char*)libname, (flag & RTLD_GLOBAL ? 1:0), (now_flag & RTLD_NOW ? 1:0)); @@ -369,7 +382,7 @@ void *dlopen(const char *libname, int flag) if (handle->dyn == tpnt) { dyn_chain->init_fini.init_fini = handle->init_fini.init_fini; dyn_chain->init_fini.nlist = handle->init_fini.nlist; - for(i=0; i < dyn_chain->init_fini.nlist; i++) + for (i = 0; i < dyn_chain->init_fini.nlist; i++) dyn_chain->init_fini.init_fini[i]->rtld_flags |= (flag & RTLD_GLOBAL); dyn_chain->next = handle->next; break; @@ -419,7 +432,7 @@ void *dlopen(const char *libname, int flag) for (tmp=dep_list; tmp; tmp = tmp->next) { if (tpnt1 == tmp->tpnt) { /* if match => cirular dependency, drop it */ _dl_if_debug_print("Circular dependency, skipping '%s',\n", - tmp->tpnt->libname); + tmp->tpnt->libname); tpnt1->usage_count--; break; } @@ -439,7 +452,7 @@ void *dlopen(const char *libname, int flag) i = 0; for (runp2 = dep_list; runp2; runp2 = runp2->next) { init_fini_list[i++] = runp2->tpnt; - for(runp = runp2->tpnt->init_fini; runp; runp = runp->next){ + for (runp = runp2->tpnt->init_fini; runp; runp = runp->next) { if (!(runp->tpnt->rtld_flags & RTLD_GLOBAL)) { tmp = malloc(sizeof(struct init_fini_list)); tmp->tpnt = runp->tpnt; @@ -471,9 +484,9 @@ void *dlopen(const char *libname, int flag) } } #ifdef __SUPPORT_LD_DEBUG__ - if(_dl_debug) { + if (_dl_debug) { fprintf(stderr, "\nINIT/FINI order and dependencies:\n"); - for (i=0;i < nlist;i++) { + for (i = 0; i < nlist; i++) { fprintf(stderr, "lib: %s has deps:\n", init_fini_list[i]->libname); runp = init_fini_list[i]->init_fini; for (; runp; runp = runp->next) @@ -1033,6 +1046,7 @@ int dladdr(const void *__address, Dl_info * __info) strtab = (char *) (pelf->dynamic_info[DT_STRTAB]); sf = sn = 0; + #ifdef __LDSO_GNU_HASH_SUPPORT__ if (pelf->l_gnu_bitmask) { for (hn = 0; hn < pelf->nbucket; hn++) { @@ -1050,9 +1064,7 @@ int dladdr(const void *__address, Dl_info * __info) sn = si; sf = 1; } - - _dl_if_debug_print("Symbol \"%s\" at %p\n", - strtab + symtab[si].st_name, symbol_addr); + _dl_if_debug_print("Symbol \"%s\" at %p\n", strtab + symtab[si].st_name, symbol_addr); ++si; } while ((*hasharr++ & 1u) == 0); } @@ -1070,7 +1082,7 @@ int dladdr(const void *__address, Dl_info * __info) } _dl_if_debug_print("Symbol \"%s\" at %p\n", - strtab + symtab[si].st_name, symbol_addr); + strtab + symtab[si].st_name, symbol_addr); } } |