2004-09-17  Ulrich Drepper  <drepper@redhat.com>

	* 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.
This commit is contained in:
Ulrich Drepper 2004-09-18 06:46:52 +00:00
parent f04b1e1f0f
commit 7a11603dc6
7 changed files with 74 additions and 5 deletions

View File

@ -1,3 +1,16 @@
2004-09-17 Ulrich Drepper <drepper@redhat.com>
* 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 <jakub@redhat.com> 2004-09-18 Jakub Jelinek <jakub@redhat.com>
* sysdeps/unix/sysv/linux/nscd_setup_thread.c (setup_thread): * sysdeps/unix/sysv/linux/nscd_setup_thread.c (setup_thread):

View File

@ -344,6 +344,9 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
symbol_scope, version, type_class, symbol_scope, version, type_class,
flags, skip_map); flags, skip_map);
/* The object is used. */
current_value.m->l_used = 1;
if (__builtin_expect (GLRO(dl_debug_mask) if (__builtin_expect (GLRO(dl_debug_mask)
& (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0)) & (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0))
_dl_debug_bindings (undef_name, undef_map, ref, symbol_scope, _dl_debug_bindings (undef_name, undef_map, ref, symbol_scope,

View File

@ -50,6 +50,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
--version print version information and exit --version print version information and exit
-d, --data-relocs process data relocations -d, --data-relocs process data relocations
-r, --function-relocs process data and function relocations -r, --function-relocs process data and function relocations
-u, --unused print unused direct dependencies
-v, --verbose print all information -v, --verbose print all information
For bug reporting instructions, please see: For bug reporting instructions, please see:
<http://www.gnu.org/software/libc/bugs.html>." <http://www.gnu.org/software/libc/bugs.html>."
@ -71,6 +72,9 @@ For bug reporting instructions, please see:
verbose=yes verbose=yes
shift shift
;; ;;
-u | --u | --un | --unu | --unus | --unuse | --unused)
unused=yes
shift
--v | --ve | --ver) --v | --ve | --ver)
echo >&2 $"ldd: option \`$1' is ambiguous" echo >&2 $"ldd: option \`$1' is ambiguous"
exit 1 exit 1
@ -97,6 +101,9 @@ nonelf ()
add_env="LD_TRACE_LOADED_OBJECTS=1 LD_WARN=$warn LD_BIND_NOW=$bind_now" add_env="LD_TRACE_LOADED_OBJECTS=1 LD_WARN=$warn LD_BIND_NOW=$bind_now"
add_env="$add_env LD_VERBOSE=$verbose" 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 case $# in
0) 0)
echo >&2 'ldd:' $"missing file arguments" echo >&2 'ldd:' $"missing file arguments"

View File

@ -1526,6 +1526,44 @@ cannot allocate TLS data structures for initial thread");
_dl_printf ("\n"); _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]) else if (! GL(dl_loaded)->l_info[DT_NEEDED])
_dl_printf ("\tstatically linked\n"); _dl_printf ("\tstatically linked\n");
else else
@ -1534,6 +1572,10 @@ cannot allocate TLS data structures for initial thread");
if (l->l_faked) if (l->l_faked)
/* The library was not found. */ /* The library was not found. */
_dl_printf ("\t%s => not found\n", l->l_libname->name); _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 else
_dl_printf ("\t%s => %s (0x%0*Zx)\n", l->l_libname->name, _dl_printf ("\t%s => %s (0x%0*Zx)\n", l->l_libname->name,
l->l_name, (int) sizeof l->l_map_start * 2, 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 }, | DL_DEBUG_BINDINGS | DL_DEBUG_VERSIONS | DL_DEBUG_IMPCALLS },
{ LEN_AND_STR ("statistics"), "display relocation statistics", { LEN_AND_STR ("statistics"), "display relocation statistics",
DL_DEBUG_STATISTICS }, DL_DEBUG_STATISTICS },
{ LEN_AND_STR ("unused"), "determined unused DSOs",
DL_DEBUG_UNUSED },
{ LEN_AND_STR ("help"), "display this help message and exit", { LEN_AND_STR ("help"), "display this help message and exit",
DL_DEBUG_HELP }, DL_DEBUG_HELP },
}; };

View File

@ -189,6 +189,7 @@ struct link_map
unsigned int l_need_tls_init:1; /* Nonzero if GL(dl_init_static_tls) unsigned int l_need_tls_init:1; /* Nonzero if GL(dl_init_static_tls)
should be called on this link map should be called on this link map
when relocation finishes. */ when relocation finishes. */
unsigned int l_used:1; /* Nonzero if the DSO is used. */
/* Array with version names. */ /* Array with version names. */
unsigned int l_nversions; unsigned int l_nversions;
struct r_found_version *l_versions; struct r_found_version *l_versions;

View File

@ -375,9 +375,10 @@ struct rtld_global_ro
#define DL_DEBUG_RELOC (1 << 5) #define DL_DEBUG_RELOC (1 << 5)
#define DL_DEBUG_FILES (1 << 6) #define DL_DEBUG_FILES (1 << 6)
#define DL_DEBUG_STATISTICS (1 << 7) #define DL_DEBUG_STATISTICS (1 << 7)
#define DL_DEBUG_UNUSED (1 << 8)
/* These two are used only internally. */ /* These two are used only internally. */
#define DL_DEBUG_HELP (1 << 8) #define DL_DEBUG_HELP (1 << 9)
#define DL_DEBUG_PRELINK (1 << 9) #define DL_DEBUG_PRELINK (1 << 10)
/* Cached value of `getpagesize ()'. */ /* Cached value of `getpagesize ()'. */
EXTERN size_t _dl_pagesize; EXTERN size_t _dl_pagesize;

View File

@ -293,8 +293,8 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
no_data = 0; \ no_data = 0; \
while (1) { \ while (1) { \
rc = 0; \ rc = 0; \
status = DL_CALL_FCT (fct, (name, _family, &th, tmpbuf, \ status = DL_CALL_FCT (fct, (name, _family, &th, tmpbuf, tmpbuflen, \
tmpbuflen, &rc, &herrno, NULL, &localcanon)); \ &rc, &herrno, NULL, &localcanon)); \
if (rc != ERANGE || herrno != NETDB_INTERNAL) \ if (rc != ERANGE || herrno != NETDB_INTERNAL) \
break; \ break; \
tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen); \ 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); \ pat = &((*pat)->next); \
} \ } \
\ \
if (localcanon != NULL) \ if (localcanon != NULL && canon == NULL) \
canon = strdupa (localcanon); \ canon = strdupa (localcanon); \
\ \
if (_family == AF_INET6 && i > 0) \ if (_family == AF_INET6 && i > 0) \