This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC PATCH 4/5] elf/dl-load.c, elf-dl-open.c: Implement RTLD_SHARED dlmopen cloning


This uses the new infrastructure to implement RTLD_SHARED object
cloning via dlmopen: Instead of opening the specified object in
the requested namespace we open it in the main namespace (if it
is not already present there) and clone it into the requated
namespace.

The following rules apply:

If a clone of the object is already present in the requested namespace,
we simply return it (with an incremented direct-open count).

If the object is already present in the requested namespace, a dl
error is signalled, since we cannot satisfy the user's request.

Clones are never created in the main namespace: RTLD_SHARED has no
effect when the requested namespace is LM_ID_BASE.
---
 elf/dl-load.c | 34 ++++++++++++++++++++++++++++++++++
 elf/dl-open.c | 31 +++++++++++++++++++++++++++++--
 2 files changed, 63 insertions(+), 2 deletions(-)

diff --git a/elf/dl-load.c b/elf/dl-load.c
index a5e3a25462..a3bc85fb0a 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -1847,6 +1847,40 @@ _dl_map_object (struct link_map *loader, const char *name,
   assert (nsid >= 0);
   assert (nsid < GL(dl_nns));
 
+#ifdef SHARED
+  /* Only need to do cloning work if `nsid' is not LM_ID_BASE.  */
+  if (__glibc_unlikely ((mode & RTLD_SHARED) && (nsid != LM_ID_BASE)))
+    {
+      /* Search the target namespace, in case the object is already there.
+         Note that unlike the search in the next section we do not attempt to
+         extract the object's name if it does not yet have one.  */
+      for (l = GL(dl_ns)[nsid]._ns_loaded; l; l = l->l_next)
+        {
+          if (__glibc_unlikely ((l->l_faked | l->l_removed) != 0))
+            continue;
+
+          if (!_dl_name_match_p (name, l))
+            continue;
+
+          /* We have a match - stop searching.  */
+          break;
+        }
+
+      if (l)
+        {
+          if (l->l_clone)
+            return l;
+
+          _dl_signal_error (EEXIST, name, NULL,
+                            N_("object cannot be demoted to a clone"));
+        }
+
+      /* Further searches should be in the base ns: We will clone the
+         resulting object in dl_open_worker *after* it is initialised.  */
+      nsid = LM_ID_BASE;
+    }
+#endif
+
   /* Look for this name among those already loaded.  */
   for (l = GL(dl_ns)[nsid]._ns_loaded; l; l = l->l_next)
     {
diff --git a/elf/dl-open.c b/elf/dl-open.c
index 9dde4acfbc..0c5c75c137 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -237,6 +237,10 @@ dl_open_worker (void *a)
   /* This object is directly loaded.  */
   ++new->l_direct_opencount;
 
+  /* Clone already existed in the target ns, nothing left to do.  */
+  if (__glibc_unlikely (new->l_clone))
+    return;
+
   /* It was already open.  */
   if (__glibc_unlikely (new->l_searchlist.r_list != NULL))
     {
@@ -252,6 +256,16 @@ dl_open_worker (void *a)
 
       assert (_dl_debug_initialize (0, args->nsid)->r_state == RT_CONSISTENT);
 
+      if (__glibc_unlikely (mode & RTLD_SHARED))
+        {
+          args->map = new = _dl_clone_object (new, mode, args->nsid);
+          ++new->l_direct_opencount;
+
+          if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
+            _dl_debug_printf ("cloning file=%s [%lu]; direct_opencount=%u\n\n",
+                              new->l_name, new->l_ns, new->l_direct_opencount);
+        }
+
       return;
     }
 
@@ -509,6 +523,11 @@ TLS generation counter wrapped!  Please report this."));
       /* It failed.  */
       return;
 
+  if (__glibc_unlikely (mode & RTLD_SHARED))
+    {
+      args->map = _dl_clone_object (new, mode, args->nsid);
+      ++args->map->l_direct_opencount;
+    }
 #ifndef SHARED
   /* We must be the static _dl_open in libc.a.  A static program that
      has loaded a dynamic object now has competition.  */
@@ -517,8 +536,16 @@ TLS generation counter wrapped!  Please report this."));
 
   /* Let the user know about the opencount.  */
   if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
-    _dl_debug_printf ("opening file=%s [%lu]; direct_opencount=%u\n\n",
-		      new->l_name, new->l_ns, new->l_direct_opencount);
+    {
+      _dl_debug_printf ("opening file=%s [%lu]; direct_opencount=%u\n\n",
+                        new->l_name, new->l_ns, new->l_direct_opencount);
+
+      if (mode & RTLD_SHARED)
+        _dl_debug_printf ("cloning file=%s [%lu]; direct_opencount=%u\n\n",
+                          args->map->l_name,
+                          args->map->l_ns,
+                          args->map->l_direct_opencount);
+    }
 }
 
 
-- 
2.11.0


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]