summary refs log tree commit diff
path: root/elf
diff options
context:
space:
mode:
Diffstat (limited to 'elf')
-rw-r--r--elf/Makefile2
-rw-r--r--elf/Versions4
-rw-r--r--elf/dl-call-libc-early-init.c (renamed from elf/dl-lookup_libc_early_init.c)23
-rw-r--r--elf/dl-load.c9
-rw-r--r--elf/dl-open.c4
-rw-r--r--elf/dl-version.c18
-rw-r--r--elf/libc-early-init.h21
-rw-r--r--elf/rtld.c12
8 files changed, 44 insertions, 49 deletions
diff --git a/elf/Makefile b/elf/Makefile
index bc68150a37..3928a08787 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -52,6 +52,7 @@ routines = \
 # The core dynamic linking functions are in libc for the static and
 # profiled libraries.
 dl-routines = \
+  dl-call-libc-early-init \
   dl-close \
   dl-debug \
   dl-debug-symbols \
@@ -64,7 +65,6 @@ dl-routines = \
   dl-load \
   dl-lookup \
   dl-lookup-direct \
-  dl-lookup_libc_early_init \
   dl-minimal-malloc \
   dl-misc \
   dl-object \
diff --git a/elf/Versions b/elf/Versions
index 6260c0fe03..a9ff278de7 100644
--- a/elf/Versions
+++ b/elf/Versions
@@ -29,8 +29,8 @@ libc {
     __placeholder_only_for_empty_version_map;
   }
   GLIBC_PRIVATE {
-    # A pattern is needed here because the suffix is dynamically generated.
-    __libc_early_init_*;
+    # functions used in other libraries
+    __libc_early_init;
 
     # Internal error handling support.  Interposes the functions in ld.so.
     _dl_signal_exception; _dl_catch_exception;
diff --git a/elf/dl-lookup_libc_early_init.c b/elf/dl-call-libc-early-init.c
index 64bc287a05..ee9860e3ab 100644
--- a/elf/dl-lookup_libc_early_init.c
+++ b/elf/dl-call-libc-early-init.c
@@ -1,4 +1,4 @@
-/* Find the address of the __libc_early_init function.
+/* Invoke the early initialization function in libc.so.
    Copyright (C) 2020-2022 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -16,21 +16,26 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
+#include <assert.h>
 #include <ldsodefs.h>
 #include <libc-early-init.h>
 #include <link.h>
 #include <stddef.h>
 
-__typeof (__libc_early_init) *
-_dl_lookup_libc_early_init (struct link_map *libc_map)
+void
+_dl_call_libc_early_init (struct link_map *libc_map, _Bool initial)
 {
+  /* There is nothing to do if we did not actually load libc.so.  */
+  if (libc_map == NULL)
+    return;
+
   const ElfW(Sym) *sym
-    = _dl_lookup_direct (libc_map, LIBC_EARLY_INIT_NAME_STRING,
-                         LIBC_EARLY_INIT_GNU_HASH,
+    = _dl_lookup_direct (libc_map, "__libc_early_init",
+                         0x069682ac, /* dl_new_hash output.  */
                          "GLIBC_PRIVATE",
                          0x0963cf85); /* _dl_elf_hash output.  */
-  if (sym == NULL)
-    _dl_signal_error (0, libc_map->l_name, NULL, "\
-ld.so/libc.so mismatch detected (upgrade in progress?)");
-  return DL_SYMBOL_ADDRESS (libc_map, sym);
+  assert (sym != NULL);
+  __typeof (__libc_early_init) *early_init
+    = DL_SYMBOL_ADDRESS (libc_map, sym);
+  early_init (initial);
 }
diff --git a/elf/dl-load.c b/elf/dl-load.c
index 00e08b5500..1ad0868dad 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -31,6 +31,7 @@
 #include <sys/param.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <gnu/lib-names.h>
 
 /* Type for the buffer we put the ELF header and hopefully the program
    header.  This buffer does not really have to be too large.  In most
@@ -1465,6 +1466,14 @@ cannot enable executable stack as shared object requires");
     add_name_to_object (l, ((const char *) D_PTR (l, l_info[DT_STRTAB])
 			    + l->l_info[DT_SONAME]->d_un.d_val));
 
+  /* If we have newly loaded libc.so, update the namespace
+     description.  */
+  if (GL(dl_ns)[nsid].libc_map == NULL
+      && l->l_info[DT_SONAME] != NULL
+      && strcmp (((const char *) D_PTR (l, l_info[DT_STRTAB])
+		  + l->l_info[DT_SONAME]->d_un.d_val), LIBC_SO) == 0)
+    GL(dl_ns)[nsid].libc_map = l;
+
   /* _dl_close can only eventually undo the module ID assignment (via
      remove_slotinfo) if this function returns a pointer to a link
      map.  Therefore, delay this step until all possibilities for
diff --git a/elf/dl-open.c b/elf/dl-open.c
index dcc24130fe..a23e65926b 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -760,8 +760,8 @@ dl_open_worker_begin (void *a)
   if (!args->libc_already_loaded)
     {
       /* dlopen cannot be used to load an initial libc by design.  */
-      if (GL(dl_ns)[args->nsid].libc_map != NULL)
-	GL(dl_ns)[args->nsid].libc_map_early_init (false);
+      struct link_map *libc_map = GL(dl_ns)[args->nsid].libc_map;
+      _dl_call_libc_early_init (libc_map, false);
     }
 
   args->worker_continue = true;
