summary refs log tree commit diff
path: root/elf/dl-close.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2003-01-12 10:11:16 +0000
committerUlrich Drepper <drepper@redhat.com>2003-01-12 10:11:16 +0000
commitaff4519d380c863ed0f259a1387cb473d3f3bad2 (patch)
tree825718efb1a8a4598d6de379d70a05ee034ab4f2 /elf/dl-close.c
parent26a676d0aae53e2e770581c133356d8c0e39268c (diff)
downloadglibc-aff4519d380c863ed0f259a1387cb473d3f3bad2.tar.gz
glibc-aff4519d380c863ed0f259a1387cb473d3f3bad2.tar.xz
glibc-aff4519d380c863ed0f259a1387cb473d3f3bad2.zip
Update.
2003-01-11  Jim Meyering  <jim@meyering.net>

	* io/ftw.c [HAVE_CONFIG_H]: Include <config.h>.
	[HAVE_SYS_PARAM_H || _LIBC]: Guard inclusion of <sys/param.h>.
	Include <sys/stat.h>, not <include/sys/stat.h>, if !_LIBC.
	[!_LIBC] (__chdir, __closedir, __fchdir, __getcwd, __opendir): Define.
	[!_LIBC] (__readdir64, __tdestroy, __tfind, __tsearch): Define.
	[!_LIBC] (internal_function, dirent64, MAX): Define.
	(__set_errno): Define if not already defined.
	(open_dir_stream): When FTW_CHDIR is enabled, invoke opendir on
	the basename, not the entire file name.
	(process_entry): When FTW_CHDIR is enabled, invoke XSTAT or LXSTAT on
	the basename, not the entire file name.

2003-01-12  Ulrich Drepper  <drepper@redhat.com>

	* string/tester.c (test_strcpy): Disable last added strcpy until
	it is fixed.

2003-01-11  Philip Blundell  <philb@gnu.org>

	* sysdeps/unix/sysv/linux/arm/socket.S: Add cancellation support.

2003-01-11  Andreas Schwab  <schwab@suse.de>

	* Makerules: Add vpath for %.dynsym and %.so so that the
	implicit rule chaining for check-abi works.

2003-01-11  Kaz Kojima  <kkojima@rr.iij4u.or.jp>

	* sysdeps/unix/sysv/linux/sh/sysdep.h (SYSCALL_ERROR_HANDLER):
	Add non-PIC case.

2003-01-11  Jakub Jelinek  <jakub@redhat.com>

	* elf/tls-macros.h [__ia64__] (__TLS_CALL_CLOBBERS): Define.
	[__ia64__] (TLS_LE, TLS_IE): Fix typos.  Add ;; at start of asm if
	gp is used early.
	[__ia64__] (TLS_LD, TLS_GD): Likewise.  Use __TLS_CALL_CLOBBERS.
	* elf/Makefile ($(objpfx)tst-tlsmod5.so, $(objpfx)tst-tlsmod6.so):
	Ensure libc.so in DT_NEEDED.
	* sysdeps/alpha/dl-machine.h (elf_machine_rela): Move
	CHECK_STATIC_TLS before l_tls_offset use.
	* sysdeps/i386/dl-machine.h (elf_machine_rel, elf_machine_rela):
	Likewise.
	* sysdeps/sh/dl-machine.h (elf_machine_rela): Likewise.
	* sysdeps/generic/dl-tls.c (_dl_allocate_tls_storage) [TLS_DTV_AT_TP]:
	Allocate TLS_PRE_TCB_SIZE bytes below result.
	(_dl_deallocate_tls) [TLS_DTV_AT_TP]: Adjust before freeing.
	* sysdeps/generic/libc-tls.c (__libc_setup_tls): If
	TLS_INIT_TP_EXPENSIVE is not defined, allocate even if no PT_TLS
	segment has been found.  If TLS_DTV_AT_TP, allocate TLS_PRE_TCB_SIZE
	bytes below result and add tcb_offset to memsz.
	* sysdeps/ia64/dl-tls.h (__tls_get_addr): New prototype.
	* sysdeps/ia64/dl-machine.h: Include tls.h.
	(elf_machine_type_class): Return ELF_RTYPE_CLASS_PLT for TLS relocs
	too.
	(elf_machine_rela): Assume if sym_map != NULL sym is non-NULL too.
	Handle R_IA64_DTPMOD*, R_IA64_DTPREL* and R_IA64_TPREL* relocations.
	* sysdeps/ia64/libc-tls.c: New file.

2003-01-10  Steven Munroe  <sjmunroe@us.ibm.com>

	* sysdeps/powerpc/powerpc64/sysdep.h (PSEUDO_RET): Add branch hit.
	* sysdeps/unix/sysv/linux/powerpc/bits/stat.h (STAT_VER_LINUX):
	Fix type.  Move definition out of #if.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/ftruncate64.c: New file.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/pread.c: New file.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/pread64.c: New file.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/pwrite.c: New file.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/pwrite64.c: New file.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/socket.S: Add cancellation
	support.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/syscalls.list: Remove
	ftruncate64, pread64, pwrite64, truncate64 entries.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
	(INLINE_SYSCALL): New version that supports function call like
	syscalls.  Add __builtin_expect.
	(LOADARGS_n): Add argument size safety checks.
	(INTERNAL_SYSCALL): New Macro.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/truncate64.c: New file.
	* sysdeps/unix/sysv/linux/powerpc/sys/procfs.h [__PPC_ELF_H]: Avoid
	redefinition of elf_fpreg_t and elf_fpregset_t.

