about summary refs log tree commit diff
path: root/elf/libc-early-init.h
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2019-10-11 16:11:21 +0200
committerFlorian Weimer <fweimer@redhat.com>2019-11-28 14:28:44 +0100
commit64afc586195fd8dfefd40f60db4e9bead983dbff (patch)
treeeaddace5e977bf7d6e465fd4a3f095d1245bf7e4 /elf/libc-early-init.h
parent5f53b8777bfaab2afbc56ecc2a223d7167314e83 (diff)
downloadglibc-fw/libc-early-init-2.tar.gz
glibc-fw/libc-early-init-2.tar.xz
glibc-fw/libc-early-init-2.zip
Implement __libc_early_init fw/libc-early-init-2
This function is defined in libc.so, and the dynamic loader calls
right after relocation has been finished, before any ELF constructors
or the preinit function is invoked.  It is also used in the static
build for initializing parts of the static libc.

To locate __libc_early_init, a direct symbol lookup function is used,
_dl_lookup_direct.  It does not search the entire symbol scope and
consults merely a single link map.  This function could also be used
to implement lookups in the vDSO (as an optimization).

A per-namespace variable (libc_map) is added for locating libc.so,
to avoid repeated traversals of the search scope.  It is similar to
GL(dl_initfirst).  An alternative would have been to thread a context
argument from _dl_open down to _dl_map_object_from_fd (where libc.so
is identified).  This could have avoided the global variable, but
the change would be larger as a result.  It would not have been
possible to use this to replace GL(dl_initfirst) because that global
variable is used to pass the function pointer past the stack switch
from dl_main to the main program.  Replacing that requires adding
a new argument to _dl_init, which in turn needs changes to the
architecture-specific libc.so startup code written in assembler.

__libc_early_init should not be used to replace _dl_var_init (as
it exists today on some architectures).  Instead, _dl_lookup_direct
should be used to look up a new variable symbol in libc.so, and
that should then be initialized from the dynamic loader, immediately
after the object has been loaded in _dl_map_object_from_fd (before
relocation is run).  This way, more IFUNC resolvers which depend on
these variables will work.
Diffstat (limited to 'elf/libc-early-init.h')
-rw-r--r--elf/libc-early-init.h35
1 files changed, 35 insertions, 0 deletions
diff --git a/elf/libc-early-init.h b/elf/libc-early-init.h
new file mode 100644
index 0000000000..02b855754e
--- /dev/null
+++ b/elf/libc-early-init.h
@@ -0,0 +1,35 @@
+/* Early initialization of libc.so.
+   Copyright (C) 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
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _LIBC_EARLY_INIT_H
+#define _LIBC_EARLY_INIT_H
+
+struct link_map;
+
+/* If LIBC_MAP is not NULL, look up the __libc_early_init symbol in it
+   and call this function.  */
+void _dl_call_libc_early_init (struct link_map *libc_map) 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
+   run.  In the static case, this function is called directly from the
+   startup code.  */
+void __libc_early_init (void);
+
+#endif /* _LIBC_EARLY_INIT_H */