diff options
Diffstat (limited to 'elf/do-lookup.h')
-rw-r--r-- | elf/do-lookup.h | 137 |
1 files changed, 64 insertions, 73 deletions
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); |