aboutsummaryrefslogtreecommitdiff
path: root/elf/rtld.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>1998-09-06 09:16:53 +0000
committerUlrich Drepper <drepper@redhat.com>1998-09-06 09:16:53 +0000
commitbe93561004695198611aa8707f10250f780988b2 (patch)
tree7b9a502d849b761d966114b855a1fa9de4022e90 /elf/rtld.c
parent9eb71e60ef889158238c3066c75b65336d846684 (diff)
downloadglibc-be93561004695198611aa8707f10250f780988b2.zip
glibc-be93561004695198611aa8707f10250f780988b2.tar.gz
glibc-be93561004695198611aa8707f10250f780988b2.tar.bz2
Update.
1998-09-06 09:00 Ulrich Drepper <drepper@cygnus.com> * version.h (VERSION): Bump to 2.0.96. Rewrite runtime linker to be truly thread-safe. There is now no global variable specifying the scope. We create all needed scopes at the time the link maps are created. * elf/Versions [GLIBC_2.1]: Add _dl_loaded and _dl_main_searchlist. * elf/link.h: Add struct r_scope_elem and use this for l_searchlist, l_symbolic_searchlist, l_scope, and l_local_scope elements in struct link_map. * elf/dl-close.c: Rewritten accordingly. * elf/dl-deps.c: Likewise. * elf/dl-error.c: Likewise. * elf/dl-init.c: Likewise. * elf/dl-load.c: Likewise. * elf/dl-lookup.c: Likewise. * elf/dl-object.c: Likewise. * elf/dl-open.c: Likewise. * elf/dl-reloc.c: Likewise. * elf/dl-runtime.c: Likewise. * elf/dl-support.c: Likewise. * elf/dl-symbol.c: Likewise. * elf/dl-version.c: Likewise. * elf/dlfcn.h: Likewise. * elf/dlsym.c: Likewise. * elf/dlvsym.c: Likewise. * elf/ldsodefs.h: Likewise. * elf/rtld.c: Likewise. * iconv/gconv_dl.c: Likewise. * nss/nsswitch.c: Likewise. * sysdeps/i386/dl-machine.h: Likewise. * sysdeps/unix/sysv/linux/i386/dl-librecon.h: Likewise.
Diffstat (limited to 'elf/rtld.c')
-rw-r--r--elf/rtld.c115
1 files changed, 61 insertions, 54 deletions
diff --git a/elf/rtld.c b/elf/rtld.c
index 66e5d6c..52295de 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -89,6 +89,14 @@ const char *_dl_inhibit_rpath; /* RPATH values which should be
ignored. */
const char *_dl_origin_path;
+/* This is a pointer to the map for the main object and through it to
+ all loaded objects. */
+struct link_map *_dl_loaded;
+/* Pointer to the l_searchlist element of the link map of the main object. */
+struct r_scope_elem *_dl_main_searchlist;
+/* Array which is used when looking up in the global scope. */
+struct r_scope_elem *_dl_global_scope[2];
+
/* Set nonzero during loading and initialization of executable and
libraries, cleared before the executable's entry point runs. This
must not be initialized to nonzero, because the unused dynamic
@@ -201,7 +209,6 @@ struct map_args
/* Arguments to version_check_doit. */
struct version_check_args
{
- struct link_map *main_map;
int doexit;
};
@@ -210,22 +217,22 @@ relocate_doit (void *a)
{
struct relocate_args *args = (struct relocate_args *) a;
- _dl_relocate_object (args->l, _dl_object_relocation_scope (args->l),
+ _dl_relocate_object (args->l, args->l->l_scope,
args->lazy, 0);
}
static void
map_doit (void *a)
{
- struct map_args *args = (struct map_args *)a;
+ struct map_args *args = (struct map_args *) a;
args->main_map = _dl_map_object (NULL, args->str, 0, lt_library, 0);
}
static void
version_check_doit (void *a)
{
- struct version_check_args *args = (struct version_check_args *)a;
- if (_dl_check_all_versions (args->main_map, 1) && args->doexit)
+ struct version_check_args *args = (struct version_check_args *) a;
+ if (_dl_check_all_versions (_dl_loaded, 1) && args->doexit)
/* We cannot start the application. Abort now. */
_exit (1);
}
@@ -234,11 +241,11 @@ version_check_doit (void *a)
static inline struct link_map *
find_needed (const char *name)
{
- unsigned int n;
+ unsigned int n = _dl_loaded->l_searchlist.r_nlist;
- 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];
+ while (n-- > 0)
+ if (_dl_name_match_p (name, _dl_loaded->l_searchlist.r_list[n]))
+ return _dl_loaded->l_searchlist.r_list[n];
/* Should never happen. */
return NULL;
@@ -289,7 +296,6 @@ dl_main (const ElfW(Phdr) *phdr,
ElfW(Addr) *user_entry)
{
const ElfW(Phdr) *ph;
- struct link_map *main_map;
int lazy;
enum mode mode;
struct link_map **preloads;
@@ -405,7 +411,7 @@ of this helper program; chances are you did not intend to run this program.\n\
args.str = _dl_argv[0];
(void) _dl_catch_error (&err_str, map_doit, &args);
- main_map = args.main_map;
+ _dl_loaded = args.main_map;
if (err_str != NULL)
{
free (err_str);
@@ -413,37 +419,37 @@ of this helper program; chances are you did not intend to run this program.\n\
}
}
else
- main_map = _dl_map_object (NULL, _dl_argv[0], 0, lt_library, 0);
+ _dl_loaded = _dl_map_object (NULL, _dl_argv[0], 0, lt_library, 0);
- phdr = main_map->l_phdr;
- phent = main_map->l_phnum;
+ phdr = _dl_loaded->l_phdr;
+ phent = _dl_loaded->l_phnum;
/* We overwrite here a pointer to a malloc()ed string. But since
the malloc() implementation used at this point is the dummy
implementations which has no real free() function it does not
makes sense to free the old string first. */
- main_map->l_name = (char *) "";
- *user_entry = main_map->l_entry;
+ _dl_loaded->l_name = (char *) "";
+ *user_entry = _dl_loaded->l_entry;
}
else
{
/* Create a link_map for the executable itself.
This will be what dlopen on "" returns. */
- main_map = _dl_new_object ((char *) "", "", lt_executable);
- if (main_map == NULL)
+ _dl_loaded = _dl_new_object ((char *) "", "", lt_executable, NULL);
+ if (_dl_loaded == NULL)
_dl_sysdep_fatal ("cannot allocate memory for link map\n", NULL);
- main_map->l_phdr = phdr;
- main_map->l_phnum = phent;
- main_map->l_entry = *user_entry;
- main_map->l_opencount = 1;
+ _dl_loaded->l_phdr = phdr;
+ _dl_loaded->l_phnum = phent;
+ _dl_loaded->l_entry = *user_entry;
+ _dl_loaded->l_opencount = 1;
/* We delay initializing the path structure until we got the dynamic
information for the program. */
}
/* It is not safe to load stuff after the main program. */
- main_map->l_map_end = ~0;
+ _dl_loaded->l_map_end = ~0;
/* Perhaps the executable has no PT_LOAD header entries at all. */
- main_map->l_map_start = ~0;
+ _dl_loaded->l_map_start = ~0;
/* Scan the program header table for the dynamic section. */
for (ph = phdr; ph < &phdr[phent]; ++ph)
@@ -451,12 +457,12 @@ of this helper program; chances are you did not intend to run this program.\n\
{
case PT_PHDR:
/* Find out the load address. */
- main_map->l_addr = (ElfW(Addr)) phdr - ph->p_vaddr;
+ _dl_loaded->l_addr = (ElfW(Addr)) phdr - ph->p_vaddr;
break;
case PT_DYNAMIC:
/* This tells us where to find the dynamic section,
which tells us everything we need to do. */
- main_map->l_ld = (void *) main_map->l_addr + ph->p_vaddr;
+ _dl_loaded->l_ld = (void *) _dl_loaded->l_addr + ph->p_vaddr;
break;
case PT_INTERP:
/* This "interpreter segment" was used by the program loader to
@@ -465,7 +471,8 @@ of this helper program; chances are you did not intend to run this program.\n\
dlopen call or DT_NEEDED entry, for something that wants to link
against the dynamic linker as a shared library, will know that
the shared object is already loaded. */
- _dl_rtld_libname.name = (const char *) main_map->l_addr + ph->p_vaddr;
+ _dl_rtld_libname.name = ((const char *) _dl_loaded->l_addr
+ + ph->p_vaddr);
_dl_rtld_libname.next = NULL;
_dl_rtld_map.l_libname = &_dl_rtld_libname;
@@ -491,9 +498,9 @@ of this helper program; chances are you did not intend to run this program.\n\
/* Remember where the main program starts in memory. */
{
ElfW(Addr) mapstart;
- mapstart = main_map->l_addr + (ph->p_vaddr & ~(ph->p_align - 1));
- if (main_map->l_map_start > mapstart)
- main_map->l_map_start = mapstart;
+ mapstart = _dl_loaded->l_addr + (ph->p_vaddr & ~(ph->p_align - 1));
+ if (_dl_loaded->l_map_start > mapstart)
+ _dl_loaded->l_map_start = mapstart;
}
break;
}
@@ -509,10 +516,10 @@ of this helper program; chances are you did not intend to run this program.\n\
assert (_dl_rtld_map.l_libname); /* How else did we get here? */
/* Extract the contents of the dynamic section for easy access. */
- elf_get_dynamic_info (main_map->l_ld, main_map->l_info);
- if (main_map->l_info[DT_HASH])
+ elf_get_dynamic_info (_dl_loaded->l_ld, _dl_loaded->l_info);
+ if (_dl_loaded->l_info[DT_HASH])
/* Set up our cache of pointers into the hash table. */
- _dl_setup_hash (main_map);
+ _dl_setup_hash (_dl_loaded);
if (mode == verify)
{
@@ -520,7 +527,7 @@ of this helper program; chances are you did not intend to run this program.\n\
executable using us as the program interpreter. Exit with an
error if we were not able to load the binary or no interpreter
is specified (i.e., this is no dynamically linked binary. */
- if (main_map->l_ld == NULL)
+ if (_dl_loaded->l_ld == NULL)
_exit (1);
/* We allow here some platform specific code. */
@@ -537,14 +544,14 @@ of this helper program; chances are you did not intend to run this program.\n\
/* Put the link_map for ourselves on the chain so it can be found by
name. Note that at this point the global chain of link maps contains
- exactly one element, which is pointed to by main_map. */
+ exactly one element, which is pointed to by _dl_loaded. */
if (! _dl_rtld_map.l_name)
/* If not invoked directly, the dynamic linker shared object file was
found by the PT_INTERP name. */
_dl_rtld_map.l_name = (char *) _dl_rtld_map.l_libname->name;
_dl_rtld_map.l_type = lt_library;
- main_map->l_next = &_dl_rtld_map;
- _dl_rtld_map.l_prev = main_map;
+ _dl_loaded->l_next = &_dl_rtld_map;
+ _dl_rtld_map.l_prev = _dl_loaded;
/* We have two ways to specify objects to preload: via environment
variable and via the file /etc/ld.so.preload. The later can also
@@ -565,7 +572,7 @@ of this helper program; chances are you did not intend to run this program.\n\
if (p[0] != '\0'
&& (! __libc_enable_secure || strchr (p, '/') == NULL))
{
- struct link_map *new_map = _dl_map_object (main_map, p, 1,
+ struct link_map *new_map = _dl_map_object (_dl_loaded, p, 1,
lt_library, 0);
if (new_map->l_opencount == 1)
/* It is no duplicate. */
@@ -627,7 +634,7 @@ of this helper program; chances are you did not intend to run this program.\n\
while ((p = strsep (&runp, ": \t\n")) != NULL)
if (p[0] != '\0')
{
- struct link_map *new_map = _dl_map_object (main_map, p, 1,
+ struct link_map *new_map = _dl_map_object (_dl_loaded, p, 1,
lt_library, 0);
if (new_map->l_opencount == 1)
/* It is no duplicate. */
@@ -638,7 +645,7 @@ of this helper program; chances are you did not intend to run this program.\n\
if (problem != NULL)
{
char *p = strndupa (problem, file_size - (problem - file));
- struct link_map *new_map = _dl_map_object (main_map, p, 1,
+ struct link_map *new_map = _dl_map_object (_dl_loaded, p, 1,
lt_library, 0);
if (new_map->l_opencount == 1)
/* It is no duplicate. */
@@ -667,7 +674,7 @@ of this helper program; chances are you did not intend to run this program.\n\
/* Load all the libraries specified by DT_NEEDED entries. If LD_PRELOAD
specified some libraries to load, these are inserted before the actual
dependencies in the executable's searchlist for symbol resolution. */
- _dl_map_object_deps (main_map, preloads, npreloads, mode == trace);
+ _dl_map_object_deps (_dl_loaded, preloads, npreloads, mode == trace);
#ifndef MAP_ANON
/* We are done mapping things, so close the zero-fill descriptor. */
@@ -687,11 +694,12 @@ of this helper program; chances are you did not intend to run this program.\n\
chain in symbol search order because gdb uses the chain's order as
its symbol search order. */
i = 1;
- while (main_map->l_searchlist[i] != &_dl_rtld_map)
+ while (_dl_loaded->l_searchlist.r_list[i] != &_dl_rtld_map)
++i;
- _dl_rtld_map.l_prev = main_map->l_searchlist[i - 1];
- _dl_rtld_map.l_next = (i + 1 < main_map->l_nsearchlist ?
- main_map->l_searchlist[i + 1] : NULL);
+ _dl_rtld_map.l_prev = _dl_loaded->l_searchlist.r_list[i - 1];
+ _dl_rtld_map.l_next = (i + 1 < _dl_loaded->l_searchlist.r_nlist
+ ? _dl_loaded->l_searchlist.r_list[i + 1]
+ : NULL);
assert (_dl_rtld_map.l_prev->l_next == _dl_rtld_map.l_next);
_dl_rtld_map.l_prev->l_next = &_dl_rtld_map;
if (_dl_rtld_map.l_next)
@@ -706,7 +714,6 @@ of this helper program; chances are you did not intend to run this program.\n\
{
struct version_check_args args;
args.doexit = mode == normal;
- args.main_map = main_map;
_dl_receive_error (print_missing_version, version_check_doit, &args);
}
@@ -745,7 +752,7 @@ of this helper program; chances are you did not intend to run this program.\n\
{
const ElfW(Sym) *ref = NULL;
ElfW(Addr) loadbase = _dl_lookup_symbol (_dl_argv[i], &ref,
- &_dl_default_scope[2],
+ _dl_loaded->l_scope,
"argument",
ELF_MACHINE_JMP_SLOT);
char buf[20], *bp;
@@ -780,7 +787,6 @@ of this helper program; chances are you did not intend to run this program.\n\
args.l = l;
_dl_receive_error (print_unresolved, relocate_doit,
&args);
- *_dl_global_scope_end = NULL;
}
l = l->l_prev;
} while (l);
@@ -890,11 +896,8 @@ of this helper program; chances are you did not intend to run this program.\n\
do
{
if (l != &_dl_rtld_map)
- {
- _dl_relocate_object (l, _dl_object_relocation_scope (l), lazy,
- consider_profiling);
- *_dl_global_scope_end = NULL;
- }
+ _dl_relocate_object (l, l->l_scope, lazy, consider_profiling);
+
l = l->l_prev;
} while (l);
@@ -908,9 +911,13 @@ of this helper program; chances are you did not intend to run this program.\n\
if (_dl_rtld_map.l_opencount > 0)
/* There was an explicit ref to the dynamic linker as a shared lib.
Re-relocate ourselves with user-controlled symbol definitions. */
- _dl_relocate_object (&_dl_rtld_map, &_dl_default_scope[2], 0, 0);
+ _dl_relocate_object (&_dl_rtld_map, _dl_loaded->l_scope, 0, 0);
}
+ /* Now set up the variable which helps the assembler startup code. */
+ _dl_main_searchlist = &_dl_loaded->l_searchlist;
+ _dl_global_scope[0] = &_dl_loaded->l_searchlist;
+
{
/* Initialize _r_debug. */
struct r_debug *r = _dl_debug_initialize (_dl_rtld_map.l_addr);