From d6ac766abe401b681282cdcf273e7fb67fff99bd Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Tue, 2 Jul 2013 17:33:12 -0700 Subject: [PATCH] glwrap: Don't hardcode "libGL.so.1" for looking up real OpenGL symbols As preparation for testing using GLESv2 we need to ensure that our GL wrappers are prepared for an OpenGL implementation in either the libGL.so.1 library or in libGLESv2.so.2. When the application is directly linked to an OpenGL implementation, we don't care about the name at all. In this case, we can simply call dlsym with RTLD_NEXT to find the real, underlying OpenGL symbols. But when an application uses dlopen to load the OpenGL library, we want to carefully call dlsym with a handle for the same library that the application uses. Previously, the glwrap code was unconditionally calling dlopen for "libGL.so" and that's not what we want. Instead, we now have our dlopen wrapper watch for any dlopen of a library whose name begins with "libGL" and then stashing the returned handle via a new glwrap_set_gl_handle call. The stashed handle will then be used by dlsym calls within glwrap. --- dlwrap.c | 9 +++++++++ dlwrap.h | 1 + glwrap.c | 50 +++++++++++++++++++++++++++++++++++++------------- glwrap.h | 4 ++++ 4 files changed, 51 insertions(+), 13 deletions(-) diff --git a/dlwrap.c b/dlwrap.c index aff9e62..858b99b 100644 --- a/dlwrap.c +++ b/dlwrap.c @@ -29,6 +29,8 @@ #include "dlwrap.h" +#include "glwrap.h" + void *libfips_handle; typedef void * (* fips_dlopen_t)(const char * filename, int flag); @@ -86,6 +88,13 @@ dlopen (const char *filename, int flag) if (! find_wrapped_library_index (filename, &index)) return ret; + /* When the application dlopens any wrapped library starting + * with 'libGL', (whether libGL.so.1 or libGLESv2.so.2), let's + * continue to use that library handle for future lookups of + * OpenGL functions. */ + if (STRNCMP_LITERAL (filename, "libGL") == 0) + glwrap_set_gl_handle (ret); + assert (index < ARRAY_SIZE(orig_handles)); orig_handles[index] = ret; diff --git a/dlwrap.h b/dlwrap.h index 1dba14a..cad5a62 100644 --- a/dlwrap.h +++ b/dlwrap.h @@ -22,6 +22,7 @@ #ifndef DLWRAP_H #define DLWRAP_H +#define _GNU_SOURCE #include /* Call the *real* dlopen. We have our own wrapper for dlopen that, of diff --git a/glwrap.c b/glwrap.c index a7d62c5..0ae295a 100644 --- a/glwrap.c +++ b/glwrap.c @@ -19,6 +19,8 @@ * THE SOFTWARE. */ +#include "dlwrap.h" + /* The prototypes for some OpenGL functions changed at one point from: * * const void* *indices @@ -45,26 +47,48 @@ #include "metrics.h" -#include "dlwrap.h" - static int inside_new_list = 0; +static void *gl_handle; + +void +glwrap_set_gl_handle (void *handle) +{ + if (gl_handle == NULL) + gl_handle = handle; +} + void * glwrap_lookup (char *name) { - const char *libgl_filename = "libGL.so.1"; - static void *libgl_handle = NULL; - - if (! libgl_handle) { - libgl_handle = dlwrap_real_dlopen (libgl_filename, RTLD_NOW | RTLD_DEEPBIND); - if (! libgl_handle) { - fprintf (stderr, "Error: Failed to dlopen %s\n", - libgl_filename); - exit (1); - } + void *ret; + + /* We don't call dlopen here to find the library in which to + * perform a dlsym lookup. That's because the application may + * be loading libGL.so or libGLESv2.so for its OpenGL symbols. + * + * So we instead watch for one of those filenames to go by in + * our dlopen wrapper, which will then call + * glwrap_set_gl_handle to give us the handle to use here. + * + + * If the application hasn't called dlopen on a "libGL" + * library, then presumably the application is linked directly + * to an OpenGL implementation. In this case, we can use + * RTLD_NEXT to find the symbol. + */ + if (gl_handle == NULL) + gl_handle = RTLD_NEXT; + + ret = dlwrap_real_dlsym (gl_handle, name); + + if (ret == NULL) { + fprintf (stderr, "Error: glwrap_lookup failed to dlsym %s\n", + name); + exit (1); } - return dlwrap_real_dlsym (libgl_handle, name); + return ret; } /* Execute an OpenGL call and time it with a GPU metrics counter. */ diff --git a/glwrap.h b/glwrap.h index bd2e265..6acf3fc 100644 --- a/glwrap.h +++ b/glwrap.h @@ -26,6 +26,10 @@ void * glwrap_lookup (char *name); +/* Register a dlopened handle to be used by glwrap. */ +void +glwrap_set_gl_handle (void *handle); + /* Defer to the real 'function' (from libGL.so) to do the real work. * The symbol is looked up once and cached in a static variable for * future uses. -- 2.43.0