From 752a2a50d4574791b2861653d4352c6b6e4b97ff Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Sat, 19 Aug 2000 07:17:09 +0000 Subject: [PATCH] Update. 2000-08-19 Ulrich Drepper * 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. --- ChangeLog | 23 +++++++++++++++++++++++ elf/constload1.c | 4 ++++ elf/dl-deps.c | 8 ++++++++ elf/dl-libc.c | 24 ++++++++++++++++++++++++ elf/dl-load.c | 1 + elf/dl-open.c | 5 ++++- elf/filter.c | 7 ++++++- elf/loadtest.c | 34 ++++++++++++++++++++++++++++------ elf/restest1.c | 8 ++++++++ elf/rtld.c | 17 ++++++++++++++--- sysdeps/generic/ldsodefs.h | 2 ++ 11 files changed, 122 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index 50bd2c7150..31f346315b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2000-08-19 Ulrich Drepper + + * 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 * sysdeps/unix/sysv/linux/mips/bits/stat.h: Add pads to show diff --git a/elf/constload1.c b/elf/constload1.c index 4640b774cb..e0ddae9acc 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 4fc2943c14..44838d6208 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 992a52e699..8518909b25 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 adeb7dced2..ea3c928169 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 60a8f1ad5b..b07ede15fc 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 76bc91adc5..46aa15ba16 100644 --- a/elf/filter.c +++ b/elf/filter.c @@ -1,3 +1,4 @@ +#include #include #include @@ -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 5b9e116987..80f99607ec 100644 --- a/elf/loadtest.c +++ b/elf/loadtest.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -66,10 +67,16 @@ static const struct #define NTESTS (sizeof (tests) / sizeof (tests[0])) +#include + + 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 e4eca557c5..2b649c00d2 100644 --- a/elf/restest1.c +++ b/elf/restest1.c @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -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 9a444fcfd9..41cf5c36d5 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 f7f77c2c1a..ceb2b87694 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. */ };