about summary refs log tree commit diff
path: root/elf/rtld.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2005-03-18 11:11:42 +0000
committerUlrich Drepper <drepper@redhat.com>2005-03-18 11:11:42 +0000
commit20fe49b93a8807b7e91732d5a1b21a2d99472793 (patch)
tree03326dfe9fea0cad1bbb77d4f546584de6c60b5d /elf/rtld.c
parent193af754dc157708224817fb8ff8914f2fc5e6e1 (diff)
downloadglibc-20fe49b93a8807b7e91732d5a1b21a2d99472793.tar.gz
glibc-20fe49b93a8807b7e91732d5a1b21a2d99472793.tar.xz
glibc-20fe49b93a8807b7e91732d5a1b21a2d99472793.zip
* include/link.h (struct link_map): Remove l_opencount. Add l_removed.
	Change type of l_idx to int.
	* elf/dl-close.c: Basically rewrite.  Do not use l_opencount to
	determine whether a DSO has to be unloaded.  Instead compute this
	in this function.
	* elf/dl-deps.c: No need to manipulate l_opencount anymore.
	* elf/dl-lookup.c: Likewise.
	* elf/rtld.c: Likewise
	* elf/dl-open.c: Likewise.  Use l_init_called to determine whether
	object was just loaded.
	* elf/dl-fini.c: Bump l_direct_opencount instead of l_opencount.
	* elf/dl-load.c (_dl_map_object_from_fd): Do not recognize DSO which
	is about to be unloaded as a match.
	(_dl_map_object): Likewise.
	* elf/do-lookup.h (do_lookup_x): Do not look into DSO which is about
	to be unloaded.
	* elf/circleload1.c: Don't use l_opencount anymore.
	* elf/neededtest.c: Likewise.
	* elf/neededtest2.c: Likewise.
	* elf/neededtest3.c: Likewise.
	* elf/neededtest4.c: Likewise.
	* elf/unload.c: Likewise.
	* elf/unload2.c: Likewise.
	* elf/loadtest.c: Likewise.

	* elf/rtld.c: Preloading errors are now never fatal.

2005-03-08  Jakub Jelinek  <jakub@redhat.com>

	* elf/Makefile: Add rules to build and run unload5 test.
	* elf/unload5.c: New file.

2005-03-08  Jakub Jelinek  <jakub@redhat.com>

	* elf/Makefile: Add rules to build and run unload4 test.
	* elf/unload4.c: New file.
	* elf/unload4mod1.c: New file.
	* elf/unload4mod2.c: New file.
	* elf/unload4mod3.c: New file.
	* elf/unload4mod4.c: New file.
Diffstat (limited to 'elf/rtld.c')
-rw-r--r--elf/rtld.c126
1 files changed, 61 insertions, 65 deletions
diff --git a/elf/rtld.c b/elf/rtld.c
index fbb4e4c3f2..56cd39f3c6 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -267,7 +267,6 @@ _dl_start_final (void *arg, struct dl_start_final_info *info)
 #endif
   _dl_setup_hash (&GL(dl_rtld_map));
   GL(dl_rtld_map).l_real = &GL(dl_rtld_map);
-  GL(dl_rtld_map).l_opencount = 1;
   GL(dl_rtld_map).l_map_start = (ElfW(Addr)) _begin;
   GL(dl_rtld_map).l_map_end = (ElfW(Addr)) _end;
   GL(dl_rtld_map).l_text_end = (ElfW(Addr)) _etext;
@@ -764,14 +763,48 @@ _dl_initial_error_catch_tsd (void)
 }
 #endif
 
+
+static unsigned int
+do_preload (char *fname, struct link_map *main_map, const char *where)
+{
+  const char *objname;
+  const char *err_str = NULL;
+  struct map_args args;
+
+  args.str = fname;
+  args.loader = main_map;
+  args.is_preloaded = 1;
+  args.mode = 0;
+
+  unsigned int old_nloaded = GL(dl_ns)[LM_ID_BASE]._ns_nloaded;
+
+  (void) _dl_catch_error (&objname, &err_str, map_doit, &args);
+  if (__builtin_expect (err_str != NULL, 0))
+    {
+      _dl_error_printf ("\
+ERROR: ld.so: object '%s' from %s cannot be preloaded: ignored.\n",
+			fname, where);
+      /* No need to call free, this is still before
+	 the libc's malloc is used.  */
+    }
+  else if (GL(dl_ns)[LM_ID_BASE]._ns_nloaded != old_nloaded)
+    /* It is no duplicate.  */
+    return 1;
+
+  /* Nothing loaded.  */
+  return 0;
+}
+
 #if defined SHARED && defined _LIBC_REENTRANT \
     && defined __rtld_lock_default_lock_recursive
