public inbox for libc-help@sourceware.org
 help / color / mirror / Atom feed
From: "Vivek Das Mohapatra" <vivek@collabora.com>
To: libc-help@sourceware.org
Subject: [RFC PATCH 4/5] elf/dl-load.c, elf-dl-open.c: Implement RTLD_SHARED dlmopen cloning
Date: Thu, 05 Apr 2018 17:59:00 -0000	[thread overview]
Message-ID: <20180405175231.14757-5-vivek@collabora.com> (raw)
In-Reply-To: <20180405175231.14757-1-vivek@collabora.com>

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

  parent reply	other threads:[~2018-04-05 17:59 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-04-05 17:52 [RFC PATCH 0/5] Proof-of-Concept implementation of RTLD_SHARED for dlmopen Vivek Das Mohapatra
2018-04-05 17:52 ` [RFC PATCH 3/5] elf/dl-object.c: Implement a helper function to clone link_map entries Vivek Das Mohapatra
2018-04-05 17:52 ` [RFC PATCH 2/5] include/link.h: Update the link_map struct to allow clones Vivek Das Mohapatra
2018-04-05 17:52 ` [RFC PATCH 1/5] bits/dlfcn.h: Declare and describe the dlmopen RTLD_SHARED flag Vivek Das Mohapatra
2018-04-05 17:59 ` Vivek Das Mohapatra [this message]
2018-04-05 17:59 ` [RFC PATCH 5/5] elf/dl-fini.c: Handle cloned link_map entries in the shutdown path Vivek Das Mohapatra
2018-04-12 19:59 ` [RFC PATCH 0/5] Proof-of-Concept implementation of RTLD_SHARED for dlmopen Adhemerval Zanella

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180405175231.14757-5-vivek@collabora.com \
    --to=vivek@collabora.com \
    --cc=libc-help@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).