summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog23
-rw-r--r--elf/constload1.c4
-rw-r--r--elf/dl-deps.c8
-rw-r--r--elf/dl-libc.c24
-rw-r--r--elf/dl-load.c1
-rw-r--r--elf/dl-open.c5
-rw-r--r--elf/filter.c7
-rw-r--r--elf/loadtest.c34
-rw-r--r--elf/restest1.c8
-rw-r--r--elf/rtld.c17
-rw-r--r--sysdeps/generic/ldsodefs.h2
11 files changed, 122 insertions, 11 deletions
diff --git a/ChangeLog b/ChangeLog
index 50bd2c7150..31f346315b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+2000-08-19  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf/Versions [ld] (GLIBC_2.2): Export _dl_check_map_versions.
+	* elf/dl-deps.c (_dl_map_object_deps): If object was dependency of
+	a dynamically loaded object remove old l_initfini list.
+	* elf/dl-libc.c (free_mem): Used as __libc_subfreeres callback to
+	remove some dynamically allocated memory blocks in the dynamic
+	loading data structures.
+	* elf/dl-load.c (add_name_to_object): Initialize dont_free to 0.
+	* elf/dl-open.c (dl_open_workder): Don't call _dl_check_all_versions.
+	Instead call _dl_check_map_versions only for the dependencies.
+	* elf/rtld.c: Avoid unneccessary initializations.  Mark l_libname
+	information of initial objects as not free-able.
+	* sysdeps/generic/ldsodefs.h (struct libname_list): Add dont_free
+	element.
+
+	* elf/filter.c: Call mtrace.
+	* elf/restest1.c: Likewise.  Close the objects.
+	* elf/loadtest.c: Call mtrace.  Check result of dlclose.  Print more
+	debug information.
+
+	* elf/constload1.c: Add comment explaining not freed memory.
+
 2000-08-18  Andreas Jaeger  <aj@suse.de>
 
 	* sysdeps/unix/sysv/linux/mips/bits/stat.h: Add pads to show
diff --git a/elf/constload1.c b/elf/constload1.c
index 4640b774cb..e0ddae9acc 100644
--- a/elf/constload1.c
+++ b/elf/constload1.c
@@ -18,6 +18,10 @@ main (void)
     error (EXIT_FAILURE, errno, "cannot load module \"constload2.so\"");
   foo = dlsym (h, "foo");
   ret = foo ();
