aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog23
-rw-r--r--elf/constload1.c4
-rw-r--r--elf/dl-deps.c8
-rw-r--r--elf/dl-libc.c24
-rw-r--r--elf/dl-load.c1
-rw-r--r--elf/dl-open.c5
-rw-r--r--elf/filter.c7
-rw-r--r--elf/loadtest.c34
-rw-r--r--elf/restest1.c8
-rw-r--r--elf/rtld.c17
-rw-r--r--sysdeps/generic/ldsodefs.h2
11 files changed, 122 insertions, 11 deletions
diff --git a/ChangeLog b/ChangeLog
index 50bd2c7..31f3463 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+2000-08-19 Ulrich Drepper <drepper@redhat.com>
+
+ * elf/Versions [ld] (GLIBC_2.2): Export _dl_check_map_versions.
+ * elf/dl-deps.c (_dl_map_object_deps): If object was dependency of
+ a dynamically loaded object remove old l_initfini list.
+ * elf/dl-libc.c (free_mem): Used as __libc_subfreeres callback to
+ remove some dynamically allocated memory blocks in the dynamic
+ loading data structures.
+ * elf/dl-load.c (add_name_to_object): Initialize dont_free to 0.
+ * elf/dl-open.c (dl_open_workder): Don't call _dl_check_all_versions.
+ Instead call _dl_check_map_versions only for the dependencies.
+ * elf/rtld.c: Avoid unneccessary initializations. Mark l_libname
+ information of initial objects as not free-able.
+ * sysdeps/generic/ldsodefs.h (struct libname_list): Add dont_free
+ element.
+
+ * elf/filter.c: Call mtrace.
+ * elf/restest1.c: Likewise. Close the objects.
+ * elf/loadtest.c: Call mtrace. Check result of dlclose. Print more
+ debug information.
+
+ * elf/constload1.c: Add comment explaining not freed memory.
+
2000-08-18 Andreas Jaeger <aj@suse.de>
* sysdeps/unix/sysv/linux/mips/bits/stat.h: Add pads to show
diff --git a/elf/constload1.c b/elf/constload1.c
index 4640b77..e0ddae9 100644
--- a/elf/constload1.c
+++ b/elf/constload1.c
@@ -18,6 +18,10 @@ main (void)
error (EXIT_FAILURE, errno, "cannot load module \"constload2.so\"");
foo = dlsym (h, "foo");
ret = foo ();
+ /* Note that the following dlclose() call cannot unload the objects.
+ Due to the introduced relocation dependency constload2.so depends
+ on constload3.so and the dependencies of constload2.so on constload3.so
+ is not visible to ld.so since it's done using dlopen(). */
if (dlclose (h) != 0)
{
puts ("failed to close");
diff --git a/elf/dl-deps.c b/elf/dl-deps.c
index 4fc2943..44838d6 100644
--- a/elf/dl-deps.c
+++ b/elf/dl-deps.c
@@ -467,6 +467,14 @@ _dl_map_object_deps (struct link_map *map,
while (runp != NULL && runp->done);
}
+ if (map->l_initfini != NULL && map->l_type == lt_loaded)
+ {
+ /* This object was previously loaded as a dependency and we have
+ a separate l_initfini list. We don't need it anymore. */
+ assert (map->l_searchlist.r_list == NULL);
+ free (map->l_initfini);
+ }
+
/* Store the search list we built in the object. It will be used for
searches in the scope of this object. */
map->l_searchlist.r_list = malloc ((2 * nlist + 1
diff --git a/elf/dl-libc.c b/elf/dl-libc.c
index 992a52e..8518909 100644
--- a/elf/dl-libc.c
+++ b/elf/dl-libc.c
@@ -120,3 +120,27 @@ __libc_dlclose (void *__map)
{
return dlerror_run (do_dlclose, __map);
}
+
+
+static void
+free_mem (void)
+{
+ struct link_map *l;
+
+ /* Remove all additional names added to the objects. */
+ for (l = _dl_loaded; l != NULL; l = l->l_next)
+ {
+ struct libname_list *lnp = l->l_libname->next;
+
+ l->l_libname->next = NULL;
+
+ while (lnp != NULL)
+ {
+ struct libname_list *old = lnp;
+ lnp = lnp->next;
+ if (! old->dont_free)
+ free (old);
+ }
+ }
+}
+text_set_element (__libc_subfreeres, free_mem);
diff --git a/elf/dl-load.c b/elf/dl-load.c
index adeb7dc..ea3c928 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -322,6 +322,7 @@ add_name_to_object (struct link_map *l, const char *name)
newname->name = memcpy (newname + 1, name, name_len);
newname->next = NULL;
+ newname->dont_free = 0;
lastp->next = newname;
}
diff --git a/elf/dl-open.c b/elf/dl-open.c
index 60a8f1a..b07ede1 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -88,6 +88,7 @@ dl_open_worker (void *a)
struct link_map *new, *l;
const char *dst;
int lazy;
+ unsigned int i;
/* Maybe we have to expand a DST. */
dst = strchr (file, '$');
@@ -163,7 +164,9 @@ dl_open_worker (void *a)
_dl_map_object_deps (new, NULL, 0, 0);
/* So far, so good. Now check the versions. */
- (void) _dl_check_all_versions (new, 0, 0);
+ for (i = 0; i < new->l_searchlist.r_nlist; ++i)
+ if (new->l_searchlist.r_list[i]->l_versions == NULL)
+ (void) _dl_check_map_versions (new->l_searchlist.r_list[i], 0, 0);
#ifdef SCOPE_DEBUG
show_scope (new);
diff --git a/elf/filter.c b/elf/filter.c
index 76bc91a..46aa15b 100644
--- a/elf/filter.c
+++ b/elf/filter.c
@@ -1,3 +1,4 @@
+#include <mcheck.h>
#include <stdio.h>
#include <string.h>
@@ -6,7 +7,11 @@ extern const char *foo (void);
int
main (void)
{
- const char *s = foo ();
+ const char *s;
+
+ mtrace ();
+
+ s = foo ();
printf ("called `foo' from `%s'\n", s);
diff --git a/elf/loadtest.c b/elf/loadtest.c
index 5b9e116..80f9960 100644
--- a/elf/loadtest.c
+++ b/elf/loadtest.c
@@ -2,6 +2,7 @@
#include <dlfcn.h>
#include <errno.h>
#include <error.h>
+#include <mcheck.h>
#include <stdio.h>
#include <stdlib.h>
@@ -66,10 +67,16 @@ static const struct
#define NTESTS (sizeof (tests) / sizeof (tests[0]))
+#include <include/link.h>
+
+
int
main (void)
{
int count = TEST_ROUNDS;
+ int result = 0;
+
+ mtrace ();
/* Just a seed. */
srandom (TEST_ROUNDS);
@@ -102,23 +109,38 @@ main (void)
fct (10);
- printf ("successfully loaded `%s'\n", testobjs[index].name);
+ printf ("successfully loaded `%s', handle %p\n",
+ testobjs[index].name, testobjs[index].handle);
}
else
{
- dlclose (testobjs[index].handle);
- testobjs[index].handle = NULL;
+ if (dlclose (testobjs[index].handle) != 0)
+ {
+ printf ("failed to close %s\n", testobjs[index].name);
+ result = 1;
+ }
+ else
+ printf ("successfully unloaded `%s', handle %p\n",
+ testobjs[index].name, testobjs[index].handle);
- printf ("successfully unloaded `%s'\n", testobjs[index].name);
+ testobjs[index].handle = NULL;
}
}
/* Unload all loaded modules. */
for (count = 0; count < NOBJS; ++count)
if (testobjs[count].handle != NULL)
- dlclose (testobjs[count].handle);
+{ printf ("\nclose: %s: l_initfini = %p, l_versions = %p\n",
+ testobjs[count].name,
+ ((struct link_map*)testobjs[count].handle)->l_initfini,
+ ((struct link_map*)testobjs[count].handle)->l_versions);
+ if (dlclose (testobjs[count].handle) != 0)
+ {
+ printf ("failed to close %s\n", testobjs[count].name);
+ result = 1;
+} }
- return 0;
+ return result;
}
diff --git a/elf/restest1.c b/elf/restest1.c
index e4eca55..2b649c0 100644
--- a/elf/restest1.c
+++ b/elf/restest1.c
@@ -1,5 +1,6 @@
#include <dlfcn.h>
#include <error.h>
+#include <mcheck.h>
#include <stdio.h>
#include <stdlib.h>
@@ -13,6 +14,8 @@ main (void)
int res1;
int res2;
+ mtrace ();
+
h1 = dlopen ("testobj1.so", RTLD_LAZY);
if (h1 == NULL)
error (EXIT_FAILURE, 0, "while loading `%s': %s", "testobj1.so",
@@ -37,6 +40,11 @@ main (void)
res2 = fp2 (10);
printf ("fp1(10) = %d\nfp2(10) = %d\n", res1, res2);
+ if (dlclose (h1) != 0)
+ error (EXIT_FAILURE, 0, "cannot close testobj1.so: %s\n", dlerror ());
+ if (dlclose (h2) != 0)
+ error (EXIT_FAILURE, 0, "cannot close testobj1_1.so: %s\n", dlerror ());
+
return res1 != 42 || res2 != 72;
}
diff --git a/elf/rtld.c b/elf/rtld.c
index 9a444fc..41cf5c3 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -590,7 +590,7 @@ of this helper program; chances are you did not intend to run this program.\n\
the shared object is already loaded. */
_dl_rtld_libname.name = ((const char *) _dl_loaded->l_addr
+ ph->p_vaddr);
- _dl_rtld_libname.next = NULL;
+ /* _dl_rtld_libname.next = NULL; Already zero. */
_dl_rtld_map.l_libname = &_dl_rtld_libname;
/* Ordinarilly, we would get additional names for the loader from
@@ -604,7 +604,7 @@ of this helper program; chances are you did not intend to run this program.\n\
if (p)
{
_dl_rtld_libname2.name = p+1;
- _dl_rtld_libname2.next = NULL;
+ /* _dl_rtld_libname2.next = NULL; Already zero. */
_dl_rtld_libname.next = &_dl_rtld_libname2;
}
}
@@ -626,7 +626,7 @@ of this helper program; chances are you did not intend to run this program.\n\
/* We were invoked directly, so the program might not have a
PT_INTERP. */
_dl_rtld_libname.name = _dl_rtld_map.l_name;
- _dl_rtld_libname.next = NULL;
+ /* _dl_rtld_libname.next = NULL; Alread zero. */
_dl_rtld_map.l_libname = &_dl_rtld_libname;
}
else
@@ -1059,6 +1059,17 @@ of this helper program; chances are you did not intend to run this program.\n\
HP_TIMING_NOW (start);
do
{
+ /* While we are at it, help the memory handling a bit. We have to
+ mark some data structures as allocated with the fake malloc()
+ implementation in ld.so. */
+ struct libname_list *lnp = l->l_libname->next;
+
+ while (__builtin_expect (lnp != NULL, 0))
+ {
+ lnp->dont_free = 1;
+ lnp = lnp->next;
+ }
+
if (l != &_dl_rtld_map)
_dl_relocate_object (l, l->l_scope, _dl_lazy, consider_profiling);
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index f7f77c2..ceb2b87 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -115,6 +115,8 @@ struct libname_list
{
const char *name; /* Name requested (before search). */
struct libname_list *next; /* Link to next name for this object. */
+ int dont_free; /* Flag whether this element should be freed
+ if the object is not entirely unloaded. */
};