]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - elf/dl-object.c
test-container: Fix "unused code" warnings on HURD
[thirdparty/glibc.git] / elf / dl-object.c
index 22a163560b48b3fb6b3a12112f470e550497908f..230ef8dce30151cda9a673f19ec7865f4530ed21 100644 (file)
@@ -1,5 +1,5 @@
 /* Storage management for the chain of loaded shared objects.
-   Copyright (C) 1995-2002,2004,2006-2008,2009 Free Software Foundation, Inc.
+   Copyright (C) 1995-2022 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -13,9 +13,8 @@
    Lesser General Public License for more details.
 
    You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
 
 #include <errno.h>
 #include <string.h>
 #include <assert.h>
 
 
+/* Add the new link_map NEW to the end of the namespace list.  */
+void
+_dl_add_to_namespace_list (struct link_map *new, Lmid_t nsid)
+{
+  /* We modify the list of loaded objects.  */
+  __rtld_lock_lock_recursive (GL(dl_load_write_lock));
+
+  if (GL(dl_ns)[nsid]._ns_loaded != NULL)
+    {
+      struct link_map *l = GL(dl_ns)[nsid]._ns_loaded;
+      while (l->l_next != NULL)
+       l = l->l_next;
+      new->l_prev = l;
+      /* new->l_next = NULL;   Would be necessary but we use calloc.  */
+      l->l_next = new;
+    }
+  else
+    GL(dl_ns)[nsid]._ns_loaded = new;
+  ++GL(dl_ns)[nsid]._ns_nloaded;
+  new->l_serial = GL(dl_load_adds);
+  ++GL(dl_load_adds);
+
+  __rtld_lock_unlock_recursive (GL(dl_load_write_lock));
+}
+
+
 /* Allocate a `struct link_map' for a new object being loaded,
    and enter it into the _dl_loaded list.  */
-
 struct link_map *
-internal_function
 _dl_new_object (char *realname, const char *libname, int type,
                struct link_map *loader, int mode, Lmid_t nsid)
 {
-  struct link_map *l;
-  int idx;
+#ifdef SHARED
+  unsigned int naudit;
+  if (__glibc_unlikely ((mode & (__RTLD_OPENEXEC | __RTLD_VDSO)) != 0))
+    {
+      if (mode & __RTLD_OPENEXEC)
+       {
+         assert (type == lt_executable);
+         assert (nsid == LM_ID_BASE);
+
+         /* Ignore the specified libname for the main executable.  It is
+            only known with an explicit loader invocation.  */
+         libname = "";
+       }
+
+      /* We create the map for the executable and vDSO before we know whether
+        we have auditing libraries and if yes, how many.  Assume the
+        worst.  */
+      naudit = DL_NNS;
+    }
+  else
+    naudit = GLRO (dl_naudit);
+#endif
+
   size_t libname_len = strlen (libname) + 1;
   struct link_map *new;
   struct libname_list *newname;
 #ifdef SHARED
-  /* We create the map for the executable before we know whether we have
-     auditing libraries and if yes, how many.  Assume the worst.  */
-  unsigned int naudit = GLRO(dl_naudit) ?: ((mode & __RTLD_OPENEXEC)
-                                           ? DL_NNS : 0);
-  size_t audit_space = naudit * sizeof (new->l_audit[0]);
+  size_t audit_space = naudit * sizeof (struct auditstate);
 #else
 # define audit_space 0
 #endif
@@ -65,7 +105,25 @@ _dl_new_object (char *realname, const char *libname, int type,
   /* newname->next = NULL;     We use calloc therefore not necessary.  */
   newname->dont_free = 1;
 
-  new->l_name = realname;
+  /* When we create the executable link map, or a VDSO link map, we start
+     with "" for the l_name. In these cases "" points to ld.so rodata
+     and won't get dumped during core file generation. Therefore to assist
+     gdb and to create more self-contained core files we adjust l_name to
+     point at the newly allocated copy (which will get dumped) instead of
+     the ld.so rodata copy.
+
+     Furthermore, in case of explicit loader invocation, discard the
+     name of the main executable, to match the regular behavior, where
+     name of the executable is not known.  */
+#ifdef SHARED
+  if (*realname != '\0' && (mode & __RTLD_OPENEXEC) == 0)
+#else
+  if (*realname != '\0')
+#endif
+    new->l_name = realname;
+  else
+    new->l_name = (char *) newname->name + libname_len - 1;
+
   new->l_type = type;
   /* If we set the bit now since we know it is never used we avoid
      dirtying the cache line later.  */
@@ -79,45 +137,24 @@ _dl_new_object (char *realname, const char *libname, int type,
 
 #ifdef SHARED
   for (unsigned int cnt = 0; cnt < naudit; ++cnt)
-    {
-      new->l_audit[cnt].cookie = (uintptr_t) new;
-      /* new->l_audit[cnt].bindflags = 0; */
-    }
+    /* No need to initialize bindflags due to calloc.  */
+    link_map_audit_state (new, cnt)->cookie = (uintptr_t) new;
 #endif
 
   /* new->l_global = 0;        We use calloc therefore not necessary.  */
 
-  /* Use the 'l_scope_mem' array by default for the the 'l_scope'
+  /* Use the 'l_scope_mem' array by default for the 'l_scope'
      information.  If we need more entries we will allocate a large
      array dynamically.  */
   new->l_scope = new->l_scope_mem;
   new->l_scope_max = sizeof (new->l_scope_mem) / sizeof (new->l_scope_mem[0]);
 
-  /* We modify the list of loaded objects.  */
-  __rtld_lock_lock_recursive (GL(dl_load_write_lock));
-
   /* Counter for the scopes we have to handle.  */
-  idx = 0;
+  int idx = 0;
 
   if (GL(dl_ns)[nsid]._ns_loaded != NULL)
-    {
-      l = GL(dl_ns)[nsid]._ns_loaded;
-      while (l->l_next != NULL)
-       l = l->l_next;
-      new->l_prev = l;
-      /* new->l_next = NULL;   Would be necessary but we use calloc.  */
-      l->l_next = new;
-
-      /* Add the global scope.  */
-      new->l_scope[idx++] = &GL(dl_ns)[nsid]._ns_loaded->l_searchlist;
-    }
-  else
-    GL(dl_ns)[nsid]._ns_loaded = new;
-  ++GL(dl_ns)[nsid]._ns_nloaded;
-  new->l_serial = GL(dl_load_adds);
-  ++GL(dl_load_adds);
-
-  __rtld_lock_unlock_recursive (GL(dl_load_write_lock));
+    /* Add the global scope.  */
+    new->l_scope[idx++] = &GL(dl_ns)[nsid]._ns_loaded->l_searchlist;
 
   /* If we have no loader the new object acts as it.  */
   if (loader == NULL)
@@ -141,7 +178,14 @@ _dl_new_object (char *realname, const char *libname, int type,
 
   new->l_local_scope[0] = &new->l_searchlist;
 
-  /* Don't try to find the origin for the main map which has the name "".  */
+  /* Determine the origin.  If allocating the link map for the main
+     executable, the realname is not known and "".  In this case, the
+     origin needs to be determined by other means.  However, in case
+     of an explicit loader invocation, the pathname of the main
+     executable is known and needs to be processed here: From the
+     point of view of the kernel, the main executable is the
+     dynamic loader, and this would lead to a computation of the wrong
+     origin.  */
   if (realname[0] != '\0')
     {
       size_t realname_len = strlen (realname) + 1;