aboutsummaryrefslogtreecommitdiff
path: root/elf
diff options
context:
space:
mode:
Diffstat (limited to 'elf')
-rw-r--r--elf/dl-deps.c11
-rw-r--r--elf/dl-load.c2
-rw-r--r--elf/rtld.c31
3 files changed, 29 insertions, 15 deletions
diff --git a/elf/dl-deps.c b/elf/dl-deps.c
index 3e49fcfe01..9fe974d982 100644
--- a/elf/dl-deps.c
+++ b/elf/dl-deps.c
@@ -38,6 +38,10 @@ _dl_map_object_deps (struct link_map *map)
head.next = NULL;
nlist = 1;
+ /* We use `l_reserved' as a mark bit to detect objects we have already
+ put in the search list and avoid adding duplicate elements later in
+ the list. */
+ map->l_reserved = 1;
/* Process each element of the search list, loading each of its immediate
dependencies and appending them to the list as we step through it.
@@ -47,11 +51,6 @@ _dl_map_object_deps (struct link_map *map)
{
struct link_map *l = scanp->map;
- /* We use `l_reserved' as a mark bit to detect objects we have
- already put in the search list and avoid adding duplicate elements
- later in the list. */
- l->l_reserved = 1;
-
if (l->l_info[DT_NEEDED])
{
const char *strtab
@@ -79,6 +78,8 @@ _dl_map_object_deps (struct link_map *map)
tailp->map = dep;
tailp->next = NULL;
++nlist;
+ /* Set the mark bit that says it's already in the list. */
+ dep->l_reserved = 1;
}
}
}
diff --git a/elf/dl-load.c b/elf/dl-load.c
index f947bb8a93..f655fdacef 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -479,7 +479,7 @@ _dl_map_object (struct link_map *loader, const char *name, int type)
l->l_info[DT_RPATH]->d_un.d_val));
/* If dynamically linked, try the DT_RPATH of the executable itself. */
l = _dl_loaded;
- if (fd == -1 && l && l->l_type != lt_loaded)
+ if (fd == -1 && l && l->l_type != lt_loaded && l->l_info[DT_RPATH])
trypath ((const char *) (l->l_addr +
l->l_info[DT_STRTAB]->d_un.d_ptr +
l->l_info[DT_RPATH]->d_un.d_val));
diff --git a/elf/rtld.c b/elf/rtld.c
index fb92809ff5..f20602d090 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -243,17 +243,30 @@ of this helper program; chances are you did not intend to run this program.\n",
__close (_dl_zerofd);
_dl_zerofd = -1;
- /* XXX if kept, move it so l_next list is in dep order because
- it will determine gdb's search order.
- Perhaps do this always, so later dlopen by name finds it?
- XXX But then gdb always considers it present. */
- if (_dl_rtld_map.l_opencount == 0)
+ /* Remove _dl_rtld_map from the chain. */
+ _dl_rtld_map.l_prev->l_next = _dl_rtld_map.l_next;
+ if (_dl_rtld_map.l_next)
+ _dl_rtld_map.l_next->l_prev = _dl_rtld_map.l_prev;
+
+ if (_dl_rtld_map.l_opencount)
{
- /* No DT_NEEDED entry referred to the interpreter object itself,
- so remove it from the list of visible objects. */
- _dl_rtld_map.l_prev->l_next = _dl_rtld_map.l_next;
+ /* Some DT_NEEDED entry referred to the interpreter object itself, so
+ put it back in the list of visible objects. We insert it into the
+ chain in symbol search order because gdb uses the chain's order as
+ its symbol search order. */
+ unsigned int i = 1;
+ while (l->l_searchlist[i] != &_dl_rtld_map)
+ ++i;
+ _dl_rtld_map.l_prev = l->l_searchlist[i - 1];
+ _dl_rtld_map.l_next = (i + 1 < l->l_nsearchlist ?
+ l->l_searchlist[i + 1] : NULL);
+ assert (_dl_rtld_map.l_prev->l_next == _dl_rtld_map.l_next);
+ _dl_rtld_map.l_prev->l_next = &_dl_rtld_map;
if (_dl_rtld_map.l_next)
- _dl_rtld_map.l_next->l_prev = _dl_rtld_map.l_prev;
+ {
+ assert (_dl_rtld_map.l_next->l_prev == _dl_rtld_map.l_prev);
+ _dl_rtld_map.l_next->l_prev = &_dl_rtld_map;
+ }
}
if (list_only)