diff options
Diffstat (limited to 'libpthread/nptl/sysdeps/generic')
| -rw-r--r-- | libpthread/nptl/sysdeps/generic/dl-support.c | 15 | ||||
| -rw-r--r-- | libpthread/nptl/sysdeps/generic/dl-tls.c | 82 | ||||
| -rw-r--r-- | libpthread/nptl/sysdeps/generic/libc-tls.c | 5 | ||||
| -rw-r--r-- | libpthread/nptl/sysdeps/generic/sysdep.h | 21 |
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 |
