mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-09 23:00:07 +00:00
Update.
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.
This commit is contained in:
parent
003715fa0d
commit
752a2a50d4
23
ChangeLog
23
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>
|
2000-08-18 Andreas Jaeger <aj@suse.de>
|
||||||
|
|
||||||
* sysdeps/unix/sysv/linux/mips/bits/stat.h: Add pads to show
|
* sysdeps/unix/sysv/linux/mips/bits/stat.h: Add pads to show
|
||||||
|
@ -18,6 +18,10 @@ main (void)
|
|||||||
error (EXIT_FAILURE, errno, "cannot load module \"constload2.so\"");
|
error (EXIT_FAILURE, errno, "cannot load module \"constload2.so\"");
|
||||||
foo = dlsym (h, "foo");
|
foo = dlsym (h, "foo");
|
||||||
ret = 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)
|
if (dlclose (h) != 0)
|
||||||
{
|
{
|
||||||
puts ("failed to close");
|
puts ("failed to close");
|
||||||
|
@ -467,6 +467,14 @@ _dl_map_object_deps (struct link_map *map,
|
|||||||
while (runp != NULL && runp->done);
|
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
|
/* Store the search list we built in the object. It will be used for
|
||||||
searches in the scope of this object. */
|
searches in the scope of this object. */
|
||||||
map->l_searchlist.r_list = malloc ((2 * nlist + 1
|
map->l_searchlist.r_list = malloc ((2 * nlist + 1
|
||||||
|
@ -120,3 +120,27 @@ __libc_dlclose (void *__map)
|
|||||||
{
|
{
|
||||||
return dlerror_run (do_dlclose, __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);
|
||||||
|
@ -322,6 +322,7 @@ add_name_to_object (struct link_map *l, const char *name)
|
|||||||
|
|
||||||
newname->name = memcpy (newname + 1, name, name_len);
|
newname->name = memcpy (newname + 1, name, name_len);
|
||||||
newname->next = NULL;
|
newname->next = NULL;
|
||||||
|
newname->dont_free = 0;
|
||||||
lastp->next = newname;
|
lastp->next = newname;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,6 +88,7 @@ dl_open_worker (void *a)
|
|||||||
struct link_map *new, *l;
|
struct link_map *new, *l;
|
||||||
const char *dst;
|
const char *dst;
|
||||||
int lazy;
|
int lazy;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
/* Maybe we have to expand a DST. */
|
/* Maybe we have to expand a DST. */
|
||||||
dst = strchr (file, '$');
|
dst = strchr (file, '$');
|
||||||
@ -163,7 +164,9 @@ dl_open_worker (void *a)
|
|||||||
_dl_map_object_deps (new, NULL, 0, 0);
|
_dl_map_object_deps (new, NULL, 0, 0);
|
||||||
|
|
||||||
/* So far, so good. Now check the versions. */
|
/* 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
|
#ifdef SCOPE_DEBUG
|
||||||
show_scope (new);
|
show_scope (new);
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include <mcheck.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@ -6,7 +7,11 @@ extern const char *foo (void);
|
|||||||
int
|
int
|
||||||
main (void)
|
main (void)
|
||||||
{
|
{
|
||||||
const char *s = foo ();
|
const char *s;
|
||||||
|
|
||||||
|
mtrace ();
|
||||||
|
|
||||||
|
s = foo ();
|
||||||
|
|
||||||
printf ("called `foo' from `%s'\n", s);
|
printf ("called `foo' from `%s'\n", s);
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <error.h>
|
#include <error.h>
|
||||||
|
#include <mcheck.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
@ -66,10 +67,16 @@ static const struct
|
|||||||
#define NTESTS (sizeof (tests) / sizeof (tests[0]))
|
#define NTESTS (sizeof (tests) / sizeof (tests[0]))
|
||||||
|
|
||||||
|
|
||||||
|
#include <include/link.h>
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main (void)
|
main (void)
|
||||||
{
|
{
|
||||||
int count = TEST_ROUNDS;
|
int count = TEST_ROUNDS;
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
mtrace ();
|
||||||
|
|
||||||
/* Just a seed. */
|
/* Just a seed. */
|
||||||
srandom (TEST_ROUNDS);
|
srandom (TEST_ROUNDS);
|
||||||
@ -102,23 +109,38 @@ main (void)
|
|||||||
|
|
||||||
fct (10);
|
fct (10);
|
||||||
|
|
||||||
printf ("successfully loaded `%s'\n", testobjs[index].name);
|
printf ("successfully loaded `%s', handle %p\n",
|
||||||
|
testobjs[index].name, testobjs[index].handle);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dlclose (testobjs[index].handle);
|
if (dlclose (testobjs[index].handle) != 0)
|
||||||
testobjs[index].handle = NULL;
|
{
|
||||||
|
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. */
|
/* Unload all loaded modules. */
|
||||||
for (count = 0; count < NOBJS; ++count)
|
for (count = 0; count < NOBJS; ++count)
|
||||||
if (testobjs[count].handle != NULL)
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <error.h>
|
#include <error.h>
|
||||||
|
#include <mcheck.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
@ -13,6 +14,8 @@ main (void)
|
|||||||
int res1;
|
int res1;
|
||||||
int res2;
|
int res2;
|
||||||
|
|
||||||
|
mtrace ();
|
||||||
|
|
||||||
h1 = dlopen ("testobj1.so", RTLD_LAZY);
|
h1 = dlopen ("testobj1.so", RTLD_LAZY);
|
||||||
if (h1 == NULL)
|
if (h1 == NULL)
|
||||||
error (EXIT_FAILURE, 0, "while loading `%s': %s", "testobj1.so",
|
error (EXIT_FAILURE, 0, "while loading `%s': %s", "testobj1.so",
|
||||||
@ -37,6 +40,11 @@ main (void)
|
|||||||
res2 = fp2 (10);
|
res2 = fp2 (10);
|
||||||
printf ("fp1(10) = %d\nfp2(10) = %d\n", res1, res2);
|
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;
|
return res1 != 42 || res2 != 72;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
17
elf/rtld.c
17
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. */
|
the shared object is already loaded. */
|
||||||
_dl_rtld_libname.name = ((const char *) _dl_loaded->l_addr
|
_dl_rtld_libname.name = ((const char *) _dl_loaded->l_addr
|
||||||
+ ph->p_vaddr);
|
+ ph->p_vaddr);
|
||||||
_dl_rtld_libname.next = NULL;
|
/* _dl_rtld_libname.next = NULL; Already zero. */
|
||||||
_dl_rtld_map.l_libname = &_dl_rtld_libname;
|
_dl_rtld_map.l_libname = &_dl_rtld_libname;
|
||||||
|
|
||||||
/* Ordinarilly, we would get additional names for the loader from
|
/* 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)
|
if (p)
|
||||||
{
|
{
|
||||||
_dl_rtld_libname2.name = p+1;
|
_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;
|
_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
|
/* We were invoked directly, so the program might not have a
|
||||||
PT_INTERP. */
|
PT_INTERP. */
|
||||||
_dl_rtld_libname.name = _dl_rtld_map.l_name;
|
_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;
|
_dl_rtld_map.l_libname = &_dl_rtld_libname;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1059,6 +1059,17 @@ of this helper program; chances are you did not intend to run this program.\n\
|
|||||||
HP_TIMING_NOW (start);
|
HP_TIMING_NOW (start);
|
||||||
do
|
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)
|
if (l != &_dl_rtld_map)
|
||||||
_dl_relocate_object (l, l->l_scope, _dl_lazy, consider_profiling);
|
_dl_relocate_object (l, l->l_scope, _dl_lazy, consider_profiling);
|
||||||
|
|
||||||
|
@ -115,6 +115,8 @@ struct libname_list
|
|||||||
{
|
{
|
||||||
const char *name; /* Name requested (before search). */
|
const char *name; /* Name requested (before search). */
|
||||||
struct libname_list *next; /* Link to next name for this object. */
|
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. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user