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>
* 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.
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.
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)
if (l->l_init_called)
{
if (l->l_info[DT_FINI] &&
!(l->l_name[0] == '\0' && l->l_type == lt_executable))
int first = 1;
/* 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. */
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)
if (_dl_debug_impcalls && first)
_dl_debug_message (1, "\ncalling fini: ",
l->l_name[0] ? l->l_name : _dl_argv[0],
"\n\n", NULL);
(*(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.
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.
The GNU C Library is free software; you can redistribute it and/or
@ -38,39 +38,59 @@ _dl_init_next (struct r_scope_elem *searchlist)
while (i-- > 0)
{
struct link_map *l = searchlist->r_list[i];
ElfW(Addr) *array;
if (l->l_init_called)
/* This object is all done. */
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;
continue;
}
if (l->l_info[DT_INIT]
&& (l->l_name[0] != '\0' || l->l_type != lt_executable))
/* Account for running next constructor. */
++l->l_runcount;
if (l->l_runcount == 1)
{
/* Run this object's initializer. */
l->l_init_running = 1;
/* Try running the DT_INIT constructor. */
if (l->l_info[DT_INIT])
{
/* Print a debug message if wanted. */
if (_dl_debug_impcalls)
_dl_debug_message (1, "\ncalling init: ",
l->l_name[0] ? l->l_name : _dl_argv[0],
"\n\n", NULL);
/* Print a debug message if wanted. */
if (_dl_debug_impcalls)
_dl_debug_message (1, "\ncalling init: ",
l->l_name[0] ? l->l_name : _dl_argv[0],
"\n\n", NULL);
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 DT_INIT, so go on with the array. */
++l->l_runcount;
}
/* No initializer for this object.
Mark it so we will skip it in the future. */
l->l_init_called = 1;
if (l->l_runcount > l->l_initcount)
{
/* That were all of the constructors. */
l->l_runcount = 0;
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

@ -35,7 +35,7 @@
/* On some systems, no flag bits are given to specify file mapping. */
#ifndef MAP_FILE
#define MAP_FILE 0
# define MAP_FILE 0
#endif
/* The right way to map in the shared library files is MAP_COPY, which
@ -46,7 +46,7 @@
means if the file is overwritten, we may at some point get some pages
from the new version after starting with pages from the old version. */
#ifndef MAP_COPY
#define MAP_COPY MAP_PRIVATE
# define MAP_COPY MAP_PRIVATE
#endif
/* Some systems link their relocatable objects for another base address
@ -55,30 +55,30 @@
This results in a more efficient address space usage. Defaults to
zero for almost all systems. */
#ifndef MAP_BASE_ADDR
#define MAP_BASE_ADDR(l) 0
# define MAP_BASE_ADDR(l) 0
#endif
#include <endian.h>
#if BYTE_ORDER == BIG_ENDIAN
#define byteorder ELFDATA2MSB
#define byteorder_name "big-endian"
# define byteorder ELFDATA2MSB
# define byteorder_name "big-endian"
#elif BYTE_ORDER == LITTLE_ENDIAN
#define byteorder ELFDATA2LSB
#define byteorder_name "little-endian"
# define byteorder ELFDATA2LSB
# define byteorder_name "little-endian"
#else
#error "Unknown BYTE_ORDER " BYTE_ORDER
#define byteorder ELFDATANONE
# error "Unknown BYTE_ORDER " BYTE_ORDER
# define byteorder ELFDATANONE
#endif
#define STRING(x) __STRING (x)
#ifdef MAP_ANON
/* The fd is not examined when using MAP_ANON. */
#define ANONFD -1
# define ANONFD -1
#else
int _dl_zerofd = -1;
#define ANONFD _dl_zerofd
# define ANONFD _dl_zerofd
#endif
/* Handle situations where we have a preferred location in memory for
@ -87,10 +87,10 @@ int _dl_zerofd = -1;
ELF_PREFERRED_ADDRESS_DATA;
#endif
#ifndef ELF_PREFERRED_ADDRESS
#define ELF_PREFERRED_ADDRESS(loader, maplength, mapstartpref) (mapstartpref)
# define ELF_PREFERRED_ADDRESS(loader, maplength, mapstartpref) (mapstartpref)
#endif
#ifndef ELF_FIXED_ADDRESS
#define ELF_FIXED_ADDRESS(loader, mapstart) ((void) 0)
# define ELF_FIXED_ADDRESS(loader, mapstart) ((void) 0)
#endif
size_t _dl_pagesize;
@ -436,7 +436,7 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep,
static struct r_search_path_elem **
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. */
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;
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)
{
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] == ':')
&& (found[len] == '\0' || found[len] == ':'))
{
/* This object is on the list of objects for which the RPATH
must not be used. */
/* This object is on the list of objects for which the
RUNPATH and RPATH must not be used. */
result = (struct r_search_path_elem **)
malloc (sizeof (*result));
if (result == NULL)
@ -473,7 +474,7 @@ decompose_rpath (const char *rpath, struct link_map *l)
string tokens. */
copy = expand_dynamic_string_token (l, rpath);
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. */
nelems = 0;
@ -488,7 +489,7 @@ decompose_rpath (const char *rpath, struct link_map *l)
if (result == NULL)
_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,15 +571,32 @@ _dl_init_paths (const char *llp)
{
assert (l->l_type != lt_loaded);
if (l->l_info[DT_RPATH])
/* Allocate room for the search path and fill in information
from RPATH. */
l->l_rpath_dirs =
decompose_rpath ((const void *) (l->l_info[DT_STRTAB]->d_un.d_ptr
+ l->l_info[DT_RPATH]->d_un.d_val),
l);
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_rpath_dirs = NULL;
{
l->l_runpath_dirs = NULL;
if (l->l_info[DT_RPATH])
/* Allocate room for the search path and fill in information
from RPATH. */
l->l_rpath_dirs =
decompose_rpath ((const void *) (l->l_info[DT_STRTAB]->d_un.d_ptr
+ l->l_info[DT_RPATH]->d_un.d_val),
l, "RPATH");
else
l->l_rpath_dirs = NULL;
}
}
#endif /* PIC */
@ -1036,7 +1054,7 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname,
" 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])
_dl_setup_hash (l);
@ -1292,35 +1310,59 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
fd = -1;
/* First try the DT_RPATH of the dependent object that caused NAME
to be loaded. Then that object's dependent, and on up. */
for (l = loader; fd == -1 && l; l = l->l_loader)
if (l->l_info[DT_RPATH])
{
/* Make sure the cache information is available. */
if (l->l_rpath_dirs == NULL)
/* 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
to be loaded. Then that object's dependent, and on up. */
for (l = loader; fd == -1 && l; l = l->l_loader)
if (l->l_info[DT_RPATH])
{
size_t ptrval = (l->l_info[DT_STRTAB]->d_un.d_ptr
+ l->l_info[DT_RPATH]->d_un.d_val);
l->l_rpath_dirs =
decompose_rpath ((const char *) ptrval, l);
/* Make sure the cache information is available. */
if (l->l_rpath_dirs == NULL)
{
size_t ptrval = (l->l_info[DT_STRTAB]->d_un.d_ptr
+ l->l_info[DT_RPATH]->d_un.d_val);
l->l_rpath_dirs =
decompose_rpath ((const char *) ptrval, l, "RPATH");
}
if (l->l_rpath_dirs != NULL)
fd = open_path (name, namelen, preloaded, l->l_rpath_dirs,
&realname);
}
if (l->l_rpath_dirs != NULL)
fd = open_path (name, namelen, preloaded, l->l_rpath_dirs,
&realname);
}
/* If dynamically linked, try the DT_RPATH of the executable itself. */
l = _dl_loaded;
if (fd == -1 && l && l->l_type != lt_loaded && l != loader
&& l->l_rpath_dirs != NULL)
fd = open_path (name, namelen, preloaded, l->l_rpath_dirs, &realname);
/* If dynamically linked, try the DT_RPATH of the executable
itself. */
l = _dl_loaded;
if (fd == -1 && l && l->l_type != lt_loaded && l != loader
&& l->l_rpath_dirs != NULL)
fd = open_path (name, namelen, preloaded, l->l_rpath_dirs,
&realname);
}
/* Try the LD_LIBRARY_PATH environment variable. */
if (fd == -1 && env_path_list != NULL)
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)
{
/* 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. */
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;
/* 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_*. */
static inline void __attribute__ ((unused))
elf_get_dynamic_info (ElfW(Dyn) *dyn, ElfW(Addr) l_addr,
ElfW(Dyn) *info[DT_NUM + DT_PROCNUM + DT_VERSIONTAGNUM
+ DT_EXTRANUM])
elf_get_dynamic_info (struct link_map *l)
{
ElfW(Dyn) *dyn = l->l_ld;
ElfW(Addr) l_addr;
ElfW(Dyn) **info;
if (! dyn)
return;
l_addr = l->l_addr;
info = l->l_info;
while (dyn->d_tag != DT_NULL)
{
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)
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

View File

@ -163,7 +163,6 @@ struct link_map
} l_type:2;
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_running:1; /* Nonzero while DT_INIT function runs. */
unsigned int l_global:1; /* Nonzero if object in _dl_global_scope. */
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. */
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 */

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\
--library-path PATH use given PATH instead of content of the environment\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);
++_dl_skip_args;