mirror of
git://sourceware.org/git/glibc.git
synced 2025-02-23 13:09:58 +08:00
Update.
2000-10-21 Ulrich Drepper <drepper@redhat.com> * elf/dl-open.c (add_to_global): New function. Split out from dl_open_worker. (dl_open_worker): Call add_to_global not only for new objects, also for previously loaded objects when (mode & RTLD_GLOBAL) and the object was not yet in the global scope. * elf/Makefile: Add rules to build and run lateglobal. * elf/lateglobal.c: New file. * elf/ltglobmod1.c: New file. * elf/ltglobmod2.c: New file.
This commit is contained in:
parent
c91bc73e3e
commit
d785c36692
12
ChangeLog
12
ChangeLog
@ -1,3 +1,15 @@
|
|||||||
|
2000-10-21 Ulrich Drepper <drepper@redhat.com>
|
||||||
|
|
||||||
|
* elf/dl-open.c (add_to_global): New function. Split out from
|
||||||
|
dl_open_worker.
|
||||||
|
(dl_open_worker): Call add_to_global not only for new objects, also for
|
||||||
|
previously loaded objects when (mode & RTLD_GLOBAL) and the object
|
||||||
|
was not yet in the global scope.
|
||||||
|
* elf/Makefile: Add rules to build and run lateglobal.
|
||||||
|
* elf/lateglobal.c: New file.
|
||||||
|
* elf/ltglobmod1.c: New file.
|
||||||
|
* elf/ltglobmod2.c: New file.
|
||||||
|
|
||||||
2000-10-20 Ulrich Drepper <drepper@redhat.com>
|
2000-10-20 Ulrich Drepper <drepper@redhat.com>
|
||||||
|
|
||||||
* include/link.h (struct link_map): Add l_soname_added bitfield.
|
* include/link.h (struct link_map): Add l_soname_added bitfield.
|
||||||
|
11
elf/Makefile
11
elf/Makefile
@ -55,7 +55,7 @@ distribute := $(rtld-routines:=.c) dynamic-link.h do-rel.h dl-machine.h \
|
|||||||
reldepmod1.c reldepmod2.c reldepmod3.c reldepmod4.c \
|
reldepmod1.c reldepmod2.c reldepmod3.c reldepmod4.c \
|
||||||
nextmod1.c nextmod2.c \
|
nextmod1.c nextmod2.c \
|
||||||
neededobj1.c neededobj2.c neededobj3.c \
|
neededobj1.c neededobj2.c neededobj3.c \
|
||||||
unload2mod.c unload2dep.c
|
unload2mod.c unload2dep.c ltglobmod1.c ltglobmod2.c
|
||||||
|
|
||||||
include ../Makeconfig
|
include ../Makeconfig
|
||||||
|
|
||||||
@ -97,7 +97,7 @@ ifeq (yes,$(build-shared))
|
|||||||
tests = loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
|
tests = loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
|
||||||
constload1 order $(tests-vis-$(have-protected)) noload filter unload \
|
constload1 order $(tests-vis-$(have-protected)) noload filter unload \
|
||||||
reldep reldep2 reldep3 next $(tests-nodelete-$(have-z-nodelete)) \
|
reldep reldep2 reldep3 next $(tests-nodelete-$(have-z-nodelete)) \
|
||||||
$(tests-nodlopen-$(have-z-nodlopen)) neededtest unload2
|
$(tests-nodlopen-$(have-z-nodlopen)) neededtest unload2 lateglobal
|
||||||
tests-vis-yes = vismain
|
tests-vis-yes = vismain
|
||||||
tests-nodelete-yes = nodelete
|
tests-nodelete-yes = nodelete
|
||||||
tests-nodlopen-yes = nodlopen
|
tests-nodlopen-yes = nodlopen
|
||||||
@ -108,7 +108,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
|
|||||||
$(modules-nodelete-$(have-z-nodelete)) \
|
$(modules-nodelete-$(have-z-nodelete)) \
|
||||||
$(modules-nodlopen-$(have-z-nodlopen)) filtmod1 filtmod2 \
|
$(modules-nodlopen-$(have-z-nodlopen)) filtmod1 filtmod2 \
|
||||||
reldepmod1 reldepmod2 reldepmod3 reldepmod4 nextmod1 nextmod2 \
|
reldepmod1 reldepmod2 reldepmod3 reldepmod4 nextmod1 nextmod2 \
|
||||||
neededobj1 neededobj2 neededobj3 unload2mod unload2dep
|
neededobj1 neededobj2 neededobj3 unload2mod unload2dep \
|
||||||
|
ltglobmod1 ltglobmod2
|
||||||
modules-vis-yes = vismod1 vismod2 vismod3
|
modules-vis-yes = vismod1 vismod2 vismod3
|
||||||
modules-nodelete-yes = nodelmod1 nodelmod2 nodelmod3 nodelmod4
|
modules-nodelete-yes = nodelmod1 nodelmod2 nodelmod3 nodelmod4
|
||||||
modules-nodlopen-yes = nodlopenmod
|
modules-nodlopen-yes = nodlopenmod
|
||||||
@ -255,6 +256,7 @@ $(objpfx)neededobj1.so: $(libdl)
|
|||||||
$(objpfx)neededobj2.so: $(objpfx)neededobj1.so $(libdl)
|
$(objpfx)neededobj2.so: $(objpfx)neededobj1.so $(libdl)
|
||||||
$(objpfx)neededobj3.so: $(objpfx)neededobj1.so $(objpfx)neededobj2.so $(libdl)
|
$(objpfx)neededobj3.so: $(objpfx)neededobj1.so $(objpfx)neededobj2.so $(libdl)
|
||||||
$(objpfx)unload2mod.so: $(objpfx)unload2dep.so
|
$(objpfx)unload2mod.so: $(objpfx)unload2dep.so
|
||||||
|
$(objpfx)ltglobmod2.so: $(libdl)
|
||||||
|
|
||||||
# filtmod1.so has a special rule
|
# filtmod1.so has a special rule
|
||||||
$(filter-out $(objpfx)filtmod1.so, $(test-modules)): $(objpfx)%.so: $(objpfx)%.os
|
$(filter-out $(objpfx)filtmod1.so, $(test-modules)): $(objpfx)%.so: $(objpfx)%.os
|
||||||
@ -356,3 +358,6 @@ $(objpfx)next: $(objpfx)nextmod1.so $(objpfx)nextmod2.so $(libdl)
|
|||||||
|
|
||||||
$(objpfx)unload2: $(libdl)
|
$(objpfx)unload2: $(libdl)
|
||||||
$(objpfx)unload2.out: $(objpfx)unload2mod.so $(objpfx)unload2dep.so
|
$(objpfx)unload2.out: $(objpfx)unload2mod.so $(objpfx)unload2dep.so
|
||||||
|
|
||||||
|
$(objpfx)lateglobal: $(libdl)
|
||||||
|
$(objpfx)lateglobal.out: $(objpfx)ltglobmod1.so $(objpfx)ltglobmod2.so
|
||||||
|
166
elf/dl-open.c
166
elf/dl-open.c
@ -80,6 +80,87 @@ struct dl_open_args
|
|||||||
struct link_map *map;
|
struct link_map *map;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
add_to_global (struct link_map *new)
|
||||||
|
{
|
||||||
|
struct link_map **new_global;
|
||||||
|
unsigned int to_add = 0;
|
||||||
|
unsigned int cnt;
|
||||||
|
|
||||||
|
/* Count the objects we have to put in the global scope. */
|
||||||
|
for (cnt = 0; cnt < new->l_searchlist.r_nlist; ++cnt)
|
||||||
|
if (new->l_searchlist.r_list[cnt]->l_global == 0)
|
||||||
|
++to_add;
|
||||||
|
|
||||||
|
/* The symbols of the new objects and its dependencies are to be
|
||||||
|
introduced into the global scope that will be used to resolve
|
||||||
|
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 = _dl_main_searchlist->r_nlist + to_add + 8;
|
||||||
|
new_global = (struct link_map **)
|
||||||
|
malloc (_dl_global_scope_alloc * sizeof (struct link_map *));
|
||||||
|
if (new_global == NULL)
|
||||||
|
{
|
||||||
|
_dl_global_scope_alloc = 0;
|
||||||
|
nomem:
|
||||||
|
_dl_signal_error (ENOMEM, new->l_libname->name,
|
||||||
|
N_("cannot extend global scope"));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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 + to_add > _dl_global_scope_alloc)
|
||||||
|
{
|
||||||
|
/* We have to extend the existing array of link maps in the
|
||||||
|
main map. */
|
||||||
|
new_global = (struct link_map **)
|
||||||
|
realloc (_dl_main_searchlist->r_list,
|
||||||
|
((_dl_global_scope_alloc + to_add + 8)
|
||||||
|
* sizeof (struct link_map *)));
|
||||||
|
if (new_global == NULL)
|
||||||
|
goto nomem;
|
||||||
|
|
||||||
|
_dl_global_scope_alloc += to_add + 8;
|
||||||
|
_dl_main_searchlist->r_list = new_global;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now add the new entries. */
|
||||||
|
for (cnt = 0; cnt < new->l_searchlist.r_nlist; ++cnt)
|
||||||
|
{
|
||||||
|
struct link_map *map = new->l_searchlist.r_list[cnt];
|
||||||
|
|
||||||
|
if (map->l_global == 0)
|
||||||
|
{
|
||||||
|
map->l_global = 1;
|
||||||
|
_dl_main_searchlist->r_list[_dl_main_searchlist->r_nlist] = map;
|
||||||
|
++_dl_main_searchlist->r_nlist;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* XXX Do we have to add something to r_dupsearchlist??? --drepper */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dl_open_worker (void *a)
|
dl_open_worker (void *a)
|
||||||
{
|
{
|
||||||
@ -172,6 +253,12 @@ dl_open_worker (void *a)
|
|||||||
buf + sizeof buf - 1, 10, 0),
|
buf + sizeof buf - 1, 10, 0),
|
||||||
"\n\n", NULL);
|
"\n\n", NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If the user requested the object t be in the global namespace
|
||||||
|
but it is not so far, add it now. */
|
||||||
|
if ((mode & RTLD_GLOBAL) && new->l_global == 0)
|
||||||
|
(void) add_to_global (new);
|
||||||
|
|
||||||
/* It was already open. */
|
/* It was already open. */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -232,81 +319,10 @@ dl_open_worker (void *a)
|
|||||||
|
|
||||||
/* Now we can make the new map available in the global scope. */
|
/* Now we can make the new map available in the global scope. */
|
||||||
if (mode & RTLD_GLOBAL)
|
if (mode & RTLD_GLOBAL)
|
||||||
{
|
/* Move the object in the global namespace. */
|
||||||
struct link_map **new_global;
|
if (add_to_global (new) != 0)
|
||||||
unsigned int to_add = 0;
|
/* It failed. */
|
||||||
unsigned int cnt;
|
return;
|
||||||
|
|
||||||
/* Count the objects we have to put in the global scope. */
|
|
||||||
for (cnt = 0; cnt < new->l_searchlist.r_nlist; ++cnt)
|
|
||||||
if (new->l_searchlist.r_list[cnt]->l_global == 0)
|
|
||||||
++to_add;
|
|
||||||
|
|
||||||
/* The symbols of the new objects and its dependencies are to be
|
|
||||||
introduced into the global scope that will be used to resolve
|
|
||||||
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 = _dl_main_searchlist->r_nlist + to_add + 8;
|
|
||||||
new_global = (struct link_map **)
|
|
||||||
malloc (_dl_global_scope_alloc * sizeof (struct link_map *));
|
|
||||||
if (new_global == NULL)
|
|
||||||
{
|
|
||||||
_dl_global_scope_alloc = 0;
|
|
||||||
nomem:
|
|
||||||
_dl_signal_error (ENOMEM, new->l_libname->name,
|
|
||||||
N_("cannot extend global scope"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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 + to_add > _dl_global_scope_alloc)
|
|
||||||
{
|
|
||||||
/* We have to extend the existing array of link maps in the
|
|
||||||
main map. */
|
|
||||||
new_global = (struct link_map **)
|
|
||||||
realloc (_dl_main_searchlist->r_list,
|
|
||||||
((_dl_global_scope_alloc + to_add + 8)
|
|
||||||
* sizeof (struct link_map *)));
|
|
||||||
if (new_global == NULL)
|
|
||||||
goto nomem;
|
|
||||||
|
|
||||||
_dl_global_scope_alloc += to_add + 8;
|
|
||||||
_dl_main_searchlist->r_list = new_global;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now add the new entries. */
|
|
||||||
for (cnt = 0; cnt < new->l_searchlist.r_nlist; ++cnt)
|
|
||||||
{
|
|
||||||
struct link_map *map = new->l_searchlist.r_list[cnt];
|
|
||||||
|
|
||||||
if (map->l_global == 0)
|
|
||||||
{
|
|
||||||
map->l_global = 1;
|
|
||||||
_dl_main_searchlist->r_list[_dl_main_searchlist->r_nlist] = map;
|
|
||||||
++_dl_main_searchlist->r_nlist;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* XXX Do we have to add something to r_dupsearchlist??? --drepper */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Mark the object as not deletable if the RTLD_NODELETE flags was
|
/* Mark the object as not deletable if the RTLD_NODELETE flags was
|
||||||
passed. */
|
passed. */
|
||||||
|
47
elf/lateglobal.c
Normal file
47
elf/lateglobal.c
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#include <dlfcn.h>
|
||||||
|
#include <mcheck.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
main (void)
|
||||||
|
{
|
||||||
|
void *h[2];
|
||||||
|
int fail;
|
||||||
|
int (*fp) (void);
|
||||||
|
|
||||||
|
mtrace ();
|
||||||
|
|
||||||
|
h[0] = dlopen ("ltglobmod1.so", RTLD_LAZY);
|
||||||
|
if (h == NULL)
|
||||||
|
{
|
||||||
|
printf ("%s: cannot open %s: %s",
|
||||||
|
__FUNCTION__, "ltglobmod1.so", dlerror ());
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
h[1] = dlopen ("ltglobmod2.so", RTLD_LAZY);
|
||||||
|
if (h == NULL)
|
||||||
|
{
|
||||||
|
printf ("%s: cannot open %s: %s",
|
||||||
|
__FUNCTION__, "ltglobmod2.so", dlerror ());
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
puts ("loaded \"ltglobmod1.so\" without RTLD_GLOBAL");
|
||||||
|
|
||||||
|
fp = dlsym (h[1], "foo");
|
||||||
|
if (fp == NULL)
|
||||||
|
{
|
||||||
|
printf ("cannot get address of `foo': %s", dlerror ());
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
fail = fp ();
|
||||||
|
|
||||||
|
puts ("back in main");
|
||||||
|
|
||||||
|
dlclose (h[1]);
|
||||||
|
dlclose (h[0]);
|
||||||
|
|
||||||
|
return fail;
|
||||||
|
}
|
5
elf/ltglobmod1.c
Normal file
5
elf/ltglobmod1.c
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
int
|
||||||
|
bar (void)
|
||||||
|
{
|
||||||
|
return 42;
|
||||||
|
}
|
32
elf/ltglobmod2.c
Normal file
32
elf/ltglobmod2.c
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#include <dlfcn.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
extern int bar (void);
|
||||||
|
|
||||||
|
int
|
||||||
|
foo (void)
|
||||||
|
{
|
||||||
|
void *h;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
/* Load ltglobalmod1 in the global namespace. */
|
||||||
|
h = dlopen ("ltglobmod1.so", RTLD_GLOBAL | RTLD_LAZY);
|
||||||
|
if (h == NULL)
|
||||||
|
{
|
||||||
|
printf ("%s: cannot open %s: %s",
|
||||||
|
__FUNCTION__, "ltglobmod1.so", dlerror ());
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Call bar. This is undefined in the DSO. */
|
||||||
|
puts ("about to call `bar'");
|
||||||
|
fflush (stdout);
|
||||||
|
res = bar ();
|
||||||
|
|
||||||
|
printf ("bar returned %d\n", res);
|
||||||
|
|
||||||
|
dlclose (h);
|
||||||
|
|
||||||
|
return res != 42;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user