1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 19:07:35 +00:00

LibELF: Check if initializers ran instead of trusting s_global_objects

The original heuristic of "a library being in `s_global_objects` means
that it was fully initialized already" doesn't hold up anymore since we
changed the loading order. This was causing us to skip parts of the
initialization of dependency libraries when running dlopen (since it was
the only user of that setting).

Instead, set a flag after we run stage 4 (which is the "run the global
initializers" stage) and check that flag when determining unfinished
dependencies. This entirely replaces the `skip_global_objects` logic.
This commit is contained in:
Tim Schumacher 2022-06-24 10:50:34 +02:00 committed by Linus Groh
parent ef1c97e3d8
commit 082a7baa3b
3 changed files with 18 additions and 10 deletions

View file

@ -292,12 +292,14 @@ static void initialize_libc(DynamicObject& libc)
}
template<typename Callback>
static void for_each_unfinished_dependency_of(String const& name, HashTable<String>& seen_names, bool first, bool skip_global_objects, Callback callback)
static void for_each_unfinished_dependency_of(String const& name, HashTable<String>& seen_names, Callback callback)
{
if (!s_loaders.contains(name))
auto loader = s_loaders.get(name);
if (!loader.has_value())
return;
if (!first && skip_global_objects && s_global_objects.contains(name))
if (loader.value()->is_fully_initialized())
return;
if (seen_names.contains(name))
@ -305,24 +307,24 @@ static void for_each_unfinished_dependency_of(String const& name, HashTable<Stri
seen_names.set(name);
for (auto const& needed_name : get_dependencies(name))
for_each_unfinished_dependency_of(get_library_name(needed_name), seen_names, false, skip_global_objects, callback);
for_each_unfinished_dependency_of(get_library_name(needed_name), seen_names, callback);
callback(*s_loaders.get(name).value());
}
static NonnullRefPtrVector<DynamicLoader> collect_loaders_for_library(String const& name, bool skip_global_objects)
static NonnullRefPtrVector<DynamicLoader> collect_loaders_for_library(String const& name)
{
HashTable<String> seen_names;
NonnullRefPtrVector<DynamicLoader> loaders;
for_each_unfinished_dependency_of(name, seen_names, true, skip_global_objects, [&](auto& loader) {
for_each_unfinished_dependency_of(name, seen_names, [&](auto& loader) {
loaders.append(loader);
});
return loaders;
}
static Result<void, DlErrorMessage> link_main_library(String const& name, int flags, bool skip_global_objects)
static Result<void, DlErrorMessage> link_main_library(String const& name, int flags)
{
auto loaders = collect_loaders_for_library(name, skip_global_objects);
auto loaders = collect_loaders_for_library(name);
for (auto& loader : loaders) {
auto dynamic_object = loader.map();
@ -447,7 +449,7 @@ static Result<void*, DlErrorMessage> __dlopen(char const* filename, int flags)
return result2.error();
}
auto result = link_main_library(library_name, flags, true);
auto result = link_main_library(library_name, flags);
if (result.is_error())
return result.error();
@ -583,7 +585,7 @@ void ELF::DynamicLinker::linker_main(String&& main_program_name, int main_progra
auto entry_point_function = [&main_program_name] {
auto library_name = get_library_name(main_program_name);
auto result = link_main_library(library_name, RTLD_GLOBAL | RTLD_LAZY, false);
auto result = link_main_library(library_name, RTLD_GLOBAL | RTLD_LAZY);
if (result.is_error()) {
warnln("{}", result.error().text);
_exit(1);