2003-01-12  Ulrich Drepper  <drepper@redhat.com>

	* elf/dl-close.c (_dl_close): Add several asserts.  Correct and
	simplify test for unloading.  If loader of a DSO is unloaded do not
	use its scope anymore.  Fall back to own scope and adjust opencounts.
	Fix several comments.
	* elf/dl-deps.c (_dl_map_object_deps): Always allocate memory for
	the l_searchlist, not only for l_initfini.

	* elf/dl-lookup.c (add_dependencies): Avoid creating relocation
	dependencies if objects cannot be removed.  Remove object with the
	definition as not unloadable if necessary.

	* elf/reldep6.c: Create relocation dependency before closing the first
	module.

2003-01-10  Guido Günther  <agx@sigxcpu.org>
	* elf/Makefile: Add rules to build and run reldep9 test.
	* elf/reldep9.c: New file.
	* elf/reldep9mod1.c: New file.
	* elf/reldep9mod2.c: New file.
	* elf/reldep9mod3.c: New file.

2003-01-09  Jakub Jelinek  <jakub@redhat.com>

	* elf/Makefile: Add rules to build and run nodelete2 test.
	* elf/nodelete2.c: New file.
	* elf/nodel2mod1.c: New file.
	* elf/nodel2mod2.c: New file.
	* elf/nodel2mod3.c: New file.

2003-01-09  Jakub Jelinek  <jakub@redhat.com>
Diffstat (limited to 'elf/dl-close.c')
-rw-r--r--elf/dl-close.c127
1 files changed, 87 insertions, 40 deletions
diff --git a/elf/dl-close.c b/elf/dl-close.c
index 7e4626e3d6..0953fab210 100644
--- a/elf/dl-close.c
+++ b/elf/dl-close.c
@@ -1,5 +1,5 @@
 /* Close a shared object opened by `_dl_open'.
-   Copyright (C) 1996-2001, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1996-2002, 2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -138,7 +138,7 @@ _dl_close (void *_map)
 	_dl_debug_printf ("\nclosing file=%s; opencount == %u\n",
 			  map->l_name, map->l_opencount);
 
-      /* One decrement the object itself, not the dependencies.  */
+      /* Decrement the object's reference counter, not the dependencies'.  */
       --map->l_opencount;
 
       __rtld_lock_unlock_recursive (GL(dl_load_lock));
@@ -165,7 +165,7 @@ _dl_close (void *_map)
     }
   --new_opencount[0];
   for (i = 1; list[i] != NULL; ++i)
-    if ((! (list[i]->l_flags_1 & DF_1_NODELETE) || ! list[i]->l_init_called)
+    if ((list[i]->l_flags_1 & DF_1_NODELETE) == 0
 	/* Decrement counter.  */
 	&& --new_opencount[i] == 0)
       {
@@ -185,7 +185,10 @@ _dl_close (void *_map)
 		{
 		  assert (dep_list[j]->l_idx < map->l_searchlist.r_nlist);
 		  if (--new_opencount[dep_list[j]->l_idx] == 0)
-		    mark_removed (dep_list[j]);
+		    {
+		      assert (dep_list[j]->l_type == lt_loaded);
+		      mark_removed (dep_list[j]);
+		    }
 		}
 	      }
 
@@ -200,8 +203,11 @@ _dl_close (void *_map)
 			    == remmap->l_reldeps[j]))
 		      /* Yes, it is.  */
 		      if (--new_opencount[remmap->l_reldeps[j]->l_idx] == 0)
-			/* This one is now gone, too.  */
-			mark_removed (remmap->l_reldeps[j]);
+			{
+			  /* This one is now gone, too.  */
+			  assert (remmap->l_reldeps[j]->l_type == lt_loaded);
+			  mark_removed (remmap->l_reldeps[j]);
+			}
 		  }
 	      }
 	  }
