#include <string.h>
#include <fcntl.h>
-#include <gelf.h>
void *libgl_handle;
void *wrapper_handle;
-/* Is the given elf program 32 or 64 bit?
- *
- * Note: This function returns -1 if 'filename' cannot
- * be opened as a valid ELF file.
- */
-static int
-elf_bits (const char *filename)
-{
- Elf *elf;
- GElf_Ehdr ehdr;
- int fd, class;
-
- fd = open (filename, O_RDONLY, 0);
- if (fd < 0)
- return -1;
-
- if (elf_version (EV_CURRENT ) == EV_NONE)
- return -1;
-
- elf = elf_begin (fd, ELF_C_READ, NULL);
- if (elf == NULL)
- return -1;
-
- if (elf_kind (elf) != ELF_K_ELF)
- return -1;
-
- if (gelf_getehdr (elf, &ehdr) == NULL)
- return -1;
-
- class = gelf_getclass (elf);
-
- switch (class) {
- case ELFCLASS32:
- return 32;
- case ELFCLASS64:
- return 64;
- default:
- return -1;
- }
-}
+#define STRNCMP_LITERAL(str, literal) strncmp (str, literal, sizeof (literal) - 1)
static void
open_libgl_handle (void)
libgl_path = getenv ("GLAZE_LIBGL");
if (libgl_path == NULL) {
- Dl_info info;
- int bits;
- if (dladdr (open_libgl_handle, &info) == 0) {
- fprintf (stderr, "Internal error: Failed to lookup filename of glaze library with dladdr.\n");
- exit (1);
- }
-
- bits = elf_bits (info.dli_fname);
+#if GLAZE_BITS == 32
+ libgl_path = getenv ("GLAZE_LIBGL_32_AUTO");
+#elif GLAZE_BITS == 64
+ libgl_path = getenv ("GLAZE_LIBGL_64_AUTO");
+#endif
- if (bits == 32)
- libgl_path = getenv ("GLAZE_LIBGL_32_AUTO");
- if (bits == 64)
- libgl_path = getenv ("GLAZE_LIBGL_64_AUTO");
-
- if (libgl_path == NULL) {
+ if (libgl_path == NULL || strlen (libgl_path) == 0) {
fprintf (stderr,
"Error: Failed to detect OpenGL library.\n"
"Please set GLAZE_LIBGL to path of real libGL.so\n");
path = getenv ("GLAZE_WRAPPER");
if (path == NULL) {
- fprintf (stderr, "GLAZE_WRAPPER unset. Please set to path of real libGL.so under glaze.\n");
+ fprintf (stderr, "GLAZE_WRAPPER unset. Please set to path of Glaze-using wrapper library.\n");
exit (1);
}
static void *
resolve (const char *name)
{
+ static int before_first_gl_call = 1;
void *symbol;
+ if (before_first_gl_call &&
+ STRNCMP_LITERAL (name, "gl") == 0 &&
+ STRNCMP_LITERAL (name, "glX") != 0)
+ {
+ char *callback_name = getenv ("GLAZE_FIRST_GL_CALL_CALLBACK");
+ if (callback_name) {
+ void (*callback) (void) = dlsym (wrapper_handle,
+ callback_name);
+ if (callback) {
+ (callback) ();
+ } else {
+ fprintf (stderr,
+ "Error: Failed to find function %s "
+ "in GLAZE_WRAPPER library.\n",
+ callback_name);
+ }
+ }
+ before_first_gl_call = 0;
+ }
+
/* The wrapper gets first choice on all symbols. */
symbol = dlsym (wrapper_handle, name);
if (symbol)
return dlsym (libgl_handle, name);
}
+void
+(*glXGetProcAddress (const unsigned char *name))(void);
+
+void
+(*glXGetProcAddress (const unsigned char *name))(void)
+{
+ static int first_call = 1;
+ static typeof (&glXGetProcAddress) wrapper_glXGetProcAddress;
+ static typeof (&glXGetProcAddress) libgl_glXGetProcAddress;
+ void *symbol;
+
+ /* On the first call, check if the wrapper provides an
+ * implementation of this function. */
+ if (first_call) {
+ wrapper_glXGetProcAddress = dlsym (wrapper_handle,
+ "glXGetProcAddress");
+ libgl_glXGetProcAddress = dlsym (libgl_handle,
+ "glXGetProcAddress");
+ first_call = 0;
+ }
+
+ /* If the wrapper implements glXGetProcAddress itself, then it
+ * had better know best what to do. Just let it. */
+ if (wrapper_glXGetProcAddress)
+ return wrapper_glXGetProcAddress (name);
+
+ /* Otherwise, we need to resolve the name.
+ *
+ * The wrapper gets first choice on all symbols. */
+ symbol = dlsym (wrapper_handle, (char *) name);
+ if (symbol)
+ return symbol;
+
+ /* The wrapper doesn't care, so defer to the underlying
+ * glXGetProcAddress */
+ return libgl_glXGetProcAddress (name);
+
+}
+
+void
+(*glXGetProcAddressARB (const unsigned char *name))(void);
+
+void
+(*glXGetProcAddressARB (const unsigned char *name))(void)
+{
+ static int first_call = 1;
+ static typeof (&glXGetProcAddressARB) wrapper_glXGetProcAddressARB;
+ static typeof (&glXGetProcAddressARB) libgl_glXGetProcAddressARB;
+ void *symbol;
+
+ /* On the first call, check if the wrapper provides an
+ * implementation of this function. */
+ if (first_call) {
+ wrapper_glXGetProcAddressARB = dlsym (wrapper_handle,
+ "glXGetProcAddressARB");
+ libgl_glXGetProcAddressARB = dlsym (libgl_handle,
+ "glXGetProcAddressARB");
+ first_call = 0;
+ }
+
+ /* If the wrapper implements glXGetProcAddressARB itself, then
+ * it had better know best what to do. Just let it. */
+ if (wrapper_glXGetProcAddressARB)
+ return wrapper_glXGetProcAddressARB (name);
+
+ /* Otherwise, we need to resolve the name.
+ *
+ * The wrapper gets first choice on all symbols. */
+ symbol = dlsym (wrapper_handle, (char *) name);
+ if (symbol)
+ return symbol;
+
+ /* The wrapper doesn't care, so defer to the underlying
+ * glXGetProcAddressARB */
+ return libgl_glXGetProcAddressARB (name);
+
+}
+
#define GLAZE_API(name) \
void * name() __attribute__((ifunc(#name "_resolver"))); \
static void * \