This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Reference counting bug in ld-linux.so.2 (2.1.2, 2.1.3, 2.1.9x, et. al.)


On Thu, Oct 19, 2000 at 11:32:10AM -0700, Ulrich Drepper wrote:
> "H . J . Lu" <hjl@lucon.org> writes:
> 
> > I don't think they are the same list. One is map->l_initfini and
> > the other is map->l_searchlist.r_list. Ulrich, are they the same list?
> 
> I will look at this when I have the time.
> 

Here is a testcase based on Allen's report.

H.J.
---
2000-10-19  H.J. Lu  <hjl@gnu.org>

	* elf/Makefile (distribute): Add neededtest.c, neededobj1.c,
	neededobj2.c and neededobj3.c.
	(tests): Add neededtest.
	(modules-names): Add neededobj1, neededobj2 and neededobj3.
	($(objpfx)neededobj1.so): New target.
	($(objpfx)neededobj2.so): Likewise.
	($(objpfx)neededobj3.so): Likewise.
	($(objpfx)neededtest): Likewise.
	($(objpfx)neededtest.out): Likewise.

	* elf/neededtest.c: New. Based on the bug report from
	"Allen Bauer" <kylix_rd@hotmail.com>.
	* elf/neededobj1.c: Likewise.
	* elf/neededobj2.c: Likewise.
	* elf/neededobj3.c: Likewise.

Index: elf/Makefile
===================================================================
RCS file: /work/cvs/gnu/glibc/elf/Makefile,v
retrieving revision 1.1.1.19
diff -u -p -r1.1.1.19 Makefile
--- elf/Makefile	2000/10/19 02:39:01	1.1.1.19
+++ elf/Makefile	2000/10/19 19:26:48
@@ -53,7 +53,8 @@ distribute	:= $(rtld-routines:=.c) dynam
 		   nodlopenmod.c nodelete.c nodelmod1.c nodelmod2.c \
 		   nodelmod3.c nodelmod4.c nodlopen.c dl-osinfo.h \
 		   reldepmod1.c reldepmod2.c reldepmod3.c reldepmod4.c \
-		   nextmod1.c nextmod2.c
+		   nextmod1.c nextmod2.c \
+		   neededtest.c neededobj1.c neededobj2.c neededobj3.c
 
 include ../Makeconfig
 
@@ -95,7 +96,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))
+	$(tests-nodlopen-$(have-z-nodlopen)) neededtest
 tests-vis-yes = vismain
 tests-nodelete-yes = nodelete
 tests-nodlopen-yes = nodlopen
@@ -105,7 +106,8 @@ modules-names = testobj1 testobj2 testob
 		dep1 dep2 dep3 dep4 $(modules-vis-$(have-protected)) \
 		$(modules-nodelete-$(have-z-nodelete)) \
 		$(modules-nodlopen-$(have-z-nodlopen)) filtmod1 filtmod2 \
-		reldepmod1 reldepmod2 reldepmod3 reldepmod4 nextmod1 nextmod2
+		reldepmod1 reldepmod2 reldepmod3 reldepmod4 nextmod1 nextmod2 \
+		neededobj1 neededobj2 neededobj3
 modules-vis-yes = vismod1 vismod2 vismod3
 modules-nodelete-yes = nodelmod1 nodelmod2 nodelmod3 nodelmod4
 modules-nodlopen-yes = nodlopenmod
@@ -249,6 +251,10 @@ $(objpfx)dep4.so: $(objpfx)dep3.so
 $(objpfx)nodelmod3.so: $(objpfx)nodelmod4.so
 $(objpfx)nextmod1.so: $(libdl)
 
+$(objpfx)neededobj1.so: $(libdl)
+$(objpfx)neededobj2.so: $(objpfx)neededobj1.so $(libdl)
+$(objpfx)neededobj3.so: $(objpfx)neededobj1.so $(objpfx)neededobj2.so $(libdl)
+
 # filtmod1.so has a special rule
 $(filter-out $(objpfx)filtmod1.so, $(test-modules)): $(objpfx)%.so: $(objpfx)%.os
 	$(build-module)
@@ -257,6 +263,11 @@ $(objpfx)loadtest: $(libdl)
 LDFLAGS-loadtest = -rdynamic
 
 $(objpfx)loadtest.out: $(test-modules)
