From dda4875f1c19782078268d9e50147d92c5e701b8 Mon Sep 17 00:00:00 2001 From: Etaash Mathamsetty Date: Thu, 26 Dec 2024 16:35:00 -0500 Subject: [PATCH] Move dlsym code to shim --- README.md | 4 +- bin/mangohud-setup.sh | 4 +- bin/mangohud.in | 7 -- build.sh | 2 - src/{elfhacks.cpp => elfhacks.c} | 2 +- src/gl/gl.h | 3 +- src/gl/shim.c | 118 ++++++++++++++++++++++++--- src/hook_dlsym.cpp | 39 --------- src/meson.build | 31 ++----- src/{real_dlsym.cpp => real_dlsym.c} | 23 +++--- src/real_dlsym.h | 6 ++ 11 files changed, 138 insertions(+), 101 deletions(-) rename src/{elfhacks.cpp => elfhacks.c} (99%) delete mode 100644 src/hook_dlsym.cpp rename src/{real_dlsym.cpp => real_dlsym.c} (82%) diff --git a/README.md b/README.md index f9134f8227..be89ccc516 100644 --- a/README.md +++ b/README.md @@ -279,7 +279,7 @@ Or alternatively, add `MANGOHUD=1` to your shell profile (Vulkan only). ## OpenGL -OpenGL games may also need `dlsym` hooking. Add `--dlsym` to your command like `mangohud --dlsym %command%` for Steam. +OpenGL games may also need `dlsym` hooking, which is now enabled by default. Set the `MANGOHUD_DLSYM` env to `0` to disable like `MANGOHUD_DLSYM=0 %command%` for Steam. Some Linux native OpenGL games overrides LD_PRELOAD and stops MangoHud from working. You can sometimes fix this by editing LD_PRELOAD in the start script `LD_PRELOAD=/path/to/mangohud/lib/` @@ -321,6 +321,8 @@ You can also specify configuration file with `MANGOHUD_CONFIGFILE=/path/to/confi You can also specify presets file with `MANGOHUD_PRESETSFILE=/path/to/config`. This is especially useful when running mangohud in a sandbox such as flatpak. +You can also specify custom hud libraries using `MANGOHUD_OPENGL_LIBS=/path/to/libMangoHud_opengl.so`. This is useful for testing MangoHud without modifying the installation on your system. + A partial list of parameters are below. See the config file for a complete list. Parameters that are enabled by default have to be explicitly disabled. These (currently) are `fps`, `frame_timing`, `cpu_stats` (cpu load), `gpu_stats` (gpu load), and each can be disabled by setting the corresponding variable to 0 (e.g., fps=0). diff --git a/bin/mangohud-setup.sh b/bin/mangohud-setup.sh index 66ec66ccb1..0f82b11556 100755 --- a/bin/mangohud-setup.sh +++ b/bin/mangohud-setup.sh @@ -63,11 +63,11 @@ mangohud_install() { echo DEFAULTLIB: $DEFAULTLIB /usr/bin/install -Dvm644 ./usr/lib/mangohud/lib64/libMangoHud.so /usr/lib/mangohud/lib64/libMangoHud.so - /usr/bin/install -Dvm644 ./usr/lib/mangohud/lib64/libMangoHud_dlsym.so /usr/lib/mangohud/lib64/libMangoHud_dlsym.so /usr/bin/install -Dvm644 ./usr/lib/mangohud/lib32/libMangoHud.so /usr/lib/mangohud/lib32/libMangoHud.so - /usr/bin/install -Dvm644 ./usr/lib/mangohud/lib32/libMangoHud_dlsym.so /usr/lib/mangohud/lib32/libMangoHud_dlsym.so /usr/bin/install -Dvm644 ./usr/lib/mangohud/lib64/libMangoHud_opengl.so /usr/lib/mangohud/lib64/libMangoHud_opengl.so /usr/bin/install -Dvm644 ./usr/lib/mangohud/lib32/libMangoHud_opengl.so /usr/lib/mangohud/lib32/libMangoHud_opengl.so + /usr/bin/install -Dvm644 ./usr/lib/mangohud/lib64/libMangoHud_shim.so /usr/lib/mangohud/lib64/libMangoHud_shim.so + /usr/bin/install -Dvm644 ./usr/lib/mangohud/lib32/libMangoHud_shim.so /usr/lib/mangohud/lib32/libMangoHud_shim.so /usr/bin/install -Dvm644 ./usr/share/vulkan/implicit_layer.d/MangoHud.x86_64.json /usr/share/vulkan/implicit_layer.d/MangoHud.x86_64.json /usr/bin/install -Dvm644 ./usr/share/vulkan/implicit_layer.d/MangoHud.x86.json /usr/share/vulkan/implicit_layer.d/MangoHud.x86.json /usr/bin/install -Dvm644 ./usr/share/man/man1/mangohud.1 /usr/share/man/man1/mangohud.1 diff --git a/bin/mangohud.in b/bin/mangohud.in index 76b678726e..a04d36f56f 100755 --- a/bin/mangohud.in +++ b/bin/mangohud.in @@ -15,13 +15,6 @@ DISABLE_LD_PRELOAD="cs2.sh MANGOHUD_LIB_NAME="@ld_libdir_mangohud@libMangoHud_shim.so" -if [ "$1" = "--dlsym" ]; then - MANGOHUD_LIB_NAME="@ld_libdir_mangohud@libMangoHud_dlsym.so:${MANGOHUD_LIB_NAME}" - shift # shift will only be executed if $1 is "--dlsym" -elif [ "$MANGOHUD_DLSYM" = "1" ]; then - MANGOHUD_LIB_NAME="@ld_libdir_mangohud@libMangoHud_dlsym.so:${MANGOHUD_LIB_NAME}" -fi - if [ "$1" = "--version" ]; then echo @version@ exit 0 diff --git a/build.sh b/build.sh index c88fb2508a..70310cddf2 100755 --- a/build.sh +++ b/build.sh @@ -225,12 +225,10 @@ install() { echo DEFAULTLIB: $DEFAULTLIB /usr/bin/install -Dvm644 ./build/release/usr/lib/mangohud/lib64/libMangoHud.so /usr/lib/mangohud/lib64/libMangoHud.so - /usr/bin/install -Dvm644 ./build/release/usr/lib/mangohud/lib64/libMangoHud_dlsym.so /usr/lib/mangohud/lib64/libMangoHud_dlsym.so /usr/bin/install -Dvm644 ./build/release/usr/lib/mangohud/lib64/libMangoHud_opengl.so /usr/lib/mangohud/lib64/libMangoHud_opengl.so /usr/bin/install -Dvm644 ./build/release/usr/lib/mangohud/lib64/libMangoHud_shim.so /usr/lib/mangohud/lib64/libMangoHud_shim.so if [ "$MACHINE" = "x86_64" ]; then /usr/bin/install -Dvm644 ./build/release/usr/lib/mangohud/lib32/libMangoHud.so /usr/lib/mangohud/lib32/libMangoHud.so - /usr/bin/install -Dvm644 ./build/release/usr/lib/mangohud/lib32/libMangoHud_dlsym.so /usr/lib/mangohud/lib32/libMangoHud_dlsym.so /usr/bin/install -Dvm644 ./build/release/usr/lib/mangohud/lib32/libMangoHud_opengl.so /usr/lib/mangohud/lib32/libMangoHud_opengl.so /usr/bin/install -Dvm644 ./build/release/usr/lib/mangohud/lib32/libMangoHud_shim.so /usr/lib/mangohud/lib32/libMangoHud_shim.so fi diff --git a/src/elfhacks.cpp b/src/elfhacks.c similarity index 99% rename from src/elfhacks.cpp rename to src/elfhacks.c index 67da329927..d0dbcfff36 100644 --- a/src/elfhacks.cpp +++ b/src/elfhacks.c @@ -83,7 +83,7 @@ int eh_find_callback(struct dl_phdr_info *info, size_t size, void *argptr) int eh_iterate_callback(struct dl_phdr_info *info, size_t size, void *argptr) { - struct eh_iterate_callback_args *args = (eh_iterate_callback_args *)argptr; + struct eh_iterate_callback_args *args = argptr; eh_obj_t obj; int ret = 0; diff --git a/src/gl/gl.h b/src/gl/gl.h index f548fe2623..1104c4b643 100644 --- a/src/gl/gl.h +++ b/src/gl/gl.h @@ -24,8 +24,9 @@ int glXQueryDrawable(void *dpy, void* glxdraw, int attr, unsigned int * value); int64_t glXSwapBuffersMscOML(void* dpy, void* drawable, int64_t target_msc, int64_t divisor, int64_t remainder); unsigned int eglSwapBuffers( void*, void* ); -void* eglGetPlatformDisplay( unsigned int, void*, const intptr_t*); +void* eglGetPlatformDisplay( unsigned int, void*, const intptr_t* ); void* eglGetDisplay( void* ); +void* eglGetProcAddress( const char* ); #ifdef __cplusplus } diff --git a/src/gl/shim.c b/src/gl/shim.c index 608110eca5..f1f32bdeed 100644 --- a/src/gl/shim.c +++ b/src/gl/shim.c @@ -2,6 +2,7 @@ #include #include #include "gl.h" +#include "real_dlsym.h" #include #include #include @@ -27,7 +28,7 @@ static void loadMangoHud() { while (lib != NULL) { - handle = dlopen(lib, RTLD_LAZY | RTLD_LOCAL | RTLD_DEEPBIND); + handle = dlopen(lib, RTLD_NOW | RTLD_LOCAL | RTLD_DEEPBIND); if (handle) { @@ -42,7 +43,7 @@ static void loadMangoHud() { if (!mangoHudLoaded) { - handle = dlopen("${ORIGIN}/libMangoHud_opengl.so", RTLD_LAZY | RTLD_LOCAL | RTLD_DEEPBIND); + handle = dlopen("${ORIGIN}/libMangoHud_opengl.so", RTLD_NOW | RTLD_LOCAL | RTLD_DEEPBIND); if (handle) mangoHudLoaded = true; } } @@ -50,11 +51,11 @@ static void loadMangoHud() { void glXSwapBuffers(void* dpy, void* drawable) { loadMangoHud(); - void (*pglXSwapBuffers)(void*, void*) = dlsym(handle, "glXSwapBuffers"); + void (*pglXSwapBuffers)(void*, void*) = real_dlsym(handle, "glXSwapBuffers"); if (pglXSwapBuffers) { pglXSwapBuffers(dpy, drawable); } else { - pglXSwapBuffers = dlsym(RTLD_NEXT, "glXSwapBuffers"); + pglXSwapBuffers = real_dlsym(RTLD_NEXT, "glXSwapBuffers"); if (pglXSwapBuffers) pglXSwapBuffers(dpy, drawable); } @@ -63,11 +64,11 @@ void glXSwapBuffers(void* dpy, void* drawable) { void* eglGetDisplay(void *native_dpy) { loadMangoHud(); - void* (*peglGetDisplay)(void*) = dlsym(handle, "eglGetDisplay"); + void* (*peglGetDisplay)(void*) = real_dlsym(handle, "eglGetDisplay"); if (peglGetDisplay) { return peglGetDisplay(native_dpy); } else { - peglGetDisplay = dlsym(RTLD_NEXT, "eglGetDisplay"); + peglGetDisplay = real_dlsym(RTLD_NEXT, "eglGetDisplay"); if (peglGetDisplay) return peglGetDisplay(native_dpy); } @@ -79,11 +80,11 @@ void* eglGetPlatformDisplay(unsigned int platform, void* native_display, const i { loadMangoHud(); - void* (*peglGetPlatformDisplay)(unsigned int, void*, const intptr_t*) = dlsym(handle, "eglGetPlatformDisplay"); + void* (*peglGetPlatformDisplay)(unsigned int, void*, const intptr_t*) = real_dlsym(handle, "eglGetPlatformDisplay"); if (peglGetPlatformDisplay) { return peglGetPlatformDisplay(platform, native_display, attrib_list); } else { - peglGetPlatformDisplay = dlsym(RTLD_NEXT, "eglGetPlatformDisplay"); + peglGetPlatformDisplay = real_dlsym(RTLD_NEXT, "eglGetPlatformDisplay"); if (peglGetPlatformDisplay) return peglGetPlatformDisplay(platform, native_display, attrib_list); } @@ -95,12 +96,12 @@ unsigned int eglSwapBuffers(void* dpy, void* surf) { loadMangoHud(); // Get the hooked eglSwapBuffers function from the loaded library if available - unsigned int (*peglSwapBuffers)(void*, void*) = dlsym(handle, "eglSwapBuffers"); + unsigned int (*peglSwapBuffers)(void*, void*) = real_dlsym(handle, "eglSwapBuffers"); if (peglSwapBuffers) { return peglSwapBuffers(dpy, surf); } else { // Fall back to the original eglSwapBuffers function - peglSwapBuffers = dlsym(RTLD_NEXT, "eglSwapBuffers"); + peglSwapBuffers = real_dlsym(RTLD_NEXT, "eglSwapBuffers"); if (peglSwapBuffers) { return peglSwapBuffers(dpy, surf); } @@ -113,12 +114,12 @@ int64_t glXSwapBuffersMscOML(void* dpy, void* drawable, int64_t target_msc, int6 loadMangoHud(); // Get the hooked glXSwapBuffersMscOML function from the loaded library if available - int64_t (*pglXSwapBuffersMscOML)(void*, void*, int64_t, int64_t, int64_t) = dlsym(handle, "glXSwapBuffersMscOML"); + int64_t (*pglXSwapBuffersMscOML)(void*, void*, int64_t, int64_t, int64_t) = real_dlsym(handle, "glXSwapBuffersMscOML"); if (pglXSwapBuffersMscOML) { return pglXSwapBuffersMscOML(dpy, drawable, target_msc, divisor, remainder); } else { // Fall back to the original glXSwapBuffersMscOML function - pglXSwapBuffersMscOML = dlsym(RTLD_NEXT, "glXSwapBuffersMscOML"); + pglXSwapBuffersMscOML = real_dlsym(RTLD_NEXT, "glXSwapBuffersMscOML"); if (pglXSwapBuffersMscOML) { return pglXSwapBuffersMscOML(dpy, drawable, target_msc, divisor, remainder); } @@ -126,3 +127,96 @@ int64_t glXSwapBuffersMscOML(void* dpy, void* drawable, int64_t target_msc, int6 return -1; } + +void* glXGetProcAddress(const unsigned char* procName) +{ + loadMangoHud(); + + void* (*pglXGetProcAddress)(const unsigned char*) = real_dlsym(handle, "glXGetProcAddress"); + if (pglXGetProcAddress) { + return pglXGetProcAddress(procName); + } else { + pglXGetProcAddress = real_dlsym(RTLD_NEXT, "glXGetProcAddress"); + if (pglXGetProcAddress) { + return pglXGetProcAddress(procName); + } + } + + return NULL; +} + +void* glXGetProcAddressARB(const unsigned char* procName) +{ + loadMangoHud(); + + void* (*pglXGetProcAddressARB)(const unsigned char*) = real_dlsym(handle, "glXGetProcAddressARB"); + if (pglXGetProcAddressARB) { + return pglXGetProcAddressARB(procName); + } else { + pglXGetProcAddressARB = real_dlsym(RTLD_NEXT, "glXGetProcAddressARB"); + if (pglXGetProcAddressARB) { + return pglXGetProcAddressARB(procName); + } + } + + return NULL; +} + +void* eglGetProcAddress(const char *procName) +{ + loadMangoHud(); + + void* (*peglGetProcAddress)(const char*) = real_dlsym(handle, "eglGetProcAddress"); + if (peglGetProcAddress) { + return peglGetProcAddress(procName); + } else { + peglGetProcAddress = real_dlsym(RTLD_NEXT, "eglGetProcAddress"); + if (peglGetProcAddress) { + return peglGetProcAddress(procName); + } + } + + return NULL; +} + +struct func_ptr { + const char* name; + void* ptr; +}; + +#define ADD_HOOK(fn) { #fn, (void*)fn } +static struct func_ptr hooks[] = { + ADD_HOOK(glXGetProcAddress), + ADD_HOOK(glXGetProcAddressARB), + ADD_HOOK(glXSwapBuffers), + ADD_HOOK(glXSwapBuffersMscOML), + ADD_HOOK(eglSwapBuffers), + ADD_HOOK(eglGetPlatformDisplay), + ADD_HOOK(eglGetDisplay), + ADD_HOOK(eglGetProcAddress) +}; +#undef ADD_HOOK + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(arr) sizeof(arr)/sizeof(arr[0]) +#endif + +void* dlsym(void *handle, const char *name) +{ + const char* dlsym_enabled = getenv("MANGOHUD_DLSYM"); + void* is_angle = real_dlsym(handle, "eglStreamPostD3DTextureANGLE"); + void* fn_ptr = real_dlsym(handle, name); + + if (!is_angle && fn_ptr && (!dlsym_enabled || dlsym_enabled[0] != '0')) + { + for (unsigned i = 0; i < ARRAY_SIZE(hooks); i++) + { + if (!strcmp(hooks[i].name, name)) + { + return hooks[i].ptr; + } + } + } + + return fn_ptr; +} diff --git a/src/hook_dlsym.cpp b/src/hook_dlsym.cpp deleted file mode 100644 index dc1eddb052..0000000000 --- a/src/hook_dlsym.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include -#include -#include -#include "real_dlsym.h" - -EXPORT_C_(void*) dlsym(void * handle, const char * name) -{ - static void *(*find_glx_ptr)(const char *name) = nullptr; - static void *(*find_egl_ptr)(const char *name) = nullptr; - - if (!find_glx_ptr) - find_glx_ptr = reinterpret_cast (real_dlsym(RTLD_NEXT, "mangohud_find_glx_ptr")); - - if (!find_egl_ptr) - find_egl_ptr = reinterpret_cast (real_dlsym(RTLD_NEXT, "mangohud_find_egl_ptr")); - - void* func = nullptr; - bool is_angle = real_dlsym(handle, "eglStreamPostD3DTextureANGLE"); - void* real_func = real_dlsym(handle, name); - - if (find_glx_ptr && real_func) { - func = find_glx_ptr(name); - if (func) { - //fprintf(stderr,"%s: local: %s\n", __func__ , name); - return func; - } - } - - if (find_egl_ptr && real_func && !is_angle) { - func = find_egl_ptr(name); - if (func) { - //fprintf(stderr,"%s: local: %s\n", __func__ , name); - return func; - } - } - - //fprintf(stderr,"%s: foreign: %s\n", __func__ , name); - return real_func; -} diff --git a/src/meson.build b/src/meson.build index 0186430fce..a05207910a 100644 --- a/src/meson.build +++ b/src/meson.build @@ -86,8 +86,8 @@ if is_unixy 'memory.cpp', 'iostats.cpp', 'notify.cpp', - 'elfhacks.cpp', - 'real_dlsym.cpp', + 'elfhacks.c', + 'real_dlsym.c', 'pci_ids.cpp', 'battery.cpp', 'control.cpp', @@ -250,30 +250,6 @@ mangohud_opengl_shared_lib = shared_library( install: true ) -if is_unixy - mangohud_dlsym = shared_library( - 'MangoHud_dlsym', - files( - 'elfhacks.cpp', - 'real_dlsym.cpp', - 'hook_dlsym.cpp', - ), - c_args : [ - pre_args, - ], - cpp_args : [ - pre_args, - ], - gnu_symbol_visibility : 'hidden', - dependencies : [dep_dl], - include_directories : [inc_common], - link_args : link_args, - link_with: mangohud_static_lib, - install_dir : libdir_mangohud, - install : true - ) -endif - if get_option('mangoapp') if not get_option('with_x11').enabled() error('mangoapp also needs \'with_x11\'') @@ -328,10 +304,13 @@ if is_unixy 'MangoHud_shim', files( 'gl/shim.c', + 'real_dlsym.c', + 'elfhacks.c' ), dependencies : [ dep_dl ], + include_directories : [inc_common], install_dir : libdir_mangohud, install: true ) diff --git a/src/real_dlsym.cpp b/src/real_dlsym.c similarity index 82% rename from src/real_dlsym.cpp rename to src/real_dlsym.c index 3e5a77c4ed..8a45853707 100644 --- a/src/real_dlsym.cpp +++ b/src/real_dlsym.c @@ -6,14 +6,15 @@ #include #include +#include #include #include "real_dlsym.h" #include "elfhacks.h" -void *(*__dlopen)(const char *, int) = nullptr; -void *(*__dlsym)(void *, const char *) = nullptr; -static bool print_dlopen = getenv("MANGOHUD_DEBUG_DLOPEN") != nullptr; -static bool print_dlsym = getenv("MANGOHUD_DEBUG_DLSYM") != nullptr; +void *(*__dlopen)(const char *, int) = NULL; +void *(*__dlsym)(void *, const char *) = NULL; +static bool print_dlopen; +static bool print_dlsym; static void get_real_functions() { @@ -29,6 +30,9 @@ static void get_real_functions() "*ld-musl-*.so*", }; + print_dlopen = getenv("MANGOHUD_DEBUG_DLOPEN") != NULL; + print_dlsym = getenv("MANGOHUD_DEBUG_DLSYM") != NULL; + for (size_t i = 0; i < sizeof(libs) / sizeof(*libs); i++) { ret = eh_find_obj(&libdl, libs[i]); @@ -41,8 +45,8 @@ static void get_real_functions() if (__dlopen && __dlsym) break; - __dlopen = nullptr; - __dlsym = nullptr; + __dlopen = NULL; + __dlsym = NULL; } if (!__dlopen && !__dlsym) @@ -58,7 +62,7 @@ static void get_real_functions() */ void *real_dlopen(const char *filename, int flag) { - if (__dlopen == nullptr) + if (__dlopen == NULL) get_real_functions(); void *result = __dlopen(filename, flag); @@ -89,7 +93,7 @@ void *real_dlopen(const char *filename, int flag) */ void *real_dlsym(void *handle, const char *symbol) { - if (__dlsym == nullptr) + if (__dlsym == NULL) get_real_functions(); void *result = __dlsym(handle, symbol); @@ -101,6 +105,5 @@ void *real_dlsym(void *handle, const char *symbol) } void* get_proc_address(const char* name) { - void (*func)() = (void (*)())real_dlsym(RTLD_NEXT, name); - return (void*)func; + return real_dlsym(RTLD_NEXT, name); } diff --git a/src/real_dlsym.h b/src/real_dlsym.h index bcfbc6cbba..ab8a38bedf 100644 --- a/src/real_dlsym.h +++ b/src/real_dlsym.h @@ -4,8 +4,14 @@ #define EXPORT_C_(type) extern "C" __attribute__((__visibility__("default"))) type +#ifdef __cplusplus +extern "C" { +#endif void *real_dlopen(const char *filename, int flag); void* real_dlsym( void*, const char* ); void* get_proc_address(const char* name); +#ifdef __cplusplus +} +#endif #endif //MANGOHUD_REAL_DLSYM_H