From ec935dea6332cb22f9881cd1162bad156173f4b0 Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Fri, 24 Apr 2020 22:31:15 +0200 Subject: elf: Implement __libc_early_init 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. Reviewed-by: Carlos O'Donell --- sysdeps/generic/ldsodefs.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'sysdeps/generic') diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index 497938ffa2..5ff4a2831b 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -336,6 +336,10 @@ struct rtld_global recursive dlopen calls from ELF constructors. */ unsigned int _ns_global_scope_pending_adds; + /* Once libc.so has been loaded into the namespace, this points to + its link map. */ + struct link_map *libc_map; + /* Search table for unique objects. */ struct unique_sym_table { @@ -946,6 +950,19 @@ extern lookup_t _dl_lookup_symbol_x (const char *undef, attribute_hidden; +/* Restricted version of _dl_lookup_symbol_x. Searches MAP (and only + MAP) for the symbol UNDEF_NAME, with GNU hash NEW_HASH (computed + with dl_new_hash), symbol version VERSION, and symbol version hash + VERSION_HASH (computed with _dl_elf_hash). Returns a pointer to + the symbol table entry in MAP on success, or NULL on failure. MAP + must have symbol versioning information, or otherwise the result is + undefined. */ +const ElfW(Sym) *_dl_lookup_direct (struct link_map *map, + const char *undef_name, + uint32_t new_hash, + const char *version, + uint32_t version_hash) attribute_hidden; + /* Add the new link_map NEW to the end of the namespace list. */ extern void _dl_add_to_namespace_list (struct link_map *new, Lmid_t nsid) attribute_hidden; -- cgit 1.4.1