1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-07-29 11:41:21 +03:00
1999-07-24  Ulrich Drepper  <drepper@cygnus.com>

	* elf/dl-fini.c: Handle DT_FINI_ARRAY.
	* elf/link.h (struct link_map): Remove l_init_running.  Add l_runcount
	and l_initcount.
	* elf/dl-init.c: Handle DT_INIT_ARRAY.
	* elf/dynamic-link.h: Change parameters.  Now only get link_map
	pointer.  Calculate l_initcount.

	* elf/link.h (struct link_map): Add l_runpath_dirs.
	* elf/dynamic-link.h: If RUNPATH is given, set RPATH to NULL.
	* elf/dl-load.c: Pretty print.
	(decompose_rpath): Take new parameter with info from where the path
	comes.  Pass it the fillin_rpath.
	(_dl_init_paths): Initialize l_runpath_dirs.
	(_dl_map_object): Don't search using RPATHs if object has RUNPATH.
	Search using RUNPATH after LD_LIBRARY_PATH.
	* elf/dl-support.c: Adjust comment.
	* elf/rtld.c: Adjust help message.
This commit is contained in:
Ulrich Drepper
1999-07-24 19:45:13 +00:00
parent 3f38221989
commit fcf70d4114
8 changed files with 218 additions and 80 deletions

View File

@ -1,3 +1,23 @@
1999-07-24 Ulrich Drepper <drepper@cygnus.com>
* elf/dl-fini.c: Handle DT_FINI_ARRAY.
* elf/link.h (struct link_map): Remove l_init_running. Add l_runcount
and l_initcount.
* elf/dl-init.c: Handle DT_INIT_ARRAY.
* elf/dynamic-link.h: Change parameters. Now only get link_map
pointer. Calculate l_initcount.
* elf/link.h (struct link_map): Add l_runpath_dirs.
* elf/dynamic-link.h: If RUNPATH is given, set RPATH to NULL.
* elf/dl-load.c: Pretty print.
(decompose_rpath): Take new parameter with info from where the path
comes. Pass it the fillin_rpath.
(_dl_init_paths): Initialize l_runpath_dirs.
(_dl_map_object): Don't search using RPATHs if object has RUNPATH.
Search using RUNPATH after LD_LIBRARY_PATH.
* elf/dl-support.c: Adjust comment.
* elf/rtld.c: Adjust help message.
1999-07-24 Andreas Jaeger <aj@arthur.rhein-neckar.de> 1999-07-24 Andreas Jaeger <aj@arthur.rhein-neckar.de>
* elf/rtld.c (dl_main): Adopt to changed _dl_lookup_symbol * elf/rtld.c (dl_main): Adopt to changed _dl_lookup_symbol

View File

@ -1,5 +1,5 @@
/* Call the termination functions of loaded shared objects. /* Call the termination functions of loaded shared objects.
Copyright (C) 1995, 1996, 1998 Free Software Foundation, Inc. Copyright (C) 1995, 1996, 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -28,18 +28,48 @@ _dl_fini (void)
for (l = _dl_loaded; l; l = l->l_next) for (l = _dl_loaded; l; l = l->l_next)
if (l->l_init_called) if (l->l_init_called)
{ {
if (l->l_info[DT_FINI] && int first = 1;
!(l->l_name[0] == '\0' && l->l_type == lt_executable))
/* Make sure nothing happens if we are called twice. */
l->l_init_called = 0;
/* Don't call the destructors for objects we are not supposed to. */
if (l->l_name[0] == '\0' && l->l_type == lt_executable)
continue;
/* First see whether an array is given. */
if (l->l_info[DT_FINI_ARRAY] != NULL)
{
ElfW(Addr) *array =
(ElfW(Addr) *) (l->l_addr
+ l->l_info[DT_FINI_ARRAY]->d_un.d_ptr);
unsigned int sz = (l->l_info[DT_FINI_ARRAYSZ]->d_un.d_val
/ sizeof (ElfW(Addr)));
unsigned int cnt;
for (cnt = 0; cnt < sz; ++cnt)
{ {
/* When debugging print a message first. */ /* When debugging print a message first. */
if (_dl_debug_impcalls) if (_dl_debug_impcalls && first)
_dl_debug_message (1, "\ncalling fini: ",
l->l_name[0] ? l->l_name : _dl_argv[0],
"\n\n", NULL);
first = 0;
(*(void (*) (void)) (l->l_addr + array[cnt])) ();
}
}
/* Next try the old-style destructor. */
if (l->l_info[DT_FINI])
{
/* When debugging print a message first. */
if (_dl_debug_impcalls && first)
_dl_debug_message (1, "\ncalling fini: ", _dl_debug_message (1, "\ncalling fini: ",
l->l_name[0] ? l->l_name : _dl_argv[0], l->l_name[0] ? l->l_name : _dl_argv[0],
"\n\n", NULL); "\n\n", NULL);
(*(void (*) (void)) (l->l_addr + l->l_info[DT_FINI]->d_un.d_ptr)) (); (*(void (*) (void)) (l->l_addr + l->l_info[DT_FINI]->d_un.d_ptr)) ();
} }
/* Make sure nothing happens if we are called twice. */
l->l_init_called = 0;
} }
} }

