PATCH: Treat RTLD_LOCAL like Solaris (Re: Duplicate data objects in shared libraries)

H . J . Lu hjl@lucon.org
Thu May 30 11:01:00 GMT 2002


On Wed, May 29, 2002 at 01:09:45PM -0700, H . J . Lu wrote:
> This patch makes glibc more like Solaris for RTLD_LOCAL. It also passed
> "make check" in glibc. Any comments?
> 
> BTW, we need to fully document the RTLD_LOCAL behavior.
> 
> 

Here is an update. I need to adjust one assert in dl-close.c.


H.J.
-------------- next part --------------
2002-05-29  H.J. Lu  <hjl@gnu.org>

	* elf/dl-close.c (_dl_close): Don't assume the object to be
	dlcosed is the first one on l_initfini or l_searchlist.r_list.
	* elf/dl-deps.c (_dl_map_object_deps): Likewise.

	* elf/dl-deps.c (_dl_map_object_deps): If a DT_NEEDED object
	is loaded via dlopen already, put it before the current object.

--- elf/dl-close.c.local	Thu May 30 08:58:36 2002
+++ elf/dl-close.c	Thu May 30 09:01:01 2002
@@ -98,6 +98,7 @@ _dl_close (void *_map)
   struct link_map **list;
   struct link_map *map = _map;
   unsigned int i;
+  unsigned int imap;
   unsigned int *new_opencount;
 #ifdef USE_TLS
   bool any_tls = false;
@@ -147,9 +148,13 @@ _dl_close (void *_map)
       list[i]->l_idx = i;
       new_opencount[i] = list[i]->l_opencount;
     }
-  --new_opencount[0];
-  for (i = 1; list[i] != NULL; ++i)
-    if ((! (list[i]->l_flags_1 & DF_1_NODELETE) || ! list[i]->l_init_called)
+  for (i = 0; list[i] != NULL; ++i)
+    if (list [i] == map)
+      {
+	--new_opencount[i];
+	imap = i;
+      }
+    else if ((! (list[i]->l_flags_1 & DF_1_NODELETE) || ! list[i]->l_init_called)
 	/* Decrement counter.  */
 	&& --new_opencount[i] == 0
 	/* Test whether this object was also loaded directly.  */
@@ -160,15 +165,16 @@ _dl_close (void *_map)
 	unsigned int j;
 	struct link_map **dep_list = list[i]->l_searchlist.r_list;
 
-	for (j = 1; j < list[i]->l_searchlist.r_nlist; ++j)
-	  if (! (dep_list[j]->l_flags_1 & DF_1_NODELETE)
-	      || ! dep_list[j]->l_init_called)
+	for (j = 0; j < list[i]->l_searchlist.r_nlist; ++j)
+	  if (list[i] != dep_list[j]
+	      && (! (dep_list[j]->l_flags_1 & DF_1_NODELETE)
+		     || ! dep_list[j]->l_init_called))
 	    {
 	      assert (dep_list[j]->l_idx < map->l_searchlist.r_nlist);
 	      --new_opencount[dep_list[j]->l_idx];
 	    }
       }
-  assert (new_opencount[0] == 0);
+  assert (new_opencount[imap] == 0);
 
   /* Call all termination functions at once.  */
   for (i = 0; list[i] != NULL; ++i)
--- elf/dl-deps.c.local	Thu May 30 08:58:36 2002
+++ elf/dl-deps.c	Thu May 30 08:58:36 2002
@@ -266,12 +266,31 @@ _dl_map_object_deps (struct link_map *ma
 
 		    newp = alloca (sizeof (struct list));
 
-		    /* Append DEP to the list.  */
-		    newp->map = dep;
-		    newp->done = 0;
-		    newp->next = NULL;
-		    tail->next = newp;
-		    tail = newp;
+		    if (dep->l_relocated && dep->l_type == lt_loaded)
+		      {
+			/* It is very tricky. We have to put DEP at the
+			   right place on the list. */
+			memcpy (newp, orig, sizeof (*newp));
+			orig->done = 0;
+			orig->map = dep;
+			orig->next = newp;
+
+			/* Move the tail pointer if necessary.  */
+			if (orig == tail)
+			  tail = newp;
+
+			/* Move on the insert point.  */
+			orig = newp;
+		      }
+		    else
+		      {
+			/* Append DEP to the list.  */
+			newp->map = dep;
+			newp->done = 0;
+			newp->next = NULL;
+			tail->next = newp;
+			tail = newp;
+		      }
 		    ++nlist;
 		    /* Set the mark bit that says it's already in the list.  */
 		    dep->l_reserved = 1;
@@ -559,13 +578,13 @@ Filters not supported with LD_TRACE_PREL
     }
 
   /* Maybe we can remove some relocation dependencies now.  */
-  assert (map->l_searchlist.r_list[0] == map);
   for (i = 0; i < map->l_reldepsact; ++i)
     {
       unsigned int j;
 
-      for (j = 1; j < nlist; ++j)
-	if (map->l_searchlist.r_list[j] == map->l_reldeps[i])
+      for (j = 0; j < nlist; ++j)
+	if (map->l_searchlist.r_list[j] != map
+	    && map->l_searchlist.r_list[j] == map->l_reldeps[i])
 	  {
 	    /* A direct or transitive dependency is also on the list
 	       of relocation dependencies.  Remove the latter.  */
@@ -588,12 +607,15 @@ Filters not supported with LD_TRACE_PREL
   /* We can skip looking for the binary itself which is at the front
      of the search list.  Look through the list backward so that circular
      dependencies are not changing the order.  */
-  for (i = 1; i < nlist; ++i)
+  for (i = 0; i < nlist; ++i)
     {
       struct link_map *l = map->l_searchlist.r_list[i];
       unsigned int j;
       unsigned int k;
 
+      if (l == map)
+	continue;
+
       /* Find the place in the initfini list where the map is currently
 	 located.  */
       for (j = 1; map->l_initfini[j] != l; ++j)


More information about the Libc-alpha mailing list