summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2021-01-31 11:46:00 +0100
committerAndreas Kling <kling@serenityos.org>2021-01-31 11:46:00 +0100
commite313323317ea06b4d86a2b037b88123f522ba5bd (patch)
tree3ecb7403a00cb5c0eaccea97ea29e1b37d3b4731 /Userland
parent36525c057207060ba0fda1b13011a5b86528c08b (diff)
downloadserenity-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.cpp5
-rw-r--r--Userland/Libraries/LibELF/DynamicLinker.cpp8
-rw-r--r--Userland/Libraries/LibELF/DynamicLoader.cpp14
-rw-r--r--Userland/Libraries/LibELF/DynamicLoader.h5
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);