]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - elf/dl-object.c
Prefer https to http for gnu.org and fsf.org URLs
[thirdparty/glibc.git] / elf / dl-object.c
index 5d15ce1869b6305f828b409e9edeebf448b50641..4dff99ed110201acc69df65b04d02cb43ba7fed4 100644 (file)
@@ -1,5 +1,5 @@
 /* Storage management for the chain of loaded shared objects.
-   Copyright (C) 1995-2002,2004,2006-2009,2010 Free Software Foundation, Inc.
+   Copyright (C) 1995-2019 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>
@@ -28,7 +27,6 @@
 
 /* Add the new link_map NEW to the end of the namespace list.  */
 void
-internal_function
 _dl_add_to_namespace_list (struct link_map *new, Lmid_t nsid)
 {
   /* We modify the list of loaded objects.  */
@@ -56,19 +54,33 @@ _dl_add_to_namespace_list (struct link_map *new, Lmid_t nsid)
 /* 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;
+#ifdef SHARED
+  unsigned int naudit;
+  if (__glibc_unlikely ((mode & __RTLD_OPENEXEC) != 0))
+    {
+      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 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]);
 #else
 # define audit_space 0
@@ -90,7 +102,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.  */
@@ -112,7 +142,7 @@ _dl_new_object (char *realname, const char *libname, int type,
 
   /* 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;
@@ -147,7 +177,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;