diff options
Diffstat (limited to 'elf')
-rw-r--r-- | elf/ldd.bash.in | 14 | ||||
-rw-r--r-- | elf/ldd.sh.in | 13 | ||||
-rw-r--r-- | elf/libdl.map | 2 | ||||
-rw-r--r-- | elf/rtld.c | 166 |
4 files changed, 174 insertions, 21 deletions
diff --git a/elf/ldd.bash.in b/elf/ldd.bash.in index c433a72679..809c2717da 100644 --- a/elf/ldd.bash.in +++ b/elf/ldd.bash.in @@ -31,14 +31,16 @@ TEXTDOMAINDIR=@TEXTDOMAINDIR@ RTLD=@RTLD@ warn= bind_now= +verbose= while test $# -gt 0; do case "$1" in - --v | --ve | --ver | --vers | --versi | --versio | --version) + --vers | --versi | --versio | --version) echo 'ldd (GNU libc) @VERSION@' echo $"Copyright (C) 1996, 1997 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." +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +Written by Roland McGrath and Ulrich Drepper." exit 0 ;; --h | --he | --hel | --help) echo $"ldd [OPTION]... FILE... @@ -46,6 +48,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." --version print version information and exit -d, --data-relocs process data relocations -r, --function-relocs process data and function relocations + -v, --verbose print all information Report bugs using the \`glibcbug' script to <bugs@gnu.ai.mit.edu>." exit 0 ;; -d | --d | --da | --dat | --data | --data- | --data-r | --data-re | \ @@ -58,6 +61,12 @@ Report bugs using the \`glibcbug' script to <bugs@gnu.ai.mit.edu>." warn=yes bind_now=yes shift ;; + -v | --verb | --verbo | --verbos | --verbose) + verbose=yes + shift ;; + --v | --ve | --ver) + echo >&2 $"ldd: option \`" $1 $"' is ambiguous" + exit 1 ;; --) # Stop option processing. shift; break ;; -*) @@ -70,6 +79,7 @@ Report bugs using the \`glibcbug' script to <bugs@gnu.ai.mit.edu>." done add_env="LD_TRACE_LOADED_OBJECTS=1 LD_WARN=$warn LD_BIND_NOW=$bind_now" +add_env="$add_env LD_VERBOSE=$verbose" case $# in 0) echo >&2 'ldd:' $"missing file arguments" diff --git a/elf/ldd.sh.in b/elf/ldd.sh.in index d5dd54a536..908a26e269 100644 --- a/elf/ldd.sh.in +++ b/elf/ldd.sh.in @@ -30,11 +30,12 @@ bind_now= while test $# -gt 0; do case "$1" in - --v | --ve | --ver | --vers | --versi | --versio | --version) + --vers | --versi | --versio | --version) echo 'ldd (GNU libc) @VERSION@ Copyright (C) 1996, 1997 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.' +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +Written by Roland McGrath and Ulrich Drepper.' exit 0 ;; --h | --he | --hel | --help) echo "ldd [OPTION]... FILE... @@ -42,6 +43,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.' --version print version information and exit -d, --data-relocs process data relocations -r, --function-relocs process data and function relocations + -v, --verbose print all information Report bugs using the \`glibcbug' script to <bugs@gnu.ai.mit.edu>." exit 0 ;; -d | --d | --da | --dat | --data | --data- | --data-r | --data-re | \ @@ -54,6 +56,12 @@ Report bugs using the \`glibcbug' script to <bugs@gnu.ai.mit.edu>." warn=yes bind_now=yes shift ;; + -v | --verb | --verbo | --verbos | --verbose) + verbose=yes + shift ;; + --v | --ve | --ver) + echo >&2 "ldd: option \`$1' is ambiguous" + exit 1 ;; --) # Stop option processing. shift; break ;; -*) @@ -67,6 +75,7 @@ Try \`ldd --help' for more information." done add_env="LD_TRACE_LOADED_OBJECTS=1 LD_WARN=$warn LD_BIND_NOW=$bind_now" +add_env="$add_env LD_VERBOSE=$verbose" case $# in 0) echo >&2 "\ diff --git a/elf/libdl.map b/elf/libdl.map index d950382346..4bd2145a47 100644 --- a/elf/libdl.map +++ b/elf/libdl.map @@ -4,4 +4,4 @@ GLIBC_2.0 { local: *; -}; \ No newline at end of file +}; diff --git a/elf/rtld.c b/elf/rtld.c index ffa569e729..78ca490447 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -23,7 +23,7 @@ #include <string.h> #include <unistd.h> #include <sys/mman.h> /* Check if MAP_ANON is defined. */ -#include "../stdio-common/_itoa.h" +#include <stdio-common/_itoa.h> #include <assert.h> #include "dynamic-link.h" @@ -188,6 +188,54 @@ version_check_doit (void *a) _exit (1); } + +static inline struct link_map * +find_needed (const char *name) +{ + unsigned int n; + + for (n = 0; n < _dl_loaded->l_nsearchlist; ++n) + if (_dl_name_match_p (name, _dl_loaded->l_searchlist[n])) + return _dl_loaded->l_searchlist[n]; + + /* Should never happen. */ + return NULL; +} + +static int +match_version (const char *string, struct link_map *map) +{ + const char *strtab = (const char *) (map->l_addr + + map->l_info[DT_STRTAB]->d_un.d_ptr); + ElfW(Verdef) *def; + +#define VERDEFTAG (DT_NUM + DT_PROCNUM + DT_VERSIONTAGIDX (DT_VERDEF)) + if (map->l_info[VERDEFTAG] == NULL) + /* The file has no symbol versioning. */ + return 0; + + def = (ElfW(Verdef) *) ((char *) map->l_addr + + map->l_info[VERDEFTAG]->d_un.d_ptr); + while (1) + { + ElfW(Verdaux) *aux = (ElfW(Verdaux) *) ((char *) def + def->vd_aux); + + /* Compare the version strings. */ + if (strcmp (string, strtab + aux->vda_name) == 0) + /* Bingo! */ + return 1; + + /* If no more definitions we failed to find what we want. */ + if (def->vd_next == 0) + break; + + /* Next definition. */ + def = (ElfW(Verdef) *) ((char *) def + def->vd_next); + } + + return 0; +} + unsigned int _dl_skip_args; /* Nonzero if we were run directly. */ static void @@ -576,27 +624,113 @@ of this helper program; chances are you did not intend to run this program.\n", *--bp = '0'; _dl_sysdep_message (" in object at 0x", bp, "\n", NULL); } - else if (lazy >= 0) + else { - /* We have to do symbol dependency testing. */ - struct relocate_args args; - struct link_map *l; + if (lazy >= 0) + { + /* We have to do symbol dependency testing. */ + struct relocate_args args; + struct link_map *l; - args.lazy = lazy; + args.lazy = lazy; - l = _dl_loaded; - while (l->l_next) - l = l->l_next; - do + l = _dl_loaded; + while (l->l_next) + l = l->l_next; + do + { + if (l != &_dl_rtld_map && l->l_opencount > 0) + { + args.l = l; + _dl_receive_error (print_unresolved, relocate_doit, + &args); + *_dl_global_scope_end = NULL; + } + l = l->l_prev; + } while (l); + } + +#define VERNEEDTAG (DT_NUM + DT_PROCNUM + DT_VERSIONTAGIDX (DT_VERNEED)) + if (*(getenv ("LD_VERBOSE") ?: "") != '\0') { - if (l != &_dl_rtld_map && l->l_opencount > 0) + /* Print more information. This means here, print information + about the versions needed. */ + int first = 1; + struct link_map *map = _dl_loaded; + + for (map = _dl_loaded; map != NULL; map = map->l_next) { - args.l = l; - _dl_receive_error (print_unresolved, relocate_doit, &args); - *_dl_global_scope_end = NULL; + const char *strtab = + (const char *) (map->l_addr + + map->l_info[DT_STRTAB]->d_un.d_ptr); + ElfW(Dyn) *dyn = map->l_info[VERNEEDTAG]; + + if (dyn != NULL) + { + ElfW(Verneed) *ent = + (ElfW(Verneed) *) (map->l_addr + dyn->d_un.d_ptr); + + if (first) + { + _dl_sysdep_message ("\n\tVersion information:\n", + NULL); + first = 0; + } + + _dl_sysdep_message ("\t", (map->l_name[0] + ? map->l_name + : _dl_argv[0]), ":\n", + NULL); + + while (1) + { + ElfW(Vernaux) *aux; + struct link_map *needed; + + needed = find_needed (strtab + ent->vn_file); + aux = (ElfW(Vernaux) *) ((char *) ent + ent->vn_aux); + + while (1) + { + const char *fname = NULL; + + _dl_sysdep_message ("\t\t", + strtab + ent->vn_file, + " (", strtab + aux->vna_name, + ") ", + (aux->vna_flags + & VER_FLG_WEAK + ? "[WEAK] " : ""), + "=> ", NULL); + + if (needed != NULL + && match_version (strtab + aux->vna_name, + needed)) + fname = needed->l_name; + + _dl_sysdep_message (fname ?: "not found", "\n", + NULL); + + if (aux->vna_next == 0) + /* No more symbols. */ + break; + + /* Next symbol. */ + aux = (ElfW(Vernaux) *) ((char *) aux + + aux->vna_next); + } + + if (ent->vn_next == 0) + /* No more dependencies. */ + break; + + /* Next dependency. */ + ent = (ElfW(Verneed) *) ((char *) ent + + ent->vn_next); + } + } } - l = l->l_prev; - } while (l); + } } _exit (0); |