2002-04-13  Ulrich Drepper  <drepper@redhat.com>

	* elf/do-lookup.h [!VERSIONED]: Add new parameter flags.  Use it to
	check whether the caller prefers getting the most recent version of
	a symbol of the earliest version.
	* elf/dl-lookup.c: Adjust all callers of do_lookup.  Change
	_dl_do_lookup to also take the new parameter and pass it on.
	Change 'explicit' parameter of _dl_lookup_symbol and
	_dl_lookup_versioned_symbol to flags.  Adjust tests.
	* sysdeps/generic/ldsodefs.h: Adjust prototypes.
	* elf/dl-libc.c: Adjust all callers of _dl_lookup_symbol and
	_dl_lookup_versioned_symbol.
	* elf/dl-reloc.c: Likewise.
	* elf/dl-runtime.c: Likewise.
	* elf/dl-sym.c: Likewise.
	* sysdeps/mips/dl-machine.h: Likewise.
This commit is contained in:
Ulrich Drepper 2002-04-13 07:55:02 +00:00
parent 61bb2ef098
commit f9f2a150e8
9 changed files with 99 additions and 41 deletions

View File

@ -1,3 +1,20 @@
2002-04-13 Ulrich Drepper <drepper@redhat.com>
* elf/do-lookup.h [!VERSIONED]: Add new parameter flags. Use it to
check whether the caller prefers getting the most recent version of
a symbol of the earliest version.
* elf/dl-lookup.c: Adjust all callers of do_lookup. Change
_dl_do_lookup to also take the new parameter and pass it on.
Change 'explicit' parameter of _dl_lookup_symbol and
_dl_lookup_versioned_symbol to flags. Adjust tests.
* sysdeps/generic/ldsodefs.h: Adjust prototypes.
* elf/dl-libc.c: Adjust all callers of _dl_lookup_symbol and
_dl_lookup_versioned_symbol.
* elf/dl-reloc.c: Likewise.
* elf/dl-runtime.c: Likewise.
* elf/dl-sym.c: Likewise.
* sysdeps/mips/dl-machine.h: Likewise.
2002-04-11 Jakub Jelinek <jakub@redhat.com> 2002-04-11 Jakub Jelinek <jakub@redhat.com>
* sysdeps/unix/sysv/linux/sparc/sparc32/sysdep.h (LOC): Don't paste * sysdeps/unix/sysv/linux/sparc/sparc32/sysdep.h (LOC): Don't paste

View File

@ -84,7 +84,8 @@ do_dlsym (void *ptr)
struct do_dlsym_args *args = (struct do_dlsym_args *) ptr; struct do_dlsym_args *args = (struct do_dlsym_args *) ptr;
args->ref = NULL; args->ref = NULL;
args->loadbase = _dl_lookup_symbol (args->name, args->map, &args->ref, args->loadbase = _dl_lookup_symbol (args->name, args->map, &args->ref,
args->map->l_local_scope, 0, 1); args->map->l_local_scope, 0,
DL_LOOKUP_RETURN_NEWEST);
} }
static void static void

View File