-static void rtld_lock_default_lock_recursive (void *lock)
+static void
+rtld_lock_default_lock_recursive (void *lock)
 {
   __rtld_lock_default_lock_recursive (lock);
 }
 
-static void rtld_lock_default_unlock_recursive (void *lock)
+static void
+rtld_lock_default_unlock_recursive (void *lock)
 {
   __rtld_lock_default_unlock_recursive (lock);
 }
@@ -792,8 +825,6 @@ dl_main (const ElfW(Phdr) *phdr,
 {
   const ElfW(Phdr) *ph;
   enum mode mode;
-  struct link_map **preloads;
-  unsigned int npreloads;
   struct link_map *main_map;
   size_t file_size;
   char *file;
@@ -1024,8 +1055,6 @@ of this helper program; chances are you did not intend to run this program.\n\
   main_map->l_text_end = 0;
   /* Perhaps the executable has no PT_LOAD header entries at all.  */
   main_map->l_map_start = ~0;
-  /* We opened the file, account for it.  */
-  ++main_map->l_opencount;
   /* And it was opened directly.  */
   ++main_map->l_direct_opencount;
 
@@ -1449,8 +1478,9 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
   /* We have two ways to specify objects to preload: via environment
      variable and via the file /etc/ld.so.preload.  The latter can also
      be used when security is enabled.  */
-  preloads = NULL;
-  npreloads = 0;
+  assert (GL(dl_rtld_map).l_next == NULL);
+  struct link_map **preloads = NULL;
+  unsigned int npreloads = 0;
 
   if (__builtin_expect (preloadlist != NULL, 0))
     {
@@ -1469,14 +1499,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
 	if (p[0] != '\0'
 	    && (__builtin_expect (! INTUSE(__libc_enable_secure), 1)
 		|| strchr (p, '/') == NULL))
-	  {
-	    struct link_map *new_map = _dl_map_object (main_map, p, 1,
-						       lt_library, 0, 0,
-						       LM_ID_BASE);
-	    if (++new_map->l_opencount == 1)
-	      /* It is no duplicate.  */
-	      ++npreloads;
-	  }
+	  npreloads += do_preload (p, main_map, "LD_PRELOAD");
 
       HP_TIMING_NOW (stop);
       HP_TIMING_DIFF (diff, start, stop);
@@ -1548,41 +1571,14 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
 	      runp = file;
 	      while ((p = strsep (&runp, ": \t\n")) != NULL)
 		if (p[0] != '\0')
-		  {
-		    const char *objname;
-		    const char *err_str = NULL;
-		    struct map_args args;
-
-		    args.str = p;
-		    args.loader = main_map;
-		    args.is_preloaded = 1;
-		    args.mode = 0;
-
-		    (void) _dl_catch_error (&objname, &err_str, map_doit,
-					    &args);
-		    if (__builtin_expect (err_str != NULL, 0))
-		      {
-			_dl_error_printf ("\
-ERROR: ld.so: object '%s' from %s cannot be preloaded: ignored.\n",
-					  p, preload_file);
-			/* No need to call free, this is still before
-			   the libc's malloc is used.  */
-		      }
-		    else if (++args.map->l_opencount == 1)
-		      /* It is no duplicate.  */
-		      ++npreloads;
-		  }
+		  npreloads += do_preload (p, main_map, preload_file);
 	    }
 
 	  if (problem != NULL)
 	    {
 	      char *p = strndupa (problem, file_size - (problem - file));
-	      struct link_map *new_map = _dl_map_object (main_map, p, 1,
-							 lt_library, 0, 0,
-							 LM_ID_BASE);
-	      if (++new_map->l_opencount == 1)
-		/* It is no duplicate.  */
-		++npreloads;
+
+	      npreloads += do_preload (p, main_map, preload_file);
 	    }
 
 	  HP_TIMING_NOW (stop);
@@ -1594,7 +1590,7 @@ ERROR: ld.so: object '%s' from %s cannot be preloaded: ignored.\n",
 	}
     }
 
