From 6f1a458c8af7dcb47e38fd1f48a8e6f99992bece Mon Sep 17 00:00:00 2001 From: baldurk Date: Thu, 27 Sep 2018 11:38:27 +0100 Subject: [PATCH] If a non-global dlopen happens, check for loaded libraries. Closes #1114 --- renderdoc/os/posix/linux/linux_hook.cpp | 56 +++++++++++++++---------- 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/renderdoc/os/posix/linux/linux_hook.cpp b/renderdoc/os/posix/linux/linux_hook.cpp index f7345c09f..1f6478f0a 100644 --- a/renderdoc/os/posix/linux/linux_hook.cpp +++ b/renderdoc/os/posix/linux/linux_hook.cpp @@ -83,6 +83,33 @@ void plthook_lib(void *handle) plthook_close(plthook); } +static void CheckLoadedLibraries() +{ + // iterate over the libraries and see which ones are already loaded, process function hooks for + // them and call callbacks. + for(auto it = libraryHooks.begin(); it != libraryHooks.end(); ++it) + { + std::string libName = *it; + void *handle = realdlopen(libName.c_str(), RTLD_NOW | RTLD_NOLOAD | RTLD_GLOBAL); + + if(handle) + { + for(FunctionHook &hook : functionHooks) + { + if(hook.orig && *hook.orig == NULL) + *hook.orig = dlsym(handle, hook.function.c_str()); + } + + for(FunctionLoadCallback cb : libraryCallbacks[libName]) + if(cb) + cb(handle); + + // don't call callbacks again if the library is dlopen'd again + libraryCallbacks[libName].clear(); + } + } +} + void *intercept_dlopen(const char *filename, int flag, void *ret) { if(filename == NULL) @@ -118,6 +145,11 @@ void *intercept_dlopen(const char *filename, int flag, void *ret) } } + // for local library loads, this library might depend on one we care about, so check again as we + // did in EndHookRegistration to see if any library has been loaded. + if((flag & RTLD_GLOBAL) == 0) + CheckLoadedLibraries(); + return ret; } @@ -138,29 +170,7 @@ void LibraryHooks::RemoveHooks() void LibraryHooks::EndHookRegistration() { - // iterate over the libraries and see which ones are already loaded, process function hooks for - // them and call callbacks. - for(auto it = libraryHooks.begin(); it != libraryHooks.end(); ++it) - { - std::string libName = *it; - void *handle = realdlopen(libName.c_str(), RTLD_NOW | RTLD_NOLOAD | RTLD_GLOBAL); - - if(handle) - { - for(FunctionHook &hook : functionHooks) - { - if(hook.orig && *hook.orig == NULL) - *hook.orig = dlsym(handle, hook.function.c_str()); - } - - for(FunctionLoadCallback cb : libraryCallbacks[libName]) - if(cb) - cb(handle); - - // don't call callbacks again if the library is dlopen'd again - libraryCallbacks[libName].clear(); - } - } + CheckLoadedLibraries(); } void LibraryHooks::Refresh()