mirror of
https://sourceware.org/git/glibc.git
synced 2025-07-30 22:43:12 +03:00
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.
This commit is contained in:
108
elf/dl-open.c
108
elf/dl-open.c
@ -77,7 +77,7 @@ dl_open_worker (void *a)
|
||||
|
||||
/* Load the named object. */
|
||||
args->map = new = _dl_map_object (NULL, file, 0, lt_loaded, 0);
|
||||
if (new->l_searchlist)
|
||||
if (new->l_searchlist.r_list)
|
||||
/* It was already open. */
|
||||
return;
|
||||
|
||||
@ -97,21 +97,6 @@ dl_open_worker (void *a)
|
||||
{
|
||||
if (! l->l_relocated)
|
||||
{
|
||||
/* We use an indirect call call for _dl_relocate_object because
|
||||
we must avoid using the PLT in the call. If our PLT entry for
|
||||
_dl_relocate_object hasn't been used yet, then the dynamic
|
||||
linker fixup routine will clobber _dl_global_scope during its
|
||||
work. We must be sure that nothing will require a PLT fixup
|
||||
between when _dl_object_relocation_scope returns and when we
|
||||
enter the dynamic linker's code (_dl_relocate_object). */
|
||||
__typeof (_dl_relocate_object) *reloc = &_dl_relocate_object;
|
||||
|
||||
/* GCC is very clever. If we wouldn't add some magic it would
|
||||
simply optimize away our nice little variable `reloc' and we
|
||||
would result in a not working binary. So let's swing the
|
||||
magic ward. */
|
||||
asm ("" : "=r" (reloc) : "0" (reloc));
|
||||
|
||||
#ifdef PIC
|
||||
if (_dl_profile != NULL)
|
||||
{
|
||||
@ -122,7 +107,7 @@ dl_open_worker (void *a)
|
||||
start the profiling. */
|
||||
struct link_map *old_profile_map = _dl_profile_map;
|
||||
|
||||
(*reloc) (l, _dl_object_relocation_scope (l), 1, 1);
|
||||
_dl_relocate_object (l, l->l_scope, 1, 1);
|
||||
|
||||
if (old_profile_map == NULL && _dl_profile_map != NULL)
|
||||
/* We must prepare the profiling. */
|
||||
@ -130,10 +115,8 @@ dl_open_worker (void *a)
|
||||
}
|
||||
else
|
||||
#endif
|
||||
(*reloc) (l, _dl_object_relocation_scope (l),
|
||||
(mode & RTLD_BINDING_MASK) == RTLD_LAZY, 0);
|
||||
|
||||
*_dl_global_scope_end = NULL;
|
||||
_dl_relocate_object (l, l->l_scope,
|
||||
(mode & RTLD_BINDING_MASK) == RTLD_LAZY, 0);
|
||||
}
|
||||
|
||||
if (l == new)
|
||||
@ -146,50 +129,58 @@ dl_open_worker (void *a)
|
||||
{
|
||||
/* The symbols of the new object and its dependencies are to be
|
||||
introduced into the global scope that will be used to resolve
|
||||
references from other dynamically-loaded objects. */
|
||||
references from other dynamically-loaded objects.
|
||||
|
||||
The global scope is the searchlist in the main link map. We
|
||||
extend this list if necessary. There is one problem though:
|
||||
since this structure was allocated very early (before the libc
|
||||
is loaded) the memory it uses is allocated by the malloc()-stub
|
||||
in the ld.so. When we come here these functions are not used
|
||||
anymore. Instead the malloc() implementation of the libc is
|
||||
used. But this means the block from the main map cannot be used
|
||||
in an realloc() call. Therefore we allocate a completely new
|
||||
array the first time we have to add something to the locale scope. */
|
||||
if (_dl_global_scope_alloc == 0)
|
||||
{
|
||||
/* This is the first dynamic object given global scope. */
|
||||
_dl_global_scope_alloc = 8;
|
||||
_dl_global_scope = malloc (_dl_global_scope_alloc
|
||||
* sizeof (struct link_map *));
|
||||
if (! _dl_global_scope)
|
||||
struct link_map **new_global;
|
||||
|
||||
_dl_global_scope_alloc = _dl_main_searchlist->r_nlist + 8;
|
||||
new_global = (struct link_map **)
|
||||
malloc (_dl_global_scope_alloc * sizeof (struct link_map *));
|
||||
if (new_global == NULL)
|
||||
{
|
||||
_dl_global_scope = _dl_default_scope;
|
||||
_dl_global_scope_alloc = 0;
|
||||
nomem:
|
||||
new->l_global = 0;
|
||||
_dl_signal_error (ENOMEM, file, "cannot extend global scope");
|
||||
}
|
||||
_dl_global_scope[2] = _dl_default_scope[2];
|
||||
_dl_global_scope[3] = new;
|
||||
_dl_global_scope[4] = NULL;
|
||||
_dl_global_scope[5] = NULL;
|
||||
_dl_global_scope_end = &_dl_global_scope [4];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_dl_global_scope_end + 3
|
||||
> _dl_global_scope + _dl_global_scope_alloc)
|
||||
{
|
||||
/* Must extend the list. */
|
||||
struct link_map **new = realloc (_dl_global_scope,
|
||||
_dl_global_scope_alloc * 2
|
||||
* sizeof (struct link_map *));
|
||||
if (! new)
|
||||
goto nomem;
|
||||
_dl_global_scope = new;
|
||||
_dl_global_scope_end = new + _dl_global_scope_alloc - 2;
|
||||
_dl_global_scope_alloc *= 2;
|
||||
}
|
||||
|
||||
/* Append the new object and re-terminate the list. */
|
||||
*_dl_global_scope_end++ = new;
|
||||
/* We keep the list double-terminated so the last element
|
||||
can be filled in for symbol lookups. */
|
||||
_dl_global_scope_end[0] = NULL;
|
||||
_dl_global_scope_end[1] = NULL;
|
||||
/* Copy over the old entries. */
|
||||
memcpy (new_global, _dl_main_searchlist->r_list,
|
||||
(_dl_main_searchlist->r_nlist * sizeof (struct link_map *)));
|
||||
|
||||
_dl_main_searchlist->r_list = new_global;
|
||||
}
|
||||
else if (_dl_main_searchlist->r_nlist == _dl_global_scope_alloc)
|
||||
{
|
||||
/* We have to extend the existing array of link maps in the
|
||||
main map. */
|
||||
struct link_map **new_global;
|
||||
|
||||
new_global = (struct link_map **)
|
||||
malloc ((_dl_global_scope_alloc + 8) * sizeof (struct link_map *));
|
||||
if (new_global == NULL)
|
||||
goto nomem;
|
||||
|
||||
_dl_global_scope_alloc += 8;
|
||||
_dl_main_searchlist->r_list = new_global;
|
||||
}
|
||||
|
||||
/* Now add the new entry. */
|
||||
_dl_main_searchlist->r_list[_dl_main_searchlist->r_nlist] = new;
|
||||
|
||||
/* XXX Do we have to add something to r_dupsearchlist??? --drepper */
|
||||
}
|
||||
|
||||
|
||||
@ -201,10 +192,14 @@ dl_open_worker (void *a)
|
||||
_dl_debug_state ();
|
||||
|
||||
/* Run the initializer functions of new objects. */
|
||||
while (init = _dl_init_next (new))
|
||||
while (init = _dl_init_next (&new->l_searchlist))
|
||||
(*(void (*) (int, char **, char **)) init) (__libc_argc, __libc_argv,
|
||||
__environ);
|
||||
|
||||
if (new->l_global)
|
||||
/* Now we can make the new map available in the global scope. */
|
||||
++_dl_main_searchlist->r_nlist;
|
||||
|
||||
if (_dl_sysdep_start == NULL)
|
||||
/* We must be the static _dl_open in libc.a. A static program that
|
||||
has loaded a dynamic object now has competition. */
|
||||
@ -241,9 +236,6 @@ _dl_open (const char *file, int mode)
|
||||
/* Some error occured during loading. */
|
||||
char *local_errstring;
|
||||
|
||||
/* Reset the global scope. */
|
||||
*_dl_global_scope_end = NULL;
|
||||
|
||||
/* Remove the object from memory. It may be in an inconsistent
|
||||
state if relocation failed, for example. */
|
||||
if (args.map)
|
||||
|
Reference in New Issue
Block a user