diff options
Diffstat (limited to 'elf')
-rw-r--r-- | elf/constload1.c | 4 | ||||
-rw-r--r-- | elf/dl-deps.c | 8 | ||||
-rw-r--r-- | elf/dl-libc.c | 24 | ||||
-rw-r--r-- | elf/dl-load.c | 1 | ||||
-rw-r--r-- | elf/dl-open.c | 5 | ||||
-rw-r--r-- | elf/filter.c | 7 | ||||
-rw-r--r-- | elf/loadtest.c | 34 | ||||
-rw-r--r-- | elf/restest1.c | 8 | ||||
-rw-r--r-- | elf/rtld.c | 17 |
9 files changed, 97 insertions, 11 deletions
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; } @@ -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); |