tests: robustify pc.test

* configure.ac: Check for dladdr in -ldl.
* tests/Makefile.am (pc_LDADD): Adde $(dl_LIBS).
* tests/pc.c: Include "config.h" and <dlfcn.h>.
(main): Use dladdr to find the address to unmap.
diff --git a/configure.ac b/configure.ac
index b21941e..0d009ea 100644
--- a/configure.ac
+++ b/configure.ac
@@ -729,6 +729,14 @@
 		  [Define to 1 if the system provides __builtin_popcount function])
 fi
 
+dl_LIBS=
+AC_CHECK_LIB([dl], [dladdr], [])
+if test "x$ac_cv_lib_dl_dladdr" = xyes; then
+	AC_DEFINE([HAVE_DLADDR], [1], [Define to 1 if the system provides dladdr])
+	dl_LIBS='-ldl'
+fi
+AC_SUBST(dl_LIBS)
+
 AC_PATH_PROG([PERL], [perl])
 
 dnl stack trace with libunwind
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 21f7361..36a187d 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -34,6 +34,7 @@
 	uio \
 	unix-pair-send-recv
 
+pc_LDADD = $(dl_LIBS)
 stat_CFLAGS = $(AM_CFLAGS) -D_FILE_OFFSET_BITS=64
 statfs_CFLAGS = $(AM_CFLAGS) -D_FILE_OFFSET_BITS=64
 uio_CFLAGS = $(AM_CFLAGS) -D_FILE_OFFSET_BITS=64
diff --git a/tests/pc.c b/tests/pc.c
index 944c1a8..a450c0d 100644
--- a/tests/pc.c
+++ b/tests/pc.c
@@ -1,3 +1,7 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <dlfcn.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <sys/mman.h>
@@ -6,7 +10,7 @@
 
 int main(void)
 {
-	const unsigned long size = sysconf(_SC_PAGESIZE);
+	const unsigned long pagesize = sysconf(_SC_PAGESIZE);
 
 	/* write instruction pointer length to the log */
 	if (write(-1, NULL, 2 * sizeof(void *)) >= 0)
@@ -21,12 +25,29 @@
 		return 77;
 
 	if (!pid) {
-		const unsigned long mask = ~(size - 1);
-		const unsigned long addr = (unsigned long) &main;
+		const unsigned long mask = ~(pagesize - 1);
+		unsigned long addr = (unsigned long) &main & mask;
+		unsigned long size = pagesize << 1;
+
+#ifdef HAVE_DLADDR
+		Dl_info info;
+		if (dladdr(&main, &info)) {
+			const unsigned long base =
+				(unsigned long) info.dli_fbase & mask;
+			if (base < addr) {
+				size += addr - base;
+				addr = base;
+			}
+		} else
+#endif
+		{
+			addr -= size;
+			size <<= 1;
+		}
 
 		/* SIGSEGV is expected */
-		(void) munmap((void *) ((addr & mask) - size * 2), size * 4);
-		(void) munmap((void *) ((addr & mask) - size * 2), size * 4);
+		(void) munmap((void *) addr, size);
+		(void) munmap((void *) addr, size);
 		return 77;
 	}
 
@@ -39,7 +60,7 @@
 	/* dump process map for debug purposes */
 	close(0);
 	if (!open("/proc/self/maps", O_RDONLY))
-		(void) sendfile(1, 0, NULL, size);
+		(void) sendfile(1, 0, NULL, pagesize);
 
 	return 0;
 }