diff --git a/ChangeLog b/ChangeLog index 152d76720b..0813b59fdc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 1998-12-23 Ulrich Drepper + * 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. diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c index 5245c628d2..8c99f499fd 100644 --- a/elf/dl-lookup.c +++ b/elf/dl-lookup.c @@ -77,6 +77,9 @@ do_lookup (const char *undef_name, unsigned long int hash, 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]; @@ -114,7 +117,7 @@ do_lookup (const char *undef_name, unsigned long int hash, 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. */ @@ -134,13 +137,20 @@ do_lookup (const char *undef_name, unsigned long int hash, { /* 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 @@ -170,6 +180,19 @@ do_lookup (const char *undef_name, unsigned long int hash, } } + /* 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: @@ -178,8 +201,7 @@ do_lookup (const char *undef_name, unsigned long int hash, 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; @@ -190,9 +212,6 @@ do_lookup (const char *undef_name, unsigned long int hash, /* 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