diff --git a/ChangeLog b/ChangeLog
index 2425c82d27ddf74e6ddfd69b88ed8ec4372c6c8f..02b949043141b58e07d9dafcdbf3ecb30543f214 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
 2015-09-02  Niels Möller  <nisse@lysator.liu.se>
 
+	* testsuite/dlopen-test.c: New test program, exposing the problem
+	with ifunc and RTLD_NOW.
+
+	* testsuite/Makefile.in (TS_ALL): Conditionally add dlopen-test.
+	(SOURCES): Added dlopen-test.c.
+	(dlopen-test): New target, unlike other test programs, *not*
+	linked with -lnettle.
+
+	* configure.ac: Check for dlfcn.h and the dlopen function.
+	(IF_DLOPEN_TEST): New substituted variable, true if dlopen is
+	available and we are building a shared library.
+
 	* fat-setup.h: Disable use of ifunc, since it breaks dlopen with
 	RTLD_NOW.
 
diff --git a/configure.ac b/configure.ac
index 1cc7c61b20b6ada37074f999b50de4e266ac4f68..a2251f8e10bd8564cffb40db9a2315f5d2bcbcce 100644
--- a/configure.ac
+++ b/configure.ac
@@ -189,7 +189,12 @@ AC_CHECK_HEADERS([openssl/blowfish.h openssl/des.h openssl/cast.h openssl/aes.h
 [enable_openssl=no
  break])
 
+# For use by the testsuite
 AC_CHECK_HEADERS([valgrind/memcheck.h])
+AC_CHECK_HEADERS([dlfcn.h])
+AC_CHECK_LIB([dl], [dlopen],
+	     [AC_DEFINE([HAVE_LIBDL], 1,
+			[Define to 1 if you have dlopen (with -ldl).])])
 
 LSH_FUNC_ALLOCA
 LSH_FUNC_STRERROR
@@ -818,9 +823,13 @@ else
   IF_STATIC='#'
 fi
 
+IF_DLOPEN_TEST='#'
 if test "x$enable_shared" = xyes ; then
   IF_SHARED=''
   IF_NOT_SHARED='#'
+  if "x$ac_cv_lib_dl_dlopen" = yes ; then
+    IF_DLOPEN_TEST=''
+  fi
 else
   IF_SHARED='#'
   IF_NOT_SHARED=''
@@ -858,6 +867,7 @@ AC_SUBST(IF_HOGWEED)
 AC_SUBST(IF_STATIC)
 AC_SUBST(IF_SHARED)
 AC_SUBST(IF_NOT_SHARED)
+AC_SUBST(IF_DLOPEN_TEST)
 AC_SUBST(IF_DOCUMENTATION)
 AC_SUBST(IF_DLL)
 AC_SUBST(IF_MINI_GMP)
diff --git a/testsuite/Makefile.in b/testsuite/Makefile.in
index f5264baa416d68e1c3b2768fe8b896bcd07a6f25..426fe1a4c83da7921ae08538532d7c9660f1fcdd 100644
--- a/testsuite/Makefile.in
+++ b/testsuite/Makefile.in
@@ -57,12 +57,13 @@ TS_C = $(TS_NETTLE) @IF_HOGWEED@ $(TS_HOGWEED)
 TS_CXX = @IF_CXX@ $(CXX_SOURCES:.cxx=$(EXEEXT))
 TARGETS = $(TS_C) $(TS_CXX)
 TS_SH = sexp-conv-test pkcs1-conv-test nettle-pbkdf2-test symbols-test
-TS_ALL = $(TARGETS) $(TS_SH)
+TS_ALL = $(TARGETS) $(TS_SH) @IF_DLOPEN_TEST@ dlopen-test$(EXEEXT)
 EXTRA_SOURCES = sha1-huge-test.c
 EXTRA_TARGETS = $(EXTRA_SOURCES:.c=$(EXEEXT))
 
+
 # Includes all C source files, regardless of configuration
-SOURCES = $(TS_SOURCES) $(EXTRA_SOURCES) testutils.c
+SOURCES = $(TS_SOURCES) $(EXTRA_SOURCES) testutils.c dlopen-test.c
 
 DISTFILES = $(SOURCES) $(CXX_SOURCES) Makefile.in .test-rules.make \
 	    $(TS_SH) setup-env teardown-env \
@@ -89,6 +90,10 @@ TEST_OBJS = testutils.$(OBJEXT) ../nettle-internal.$(OBJEXT) \
 ../nettle-internal.$(OBJEXT):
 	( cd .. && $(MAKE) nettle-internal.$(OBJEXT) )
 
+# Special target, to omit linking with libnettle
+dlopen-test$(EXEEXT): dlopen-test.$(OBJEXT) testutils.$(OBJEXT)
+	$(LINK) dlopen-test.$(OBJEXT) -ldl -o dlopen-test$(EXEEXT)
+
 .PHONY: test-rules
 test-rules:
 	(for f in $(TS_NETTLE) $(TS_HOGWEED) $(EXTRA_TARGETS) ; do \
diff --git a/testsuite/dlopen-test.c b/testsuite/dlopen-test.c
new file mode 100644
index 0000000000000000000000000000000000000000..7a6384579372ebc6485c5ad026b2cfb81d94e9c1
--- /dev/null
+++ b/testsuite/dlopen-test.c
@@ -0,0 +1,35 @@
+#include "testutils.h"
+#include "version.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+int
+main (int argc, char **argv)
+{
+#if HAVE_LIBDL
+  void *handle = dlopen ("../libnettle.so", RTLD_NOW);
+  int (*get_version)(void);
+  if (!handle)
+    {
+      fprintf (stderr, "dlopen failed: %s\n", dlerror());
+      FAIL ();
+    }
+
+  get_version = (int(*)(void)) dlsym (handle, "nettle_version_minor");
+  if (!get_version)
+    {
+      fprintf (stderr, "dlsym failed: %s\n", dlerror());
+      FAIL ();
+    }
+  if (get_version() != NETTLE_VERSION_MINOR)
+    {
+      fprintf (stderr, "unexpected nettle version\n");
+      FAIL ();
+    }
+  return EXIT_SUCCESS;
+#else
+  SKIP();
+#endif
+}