[PATCH v3 27/32] elf: Determine the caller link map in _dl_open

Florian Weimer fweimer@redhat.com
Thu Dec 7 10:32:41 GMT 2023


No functional change expected.

This is in preparation of adding a fast path to dlopen in case
no link map changes are required.
---
 elf/dl-open.c | 47 +++++++++++++++++++----------------------------
 1 file changed, 19 insertions(+), 28 deletions(-)

diff --git a/elf/dl-open.c b/elf/dl-open.c
index afac8498be..52e44804cf 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -49,8 +49,7 @@ struct dl_open_args
 {
   const char *file;
   int mode;
-  /* This is the caller of the dlopen() function.  */
-  const void *caller_dlopen;
+  struct link_map_private *caller_map; /* Derived from the caller address.  */
   struct link_map_private *map;
   /* Namespace ID.  */
   Lmid_t nsid;
@@ -540,30 +539,6 @@ dl_open_worker_begin (void *a)
   struct dl_open_args *args = a;
   const char *file = args->file;
   int mode = args->mode;
-  struct link_map_private *call_map = NULL;
-
-  /* Determine the caller's map if necessary.  This is needed in case
-     we have a DST, when we don't know the namespace ID we have to put
-     the new object in, or when the file name has no path in which
-     case we need to look along the RUNPATH/RPATH of the caller.  */
-  const char *dst = strchr (file, '$');
-  if (dst != NULL || args->nsid == __LM_ID_CALLER
-      || strchr (file, '/') == NULL)
-    {
-      const void *caller_dlopen = args->caller_dlopen;
-
-      /* We have to find out from which object the caller is calling.
-	 By default we assume this is the main application.  */
-      call_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
-
-      struct link_map_private *l = _dl_find_dso_for_object ((ElfW(Addr)) caller_dlopen);
-
-      if (l)
-	call_map = l;
-
-      if (args->nsid == __LM_ID_CALLER)
-	args->nsid = call_map->l_ns;
-    }
 
   /* Prepare for link map updates.  If dl_open_worker below returns
      normally, a matching _dl_protmem_end call is performed there.  On
@@ -585,7 +560,7 @@ dl_open_worker_begin (void *a)
 
   /* Load the named object.  */
   struct link_map_private *new;
-  args->map = new = _dl_map_object (call_map, file, lt_loaded, 0,
+  args->map = new = _dl_map_object (args->caller_map, file, lt_loaded, 0,
 				    mode | __RTLD_CALLMAP, args->nsid);
 
   /* If the pointer returned is NULL this means the RTLD_NOLOAD flag is
@@ -906,7 +881,6 @@ no more namespaces available for dlmopen()"));
   struct dl_open_args args;
   args.file = file;
   args.mode = mode;
-  args.caller_dlopen = caller_dlopen;
   args.map = NULL;
   args.nsid = nsid;
   /* args.libc_already_loaded is always assigned by dl_open_worker
@@ -915,6 +889,23 @@ no more namespaces available for dlmopen()"));
   args.argv = argv;
   args.env = env;
 
+  /* Determine the caller's map if necessary.  This is needed when we
+     don't know the namespace ID in which we have to put the new object,
+     in case we have a DST, or when the file name has no path in
+     which case we need to look along the RUNPATH/RPATH of the caller.  */
+  if (nsid == __LM_ID_CALLER || strchr (file, '$') != NULL
+      || strchr (file, '/') == NULL)
+    {
+      args.caller_map = _dl_find_dso_for_object ((ElfW(Addr)) caller_dlopen);
+      if (args.caller_map == NULL)
+	/* By default we assume this is the main application.  */
+	args.caller_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
+      if (args.nsid == __LM_ID_CALLER)
+	args.nsid = args.caller_map->l_ns;
+    }
+  else
+    args.caller_map = NULL;
+
   struct dl_exception exception;
   int errcode = _dl_catch_exception (&exception, dl_open_worker, &args);
 
-- 
2.43.0




More information about the Libc-alpha mailing list