summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog19
-rw-r--r--elf/Versions2
-rw-r--r--elf/dl-close.c16
-rw-r--r--elf/dl-open.c9
-rw-r--r--elf/dl-support.c8
-rw-r--r--elf/ldsodefs.h6
-rw-r--r--elf/rtld.c6
-rw-r--r--malloc/mtrace.c19
8 files changed, 74 insertions, 11 deletions
diff --git a/ChangeLog b/ChangeLog
index 097fe634cf..5d4adbeeaa 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+1998-10-07  Ulrich Drepper  <drepper@cygnus.com>
+
+	* elf/dl-open.c (_dl_global_scope_alloc): Make global.
+	(dl_open_worker): Use realloc, not malloc to resize array.
+	* elf/rtld.c (_dl_initial_searchlist): New variable.
+	(_dl_main): Copy content of _dl_main_searchlist to
+	_dl_initial_searchlist.
+	* elf/ldsodefs.h: Add declarations for _dl_initial_searchlist and
+	_dl_global_scope_alloc.
+	* elf/Versions [libc, GLIBC_2.1]: Add _dl_initial_searchlist.
+	* elf/dl-close.c (_dl_close): When removing object with global
+	scope remove allocated searchlist if no dynamically loaded object
+	is on it anymore.
+	* elf/dl-support.c (_dl_initial_searchlist): Renamed from fake_scope.
+	(_dl_global_scope, _dl_main_searchlist): Use _dl_initial_searchlist.
+
+	* malloc/mtrace.c (tr_where): Don't print space in location string,
+	print it afterwards.  Print better symbol name information.
+
 1998-10-06  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
 
 	* manual/filesys.texi (Setting Permissions): Fix example for
diff --git a/elf/Versions b/elf/Versions
index 1cfb5ccf2c..5e10adf1fb 100644
--- a/elf/Versions
+++ b/elf/Versions
@@ -19,7 +19,7 @@ libc {
   GLIBC_2.1 {
     # global variables
     _dl_profile; _dl_profile_map; _dl_profile_output; _dl_start_profile;
-    _dl_loaded; _dl_main_searchlist; _dl_fpu_control;
+    _dl_loaded; _dl_main_searchlist; _dl_fpu_control; _dl_initial_searchlist;
 
     # functions used in other libraries
     _dl_mcount; _dl_mcount_wrapper; _dl_mcount_wrapper_check; _dl_unload_cache;
diff --git a/elf/dl-close.c b/elf/dl-close.c
index 3618b13da7..0fbeecc4cd 100644
--- a/elf/dl-close.c
+++ b/elf/dl-close.c
@@ -115,6 +115,22 @@ _dl_close (struct link_map *map)
 		  ++cnt;
 		}
 	      --_dl_main_searchlist->r_nlist;
+	      if (_dl_main_searchlist->r_nlist
+		  == _dl_initial_searchlist.r_nlist)
+		{
+		  /* All object dynamically loaded by the program are
+		     unloaded.  Free the memory allocated for the global
+		     scope variable.  */
+		  struct link_map **old = _dl_main_searchlist->r_list;
+
+		  /* Put the old map in.  */
+		  _dl_main_searchlist->r_list = _dl_initial_searchlist.r_list;
+		  /* Signal that the old map is used.  */
+		  _dl_global_scope_alloc = 0;
+
+		  /* Now free the old map.  */
+		  free (old);
+		}
 	    }
 
 	  /* We can unmap all the maps at once.  We determined the
diff --git a/elf/dl-open.c b/elf/dl-open.c
index e5509dffd4..83e6424c84 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -42,7 +42,10 @@ extern char **__libc_argv;
 
 extern char **__environ;
 
-static size_t _dl_global_scope_alloc;
+/* This is zero at program start to signal that the global scope map is
+   allocated by rtld.  Later it keeps the size of the map.  It might be
+   reset if in _dl_close if the last global object is removed.  */
+size_t _dl_global_scope_alloc;
 
 
 /* During the program run we must not modify the global data of
@@ -167,7 +170,9 @@ dl_open_worker (void *a)
 	  /* We have to extend the existing array of link maps in the
 	     main map.  */
 	  new_global = (struct link_map **)
-	    malloc ((_dl_global_scope_alloc + 8) * sizeof (struct link_map *));
+	    realloc (_dl_main_searchlist->r_list,
+		     ((_dl_global_scope_alloc + 8)
+		      * sizeof (struct link_map *)));
 	  if (new_global == NULL)
 	    goto nomem;
 
