PATCH: Treat RTLD_LOCAL like Solaris (Re: Duplicate data objects in shared libraries)
H . J . Lu
hjl@lucon.org
Wed May 29 14:43:00 GMT 2002
This patch makes glibc more like Solaris for RTLD_LOCAL. It also passed
"make check" in glibc. Any comments?
BTW, we need to fully document the RTLD_LOCAL behavior.
H.J.
-------------- next part --------------
2002-05-29 H.J. Lu <hjl@gnu.org>
* elf/dl-close.c (_dl_close): Don't assume the object to be
dlcosed is the first one on l_initfini or l_searchlist.r_list.
* elf/dl-deps.c (_dl_map_object_deps): Likewise.
* elf/dl-deps.c (_dl_map_object_deps): If a DT_NEEDED object
is loaded via dlopen already, put it before the current object.
--- elf/dl-close.c.local Wed May 29 12:21:14 2002
+++ elf/dl-close.c Wed May 29 12:21:14 2002
@@ -147,9 +147,10 @@ _dl_close (void *_map)
list[i]->l_idx = i;
new_opencount[i] = list[i]->l_opencount;
}
- --new_opencount[0];
- for (i = 1; list[i] != NULL; ++i)
- if ((! (list[i]->l_flags_1 & DF_1_NODELETE) || ! list[i]->l_init_called)
+ for (i = 0; list[i] != NULL; ++i)
+ if (list [i] == map)
+ --new_opencount[i];
+ else if ((! (list[i]->l_flags_1 & DF_1_NODELETE) || ! list[i]->l_init_called)
/* Decrement counter. */
&& --new_opencount[i] == 0
/* Test whether this object was also loaded directly. */
@@ -160,9 +161,10 @@ _dl_close (void *_map)
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)
- || ! dep_list[j]->l_init_called)
+ for (j = 0; j < list[i]->l_searchlist.r_nlist; ++j)
+ if (list[i] != dep_list[j]
+ && (! (dep_list[j]->l_flags_1 & DF_1_NODELETE)
+ || ! dep_list[j]->l_init_called))
{
assert (dep_list[j]->l_idx < map->l_searchlist.r_nlist);
--new_opencount[dep_list[j]->l_idx];
--- elf/dl-deps.c.local Wed May 29 12:21:14 2002
+++ elf/dl-deps.c Wed May 29 12:26:21 2002
@@ -266,12 +266,31 @@ _dl_map_object_deps (struct link_map *ma
newp = alloca (sizeof (struct list));
- /* Append DEP to the list. */
- newp->map = dep;
- newp->done = 0;
- newp->next = NULL;
- tail->next = newp;
- tail = newp;
+ if (dep->l_relocated && dep->l_type == lt_loaded)
+ {
+ /* It is very tricky. We have to put DEP at the
+ right place on the list. */
+ memcpy (newp, orig, sizeof (*newp));
+ orig->done = 0;
+ orig->map = dep;
+ orig->next = newp;
+
+ /* Move the tail pointer if necessary. */
+ if (orig == tail)
+ tail = newp;
+
+ /* Move on the insert point. */
+ orig = newp;
+ }
+ else
+ {
+ /* Append DEP to the list. */
+ newp->map = dep;
+ newp->done = 0;
+ newp->next = NULL;
+ tail->next = newp;
+ tail = newp;
+ }
++nlist;
/* Set the mark bit that says it's already in the list. */
dep->l_reserved = 1;
@@ -559,13 +578,13 @@ Filters not supported with LD_TRACE_PREL
}
/* Maybe we can remove some relocation dependencies now. */
- assert (map->l_searchlist.r_list[0] == map);
for (i = 0; i < map->l_reldepsact; ++i)
{
unsigned int j;
- for (j = 1; j < nlist; ++j)
- if (map->l_searchlist.r_list[j] == map->l_reldeps[i])
+ for (j = 0; j < nlist; ++j)
+ if (map->l_searchlist.r_list[j] != map
+ && map->l_searchlist.r_list[j] == map->l_reldeps[i])
{
/* A direct or transitive dependency is also on the list
of relocation dependencies. Remove the latter. */
@@ -588,12 +607,15 @@ Filters not supported with LD_TRACE_PREL
/* We can skip looking for the binary itself which is at the front
of the search list. Look through the list backward so that circular
dependencies are not changing the order. */
- for (i = 1; i < nlist; ++i)
+ for (i = 0; i < nlist; ++i)
{
struct link_map *l = map->l_searchlist.r_list[i];
unsigned int j;
unsigned int k;
+ if (l == map)
+ continue;
+
/* Find the place in the initfini list where the map is currently
located. */
for (j = 1; map->l_initfini[j] != l; ++j)
More information about the Libc-alpha
mailing list