diff options
author | "Steven J. Hill" <sjhill@realitydiluted.com> | 2005-09-21 04:17:32 +0000 |
---|---|---|
committer | "Steven J. Hill" <sjhill@realitydiluted.com> | 2005-09-21 04:17:32 +0000 |
commit | 689f30d2cf483dd3b4d70e105c2f13496d5478f7 (patch) | |
tree | 39736731f20b0398bb7388ef287cd69dfe66a392 | |
parent | 52097a030ab9bd28b5944c8707f6a580eac833ef (diff) | |
download | uClibc-alpine-689f30d2cf483dd3b4d70e105c2f13496d5478f7.tar.bz2 uClibc-alpine-689f30d2cf483dd3b4d70e105c2f13496d5478f7.tar.xz |
Added TLS variables to 'struct elf_resolve' which will be needed for TLS support. Created 'dl-tls.c' specifically for ldso instead of trying to share with the one used by the C library. It was getting to be too much of a hassle and this way hopefully all of the TLS functions can be in one place making maintenance much easier. Added new TLS relocation handlers for MIPS. The code is correct, but the variables used to perform the relocations are not set properly as more changes are necessary to the core of ldso.
-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. */ |