diff --git a/capsule/capsule.h b/capsule/capsule.h
index 0de488575fe1987048ffa35eadce25cb8cfbba08..d6d5410a32faeefaf5f36f1d78d4822c93234e64 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 179066d6dad1c65b38b62cfa5cfb31cd5406acb5..f0478e1ca6a5b0cc36531e434817d2023c078bd7 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 b950b6c44ccd7a2b92b2f68f276c008b2d942dc1..5e3bae6bc62e6214c2480d9079cf5baef5a83234 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 d29dfac3e52dd916d888f25d400f883058771805..d46e12d0af80a3e3a7868fefc0e8cc00c655d5b0 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