Update.
authorUlrich Drepper <drepper@redhat.com>
Sat, 21 Oct 2000 07:16:18 +0000 (07:16 +0000)
committerUlrich Drepper <drepper@redhat.com>
Sat, 21 Oct 2000 07:16:18 +0000 (07:16 +0000)
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.

ChangeLog
elf/Makefile
elf/dl-open.c
elf/lateglobal.c [new file with mode: 0644]
elf/ltglobmod1.c [new file with mode: 0644]
elf/ltglobmod2.c [new file with mode: 0644]

index fb9cce5..c668cab 100644 (file)
--- a/ChangeLog
+++ b/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>
 
        * include/link.h (struct link_map): Add l_soname_added bitfield.
index 033b0dc..06ff79d 100644 (file)
@@ -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 \
                   nextmod1.c nextmod2.c \
                   neededobj1.c neededobj2.c neededobj3.c \
-                  unload2mod.c unload2dep.c
+                  unload2mod.c unload2dep.c ltglobmod1.c ltglobmod2.c
 
 include ../Makeconfig
 
@@ -97,7 +97,7 @@ ifeq (yes,$(build-shared))
 tests = loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
        constload1 order $(tests-vis-$(have-protected)) noload filter unload \
        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-nodelete-yes = nodelete
 tests-nodlopen-yes = nodlopen
@@ -108,7 +108,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
                $(modules-nodelete-$(have-z-nodelete)) \
                $(modules-nodlopen-$(have-z-nodlopen)) filtmod1 filtmod2 \
                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-nodelete-yes = nodelmod1 nodelmod2 nodelmod3 nodelmod4
 modules-nodlopen-yes = nodlopenmod
@@ -255,6 +256,7 @@ $(objpfx)neededobj1.so: $(libdl)
 $(objpfx)neededobj2.so: $(objpfx)neededobj1.so $(libdl)
 $(objpfx)neededobj3.so: $(objpfx)neededobj1.so $(objpfx)neededobj2.so $(libdl)
 $(objpfx)unload2mod.so: $(objpfx)unload2dep.so
+$(objpfx)ltglobmod2.so: $(libdl)
 
 # filtmod1.so has a special rule
 $(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.out: $(objpfx)unload2mod.so $(objpfx)unload2dep.so
+
+$(objpfx)lateglobal: $(libdl)
+$(objpfx)lateglobal.out: $(objpfx)ltglobmod1.so $(objpfx)ltglobmod2.so
index a618ca0..5c078d9 100644 (file)
@@ -80,6 +80,87 @@ struct dl_open_args
   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
 dl_open_worker (void *a)
 {
@@ -172,6 +253,12 @@ dl_open_worker (void *a)
                                         buf + sizeof buf - 1, 10, 0),
                             "\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.  */
       return;
     }
@@ -232,81 +319,10 @@ dl_open_worker (void *a)
 
   /* Now we can make the new map available in the global scope.  */
   if (mode & RTLD_GLOBAL)
-    {
-      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;
-           }
-
-         /* 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 */
-    }
+    /* Move the object in the global namespace.  */
+    if (add_to_global (new) != 0)
+      /* It failed.  */
+      return;
 
   /* Mark the object as not deletable if the RTLD_NODELETE flags was
      passed.  */
diff --git a/elf/lateglobal.c b/elf/lateglobal.c
new file mode 100644 (file)
index 0000000..2f6c269
--- /dev/null
@@ -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;
+}
diff --git a/elf/ltglobmod1.c b/elf/ltglobmod1.c
new file mode 100644 (file)
index 0000000..46e74ee
--- /dev/null
@@ -0,0 +1,5 @@
+int
+bar (void)
+{
+  return 42;
+}
diff --git a/elf/ltglobmod2.c b/elf/ltglobmod2.c
new file mode 100644 (file)
index 0000000..bc1cd27
--- /dev/null
@@ -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;
+}