1998-12-23 Ulrich Drepper <drepper@cygnus.com>
+ * elf/dl-lookup.c (do_lookup): If looking up an unversioned symbol
+ but the object file only contains versioned definitions than
+ accept the definition if there is exactly one even if the version
+ number is not the default version. This helps dlsym() to find
+ newly introduced symbols.
+
* locale/programs/ld-collate.c: Unify messages and correct typos.
* locale/programs/ld-monetary.c: Likewise.
* locale/programs/ld-numeric.c: Likewise.
const char *strtab;
const ElfW(Half) *verstab;
ElfW(Symndx) symidx;
+ int num_versions = 0;
+ const ElfW(Sym) *sym;
+ const ElfW(Sym) *versioned_sym;
map = list[i];
symidx != STN_UNDEF;
symidx = map->l_chain[symidx])
{
- const ElfW(Sym) *sym = &symtab[symidx];
+ sym = &symtab[symidx];
if (sym->st_value == 0 || /* No value. */
(elf_machine_lookup_noplt_p (reloc_type) /* Reject PLT entry. */
{
/* No specific version is selected. When the object
file also does not define a version we have a match.
- Otherwise we only accept the default version, i.e.,
- the version which name is "". */
+ Otherwise we accept the default version, or in case
+ there is only one version defined, this one version. */
if (verstab != NULL)
{
ElfW(Half) ndx = verstab[symidx] & 0x7fff;
if (ndx > 2) /* map->l_versions[ndx].hash != 0) */
- continue;
+ {
+ /* Don't accept hidden symbols. */
+ if ((verstab[symidx] & 0x8000) == 0
+ && num_versions++ == 0)
+ /* No version so far. */
+ versioned_sym = sym;
+ continue;
+ }
}
}
else
}
}
+ /* There cannot be another entry for this symbol so stop here. */
+ goto found_it;
+ }
+
+ /* If we have seem exactly one versioned symbol while we are
+ looking for an unversioned symbol and the version is not the
+ default version we still accept this symbol since there are
+ no possible ambiguities. */
+ sym = num_versions == 1 ? versioned_sym : NULL;
+
+ if (sym != NULL)
+ {
+ found_it:
switch (ELFW(ST_BIND) (sym->st_info))
{
case STB_GLOBAL:
result->m = map;
return 1;
case STB_WEAK:
- /* Weak definition. Use this value if we don't find
- another. */
+ /* Weak definition. Use this value if we don't find another. */
if (! result->s)
{
result->s = sym;
/* Local symbols are ignored. */
break;
}
-
- /* There cannot be another entry for this symbol so stop here. */
- break;
}
/* If this current map is the one mentioned in the verneed entry