aboutsummaryrefslogtreecommitdiff
path: root/elf
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>1997-02-19 04:43:53 +0000
committerUlrich Drepper <drepper@redhat.com>1997-02-19 04:43:53 +0000
commit1fb05e3db1891142410bc58c320dfe281749fffe (patch)
tree46299dbecec282055e3493787910444e77099fe7 /elf
parentc84142e8fe3cbcce43ae35ac957a74ac8216d11d (diff)
downloadglibc-1fb05e3db1891142410bc58c320dfe281749fffe.tar
glibc-1fb05e3db1891142410bc58c320dfe281749fffe.tar.gz
glibc-1fb05e3db1891142410bc58c320dfe281749fffe.tar.bz2
glibc-1fb05e3db1891142410bc58c320dfe281749fffe.zip
update from main archive 970218cvs/libc-970221cvs/libc-970220cvs/libc-970219
1997-02-19 03:28 Miles Bader <miles@gnu.ai.mit.edu> * argp/argp-help.c: Add support for user provided filter of help messages. * argp/argp-parse.c: Likewise. * argp/argp.h: Likewise. * argp/argp-namefrob.h: Define __argp_input. * argp/argp-test.c: Add example for filter. 1997-02-19 02:58 Ulrich Drepper <drepper@cygnus.com> * argp.h: New file. * locale/programs/locale.c: Switch to use argp. * errno.h: Make it possible to get definition of error_t even after having errno.h already. * elf/dl-hash.h: New file. ELF hashing function. Extracted from dl-lookup.c. * elf/dl-lookup.c (_dl_elf_hash): Remove definition. * elf/dl-load.c: Rename _dl_does_name_match_p to _dl_name_match_p. * elf/dl-version.c: Likewise. * elf/dl-lookup.c: Implement new versioning lookup scheme. * elf/dl-version.c (_dl_check_map_versions): Initialize new field in l_versions member. * elf/dlvsym.c: Correct call of _dl_lookup_versioned_symbol_skip and _dl_lookup_versioned_symbol. * elf/link.h: Rename hash_name_pair to struct r_found_version. * sysdeps/alpha/dl-machine.h: Likewise. * sysdeps/i386/dl-machine.h: Likewise. * sysdeps/m68k/dl-machine.h: Likewise. * sysdeps/mips/dl-machine.h: Likewise. * intl/l10nflist.c: (_nl_make_l10nflist): Fix bug in computation of length of abs_filename. * locale/Makefile (CPPFLAGS): Define LOCALE_ALIAS_PATH. * locale/programs/ld-monetary.c (monetary_add): Allow value 0 in mon_grouping information. This means no more grouping. * locale/programs/ld-numeric.c (numeric_add): Write value \377 when seein value 0 in grouping information. * locale/programs/linereader.c (lr_close): Don't free fname since it might be used in error messages. * locale/programs/locale.c: Check whether output of `locale -a' really is locale directory. Also print locale aliases. * misc/search.h (__action_fn_t): Parameters VALUE and LEVEL cannot be const. 1997-02-19 02:16 Ulrich Drepper <drepper@cygnus.com> * sysdeps/unix/bsd/sun/sunos4/resourcebits.h: Correct #defin to #define. Reported by Rick Flower <FLOWER@sdvax2.sdd.TRW.COM>. 1997-02-19 01:37 Erik Troan <ewt@redhat.com> * shadow/sgetspent_r.c: Accept empty third, fourth and fifth fields. 1997-02-19 01:02 Ulrich Drepper <drepper@cygnus.com> * sysdeps/unix/mman/syscalls.list: msync takes 3 arguments. Reported by Andreas Jaeger <aj@arthur.pfalz.de>. * sysdeps/stub/msync.c (msync): Add missing third parameter. 1997-02-19 00:29 Ulrich Drepper <drepper@cygnus.com> * sysdeps/unix/bsd/sigsuspend.c: Call __sigpause with needed additional argument. 1997-02-18 22:13 Ulrich Drepper <drepper@cygnus.com> * inet/net/ethernet.h: New file. * sysdeps/unix/sysv/linux/netinet/if_ether.c: Add BSD compatibility. * sysdeps/unix/sysv/linux/net/if_slip.h: New file. Contributed by a sun <asun@zoology.washington.edu>. * sysdeps/unix/sysv/linux/net/if_arp.h: Include <sys/socket.h>. * sunrpc/rpc/rpc_msg.h: Include <rpc/clnt.h>. Reported by a sun <asun@zoology.washington.edu>. 1997-02-16 14:25 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> * Makerules ((common-objpfx)distinfo-$(subdir)): Depend on sysdep makefiles which may change the distinfo variables. 1997-02-16 14:03 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> * sysdeps/unix/sysv/linux/Makefile (sysdep_headers) [$(subdir)=misc]: Add sys/quota.h. (sysdep_headers) [$(subdir)=inet]: Add netinet/udp.h. 1997-02-17 13:12 aleph1@dfw.net * sunrpc/clnt_simp.c (callrpc): Prevent buffer overflow by using strncpy. 1997-02-18 03:28 Ulrich Drepper <drepper@cygnus.com> * stdio-common/bug10.c (main): Correct parameter. 1997-02-17 02:51 Ulrich Drepper <drepper@cygnus.com> * malloc/obstack.h: Add `extern "C"' protection. * posix/regex.h: Likewise. * io/ftw.h: Likewise. * misc/libgen.h: Likewise. * login/utmp.h: Likewise. * sysdeps/unix/sysv/linux/sys/reboot.h: Likewise. * sysdeps/unix/sysv/linux/netinet/in.h: Likewise. * sunrpc/rpc/pmap_rmt.h: Likewise. * sunrpc/rpc/auth_des.h: Likewise. * elf/link.h: Likewise. Reported by HJ Lu. 1997-02-17 01:45 a sun <asun@zoology.washington.edu> Linux specific network headers. * sysdeps/unix/sysv/linux/netinet/if_fddi.h: New file. * sysdeps/unix/sysv/linux/netinet/if_tr.h: New file. * sysdeps/unix/sysv/linux/netinet/ip_icmp.h: New file. * sysdeps/unix/sysv/linux/netinet/ip_fw.h: New file. * sysdeps/unix/sysv/linux/netinet/igmp.h: New file. * sysdeps/unix/sysv/linux/netinet/icmp.h: New file. * sysdeps/unix/sysv/linux/netinet/ip.h: New file. * sysdeps/unix/sysv/linux/netinet/tcp.h: New file. * sysdeps/unix/sysv/linux/netipx/ipx.h: New file. * sysdeps/unix/sysv/linux/netatalk/atalk.h: New file. * sysdeps/unix/sysv/linux/Dist: Add new network headers. * sysdeps/unix/sysv/linux/Makefile [$(subdir)=misc] (sysdep_headers): Add sys/quota.h. [$(subdir)=inet] (sysdep_headers): Add new network header. * sysdeps/unix/sysv/linux/netinet/udp.h: Add Linux specific changes. * inet/netinet/ip.h: Move to sysdeps/generic. * inet/netinet/tcp.h: Likewise. * sysdeps/generic/netinet/ip.h: Moved to here from inet/netinet. * sysdeps/generic/netinet/tcp.h: Likewise. 1997-02-17 01:18 Ulrich Drepper <drepper@cygnus.com> * misc/sys/syslog.h (prioritynames): Correct definition to use braces where necessary. (facilitynames): Likewise. Patch by Ronald F. Guilmette <rfg@monkeys.com>. Comment and beautify declarations. 1997-02-16 19:54 1997 Philip Blundell <Philip.Blundell@pobox.com> * inet/Makefile (routines): Add in6_addr, getnameinfo. * inet/getnameinfo.c: New file. Implementation of getnameinfo() by Craig Metz. * inet/in6_addr.c: New file. IPv6 addressing constants. * posix/Makefile (routines): Add gai_strerror. * resolv/netdb.h: Add more constants for IPv6 basic API. * sysdeps/posix/gai_strerror.c: New file. * sysdeps/stub/gai_strerror.c New file. * sysdeps/unix/sysv/linux/netinet/in.h: Add definitions for IPv6 basic API. * sysdeps/posix/getaddrinfo.c: Update from latest version by Craig Metz and use reentrant getXXbyYY functions. 1997-02-15 14:32 Andreas Jaeger <aj@arthur.pfalz.de> * argp/argp.h: Declare argp_program_version as const char. * argp/argp-test.c: Likewise * stdlib/testrand.c (main): Declare main prototype. * stdlib/testdiv.c (main): Likewise. * string/testcopy.c (main): Likewise. * string/test-ffs.c (main): Likewise. * time/test_time.c (main): Likewise. * locale/duplocale.c (__duplocale): Return result. 1997-02-16 03:54 Ulrich Drepper <drepper@cygnus.com> * sysdeps/unix/sysv/linux/netinet/in.h: Declare bindresvport. Reported by fabsoft@fabserver1.zarm.uni-bremen.de. * nss/nss.h: Remove declaration of __nss_shlib_revision. * nss/nsswitch.c: Don't use NSS_SHLIB_VERSION macro. 1997-02-16 03:48 Thorsten Kukuk <kukuk@weber.uni-paderborn.de> * nis/nss_nis/nis-ethers.c (_nss_nis_getethernam_r): Rename to _nss_nis_gethostton_r. (_nss_nis_getetherbyaddr_r): Rename to _nss_nis_getntohost_r. 1997-02-15 22:37 Andy Berkheimer <andy@tho.org> * resolv/gethnamaddr.c (gethostbyname2): Test for ':' in name before trying to resolv name as numeric IPv6 address. * nss/digits_dots.c: Likewise. Sat Feb 15 04:51:08 1997 Ulrich Drepper <drepper@cygnus.com> * locale/setlocale.c (setlocale): Don't try to be clever about unused locales. When the existence of the locale files isn't tested the result of setlocale might be different. 1997-02-15 03:34 Ulrich Drepper <drepper@cygnus.com> * locale/setlocale.c (setlocale): Don't increment usage_count of new locale if it already has the value MAX_USAGE_COUNT (it might be the C locale data which is read-only).
Diffstat (limited to 'elf')
-rw-r--r--elf/dl-hash.h69
-rw-r--r--elf/dl-load.c2
-rw-r--r--elf/dl-lookup.c187
-rw-r--r--elf/dl-version.c13
-rw-r--r--elf/dlvsym.c18
-rw-r--r--elf/link.h23
6 files changed, 198 insertions, 114 deletions
diff --git a/elf/dl-hash.h b/elf/dl-hash.h
new file mode 100644
index 0000000000..007f192a23
--- /dev/null
+++ b/elf/dl-hash.h
@@ -0,0 +1,69 @@
+/* Compute hash alue for given string according to ELF standard.
+ Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifndef _DL_HASH_H
+#define _DL_HASH_H 1
+
+
+/* This is the hashing function specified by the ELF ABI. In the
+ first five operations now overflow is possible so we optimized it a
+ bit. */
+static inline unsigned
+_dl_elf_hash (const char *name)
+{
+ unsigned long int hash = 0;
+ if (*name != '\0')
+ {
+ hash = (hash << 4) + *name++;
+ if (*name != '\0')
+ {
+ hash = (hash << 4) + *name++;
+ if (*name != '\0')
+ {
+ hash = (hash << 4) + *name++;
+ if (*name != '\0')
+ {
+ hash = (hash << 4) + *name++;
+ if (*name != '\0')
+ {
+ hash = (hash << 4) + *name++;
+ while (*name != '\0')
+ {
+ unsigned long int hi;
+ hash = (hash << 4) + *name++;
+ hi = hash & 0xf0000000;
+ if (hi != 0)
+ {
+ hash ^= hi >> 24;
+ /* The ELF ABI says `hash &= ~hi', but
+ this is equivalent in this case and
+ on some machines one insn instead of
+ two. */
+ hash ^= hi;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return hash;
+}
+
+#endif /* dl-hash.h */
diff --git a/elf/dl-load.c b/elf/dl-load.c
index e3de0764ec..a103d38548 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -540,7 +540,7 @@ _dl_map_object (struct link_map *loader, const char *name, int type,
/* Look for this name among those already loaded. */
for (l = _dl_loaded; l; l = l->l_next)
- if (_dl_does_name_match_p (name, l) ||
+ if (_dl_name_match_p (name, l) ||
/* If the requested name matches the soname of a loaded object,
use that object. */
(l->l_info[DT_SONAME] &&
diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
index 06d1d09b90..8702a85bbb 100644
--- a/elf/dl-lookup.c
+++ b/elf/dl-lookup.c
@@ -22,6 +22,7 @@
#include <assert.h>
#include <string.h>
+#include <dl-hash.h>
#include "../stdio-common/_itoa.h"
#define VERSTAG(tag) (DT_NUM + DT_PROCNUM + DT_VERSIONTAGIDX (tag))
@@ -33,58 +34,32 @@ struct sym_val
};
-/* This is the hashing function specified by the ELF ABI. In the
- first five operations now overflow is possible so we optimized it a
- bit. */
-static inline unsigned
-_dl_elf_hash (const char *name)
-{
- unsigned long int hash = 0;
- if (*name != '\0')
- {
- hash = (hash << 4) + *name++;
- if (*name != '\0')
- {
- hash = (hash << 4) + *name++;
- if (*name != '\0')
- {
- hash = (hash << 4) + *name++;
- if (*name != '\0')
- {
- hash = (hash << 4) + *name++;
- if (*name != '\0')
- {
- hash = (hash << 4) + *name++;
- while (*name != '\0')
- {
- unsigned long int hi;
- hash = (hash << 4) + *name++;
- hi = hash & 0xf0000000;
- if (hi != 0)
- {
- hash ^= hi >> 24;
- /* The ELF ABI says `hash &= ~hi', but
- this is equivalent in this case and
- on some machines one insn instead of
- two. */
- hash ^= hi;
- }
- }
- }
- }
- }
- }
- }
- return hash;
-}
-
-
-/* Inner part of the lookup functions. */
-static inline ElfW(Addr)
+#define make_string(string, rest...) \
+ ({ \
+ const char *all[] = { string, ## rest }; \
+ size_t len, cnt; \
+ char *result, *cp; \
+ \
+ len = 1; \
+ for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt) \
+ len += strlen (all[cnt]); \
+ \
+ cp = result = alloca (len); \
+ for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt) \
+ cp = stpcpy (cp, all[cnt]); \
+ \
+ result; \
+ })
+
+
+/* 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 inline int
do_lookup (const char *undef_name, unsigned long int hash,
const ElfW(Sym) **ref, struct sym_val *result,
struct link_map *list[], size_t i, size_t n,
- const char *reference_name, const hash_name_pair *version,
+ const char *reference_name, const struct r_found_version *version,
struct link_map *skip, int flags)
{
struct link_map *map;
@@ -108,8 +83,7 @@ do_lookup (const char *undef_name, unsigned long int hash,
symtab = ((void *) map->l_addr + map->l_info[DT_SYMTAB]->d_un.d_ptr);
strtab = ((void *) map->l_addr + map->l_info[DT_STRTAB]->d_un.d_ptr);
- if (version != NULL
- && map->l_nversions > 0 && map->l_info[VERSTAG (DT_VERSYM)] != NULL)
+ if (map->l_nversions > 0 && map->l_info[VERSTAG (DT_VERSYM)] != NULL)
verstab = ((void *) map->l_addr
+ map->l_info[VERSTAG (DT_VERSYM)]->d_un.d_ptr);
else
@@ -143,13 +117,41 @@ do_lookup (const char *undef_name, unsigned long int hash,
/* Not the symbol we are looking for. */
continue;
- if (verstab != NULL)
+ if (version == NULL)
{
- /* We can match the version information. */
- ElfW(Half) ndx = verstab[symidx] & 0x7fff;
- if (map->l_versions[ndx].hash != version->hash
- || strcmp (map->l_versions[ndx].name, version->name))
- continue;
+ /* 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 "". */
+ if (verstab != NULL)
+ {
+ ElfW(Half) ndx = verstab[symidx] & 0x7fff;
+ if (map->l_versions[ndx].hash != 0)
+ continue;
+ }
+ }
+ else
+ {
+ if (verstab == NULL)
+ {
+ /* We need a versioned system 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. */
+ if (version->filename != NULL
+ && _dl_name_match_p (version->filename, map))
+ return -1;
+ /* Otherwise we accept the symbol. */
+ }
+ else
+ {
+ /* We can match the version information. */
+ ElfW(Half) ndx = verstab[symidx] & 0x7fff;
+ if (map->l_versions[ndx].hash != version->hash
+ || strcmp (map->l_versions[ndx].name, version->name))
+ /* It's not the version we want. */
+ continue;
+ }
}
switch (ELFW(ST_BIND) (sym->st_info))
@@ -173,6 +175,12 @@ do_lookup (const char *undef_name, unsigned long int hash,
break;
}
}
+
+ /* If this current is the one mentioned in the verneed entry it
+ is a bug. */
+ if (version != NULL && version->filename != NULL
+ && _dl_name_match_p (version->filename, map))
+ return -1;
}
/* We have not found anything until now. */
@@ -204,15 +212,9 @@ _dl_lookup_symbol (const char *undef_name, const ElfW(Sym) **ref,
if (current_value.s == NULL &&
(*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK))
- {
- /* We could find no value for a strong reference. */
- static const char msg[] = "undefined symbol: ";
- const size_t len = strlen (undef_name);
- char buf[sizeof msg + len];
- memcpy (buf, msg, sizeof msg - 1);
- memcpy (&buf[sizeof msg - 1], undef_name, len + 1);
- _dl_signal_error (0, reference_name, buf);
- }
+ /* We could find no value for a strong reference. */
+ _dl_signal_error (0, reference_name,
+ make_string ("undefined symbol: ", undef_name));
*ref = current_value.s;
return current_value.a;
@@ -264,7 +266,7 @@ ElfW(Addr)
_dl_lookup_versioned_symbol (const char *undef_name, const ElfW(Sym) **ref,
struct link_map *symbol_scope[],
const char *reference_name,
- const hash_name_pair *version, int flags)
+ const struct r_found_version *version, int flags)
{
const unsigned long int hash = _dl_elf_hash (undef_name);
struct sym_val current_value = { 0, NULL };
@@ -272,28 +274,30 @@ _dl_lookup_versioned_symbol (const char *undef_name, const ElfW(Sym) **ref,
/* Search the relevant loaded objects for a definition. */
for (scope = symbol_scope; *scope; ++scope)
- if (do_lookup (undef_name, hash, ref, &current_value,
- (*scope)->l_searchlist, 0, (*scope)->l_nsearchlist,
- reference_name, version, NULL, flags))
- break;
+ {
+ int res = do_lookup (undef_name, hash, ref, &current_value,
+ (*scope)->l_searchlist, 0, (*scope)->l_nsearchlist,
+ reference_name, version, NULL, flags);
+ if (res > 0)
+ break;
+
+ if (res < 0)
+ /* Oh, oh. The file named in the relocation entry does not
+ contain the needed symbol. */
+ _dl_signal_error (0, *reference_name ? reference_name : NULL,
+ make_string ("symbol ", undef_name, ", version ",
+ version->name,
+ " not defined in file ",
+ version->filename,
+ " with link time reference"));
+ }
if (current_value.s == NULL &&
(*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK))
- {
- /* We could find no value for a strong reference. */
- static const char msg1[] = "undefined symbol: ";
- const size_t len = strlen (undef_name);
- static const char msg2[] = ", version ";
- const size_t verslen = strlen (version->name ?: "") + 1;
- char buf[sizeof msg1 - 1 + len + sizeof msg2 - 1 + verslen];
-
- memcpy (buf, msg1, sizeof msg1 - 1);
- memcpy (&buf[sizeof msg1 - 1], undef_name, len + 1);
- memcpy (&buf[sizeof msg1 - 1 + len], msg2, sizeof msg2 - 1);
- memcpy (&buf[sizeof msg1 - 1 + len + sizeof msg2 - 1], version->name,
- verslen);
- _dl_signal_error (0, reference_name, buf);
- }
+ /* We could find no value for a strong reference. */
+ _dl_signal_error (0, reference_name,
+ make_string ("undefined symbol: ", undef_name,
+ ", version ", version->name ?: NULL));
*ref = current_value.s;
return current_value.a;
@@ -307,20 +311,15 @@ _dl_lookup_versioned_symbol_skip (const char *undef_name,
const ElfW(Sym) **ref,
struct link_map *symbol_scope[],
const char *reference_name,
- const char *version_name,
+ const struct r_found_version *version,
struct link_map *skip_map,
int flags)
{
const unsigned long int hash = _dl_elf_hash (undef_name);
struct sym_val current_value = { 0, NULL };
struct link_map **scope;
- hash_name_pair version;
size_t i;
- /* First convert the VERSION_NAME into a `hash_name_pair' value. */
- version.hash = _dl_elf_hash (version_name);
- version.name = version_name;
-
/* Search the relevant loaded objects for a definition. */
scope = symbol_scope;
for (i = 0; (*scope)->l_dupsearchlist[i] != skip_map; ++i)
@@ -328,11 +327,11 @@ _dl_lookup_versioned_symbol_skip (const char *undef_name,
if (! do_lookup (undef_name, hash, ref, &current_value,
(*scope)->l_dupsearchlist, i, (*scope)->l_ndupsearchlist,
- reference_name, &version, skip_map, flags))
+ reference_name, version, skip_map, flags))
while (*++scope)
if (do_lookup (undef_name, hash, ref, &current_value,
(*scope)->l_dupsearchlist, 0, (*scope)->l_ndupsearchlist,
- reference_name, &version, skip_map, flags))
+ reference_name, version, skip_map, flags))
break;
*ref = current_value.s;
diff --git a/elf/dl-version.c b/elf/dl-version.c
index 4382a4c0ae..ae1c2f34f7 100644
--- a/elf/dl-version.c
+++ b/elf/dl-version.c
@@ -58,7 +58,7 @@ find_needed (struct link_map *map, const char *name)
unsigned int n;
for (n = 0; n < map->l_nsearchlist; ++n)
- if (_dl_does_name_match_p (name, map->l_searchlist[n]))
+ if (_dl_name_match_p (name, map->l_searchlist[n]))
return map->l_searchlist[n];
/* Should never happen. */
@@ -246,13 +246,14 @@ _dl_check_map_versions (struct link_map *map, int verbose)
/* Now we are ready to build the array with the version names
which can be indexed by the version index in the VERSYM
section. */
- map->l_versions = (hash_name_pair*) malloc ((ndx_high + 1)
- * sizeof (hash_name_pair));
- memset (map->l_versions, '\0', (ndx_high + 1) * sizeof (hash_name_pair));
+ map->l_versions = (struct r_found_version *)
+ malloc ((ndx_high + 1) * sizeof (*map->l_versions));
+ memset (map->l_versions, '\0',
+ (ndx_high + 1) * sizeof (*map->l_versions));
if (map->l_versions == NULL)
{
_dl_signal_error (ENOMEM, (*map->l_name ? map->l_name : _dl_argv[0]),
- "cannot allocate version name table");
+ "cannot allocate version reference table");
result = 1;
}
else
@@ -273,6 +274,7 @@ _dl_check_map_versions (struct link_map *map, int verbose)
ElfW(Half) ndx = aux->vna_other & 0x7fff;
map->l_versions[ndx].hash = aux->vna_hash;
map->l_versions[ndx].name = &strtab[aux->vna_name];
+ map->l_versions[ndx].filename = &strtab[ent->vn_file];
if (aux->vna_next == 0)
/* No more symbols. */
@@ -308,6 +310,7 @@ _dl_check_map_versions (struct link_map *map, int verbose)
ElfW(Half) ndx = ent->vd_ndx & 0x7fff;
map->l_versions[ndx].hash = ent->vd_hash;
map->l_versions[ndx].name = &strtab[aux->vda_name];
+ map->l_versions[ndx].filename = NULL;
}
if (ent->vd_next == 0)
diff --git a/elf/dlvsym.c b/elf/dlvsym.c
index 5063b3ba0d..922a6eed1f 100644
--- a/elf/dlvsym.c
+++ b/elf/dlvsym.c
@@ -1,4 +1,4 @@
-/* Look up a symbol in a shared object loaded by `dlopen'.
+/* Look up a versioned symbol in a shared object loaded by `dlopen'.
Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
@@ -22,12 +22,14 @@
#include <dlfcn.h>
#include <setjmp.h>
+#include <dl-hash.h>
void *
-__dlvsym (void *handle, const char *name, const char *version)
+__dlvsym (void *handle, const char *name, const char *version_str)
{
ElfW(Addr) caller = (ElfW(Addr)) __builtin_return_address (0);
ElfW(Addr) loadbase;
+ struct r_found_version version;
const ElfW(Sym) *ref = NULL;
void doit (void)
{
@@ -35,7 +37,7 @@ __dlvsym (void *handle, const char *name, const char *version)
/* Search the global scope. */
loadbase = _dl_lookup_versioned_symbol
(name, &ref, &(_dl_global_scope ?: _dl_default_scope)[2], NULL,
- version, 0);
+ &version, 0);
else if (handle == RTLD_NEXT)
{
struct link_map *l, *match;
@@ -55,7 +57,7 @@ RTLD_NEXT used in code not dynamically loaded"));
l = l->l_loader;
loadbase = _dl_lookup_versioned_symbol_skip
- (name, &ref, &_dl_loaded, NULL, version, l, 0);
+ (name, &ref, &_dl_loaded, NULL, &version, l, 0);
}
else
{
@@ -63,10 +65,16 @@ RTLD_NEXT used in code not dynamically loaded"));
struct link_map *map = handle;
struct link_map *mapscope[2] = { map, NULL };
loadbase = _dl_lookup_versioned_symbol
- (name, &ref, mapscope, map->l_name, version, 0);
+ (name, &ref, mapscope, map->l_name, &version, 0);
}
}
+ /* Compute hash value to the version string. */
+ version.name = version_str;
+ version.hash = _dl_elf_hash (version_str);
+ /* We don't have a specific file where the symbol can be found. */
+ version.filename = NULL;
+
return _dlerror_run (doit) ? NULL : (void *) (loadbase + ref->st_value);
}
weak_alias (__dlvsym, dlvsym)
diff --git a/elf/link.h b/elf/link.h
index 58041332e9..b0b920074b 100644
--- a/elf/link.h
+++ b/elf/link.h
@@ -25,6 +25,8 @@
#include <elf.h>
+__BEGIN_DECLS
+
/* We use this macro to refer to ELF types independent of the native wordsize.
`ElfW(TYPE)' is used in place of `Elf32_TYPE' or `Elf64_TYPE'. */
#define ElfW(type) _ElfW (Elf, __ELF_NATIVE_CLASS, type)
@@ -76,11 +78,13 @@ extern ElfW(Dyn) _DYNAMIC[];
/* For the version handling we need an array with only names and their
hash values. */
-typedef struct
-{
- const char *name;
- ElfW(Word) hash;
-} hash_name_pair;
+struct r_found_version
+ {
+ const char *name;
+ ElfW(Word) hash;
+
+ const char *filename;
+ };
/* Structure describing a loaded shared object. The `l_next' and `l_prev'
members form a chain of all the shared objects loaded at startup.
@@ -153,14 +157,14 @@ struct link_map
/* Array with version names. */
unsigned int l_nversions;
- hash_name_pair *l_versions;
+ struct r_found_version *l_versions;
};
/* Test whether given NAME matches any of the names of the given object. */
static inline int
__attribute__ ((unused))
-_dl_does_name_match_p (const char *__name, struct link_map *__map)
+_dl_name_match_p (const char *__name, struct link_map *__map)
{
int __found = strcmp (__name, __map->l_name) == 0;
struct libname_list *__runp = __map->l_libname;
@@ -301,7 +305,7 @@ extern ElfW(Addr) _dl_lookup_versioned_symbol (const char *undef,
const ElfW(Sym) **sym,
struct link_map *symbol_scope[],
const char *reference_name,
- const hash_name_pair *version,
+ const struct r_found_version *version,
int flags);
/* For handling RTLD_NEXT we must be able to skip shared objects. */
@@ -318,7 +322,7 @@ extern ElfW(Addr) _dl_lookup_versioned_symbol_skip (const char *undef,
const ElfW(Sym) **sym,
struct link_map *symbol_scope[],
const char *reference_name,
- const char *version_name,
+ const struct r_found_version *version,
struct link_map *skip_this,
int flags);
@@ -398,5 +402,6 @@ extern void _dl_debug_state (void);
in the `r_ldbase' member. Returns the address of the structure. */
extern struct r_debug *_dl_debug_initialize (ElfW(Addr) ldbase);
+__END_DECLS
#endif /* link.h */