diff options
author | Ulrich Drepper <drepper@redhat.com> | 1996-11-20 03:45:51 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 1996-11-20 03:45:51 +0000 |
commit | 84384f5b6aaa622236ada8c9a7ff51f40b91fc20 (patch) | |
tree | a44eb8cd85e2a868fa8cd24f8c9cf7fc7d0e7f8c /elf/dl-lookup.c | |
parent | c44db1b1985cb3c41ea9cd76fc5dd60edd087842 (diff) | |
download | glibc-84384f5b6aaa622236ada8c9a7ff51f40b91fc20.zip glibc-84384f5b6aaa622236ada8c9a7ff51f40b91fc20.tar.gz glibc-84384f5b6aaa622236ada8c9a7ff51f40b91fc20.tar.bz2 |
update from main archive 961119cvs/libc-961126cvs/libc-961125cvs/libc-961124cvs/libc-961123cvs/libc-961122cvs/libc-961120
Wed Nov 20 02:04:11 1996 Ulrich Drepper <drepper@cygnus.com>
* sysdeps/unix/sysv/linux/sigsuspend.c: Make sigsuspend a weak
alias of __sigsuspend.
* grp/grp.h: Correct comment about POSIX compliance.
* pwd/pwd.h: Likewise.
* login/utmp.h: Update copyright and pretty-print prototypes.
* sysdeps/generic/paths.h: Add _PATH_LASTLOG, _PATH_UTMP and
_PATH_WTMP from utmpbits.h.
* sysdeps/unix/sysv/linux/paths.h: Likewise.
* sysdeps/generic/utmpbits.h: Remove here.
* sysdeps/gnu/utmpbits.h: Likewise.
* misc/sys/uio.h: Place __BEGIN_DECLS correctly.
Pretty-print prototypes.
* sysdeps/unix/sysv/linux/sparc/clone.S: New file. Taken from
LinuxThreads-0.5.
Tue Nov 19 13:43:07 1996 Richard Henderson <rth@tamu.edu>
* inet/ether_hton.c: Include <string.h>.
* inet/ether_ntoh.c: Likewise.
* inet/rexec.c: Get errno, index, getpass, getlogin from headers.
* misc/search.h: Fix hcreate_r argument type (unsigned -> size_t).
* misc/sys/cdefs.h: Change __long_double_t definition from typedef
to define. Jim Nance reports problems building XEmacs otherwise.
* resolv/gethnamaddr.c: Protect h_errno redefinition.
* resolv/getnetnamadr.c: Likewise.
* resolv/herror.c: Likewise.
* sysdeps/generic/sigset.h (__SIGSETFN): Operator ## doesn't work
with -traditional. Reported by Eric Youngdale. While we're at this,
don't do error checking in the __ functions. This is consistent
with the sysv4 definitions and seems Right.
* signal/signal.h: Don't __OPTIMIZE__ sigops to __ versions. Add
prototype for __sigsuspend.
* sysdeps/posix/sigblock.c: Optimize sigmask <-> sigset_t conversions
for sigset_t == unsigned long. De-ansidecl-ify. Reformat copyright.
* sysdeps/posix/sigpause.c: Likewise.
* sysdeps/posix/sigsetmask.c: Likewise.
* sysdeps/posix/sigvec.c: Likewise.
* sysdeps/posix/sigintr.c: Reformat copyright.
* sysdeps/posix/signal.c: Check signal number out of range since
__sigismember doesn't anymore. Reformat copyright.
* sysdeps/posix/sigwait.c: Use __ versions of sigfillset, sigismember,
sigdelset, sigaction, and sigsuspend.
* stdlib/drand48-iter.c (__drand48_iterate): Cast state fragments
to the wider type before shifting.
* sysdeps/alpha/bsd-_setjmp.S: Silence assembler warning "$at used
without .set noat" in profiling hook.
* sysdeps/alpha/bsd-setjmp.S: Likewise.
* sysdeps/alpha/htonl.S: Likewise.
* sysdeps/alpha/htons.S: Likewise.
* sysdeps/alpha/s_copysign.S: Likewise.
* sysdeps/alpha/setjmp.S: Likewise.
* sysdeps/alpha/stpcpy.S: Likewise.
* sysdeps/alpha/strcat.S: Likewise.
* sysdeps/alpha/strcpy.S: Likewise.
* sysdeps/alpha/strncat.S: Likewise.
* sysdeps/unix/sysv/linux/alpha/brk.S: Likewise.
* sysdeps/unix/sysv/linux/alpha/clone.S: Likewise.
* sysdeps/unix/sysv/linux/alpha/ieee_get_fp_control.S: Likewise.
* sysdeps/unix/sysv/linux/alpha/ieee_set_fp_control.S: Likewise.
* sysdeps/unix/sysv/linux/alpha/llseek.S: Likewise.
* sysdeps/unix/sysv/linux/alpha/sigsuspend.S: Likewise. Rename
function to __sigsuspend and add weak alias.
* sysdeps/unix/sysv/linux/alpha/syscall.S: Likewise. Add missing END.
* sysdeps/alpha/w_sqrt.S: Define _ERRNO_H so <errnos.h> defines EDOM.
* sysdeps/unix/execve.S: Match PSEUDO_END symbol with the symbol
SYSCALL__ actually generated.
* sysdeps/unix/sysv/linux/errnos.h [_LIBC_REENTRANT]: Reflexively
#define __set_errno, as several imported subsystems (eg. BIND) check
that the symbol is defined.
* sysdeps/unix/sysv/linux/getsysstats.c: Include <alloca.h>.
* sysdeps/alpha/memcpy.S: Temporarily remove until I can find a bug
that manifests in GCC.
Tue Nov 19 11:10:05 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
* sysdeps/posix/writev.c (writev): COUNT parm is now int.
* sysdeps/posix/readv.c (readv): Likewise.
Tue Nov 19 15:28:29 1996 Ulrich Drepper <drepper@cygnus.com>
* nss/nss_dns/dns-network.c: Change return type of all functions
to enum nss_status.
Reported by NIIBE Yutaka.
* nss/nss_dns/dns-host.c: Update copyright.
Fri Nov 15 20:16:38 1996 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
* config.make.in: Remove definition of top_absdir.
* configure.in: Likewise. Use $(..) instead.
* Makerules (make-link): Use $(..) to find rellns-sh script.
Sat Nov 16 15:52:29 1996 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
* manual/nss.texi (Name Service Switch): Fix reference to
`frobnicate'.
Fri Nov 15 22:08:33 1996 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
* sysdeps/unix/sysv/linux/Makefile (sysdep_headers): Add
sys/mtio.h.
Mon Nov 18 05:51:13 1996 Ulrich Drepper <drepper@cygnus.com>
* sysdeps/generic/waitstatus.h (__WIFSIGNALED): Rename local
variable from __stat to __status to prevent shadowing.
* sunrpc/rpc/clnt.h (clntudp_create, clntudp_bufcreate): Likewise
for parameter __wait.
Reported by NIIBE Yutaka.
Mon Nov 18 02:05:38 1996 Ulrich Drepper <drepper@cygnus.com>
* misc/regexp.c: New file. Implementation of obsolete interface
to regular expression matcher (required in XPG4.2).
* misc/regexp.h: New file. Header for above.
* misc/Makefile (headers): Add regexp.h.
(routines): Add regexp.c.
Update copyright.
Sun Nov 17 21:50:24 1996 Andreas Jaeger <aj@arthur.pfalz.de>
* stdlib/tst-strtod.c (main): Add arguments for main.
* stdlib/tst-strtol.c (main): Likewise.
Sun Nov 17 21:15:05 1996 Ulrich Drepper <drepper@cygnus.com>
* configure.in: Substitute libc_cv_slibdir and libc_cv_sysconfdir
in output files.
* sysdepes/unix/sysv/linux/configure: Define libc_cv_slibdir to /lib
and sysconfdir to /etc if $prefix is /usr.
* config.make.in: Add slibdir, sysconfdir and BASH to be replaced.
* elf/Makefile ($(objpfx)ldd): Install ldd.bash.in if
$(have-bash2) is yes.
* elf/ldd.bash.in: Add copyright and various cleanups.
* elf/ldd.sh.in: Likewise.
Implement RTLD_NEXT.
* elf/dlfcn.h: Define RTLD_NEXT.
* elf/dl-deps.c: Build second searchlist which contains duplicates.
* elf/dl-lookup.c (_dl_lookup_symbol_skip): New function. Used
for RTLD_NEXT lookup.
Rewrite _dl_lookup_symbol to put common parts for both lookup
functions in a separate function.
* elf/dlsym.c: Handle RTLD_NEXT by calling _dl_lookup_symbol_skip.
* elf/link.h (struct link_map): Add l_dupsearchlist and
l_ndupsearchlist.
Add prototype for _dl_lookup_symbol_skip.
* sunrpc/Makefile (rpcsvc): Add rusers.
* sunrpc/rpcsvc/rnusers.x: Remove. Obsolteted by rusers.x.
* sunrpc/rpcsvc/rusers.x: New file.
Sun Nov 17 04:24:35 1996 Ulrich Drepper <drepper@cygnus.com>
* stdio-common/vfprintf.c [USE_IN_LIBIO] (buffered_vfprintf): Call
__libc_lock_init for local lock.
Reported by a sun <asun@zoology.washington.edu>.
[!USE_IN_LIBIO] (PAD): Optimize a bit.
Diffstat (limited to 'elf/dl-lookup.c')
-rw-r--r-- | elf/dl-lookup.c | 211 |
1 files changed, 137 insertions, 74 deletions
diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c index f35bbbe..717ac83 100644 --- a/elf/dl-lookup.c +++ b/elf/dl-lookup.c @@ -23,6 +23,13 @@ #include <string.h> +struct sym_val + { + ElfW(Addr) a; + const ElfW(Sym) *s; + }; + + /* This is the hashing function specified by the ELF ABI. */ static inline unsigned _dl_elf_hash (const char *name) @@ -44,6 +51,90 @@ _dl_elf_hash (const char *name) return hash; } + +/* Inner part of the lookup functions. */ +static inline ElfW(Addr) +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, struct link_map *skip, int flags) +{ + struct link_map *map; + + for (; i < n; ++i) + { + const ElfW(Sym) *symtab; + const char *strtab; + ElfW(Symndx) symidx; + + map = list[i]; + + /* Here come the extra test needed for `_dl_lookup_symbol_skip'. */ + if (skip != NULL && map == skip) + continue; + + /* Don't search the executable when resolving a copy reloc. */ + if (flags & DL_LOOKUP_NOEXEC && map->l_type == lt_executable) + continue; + + 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); + + /* Search the appropriate hash bucket in this object's symbol table + for a definition for the same symbol name. */ + for (symidx = map->l_buckets[hash % map->l_nbuckets]; + symidx != STN_UNDEF; + symidx = map->l_chain[symidx]) + { + const ElfW(Sym) *sym = &symtab[symidx]; + + if (sym->st_value == 0 || /* No value. */ + ((flags & DL_LOOKUP_NOPLT) != 0 /* Reject PLT entry. */ + && sym->st_shndx == SHN_UNDEF)) + continue; + + switch (ELFW(ST_TYPE) (sym->st_info)) + { + case STT_NOTYPE: + case STT_FUNC: + case STT_OBJECT: + break; + default: + /* Not a code/data definition. */ + continue; + } + + if (sym != *ref && strcmp (strtab + sym->st_name, undef_name)) + /* Not the symbol we are looking for. */ + continue; + + switch (ELFW(ST_BIND) (sym->st_info)) + { + case STB_GLOBAL: + /* Global definition. Just what we need. */ + result->s = sym; + result->a = map->l_addr; + return 1; + case STB_WEAK: + /* Weak definition. Use this value if we don't find + another. */ + if (! result->s) + { + result->s = sym; + result->a = map->l_addr; + } + break; + default: + /* Local symbols are ignored. */ + break; + } + } + } + + /* We have not found anything until now. */ + return 0; +} + /* Search loaded objects' symbol tables for a definition of the symbol UNDEF_NAME. FLAGS is a set of flags. If DL_LOOKUP_NOEXEC is set, then don't search the executable for a definition; this used for @@ -57,82 +148,17 @@ _dl_lookup_symbol (const char *undef_name, const ElfW(Sym) **ref, int flags) { const unsigned long int hash = _dl_elf_hash (undef_name); - struct - { - ElfW(Addr) a; - const ElfW(Sym) *s; - } weak_value = { 0, NULL }; - size_t i; - struct link_map **scope, *map; + struct sym_val current_value = { 0, NULL }; + struct link_map **scope; /* Search the relevant loaded objects for a definition. */ for (scope = symbol_scope; *scope; ++scope) - for (i = 0; i < (*scope)->l_nsearchlist; ++i) - { - const ElfW(Sym) *symtab; - const char *strtab; - ElfW(Symndx) symidx; - - map = (*scope)->l_searchlist[i]; - - /* Don't search the executable when resolving a copy reloc. */ - if (flags & DL_LOOKUP_NOEXEC && map->l_type == lt_executable) - continue; - - 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); - - /* Search the appropriate hash bucket in this object's symbol table - for a definition for the same symbol name. */ - for (symidx = map->l_buckets[hash % map->l_nbuckets]; - symidx != STN_UNDEF; - symidx = map->l_chain[symidx]) - { - const ElfW(Sym) *sym = &symtab[symidx]; - - if (sym->st_value == 0 || /* No value. */ - ((flags & DL_LOOKUP_NOPLT) != 0 /* Reject PLT entry. */ - && sym->st_shndx == SHN_UNDEF)) - continue; - - switch (ELFW(ST_TYPE) (sym->st_info)) - { - case STT_NOTYPE: - case STT_FUNC: - case STT_OBJECT: - break; - default: - /* Not a code/data definition. */ - continue; - } - - if (sym != *ref && strcmp (strtab + sym->st_name, undef_name)) - /* Not the symbol we are looking for. */ - continue; + if (do_lookup (undef_name, hash, ref, ¤t_value, + (*scope)->l_searchlist, 0, (*scope)->l_nsearchlist, + reference_name, NULL, flags)) + break; - switch (ELFW(ST_BIND) (sym->st_info)) - { - case STB_GLOBAL: - /* Global definition. Just what we need. */ - *ref = sym; - return map->l_addr; - case STB_WEAK: - /* Weak definition. Use this value if we don't find - another. */ - if (! weak_value.s) - { - weak_value.s = sym; - weak_value.a = map->l_addr; - } - break; - default: - /* Local symbols are ignored. */ - break; - } - } - } - - if (weak_value.s == NULL && + if (current_value.s == NULL && (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)) { /* We could find no value for a strong reference. */ @@ -144,8 +170,45 @@ _dl_lookup_symbol (const char *undef_name, const ElfW(Sym) **ref, _dl_signal_error (0, reference_name, buf); } - *ref = weak_value.s; - return weak_value.a; + *ref = current_value.s; + return current_value.a; +} + + +/* This function is nearly the same as `_dl_lookup_symbol' but it + skips in the first list all objects until SKIP_MAP is found. I.e., + it only considers objects which were loaded after the described + object. If there are more search lists the object described by + SKIP_MAP is only skipped. */ +ElfW(Addr) +_dl_lookup_symbol_skip (const char *undef_name, const ElfW(Sym) **ref, + struct link_map *symbol_scope[], + const char *reference_name, + struct link_map *skip_map, + int flags) +{ + int found_entry = 0; + const unsigned long int hash = _dl_elf_hash (undef_name); + struct sym_val current_value = { 0, NULL }; + struct link_map **scope; + size_t i; + + /* Search the relevant loaded objects for a definition. */ + scope = symbol_scope; + for (i = 0; (*scope)->l_dupsearchlist[i] != skip_map; ++i) + assert (i < (*scope)->l_ndupsearchlist); + + if (! do_lookup (undef_name, hash, ref, ¤t_value, + (*scope)->l_dupsearchlist, i, (*scope)->l_ndupsearchlist, + reference_name, skip_map, flags)) + while (*++scope) + if (do_lookup (undef_name, hash, ref, ¤t_value, + (*scope)->l_dupsearchlist, 0, (*scope)->l_ndupsearchlist, + reference_name, skip_map, flags)) + break; + + *ref = current_value.s; + return current_value.a; } |