From 84384f5b6aaa622236ada8c9a7ff51f40b91fc20 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Wed, 20 Nov 1996 03:45:51 +0000 Subject: update from main archive 961119 Wed Nov 20 02:04:11 1996 Ulrich Drepper * 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 * inet/ether_hton.c: Include . * 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 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 . * 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 * 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 * 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 * 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 * manual/nss.texi (Name Service Switch): Fix reference to `frobnicate'. Fri Nov 15 22:08:33 1996 Andreas Schwab * sysdeps/unix/sysv/linux/Makefile (sysdep_headers): Add sys/mtio.h. Mon Nov 18 05:51:13 1996 Ulrich Drepper * 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 * 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 * stdlib/tst-strtod.c (main): Add arguments for main. * stdlib/tst-strtol.c (main): Likewise. Sun Nov 17 21:15:05 1996 Ulrich Drepper * 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 * stdio-common/vfprintf.c [USE_IN_LIBIO] (buffered_vfprintf): Call __libc_lock_init for local lock. Reported by a sun . [!USE_IN_LIBIO] (PAD): Optimize a bit. --- elf/Makefile | 10 +++ elf/dl-deps.c | 31 +++++++-- elf/dl-lookup.c | 211 ++++++++++++++++++++++++++++++++++++-------------------- elf/dlfcn.h | 6 ++ elf/dlsym.c | 38 +++++++--- elf/ldd.bash.in | 45 +++++++++--- elf/ldd.sh.in | 38 +++++++--- elf/link.h | 13 ++++ 8 files changed, 288 insertions(+), 104 deletions(-) (limited to 'elf') diff --git a/elf/Makefile b/elf/Makefile index 58b3a90..4cb8d7e 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -99,11 +99,21 @@ $(objpfx)libdl.so: $(objpfx)libdl_pic.a $(common-objpfx)libc.so $(objpfx)ld.so $(slibdir)/$(rtld-installed-name): $(objpfx)ld.so; $(do-install-program) +ifneq ($(have-bash2),yes) $(objpfx)ldd: ldd.sh.in Makefile sed -e 's%@RTLD@%$(slibdir)/$(rtld-installed-name)%g' \ -e 's%@VERSION@%$(version)%g' < $< > $@.new chmod 555 $@.new mv -f $@.new $@ +else +$(objpfx)ldd: ldd.bash.in Makefile + sed -e 's%@BASH@%$(BASH)%g' \ + -e 's%@RTLD@%$(slibdir)/$(rtld-installed-name)%g' \ + -e 's%@VERSION@%$(version)%g' \ + -e 's%@TEXTDOMAINDIR@%$(localedir)%g' < $< > $@.new + chmod 555 $@.new + mv -f $@.new $@ +endif # muwahaha diff --git a/elf/dl-deps.c b/elf/dl-deps.c index 977b323..115982f 100644 --- a/elf/dl-deps.c +++ b/elf/dl-deps.c @@ -33,16 +33,24 @@ _dl_map_object_deps (struct link_map *map, struct list *next; }; struct list head[1 + npreloads], *tailp, *scanp; + struct list duphead, *duptailp; unsigned int nlist; + unsigned int nduplist; /* Start the search list with one element: MAP itself. */ head[0].map = map; + /* We use `l_reserved' as a mark bit to detect objects we have already + put in the search list and avoid adding duplicate elements later in + the list. */ + map->l_reserved = 1; + /* Add the preloaded items after MAP but before any of its dependencies. */ for (nlist = 0; nlist < npreloads; ++nlist) { head[nlist].next = &head[nlist + 1]; head[nlist + 1].map = preloads[nlist]; + preloads[nlist]->l_reserved = 1; } /* Terminate the list. */ @@ -51,10 +59,10 @@ _dl_map_object_deps (struct link_map *map, /* Start here for adding dependencies to the list. */ tailp = &head[nlist++]; - /* We use `l_reserved' as a mark bit to detect objects we have already - put in the search list and avoid adding duplicate elements later in - the list. */ - map->l_reserved = 1; + /* Until now we have the same number of libraries in the normal and + the list with duplicates. */ + nduplist = nlist; + duptailp = &duphead; /* Process each element of the search list, loading each of its immediate dependencies and appending them to the list as we step through it. @@ -94,6 +102,13 @@ _dl_map_object_deps (struct link_map *map, /* Set the mark bit that says it's already in the list. */ dep->l_reserved = 1; } + + /* In any case Append DEP to the duplicates search list. */ + duptailp->next = alloca (sizeof *duptailp); + duptailp = duptailp->next; + duptailp->map = dep; + duptailp->next = NULL; + ++nduplist; } } } @@ -112,4 +127,12 @@ _dl_map_object_deps (struct link_map *map, to avoid duplicates, so the next call starts fresh. */ scanp->map->l_reserved = 0; } + + map->l_dupsearchlist = malloc (nduplist * sizeof (struct link_map *)); + map->l_ndupsearchlist = nduplist; + + for (nlist = 0; nlist < npreloads + 1; ++nlist) + map->l_dupsearchlist[nlist] = head[nlist].map; + for (scanp = duphead.next; scanp; scanp = scanp->next) + map->l_dupsearchlist[nlist++] = scanp->map; } 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 +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; } diff --git a/elf/dlfcn.h b/elf/dlfcn.h index b59bebd..c2b66a7 100644 --- a/elf/dlfcn.h +++ b/elf/dlfcn.h @@ -32,6 +32,12 @@ visible as if the object were linked directly into the program. */ #define RTLD_GLOBAL 0x100 +/* If the first argument of `dlsym' is set to RTLD_NEXT the run-time + address of the symbol called NAME in the next shared object is + returned. The "next" relation is defined by the order the shared + objects were loaded. */ +#define RTLD_NEXT ((void *) -1l) + /* Open the shared object FILE and map it in; return a handle that can be passed to `dlsym' to get symbol values from it. */ extern void *dlopen __P ((__const char *__file, int __mode)); diff --git a/elf/dlsym.c b/elf/dlsym.c index edfe1c6..12a29e4 100644 --- a/elf/dlsym.c +++ b/elf/dlsym.c @@ -26,25 +26,43 @@ void * dlsym (void *handle, const char *name) { + ElfW(Addr) caller = (ElfW(Addr)) __builtin_return_address (0); ElfW(Addr) loadbase; const ElfW(Sym) *ref = NULL; void doit (void) { - struct link_map *map = handle, **scope, *mapscope[2] = { map, NULL }; - const char *owner; - - if (map) + if (handle == NULL) + /* Search the global scope. */ + loadbase = _dl_lookup_symbol + (name, &ref, &(_dl_global_scope ?: _dl_default_scope)[2], NULL, 0); + else if (handle == RTLD_NEXT) { - /* Search the scope of the given object. */ - scope = mapscope; - owner = map->l_name; + struct link_map *l, *match; + + /* Find the highest-addressed object that CALLER is not below. */ + match = NULL; + for (l = _dl_loaded; l; l = l->l_next) + if (caller >= l->l_addr && (!match || match->l_addr < l->l_addr)) + match = l; + + if (! match) + _dl_signal_error (0, NULL, _("\ +RTLD_NEXT used in code not dynamically loaded")); + + l = match; + while (l->l_loader) + l = l->l_loader; + + loadbase = _dl_lookup_symbol_skip + (name, &ref, &_dl_loaded, NULL, l, 0); } else { - scope = &(_dl_global_scope ?: _dl_default_scope)[2]; - owner = NULL; + /* Search the scope of the given object. */ + struct link_map *map = handle; + struct link_map *mapscope[2] = { map, NULL }; + loadbase = _dl_lookup_symbol (name, &ref, mapscope, map->l_name, 0); } - loadbase = _dl_lookup_symbol (name, &ref, scope, owner, 0); } return _dlerror_run (doit) ? NULL : (void *) (loadbase + ref->st_value); diff --git a/elf/ldd.bash.in b/elf/ldd.bash.in index e7ad21f..5269708f 100644 --- a/elf/ldd.bash.in +++ b/elf/ldd.bash.in @@ -1,24 +1,50 @@ #! @BASH@ +# Copyright (C) 1996 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. + + # This is the `ldd' command, which lists what shared libraries are # used by given dynamically-linked executables. It works by invoking the # run-time dynamic linker as a command and setting the environment # variable LD_TRACE_LOADED_OBJECTS to a non-empty value. +# We should be able to find the translation right at the beginning. +TEXTDOMAIN=libc +TEXTDOMAINDIR=@TEXTDOMAINDIR@ + RTLD=@RTLD@ -usage=$"\ -ldd [OPTION]... FILE... - --help print this help and exit - --version print version information and exit -Report bugs to ." while test $# -gt 0; do case "$1" in --v*) - echo 'ldd (GNU libc) @VERSION@'; exit 0 ;; + echo $"ldd (GNU libc) @VERSION@ +Copyright (C) 1996 Free Software Foundation, Inc. +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + exit 0 ;; --h*) - echo "$usage"; exit 0 ;; - --) # Stop option prcessing + echo $"ldd [OPTION]... FILE... + --help print this help and exit + --version print version information and exit +Report bugs to ." + exit 0 ;; + --) # Stop option prcessing. shift; break ;; *) break ;; @@ -64,3 +90,6 @@ Try \`ldd --help' for more information." esac exit 0 +# Local Variables: +# mode:ksh +# End: diff --git a/elf/ldd.sh.in b/elf/ldd.sh.in index 16d3fd8..f8df62d 100644 --- a/elf/ldd.sh.in +++ b/elf/ldd.sh.in @@ -1,24 +1,46 @@ #! /bin/sh +# Copyright (C) 1996 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. + + # This is the `ldd' command, which lists what shared libraries are # used by given dynamically-linked executables. It works by invoking the # run-time dynamic linker as a command and setting the environment # variable LD_TRACE_LOADED_OBJECTS to a non-empty value. RTLD=@RTLD@ -usage="\ -ldd [OPTION]... FILE... - --help print this help and exit - --version print version information and exit -Report bugs to ." while test $# -gt 0; do case "$1" in --v*) - echo 'ldd (GNU libc) @VERSION@'; exit 0 ;; + echo 'ldd (GNU libc) @VERSION@ +Copyright (C) 1996 Free Software Foundation, Inc. +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.' + exit 0 ;; --h*) - echo "$usage"; exit 0 ;; - --) # Stop option prcessing + echo 'ldd [OPTION]... FILE... + --help print this help and exit + --version print version information and exit +Report bugs to .' + exit 0 ;; + --) # Stop option prcessing. shift; break ;; *) break ;; diff --git a/elf/link.h b/elf/link.h index 17fea30..b277bf7 100644 --- a/elf/link.h +++ b/elf/link.h @@ -109,6 +109,11 @@ struct link_map struct link_map **l_searchlist; unsigned int l_nsearchlist; + /* We keep another list in which we keep duplicates. This is + needed in _dl_lookup_symbol_skip to implemented RTLD_NEXT. */ + struct link_map **l_dupsearchlist; + unsigned int l_ndupsearchlist; + /* Dependent object that first caused this object to be loaded. */ struct link_map *l_loader; @@ -239,6 +244,14 @@ extern ElfW(Addr) _dl_lookup_symbol (const char *undef, const char *reference_name, int flags); +/* For handling RTLD_NEXT we must be able to skip shared objects. */ +extern ElfW(Addr) _dl_lookup_symbol_skip (const char *undef, + const ElfW(Sym) **sym, + struct link_map *symbol_scope[], + const char *reference_name, + struct link_map *skip_this, + int flags); + /* Look up symbol NAME in MAP's scope and return its run-time address. */ extern ElfW(Addr) _dl_symbol_value (struct link_map *map, const char *name); -- cgit v1.1