]> git.cworth.org Git - glaze/blobdiff - glaze-gl.c
Add a glaze_execute function to libglaze
[glaze] / glaze-gl.c
index b6e7d72d3f8f9317a4ae03136f73b1ff9f444fa7..d4ad33f77023415466f76febc3ce5c62c8437f44 100644 (file)
 
 #include <stdio.h>
 #include <stdlib.h>
+#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;
+       }
+}
+
 static void
 open_libgl_handle (void)
 {
-       const char *path;
+       const char *libgl_path;
 
        if (libgl_handle)
                return;
 
-       path = getenv ("GLAZE_LIBGL");
-       if (path == NULL) {
-               fprintf (stderr, "GLAZE_LIBGL unset. Please set to path of real libGL.so under glaze.\n");
-               exit (1);
+       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 (bits == 32)
+                       libgl_path = getenv ("GLAZE_LIBGL_32_AUTO");
+               if (bits == 64)
+                       libgl_path = getenv ("GLAZE_LIBGL_64_AUTO");
+
+               if (libgl_path == NULL) {
+                       fprintf (stderr,
+                                "Error: Failed to detect OpenGL library.\n"
+                                "Please set GLAZE_LIBGL to path of real libGL.so\n");
+                       exit (1);
+               }
+
+               setenv ("GLAZE_LIBGL", libgl_path, 1);
        }
 
-       libgl_handle = dlopen (path, RTLD_LAZY | RTLD_GLOBAL);
+       dlerror();
+       libgl_handle = dlopen (libgl_path, RTLD_LAZY | RTLD_GLOBAL);
        if (libgl_handle == NULL) {
-               fprintf (stderr, "Error: Failed to dlopen %s\n", path);
+               fprintf (stderr, "glaze_init: Error: Failed to dlopen %s: %s\n",
+                        libgl_path, dlerror());
                exit (1);
        }
 }