@ -190,7 +190,7 @@ static int
internal_function internal_function
_dl_do_lookup (const char *undef_name, unsigned long int hash, _dl_do_lookup (const char *undef_name, unsigned long int hash,
const ElfW(Sym) *ref, struct sym_val *result, const ElfW(Sym) *ref, struct sym_val *result,
struct r_scope_elem *scope, size_t i, struct r_scope_elem *scope, size_t i, int flags,
struct link_map *skip, int type_class); struct link_map *skip, int type_class);
static int static int
internal_function internal_function
@ -215,7 +215,7 @@ lookup_t
internal_function internal_function
_dl_lookup_symbol (const char *undef_name, struct link_map *undef_map, _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[], const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[],
int type_class, int explicit) int type_class, int flags)
{ {
const unsigned long int hash = _dl_elf_hash (undef_name); const unsigned long int hash = _dl_elf_hash (undef_name);
struct sym_val current_value = { NULL, NULL }; struct sym_val current_value = { NULL, NULL };
@ -226,8 +226,8 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
/* Search the relevant loaded objects for a definition. */ /* Search the relevant loaded objects for a definition. */
for (scope = symbol_scope; *scope; ++scope) for (scope = symbol_scope; *scope; ++scope)
if (do_lookup (undef_name, hash, *ref, &current_value, *scope, 0, NULL, if (do_lookup (undef_name, hash, *ref, &current_value, *scope, 0, flags,
type_class)) NULL, type_class))
{ {
/* We have to check whether this would bind UNDEF_MAP to an object /* We have to check whether this would bind UNDEF_MAP to an object
in the global scope which was dynamically loaded. In this case in the global scope which was dynamically loaded. In this case
@ -236,7 +236,7 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
if (__builtin_expect (current_value.m->l_type == lt_loaded, 0) if (__builtin_expect (current_value.m->l_type == lt_loaded, 0)
/* Don't do this for explicit lookups as opposed to implicit /* Don't do this for explicit lookups as opposed to implicit
runtime lookups. */ runtime lookups. */
&& ! explicit && (flags & DL_LOOKUP_ADD_DEPENDENCY) != 0
/* Add UNDEF_MAP to the dependencies. */ /* Add UNDEF_MAP to the dependencies. */
&& add_dependency (undef_map, current_value.m) < 0) && add_dependency (undef_map, current_value.m) < 0)
/* Something went wrong. Perhaps the object we tried to reference /* Something went wrong. Perhaps the object we tried to reference
@ -272,7 +272,7 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
for (scope = symbol_scope; *scope; ++scope) for (scope = symbol_scope; *scope; ++scope)
if (_dl_do_lookup (undef_name, hash, *ref, &protected_value, *scope, if (_dl_do_lookup (undef_name, hash, *ref, &protected_value, *scope,
0, NULL, ELF_RTYPE_CLASS_PLT)) 0, flags, NULL, ELF_RTYPE_CLASS_PLT))
break; break;
if (protected_value.s != NULL && protected_value.m != undef_map) if (protected_value.s != NULL && protected_value.m != undef_map)
@ -319,10 +319,10 @@ _dl_lookup_symbol_skip (const char *undef_name,
assert (i < (*scope)->r_nlist); assert (i < (*scope)->r_nlist);
if (! _dl_do_lookup (undef_name, hash, *ref, &current_value, *scope, i, if (! _dl_do_lookup (undef_name, hash, *ref, &current_value, *scope, i,
skip_map, 0)) DL_LOOKUP_RETURN_NEWEST, skip_map, 0))
while (*++scope) while (*++scope)
if (_dl_do_lookup (undef_name, hash, *ref, &current_value, *scope, 0, if (_dl_do_lookup (undef_name, hash, *ref, &current_value, *scope, 0,
skip_map, 0)) DL_LOOKUP_RETURN_NEWEST, skip_map, 0))
break; break;
if (__builtin_expect (current_value.s == NULL, 0)) if (__builtin_expect (current_value.s == NULL, 0))
@ -341,10 +341,12 @@ _dl_lookup_symbol_skip (const char *undef_name,
if (i >= (*scope)->r_nlist if (i >= (*scope)->r_nlist
|| !_dl_do_lookup (undef_name, hash, *ref, &protected_value, *scope, || !_dl_do_lookup (undef_name, hash, *ref, &protected_value, *scope,
i, skip_map, ELF_RTYPE_CLASS_PLT)) i, DL_LOOKUP_RETURN_NEWEST, skip_map,
ELF_RTYPE_CLASS_PLT))
while (*++scope) while (*++scope)
if (_dl_do_lookup (undef_name, hash, *ref, &protected_value, *scope, if (_dl_do_lookup (undef_name, hash, *ref, &protected_value, *scope,
0, skip_map, ELF_RTYPE_CLASS_PLT)) 0, DL_LOOKUP_RETURN_NEWEST, skip_map,
ELF_RTYPE_CLASS_PLT))
break; break;
if (protected_value.s != NULL && protected_value.m != undef_map) if (protected_value.s != NULL && protected_value.m != undef_map)
@ -375,7 +377,7 @@ _dl_lookup_versioned_symbol (const char *undef_name,
struct link_map *undef_map, const ElfW(Sym) **ref, struct link_map *undef_map, const ElfW(Sym) **ref,
struct r_scope_elem *symbol_scope[], struct r_scope_elem *symbol_scope[],
const struct r_found_version *version, const struct r_found_version *version,
int type_class, int explicit) int type_class, int flags)
{ {
const unsigned long int hash = _dl_elf_hash (undef_name); const unsigned long int hash = _dl_elf_hash (undef_name);
struct sym_val current_value = { NULL, NULL }; struct sym_val current_value = { NULL, NULL };
@ -384,6 +386,9 @@ _dl_lookup_versioned_symbol (const char *undef_name,
bump_num_relocations (); bump_num_relocations ();
/* No other flag than DL_LOOKUP_ADD_DEPENDENCY is allowed. */
assert (flags == 0 || flags == DL_LOOKUP_ADD_DEPENDENCY);
/* Search the relevant loaded objects for a definition. */ /* Search the relevant loaded objects for a definition. */
for (scope = symbol_scope; *scope; ++scope) for (scope = symbol_scope; *scope; ++scope)
{ {
@ -398,14 +403,15 @@ _dl_lookup_versioned_symbol (const char *undef_name,
if (__builtin_expect (current_value.m->l_type == lt_loaded, 0) if (__builtin_expect (current_value.m->l_type == lt_loaded, 0)
/* Don't do this for explicit lookups as opposed to implicit /* Don't do this for explicit lookups as opposed to implicit
runtime lookups. */ runtime lookups. */
&& ! explicit && flags != 0
/* Add UNDEF_MAP to the dependencies. */ /* Add UNDEF_MAP to the dependencies. */
&& add_dependency (undef_map, current_value.m) < 0) && add_dependency (undef_map, current_value.m) < 0)
/* Something went wrong. Perhaps the object we tried to reference /* Something went wrong. Perhaps the object we tried to reference
was just removed. Try finding another definition. */ was just removed. Try finding another definition. */
return INTUSE(_dl_lookup_versioned_symbol) (undef_name, undef_map, return INTUSE(_dl_lookup_versioned_symbol) (undef_name, undef_map,
ref, symbol_scope, ref, symbol_scope,
version, type_class, 0); version, type_class,
0);
break; break;
} }
@ -590,12 +596,14 @@ _dl_setup_hash (struct link_map *map)
map->l_chain = hash; map->l_chain = hash;
} }
static void static void
internal_function internal_function
_dl_debug_bindings (const char *undef_name, struct link_map *undef_map, _dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[], const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[],
struct sym_val *value, const struct r_found_version *version, struct sym_val *value,
int type_class, int protected) const struct r_found_version *version, int type_class,
int protected)
{ {
const char *reference_name = undef_map->l_name; const char *reference_name = undef_map->l_name;
@ -628,7 +636,8 @@ _dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
if (version == 0) if (version == 0)
_dl_do_lookup (undef_name, hash, *ref, &val, _dl_do_lookup (undef_name, hash, *ref, &val,
undef_map->l_local_scope[0], 0, NULL, type_class); undef_map->l_local_scope[0], 0, 0, NULL,
type_class);
else else
_dl_do_lookup_versioned (undef_name, hash, *ref, &val, _dl_do_lookup_versioned (undef_name, hash, *ref, &val,
undef_map->l_local_scope[0], 0, version, undef_map->l_local_scope[0], 0, version,
@ -671,10 +680,10 @@ static int __attribute_noinline__
internal_function internal_function
_dl_do_lookup (const char *undef_name, unsigned long int hash, _dl_do_lookup (const char *undef_name, unsigned long int hash,
const ElfW(Sym) *ref, struct sym_val *result, const ElfW(Sym) *ref, struct sym_val *result,
struct r_scope_elem *scope, size_t i, struct r_scope_elem *scope, size_t i, int flags,
struct link_map *skip, int type_class) struct link_map *skip, int type_class)
{ {
return do_lookup (undef_name, hash, ref, result, scope, i, skip, return do_lookup (undef_name, hash, ref, result, scope, i, flags, skip,
type_class); type_class);
} }

View File

@ -131,7 +131,8 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
l, (ref), scope, \ l, (ref), scope, \
(version), _tc, 0) \ (version), _tc, 0) \
: INTUSE(_dl_lookup_symbol) (strtab + (*ref)->st_name, l, \ : INTUSE(_dl_lookup_symbol) (strtab + (*ref)->st_name, l, \
(ref), scope, _tc, 0)); \ (ref), scope, _tc, \
DL_LOOKUP_ADD_DEPENDENCY)); \
l->l_lookup_cache.ret = (*ref); \ l->l_lookup_cache.ret = (*ref); \
l->l_lookup_cache.value = _lr; })) \ l->l_lookup_cache.value = _lr; })) \
: l) : l)
@ -152,7 +153,8 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
l, (ref), scope, \ l, (ref), scope, \
(version), _tc, 0) \ (version), _tc, 0) \
: INTUSE(_dl_lookup_symbol) (strtab + (*ref)->st_name, l, \ : INTUSE(_dl_lookup_symbol) (strtab + (*ref)->st_name, l, \
(ref), scope, _tc, 0)); \ (ref), scope, _tc, \
DL_LOOKUP_ADD_DEPENDENCY)); \
l->l_lookup_cache.ret = (*ref); \ l->l_lookup_cache.ret = (*ref); \
l->l_lookup_cache.value = _lr; })) \ l->l_lookup_cache.value = _lr; })) \
: l->l_addr) : l->l_addr)

