summaryrefslogtreecommitdiff
path: root/Userland/Libraries
diff options
context:
space:
mode:
authorTim Schumacher <timschumi@gmx.de>2022-02-18 19:22:45 +0100
committerLinus Groh <mail@linusgroh.de>2022-03-08 23:21:35 +0100
commite7f861f34cbfa160ce828b502722701a14ce0d4e (patch)
treebb8a8f4d47740f8ba765b7221cf8b10bb4d29c84 /Userland/Libraries
parent7bd0a3e9bac9bd7afd6e8c9fb2e9b87c56a7edea (diff)
downloadserenity-e7f861f34cbfa160ce828b502722701a14ce0d4e.zip
DynamicLinker: Implement support for RPATH and RUNPATH
Diffstat (limited to 'Userland/Libraries')
-rw-r--r--Userland/Libraries/LibELF/DynamicLinker.cpp46
1 files changed, 27 insertions, 19 deletions
diff --git a/Userland/Libraries/LibELF/DynamicLinker.cpp b/Userland/Libraries/LibELF/DynamicLinker.cpp
index 7c5e0c225d..fdacd398e4 100644
--- a/Userland/Libraries/LibELF/DynamicLinker.cpp
+++ b/Userland/Libraries/LibELF/DynamicLinker.cpp
@@ -101,7 +101,7 @@ static Result<NonnullRefPtr<DynamicLoader>, DlErrorMessage> map_library(const St
return loader;
}
-static Result<NonnullRefPtr<DynamicLoader>, DlErrorMessage> map_library(const String& name)
+static Result<NonnullRefPtr<DynamicLoader>, DlErrorMessage> map_library(String const& name, DynamicObject const& parent_object)
{
if (name.contains("/"sv)) {
int fd = open(name.characters(), O_RDONLY);
@@ -110,25 +110,29 @@ static Result<NonnullRefPtr<DynamicLoader>, DlErrorMessage> map_library(const St
return map_library(name, fd);
}
- // Scan the LD_LIBRARY_PATH environment variable if applicable
- if (s_ld_library_path != nullptr) {
- for (const auto& search_path : s_ld_library_path.split_view(':')) {
- LexicalPath library_path(search_path);
- int fd = open(library_path.append(name).string().characters(), O_RDONLY);
- if (fd < 0)
- continue;
- return map_library(name, fd);
- }
- }
+ Vector<StringView> search_paths;
+
+ // Search RPATH values indicated by the ELF (only if RUNPATH is not present).
+ if (parent_object.runpath().is_empty())
+ search_paths.extend(parent_object.rpath().split_view(':'));
+
+ // Scan the LD_LIBRARY_PATH environment variable if applicable.
+ search_paths.extend(s_ld_library_path.split_view(':'));
+
+ // Search RUNPATH values indicated by the ELF.
+ search_paths.extend(parent_object.runpath().split_view(':'));
+
+ // Last are the default search paths.
+ search_paths.append("/usr/lib"sv);
+ search_paths.append("/usr/local/lib"sv);
+
+ for (auto const& search_path : search_paths) {
+ LexicalPath library_path(search_path);
+ int fd = open(library_path.append(name).string().characters(), O_RDONLY);
- // Now check the default paths.
- // TODO: Do we want to also look for libs in other paths too?
- const char* search_paths[] = { "/usr/lib/{}", "/usr/local/lib/{}" };
- for (auto& search_path : search_paths) {
- auto path = String::formatted(search_path, name);
- int fd = open(path.characters(), O_RDONLY);
if (fd < 0)
continue;
+
return map_library(name, fd);
}
@@ -152,12 +156,14 @@ static Result<void, DlErrorMessage> map_dependencies(const String& name)
{
dbgln_if(DYNAMIC_LOAD_DEBUG, "mapping dependencies for: {}", name);
+ auto const& parent_object = (*s_loaders.get(name))->dynamic_object();
+
for (const auto& needed_name : get_dependencies(name)) {
dbgln_if(DYNAMIC_LOAD_DEBUG, "needed library: {}", needed_name.characters());
String library_name = get_library_name(needed_name);
if (!s_loaders.contains(library_name) && !s_global_objects.contains(library_name)) {
- auto result1 = map_library(needed_name);
+ auto result1 = map_library(needed_name, parent_object);
if (result1.is_error()) {
return result1.error();
}
@@ -415,7 +421,9 @@ static Result<void*, DlErrorMessage> __dlopen(const char* filename, int flags)
VERIFY(!library_name.is_empty());
- auto result1 = map_library(filename);
+ auto const& parent_object = **s_global_objects.get(get_library_name(s_main_program_name));
+
+ auto result1 = map_library(filename, parent_object);
if (result1.is_error()) {
return result1.error();
}