[yocto] [prelink-cross][PATCH] rtld: Add missing DT_NEEDED DSOs to needed_list

Kyle Russell bkylerussell at gmail.com
Thu Aug 25 08:39:17 PDT 2016


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 <bkylerussell at 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




More information about the yocto mailing list