diff --git a/options/rtdl/generic/linker.cpp b/options/rtdl/generic/linker.cpp index db03129a5c..b341d933dc 100644 --- a/options/rtdl/generic/linker.cpp +++ b/options/rtdl/generic/linker.cpp @@ -46,6 +46,7 @@ extern DebugInterface globalDebugInterface; extern uintptr_t __stack_chk_guard; extern frg::manual_box> libraryPaths; +extern frg::manual_box> preloads; #if MLIBC_STATIC_BUILD extern "C" size_t __init_array_start[]; @@ -759,6 +760,24 @@ void ObjectRepository::_parseDynamic(SharedObject *object) { void ObjectRepository::_discoverDependencies(SharedObject *object, Scope *localScope, uint64_t rts) { + if(object->isMainObject) { + for(auto preload : *preloads) { + frg::expected libraryResult; + if (preload.find_first('/') == size_t(-1)) { + libraryResult = requestObjectWithName(preload, object, globalScope.get(), false, 1); + } else { + libraryResult = requestObjectAtPath(preload, globalScope.get(), false, 1); + } + if(!libraryResult) + mlibc::panicLogger() << "rtdl: Could not load preload " << preload << frg::endlog; + + if(verbose) + mlibc::infoLogger() << "rtdl: Preloading " << preload << frg::endlog; + + object->dependencies.push_back(libraryResult.value()); + } + } + // Load required dynamic libraries. for(size_t i = 0; object->dynamic[i].d_tag != DT_NULL; i++) { elf_dyn *dynamic = &object->dynamic[i]; diff --git a/options/rtdl/generic/main.cpp b/options/rtdl/generic/main.cpp index 20a401e142..3cff1e44a9 100644 --- a/options/rtdl/generic/main.cpp +++ b/options/rtdl/generic/main.cpp @@ -51,6 +51,8 @@ frg::manual_box runtimeTlsMap; // We use a small vector of size 4 to avoid memory allocation for the default library paths frg::manual_box> libraryPaths; +frg::manual_box> preloads; + static SharedObject *executableSO; extern HIDDEN char __ehdr_start[]; @@ -203,34 +205,38 @@ extern "C" [[gnu::alias("dl_debug_state"), gnu::visibility("default")]] void _dl // This symbol can be used by GDB to find the global interface structure [[ gnu::visibility("default") ]] DebugInterface *_dl_debug_addr = &globalDebugInterface; -static void parseLibraryPaths(frg::string_view paths) { +static frg::vector parseList(frg::string_view paths, frg::string_view separators) { + frg::vector list{getAllocator()}; + size_t p = 0; while(p < paths.size()) { size_t s; // Offset of next colon or end of string. - if(size_t cs = paths.find_first(':', p); cs != size_t(-1)) { + if(size_t cs = paths.find_first_of(separators, p); cs != size_t(-1)) { s = cs; }else{ s = paths.size(); } - auto ldPath = paths.sub_string(p, s - p); + auto path = paths.sub_string(p, s - p); p = s + 1; - if(ldPath.size() == 0) + if(path.size() == 0) continue; - if(ldPath.ends_with("/")) { - size_t i = ldPath.size() - 1; - while(i > 0 && ldPath[i] == '/') + if(path.ends_with("/")) { + size_t i = path.size() - 1; + while(i > 0 && path[i] == '/') i--; - ldPath = ldPath.sub_string(0, i + 1); + path = path.sub_string(0, i + 1); } - if(ldPath == "/") - ldPath = ""; + if(path == "/") + path = ""; - libraryPaths->push_back(ldPath); + list.push_back(path); } + + return list; } extern "C" void *interpreterMain(uintptr_t *entry_stack) { @@ -239,6 +245,7 @@ extern "C" void *interpreterMain(uintptr_t *entry_stack) { entryStack = entry_stack; runtimeTlsMap.initialize(); libraryPaths.initialize(getAllocator()); + preloads.initialize(getAllocator()); void *phdr_pointer = 0; size_t phdr_entry_size = 0; @@ -323,7 +330,10 @@ extern "C" void *interpreterMain(uintptr_t *entry_stack) { if(name == "LD_SHOW_AUXV" && *value && *value != '0') { ldShowAuxv = true; }else if(name == "LD_LIBRARY_PATH" && *value) { - parseLibraryPaths(value); + for(auto path : parseList(value, ":;")) + libraryPaths->push_back(path); + }else if(name == "LD_PRELOAD" && *value) { + *preloads = parseList(value, " :"); } aux++;