diff options
author | Ulrich Drepper <drepper@redhat.com> | 2004-03-07 05:26:02 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2004-03-07 05:26:02 +0000 |
commit | 021723ab784461de9eac57398ea16a47d4ab9366 (patch) | |
tree | 9fef57d701b88d5729e3150ea197f86957727998 /elf | |
parent | bdf4a4f1eabb2e085b0610b53bb37b5263f4728d (diff) | |
download | glibc-021723ab784461de9eac57398ea16a47d4ab9366.tar glibc-021723ab784461de9eac57398ea16a47d4ab9366.tar.gz glibc-021723ab784461de9eac57398ea16a47d4ab9366.tar.bz2 glibc-021723ab784461de9eac57398ea16a47d4ab9366.zip |
Update.
2004-03-06 Ulrich Drepper <drepper@redhat.com>
* elf/dl-lookup.c: We don't need for specialized lookup functions.
Combining the functionality does not slow down relocation processing,
it might even speed it up a little.
* sysdeps/generic/ldsodefs.h: Adjust prototypes for lookup function.
Add only one function pointer to rtlf_global_ro.
* elf/do-lookup.h: Replace #ifs with ifs.
* elf/dl-libc.c: Adjust _dl_lookup_* callers.
* elf/dl-reloc.c: Likewise.
* elf/dl-runtime.c: Likewise.
* elf/dl-sym.c: Likewise.
* elf/rtld.c: Likewise. Adjust _rtld_global_ro initialization.
* sysdeps/generic/ldsodefs.h (__rtld_local_attribute__,
__rtld_global_attribute__): Undef after use.
(_rtld_local_ro): Define __rtld_local_attribute__ with just hidden
if available.
* sysdeps/alpha/Subdirs: New file.
* sysdeps/alpha/soft-fp/Makefile: New file.
* sysdeps/alpha/soft-fp/Versions: New file.
* sysdeps/alpha/soft-fp/local-soft-fp.h: New file.
* sysdeps/alpha/soft-fp/ots_add.c: New file.
* sysdeps/alpha/soft-fp/ots_cmp.c: new file.
* sysdeps/alpha/soft-fp/ots_cmpe.c: New file.
* sysdeps/alpha/soft-fp/ots_cvtqux.c: New file.
* sysdeps/alpha/soft-fp/ots_cvtqx.c: New file.
* sysdeps/alpha/soft-fp/ots_cvttx.c: New file.
* sysdeps/alpha/soft-fp/ots_cvtxq.c: New file.
* sysdeps/alpha/soft-fp/ots_cvtxt.c: New file.
* sysdeps/alpha/soft-fp/ots_div.c: New file.
* sysdeps/alpha/soft-fp/ots_mul.c: New file.
* sysdeps/alpha/soft-fp/ots_nintxq.c: New file.
* sysdeps/alpha/soft-fp/ots_sub.c: New file.
Diffstat (limited to 'elf')
-rw-r--r-- | elf/dl-libc.c | 11 | ||||
-rw-r--r-- | elf/dl-reloc.c | 32 | ||||
-rw-r--r-- | elf/dl-runtime.c | 79 | ||||
-rw-r--r-- | elf/dl-sym.c | 32 | ||||
-rw-r--r-- | elf/do-lookup.h | 137 | ||||
-rw-r--r-- | elf/rtld.c | 12 |
6 files changed, 142 insertions, 161 deletions
diff --git a/elf/dl-libc.c b/elf/dl-libc.c index 2b8cb0e15d..a6c833a9e2 100644 --- a/elf/dl-libc.c +++ b/elf/dl-libc.c @@ -85,9 +85,9 @@ do_dlsym (void *ptr) { struct do_dlsym_args *args = (struct do_dlsym_args *) ptr; args->ref = NULL; - args->loadbase = GLRO(dl_lookup_symbol) (args->name, args->map, &args->ref, - args->map->l_local_scope, 0, - DL_LOOKUP_RETURN_NEWEST); + args->loadbase = GLRO(dl_lookup_symbol_x) (args->name, args->map, &args->ref, + args->map->l_local_scope, NULL, 0, + DL_LOOKUP_RETURN_NEWEST, NULL); } static void @@ -126,9 +126,8 @@ do_dlsym_private (void *ptr) struct do_dlsym_args *args = (struct do_dlsym_args *) ptr; args->ref = NULL; - l = GLRO(dl_lookup_versioned_symbol) (args->name, args->map, - &args->ref, args->map->l_scope, - &vers, 0, 0); + l = GLRO(dl_lookup_symbol_x) (args->name, args->map, &args->ref, + args->map->l_scope, &vers, 0, 0, NULL); args->loadbase = l; } diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c index 4349dc27fb..4004316c5a 100644 --- a/elf/dl-reloc.c +++ b/elf/dl-reloc.c @@ -213,13 +213,15 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[], int _tc = elf_machine_type_class (r_type); \ l->l_lookup_cache.type_class = _tc; \ l->l_lookup_cache.sym = (*ref); \ - _lr = ((version) != NULL && (version)->hash != 0 \ - ? _dl_lookup_versioned_symbol (strtab + (*ref)->st_name, \ - l, (ref), scope, (version),\ - _tc, 0) \ - : _dl_lookup_symbol (strtab + (*ref)->st_name, l, (ref), \ - scope, _tc, \ - DL_LOOKUP_ADD_DEPENDENCY)); \ + 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) @@ -234,13 +236,15 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[], int _tc = elf_machine_type_class (r_type); \ l->l_lookup_cache.type_class = _tc; \ l->l_lookup_cache.sym = (*ref); \ - _lr = ((version) != NULL && (version)->hash != 0 \ - ? _dl_lookup_versioned_symbol (strtab + (*ref)->st_name, \ - l, (ref), scope, \ - (version), _tc, 0) \ - : _dl_lookup_symbol (strtab + (*ref)->st_name, l, (ref), \ - scope, _tc, \ - DL_LOOKUP_ADD_DEPENDENCY)); \ + 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) diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c index f89cc68de2..ca936d0052 100644 --- a/elf/dl-runtime.c +++ b/elf/dl-runtime.c @@ -73,30 +73,26 @@ fixup ( used don't look in the global scope. */ if (__builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0) { - switch (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL) + const struct r_found_version *version = NULL; + // XXX Why exactly do we have the differentiation of the flags here? + int flags = DL_LOOKUP_ADD_DEPENDENCY; + + if (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL) { - default: - { - const ElfW(Half) *vernum = - (const void *) D_PTR (l, l_info[VERSYMIDX (DT_VERSYM)]); - ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)] & 0x7fff; - const struct r_found_version *version = &l->l_versions[ndx]; - - if (version->hash != 0) - { - result = _dl_lookup_versioned_symbol (strtab + sym->st_name, - l, &sym, l->l_scope, - version, - ELF_RTYPE_CLASS_PLT, 0); - break; - } - } - case 0: - result = _dl_lookup_symbol (strtab + sym->st_name, l, &sym, - l->l_scope, ELF_RTYPE_CLASS_PLT, - DL_LOOKUP_ADD_DEPENDENCY); + const ElfW(Half) *vernum = + (const void *) D_PTR (l, l_info[VERSYMIDX (DT_VERSYM)]); + ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)] & 0x7fff; + version = &l->l_versions[ndx]; + if (version->hash == 0) + version = NULL; + else + flags = 0; } + result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym, + l->l_scope, version, ELF_RTYPE_CLASS_PLT, + DL_LOOKUP_ADD_DEPENDENCY, NULL); + /* Currently result contains the base load address (or link map) of the object that defines sym. Now add in the symbol offset. */ @@ -161,32 +157,27 @@ profile_fixup ( don't look in the global scope. */ if (__builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0) { - switch (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL) + const struct r_found_version *version = NULL; + // XXX Why exactly do we have the differentiation of the flags here? + int flags = DL_LOOKUP_ADD_DEPENDENCY; + + if (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL) { - default: - { - const ElfW(Half) *vernum = - (const void *) D_PTR (l,l_info[VERSYMIDX (DT_VERSYM)]); - ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)] & 0x7fff; - const struct r_found_version *version = &l->l_versions[ndx]; - - if (version->hash != 0) - { - result = _dl_lookup_versioned_symbol (strtab - + sym->st_name, - l, &sym, l->l_scope, - version, - ELF_RTYPE_CLASS_PLT, - 0); - break; - } - } - case 0: - result = _dl_lookup_symbol (strtab + sym->st_name, l, &sym, - l->l_scope, ELF_RTYPE_CLASS_PLT, - DL_LOOKUP_ADD_DEPENDENCY); + const ElfW(Half) *vernum = + (const void *) D_PTR (l, l_info[VERSYMIDX (DT_VERSYM)]); + ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)] & 0x7fff; + version = &l->l_versions[ndx]; + if (version->hash == 0) + version = NULL; + else + flags = 0; } + result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym, + l->l_scope, version, + ELF_RTYPE_CLASS_PLT, + DL_LOOKUP_ADD_DEPENDENCY, NULL); + /* 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-sym.c b/elf/dl-sym.c index bee49f1fda..27f79a29e5 100644 --- a/elf/dl-sym.c +++ b/elf/dl-sym.c @@ -82,9 +82,9 @@ _dl_sym (void *handle, const char *name, void *who) if (handle == RTLD_DEFAULT) /* Search the global scope as seen in the caller object. */ - result = GLRO(dl_lookup_symbol) (name, match, &ref, match->l_scope, 0, - DL_LOOKUP_RETURN_NEWEST - | DL_LOOKUP_ADD_DEPENDENCY); + result = GLRO(dl_lookup_symbol_x) (name, match, &ref, match->l_scope, NULL, + 0, (DL_LOOKUP_RETURN_NEWEST + | DL_LOOKUP_ADD_DEPENDENCY), NULL); else { if (handle != RTLD_NEXT) @@ -92,9 +92,9 @@ _dl_sym (void *handle, const char *name, void *who) /* Search the scope of the given object. */ struct link_map *map = handle; - result = GLRO(dl_lookup_symbol) (name, match, &ref, - map->l_local_scope, 0, - DL_LOOKUP_RETURN_NEWEST); + result = GLRO(dl_lookup_symbol_x) (name, match, &ref, + map->l_local_scope, NULL, 0, + DL_LOOKUP_RETURN_NEWEST, NULL); } else { @@ -111,8 +111,8 @@ RTLD_NEXT used in code not dynamically loaded")); while (l->l_loader != NULL) l = l->l_loader; - result = GLRO(dl_lookup_symbol_skip) (name, l, &ref, - l->l_local_scope, match); + result = GLRO(dl_lookup_symbol_x) (name, l, &ref, l->l_local_scope, + NULL, 0, 0, match); } } @@ -165,9 +165,9 @@ _dl_vsym (void *handle, const char *name, const char *version, void *who) if (handle == RTLD_DEFAULT) /* Search the global scope. */ - result = GLRO(dl_lookup_versioned_symbol) (name, match, &ref, - match->l_scope, &vers, 0, - DL_LOOKUP_ADD_DEPENDENCY); + result = GLRO(dl_lookup_symbol_x) (name, match, &ref, match->l_scope, + &vers, 0, DL_LOOKUP_ADD_DEPENDENCY, + NULL); else if (handle == RTLD_NEXT) { if (__builtin_expect (match == GL(dl_loaded), 0)) @@ -183,17 +183,15 @@ RTLD_NEXT used in code not dynamically loaded")); while (l->l_loader != NULL) l = l->l_loader; - result = GLRO(dl_lookup_versioned_symbol_skip) (name, l, &ref, - l->l_local_scope, - &vers, match); + result = GLRO(dl_lookup_symbol_x) (name, l, &ref, l->l_local_scope, + &vers, 0, 0, match); } else { /* Search the scope of the given object. */ struct link_map *map = handle; - result = GLRO(dl_lookup_versioned_symbol) (name, map, &ref, - map->l_local_scope, &vers, - 0, 0); + result = GLRO(dl_lookup_symbol_x) (name, map, &ref, map->l_local_scope, + &vers, 0, 0, NULL); } if (ref != NULL) diff --git a/elf/do-lookup.h b/elf/do-lookup.h index 014a06a5aa..9e78dbfa8d 100644 --- a/elf/do-lookup.h +++ b/elf/do-lookup.h @@ -17,21 +17,16 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#if VERSIONED -# define FCT do_lookup_versioned -# define ARG const struct r_found_version *const version -#else -# define FCT do_lookup -# define ARG int flags -#endif - /* Inner part of the lookup functions. We return a value > 0 if we found the symbol, the value 0 if nothing is found and < 0 if something bad happened. */ static int -FCT (const char *undef_name, unsigned long int hash, const ElfW(Sym) *ref, - struct sym_val *result, struct r_scope_elem *scope, size_t i, ARG, - struct link_map *skip, int type_class) +__attribute_noinline__ +do_lookup_x (const char *undef_name, unsigned long int hash, + const ElfW(Sym) *ref, struct sym_val *result, + struct r_scope_elem *scope, size_t i, + 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; @@ -44,10 +39,8 @@ FCT (const char *undef_name, unsigned long int hash, const ElfW(Sym) *ref, const ElfW(Half) *verstab; Elf_Symndx symidx; const ElfW(Sym) *sym; -#if ! VERSIONED int num_versions = 0; const ElfW(Sym) *versioned_sym = NULL; -#endif map = list[i]; @@ -100,67 +93,71 @@ FCT (const char *undef_name, unsigned long int hash, const ElfW(Sym) *ref, /* Not the symbol we are looking for. */ continue; -#if VERSIONED - if (__builtin_expect (verstab == NULL, 0)) + if (version != NULL) { - /* We need a versioned symbol but haven't found any. If - this is the object which is referenced in the verneed - entry it is a bug in the library since a symbol must - not simply disappear. - - It would also be a bug in the object since it means that - the list of required versions is incomplete and so the - tests in dl-version.c haven't found a problem.*/ - assert (version->filename == NULL - || ! _dl_name_match_p (version->filename, map)); - - /* Otherwise we accept the symbol. */ + if (__builtin_expect (verstab == NULL, 0)) + { + /* We need a versioned symbol but haven't found any. If + this is the object which is referenced in the verneed + entry it is a bug in the library since a symbol must + not simply disappear. + + It would also be a bug in the object since it means that + the list of required versions is incomplete and so the + tests in dl-version.c haven't found a problem.*/ + assert (version->filename == NULL + || ! _dl_name_match_p (version->filename, map)); + + /* Otherwise we accept the symbol. */ + } + else + { + /* We can match the version information or use the + default one if it is not hidden. */ + ElfW(Half) ndx = verstab[symidx] & 0x7fff; + if ((map->l_versions[ndx].hash != version->hash + || strcmp (map->l_versions[ndx].name, version->name)) + && (version->hidden || map->l_versions[ndx].hash + || (verstab[symidx] & 0x8000))) + /* It's not the version we want. */ + continue; + } } else { - /* We can match the version information or use the - default one if it is not hidden. */ - ElfW(Half) ndx = verstab[symidx] & 0x7fff; - if ((map->l_versions[ndx].hash != version->hash - || strcmp (map->l_versions[ndx].name, version->name)) - && (version->hidden || map->l_versions[ndx].hash - || (verstab[symidx] & 0x8000))) - /* It's not the version we want. */ - continue; - } -#else - /* No specific version is selected. There are two ways we - can got here: - - - a binary which does not include versioning information - is loaded - - - dlsym() instead of dlvsym() is used to get a symbol which - might exist in more than one form - - If the library does not provide symbol version - information there is no problem at at: we simply use the - symbol if it is defined. - - These two lookups need to be handled differently if the - library defines versions. In the case of the old - unversioned application the oldest (default) version - should be used. In case of a dlsym() call the latest and - public interface should be returned. */ - if (verstab != NULL) - { - if ((verstab[symidx] & 0x7fff) - >= ((flags & DL_LOOKUP_RETURN_NEWEST) ? 2 : 3)) + /* No specific version is selected. There are two ways we + can got here: + + - a binary which does not include versioning information + is loaded + + - dlsym() instead of dlvsym() is used to get a symbol which + might exist in more than one form + + If the library does not provide symbol version + information there is no problem at at: we simply use the + symbol if it is defined. + + These two lookups need to be handled differently if the + library defines versions. In the case of the old + unversioned application the oldest (default) version + should be used. In case of a dlsym() call the latest and + public interface should be returned. */ + if (verstab != NULL) { - /* Don't accept hidden symbols. */ - if ((verstab[symidx] & 0x8000) == 0 && num_versions++ == 0) - /* No version so far. */ - versioned_sym = sym; + if ((verstab[symidx] & 0x7fff) + >= ((flags & DL_LOOKUP_RETURN_NEWEST) ? 2 : 3)) + { + /* Don't accept hidden symbols. */ + if ((verstab[symidx] & 0x8000) == 0 + && num_versions++ == 0) + /* No version so far. */ + versioned_sym = sym; - continue; + continue; + } } } -#endif /* There cannot be another entry for this symbol so stop here. */ goto found_it; @@ -170,11 +167,7 @@ FCT (const char *undef_name, unsigned long int hash, const ElfW(Sym) *ref, looking for an unversioned symbol and the version is not the default version we still accept this symbol since there are no possible ambiguities. */ -#if VERSIONED - sym = NULL; -#else sym = num_versions == 1 ? versioned_sym : NULL; -#endif if (sym != NULL) { @@ -204,13 +197,11 @@ FCT (const char *undef_name, unsigned long int hash, const ElfW(Sym) *ref, } } -#if VERSIONED /* If this current map is the one mentioned in the verneed entry and we have not found a weak entry, it is a bug. */ - if (symidx == STN_UNDEF && version->filename != NULL + if (symidx == STN_UNDEF && version != NULL && version->filename != NULL && __builtin_expect (_dl_name_match_p (version->filename, map), 0)) return -1; -#endif } while (++i < n); diff --git a/elf/rtld.c b/elf/rtld.c index e2d62b70dc..87d3958679 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -139,10 +139,7 @@ struct rtld_global_ro _rtld_global_ro attribute_relro = ._dl_signal_error = _dl_signal_error, ._dl_start_profile = _dl_start_profile, ._dl_mcount = _dl_mcount_internal, - ._dl_lookup_symbol = _dl_lookup_symbol, - ._dl_lookup_versioned_symbol = _dl_lookup_versioned_symbol, - ._dl_lookup_symbol_skip = _dl_lookup_symbol_skip, - ._dl_lookup_versioned_symbol_skip = _dl_lookup_versioned_symbol_skip, + ._dl_lookup_symbol_x = _dl_lookup_symbol_x, }; /* If we would use strong_alias here the compiler would see a non-hidden definition. This would undo the effect of the previous @@ -1521,9 +1518,10 @@ cannot allocate TLS data structures for initial thread"); ElfW(Addr) loadbase; lookup_t result; - result = _dl_lookup_symbol (INTUSE(_dl_argv)[i], GL(dl_loaded), - &ref, GL(dl_loaded)->l_scope, - ELF_RTYPE_CLASS_PLT, 1); + result = _dl_lookup_symbol_x (INTUSE(_dl_argv)[i], GL(dl_loaded), + &ref, GL(dl_loaded)->l_scope, NULL, + ELF_RTYPE_CLASS_PLT, + DL_LOOKUP_ADD_DEPENDENCY, NULL); loadbase = LOOKUP_VALUE_ADDRESS (result); |