+
+$(objpfx)neededtest: $(libdl)
+
+$(objpfx)neededtest.out: $(objpfx)neededobj1.so $(objpfx)neededobj2.so \
+		     $(objpfx)neededobj3.so
 
 $(objpfx)restest1: $(objpfx)testobj1.so $(objpfx)testobj1_1.so $(libdl)
 LDFLAGS-restest1 = -rdynamic
--- /dev/null	Thu Aug 24 02:00:32 2000
+++ elf/neededobj1.c	Thu Oct 19 12:13:23 2000
@@ -0,0 +1,3 @@
+void c_function(void)
+{
+}
--- /dev/null	Thu Aug 24 02:00:32 2000
+++ elf/neededobj2.c	Thu Oct 19 12:13:23 2000
@@ -0,0 +1,6 @@
+void c_function ();
+
+void b_function(void)
+{
+  c_function();
+}
--- /dev/null	Thu Aug 24 02:00:32 2000
+++ elf/neededobj3.c	Thu Oct 19 12:13:23 2000
@@ -0,0 +1,8 @@
+void b_function(void);
+void c_function(void);
+
+void a_function (void)
+{
+  b_function();
+  c_function();
+}
--- /dev/null	Thu Aug 24 02:00:32 2000
+++ elf/neededtest.c	Thu Oct 19 12:43:48 2000
@@ -0,0 +1,103 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <link.h>
+
+static int
+check_loaded_objects(const char **loaded)
+{
+  struct link_map *lm;
+  int n;
+  int *found = NULL;
+  int error = 0;
+
+  for (n = 0; loaded [n]; n++);
+
+  if (n)
+    {
+      found = (int *) alloca (sizeof (int) * n);
+      memset (found, 0, sizeof (int) * n);
+    }
+
+  printf("   Name\n");
+  printf(" --------------------------------------------------------\n");
+  for (lm = _r_debug.r_map; lm; lm = lm->l_next)
+    {
+      if (lm->l_name && lm->l_name [0])
+	printf(" %s\n", lm->l_name);
+      if (lm->l_type == lt_loaded && lm->l_name)
+	{
+	  int match = 0;
+	  for (n = 0; loaded [n]; n++)
+	    {
+	      if (strcmp (basename (loaded [n]), basename (lm->l_name)) == 0)
+	        {
+		  found [n] = 1;
+		  match = 1;
+		  break;
+		}
+	    }
+
+	  if (!match)
+	    {
+	      error++;
+	      printf ("ERROR: %s is not unloaded\n", lm->l_name);
+	    }
+	}
+    }
+
+  for (n = 0; loaded [n]; n++)
+    {
+      if (!found [n])
+        {
+	  error++;
+	  printf ("ERROR: %s is not loaded\n", loaded [n]);
+	}
+    }
+
+  return error;
+}
+
+int
+main(void)
+{
+  void *obj2;
+  void *obj3;
+  const char *loaded [] = { NULL, NULL, NULL, NULL};
+  int error = 0;
+
+  printf("\nThis is what is in memory now:\n");
+  error += check_loaded_objects (loaded);
+  printf("Loading shared object neededobj3.so\n");
+  obj3 = dlopen("neededobj3.so", RTLD_LAZY);
+  if (!obj3)
+    {
+      printf("%s\n", dlerror());
+      exit(1);
+    }    	
+  printf("And this is what is now in memory\n");
+  loaded [0] = "neededobj1.so";
+  loaded [1] = "neededobj2.so";
+  loaded [2] = "neededobj3.so";
+  error += check_loaded_objects (loaded);
+  printf("Now loading shared object neededobj2.so\n");
+  obj2 = dlopen("neededobj2.so", RTLD_LAZY);
+  if (!obj2)
+    {
+      printf("%s\n", dlerror());
+      exit(1);
+    }
+  printf("Again, this is what is in memory\n");
+  error += check_loaded_objects (loaded);
+  printf("Closing neededobj2.so\n");
+  dlclose(obj2);
+  error += check_loaded_objects (loaded);
+  printf("Closing neededobj3.so\n");
+  dlclose(obj3);
+  loaded [0] = NULL;
+  error += check_loaded_objects (loaded);
+  if (error)
+    printf ("%d errors found\n", error);
+  return error;
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]