diff options
-rw-r--r-- | ldso/include/dl-hash.h | 24 | ||||
-rw-r--r-- | ldso/include/ldso.h | 2 | ||||
-rw-r--r-- | ldso/ldso/Makefile | 7 | ||||
-rw-r--r-- | ldso/ldso/dl-tls.c | 96 | ||||
-rw-r--r-- | ldso/ldso/ldso.c | 13 | ||||
-rw-r--r-- | ldso/ldso/mips/elfinterp.c | 39 | ||||
-rw-r--r-- | libpthread/nptl/sysdeps/generic/dl-tls.c | 4 |
7 files changed, 171 insertions, 14 deletions
diff --git a/ldso/include/dl-hash.h b/ldso/include/dl-hash.h index af6c2b93f..37e420c14 100644 --- a/ldso/include/dl-hash.h +++ b/ldso/include/dl-hash.h @@ -49,6 +49,29 @@ struct elf_resolve{ ElfW(Addr) relro_addr; size_t relro_size; +#if USE_TLS + /* Thread-local storage related info. */ + + /* Start of the initialization image. */ + void *l_tls_initimage; + /* Size of the initialization image. */ + size_t l_tls_initimage_size; + /* Size of the TLS block. */ + size_t l_tls_blocksize; + /* Alignment requirement of the TLS block. */ + size_t l_tls_align; + /* Offset of first byte module alignment. */ + size_t l_tls_firstbyte_offset; +# ifndef NO_TLS_OFFSET +# define NO_TLS_OFFSET 0 +# endif + /* For objects present at startup time: offset in the static TLS block. */ + ptrdiff_t l_tls_offset; + /* Index of the module in the dtv array. */ + size_t l_tls_modid; + /* Nonzero if _dl_init_static_tls should be called for this module */ + unsigned int l_need_tls_init:1; +#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 */ @@ -102,4 +125,3 @@ static inline int _dl_symbol(char * name) #endif /* _LD_HASH_H_ */ - diff --git a/ldso/include/ldso.h b/ldso/include/ldso.h index 300a7292e..9f922f1fa 100644 --- a/ldso/include/ldso.h +++ b/ldso/include/ldso.h @@ -31,6 +31,8 @@ /* Now the ldso specific headers */ #include <dl-elf.h> #include <dl-hash.h> +/* Defines USE_TLS */ +#include <tls.h> /* For INIT/FINI dependency sorting. */ struct init_fini_list { diff --git a/ldso/ldso/Makefile b/ldso/ldso/Makefile index 32b345176..3ca9b731f 100644 --- a/ldso/ldso/Makefile +++ b/ldso/ldso/Makefile @@ -80,10 +80,7 @@ XXFLAGS := $(XXFLAGS:-fomit-frame-pointer=) all: $(LDSO_FULLNAME) ifeq ($(PTHREADS_NATIVE),y) -dl-tls.c dl-minimal.c: - $(LN) -sf $(TOPDIR)libpthread/nptl/sysdeps/generic/$@ $@ - -$(LDSO_FULLNAME): dl-tls.c dl-minimal.c $(OBJS) $(DLINK_OBJS) +$(LDSO_FULLNAME): dl-tls.c $(OBJS) $(DLINK_OBJS) else $(LDSO_FULLNAME): $(OBJS) $(DLINK_OBJS) endif @@ -105,4 +102,4 @@ ldso.o: $(CSRC) dl-elf.c dl-hash.c dl-startup.c dl-debug.c \ $(TARGET_ARCH)/*.h $(TARGET_ARCH)/*.c $(TOPDIR)ldso/include/*.h clean: - $(RM) $(UCLIBC_LDSO)* $(OBJS) $(LDSO_FULLNAME)* core *.o *.a *.s *.i ldso.h *~ dl-tls.c dl-minimal.c + $(RM) $(UCLIBC_LDSO)* $(OBJS) $(LDSO_FULLNAME)* core *.o *.a *.s *.i ldso.h *~ diff --git a/ldso/ldso/dl-tls.c b/ldso/ldso/dl-tls.c new file mode 100644 index 000000000..aec763620 --- /dev/null +++ b/ldso/ldso/dl-tls.c @@ -0,0 +1,96 @@ +/* vi: set sw=4 ts=4: */ +/* + * Thread-local storage handling in the ELF dynamic linker. + * + * Copyright (C) 2005 by Steven J. Hill <sjhill@realitydiluted.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <tls.h> +#include <dl-tls.h> + +/* Taken from glibc/sysdeps/generic/dl-tls.c */ +#ifndef GET_ADDR_ARGS +# define GET_ADDR_ARGS tls_index *ti +#endif +#ifndef GET_ADDR_MODULE +# define GET_ADDR_MODULE ti->ti_module +#endif +#ifndef GET_ADDR_OFFSET +# define GET_ADDR_OFFSET ti->ti_offset +#endif + +/* Taken from glibc/elf/dl-reloc.c */ +#define CHECK_STATIC_TLS(sym_map) \ + do { \ + if (__builtin_expect ((sym_map)->l_tls_offset == NO_TLS_OFFSET, 0)) \ + _dl_allocate_static_tls (sym_map); \ + } while (0) + +/* Taken from glibc/elf/dl-reloc.c */ +void +internal_function __attribute_noinline__ +_dl_allocate_static_tls (struct elf_resolve *map) +{ + _dl_dprintf(2, "_dl_allocate_static_tls NOT IMPLEMENTED!\n"); + _dl_exit(1); + return; +} + +/* Taken from glibc/sysdeps/generic/dl-tls.c */ +void * +__tls_get_addr (GET_ADDR_ARGS) +{ + dtv_t *dtv = THREAD_DTV (); + struct link_map *the_map = NULL; + void *p; + + if (__builtin_expect (dtv[0].counter != _dl_tls_generation, 0)) + the_map = _dl_update_slotinfo (GET_ADDR_MODULE); + + p = dtv[GET_ADDR_MODULE].pointer.val; + + if (__builtin_expect (p == TLS_DTV_UNALLOCATED, 0)) + { + /* The allocation was deferred. Do it now. */ + if (the_map == NULL) + { + /* Find the link map for this module. */ + size_t idx = GET_ADDR_MODULE; + struct dtv_slotinfo_list *listp = _dl_tls_dtv_slotinfo_list; + + while (idx >= listp->len) + { + idx -= listp->len; + listp = listp->next; + } + + the_map = listp->slotinfo[idx].map; + } + + p = dtv[GET_ADDR_MODULE].pointer.val = allocate_and_init (the_map); + dtv[GET_ADDR_MODULE].pointer.is_static = false; + } + + return (char *) p + GET_ADDR_OFFSET; +} diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c index a9dc70721..aaccb0bd1 100644 --- a/ldso/ldso/ldso.c +++ b/ldso/ldso/ldso.c @@ -38,6 +38,10 @@ #define ALLOW_ZERO_PLTGOT +#if USE_TLS +#include "dl-tls.c" +#endif + /* Pull in the value of _dl_progname */ #include "dl-progname.h" @@ -69,11 +73,6 @@ const char *_dl_progname = UCLIBC_LDSO; /* The name of the executable being /* Forward function declarations */ static int _dl_suid_ok(void); -#ifdef __PTHREADS_NATIVE__ -#include "dl-minimal.c" -#include "dl-tls.c" -#endif - /* * This stub function is used by some debuggers. The idea is that they * can set an internal breakpoint on it, so that we are notified when the @@ -201,6 +200,10 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, unlazy = RTLD_NOW; } +#if defined USE_TLS && NO_TLS_OFFSET != 0 + tpnt->l_tls_offset = NO_TLS_OFFSET; +#endif + /* At this point we are now free to examine the user application, * and figure out which libraries are supposed to be called. Until * we have this list, we will not be completely ready for dynamic diff --git a/ldso/ldso/mips/elfinterp.c b/ldso/ldso/mips/elfinterp.c index 18b5799d9..e7e1db439 100644 --- a/ldso/ldso/mips/elfinterp.c +++ b/ldso/ldso/mips/elfinterp.c @@ -127,6 +127,45 @@ int _dl_parse_relocation_information(struct dyn_elf *xpnt, #endif switch (reloc_type) { +#if USE_TLS +# if _MIPS_SIM == _ABI64 + case R_MIPS_TLS_DTPMOD64: + case R_MIPS_TLS_DTPREL64: + case R_MIPS_TLS_TPREL64: +# else + case R_MIPS_TLS_DTPMOD32: + case R_MIPS_TLS_DTPREL32: + case R_MIPS_TLS_TPREL32: +# endif + { + switch (reloc_type) + { + case R_MIPS_TLS_DTPMOD64: + case R_MIPS_TLS_DTPMOD32: + if (symtab_index) + *(ElfW(Word) *)reloc_addr = tpnt->l_tls_modid; + break; + + case R_MIPS_TLS_DTPREL64: + case R_MIPS_TLS_DTPREL32: + *(ElfW(Word) *)reloc_addr += + (symtab[symtab_index].st_value - + TLS_DTV_OFFSET); + break; + + case R_MIPS_TLS_TPREL32: + case R_MIPS_TLS_TPREL64: + CHECK_STATIC_TLS (tpnt); + *(ElfW(Word) *)reloc_addr += + (tpnt->l_tls_offset + + symtab[symtab_index].st_value - + TLS_TP_OFFSET); + break; + } + + break; + } +#endif case R_MIPS_REL32: if (symtab_index) { if (symtab_index < tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX]) diff --git a/libpthread/nptl/sysdeps/generic/dl-tls.c b/libpthread/nptl/sysdeps/generic/dl-tls.c index 4c3a9db4b..1ba8d85fe 100644 --- a/libpthread/nptl/sysdeps/generic/dl-tls.c +++ b/libpthread/nptl/sysdeps/generic/dl-tls.c @@ -1,4 +1,4 @@ -/* tHREAD-local storage handling in the ELF dynamic linker. Generic version. +/* Thread-local storage handling in the ELF dynamic linker. Generic version. Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -25,7 +25,6 @@ #include <dl-tls.h> #include <ldsodefs.h> -#ifndef IS_IN_rtld #include <assert.h> #include <link.h> #include <string.h> @@ -37,7 +36,6 @@ #define _dl_dprintf fprintf #define _dl_debug_file stderr #define _dl_exit exit -#endif /* Amount of excess space to allocate in the static TLS area to allow dynamic loading of modules defining IE-model TLS data. */ |