diff --git a/elf/dl-version.c b/elf/dl-version.c
index d9ec44eed6..cda0889209 100644
--- a/elf/dl-version.c
+++ b/elf/dl-version.c
@@ -23,8 +23,6 @@
 #include <string.h>
 #include <ldsodefs.h>
 #include <_itoa.h>
-#include <gnu/lib-names.h>
-#include <libc-early-init.h>
 
 #include <assert.h>
 
@@ -361,22 +359,6 @@ _dl_check_map_versions (struct link_map *map, int verbose, int trace_mode)
 	}
     }
 
-  /* Detect a libc.so loaded into this namespace.  The
-     __libc_early_init lookup below means that we have to do this
-     after parsing the version data.  */
-  if (GL(dl_ns)[map->l_ns].libc_map == NULL
-      && map->l_info[DT_SONAME] != NULL
-      && strcmp (((const char *) D_PTR (map, l_info[DT_STRTAB])
-		  + map->l_info[DT_SONAME]->d_un.d_val), LIBC_SO) == 0)
-    {
-      /* Look up this symbol early to trigger a mismatch error before
-	 relocation (which may call IFUNC resolvers, and those can
-	 have an internal ABI dependency).  */
-      GL(dl_ns)[map->l_ns].libc_map_early_init
-	= _dl_lookup_libc_early_init (map);
-      GL(dl_ns)[map->l_ns].libc_map = map;
-    }
-
   /* When there is a DT_VERNEED entry with libc.so on DT_NEEDED, issue
      an error if there is a DT_RELR entry without GLIBC_ABI_DT_RELR
      dependency.  */
diff --git a/elf/libc-early-init.h b/elf/libc-early-init.h
index ac8c204bc7..a8edfadfb0 100644
--- a/elf/libc-early-init.h
+++ b/elf/libc-early-init.h
@@ -19,10 +19,13 @@
 #ifndef _LIBC_EARLY_INIT_H
 #define _LIBC_EARLY_INIT_H
 
-#include <libc_early_init_name.h>
-
 struct link_map;
 
+/* If LIBC_MAP is not NULL, look up the __libc_early_init symbol in it
+   and call this function, with INITIAL as the argument.  */
+void _dl_call_libc_early_init (struct link_map *libc_map, _Bool initial)
+  attribute_hidden;
+
 /* In the shared case, this function is defined in libc.so and invoked
    from ld.so (or on the fist static dlopen) after complete relocation
    of a new loaded libc.so, but before user-defined ELF constructors
@@ -30,18 +33,6 @@ struct link_map;
    startup code.  If INITIAL is true, the libc being initialized is
    the libc for the main program.  INITIAL is false for libcs loaded
    for audit modules, dlmopen, and static dlopen.  */
-void __libc_early_init (_Bool initial)
-#ifdef SHARED
-/* Redirect to the actual implementation name.  */
-  __asm__ (LIBC_EARLY_INIT_NAME_STRING)
-#endif
-  ;
-
-/* Attempts to find the appropriately named __libc_early_init function
-   in LIBC_MAP.  On lookup failure, an exception is signaled,
-   indicating an ld.so/libc.so mismatch.  */
-__typeof (__libc_early_init) *_dl_lookup_libc_early_init (struct link_map *
-                                                          libc_map)
-  attribute_hidden;
+void __libc_early_init (_Bool initial);
 
 #endif /* _LIBC_EARLY_INIT_H */
diff --git a/elf/rtld.c b/elf/rtld.c
index 910075c37f..cbbaf4a331 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -1707,6 +1707,15 @@ dl_main (const ElfW(Phdr) *phdr,
       /* Extract the contents of the dynamic section for easy access.  */
       elf_get_dynamic_info (main_map, false, false);
 
+      /* If the main map is libc.so, update the base namespace to
+	 refer to this map.  If libc.so is loaded later, this happens
+	 in _dl_map_object_from_fd.  */
+      if (main_map->l_info[DT_SONAME] != NULL
+	  && (strcmp (((const char *) D_PTR (main_map, l_info[DT_STRTAB])
+		      + main_map->l_info[DT_SONAME]->d_un.d_val), LIBC_SO)
+	      == 0))
+	GL(dl_ns)[LM_ID_BASE].libc_map = main_map;
+
       /* Set up our cache of pointers into the hash table.  */
       _dl_setup_hash (main_map);
     }
@@ -2377,8 +2386,7 @@ dl_main (const ElfW(Phdr) *phdr,
   /* Relocation is complete.  Perform early libc initialization.  This
      is the initial libc, even if audit modules have been loaded with
      other libcs.  */
-  if (GL(dl_ns)[LM_ID_BASE].libc_map != NULL)
-    GL(dl_ns)[LM_ID_BASE].libc_map_early_init (true);
+  _dl_call_libc_early_init (GL(dl_ns)[LM_ID_BASE].libc_map, true);
 
   /* Do any necessary cleanups for the startup OS interface code.
      We do these now so that no calls are made after rtld re-relocation