aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog16
-rw-r--r--elf/dl-close.c56
-rw-r--r--elf/dl-deps.c21
-rw-r--r--elf/dl-load.c15
-rw-r--r--elf/dl-lookup.c6
-rw-r--r--elf/dl-open.c11
-rw-r--r--elf/loadtest.c8
-rw-r--r--elf/rtld.c16
8 files changed, 91 insertions, 58 deletions
diff --git a/ChangeLog b/ChangeLog
index 79c3c0d..4c0a905 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2000-10-24 Ulrich Drepper <drepper@redhat.com>
+
+ Complete revamp of the reference counter handling.
+ * include/link.h (struct link_map): Add l_idx field.
+ * elf/dl-close.c: Handle decrementing of reference counters more
+ correctly. If necessary decrement reference counters of dependencies
+ of dependencies.
+ * elf/dl-lookup.c (add_dependency): Only increment reference counter
+ of the object itself and not also its dependencies.
+ * elf/dl-open.c: Increment reference counters here.
+ * elf/dl-deps.c: Remove reference counter handling here.
+ * elf/dl-load.c: Likewise.
+ * elf/rtld.c: Adjust for _dl_map_deps not handling reference counters.
+
+ * elf/loadtest.c: Print loaded objects at the beginning.
+
2000-10-24 Andreas Jaeger <aj@suse.de>
* sysdeps/mips/dl-machine.h: Partly revert patch from 2000-10-18.
diff --git a/elf/dl-close.c b/elf/dl-close.c
index 4c861a1..2130540 100644
--- a/elf/dl-close.c
+++ b/elf/dl-close.c
@@ -49,6 +49,7 @@ _dl_close (void *_map)
unsigned int nsearchlist;
unsigned int nrellist;
unsigned int i;
+ unsigned int *new_opencount;
/* First see whether we can remove the object at all. */
if (map->l_flags_1 & DF_1_NODELETE)
@@ -61,9 +62,6 @@ _dl_close (void *_map)
/* Acquire the lock. */
__libc_lock_lock (_dl_load_lock);
- list = map->l_searchlist.r_list;
- nsearchlist = map->l_searchlist.r_nlist;
-
/* Decrement the reference count. */
if (map->l_opencount > 1 || map->l_type != lt_loaded)
{
@@ -81,14 +79,46 @@ _dl_close (void *_map)
"\n", NULL);
}
- for (i = 0; i < nsearchlist; ++i)
- if (! (list[i]->l_flags_1 & DF_1_NODELETE))
- --list[i]->l_opencount;
+ /* One decrement the object itself, not the dependencies. */
+ --map->l_opencount;
__libc_lock_unlock (_dl_load_lock);
return;
}
+ list = map->l_searchlist.r_list;
+ nsearchlist = map->l_searchlist.r_nlist;
+
+ /* Compute the new l_opencount values. */
+ new_opencount = (unsigned int *) alloca (nsearchlist
+ * sizeof (unsigned int));
+ for (i = 0; i < nsearchlist; ++i)
+ {
+ list[i]->l_idx = i;
+ new_opencount[i] = list[i]->l_opencount;
+ }
+ --new_opencount[0];
+ for (i = 1; i < nsearchlist; ++i)
+ if (! (list[i]->l_flags_1 & DF_1_NODELETE)
+ /* Decrement counter. */
+ && --new_opencount[i] == 0
+ /* Test whether this object was also loaded directly. */
+ && list[i]->l_searchlist.r_list != NULL)
+ {
+ /* In this case we have the decrement all the dependencies of
+ this object. They are all in MAP's dependency list. */
+ unsigned int j;
+ struct link_map **dep_list = list[i]->l_searchlist.r_list;
+
+ for (j = 1; j < list[i]->l_searchlist.r_nlist; ++j)
+ if (! (dep_list[j]->l_flags_1 & DF_1_NODELETE))
+ {
+ assert (dep_list[j]->l_idx < nsearchlist);
+ --new_opencount[dep_list[j]->l_idx];
+ }
+ }
+ assert (new_opencount[0] == 0);
+
rellist = map->l_reldeps;
nrellist = map->l_reldepsact;
@@ -96,7 +126,7 @@ _dl_close (void *_map)
for (i = 0; i < nsearchlist; ++i)
{
struct link_map *imap = map->l_initfini[i];
- if (imap->l_opencount == 1 && imap->l_type == lt_loaded
+ if (new_opencount[i] == 0 && imap->l_type == lt_loaded
&& (imap->l_info[DT_FINI] || imap->l_info[DT_FINI_ARRAY])
&& ! (imap->l_flags_1 & DF_1_NODELETE)
/* Skip any half-cooked objects that were never initialized. */
@@ -126,19 +156,17 @@ _dl_close (void *_map)
(*(void (*) (void)) ((void *) imap->l_addr
+ imap->l_info[DT_FINI]->d_un.d_ptr)) ();
}
+
+ /* Store the new l_opencount value. */
+ imap->l_opencount = new_opencount[i];
+ /* Just a sanity check. */
+ assert (imap->l_type == lt_loaded || imap->l_opencount > 0);
}
/* Notify the debugger we are about to remove some loaded objects. */
_r_debug.r_state = RT_DELETE;
_dl_debug_state ();
- /* The search list contains a counted reference to each object it
- points to, the 0th elt being MAP itself. Decrement the reference
- counts on all the objects MAP depends on. */
- for (i = 0; i < nsearchlist; ++i)
- if (! (list[i]->l_flags_1 & DF_1_NODELETE))
- --list[i]->l_opencount;
-
/* Check each element of the search list to see if all references to
it are gone. */
for (i = 0; i < nsearchlist; ++i)
diff --git a/elf/dl-deps.c b/elf/dl-deps.c
index c458292..c3feb98 100644
--- a/elf/dl-deps.c
+++ b/elf/dl-deps.c
@@ -243,18 +243,7 @@ _dl_map_object_deps (struct link_map *map,
dtail = newp;
++nduplist;
- if (dep->l_reserved)
- {
- /* This object is already in the search list we are
- building. Don't add a duplicate pointer.
- Release the reference just added by
- _dl_map_object. */
- if (dep->l_initfini != NULL)
- for (i = 1; dep->l_initfini[i] != NULL; ++i)
- --dep->l_initfini[i]->l_opencount;
- --dep->l_opencount;
- }
- else
+ if (! dep->l_reserved)
{
/* Append DEP to the unique list. */
newp->done = 0;
@@ -363,13 +352,7 @@ _dl_map_object_deps (struct link_map *map,
/* This object is already in the search list we
are building. Don't add a duplicate pointer.
- Release the reference just added by
- _dl_map_object. */
- if (args.aux->l_initfini != NULL)
- for (i = 1; args.aux->l_initfini[i] != NULL; ++i)
- --args.aux->l_initfini[i]->l_opencount;
- --args.aux->l_opencount;
-
+ Just added by _dl_map_object. */
for (late = newp; late->unique; late = late->unique)
if (late->unique->map == args.aux)
break;
diff --git a/elf/dl-load.c b/elf/dl-load.c
index bb3a2e3..80fbf65 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -785,10 +785,6 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
free (realname);
add_name_to_object (l, name);
- if (l->l_initfini != NULL)
- for (i = 1; l->l_initfini[i] != NULL; ++i)
- ++l->l_initfini[i]->l_opencount;
- ++l->l_opencount;
return l;
}
@@ -821,7 +817,6 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
l = _dl_new_object (realname, name, l_type, loader);
if (__builtin_expect (! l, 0))
LOSE (ENOMEM, N_("cannot create shared object descriptor"));
- l->l_opencount = 1;
/* Extract the remaining details we need from the ELF header
and then read in the program header table. */
@@ -1467,7 +1462,9 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
/* If the requested name matches the soname of a loaded object,
use that object. Elide this check for names that have not
yet been opened. */
- if (l->l_opencount <= 0)
+ /* XXX Is this test still correct after the reference counter
+ handling rewrite? */
+ if (l->l_opencount == 0)
continue;
if (!_dl_name_match_p (name, l))
{
@@ -1487,11 +1484,7 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
l->l_soname_added = 1;
}
- /* We have a match -- bump the reference count and return it. */
- if (l->l_initfini != NULL)
- for (i = 1; l->l_initfini[i] != NULL; ++i)
- ++l->l_initfini[i]->l_opencount;
- ++l->l_opencount;
+ /* We have a match. */
return l;
}
diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
index d947681..1284e2b 100644
--- a/elf/dl-lookup.c
+++ b/elf/dl-lookup.c
@@ -160,11 +160,7 @@ add_dependency (struct link_map *undef_map, struct link_map *map)
if (__builtin_expect (act < undef_map->l_reldepsmax, 1))
undef_map->l_reldeps[undef_map->l_reldepsact++] = map;
- /* And increment the counter in the referenced object
- and its dependencies. */
- if (map->l_initfini != NULL)
- for (j = 1; map->l_initfini[j] != NULL; ++j)
- ++map->l_initfini[j]->l_opencount;
+ /* And increment the counter in the referenced object. */
++map->l_opencount;
/* Display information if we are debugging. */
diff --git a/elf/dl-open.c b/elf/dl-open.c
index 5c078d9..b278e20 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -238,7 +238,8 @@ dl_open_worker (void *a)
return;
}
- if (new->l_searchlist.r_list)
+ /* It was already open. */
+ if (new->l_searchlist.r_list != NULL)
{
/* Let the user know about the opencount. */
if (__builtin_expect (_dl_debug_files, 0))
@@ -259,13 +260,19 @@ dl_open_worker (void *a)
if ((mode & RTLD_GLOBAL) && new->l_global == 0)
(void) add_to_global (new);
- /* It was already open. */
+ /* Increment just the reference counter of the object. */
+ ++new->l_opencount;
+
return;
}
/* Load that object's dependencies. */
_dl_map_object_deps (new, NULL, 0, 0);
+ /* Increment the open count for all dependencies. */
+ for (i = 0; i < new->l_searchlist.r_nlist; ++i)
+ ++new->l_searchlist.r_list[i]->l_opencount;
+
/* So far, so good. Now check the versions. */
for (i = 0; i < new->l_searchlist.r_nlist; ++i)
if (new->l_searchlist.r_list[i]->l_versions == NULL)
diff --git a/elf/loadtest.c b/elf/loadtest.c
index 4a3c4c0..25b2700 100644
--- a/elf/loadtest.c
+++ b/elf/loadtest.c
@@ -83,17 +83,23 @@ main (int argc, char *argv[])
int debug = argc > 1 && argv[1][0] != '\0';
int count = TEST_ROUNDS;
int result = 0;
+ struct link_map *map;
mtrace ();
/* Just a seed. */
srandom (TEST_ROUNDS);
+ if (debug)
+ {
+ puts ("in the beginning");
+ OUT;
+ }
+
while (count--)
{
int nr = random () % NTESTS;
int index = tests[nr].index;
- struct link_map *map;
printf ("%4d: %4d: ", count + 1, nr);
fflush (stdout);
diff --git a/elf/rtld.c b/elf/rtld.c
index ea5d7b5..c44506a 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -550,7 +550,6 @@ of this helper program; chances are you did not intend to run this program.\n\
_dl_loaded->l_phdr = phdr;
_dl_loaded->l_phnum = phent;
_dl_loaded->l_entry = *user_entry;
- _dl_loaded->l_opencount = 1;
/* At this point we are in a bit of trouble. We would have to
fill in the values for l_dev and l_ino. But in general we
@@ -707,7 +706,7 @@ of this helper program; chances are you did not intend to run this program.\n\
{
struct link_map *new_map = _dl_map_object (_dl_loaded, p, 1,
lt_library, 0, 0);
- if (new_map->l_opencount == 1)
+ if (++new_map->l_opencount == 1)
/* It is no duplicate. */
++npreloads;
}
@@ -775,7 +774,7 @@ of this helper program; chances are you did not intend to run this program.\n\
{
struct link_map *new_map = _dl_map_object (_dl_loaded, p, 1,
lt_library, 0, 0);
- if (new_map->l_opencount == 1)
+ if (++new_map->l_opencount == 1)
/* It is no duplicate. */
++npreloads;
}
@@ -786,7 +785,7 @@ of this helper program; chances are you did not intend to run this program.\n\
char *p = strndupa (problem, file_size - (problem - file));
struct link_map *new_map = _dl_map_object (_dl_loaded, p, 1,
lt_library, 0, 0);
- if (new_map->l_opencount == 1)
+ if (++new_map->l_opencount == 1)
/* It is no duplicate. */
++npreloads;
}
@@ -823,9 +822,14 @@ of this helper program; chances are you did not intend to run this program.\n\
HP_TIMING_DIFF (diff, start, stop);
HP_TIMING_ACCUM_NT (load_time, diff);
- /* Mark all objects as being in the global scope. */
+ /* Mark all objects as being in the global scope and set the open
+ counter. */
for (i = _dl_loaded->l_searchlist.r_nlist; i > 0; )
- _dl_loaded->l_searchlist.r_list[--i]->l_global = 1;
+ {
+ --i;
+ _dl_loaded->l_searchlist.r_list[i]->l_global = 1;
+ ++_dl_loaded->l_searchlist.r_list[i]->l_opencount;
+ }
#ifndef MAP_ANON
/* We are done mapping things, so close the zero-fill descriptor. */