View File

@ -98,7 +98,8 @@ fixup (
} }
case 0: case 0:
result = INTUSE(_dl_lookup_symbol) (strtab + sym->st_name, l, &sym, result = INTUSE(_dl_lookup_symbol) (strtab + sym->st_name, l, &sym,
l->l_scope, ELF_RTYPE_CLASS_PLT, 0); l->l_scope, ELF_RTYPE_CLASS_PLT,
DL_LOOKUP_ADD_DEPENDENCY);
} }
/* Currently result contains the base load address (or link map) /* Currently result contains the base load address (or link map)
@ -192,9 +193,10 @@ profile_fixup (
} }
} }
case 0: case 0:
result = INTUSE(_dl_lookup_symbol) (strtab + sym->st_name, l, &sym, result = INTUSE(_dl_lookup_symbol) (strtab + sym->st_name, l,
l->l_scope, ELF_RTYPE_CLASS_PLT, &sym, l->l_scope,
0); ELF_RTYPE_CLASS_PLT,
DL_LOOKUP_ADD_DEPENDENCY);
} }
/* Currently result contains the base load address (or link map) /* Currently result contains the base load address (or link map)

View File

@ -51,7 +51,9 @@ _dl_sym (void *handle, const char *name, void *who)
if (handle == RTLD_DEFAULT) if (handle == RTLD_DEFAULT)
/* Search the global scope as seen in the caller object. */ /* Search the global scope as seen in the caller object. */
result = _dl_lookup_symbol (name, match, &ref, match->l_scope, 0, 0); result = _dl_lookup_symbol (name, match, &ref, match->l_scope, 0,
DL_LOOKUP_RETURN_NEWEST
| DL_LOOKUP_ADD_DEPENDENCY);
else else
{ {
if (handle != RTLD_NEXT) if (handle != RTLD_NEXT)
@ -60,7 +62,7 @@ _dl_sym (void *handle, const char *name, void *who)
struct link_map *map = handle; struct link_map *map = handle;
result = _dl_lookup_symbol (name, match, &ref, map->l_local_scope, result = _dl_lookup_symbol (name, match, &ref, map->l_local_scope,
0, 1); 0, DL_LOOKUP_RETURN_NEWEST);
} }
else else
{ {
@ -132,7 +134,7 @@ _dl_vsym (void *handle, const char *name, const char *version, void *who)
if (handle == RTLD_DEFAULT) if (handle == RTLD_DEFAULT)
/* Search the global scope. */ /* Search the global scope. */
result = _dl_lookup_versioned_symbol (name, match, &ref, match->l_scope, result = _dl_lookup_versioned_symbol (name, match, &ref, match->l_scope,
&vers, 0, 0); &vers, 0, DL_LOOKUP_ADD_DEPENDENCY);
else if (handle == RTLD_NEXT) else if (handle == RTLD_NEXT)
{ {
if (__builtin_expect (match == GL(dl_loaded), 0)) if (__builtin_expect (match == GL(dl_loaded), 0))
@ -157,7 +159,7 @@ RTLD_NEXT used in code not dynamically loaded"));
/* Search the scope of the given object. */ /* Search the scope of the given object. */
struct link_map *map = handle; struct link_map *map = handle;
result = _dl_lookup_versioned_symbol (name, map, &ref, result = _dl_lookup_versioned_symbol (name, map, &ref,
map->l_local_scope, &vers, 0, 1); map->l_local_scope, &vers, 0, 0);
} }
if (ref != NULL) if (ref != NULL)

View File

@ -19,10 +19,10 @@
#if VERSIONED #if VERSIONED
# define FCT do_lookup_versioned # define FCT do_lookup_versioned
# define ARG const struct r_found_version *const version, # define ARG const struct r_found_version *const version
#else #else
# define FCT do_lookup # define FCT do_lookup
# define ARG # define ARG int flags
#endif #endif
/* Inner part of the lookup functions. We return a value > 0 if we /* Inner part of the lookup functions. We return a value > 0 if we
@ -30,7 +30,7 @@
something bad happened. */ something bad happened. */
static inline int static inline int
FCT (const char *undef_name, unsigned long int hash, const ElfW(Sym) *ref, 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 sym_val *result, struct r_scope_elem *scope, size_t i, ARG,
struct link_map *skip, int type_class) struct link_map *skip, int type_class)
{ {
struct link_map **list = scope->r_list; struct link_map **list = scope->r_list;
@ -129,19 +129,34 @@ FCT (const char *undef_name, unsigned long int hash, const ElfW(Sym) *ref,
continue; continue;
} }
#else #else
/* No specific version is selected. When the object file /* No specific version is selected. There are two ways we
also does not define a version we have a match. can got here:
Otherwise we accept the default version, or in case there
is only one version defined, this one version. */ - 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 != NULL)
{ {
ElfW(Half) ndx = verstab[symidx] & 0x7fff; if ((verstab[symidx] & 0x7fff)
if (ndx >= 2) /* map->l_versions[ndx].hash != 0) */ >= ((flags & DL_LOOKUP_RETURN_NEWEST) ? 2 : 3))
{ {
/* Don't accept hidden symbols. */ /* Don't accept hidden symbols. */
if ((verstab[symidx] & 0x8000) == 0 && num_versions++ == 0) if ((verstab[symidx] & 0x8000) == 0 && num_versions++ == 0)
/* No version so far. */ /* No version so far. */
versioned_sym = sym; versioned_sym = sym;
continue; continue;
} }
} }

View File

@ -532,15 +532,24 @@ extern lookup_t _dl_lookup_symbol (const char *undef,
struct link_map *undef_map, struct link_map *undef_map,
const ElfW(Sym) **sym, const ElfW(Sym) **sym,
struct r_scope_elem *symbol_scope[], struct r_scope_elem *symbol_scope[],
int type_class, int explicit) int type_class, int flags)
internal_function; internal_function;
extern lookup_t _dl_lookup_symbol_internal (const char *undef, extern lookup_t _dl_lookup_symbol_internal (const char *undef,
struct link_map *undef_map, struct link_map *undef_map,
const ElfW(Sym) **sym, const ElfW(Sym) **sym,
struct r_scope_elem *symbol_scope[], struct r_scope_elem *symbol_scope[],
int type_class, int explicit) int type_class, int flags)
internal_function; internal_function;
enum
{
/* If necessary add dependency between user and provider object. */
DL_LOOKUP_ADD_DEPENDENCY = 1,
/* Return most recent version instead of default version for
unversioned lookup. */
DL_LOOKUP_RETURN_NEWEST = 2
};
/* Lookup versioned symbol. */ /* Lookup versioned symbol. */
extern lookup_t _dl_lookup_versioned_symbol (const char *undef, extern lookup_t _dl_lookup_versioned_symbol (const char *undef,
struct link_map *undef_map, struct link_map *undef_map,

View File

@ -307,7 +307,8 @@ __dl_runtime_resolve (ElfW(Word) sym_index, \
} \ } \
case 0: \ case 0: \
value = _dl_lookup_symbol (strtab + sym->st_name, l, &sym, \ value = _dl_lookup_symbol (strtab + sym->st_name, l, &sym, \
l->l_scope, ELF_RTYPE_CLASS_PLT, 0); \ l->l_scope, ELF_RTYPE_CLASS_PLT, \
DL_LOOKUP_ADD_DEPENDENCY); \
} \ } \
\ \
/* Currently value contains the base load address of the object \ /* Currently value contains the base load address of the object \