diff options
author | Andreas Kling <kling@serenityos.org> | 2021-01-31 11:46:00 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-01-31 11:46:00 +0100 |
commit | e313323317ea06b4d86a2b037b88123f522ba5bd (patch) | |
tree | 3ecb7403a00cb5c0eaccea97ea29e1b37d3b4731 /Userland | |
parent | 36525c057207060ba0fda1b13011a5b86528c08b (diff) | |
download | serenity-e313323317ea06b4d86a2b037b88123f522ba5bd.zip |
LibELF: Split the DynamicLoader's loading mechanism into two steps
load_from_image() becomes map() and link(). This allows us to map
an object before mapping its dependencies.
This solves an issue where fixed-position executables (like GCC)
would clash with the ASLR placement of their own shared libraries.
Diffstat (limited to 'Userland')
-rw-r--r-- | Userland/Libraries/LibC/dlfcn.cpp | 5 | ||||
-rw-r--r-- | Userland/Libraries/LibELF/DynamicLinker.cpp | 8 | ||||
-rw-r--r-- | Userland/Libraries/LibELF/DynamicLoader.cpp | 14 | ||||
-rw-r--r-- | Userland/Libraries/LibELF/DynamicLoader.h | 5 |
4 files changed, 19 insertions, 13 deletions
diff --git a/Userland/Libraries/LibC/dlfcn.cpp b/Userland/Libraries/LibC/dlfcn.cpp index 2a52042804..49cd5b3930 100644 --- a/Userland/Libraries/LibC/dlfcn.cpp +++ b/Userland/Libraries/LibC/dlfcn.cpp @@ -88,9 +88,8 @@ void* dlopen(const char* filename, int flags) return nullptr; } - if (!loader->load_from_image(flags, - 0 // total_tls_size = 0, FIXME: Support TLS when using dlopen() - )) { + auto object = loader->map(); + if (!object || !loader->link(flags, /* total_tls_size (FIXME) */ 0)) { g_dlerror_msg = String::formatted("Failed to load ELF object {}", filename); return nullptr; } diff --git a/Userland/Libraries/LibELF/DynamicLinker.cpp b/Userland/Libraries/LibELF/DynamicLinker.cpp index 8fa91231fb..f3273ea87c 100644 --- a/Userland/Libraries/LibELF/DynamicLinker.cpp +++ b/Userland/Libraries/LibELF/DynamicLinker.cpp @@ -181,6 +181,10 @@ static void load_elf(const String& name) { dbgln<DYNAMIC_LOAD_DEBUG>("load_elf: {}", name); auto loader = g_loaders.get(name).value(); + + auto dynamic_object = loader->map(); + ASSERT(dynamic_object); + for (const auto& needed_name : get_dependencies(name)) { dbgln<DYNAMIC_LOAD_DEBUG>("needed library: {}", needed_name); String library_name = get_library_name(needed_name); @@ -189,8 +193,8 @@ static void load_elf(const String& name) } } - auto dynamic_object = loader->load_from_image(RTLD_GLOBAL | RTLD_LAZY, g_total_tls_size); - ASSERT(dynamic_object); + bool success = loader->link(RTLD_GLOBAL | RTLD_LAZY, g_total_tls_size); + ASSERT(success); g_loaded_objects.set(name, *dynamic_object); g_global_objects.append(*dynamic_object); diff --git a/Userland/Libraries/LibELF/DynamicLoader.cpp b/Userland/Libraries/LibELF/DynamicLoader.cpp index 261484c641..8dbd7a1bb2 100644 --- a/Userland/Libraries/LibELF/DynamicLoader.cpp +++ b/Userland/Libraries/LibELF/DynamicLoader.cpp @@ -143,12 +143,12 @@ void* DynamicLoader::symbol_for_name(const char* name) return m_dynamic_object->base_address().offset(symbol.value()).as_ptr(); } -RefPtr<DynamicObject> DynamicLoader::load_from_image(unsigned flags, size_t total_tls_size) +RefPtr<DynamicObject> DynamicLoader::map() { ASSERT(!m_dynamic_object); if (!m_valid) { - dbgln("DynamicLoader::load_from_image failed: image is invalid"); + dbgln("DynamicLoader::map failed: image is invalid"); return nullptr; } @@ -158,14 +158,14 @@ RefPtr<DynamicObject> DynamicLoader::load_from_image(unsigned flags, size_t tota m_dynamic_object->set_tls_offset(m_tls_offset); m_dynamic_object->set_tls_size(m_tls_size); - auto rc = load_stage_2(flags, total_tls_size); - if (!rc) { - dbgln("DynamicLoader::load_from_image failed at load_stage_2"); - return nullptr; - } return m_dynamic_object; } +bool DynamicLoader::link(unsigned flags, size_t total_tls_size) +{ + return load_stage_2(flags, total_tls_size); +} + bool DynamicLoader::load_stage_2(unsigned flags, size_t total_tls_size) { ASSERT(flags & RTLD_GLOBAL); diff --git a/Userland/Libraries/LibELF/DynamicLoader.h b/Userland/Libraries/LibELF/DynamicLoader.h index 896a7e2158..7a5aee3ba0 100644 --- a/Userland/Libraries/LibELF/DynamicLoader.h +++ b/Userland/Libraries/LibELF/DynamicLoader.h @@ -49,7 +49,10 @@ public: // Load a full ELF image from file into the current process and create an DynamicObject // from the SHT_DYNAMIC in the file. - RefPtr<DynamicObject> load_from_image(unsigned flags, size_t total_tls_size); + // Note that the DynamicObject will not be linked yet. Callers are responsible for calling link() to finish it. + RefPtr<DynamicObject> map(); + + bool link(unsigned flags, size_t total_tls_size); // Stage 2 of loading: dynamic object loading and primary relocations bool load_stage_2(unsigned flags, size_t total_tls_size); |