View File

@ -1,5 +1,5 @@
/* Return the next shared object initializer function not yet run. /* Return the next shared object initializer function not yet run.
Copyright (C) 1995, 1996, 1998 Free Software Foundation, Inc. Copyright (C) 1995, 1996, 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -38,27 +38,28 @@ _dl_init_next (struct r_scope_elem *searchlist)
while (i-- > 0) while (i-- > 0)
{ {
struct link_map *l = searchlist->r_list[i]; struct link_map *l = searchlist->r_list[i];
ElfW(Addr) *array;
if (l->l_init_called) if (l->l_init_called)
/* This object is all done. */ /* This object is all done. */
continue; continue;
if (l->l_init_running) /* Check for object which constructors we do not run here.
XXX Maybe this should be pre-computed, but where? */
if (l->l_name[0] == '\0' && l->l_type == lt_executable)
{ {
/* This object's initializer was just running.
Now mark it as having run, so this object
will be skipped in the future. */
l->l_init_running = 0;
l->l_init_called = 1; l->l_init_called = 1;
continue; continue;
} }
if (l->l_info[DT_INIT] /* Account for running next constructor. */
&& (l->l_name[0] != '\0' || l->l_type != lt_executable)) ++l->l_runcount;
{
/* Run this object's initializer. */
l->l_init_running = 1;
if (l->l_runcount == 1)
{
/* Try running the DT_INIT constructor. */
if (l->l_info[DT_INIT])
{
/* Print a debug message if wanted. */ /* Print a debug message if wanted. */
if (_dl_debug_impcalls) if (_dl_debug_impcalls)
_dl_debug_message (1, "\ncalling init: ", _dl_debug_message (1, "\ncalling init: ",
@ -68,9 +69,28 @@ _dl_init_next (struct r_scope_elem *searchlist)
return l->l_addr + l->l_info[DT_INIT]->d_un.d_ptr; return l->l_addr + l->l_info[DT_INIT]->d_un.d_ptr;
} }
/* No initializer for this object. /* No DT_INIT, so go on with the array. */
Mark it so we will skip it in the future. */ ++l->l_runcount;
}
if (l->l_runcount > l->l_initcount)
{
/* That were all of the constructors. */
l->l_runcount = 0;
l->l_init_called = 1; l->l_init_called = 1;
continue;
}
/* Print a debug message if wanted. */
if (_dl_debug_impcalls && l->l_info[DT_INIT] == NULL
&& l->l_runcount == 2)
_dl_debug_message (1, "\ncalling init: ",
l->l_name[0] ? l->l_name : _dl_argv[0],
"\n\n", NULL);
array = (ElfW(Addr) *) l->l_info[DT_INIT_ARRAY]->d_un.d_ptr;
return l->l_addr + array[l->l_runcount - 2];
/* NOTREACHED */
} }

View File