diff --git a/elf/dl-support.c b/elf/dl-support.c
index 1126d46771..450c9c90df 100644
--- a/elf/dl-support.c
+++ b/elf/dl-support.c
@@ -66,15 +66,15 @@ const char *_dl_origin_path;
 struct link_map *_dl_loaded;
 
 /* Fake scope.  In dynamically linked binaries this is the scope of the
-   main application but here we don't have  something like this.  So
+   main application but here we don't have something like this.  So
    create a fake scope containing nothing.  */
-static struct r_scope_elem fake_scope;
+struct r_scope_elem _dl_initial_searchlist;
 /* Variable which can be used in lookup to process the global scope.  */
-struct r_scope_elem *_dl_global_scope[2] = { &fake_scope, NULL };
+struct r_scope_elem *_dl_global_scope[2] = { &_dl_initial_searchlist, NULL };
 /* This is a global pointer to this structure which is public.  It is
    used by dlopen/dlclose to add and remove objects from what is regarded
    to be the global scope.  */
-struct r_scope_elem *_dl_main_searchlist = &fake_scope;
+struct r_scope_elem *_dl_main_searchlist = &_dl_initial_searchlist;
 
 
 static void non_dynamic_init (void) __attribute__ ((unused));
diff --git a/elf/ldsodefs.h b/elf/ldsodefs.h
index 946cf34439..7d0bdda980 100644
--- a/elf/ldsodefs.h
+++ b/elf/ldsodefs.h
@@ -331,6 +331,12 @@ extern struct link_map *_dl_loaded;
 extern struct r_scope_elem *_dl_global_scope[2];
 /* Direct pointer to the searchlist of the main object.  */
 extern struct r_scope_elem *_dl_main_searchlist;
+/* Copy of the content of `_dl_main_searchlist'.  */
+extern struct r_scope_elem _dl_initial_searchlist;
+/* This is zero at program start to signal that the global scope map is
+   allocated by rtld.  Later it keeps the size of the map.  It might be
+   reset if in _dl_close if the last global object is removed.  */
+extern size_t _dl_global_scope_alloc;
 
 /* Allocate a `struct link_map' for a new object being loaded,
    and enter it into the _dl_main_map list.  */
diff --git a/elf/rtld.c b/elf/rtld.c
index 4d67176d03..33002f8cef 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -95,6 +95,8 @@ const char *_dl_origin_path;
 struct link_map *_dl_loaded;
 /* Pointer to the l_searchlist element of the link map of the main object.  */
 struct r_scope_elem *_dl_main_searchlist;
+/* Copy of the content of `_dl_main_searchlist'.  */
+struct r_scope_elem _dl_initial_searchlist;
 /* Array which is used when looking up in the global scope.  */
 struct r_scope_elem *_dl_global_scope[2];
 
@@ -909,6 +911,10 @@ of this helper program; chances are you did not intend to run this program.\n\
   _dl_main_searchlist = &_dl_loaded->l_searchlist;
   _dl_global_scope[0] = &_dl_loaded->l_searchlist;
 
+  /* Safe the information about the original global scope list since
+     we need it in the memory handling later.  */
+  _dl_initial_searchlist = *_dl_main_searchlist;
+
   {
     /* Initialize _r_debug.  */
     struct r_debug *r = _dl_debug_initialize (_dl_rtld_map.l_addr);
diff --git a/malloc/mtrace.c b/malloc/mtrace.c
index 86f89540d4..02da0ae764 100644
--- a/malloc/mtrace.c
+++ b/malloc/mtrace.c
@@ -97,11 +97,22 @@ tr_where (caller)
       Dl_info info;
       if (_dl_addr (caller, &info))
 	{
-	  fprintf (mallstream, "@ %s%s%s%s%s[%p]",
+	  char *buf = (char *) "";
+	  if (info.dli_sname && info.dli_sname[0])
+	    {
+	      size_t len = strlen (info.dli_sname) + 22;
+	      buf = alloca (len);
+	      if (caller >= (const __ptr_t) info.dli_saddr)
+		snprintf (buf, len, "(%s+0x%x)", info.dli_sname,
+			  caller - (const __ptr_t) info.dli_saddr);
+	      else
+		snprintf (buf, len, "(%s-0x%x)", info.dli_sname,
+			  (const __ptr_t) info.dli_saddr - caller);
+	    }
+
+	  fprintf (mallstream, "@ %s%s%s[%p] ",
 		   info.dli_fname ?: "", info.dli_fname ? ":" : "",
-		   info.dli_sname ? "(" : "",
-		   info.dli_sname ?: "", info.dli_sname ? ") " : " ",
-		   caller);
+		   buf, caller);
 	}
       else
 #endif