diff options
author | Jakub Jelinek <jakub@redhat.com> | 2007-07-07 17:15:07 +0000 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2007-07-07 17:15:07 +0000 |
commit | 542ac2393c1ca0d070fa9cce57ca2b2e562f72cc (patch) | |
tree | d17a88450a5ec0811ab35c82f003bde8a3f4a329 /elf | |
parent | 9542710f1329c25f861435d7b96d08991e52bd6d (diff) | |
download | glibc-542ac2393c1ca0d070fa9cce57ca2b2e562f72cc.tar.gz glibc-542ac2393c1ca0d070fa9cce57ca2b2e562f72cc.tar.xz glibc-542ac2393c1ca0d070fa9cce57ca2b2e562f72cc.zip |
2007-06-09 Ulrich Drepper <drepper@redhat.com>
* elf/do-lookup.h (do_lookup_x): Read r_nlist before r_list and make sure gcc doesn't mess around with this. 2007-06-08 Ulrich Drepper <drepper@redhat.com> * elf/dl-lookup.c (_dl_lookup_symbol_x): Remove use of r_nlist. 2007-06-08 Jakub Jelinek <jakub@redhat.com> * elf/dl-close.c (_dl_close_worker): Remove all to be removed libraries from the global scope at once and call THREAD_GSCOPE_WAIT 2007-05-18 Ulrich Drepper <drepper@redhat.com> * elf/dl-close.c (_dl_close_worker): When removing object from global scope, wait for all lookups to finish afterwards. * elf/dl-open.c (add_to_global): When global scope array must grow, allocate a new one and free old array only after all lookups finish. * elf/dl-runtime.c (_dl_fixup): Protect using global scope. (_dl_lookup_symbol_x): Likewise. * elf/dl-support.c: Define _dl_wait_lookup_done. * sysdeps/generic/ldsodefs.h (struct rtld_global): Add _dl_wait_lookup_done. nptl/ 2007-05-28 Jakub Jelinek <jakub@redhat.com> * sysdeps/i386/tls.h (THREAD_GSCOPE_RESET_FLAG): Use explicit insn suffix. (THREAD_GSCOPE_GET_FLAG): Remove. * sysdeps/x86_64/tls.h (THREAD_GSCOPE_GET_FLAG): Remove. * allocatestack.c (__wait_lookup_done): Revert 2007-05-24 changes. * sysdeps/powerpc/tls.h (tcbhead_t): Remove gscope_flag. (THREAD_GSCOPE_GET_FLAG): Remove. (THREAD_GSCOPE_RESET_FLAG): Use THREAD_SELF->header.gscope_flag instead of THREAD_GSCOPE_GET_FLAG. (THREAD_GSCOPE_SET_FLAG): Likewise. Add atomic_write_barrier after it. * sysdeps/s390/tls.h (THREAD_GSCOPE_FLAG_UNUSED, THREAD_GSCOPE_FLAG_USED, THREAD_GSCOPE_FLAG_WAIT, THREAD_GSCOPE_RESET_FLAG, THREAD_GSCOPE_SET_FLAG, THREAD_GSCOPE_WAIT): Define. * sysdeps/sparc/tls.h (THREAD_GSCOPE_FLAG_UNUSED, THREAD_GSCOPE_FLAG_USED, THREAD_GSCOPE_FLAG_WAIT, THREAD_GSCOPE_RESET_FLAG, THREAD_GSCOPE_SET_FLAG, THREAD_GSCOPE_WAIT): Define. * sysdeps/sh/tls.h (THREAD_GSCOPE_FLAG_UNUSED, THREAD_GSCOPE_FLAG_USED, THREAD_GSCOPE_FLAG_WAIT, THREAD_GSCOPE_RESET_FLAG, THREAD_GSCOPE_SET_FLAG, THREAD_GSCOPE_WAIT): Define. * sysdeps/ia64/tls.h (THREAD_GSCOPE_FLAG_UNUSED, THREAD_GSCOPE_FLAG_USED, THREAD_GSCOPE_FLAG_WAIT, THREAD_GSCOPE_RESET_FLAG, THREAD_GSCOPE_SET_FLAG, THREAD_GSCOPE_WAIT): Define. 2007-05-24 Richard Henderson <rth@redhat.com> * descr.h (struct pthread): Add header.gscope_flag. * sysdeps/alpha/tls.h (THREAD_GSCOPE_FLAG_UNUSED, THREAD_GSCOPE_FLAG_USED, THREAD_GSCOPE_FLAG_WAIT, THREAD_GSCOPE_RESET_FLAG, THREAD_GSCOPE_SET_FLAG, THREAD_GSCOPE_WAIT): Define. 2007-05-26 Ulrich Drepper <drepper@redhat.com> * allocatestack.c: Revert last change. * init.c: Likewise. * sysdeps/i386/tls.h: Likewise. * sysdeps/x86_64/tls.h: Likewise. 2007-05-24 Jakub Jelinek <jakub@redhat.com> * sysdeps/powerpc/tls.h (tcbhead_t): Add gscope_flag. (THREAD_GSCOPE_FLAG_UNUSED, THREAD_GSCOPE_FLAG_USED, THREAD_GSCOPE_FLAG_WAIT): Define. (THREAD_GSCOPE_GET_FLAG, THREAD_GSCOPE_SET_FLAG, THREAD_GSCOPE_RESET_FLAG, THREAD_GSCOPE_WAIT): Define. * sysdeps/i386/tls.h (THREAD_GSCOPE_WAIT): Don't use PTR_DEMANGLE. (THREAD_GSCOPE_GET_FLAG): Define. * sysdeps/x86_64/tls.h (THREAD_GSCOPE_GET_FLAG): Define. * allocatestack.c (__wait_lookup_done): Use THREAD_GSCOPE_GET_FLAG instead of ->header.gscope_flag directly. 2007-05-21 Ulrich Drepper <drepper@redhat.com> * sysdeps/pthread/pthread-functions.h (struct pthread_functions): Remove ptr_wait_lookup_done again. * init.c (pthread_functions): Don't add .ptr_wait_lookup_done here. (__pthread_initialize_minimal_internal): Initialize _dl_wait_lookup_done pointer in _rtld_global directly. * sysdeps/unix/sysv/linux/libc_pthread_init.c (__libc_pthread_init): Remove code to code _dl_wait_lookup_done. * sysdeps/x86_64/tls.h (THREAD_GSCOPE_WAIT): The pointer is not encrypted for now. 2007-05-19 Ulrich Drepper <drepper@redhat.com> * allocatestack.c (__wait_lookup_done): New function. * sysdeps/pthread/pthread-functions.h (struct pthread_functions): Add ptr_wait_lookup_done. * init.c (pthread_functions): Initialize .ptr_wait_lookup_done. * pthreadP.h: Declare __wait_lookup_done. * sysdeps/i386/tls.h (tcbhead_t): Add gscope_flag. Define macros to implement reference handling of global scope. * sysdeps/x86_64/tls.h: Likewise. * sysdeps/unix/sysv/linux/libc_pthread_init.c (__libc_pthread_init): Initialize GL(dl_wait_lookup_done).
Diffstat (limited to 'elf')
-rw-r--r-- | elf/dl-close.c | 49 | ||||
-rw-r--r-- | elf/dl-lookup.c | 10 | ||||
-rw-r--r-- | elf/dl-open.c | 23 | ||||
-rw-r--r-- | elf/dl-runtime.c | 32 | ||||
-rw-r--r-- | elf/dl-support.c | 5 | ||||
-rw-r--r-- | elf/do-lookup.h | 9 |
6 files changed, 88 insertions, 40 deletions
diff --git a/elf/dl-close.c b/elf/dl-close.c index e0fe26ad02..2c2b3b6163 100644 --- a/elf/dl-close.c +++ b/elf/dl-close.c @@ -31,6 +31,7 @@ #include <sys/types.h> #include <sys/mman.h> #include <sysdep-cancel.h> +#include <tls.h> /* Type of the constructor functions. */ @@ -228,6 +229,7 @@ _dl_close_worker (struct link_map *map) bool do_audit = GLRO(dl_naudit) > 0 && !ns->_ns_loaded->l_auditing; #endif bool unload_any = false; + unsigned int unload_global = 0; unsigned int first_loaded = ~0; for (unsigned int i = 0; i < nloaded; ++i) { @@ -292,6 +294,9 @@ _dl_close_worker (struct link_map *map) /* We indeed have an object to remove. */ unload_any = true; + if (imap->l_global) + ++unload_global; + /* Remember where the first dynamically loaded object is. */ if (i < first_loaded) first_loaded = i; @@ -457,6 +462,34 @@ _dl_close_worker (struct link_map *map) r->r_state = RT_DELETE; _dl_debug_state (); + if (unload_global) + { + /* Some objects are in the global scope list. Remove them. */ + struct r_scope_elem *ns_msl = ns->_ns_main_searchlist; + unsigned int i; + unsigned int j = 0; + unsigned int cnt = ns_msl->r_nlist; + + while (cnt > 0 && ns_msl->r_list[cnt - 1]->l_removed) + --cnt; + + if (cnt + unload_global == ns_msl->r_nlist) + /* Speed up removing most recently added objects. */ + j = cnt; + else + for (i = 0; i < cnt; i++) + if (ns_msl->r_list[i]->l_removed == 0) + { + if (i != j) + ns_msl->r_list[j] = ns_msl->r_list[i]; + j++; + } + ns_msl->r_nlist = j; + + if (!RTLD_SINGLE_THREAD_P) + THREAD_GSCOPE_WAIT (); + } + size_t tls_free_start; size_t tls_free_end; tls_free_start = tls_free_end = NO_TLS_OFFSET; @@ -472,22 +505,6 @@ _dl_close_worker (struct link_map *map) /* That was the last reference, and this was a dlopen-loaded object. We can unmap it. */ - if (__builtin_expect (imap->l_global, 0)) - { - /* This object is in the global scope list. Remove it. */ - struct r_scope_elem *ns_msl = ns->_ns_main_searchlist; - unsigned int cnt = ns_msl->r_nlist; - - do - --cnt; - while (ns_msl->r_list[cnt] != imap); - - /* The object was already correctly registered. */ - while (++cnt < ns_msl->r_nlist) - ns_msl->r_list[cnt - 1] = ns_msl->r_list[cnt]; - - --ns_msl->r_nlist; - } /* Remove the object from the dtv slotinfo array if it uses TLS. */ if (__builtin_expect (imap->l_tls_blocksize > 0, 0)) diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c index a6a958419f..dc1b865bc7 100644 --- a/elf/dl-lookup.c +++ b/elf/dl-lookup.c @@ -244,13 +244,9 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map, size_t i = 0; if (__builtin_expect (skip_map != NULL, 0)) - { - /* Search the relevant loaded objects for a definition. */ - while ((*scope)->r_list[i] != skip_map) - ++i; - - assert (i < (*scope)->r_nlist); - } + /* Search the relevant loaded objects for a definition. */ + while ((*scope)->r_list[i] != skip_map) + ++i; /* Search the relevant loaded objects for a definition. */ for (size_t start = i; *scope != NULL; start = 0, ++scope) diff --git a/elf/dl-open.c b/elf/dl-open.c index 0afe94b5bf..a043cf61b6 100644 --- a/elf/dl-open.c +++ b/elf/dl-open.c @@ -32,6 +32,7 @@ #include <bp-sym.h> #include <caller.h> #include <sysdep-cancel.h> +#include <tls.h> #include <dl-dst.h> @@ -125,19 +126,25 @@ add_to_global (struct link_map *new) { /* We have to extend the existing array of link maps in the main map. */ - size_t new_size = ns->_ns_global_scope_alloc; - if (new_size >= 256 && new_size > to_add + 8) - new_size *= 2; - else - new_size += to_add + 8; + struct link_map **old_global + = GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_list; + size_t new_nalloc = ((ns->_ns_global_scope_alloc + to_add) * 2); + new_global = (struct link_map **) - realloc (ns->_ns_main_searchlist->r_list, - new_size * sizeof (struct link_map *)); + malloc (new_nalloc * sizeof (struct link_map *)); if (new_global == NULL) goto nomem; - ns->_ns_global_scope_alloc = new_size; + memcpy (new_global, old_global, + ns->_ns_global_scope_alloc * sizeof (struct link_map *)); + + ns->_ns_global_scope_alloc = new_nalloc; ns->_ns_main_searchlist->r_list = new_global; + + if (!RTLD_SINGLE_THREAD_P) + THREAD_GSCOPE_WAIT (); + + free (old_global); } /* Now add the new entries. */ diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c index 9ecf62b436..6add5e4fff 100644 --- a/elf/dl-runtime.c +++ b/elf/dl-runtime.c @@ -26,6 +26,8 @@ #include <ldsodefs.h> #include <sysdep-cancel.h> #include "dynamic-link.h" +#include <tls.h> + #if (!defined ELF_MACHINE_NO_RELA && !defined ELF_MACHINE_PLT_REL) \ || ELF_MACHINE_NO_REL @@ -97,10 +99,15 @@ _dl_fixup ( not necessary for objects which cannot be unloaded or when we are not using any threads (yet). */ int flags = DL_LOOKUP_ADD_DEPENDENCY; - if (l->l_type == lt_loaded && !RTLD_SINGLE_THREAD_P) + if (!RTLD_SINGLE_THREAD_P) { - __rtld_mrlock_lock (l->l_scope_lock); - flags |= DL_LOOKUP_SCOPE_LOCK; + THREAD_GSCOPE_SET_FLAG (); + + if (l->l_type == lt_loaded) + { + __rtld_mrlock_lock (l->l_scope_lock); + flags |= DL_LOOKUP_SCOPE_LOCK; + } } result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym, l->l_scope, @@ -109,6 +116,10 @@ _dl_fixup ( if ((flags & DL_LOOKUP_SCOPE_LOCK) != 0) __rtld_mrlock_unlock (l->l_scope_lock); + /* We are done with the global scope. */ + if (!RTLD_SINGLE_THREAD_P) + THREAD_GSCOPE_RESET_FLAG (); + /* Currently result contains the base load address (or link map) of the object that defines sym. Now add in the symbol offset. */ @@ -191,10 +202,15 @@ _dl_profile_fixup ( not necessary for objects which cannot be unloaded or when we are not using any threads (yet). */ int flags = DL_LOOKUP_ADD_DEPENDENCY; - if (l->l_type == lt_loaded && !RTLD_SINGLE_THREAD_P) + if (!RTLD_SINGLE_THREAD_P) { - __rtld_mrlock_lock (l->l_scope_lock); - flags |= DL_LOOKUP_SCOPE_LOCK; + THREAD_GSCOPE_SET_FLAG (); + + if (l->l_type == lt_loaded) + { + __rtld_mrlock_lock (l->l_scope_lock); + flags |= DL_LOOKUP_SCOPE_LOCK; + } } result = _dl_lookup_symbol_x (strtab + refsym->st_name, l, @@ -204,6 +220,10 @@ _dl_profile_fixup ( if ((flags & DL_LOOKUP_SCOPE_LOCK) != 0) __rtld_mrlock_unlock (l->l_scope_lock); + /* We are done with the global scope. */ + if (!RTLD_SINGLE_THREAD_P) + THREAD_GSCOPE_RESET_FLAG (); + /* Currently result contains the base load address (or link map) of the object that defines sym. Now add in the symbol offset. */ diff --git a/elf/dl-support.c b/elf/dl-support.c index c7479dc639..cecb603ae6 100644 --- a/elf/dl-support.c +++ b/elf/dl-support.c @@ -1,5 +1,5 @@ /* Support for dynamic linking code in static libc. - Copyright (C) 1996-2005, 2006 Free Software Foundation, Inc. + Copyright (C) 1996-2005, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -132,6 +132,9 @@ int (*_dl_make_stack_executable_hook) (void **) internal_function = _dl_make_stack_executable; +/* Function in libpthread to wait for termination of lookups. */ +void (*_dl_wait_lookup_done) (void); + #ifdef NEED_DL_SYSINFO /* Needed for improved syscall handling on at least x86/Linux. */ uintptr_t _dl_sysinfo = DL_SYSINFO_DEFAULT; diff --git a/elf/do-lookup.h b/elf/do-lookup.h index 2585d83005..ab9a510ba1 100644 --- a/elf/do-lookup.h +++ b/elf/do-lookup.h @@ -1,5 +1,5 @@ /* Look up a symbol in the loaded objects. - Copyright (C) 1995-2004, 2005, 2006 Free Software Foundation, Inc. + Copyright (C) 1995-2004, 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -29,8 +29,13 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash, const struct r_found_version *const version, int flags, struct link_map *skip, int type_class) { - struct link_map **list = scope->r_list; size_t n = scope->r_nlist; + /* Make sure we read the value before proceeding. Otherwise we + might use r_list pointing to the initial scope and r_nlist being + the value after a resize. That is the only path in dl-open.c not + protected by GSCOPE. A read barrier here might be to expensive. */ + __asm volatile ("" : "+r" (n), "+m" (scope->r_list)); + struct link_map **list = scope->r_list; do { |