[Mesa-dev] [PATCH 1/7] loader: Use dlsym to get our udev symbols instead of explicit linking.

Kristian Høgsberg krh at bitplanet.net
Sun Jan 26 15:45:41 PST 2014


On Thu, Jan 23, 2014 at 3:12 PM, Eric Anholt <eric at anholt.net> wrote:
> 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.

Less painful than I thought it'd be, nice.

Reviewed-by: Kristian Høgsberg <krh at bitplanet.net>

> ---
>  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);
> --
> 1.8.5.3
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list