summaryrefslogtreecommitdiffstats
path: root/libpthread/nptl/sysdeps/generic
diff options
context:
space:
mode:
Diffstat (limited to 'libpthread/nptl/sysdeps/generic')
-rw-r--r--libpthread/nptl/sysdeps/generic/dl-support.c15
-rw-r--r--libpthread/nptl/sysdeps/generic/dl-tls.c82
-rw-r--r--libpthread/nptl/sysdeps/generic/libc-tls.c5
-rw-r--r--libpthread/nptl/sysdeps/generic/sysdep.h21
4 files changed, 111 insertions, 12 deletions
diff --git a/libpthread/nptl/sysdeps/generic/dl-support.c b/libpthread/nptl/sysdeps/generic/dl-support.c
index 496694ca4..b8f0c07a6 100644
--- a/libpthread/nptl/sysdeps/generic/dl-support.c
+++ b/libpthread/nptl/sysdeps/generic/dl-support.c
@@ -35,16 +35,11 @@ void
internal_function
_dl_aux_init (ElfW(auxv_t) *av)
{
- for (; av->a_type != AT_NULL; ++av)
- switch (av->a_type)
- {
- case AT_PHDR:
- GL(dl_phdr) = (void *) av->a_un.a_val;
- break;
- case AT_PHNUM:
- GL(dl_phnum) = av->a_un.a_val;
- break;
- }
+ /* Get the program headers base address from the aux vect */
+ GL(dl_phdr) = (ElfW(Phdr) *) av[AT_PHDR].a_un.a_val;
+
+ /* Get the number of program headers from the aux vect */
+ GL(dl_phnum) = (size_t) av[AT_PHNUM].a_un.a_val;
}
/* Initialize static TLS area and DTV for current (only) thread.
diff --git a/libpthread/nptl/sysdeps/generic/dl-tls.c b/libpthread/nptl/sysdeps/generic/dl-tls.c
index 1a045ba5b..ad2e84ea3 100644
--- a/libpthread/nptl/sysdeps/generic/dl-tls.c
+++ b/libpthread/nptl/sysdeps/generic/dl-tls.c
@@ -24,6 +24,8 @@
#include <tls.h>
#include <dl-tls.h>
#include <ldsodefs.h>
+#include <dl-elf.h>
+#include <dl-hash.h>
#include <assert.h>
#include <link.h>
@@ -66,6 +68,86 @@ void *_dl_memalign(size_t alignment, size_t bytes)
return _dl_malloc(bytes);
}
+
+/*
+ * We are trying to perform a static TLS relocation in MAP, but it was
+ * dynamically loaded. This can only work if there is enough surplus in
+ * the static TLS area already allocated for each running thread. If this
+ * object's TLS segment is too big to fit, we fail. If it fits,
+ * we set MAP->l_tls_offset and return.
+ * This function intentionally does not return any value but signals error
+ * directly, as static TLS should be rare and code handling it should
+ * not be inlined as much as possible.
+ */
+
+
+void
+internal_function __attribute_noinline__
+_dl_allocate_static_tls (struct link_map *map)
+{
+ /* If the alignment requirements are too high fail. */
+ if (map->l_tls_align > _dl_tls_static_align)
+ {
+fail:
+ _dl_dprintf(_dl_debug_file, "cannot allocate memory in static TLS block");
+ _dl_exit(30);
+ }
+
+# if TLS_TCB_AT_TP
+ size_t freebytes;
+ size_t n;
+ size_t blsize;
+
+ freebytes = _dl_tls_static_size - _dl_tls_static_used - TLS_TCB_SIZE;
+
+ blsize = map->l_tls_blocksize + map->l_tls_firstbyte_offset;
+ if (freebytes < blsize)
+ goto fail;
+
+ n = (freebytes - blsize) / map->l_tls_align;
+
+ size_t offset = _dl_tls_static_used + (freebytes - n * map->l_tls_align
+ - map->l_tls_firstbyte_offset);
+
+ map->l_tls_offset = _dl_tls_static_used = offset;
+# elif TLS_DTV_AT_TP
+ size_t used;
+ size_t check;
+
+ size_t offset = roundup (_dl_tls_static_used, map->l_tls_align);
+ used = offset + map->l_tls_blocksize;
+ check = used;
+
+ /* dl_tls_static_used includes the TCB at the beginning. */
+ if (check > _dl_tls_static_size)
+ goto fail;
+
+ map->l_tls_offset = offset;
+ _dl_tls_static_used = used;
+# else
+# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
+# endif
+
+ /*
+ * If the object is not yet relocated we cannot initialize the
+ * static TLS region. Delay it.
+ */
+ if (((struct elf_resolve *) map)->init_flag & RELOCS_DONE)
+ {
+#ifdef SHARED
+ /*
+ * Update the slot information data for at least the generation of
+ * the DSO we are allocating data for.
+ */
+ if (__builtin_expect (THREAD_DTV()[0].counter != _dl_tls_generation, 0))
+ (void) _dl_update_slotinfo (map->l_tls_modid);
+#endif
+ _dl_init_static_tls (map);
+ }
+ else
+ map->l_need_tls_init = 1;
+}
+
size_t
internal_function
_dl_next_tls_modid (void)
diff --git a/libpthread/nptl/sysdeps/generic/libc-tls.c b/libpthread/nptl/sysdeps/generic/libc-tls.c
index 3b58ce21f..d302d31c9 100644
--- a/libpthread/nptl/sysdeps/generic/libc-tls.c
+++ b/libpthread/nptl/sysdeps/generic/libc-tls.c
@@ -26,13 +26,14 @@
#include <elf.h>
#include <link.h>
#include <string.h>
+#include <stdlib.h>
#ifdef SHARED
#error makefile bug, this file is for static only
#endif
-#ifdef USE_TLS
+#if USE_TLS
extern ElfW(Phdr) *_dl_phdr;
extern size_t _dl_phnum;
@@ -191,7 +192,7 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign)
const char *lossage = TLS_INIT_TP ((char *) tlsblock + tcb_offset, 0);
# elif TLS_DTV_AT_TP
INSTALL_DTV (tlsblock, static_dtv);
- const char *lossage = TLS_INIT_TP (tlsblock, 0);
+ const char *lossage = (char *)TLS_INIT_TP (tlsblock, 0);
# else
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
# endif
diff --git a/libpthread/nptl/sysdeps/generic/sysdep.h b/libpthread/nptl/sysdeps/generic/sysdep.h
index 7c2d76b92..0bbcf9a69 100644
--- a/libpthread/nptl/sysdeps/generic/sysdep.h
+++ b/libpthread/nptl/sysdeps/generic/sysdep.h
@@ -17,6 +17,25 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
+#ifndef C_LABEL
+
+/* Define a macro we can use to construct the asm name for a C symbol. */
+#ifdef NO_UNDERSCORES
+#ifdef __STDC__
+#define C_LABEL(name) name##:
+#else
+#define C_LABEL(name) name/**/:
+#endif
+#else
+#ifdef __STDC__
+#define C_LABEL(name) _##name##:
+#else
+#define C_LABEL(name) _/**/name/**/:
+#endif
+#endif
+
+#endif
+
#ifdef __ASSEMBLER__
/* Mark the end of function named SYM. This is used on some platforms
to generate correct debugging information. */
@@ -41,6 +60,7 @@
# define cfi_register(r1, r2) .cfi_register r1, r2
# define cfi_return_column(reg) .cfi_return_column reg
# define cfi_restore(reg) .cfi_restore reg
+# define cfi_same_value(reg) .cfi_same_value reg
# define cfi_undefined(reg) .cfi_undefined reg
# define cfi_remember_state .cfi_remember_state
# define cfi_restore_state .cfi_restore_state
@@ -57,6 +77,7 @@
# define cfi_register(r1, r2)
# define cfi_return_column(reg)
# define cfi_restore(reg)
+# define cfi_same_value(reg)
# define cfi_undefined(reg)
# define cfi_remember_state
# define cfi_restore_state