From f9d03761b378aaa4640619078b0f3248bbb5996d Mon Sep 17 00:00:00 2001 From: baldurk Date: Wed, 16 Apr 2025 12:08:39 +0100 Subject: [PATCH] Avoid libraries loading and unloading for GL hooks on windows * This can cause the hooks to get out of sync if the libraries move between loads, so should be avoided. Most applications won't do this anyway. --- renderdoc/driver/gl/egl_hooks.cpp | 7 ++++++- renderdoc/driver/gl/gl_hooks.cpp | 7 ++++++- renderdoc/driver/gl/wgl_hooks.cpp | 5 ++++- renderdoc/hooks/hooks.h | 2 +- renderdoc/os/posix/android/android_hook.cpp | 2 +- renderdoc/os/posix/apple/apple_hook.cpp | 2 +- renderdoc/os/posix/linux/linux_hook.cpp | 4 ++-- renderdoc/os/win32/win32_hook.cpp | 2 +- 8 files changed, 22 insertions(+), 9 deletions(-) diff --git a/renderdoc/driver/gl/egl_hooks.cpp b/renderdoc/driver/gl/egl_hooks.cpp index 9ad1c01a3..ef735d878 100644 --- a/renderdoc/driver/gl/egl_hooks.cpp +++ b/renderdoc/driver/gl/egl_hooks.cpp @@ -969,7 +969,7 @@ EGL_PASSTHRU_4(EGLSurface, eglCreatePlatformPixmapSurface, EGLDisplay, dpy, EGLC void *, native_pixmap, const EGLAttrib *, attrib_list) EGL_PASSTHRU_3(EGLBoolean, eglWaitSync, EGLDisplay, dpy, EGLSync, sync, EGLint, flags) -static void EGLHooked(void *handle) +static void EGLHooked(void *handle, const char *libName) { RDCDEBUG("EGL library hooked"); @@ -1013,6 +1013,11 @@ static void EGLHooked(void *handle) ScopedSuppressHooking suppress; return (void *)EGL.GetProcAddress(funcName); }); + +#if ENABLED(RDOC_WIN32) + // force library to stay loaded so that function pointers don't move + LoadLibraryA(libName); +#endif } #if ENABLED(RDOC_WIN32) diff --git a/renderdoc/driver/gl/gl_hooks.cpp b/renderdoc/driver/gl/gl_hooks.cpp index 1ab2955f2..5400ece42 100644 --- a/renderdoc/driver/gl/gl_hooks.cpp +++ b/renderdoc/driver/gl/gl_hooks.cpp @@ -259,11 +259,16 @@ void GLDispatchTable::PopulateWithCallback(PlatformGetProcAddr lookupFunc) ForEachSupported(HookFunc); } -static void GLHooked(void *handle) +static void GLHooked(void *handle, const char *libName) { // store the handle for any unimplemented functions that need to look up their onward // pointers glhook.handle = handle; + +#if ENABLED(RDOC_WIN32) + // force library to stay loaded so that function pointers don't move + LoadLibraryA(libName); +#endif } void GLHook::RegisterHooks() diff --git a/renderdoc/driver/gl/wgl_hooks.cpp b/renderdoc/driver/gl/wgl_hooks.cpp index 6abbb4bc1..ad09622f6 100644 --- a/renderdoc/driver/gl/wgl_hooks.cpp +++ b/renderdoc/driver/gl/wgl_hooks.cpp @@ -634,7 +634,7 @@ static PROC WINAPI wglGetProcAddress_hooked(const char *func) return (PROC)HookedGetProcAddress(func, (void *)realFunc); } -static void WGLHooked(void *handle) +static void WGLHooked(void *handle, const char *libName) { RDCDEBUG("WGL library hooked"); @@ -647,6 +647,9 @@ static void WGLHooked(void *handle) WGL_NONHOOKED_SYMBOLS(WGL_FETCH) #undef WGL_FETCH + // force library to stay loaded so that function pointers don't move + LoadLibraryA(libName); + // maybe in future we could create a dummy context here and populate the GL hooks already? } diff --git a/renderdoc/hooks/hooks.h b/renderdoc/hooks/hooks.h index b42a55505..19507f142 100644 --- a/renderdoc/hooks/hooks.h +++ b/renderdoc/hooks/hooks.h @@ -27,7 +27,7 @@ #include "os/os_specific.h" -typedef std::function FunctionLoadCallback; +typedef std::function FunctionLoadCallback; struct FunctionHook { diff --git a/renderdoc/os/posix/android/android_hook.cpp b/renderdoc/os/posix/android/android_hook.cpp index 0d9c05001..4f0a73840 100644 --- a/renderdoc/os/posix/android/android_hook.cpp +++ b/renderdoc/os/posix/android/android_hook.cpp @@ -810,7 +810,7 @@ void LibraryHooks::EndHookRegistration() HOOK_DEBUG_PRINT("Calling callbacks for %s", it->first.c_str()); for(FunctionLoadCallback callback : it->second) if(callback) - callback(handle); + callback(handle, it->first.c_str()); } } diff --git a/renderdoc/os/posix/apple/apple_hook.cpp b/renderdoc/os/posix/apple/apple_hook.cpp index 7080e1ea1..a43223dca 100644 --- a/renderdoc/os/posix/apple/apple_hook.cpp +++ b/renderdoc/os/posix/apple/apple_hook.cpp @@ -118,7 +118,7 @@ void LibraryHooks::EndHookRegistration() { for(FunctionLoadCallback cb : it->second) if(cb) - cb(handle); + cb(handle, libName.c_str()); // don't call callbacks again if the library is dlopen'd again it->second.clear(); diff --git a/renderdoc/os/posix/linux/linux_hook.cpp b/renderdoc/os/posix/linux/linux_hook.cpp index a8ea8ec0b..cf97cd6da 100644 --- a/renderdoc/os/posix/linux/linux_hook.cpp +++ b/renderdoc/os/posix/linux/linux_hook.cpp @@ -500,7 +500,7 @@ static void CheckLoadedLibraries() for(FunctionLoadCallback cb : callbacks) if(cb) - cb(handle); + cb(handle, libName.c_str()); } } @@ -542,7 +542,7 @@ void *intercept_dlopen(const char *filename, int flag, void *ret) for(FunctionLoadCallback cb : callbacks) if(cb) - cb(ret); + cb(ret, libName.c_str()); ret = realdlopen("lib" STRINGIZE(RDOC_BASE_NAME) ".so", flag); break; diff --git a/renderdoc/os/win32/win32_hook.cpp b/renderdoc/os/win32/win32_hook.cpp index d66874639..cd48899c8 100644 --- a/renderdoc/os/win32/win32_hook.cpp +++ b/renderdoc/os/win32/win32_hook.cpp @@ -598,7 +598,7 @@ static void HookAllModules() for(FunctionLoadCallback cb : callbacks) if(cb) - cb(it->second.module); + cb(it->second.module, it->first.c_str()); } Atomic::CmpExch32(&s_HookData->posthooking, 1, 0);