diff options
Diffstat (limited to 'elf/dl-reloc.c')
-rw-r--r-- | elf/dl-reloc.c | 74 |
1 files changed, 37 insertions, 37 deletions
diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c index 4004316..117410e 100644 --- a/elf/dl-reloc.c +++ b/elf/dl-reloc.c @@ -1,5 +1,5 @@ /* Relocate a shared object and resolve its references to other loaded objects. - Copyright (C) 1995-2002, 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 1995-2004, 2005 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 @@ -48,8 +48,6 @@ void internal_function __attribute_noinline__ _dl_allocate_static_tls (struct link_map *map) { - size_t offset; - /* If the alignment requirements are too high fail. */ if (map->l_tls_align > GL(dl_tls_static_align)) { @@ -71,15 +69,15 @@ cannot allocate memory in static TLS block")); n = (freebytes - blsize) / map->l_tls_align; - offset = GL(dl_tls_static_used) + (freebytes - n * map->l_tls_align - - map->l_tls_firstbyte_offset); + size_t offset = GL(dl_tls_static_used) + (freebytes - n * map->l_tls_align + - map->l_tls_firstbyte_offset); map->l_tls_offset = GL(dl_tls_static_used) = offset; # elif TLS_DTV_AT_TP size_t used; size_t check; - offset = roundup (GL(dl_tls_static_used), map->l_tls_align); + size_t offset = roundup (GL(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. */ @@ -93,8 +91,20 @@ cannot allocate memory in static TLS block")); # error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" # endif - if (map->l_relocated) - GL(dl_init_static_tls) (map); + /* If the object is not yet relocated we cannot initialize the + static TLS region. Delay it. */ + if (map->l_real->l_relocated) + { +#ifdef SHARED + if (__builtin_expect (THREAD_DTV()[0].counter != GL(dl_tls_generation), + 0)) + /* Update the slot information data for at least the generation of + the DSO we are allocating data for. */ + (void) _dl_update_slotinfo (map->l_tls_modid); +#endif + + GL(dl_init_static_tls) (map); + } else map->l_need_tls_init = 1; } @@ -114,7 +124,10 @@ _dl_nothread_init_static_tls (struct link_map *map) # endif /* Fill in the DTV slot so that a later LD/GD access will find it. */ - THREAD_DTV ()[map->l_tls_modid].pointer = dest; + dtv_t *dtv = THREAD_DTV (); + assert (map->l_tls_modid <= dtv[-1].counter); + dtv[map->l_tls_modid].pointer.val = dest; + dtv[map->l_tls_modid].pointer.is_static = true; /* Initialize the memory. */ memset (__mempcpy (dest, map->l_tls_initimage, map->l_tls_initimage_size), @@ -137,11 +150,20 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[], /* Initialize it to make the compiler happy. */ const char *errstring = NULL; +#ifdef SHARED + /* If we are auditing, install the same handlers we need for profiling. */ + consider_profiling |= GLRO(dl_audit) != NULL; +#elif defined PROF + /* Never use dynamic linker profiling for gprof profiling code. */ +# define consider_profiling 0 +#endif + if (l->l_relocated) return; /* If DT_BIND_NOW is set relocate all references in this object. We do not do this if we are profiling, of course. */ + // XXX Correct for auditing? if (!consider_profiling && __builtin_expect (l->l_info[DT_BIND_NOW] != NULL, 0)) lazy = 0; @@ -225,29 +247,6 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[], l->l_lookup_cache.ret = (*ref); \ l->l_lookup_cache.value = _lr; })) \ : l) -#define RESOLVE(ref, version, r_type) \ - (ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL \ - ? ((__builtin_expect ((*ref) == l->l_lookup_cache.sym, 0) \ - && elf_machine_type_class (r_type) == l->l_lookup_cache.type_class) \ - ? (bump_num_cache_relocations (), \ - (*ref) = l->l_lookup_cache.ret, \ - l->l_lookup_cache.value) \ - : ({ lookup_t _lr; \ - int _tc = elf_machine_type_class (r_type); \ - l->l_lookup_cache.type_class = _tc; \ - l->l_lookup_cache.sym = (*ref); \ - const struct r_found_version *v = NULL; \ - int flags = DL_LOOKUP_ADD_DEPENDENCY; \ - if ((version) != NULL && (version)->hash != 0) \ - { \ - v = (version); \ - flags = 0; \ - } \ - _lr = _dl_lookup_symbol_x (strtab + (*ref)->st_name, l, (ref), \ - scope, v, _tc, flags, NULL); \ - l->l_lookup_cache.ret = (*ref); \ - l->l_lookup_cache.value = _lr; })) \ - : l->l_addr) /* This macro is used as a callback from elf_machine_rel{a,} when a static TLS reloc is about to be performed. Since (in dl-load.c) we @@ -268,6 +267,7 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[], ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling); +#ifndef PROF if (__builtin_expect (consider_profiling, 0)) { /* Allocate the array which will contain the already found @@ -276,23 +276,23 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[], will be NULL. */ if (l->l_info[DT_PLTRELSZ] == NULL) { - errstring = N_("%s: profiler found no PLTREL in object %s\n"); + errstring = N_("%s: no PLTREL found in object %s\n"); fatal: _dl_fatal_printf (errstring, rtld_progname ?: "<program name unknown>", l->l_name); } - l->l_reloc_result = - (ElfW(Addr) *) calloc (sizeof (ElfW(Addr)), - l->l_info[DT_PLTRELSZ]->d_un.d_val); + l->l_reloc_result = calloc (sizeof (l->l_reloc_result[0]), + l->l_info[DT_PLTRELSZ]->d_un.d_val); if (l->l_reloc_result == NULL) { errstring = N_("\ -%s: profiler out of memory shadowing PLTREL of %s\n"); +%s: out of memory to store relocation results for %s\n"); goto fatal; } } +#endif } /* Mark the object so we know this work has been done. */ |