From 859ea86a6e2e08a0648aa0a9ec7ff9e3c89c15ba Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Vivek=20Das=C2=A0Mohapatra?= <vivek@collabora.co.uk>
Date: Wed, 13 Sep 2017 23:21:32 +0100
Subject: [PATCH] Use the new capsule_shim_dlsym helper to implement a dlsym
 wrapper

The capsule-init-project script now implements and installs a
dlsym() wrapper in generated shim project source trees.
---
 capsule/capsule.h         |  2 +-
 data/capsule-init-project | 16 ++++++++++++++++
 data/capsule-mkstublib    | 19 ++++++++++++++++++-
 data/capsule-shim.mk.in   |  2 +-
 4 files changed, 36 insertions(+), 3 deletions(-)

diff --git a/capsule/capsule.h b/capsule/capsule.h
index 0de488575..d6d5410a3 100644
--- a/capsule/capsule.h
+++ b/capsule/capsule.h
@@ -47,8 +47,8 @@ typedef struct _capsule_item capsule_item;
 struct _capsule_item
 {
     const char *name;
-    capsule_addr shim;
     capsule_addr real;
+    capsule_addr shim;
 
     /*< private >*/
     void *unused0;
diff --git a/data/capsule-init-project b/data/capsule-init-project
index 179066d6d..f0478e1ca 100755
--- a/data/capsule-init-project
+++ b/data/capsule-init-project
@@ -70,6 +70,22 @@ static void *_dlopen (const char *filename, int flag)
 }
 EOF
 
+cat - <<EOF > shim/$base.so.c.dlsym
+// This allows symbols inside the capsule to be found by dlopen calls from
+// outside the capsule iff they are in one of the exported DSOs.
+//
+// This is useful in libGL shims as libGL has an ‘interesting’ history
+// of symbols appearing and disappearing so its users often do a
+// bizarre dlopen()/dlsym() dance instead of referring to a symbol
+// directly (and we may be missing those symbols from our static
+// export list even if the target libGL has them)
+static void *_dlsym (void *handle, const char *symbol)
+{
+    const char **valid_sources = { "libGL.so.1", NULL };
+    return capsule_shim_dlsym( dso, handle, symbol, valid_sources );
+}
+EOF
+
 echo Initialising configure.ac;
 
 cat - <<EOF > configure.ac
diff --git a/data/capsule-mkstublib b/data/capsule-mkstublib
index b950b6c44..5e3bae6bc 100755
--- a/data/capsule-mkstublib
+++ b/data/capsule-mkstublib
@@ -47,6 +47,7 @@ proxied_dso=lib${dso_base}.so.${major_version};
 symbol_file=${proxy_src%.c}.symbols;
 map_file=${proxy_src%.c}.map;
 dlopen_file=${proxy_src}.dlopen;
+dlsym_file=${proxy_src}.dlsym;
 sharedir=$(pkg-config --variable=makeinc capsule)
 
 exec >$proxy_src.tmp;
@@ -120,6 +121,15 @@ then
     echo "// -------------------------------------------------------------";
 fi
 
+if [ -f ${dlsym_file} ];
+then
+    echo "// -------------------------------------------------------------";
+    echo "// start of ${proxy_src%.c} dlsym wrapper";
+    cat $dlsym_file;
+    echo "// end of ${proxy_src%.c} dlsym wrapper";
+    echo "// -------------------------------------------------------------";
+fi
+
 cat - <<EOF
 
 static void __attribute__ ((constructor)) _capsule_init (void)
@@ -134,8 +144,15 @@ EOF
 
 while read sym x; do echo "         { \"$sym\" },"; done < $symbol_file;
 
+if [ -f $dlsym_file ];
+then
+    cat - <<EOF
+         { "dlsym", (capsule_addr) _dlsym },
+EOF
+fi;
+
 cat - <<EOF
-        { NULL }
+         { NULL }
       };
 
     // and this is an aray of functions we must override in the DSOs
diff --git a/data/capsule-shim.mk.in b/data/capsule-shim.mk.in
index d29dfac3e..d46e12d0a 100644
--- a/data/capsule-shim.mk.in
+++ b/data/capsule-shim.mk.in
@@ -29,7 +29,7 @@ GENSTUB_V0 = @echo "  GENSTUB " $(subst $(word 1, $(basename $(filter shim/lib%,
 GENSTUB    = $(GENSTUB_V$(V))
 
 # regenerate if any dependencies get updated:
-shim/lib%.so.c: shim/lib%.so.c.excluded shim/lib%.so.c.dlopen shim/lib%.so.symbols
+shim/lib%.so.c: shim/lib%.so.c.excluded shim/lib%.so.c.dlopen shim/lib%.so.c.dlsym shim/lib%.so.symbols
 	$(GENSTUB)V=$V $(mkstub) $$(basename $@ .c) $@.excluded $@.shared $@ $(ltver) $(CAPSULE_TREE)
 
 # regenerate the exportable symbols list
-- 
GitLab