-  if (__builtin_expect (npreloads, 0) != 0)
+  if (__builtin_expect (GL(dl_rtld_map).l_next != NULL, 0))
     {
       /* Set up PRELOADS with a vector of the preloaded libraries.  */
       struct link_map *l;
@@ -1694,14 +1690,9 @@ ERROR: ld.so: object '%s' from %s cannot be preloaded: ignored.\n",
   HP_TIMING_DIFF (diff, start, stop);
   HP_TIMING_ACCUM_NT (load_time, diff);
 
-  /* Mark all objects as being in the global scope and set the open
-     counter.  */
+  /* Mark all objects as being in the global scope.  */
   for (i = main_map->l_searchlist.r_nlist; i > 0; )
-    {
-      --i;
-      main_map->l_searchlist.r_list[i]->l_global = 1;
-      ++main_map->l_searchlist.r_list[i]->l_opencount;
-    }
+    main_map->l_searchlist.r_list[--i]->l_global = 1;
 
 #ifndef MAP_ANON
   /* We are done mapping things, so close the zero-fill descriptor.  */
@@ -1711,18 +1702,22 @@ ERROR: ld.so: object '%s' from %s cannot be preloaded: ignored.\n",
 
   /* Remove _dl_rtld_map from the chain.  */
   GL(dl_rtld_map).l_prev->l_next = GL(dl_rtld_map).l_next;
-  if (GL(dl_rtld_map).l_next)
+  if (GL(dl_rtld_map).l_next != NULL)
     GL(dl_rtld_map).l_next->l_prev = GL(dl_rtld_map).l_prev;
 
-  if (__builtin_expect (GL(dl_rtld_map).l_opencount > 1, 1))
+  for (i = 1; i < main_map->l_searchlist.r_nlist; ++i)
+    if (main_map->l_searchlist.r_list[i] == &GL(dl_rtld_map))
+      break;
+
+  bool rtld_multiple_ref = false;
+  if (__builtin_expect (i < main_map->l_searchlist.r_nlist, 1))
     {
       /* Some DT_NEEDED entry referred to the interpreter object itself, so
 	 put it back in the list of visible objects.  We insert it into the
 	 chain in symbol search order because gdb uses the chain's order as
 	 its symbol search order.  */
-      i = 1;
-      while (main_map->l_searchlist.r_list[i] != &GL(dl_rtld_map))
-	++i;
+      rtld_multiple_ref = true;
+
       GL(dl_rtld_map).l_prev = main_map->l_searchlist.r_list[i - 1];
       if (__builtin_expect (mode, normal) == normal)
 	{
@@ -1894,7 +1889,7 @@ ERROR: ld.so: object '%s' from %s cannot be preloaded: ignored.\n",
 	  }
       else
 	{
-	  /* If LD_WARN is set warn about undefined symbols.  */
+	  /* If LD_WARN is set, warn about undefined symbols.  */
 	  if (GLRO(dl_lazy) >= 0 && GLRO(dl_verbose))
 	    {
 	      /* We have to do symbol dependency testing.  */
@@ -1904,7 +1899,7 @@ ERROR: ld.so: object '%s' from %s cannot be preloaded: ignored.\n",
 	      args.lazy = GLRO(dl_lazy);
 
 	      l = main_map;
-	      while (l->l_next)
+	      while (l->l_next != NULL)
 		l = l->l_next;
 	      do
 		{
@@ -1915,10 +1910,11 @@ ERROR: ld.so: object '%s' from %s cannot be preloaded: ignored.\n",
 					 &args);
 		    }
 		  l = l->l_prev;
-		} while (l);
+		}
+	      while (l != NULL);
 
 	      if ((GLRO(dl_debug_mask) & DL_DEBUG_PRELINK)
-		  && GL(dl_rtld_map).l_opencount > 1)
+		  && rtld_multiple_ref)
 		{
 		  /* Mark the link map as not yet relocated again.  */
 		  GL(dl_rtld_map).l_relocated = 0;
@@ -2198,7 +2194,7 @@ ERROR: ld.so: object '%s' from %s cannot be preloaded: ignored.\n",
 	/* We must prepare the profiling.  */
 	_dl_start_profile ();
 
-      if (GL(dl_rtld_map).l_opencount > 1)
+      if (rtld_multiple_ref)
 	{
 	  /* There was an explicit ref to the dynamic linker as a shared lib.
 	     Re-relocate ourselves with user-controlled symbol definitions.  */