Skip to content

Commit

Permalink
Merge pull request #999 from Qwinci/ld-preload
Browse files Browse the repository at this point in the history
  • Loading branch information
Dennisbonke authored Feb 17, 2024
2 parents 4a9f0e2 + 91d8a7b commit 429765b
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 12 deletions.
19 changes: 19 additions & 0 deletions options/rtdl/generic/linker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ extern DebugInterface globalDebugInterface;
extern uintptr_t __stack_chk_guard;

extern frg::manual_box<frg::small_vector<frg::string_view, 4, MemoryAllocator>> libraryPaths;
extern frg::manual_box<frg::vector<frg::string_view, MemoryAllocator>> preloads;

#if MLIBC_STATIC_BUILD
extern "C" size_t __init_array_start[];
Expand Down Expand Up @@ -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<LinkerError, SharedObject *> 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];
Expand Down
34 changes: 22 additions & 12 deletions options/rtdl/generic/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ frg::manual_box<RuntimeTlsMap> runtimeTlsMap;
// We use a small vector of size 4 to avoid memory allocation for the default library paths
frg::manual_box<frg::small_vector<frg::string_view, 4, MemoryAllocator>> libraryPaths;

frg::manual_box<frg::vector<frg::string_view, MemoryAllocator>> preloads;

static SharedObject *executableSO;
extern HIDDEN char __ehdr_start[];

Expand Down Expand Up @@ -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<frg::string_view, MemoryAllocator> parseList(frg::string_view paths, frg::string_view separators) {
frg::vector<frg::string_view, MemoryAllocator> 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) {
Expand All @@ -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;
Expand Down Expand Up @@ -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++;
Expand Down

0 comments on commit 429765b

Please sign in to comment.