[OpenGL] Use elfhacks to load real OpenGL functions

This commit is contained in:
jackun 2020-03-16 22:35:34 +02:00
parent 85801bcc17
commit bb3aba9080
No known key found for this signature in database
GPG Key ID: 119DB3F1D05A9ED3
6 changed files with 86 additions and 39 deletions

View File

@ -186,10 +186,10 @@ void* get_proc_address(const char* name) {
void* get_glx_proc_address(const char* name) {
if (!gl.Load()) {
// Force load libGL then. If it still doesn't find it, get_proc_address should quit the program
void *handle = dlopen("libGL.so.1", RTLD_GLOBAL | RTLD_LAZY | RTLD_DEEPBIND);
void *handle = real_dlopen("libGL.so.1", RTLD_LAZY);
if (!handle)
std::cerr << "MANGOHUD: couldn't find libGL.so.1" << std::endl;
gl.Load();
gl.Load(handle);
}
void *func = nullptr;
@ -332,8 +332,6 @@ static void *find_ptr(const char *name)
}
EXPORT_C_(void *) glXGetProcAddress(const unsigned char* procName) {
gl.Load();
//std::cerr << __func__ << ":" << procName << std::endl;
void* func = find_ptr( (const char*)procName );
@ -344,8 +342,6 @@ EXPORT_C_(void *) glXGetProcAddress(const unsigned char* procName) {
}
EXPORT_C_(void *) glXGetProcAddressARB(const unsigned char* procName) {
gl.Load();
//std::cerr << __func__ << ":" << procName << std::endl;
void* func = find_ptr( (const char*)procName );

View File

@ -1,18 +1,83 @@
#include "real_dlsym.h"
/**
* \author Pyry Haulos <pyry.haulos@gmail.com>
* \date 2007-2008
* For conditions of distribution and use, see copyright notice in elfhacks.h
*/
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include "real_dlsym.h"
#include "elfhacks.h"
extern "C" void* __libc_dlsym( void* handle, const char* name );
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* real_dlsym( void* handle, const char* name )
void get_real_functions()
{
static void *(*the_real_dlsym)( void*, const char* );
eh_obj_t libdl;
if (!the_real_dlsym) {
void* libdl = dlopen( "libdl.so", RTLD_NOW | RTLD_LOCAL );
the_real_dlsym = reinterpret_cast<decltype(the_real_dlsym)> (__libc_dlsym( libdl, "dlsym" ));
if (eh_find_obj(&libdl, "*libdl.so*")) {
fprintf(stderr, "can't get libdl.so\n");
exit(1);
}
return the_real_dlsym( handle, name );
if (eh_find_sym(&libdl, "dlopen", (void **) &__dlopen)) {
fprintf(stderr, "can't get dlopen()\n");
exit(1);
}
if (eh_find_sym(&libdl, "dlsym", (void **) &__dlsym)) {
fprintf(stderr, "can't get dlsym()\n");
exit(1);
}
eh_destroy_obj(&libdl);
}
/**
* \brief dlopen() wrapper, just passes calls to real dlopen()
* and writes information to standard output
*/
void *real_dlopen(const char *filename, int flag)
{
if (__dlopen == nullptr)
get_real_functions();
void *result = __dlopen(filename, flag);
if (print_dlopen) {
printf("dlopen(%s, ", filename);
const char *fmt = "%s";
#define FLAG(test) if (flag & test) { printf(fmt, #test); fmt = "|%s"; }
FLAG(RTLD_LAZY)
FLAG(RTLD_NOW)
FLAG(RTLD_GLOBAL)
FLAG(RTLD_LOCAL)
FLAG(RTLD_NODELETE)
FLAG(RTLD_NOLOAD)
FLAG(RTLD_DEEPBIND)
#undef FLAG
printf(") = %p\n", result);
}
return result;
}
/**
* \brief dlsym() wrapper, passes calls to real dlsym() and
* writes information to standard output
*/
void *real_dlsym(void *handle, const char *symbol)
{
if (__dlsym == nullptr)
get_real_functions();
void *result = __dlsym(handle, symbol);
if (print_dlsym)
printf("dlsym(%p, %s) = %p\n", handle, symbol, result);
return result;
}

View File

@ -1,22 +1,4 @@
/*
Copyright (C) 2016-2017 Björn Spindel
This file is part of libstrangle.
libstrangle is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
libstrangle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with libstrangle. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
void *real_dlopen(const char *filename, int flag);
void* real_dlsym( void*, const char* );

View File

@ -8,14 +8,17 @@ gl_loader::~gl_loader() {
CleanUp(loaded_);
}
bool gl_loader::Load(bool egl_only) {
bool gl_loader::Load(void *handle, bool egl_only) {
if (loaded_) {
return true;
}
if (!handle)
handle = RTLD_NEXT;
eglSwapBuffers =
reinterpret_cast<decltype(this->eglSwapBuffers)>(
real_dlsym(RTLD_NEXT, "eglSwapBuffers"));
real_dlsym(handle, "eglSwapBuffers"));
if (egl_only) {
loaded_ = true;
@ -24,11 +27,11 @@ bool gl_loader::Load(bool egl_only) {
glXGetProcAddress =
reinterpret_cast<decltype(this->glXGetProcAddress)>(
real_dlsym(RTLD_NEXT, "glXGetProcAddress"));
real_dlsym(handle, "glXGetProcAddress"));
glXGetProcAddressARB =
reinterpret_cast<decltype(this->glXGetProcAddressARB)>(
real_dlsym(RTLD_NEXT, "glXGetProcAddressARB"));
real_dlsym(handle, "glXGetProcAddressARB"));
if (!glXGetProcAddress) {
CleanUp(true);

View File

@ -9,7 +9,7 @@ class gl_loader {
gl_loader();
~gl_loader();
bool Load(bool egl_only = false);
bool Load(void *handle = nullptr, bool egl_only = false);
bool IsLoaded() { return loaded_; }
decltype(&::glXGetProcAddress) glXGetProcAddress;

View File

@ -51,6 +51,7 @@ vklayer_files = files(
'iostats.cpp',
'gpu.cpp',
'notify.cpp',
'elfhacks.cpp',
)
opengl_files = files(