#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);
}
}