diff --git a/ChangeLog b/ChangeLog index 768cc8b37b..82f8f3b12c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2004-09-17 Ulrich Drepper + + * include/link.h (struct link_map): Add l_used element. + * sysdeps/generic/ldsodefs.h: Define DL_DEBUG_UNUSED. + * elf/rtld.c (process_dl_debug): Recognize unused. + (dl_main): When unused debug flag is set check for unused direct + dependencies. + When printing dependencies and SONAME starts with /, omit the SONAME => + part. + * elf/dl-lookup.c (_dl_lookup_symbol_x): Mark object in which the + symbol has been found as used. + * elf/ldd.bash.in: Add -u option. + 2004-09-18 Jakub Jelinek * sysdeps/unix/sysv/linux/nscd_setup_thread.c (setup_thread): diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c index 2b73da591a..d2a6976e4e 100644 --- a/elf/dl-lookup.c +++ b/elf/dl-lookup.c @@ -344,6 +344,9 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map, symbol_scope, version, type_class, flags, skip_map); + /* The object is used. */ + current_value.m->l_used = 1; + if (__builtin_expect (GLRO(dl_debug_mask) & (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0)) _dl_debug_bindings (undef_name, undef_map, ref, symbol_scope, diff --git a/elf/ldd.bash.in b/elf/ldd.bash.in index 8867211109..6ee9b60e51 100644 --- a/elf/ldd.bash.in +++ b/elf/ldd.bash.in @@ -50,6 +50,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 + -u, --unused print unused direct dependencies -v, --verbose print all information For bug reporting instructions, please see: ." @@ -71,6 +72,9 @@ For bug reporting instructions, please see: verbose=yes shift ;; + -u | --u | --un | --unu | --unus | --unuse | --unused) + unused=yes + shift --v | --ve | --ver) echo >&2 $"ldd: option \`$1' is ambiguous" exit 1 @@ -97,6 +101,9 @@ nonelf () add_env="LD_TRACE_LOADED_OBJECTS=1 LD_WARN=$warn LD_BIND_NOW=$bind_now" add_env="$add_env LD_VERBOSE=$verbose" +if test "$unused" = yes; then + add_env="$add_env LD_DEBUG="$LD_DEBUG${LD_DEBUG:+,}unused" +fi case $# in 0) echo >&2 'ldd:' $"missing file arguments" diff --git a/elf/rtld.c b/elf/rtld.c index e015477c19..93c45311d4 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -1526,6 +1526,44 @@ cannot allocate TLS data structures for initial thread"); _dl_printf ("\n"); } } + else if (GLRO(dl_debug_mask) & DL_DEBUG_UNUSED) + { + /* Look through the dependencies of the main executable + and determine which of them is not actually + required. */ + struct link_map *l = GL(dl_loaded); + + /* Relocate the main executable. */ + struct relocate_args args = { .l = l, .lazy = GLRO(dl_lazy) }; + _dl_receive_error (print_unresolved, relocate_doit, &args); + + /* This loop depends on the dependencies of the executable to + correspond in number and order to the DT_NEEDED entries. */ + ElfW(Dyn) *dyn = GL(dl_loaded)->l_ld; + bool first = true; + while (dyn->d_tag != DT_NULL) + { + if (dyn->d_tag == DT_NEEDED) + { + l = l->l_next; + + if (!l->l_used) + { + if (first) + { + _dl_printf ("Unused direct dependencies:\n"); + first = false; + } + + _dl_printf ("\t%s\n", l->l_name); + } + } + + ++dyn; + } + + _exit (first != true); + } else if (! GL(dl_loaded)->l_info[DT_NEEDED]) _dl_printf ("\tstatically linked\n"); else @@ -1534,6 +1572,10 @@ cannot allocate TLS data structures for initial thread"); if (l->l_faked) /* The library was not found. */ _dl_printf ("\t%s => not found\n", l->l_libname->name); + else if (l->l_libname->name[0] == '/') + _dl_printf ("\t%s (0x%0*Zx)\n", l->l_libname->name, + (int) sizeof l->l_map_start * 2, + (size_t) l->l_map_start); else _dl_printf ("\t%s => %s (0x%0*Zx)\n", l->l_libname->name, l->l_name, (int) sizeof l->l_map_start * 2, @@ -1962,6 +2004,8 @@ process_dl_debug (const char *dl_debug) | DL_DEBUG_BINDINGS | DL_DEBUG_VERSIONS | DL_DEBUG_IMPCALLS }, { LEN_AND_STR ("statistics"), "display relocation statistics", DL_DEBUG_STATISTICS }, + { LEN_AND_STR ("unused"), "determined unused DSOs", + DL_DEBUG_UNUSED }, { LEN_AND_STR ("help"), "display this help message and exit", DL_DEBUG_HELP }, }; diff --git a/include/link.h b/include/link.h index 5829f3c98f..1567c67c54 100644 --- a/include/link.h +++ b/include/link.h @@ -189,6 +189,7 @@ struct link_map unsigned int l_need_tls_init:1; /* Nonzero if GL(dl_init_static_tls) should be called on this link map when relocation finishes. */ + unsigned int l_used:1; /* Nonzero if the DSO is used. */ /* Array with version names. */ unsigned int l_nversions; struct r_found_version *l_versions; diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index 49f766642c..be3d2dd61f 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -375,9 +375,10 @@ struct rtld_global_ro #define DL_DEBUG_RELOC (1 << 5) #define DL_DEBUG_FILES (1 << 6) #define DL_DEBUG_STATISTICS (1 << 7) +#define DL_DEBUG_UNUSED (1 << 8) /* These two are used only internally. */ -#define DL_DEBUG_HELP (1 << 8) -#define DL_DEBUG_PRELINK (1 << 9) +#define DL_DEBUG_HELP (1 << 9) +#define DL_DEBUG_PRELINK (1 << 10) /* Cached value of `getpagesize ()'. */ EXTERN size_t _dl_pagesize; diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c index c8cb752b18..f9d0bf42fe 100644 --- a/sysdeps/posix/getaddrinfo.c +++ b/sysdeps/posix/getaddrinfo.c @@ -293,8 +293,8 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp, no_data = 0; \ while (1) { \ rc = 0; \ - status = DL_CALL_FCT (fct, (name, _family, &th, tmpbuf, \ - tmpbuflen, &rc, &herrno, NULL, &localcanon)); \ + status = DL_CALL_FCT (fct, (name, _family, &th, tmpbuf, tmpbuflen, \ + &rc, &herrno, NULL, &localcanon)); \ if (rc != ERANGE || herrno != NETDB_INTERNAL) \ break; \ tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen); \ @@ -343,7 +343,7 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp, pat = &((*pat)->next); \ } \ \ - if (localcanon != NULL) \ + if (localcanon != NULL && canon == NULL) \ canon = strdupa (localcanon); \ \ if (_family == AF_INET6 && i > 0) \