Mesa (master): loader: Use dlsym to get our udev symbols instead of explicit linking.

Eric Anholt anholt at kemper.freedesktop.org
Mon Jan 27 17:54:52 UTC 2014


Module: Mesa
Branch: master
Commit: 4556c734700da2dd95d4f148d6929a537882bade
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=4556c734700da2dd95d4f148d6929a537882bade

Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jan 23 13:12:26 2014 -0800

loader: Use dlsym to get our udev symbols instead of explicit linking.

Steam links against libudev.so.0, while we're linking against
libudev.so.1.  The result is that the symbol names (which are the same in
the two libraries) end up conflicting, and some of the usage of .so.1
calls the .so.0 bits, which have different internal structures, and
segfaults happen.

By using a dlopen() with RTLD_LOCAL, we can explicitly look for the
symbols we want, while they get the symbols they want.

Reviewed-by: Keith Packard <keithp at keithp.com>
Reviewed-by: Kristian Høgsberg <krh at bitplanet.net>
Tested-by: Alexandre Demers <alexandre.f.demers at gmail.com>
Tested-by: Mike Lothian <mike at fireburn.co.uk>

---

 configure.ac             |    2 +-
 src/egl/main/Makefile.am |    2 +-
 src/loader/Makefile.am   |    5 +----
 src/loader/loader.c      |   42 ++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 45 insertions(+), 6 deletions(-)

diff --git a/configure.ac b/configure.ac
index 33ac922..d266d96 100644
--- a/configure.ac
+++ b/configure.ac
@@ -858,7 +858,7 @@ xyesno)
 
     if test x"$enable_dri3$have_libudev" = xyesyes; then
         X11_INCLUDES="$X11_INCLUDES $LIBUDEV_CFLAGS"
-        GL_LIB_DEPS="$GL_LIB_DEPS $LIBUDEV_LIBS"
+        GL_LIB_DEPS="$GL_LIB_DEPS"
     fi
 
     # need DRM libs, $PTHREAD_LIBS, etc.
diff --git a/src/egl/main/Makefile.am b/src/egl/main/Makefile.am
index 60cb600..e12aeae 100644
--- a/src/egl/main/Makefile.am
+++ b/src/egl/main/Makefile.am
@@ -112,7 +112,7 @@ if HAVE_EGL_DRIVER_DRI2
 AM_CFLAGS += -D_EGL_BUILT_IN_DRIVER_DRI2
 AM_CFLAGS += -DHAVE_XCB_DRI2
 libEGL_la_LIBADD += ../drivers/dri2/libegl_dri2.la
-libEGL_la_LIBADD += $(LIBUDEV_LIBS) $(DLOPEN_LIBS) $(LIBDRM_LIBS)
+libEGL_la_LIBADD += $(DLOPEN_LIBS) $(LIBDRM_LIBS)
 endif
 
 # Provide compatibility with scripts for the old Mesa build system for
diff --git a/src/loader/Makefile.am b/src/loader/Makefile.am
index 371dd57..bddf7ac 100644
--- a/src/loader/Makefile.am
+++ b/src/loader/Makefile.am
@@ -29,9 +29,6 @@ libloader_la_CPPFLAGS = \
 	$(VISIBILITY_CFLAGS) \
 	$(LIBUDEV_CFLAGS)
 
-libloader_la_LIBADD = \
-	$(LIBUDEV_LIBS)
-
 if !HAVE_LIBDRM
 libloader_la_CPPFLAGS += \
 	-D__NOT_HAVE_DRM_H
@@ -39,7 +36,7 @@ else
 libloader_la_CPPFLAGS += \
 	$(LIBDRM_CFLAGS)
 
-libloader_la_LIBADD += \
+libloader_la_LIBADD = \
 	$(LIBDRM_LIBS)
 endif
 
diff --git a/src/loader/loader.c b/src/loader/loader.c
index a5bd769..63b977a 100644
--- a/src/loader/loader.c
+++ b/src/loader/loader.c
@@ -67,6 +67,8 @@
 #include <stdarg.h>
 #include <stdio.h>
 #include <string.h>
+#include <assert.h>
+#include <dlfcn.h>
 #include "loader.h"
 
 #ifndef __NOT_HAVE_DRM_H
@@ -92,11 +94,37 @@ static void (*log_)(int level, const char *fmt, ...) = default_logger;
 #ifdef HAVE_LIBUDEV
 #include <libudev.h>
 
+static void *udev_handle = NULL;
+
+static void *
+udev_dlopen_handle(void)
+{
+   if (!udev_handle) {
+      udev_handle = dlopen("libudev.so.1", RTLD_LOCAL | RTLD_LAZY);
+   }
+
+   return udev_handle;
+}
+
+static void *
+asserted_dlsym(void *dlopen_handle, const char *name)
+{
+   void *result = dlsym(dlopen_handle, name);
+   assert(result);
+   return result;
+}
+
+#define UDEV_SYMBOL(ret, name, args) \
+   ret (*name) args = asserted_dlsym(udev_dlopen_handle(), #name);
+
+
 static inline struct udev_device *
 udev_device_new_from_fd(struct udev *udev, int fd)
 {
    struct udev_device *device;
    struct stat buf;
+   UDEV_SYMBOL(struct udev_device *, udev_device_new_from_devnum,
+               (struct udev *udev, char type, dev_t devnum));
 
    if (fstat(fd, &buf) < 0) {
       log_(_LOADER_WARNING, "MESA-LOADER: failed to stat fd %d", fd);
@@ -119,6 +147,14 @@ loader_get_pci_id_for_fd(int fd, int *vendor_id, int *chip_id)
    struct udev *udev = NULL;
    struct udev_device *device = NULL, *parent;
    const char *pci_id;
+   UDEV_SYMBOL(struct udev *, udev_new, (void));
+   UDEV_SYMBOL(struct udev_device *, udev_device_get_parent,
+               (struct udev_device *));
+   UDEV_SYMBOL(const char *, udev_device_get_property_value,
+               (struct udev_device *, const char *));
+   UDEV_SYMBOL(struct udev_device *, udev_device_unref,
+               (struct udev_device *));
+   UDEV_SYMBOL(struct udev *, udev_unref, (struct udev *));
 
    *chip_id = -1;
 
@@ -240,6 +276,12 @@ loader_get_device_name_for_fd(int fd)
    struct udev *udev;
    struct udev_device *device;
    const char *const_device_name;
+   UDEV_SYMBOL(struct udev *, udev_new, (void));
+   UDEV_SYMBOL(const char *, udev_device_get_devnode,
+               (struct udev_device *));
+   UDEV_SYMBOL(struct udev_device *, udev_device_unref,
+               (struct udev_device *));
+   UDEV_SYMBOL(struct udev *, udev_unref, (struct udev *));
 
    udev = udev_new();
    device = udev_device_new_from_fd(udev, fd);




More information about the mesa-commit mailing list