summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ldso/include/dl-hash.h24
-rw-r--r--ldso/include/ldso.h2
-rw-r--r--ldso/ldso/Makefile7
-rw-r--r--ldso/ldso/dl-tls.c96
-rw-r--r--ldso/ldso/ldso.c13
-rw-r--r--ldso/ldso/mips/elfinterp.c39
-rw-r--r--libpthread/nptl/sysdeps/generic/dl-tls.c4
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. */