prelink-rtld may report an "error while loading shared libraries" for
the wrong library.

If some set of DT_NEEDED DSOs are not in the default search path, they
may have a dso_list entry added, but no matching entry is added to the
needed_list.  This causes the linker to miscalculate the max number of
dsos during build_local_scope(), which later causes find_needed() to not
search the entire l_local_scope[0]->r_list during
_dl_check_map_versions() (since the max from build_local_scope() becomes
l_local_scope[0]->r_nlist).

Since find_needed() searches through the r_list, which would have the
dso_list entries for the libraries that weren't found earlier, this cuts
the search short, meaning libraries near the end of the local scope don't
get included in the map version search.

As the comment in _dl_check_map_versions() suggests, if needed is NULL,
that means a dependency was not found and no stub entry created, which
should never happen.

Signed-off-by: Kyle Russell <bkyleruss...@gmail.com>
---
 src/rtld/rtld.c | 36 ++++++++++++++++++++++--------------
 1 file changed, 22 insertions(+), 14 deletions(-)

diff --git a/src/rtld/rtld.c b/src/rtld/rtld.c
index 8d7d760..d9a0862 100644
--- a/src/rtld/rtld.c
+++ b/src/rtld/rtld.c
@@ -686,6 +686,25 @@ find_lib_by_soname (const char *soname, struct dso_list 
*loader,
   return NULL;
 }
 
+static void
+add_dso_to_needed (struct dso_list *cur_dso_ent, struct dso_list *new_dso_ent)
+{
+  if (!cur_dso_ent->needed)
+    {
+      cur_dso_ent->needed = malloc (sizeof (struct needed_list));
+      cur_dso_ent->needed_tail = cur_dso_ent->needed;
+      cur_dso_ent->needed_tail->ent = new_dso_ent;
+      cur_dso_ent->needed_tail->next = NULL;
+    }
+  else if (!in_needed_list (cur_dso_ent->needed, new_dso_ent->name))
+    {
+      cur_dso_ent->needed_tail->next = malloc (sizeof (struct needed_list));
+      cur_dso_ent->needed_tail = cur_dso_ent->needed_tail->next;
+      cur_dso_ent->needed_tail->ent = new_dso_ent;
+      cur_dso_ent->needed_tail->next = NULL;
+    }
+}
+
 static struct dso_list *
 load_dsos (DSO *dso, int host_paths)
 {
@@ -812,6 +831,8 @@ load_dsos (DSO *dso, int host_paths)
                          dso_list_tail->canon_filename = strdup(soname);
                          dso_list_tail->err_no = errno;
 
+                          add_dso_to_needed(cur_dso_ent, new_dso_ent);
+
                          continue;
                        }
 
@@ -854,20 +875,7 @@ load_dsos (DSO *dso, int host_paths)
                        dso_list_tail->name = new_dso->soname;
                    }
 
-                 if (!cur_dso_ent->needed)
-                   {
-                     cur_dso_ent->needed = malloc (sizeof (struct 
needed_list));
-                     cur_dso_ent->needed_tail = cur_dso_ent->needed;
-                     cur_dso_ent->needed_tail->ent = new_dso_ent;
-                     cur_dso_ent->needed_tail->next = NULL;
-                   }
-                 else if (!in_needed_list (cur_dso_ent->needed, soname))
-                   {
-                     cur_dso_ent->needed_tail->next = malloc (sizeof (struct 
needed_list));
-                     cur_dso_ent->needed_tail = cur_dso_ent->needed_tail->next;
-                     cur_dso_ent->needed_tail->ent = new_dso_ent;
-                     cur_dso_ent->needed_tail->next = NULL;
-                   }
+                  add_dso_to_needed(cur_dso_ent, new_dso_ent);
 
                  continue;
                }
-- 
2.7.4

-- 
_______________________________________________
yocto mailing list
yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/yocto

Reply via email to