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>
* 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;
args->ref = NULL;
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

View file

@ -190,7 +190,7 @@ static int
internal_function
_dl_do_lookup (const char *undef_name, unsigned long int hash,
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);
static int
internal_function
@ -215,7 +215,7 @@ lookup_t
internal_function
_dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
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);
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. */
for (scope = symbol_scope; *scope; ++scope)
if (do_lookup (undef_name, hash, *ref, &current_value, *scope, 0, NULL,
type_class))
if (do_lookup (undef_name, hash, *ref, &current_value, *scope, 0, flags,
NULL, type_class))
{
/* We have to check whether this would bind UNDEF_MAP to an object
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)
/* Don't do this for explicit lookups as opposed to implicit
runtime lookups. */
&& ! explicit
&& (flags & DL_LOOKUP_ADD_DEPENDENCY) != 0
/* Add UNDEF_MAP to the dependencies. */
&& add_dependency (undef_map, current_value.m) < 0)
/* 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)
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;
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);
if (! _dl_do_lookup (undef_name, hash, *ref, &current_value, *scope, i,
skip_map, 0))
DL_LOOKUP_RETURN_NEWEST, skip_map, 0))
while (*++scope)
if (_dl_do_lookup (undef_name, hash, *ref, &current_value, *scope, 0,
skip_map, 0))
DL_LOOKUP_RETURN_NEWEST, skip_map, 0))
break;
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
|| !_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)
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;
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 r_scope_elem *symbol_scope[],
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);
struct sym_val current_value = { NULL, NULL };
@ -384,6 +386,9 @@ _dl_lookup_versioned_symbol (const char *undef_name,
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. */
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)
/* Don't do this for explicit lookups as opposed to implicit
runtime lookups. */
&& ! explicit
&& flags != 0
/* Add UNDEF_MAP to the dependencies. */
&& add_dependency (undef_map, current_value.m) < 0)
/* Something went wrong. Perhaps the object we tried to reference
was just removed. Try finding another definition. */
return INTUSE(_dl_lookup_versioned_symbol) (undef_name, undef_map,
ref, symbol_scope,
version, type_class, 0);
version, type_class,
0);
break;
}
@ -590,12 +596,14 @@ _dl_setup_hash (struct link_map *map)
map->l_chain = hash;
}
static void
internal_function
_dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[],
struct sym_val *value, const struct r_found_version *version,
int type_class, int protected)
struct sym_val *value,
const struct r_found_version *version, int type_class,
int protected)
{
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)
_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
_dl_do_lookup_versioned (undef_name, hash, *ref, &val,
undef_map->l_local_scope[0], 0, version,
@ -671,10 +680,10 @@ static int __attribute_noinline__
internal_function
_dl_do_lookup (const char *undef_name, unsigned long int hash,
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)
{
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);
}

View file

@ -131,7 +131,8 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
l, (ref), scope, \
(version), _tc, 0) \
: 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.value = _lr; })) \
: l)
@ -152,7 +153,8 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
l, (ref), scope, \
(version), _tc, 0) \
: 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.value = _lr; })) \
: l->l_addr)

View file

@ -98,7 +98,8 @@ fixup (
}
case 0:
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)
@ -192,9 +193,10 @@ profile_fixup (
}
}
case 0:
result = INTUSE(_dl_lookup_symbol) (strtab + sym->st_name, l, &sym,
l->l_scope, ELF_RTYPE_CLASS_PLT,
0);
result = INTUSE(_dl_lookup_symbol) (strtab + sym->st_name, l,
&sym, l->l_scope,
ELF_RTYPE_CLASS_PLT,
DL_LOOKUP_ADD_DEPENDENCY);
}
/* 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)
/* 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
{
if (handle != RTLD_NEXT)
@ -60,7 +62,7 @@ _dl_sym (void *handle, const char *name, void *who)
struct link_map *map = handle;
result = _dl_lookup_symbol (name, match, &ref, map->l_local_scope,
0, 1);
0, DL_LOOKUP_RETURN_NEWEST);
}
else
{
@ -132,7 +134,7 @@ _dl_vsym (void *handle, const char *name, const char *version, void *who)
if (handle == RTLD_DEFAULT)
/* Search the global 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)
{
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. */
struct link_map *map = handle;
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)

View file

@ -19,10 +19,10 @@
#if 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
# define FCT do_lookup
# define ARG
# define ARG int flags
#endif
/* Inner part of the lookup functions. We return a value > 0 if we
@ -30,7 +30,7 @@
something bad happened. */
static inline 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 sym_val *result, struct r_scope_elem *scope, size_t i, ARG,
struct link_map *skip, int type_class)
{
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;
}
#else
/* No specific version is selected. When the object file
also does not define a version we have a match.
Otherwise we accept the default version, or in case there
is only one version defined, this one version. */
/* 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)
{
ElfW(Half) ndx = verstab[symidx] & 0x7fff;
if (ndx >= 2) /* map->l_versions[ndx].hash != 0) */
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;
}
}

View file

@ -532,15 +532,24 @@ extern lookup_t _dl_lookup_symbol (const char *undef,
struct link_map *undef_map,
const ElfW(Sym) **sym,
struct r_scope_elem *symbol_scope[],
int type_class, int explicit)
int type_class, int flags)
internal_function;
extern lookup_t _dl_lookup_symbol_internal (const char *undef,
struct link_map *undef_map,
const ElfW(Sym) **sym,
struct r_scope_elem *symbol_scope[],
int type_class, int explicit)
int type_class, int flags)
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. */
extern lookup_t _dl_lookup_versioned_symbol (const char *undef,
struct link_map *undef_map,

View file

@ -307,7 +307,8 @@ __dl_runtime_resolve (ElfW(Word) sym_index, \
} \
case 0: \
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 \