+  /* Note that the following dlclose() call cannot unload the objects.
+     Due to the introduced relocation dependency constload2.so depends
+     on constload3.so and the dependencies of constload2.so on constload3.so
+     is not visible to ld.so since it's done using dlopen().  */
   if (dlclose (h) != 0)
     {
       puts ("failed to close");
diff --git a/elf/dl-deps.c b/elf/dl-deps.c
index 4fc2943c14..44838d6208 100644
--- a/elf/dl-deps.c
+++ b/elf/dl-deps.c
@@ -467,6 +467,14 @@ _dl_map_object_deps (struct link_map *map,
 	while (runp != NULL && runp->done);
     }
 
+  if (map->l_initfini != NULL && map->l_type == lt_loaded)
+    {
+      /* This object was previously loaded as a dependency and we have
+	 a separate l_initfini list.  We don't need it anymore.  */
+      assert (map->l_searchlist.r_list == NULL);
+      free (map->l_initfini);
+    }
+
   /* Store the search list we built in the object.  It will be used for
      searches in the scope of this object.  */
   map->l_searchlist.r_list = malloc ((2 * nlist + 1
diff --git a/elf/dl-libc.c b/elf/dl-libc.c
index 992a52e699..8518909b25 100644
--- a/elf/dl-libc.c
+++ b/elf/dl-libc.c
@@ -120,3 +120,27 @@ __libc_dlclose (void *__map)
 {
   return dlerror_run (do_dlclose, __map);
 }
+
+
+static void
+free_mem (void)
+{
+  struct link_map *l;
+
+  /* Remove all additional names added to the objects.  */
+  for (l = _dl_loaded; l != NULL; l = l->l_next)
+    {
+      struct libname_list *lnp = l->l_libname->next;
+
+      l->l_libname->next = NULL;
+
+      while (lnp != NULL)
+	{
+	  struct libname_list *old = lnp;
+	  lnp = lnp->next;
+	  if (! old->dont_free)
+	    free (old);
+	}
+    }
+}
+text_set_element (__libc_subfreeres, free_mem);
diff --git a/elf/dl-load.c b/elf/dl-load.c
index adeb7dced2..ea3c928169 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -322,6 +322,7 @@ add_name_to_object (struct link_map *l, const char *name)
 
   newname->name = memcpy (newname + 1, name, name_len);
   newname->next = NULL;
+  newname->dont_free = 0;
   lastp->next = newname;
 }
 
diff --git a/elf/dl-open.c b/elf/dl-open.c
index 60a8f1ad5b..b07ede15fc 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -88,6 +88,7 @@ dl_open_worker (void *a)
   struct link_map *new, *l;
   const char *dst;
   int lazy;
+  unsigned int i;
 
   /* Maybe we have to expand a DST.  */
   dst = strchr (file, '$');
@@ -163,7 +164,9 @@ dl_open_worker (void *a)
   _dl_map_object_deps (new, NULL, 0, 0);
 
   /* So far, so good.  Now check the versions.  */
-  (void) _dl_check_all_versions (new, 0, 0);
+  for (i = 0; i < new->l_searchlist.r_nlist; ++i)
+    if (new->l_searchlist.r_list[i]->l_versions == NULL)
+      (void) _dl_check_map_versions (new->l_searchlist.r_list[i], 0, 0);
 
 #ifdef SCOPE_DEBUG
   show_scope (new);
diff --git a/elf/filter.c b/elf/filter.c
index 76bc91adc5..46aa15ba16 100644
--- a/elf/filter.c
+++ b/elf/filter.c
@@ -1,3 +1,4 @@
+#include <mcheck.h>
 #include <stdio.h>
 #include <string.h>
 
@@ -6,7 +7,11 @@ extern const char *foo (void);
 int
 main (void)
 {
-  const char *s = foo ();
+  const char *s;
+
+  mtrace ();
+
+  s = foo ();
 
   printf ("called `foo' from `%s'\n", s);
 
diff --git a/elf/loadtest.c b/elf/loadtest.c
index 5b9e116987..80f99607ec 100644
--- a/elf/loadtest.c
+++ b/elf/loadtest.c
@@ -2,6 +2,7 @@
 #include <dlfcn.h>
 #include <errno.h>
 #include <error.h>
+#include <mcheck.h>
 #include <stdio.h>
 #include <stdlib.h>
 
@@ -66,10 +67,16 @@ static const struct
 #define NTESTS	(sizeof (tests) / sizeof (tests[0]))
 
 
+#include <include/link.h>
+
+
 int
 main (void)
 {
   int count = TEST_ROUNDS;
+  int result = 0;
+
+  mtrace ();
 
   /* Just a seed.  */
   srandom (TEST_ROUNDS);
@@ -102,23 +109,38 @@ main (void)
 
 	  fct (10);
 
-	  printf ("successfully loaded `%s'\n", testobjs[index].name);
+	  printf ("successfully loaded `%s', handle %p\n",
+		  testobjs[index].name, testobjs[index].handle);
 	}
       else
 	{
-	  dlclose (testobjs[index].handle);
-	  testobjs[index].handle = NULL;
+	  if (dlclose (testobjs[index].handle) != 0)
+	    {
+	      printf ("failed to close %s\n", testobjs[index].name);
+	      result = 1;
+	    }
+	  else
+	    printf ("successfully unloaded `%s', handle %p\n",
+		    testobjs[index].name, testobjs[index].handle);
 
-	  printf ("successfully unloaded `%s'\n", testobjs[index].name);
+	  testobjs[index].handle = NULL;
 	}
     }
 
   /* Unload all loaded modules.  */
   for (count = 0; count < NOBJS; ++count)
     if (testobjs[count].handle != NULL)
-      dlclose (testobjs[count].handle);
+{	  printf ("\nclose: %s: l_initfini = %p, l_versions = %p\n",
+		  testobjs[count].name,
+		  ((struct link_map*)testobjs[count].handle)->l_initfini,
+		  ((struct link_map*)testobjs[count].handle)->l_versions);
+      if (dlclose (testobjs[count].handle) != 0)
+	{
+	  printf ("failed to close %s\n", testobjs[count].name);
+	  result = 1;
+}	}
 
-  return 0;
+  return result;
 }
 
 
diff --git a/elf/restest1.c b/elf/restest1.c
index e4eca557c5..2b649c00d2 100644
--- a/elf/restest1.c
+++ b/elf/restest1.c
@@ -1,5 +1,6 @@
 #include <dlfcn.h>
 #include <error.h>
+#include <mcheck.h>
 #include <stdio.h>
 #include <stdlib.h>
 
@@ -13,6 +14,8 @@ main (void)
   int res1;
   int res2;
 
+  mtrace ();
+
   h1 = dlopen ("testobj1.so", RTLD_LAZY);
   if (h1 == NULL)
     error (EXIT_FAILURE, 0, "while loading `%s': %s", "testobj1.so",
@@ -37,6 +40,11 @@ main (void)
   res2 = fp2 (10);
   printf ("fp1(10) = %d\nfp2(10) = %d\n", res1, res2);
 
+  if (dlclose (h1) != 0)
+    error (EXIT_FAILURE, 0, "cannot close testobj1.so: %s\n", dlerror ());
+  if (dlclose (h2) != 0)
+    error (EXIT_FAILURE, 0, "cannot close testobj1_1.so: %s\n", dlerror ());
+
   return res1 != 42 || res2 != 72;
 }
 
diff --git a/elf/rtld.c b/elf/rtld.c
index 9a444fcfd9..41cf5c36d5 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -590,7 +590,7 @@ of this helper program; chances are you did not intend to run this program.\n\
 	   the shared object is already loaded.  */
 	_dl_rtld_libname.name = ((const char *) _dl_loaded->l_addr
 				 + ph->p_vaddr);
-	_dl_rtld_libname.next = NULL;
+	/* _dl_rtld_libname.next = NULL;	Already zero.  */
 	_dl_rtld_map.l_libname = &_dl_rtld_libname;
 
 	/* Ordinarilly, we would get additional names for the loader from
@@ -604,7 +604,7 @@ of this helper program; chances are you did not intend to run this program.\n\
 	    if (p)
 	      {
 		_dl_rtld_libname2.name = p+1;
-		_dl_rtld_libname2.next = NULL;
+		/* _dl_rtld_libname2.next = NULL;  Already zero.  */
 		_dl_rtld_libname.next = &_dl_rtld_libname2;
 	      }
 	  }