@ -436,7 +436,7 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep,
static struct r_search_path_elem ** static struct r_search_path_elem **
internal_function internal_function
decompose_rpath (const char *rpath, struct link_map *l) decompose_rpath (const char *rpath, struct link_map *l, const char *what)
{ {
/* Make a copy we can work with. */ /* Make a copy we can work with. */
const char *where = l->l_name; const char *where = l->l_name;
@ -445,7 +445,8 @@ decompose_rpath (const char *rpath, struct link_map *l)
struct r_search_path_elem **result; struct r_search_path_elem **result;
size_t nelems; size_t nelems;
/* First see whether we must forget the RPATH from this object. */ /* First see whether we must forget the RUNPATH and RPATH from this
object. */
if (_dl_inhibit_rpath != NULL && !__libc_enable_secure) if (_dl_inhibit_rpath != NULL && !__libc_enable_secure)
{ {
const char *found = strstr (_dl_inhibit_rpath, where); const char *found = strstr (_dl_inhibit_rpath, where);
@ -455,8 +456,8 @@ decompose_rpath (const char *rpath, struct link_map *l)
if ((found == _dl_inhibit_rpath || found[-1] == ':') if ((found == _dl_inhibit_rpath || found[-1] == ':')
&& (found[len] == '\0' || found[len] == ':')) && (found[len] == '\0' || found[len] == ':'))
{ {
/* This object is on the list of objects for which the RPATH /* This object is on the list of objects for which the
must not be used. */ RUNPATH and RPATH must not be used. */
result = (struct r_search_path_elem **) result = (struct r_search_path_elem **)
malloc (sizeof (*result)); malloc (sizeof (*result));
if (result == NULL) if (result == NULL)
@ -473,7 +474,7 @@ decompose_rpath (const char *rpath, struct link_map *l)
string tokens. */ string tokens. */
copy = expand_dynamic_string_token (l, rpath); copy = expand_dynamic_string_token (l, rpath);
if (copy == NULL) if (copy == NULL)
_dl_signal_error (ENOMEM, NULL, "cannot create RPATH copy"); _dl_signal_error (ENOMEM, NULL, "cannot create RUNPATH/RPATH copy");
/* Count the number of necessary elements in the result array. */ /* Count the number of necessary elements in the result array. */
nelems = 0; nelems = 0;
@ -488,7 +489,7 @@ decompose_rpath (const char *rpath, struct link_map *l)
if (result == NULL) if (result == NULL)
_dl_signal_error (ENOMEM, NULL, "cannot create cache for search path"); _dl_signal_error (ENOMEM, NULL, "cannot create cache for search path");
return fillin_rpath (copy, result, ":", 0, "RPATH", where); return fillin_rpath (copy, result, ":", 0, what, where);
} }
@ -570,16 +571,33 @@ _dl_init_paths (const char *llp)
{ {
assert (l->l_type != lt_loaded); assert (l->l_type != lt_loaded);
if (l->l_info[DT_RUNPATH])
{
/* Allocate room for the search path and fill in information
from RUNPATH. */
l->l_runpath_dirs =
decompose_rpath ((const void *) (l->l_info[DT_STRTAB]->d_un.d_ptr
+ l->l_info[DT_RUNPATH]->d_un.d_val),
l, "RUNPATH");
/* The RPATH is ignored. */
l->l_rpath_dirs = NULL;
}
else
{
l->l_runpath_dirs = NULL;
if (l->l_info[DT_RPATH]) if (l->l_info[DT_RPATH])
/* Allocate room for the search path and fill in information /* Allocate room for the search path and fill in information
from RPATH. */ from RPATH. */
l->l_rpath_dirs = l->l_rpath_dirs =
decompose_rpath ((const void *) (l->l_info[DT_STRTAB]->d_un.d_ptr decompose_rpath ((const void *) (l->l_info[DT_STRTAB]->d_un.d_ptr
+ l->l_info[DT_RPATH]->d_un.d_val), + l->l_info[DT_RPATH]->d_un.d_val),
l); l, "RPATH");
else else
l->l_rpath_dirs = NULL; l->l_rpath_dirs = NULL;
} }
}
#endif /* PIC */ #endif /* PIC */
if (llp != NULL && *llp != '\0') if (llp != NULL && *llp != '\0')
@ -1036,7 +1054,7 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname,
" phnum: ", buf3, "\n\n", NULL); " phnum: ", buf3, "\n\n", NULL);
} }
elf_get_dynamic_info (l->l_ld, l->l_addr, l->l_info); elf_get_dynamic_info (l);
if (l->l_info[DT_HASH]) if (l->l_info[DT_HASH])
_dl_setup_hash (l); _dl_setup_hash (l);
@ -1292,6 +1310,10 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
fd = -1; fd = -1;
/* When the object has the RUNPATH information we don't use any
RPATHs. */
if (loader != NULL && loader->l_info[DT_RUNPATH] == NULL)
{
/* First try the DT_RPATH of the dependent object that caused NAME /* First try the DT_RPATH of the dependent object that caused NAME
to be loaded. Then that object's dependent, and on up. */ to be loaded. Then that object's dependent, and on up. */
for (l = loader; fd == -1 && l; l = l->l_loader) for (l = loader; fd == -1 && l; l = l->l_loader)
@ -1303,7 +1325,7 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
size_t ptrval = (l->l_info[DT_STRTAB]->d_un.d_ptr size_t ptrval = (l->l_info[DT_STRTAB]->d_un.d_ptr
+ l->l_info[DT_RPATH]->d_un.d_val); + l->l_info[DT_RPATH]->d_un.d_val);
l->l_rpath_dirs = l->l_rpath_dirs =
decompose_rpath ((const char *) ptrval, l); decompose_rpath ((const char *) ptrval, l, "RPATH");
} }
if (l->l_rpath_dirs != NULL) if (l->l_rpath_dirs != NULL)
@ -1311,16 +1333,36 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
&realname); &realname);
} }
/* If dynamically linked, try the DT_RPATH of the executable itself. */ /* If dynamically linked, try the DT_RPATH of the executable
itself. */
l = _dl_loaded; l = _dl_loaded;
if (fd == -1 && l && l->l_type != lt_loaded && l != loader if (fd == -1 && l && l->l_type != lt_loaded && l != loader
&& l->l_rpath_dirs != NULL) && l->l_rpath_dirs != NULL)
fd = open_path (name, namelen, preloaded, l->l_rpath_dirs, &realname); fd = open_path (name, namelen, preloaded, l->l_rpath_dirs,
&realname);
}
/* Try the LD_LIBRARY_PATH environment variable. */ /* Try the LD_LIBRARY_PATH environment variable. */
if (fd == -1 && env_path_list != NULL) if (fd == -1 && env_path_list != NULL)
fd = open_path (name, namelen, preloaded, env_path_list, &realname); fd = open_path (name, namelen, preloaded, env_path_list, &realname);
/* Look at the RUNPATH informaiton for this binary. */
if (loader != NULL && loader->l_info[DT_RUNPATH])
{
/* Make sure the cache information is available. */
if (loader->l_runpath_dirs == NULL)
{
size_t ptrval = (loader->l_info[DT_STRTAB]->d_un.d_ptr
+ loader->l_info[DT_RUNPATH]->d_un.d_val);
loader->l_runpath_dirs =
decompose_rpath ((const char *) ptrval, loader, "RUNPATH");
}
if (loader->l_runpath_dirs != NULL)
fd = open_path (name, namelen, preloaded, loader->l_runpath_dirs,
&realname);
}
if (fd == -1) if (fd == -1)
{ {
/* Check the list of libraries in the file /etc/ld.so.cache, /* Check the list of libraries in the file /etc/ld.so.cache,

View File

@ -51,7 +51,8 @@ struct r_search_path *_dl_search_paths;
/* We never do profiling. */ /* We never do profiling. */
const char *_dl_profile; const char *_dl_profile;
/* Names of shared object for which the RPATHs should be ignored. */ /* Names of shared object for which the RUNPATHs and RPATHs should be
ignored. */
const char *_dl_inhibit_rpath; const char *_dl_inhibit_rpath;
/* The map for the object we will profile. */ /* The map for the object we will profile. */

View File

@ -34,13 +34,18 @@ extern int _dl_verbose __attribute__ ((unused));
/* Read the dynamic section at DYN and fill in INFO with indices DT_*. */ /* Read the dynamic section at DYN and fill in INFO with indices DT_*. */
static inline void __attribute__ ((unused)) static inline void __attribute__ ((unused))
elf_get_dynamic_info (ElfW(Dyn) *dyn, ElfW(Addr) l_addr, elf_get_dynamic_info (struct link_map *l)
ElfW(Dyn) *info[DT_NUM + DT_PROCNUM + DT_VERSIONTAGNUM
+ DT_EXTRANUM])
{ {
ElfW(Dyn) *dyn = l->l_ld;
ElfW(Addr) l_addr;
ElfW(Dyn) **info;
if (! dyn) if (! dyn)
return; return;
l_addr = l->l_addr;
info = l->l_info;
while (dyn->d_tag != DT_NULL) while (dyn->d_tag != DT_NULL)
{ {
if (dyn->d_tag < DT_NUM) if (dyn->d_tag < DT_NUM)
@ -106,6 +111,16 @@ elf_get_dynamic_info (ElfW(Dyn) *dyn, ElfW(Addr) l_addr,
if (flags & DF_BIND_NOW) if (flags & DF_BIND_NOW)
info[DT_BIND_NOW] = info[DT_FLAGS]; info[DT_BIND_NOW] = info[DT_FLAGS];
} }
/* Determine how many constructors there are. */
if (info[DT_INIT_ARRAY] != NULL)
info[DT_INIT_ARRAY]->d_un.d_ptr += l_addr;
l->l_initcount = 1 + (info[DT_INIT_ARRAY]
? (info[DT_INIT_ARRAYSZ]->d_un.d_val
/ sizeof (ElfW(Addr)))
: 0);
if (info[DT_RUNPATH] != NULL)
/* If both RUNPATH and RPATH are given, the latter is ignored. */
info[DT_RPATH] = NULL;
} }
#ifdef RESOLVE #ifdef RESOLVE

View File

@ -163,7 +163,6 @@ struct link_map
} l_type:2; } l_type:2;
unsigned int l_relocated:1; /* Nonzero if object's relocations done. */ unsigned int l_relocated:1; /* Nonzero if object's relocations done. */
unsigned int l_init_called:1; /* Nonzero if DT_INIT function called. */ unsigned int l_init_called:1; /* Nonzero if DT_INIT function called. */
unsigned int l_init_running:1; /* Nonzero while DT_INIT function runs. */
unsigned int l_global:1; /* Nonzero if object in _dl_global_scope. */ unsigned int l_global:1; /* Nonzero if object in _dl_global_scope. */
unsigned int l_reserved:2; /* Reserved for internal use. */ unsigned int l_reserved:2; /* Reserved for internal use. */
@ -202,6 +201,16 @@ struct link_map
/* Nonzero if the data structure pointed to by `l_phdr' is allocated. */ /* Nonzero if the data structure pointed to by `l_phdr' is allocated. */
int l_phdr_allocated; int l_phdr_allocated;
/* Counter for running constructors and destructors. */
unsigned int l_runcount;
/* Number of constructors. We compute this during loading to avoid
duplication of this during the possibly many calls to _dl_init_next. */
unsigned int l_initcount;
/* Collected information about own RUNPATH directories. */
struct r_search_path_elem **l_runpath_dirs;
}; };
#endif /* link.h */ #endif /* link.h */

View File

@ -448,7 +448,8 @@ of this helper program; chances are you did not intend to run this program.\n\
object we get handle\n\ object we get handle\n\
--library-path PATH use given PATH instead of content of the environment\n\ --library-path PATH use given PATH instead of content of the environment\n\
variable LD_LIBRARY_PATH\n\ variable LD_LIBRARY_PATH\n\
--inhibit-rpath LIST ignore RPATH information in object names in LIST\n", --inhibit-rpath LIST ignore RUNPATH and RPATH information in object names\n\
in LIST\n",
NULL); NULL);
++_dl_skip_args; ++_dl_skip_args;