[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