DynamicLoader: Add support for LD_LIBRARY_PATH

Also fix a bug with dlopen with TLS
This commit is contained in:
Bananymous 2025-07-31 22:12:05 +03:00
parent c1978f9133
commit 7831c74e8c
1 changed files with 38 additions and 7 deletions

View File

@ -195,6 +195,8 @@ struct LoadedElf
static LoadedElf s_loaded_files[128]; static LoadedElf s_loaded_files[128];
static size_t s_loaded_file_count = 0; static size_t s_loaded_file_count = 0;
static const char* s_ld_library_path = nullptr;
constexpr uintptr_t SYM_NOT_FOUND = -1; constexpr uintptr_t SYM_NOT_FOUND = -1;
static uint32_t elf_hash(const char* name) static uint32_t elf_hash(const char* name)
@ -717,16 +719,15 @@ uintptr_t resolve_symbol(const LoadedElf& elf, uintptr_t plt_entry)
static LoadedElf& load_elf(const char* path, int fd); static LoadedElf& load_elf(const char* path, int fd);
static bool find_library(const char* library_name, char out[PATH_MAX]) static bool check_library(const char* library_dir, const char* library_name, char out[PATH_MAX])
{ {
const char* library_dir = "/usr/lib/";
char path_buffer[PATH_MAX]; char path_buffer[PATH_MAX];
char* path_ptr = path_buffer; char* path_ptr = path_buffer;
if (library_name[0] != '/') if (library_name[0] != '/')
for (size_t i = 0; library_dir[i]; i++) for (size_t i = 0; library_dir[i]; i++)
*path_ptr++ = library_dir[i]; *path_ptr++ = library_dir[i];
*path_ptr++ = '/';
for (size_t i = 0; library_name[i]; i++) for (size_t i = 0; library_name[i]; i++)
*path_ptr++ = library_name[i]; *path_ptr++ = library_name[i];
*path_ptr = '\0'; *path_ptr = '\0';
@ -734,6 +735,15 @@ static bool find_library(const char* library_name, char out[PATH_MAX])
return syscall(SYS_REALPATH, path_buffer, out) >= 0; return syscall(SYS_REALPATH, path_buffer, out) >= 0;
} }
static bool find_library(const char* library_name, char out[PATH_MAX])
{
if (s_ld_library_path && check_library(s_ld_library_path, library_name, out))
return true;
if (check_library("/usr/lib", library_name, out))
return true;
return false;
}
static void handle_dynamic(LoadedElf& elf) static void handle_dynamic(LoadedElf& elf)
{ {
uintptr_t pltgot = 0; uintptr_t pltgot = 0;
@ -798,7 +808,10 @@ static void handle_dynamic(LoadedElf& elf)
char path_buffer[PATH_MAX]; char path_buffer[PATH_MAX];
if (!find_library(library_name, path_buffer)) if (!find_library(library_name, path_buffer))
print_error_and_exit("could not open shared object", 0); {
print(STDERR_FILENO, "could not open shared object: ");
print_error_and_exit(library_name, 0);
}
const auto& loaded_elf = load_elf(path_buffer, -1); const auto& loaded_elf = load_elf(path_buffer, -1);
dynamic.d_un.d_ptr = reinterpret_cast<uintptr_t>(&loaded_elf); dynamic.d_un.d_ptr = reinterpret_cast<uintptr_t>(&loaded_elf);
@ -1346,16 +1359,21 @@ void* __dlopen(const char* file, int mode)
return nullptr; return nullptr;
} }
const size_t old_loaded_count = s_loaded_file_count;
init_random(); init_random();
auto& elf = load_elf(path_buffer, -1); auto& elf = load_elf(path_buffer, -1);
fini_random(); fini_random();
if (!elf.is_relocating && !elf.is_calling_init) if (!elf.is_relocating && !elf.is_calling_init)
{ {
if (elf.tls_header.p_type == PT_TLS) for (size_t i = old_loaded_count + 1; i < s_loaded_file_count; i++)
{ {
s_dlerror_string = "TODO: __dlopen with TLS"; if (s_loaded_files[i].tls_header.p_type == PT_TLS)
return nullptr; {
s_dlerror_string = "TODO: __dlopen with TLS";
return nullptr;
}
} }
relocate_elf(elf, lazy); relocate_elf(elf, lazy);
@ -1399,10 +1417,23 @@ static LibELF::AuxiliaryVector* find_auxv(char** envp)
return reinterpret_cast<LibELF::AuxiliaryVector*>(null_env + 1); return reinterpret_cast<LibELF::AuxiliaryVector*>(null_env + 1);
} }
static bool starts_with(const char* string, const char* comp)
{
size_t i = 0;
for (; string[i] && comp[i]; i++)
if (string[i] != comp[i])
return false;
return comp[i] == '\0';
}
extern "C" extern "C"
__attribute__((used)) __attribute__((used))
uintptr_t _entry(int argc, char* argv[], char* envp[]) uintptr_t _entry(int argc, char* argv[], char* envp[])
{ {
for (size_t i = 0; envp[i]; i++)
if (starts_with(envp[i], "LD_LIBRARY_PATH="))
s_ld_library_path = envp[i] + 16;
int execfd = -1; int execfd = -1;
if (auto* auxv = find_auxv(envp)) if (auto* auxv = find_auxv(envp))
for (auto* aux = auxv; aux->a_type != LibELF::AT_NULL; aux++) for (auto* aux = auxv; aux->a_type != LibELF::AT_NULL; aux++)