@@ -215,57 +221,98 @@ _dl_close (void *_map)
     {
       struct link_map *imap = list[i];
       if (new_opencount[i] == 0 && imap->l_type == lt_loaded
-	  && (imap->l_info[DT_FINI] || imap->l_info[DT_FINI_ARRAY])
-	  && (! (imap->l_flags_1 & DF_1_NODELETE) || ! imap->l_init_called)
-	  /* Skip any half-cooked objects that were never initialized.  */
-	  && imap->l_init_called)
+	  && (imap->l_flags_1 & DF_1_NODELETE) == 0)
 	{
 	  /* When debugging print a message first.  */
 	  if (__builtin_expect (GL(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0))
 	    _dl_debug_printf ("\ncalling fini: %s\n\n", imap->l_name);
 
-	  /* Call its termination function.  */
-	  if (imap->l_info[DT_FINI_ARRAY] != NULL)
+	  /* Call its termination function.  Do not do it for
+	     half-cooked objects.  */
+	  if (imap->l_init_called)
 	    {
-	      ElfW(Addr) *array =
-		(ElfW(Addr) *) (imap->l_addr
-				+ imap->l_info[DT_FINI_ARRAY]->d_un.d_ptr);
-	      unsigned int sz = (imap->l_info[DT_FINI_ARRAYSZ]->d_un.d_val
-				 / sizeof (ElfW(Addr)));
-	      unsigned int cnt;
-
-	      for (cnt = 0; cnt < sz; ++cnt)
-		((fini_t) (imap->l_addr + array[cnt])) ();
+	      if (imap->l_info[DT_FINI_ARRAY] != NULL)
+		{
+		  ElfW(Addr) *array =
+		    (ElfW(Addr) *) (imap->l_addr
+				    + imap->l_info[DT_FINI_ARRAY]->d_un.d_ptr);
+		  unsigned int sz = (imap->l_info[DT_FINI_ARRAYSZ]->d_un.d_val
+				     / sizeof (ElfW(Addr)));
+		  unsigned int cnt;
+
+		  for (cnt = 0; cnt < sz; ++cnt)
+		    ((fini_t) (imap->l_addr + array[cnt])) ();
+		}
+
+	      /* Next try the old-style destructor.  */
+	      if (imap->l_info[DT_FINI] != NULL)
+		(*(void (*) (void)) DL_DT_FINI_ADDRESS
+		 (imap, ((void *) imap->l_addr
+			 + imap->l_info[DT_FINI]->d_un.d_ptr))) ();
 	    }
 
-	  /* Next try the old-style destructor.  */
-	  if (imap->l_info[DT_FINI] != NULL)
-	    (*(void (*) (void)) DL_DT_FINI_ADDRESS
-	      (imap, (void *) imap->l_addr
-		     + imap->l_info[DT_FINI]->d_un.d_ptr)) ();
+	  /* This object must not be used anymore.  We must remove the
+	     reference from the scope.  */
+	  unsigned int j;
+	  struct link_map **searchlist = map->l_searchlist.r_list;
+	  unsigned int nsearchlist = map->l_searchlist.r_nlist;
+
+#ifndef NDEBUG
+	  bool found = false;
+#endif
+	  for (j = 0; j < nsearchlist; ++j)
+	    if (imap == searchlist[j])
+	      {
+		/* This is the object to remove.  Copy all the
+		   following ones.  */
+		while (++j < nsearchlist)
+		  searchlist[j - 1] = searchlist[j];
+
+		searchlist[j - 1] = NULL;
+
+		--map->l_searchlist.r_nlist;
+
+#ifndef NDEBUG
+		found = true;
+#endif
+		break;
+	      }
+	  assert (found);
 	}
-      else if (new_opencount[i] != 0 && imap->l_type == lt_loaded)
+      else if (new_opencount[i] != 0 && imap->l_type == lt_loaded
+	       && imap->l_searchlist.r_list == NULL
+	       && imap->l_initfini != NULL)
 	{
-	  /* The object is still used.  But the object we are unloading
-	     right now is responsible for loading it and therefore we
-	     have the search list of the current object in its scope.
-	     Remove it.  */
-	  struct r_scope_elem **runp = imap->l_scope;
-
-	  while (*runp != NULL)
-	    if (*runp == &map->l_searchlist)
+	  /* The object is still used.  But the object we are
+	     unloading right now is responsible for loading it.  If
+	     the current object does not have it's own scope yet we
+	     have to create one.  This has to be done before running
+	     the finalizers.
+
+	     To do this count the number of dependencies.  */
+	  unsigned int cnt;
+	  for (cnt = 1; imap->l_initfini[cnt] != NULL; ++cnt)
+	    if (imap->l_initfini[cnt]->l_idx >= i
+		&& imap->l_initfini[cnt]->l_idx < nopencount)
+	      ++new_opencount[imap->l_initfini[cnt]->l_idx];
+	    else
+	      ++imap->l_initfini[cnt]->l_opencount;
+
+	  /* We simply reuse the l_initfini list.  */
+	  imap->l_searchlist.r_list = &imap->l_initfini[cnt + 1];
+	  imap->l_searchlist.r_nlist = cnt;
+
+	  for (cnt = 0; imap->l_scope[cnt] != NULL; ++cnt)
+	    if (imap->l_scope[cnt] = &map->l_searchlist)
 	      {
-		/* Copy all later elements.  */
-		while ((runp[0] = runp[1]) != NULL)
-		  ++runp;
+		imap->l_scope[cnt] = &imap->l_searchlist;
 		break;
 	      }
-	    else
-	      ++runp;
 	}
 
       /* Store the new l_opencount value.  */
       imap->l_opencount = new_opencount[i];
+
       /* Just a sanity check.  */
       assert (imap->l_type == lt_loaded || imap->l_opencount > 0);
     }