@@ -626,7 +626,7 @@ of this helper program; chances are you did not intend to run this program.\n\
       /* We were invoked directly, so the program might not have a
 	 PT_INTERP.  */
       _dl_rtld_libname.name = _dl_rtld_map.l_name;
-      _dl_rtld_libname.next = NULL;
+      /* _dl_rtld_libname.next = NULL; 	Alread zero.  */
       _dl_rtld_map.l_libname =  &_dl_rtld_libname;
     }
   else
@@ -1059,6 +1059,17 @@ of this helper program; chances are you did not intend to run this program.\n\
     HP_TIMING_NOW (start);
     do
       {
+	/* While we are at it, help the memory handling a bit.  We have to
+	   mark some data structures as allocated with the fake malloc()
+	   implementation in ld.so.  */
+	struct libname_list *lnp = l->l_libname->next;
+
+	while (__builtin_expect (lnp != NULL, 0))
+	  {
+	    lnp->dont_free = 1;
+	    lnp = lnp->next;
+	  }
+
 	if (l != &_dl_rtld_map)
 	  _dl_relocate_object (l, l->l_scope, _dl_lazy, consider_profiling);
 
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index f7f77c2c1a..ceb2b87694 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -115,6 +115,8 @@ struct libname_list
   {
     const char *name;		/* Name requested (before search).  */
     struct libname_list *next;	/* Link to next name for this object.  */
+    int dont_free;		/* Flag whether this element should be freed
+				   if the object is not entirely unloaded.  */
   };