PATCH: Treat RTLD_LOCAL like Solaris (Re: Duplicate data objects in shared libraries)
H . J . Lu
hjl@lucon.org
Thu May 30 11:01:00 GMT 2002
On Wed, May 29, 2002 at 01:09:45PM -0700, H . J . Lu wrote:
> 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.
>
>
Here is an update. I need to adjust one assert in dl-close.c.
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 Thu May 30 08:58:36 2002
+++ elf/dl-close.c Thu May 30 09:01:01 2002
@@ -98,6 +98,7 @@ _dl_close (void *_map)
struct link_map **list;
struct link_map *map = _map;
unsigned int i;
+ unsigned int imap;
unsigned int *new_opencount;
#ifdef USE_TLS
bool any_tls = false;
@@ -147,9 +148,13 @@ _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];
+ imap = 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,15 +165,16 @@ _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];
}
}
- assert (new_opencount[0] == 0);
+ assert (new_opencount[imap] == 0);
/* Call all termination functions at once. */
for (i = 0; list[i] != NULL; ++i)
--- elf/dl-deps.c.local Thu May 30 08:58:36 2002
+++ elf/dl-deps.c Thu May 30 08:58:36 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