diff options
author | Ulrich Drepper <drepper@redhat.com> | 1997-02-19 04:43:53 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 1997-02-19 04:43:53 +0000 |
commit | 1fb05e3db1891142410bc58c320dfe281749fffe (patch) | |
tree | 46299dbecec282055e3493787910444e77099fe7 /elf/dl-lookup.c | |
parent | c84142e8fe3cbcce43ae35ac957a74ac8216d11d (diff) | |
download | glibc-1fb05e3db1891142410bc58c320dfe281749fffe.tar.gz glibc-1fb05e3db1891142410bc58c320dfe281749fffe.tar.xz glibc-1fb05e3db1891142410bc58c320dfe281749fffe.zip |
update from main archive 970218 cvs/libc-970221 cvs/libc-970220 cvs/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/dl-lookup.c')
-rw-r--r-- | elf/dl-lookup.c | 187 |
1 files changed, 93 insertions, 94 deletions
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, ¤t_value, - (*scope)->l_searchlist, 0, (*scope)->l_nsearchlist, - reference_name, version, NULL, flags)) - break; + { + int res = do_lookup (undef_name, hash, ref, ¤t_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, ¤t_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, ¤t_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; |