summaryrefslogtreecommitdiffstats
path: root/trunk/testsuite
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/testsuite')
-rw-r--r--trunk/testsuite/Makefile.am1
-rw-r--r--trunk/testsuite/Makefile.in1
-rw-r--r--trunk/testsuite/ifunc.h33
-rw-r--r--trunk/testsuite/ifunc1.c29
-rwxr-xr-xtrunk/testsuite/ifunc1.sh21
-rw-r--r--trunk/testsuite/ifunc1lib1.c32
-rw-r--r--trunk/testsuite/ifunc1lib2.c39
-rwxr-xr-xtrunk/testsuite/ifunc2.sh21
-rw-r--r--trunk/testsuite/ifunc3.c32
-rwxr-xr-xtrunk/testsuite/ifunc3.sh21
-rw-r--r--trunk/testsuite/ifunc3lib1.c37
-rw-r--r--trunk/testsuite/ifunctest.c16
12 files changed, 283 insertions, 0 deletions
diff --git a/trunk/testsuite/Makefile.am b/trunk/testsuite/Makefile.am
index 514cf8e..0de603c 100644
--- a/trunk/testsuite/Makefile.am
+++ b/trunk/testsuite/Makefile.am
@@ -14,6 +14,7 @@ TESTS = movelibs.sh \
tls1.sh tls2.sh tls3.sh tls4.sh tls5.sh tls6.sh tls7.sh \
cxx1.sh cxx2.sh quick1.sh quick2.sh quick3.sh cycle1.sh cycle2.sh \
deps1.sh deps2.sh \
+ ifunc1.sh ifunc2.sh ifunc3.sh \
undosyslibs.sh
TESTS_ENVIRONMENT = \
PRELINK="../src/prelink -c ./prelink.conf -C ./prelink.cache --ld-library-path=. --dynamic-linker=`echo ./ld*.so.*[0-9]`" \
diff --git a/trunk/testsuite/Makefile.in b/trunk/testsuite/Makefile.in
index 5dff524..30eeeb5 100644
--- a/trunk/testsuite/Makefile.in
+++ b/trunk/testsuite/Makefile.in
@@ -109,6 +109,7 @@ TESTS = movelibs.sh \
tls1.sh tls2.sh tls3.sh tls4.sh tls5.sh tls6.sh tls7.sh \
cxx1.sh cxx2.sh quick1.sh quick2.sh quick3.sh cycle1.sh cycle2.sh \
deps1.sh deps2.sh \
+ ifunc1.sh ifunc2.sh ifunc3.sh \
undosyslibs.sh
TESTS_ENVIRONMENT = \
diff --git a/trunk/testsuite/ifunc.h b/trunk/testsuite/ifunc.h
new file mode 100644
index 0000000..3593396
--- /dev/null
+++ b/trunk/testsuite/ifunc.h
@@ -0,0 +1,33 @@
+#ifndef PICKNO
+# define PICKNO 1
+#endif
+#if PICKNO == 2
+# define PICK(fn1, fn2) #fn2
+#else
+# define PICK(fn1, fn2) #fn1
+#endif
+#ifdef __x86_64__
+# define IFUNC_ASM(fn) "\tleaq " fn "(%rip), %rax\n\tretq\n"
+#elif defined __i386__
+# ifdef __PIC__
+# define IFUNC_ASM(fn) "\tcall 1f\n1:\tpopl %ecx\n" \
+ "\taddl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ecx\n" \
+ "\tleal " fn "@GOTOFF(%ecx), %eax\n\tret\n"
+# else
+# define IFUNC_ASM(fn) "\tmovl $" fn ", %eax\n\tret\n"
+# endif
+#else
+# error Architecture not supported
+#endif
+#define IFUNC(name, hidden, fn1, fn2) \
+extern __typeof (fn1) fn1 __attribute__((used)); \
+extern __typeof (fn2) fn2 __attribute__((used)); \
+extern __typeof (fn1) name; \
+asm (".globl " #name "\n" \
+ "\t" hidden " " #name "\n" \
+ "\t.type " #name ", @gnu_indirect_function\n" \
+ #name ":\n" \
+ IFUNC_ASM (PICK (fn1, fn2)) \
+ "\t.size " #name ", .-" #name "\n")
+#define IFUNC_LOCAL(name, fn1, fn2) IFUNC(name, ".hidden", fn1, fn2)
+#define IFUNC_GLOBAL(name, fn1, fn2) IFUNC(name, ".globl", fn1, fn2)
diff --git a/trunk/testsuite/ifunc1.c b/trunk/testsuite/ifunc1.c
new file mode 100644
index 0000000..f5500df
--- /dev/null
+++ b/trunk/testsuite/ifunc1.c
@@ -0,0 +1,29 @@
+#include "ifunc.h"
+
+static int bint11 (void) { return 1; }
+static int bint12 (void) { return 2; }
+
+IFUNC_LOCAL (bint1, bint11, bint12);
+
+static int lib2t21 (void) { return 1; }
+static int lib2t22 (void) { return 2; }
+
+IFUNC_GLOBAL (lib2t2, lib2t21, lib2t22);
+
+extern int lib1t2 (void);
+extern int lib1test (void);
+extern int lib2test (void);
+
+extern void abort (void);
+
+int
+main (void)
+{
+ lib1test ();
+ lib2test ();
+ if (bint1 () != PICKNO)
+ abort ();
+ if (lib1t2 () != PICKNO)
+ abort ();
+ return 0;
+}
diff --git a/trunk/testsuite/ifunc1.sh b/trunk/testsuite/ifunc1.sh
new file mode 100755
index 0000000..7746234
--- /dev/null
+++ b/trunk/testsuite/ifunc1.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+. `dirname $0`/functions.sh
+# First check if __thread is supported by ld.so/gcc/ld/as:
+$CCLINK -o ifunctest $srcdir/ifunctest.c -Wl,--rpath-link,. > /dev/null 2>&1 || exit 77
+( ./ifunctest || { rm -f ifunctest; exit 77; } ) 2>/dev/null || exit 77
+rm -f ifunctest ifunc1 ifunc1lib*.so ifunc1.log
+rm -f prelink.cache
+$CC -shared -O2 -fpic -o ifunc1lib1.so $srcdir/ifunc1lib1.c
+$CC -shared -O2 -fpic -o ifunc1lib2.so $srcdir/ifunc1lib2.c ifunc1lib1.so
+BINS="ifunc1"
+LIBS="ifunc1lib1.so ifunc1lib2.so"
+$CCLINK -o ifunc1 $srcdir/ifunc1.c -Wl,--rpath-link,. ifunc1lib2.so
+savelibs
+echo $PRELINK ${PRELINK_OPTS--vm} ./ifunc1 >> ifunc1.log
+$PRELINK ${PRELINK_OPTS--vm} ./ifunc1 >> ifunc1.log 2>&1 || exit 1
+grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` ifunc1.log && exit 2
+LD_LIBRARY_PATH=. ./ifunc1 || exit 3
+readelf -a ./ifunc1 >> ifunc1.log 2>&1 || exit 4
+# So that it is not prelinked again
+chmod -x ./ifunc1
+comparelibs >> ifunc1.log 2>&1 || exit 5
diff --git a/trunk/testsuite/ifunc1lib1.c b/trunk/testsuite/ifunc1lib1.c
new file mode 100644
index 0000000..27a3f03
--- /dev/null
+++ b/trunk/testsuite/ifunc1lib1.c
@@ -0,0 +1,32 @@
+#include "ifunc.h"
+
+static int lib1t11 (void) { return 11; }
+static int lib1t12 (void) { return 12; }
+
+IFUNC_LOCAL (lib1t1, lib1t11, lib1t12);
+
+static int lib1t21 (void) { return 1; }
+static int lib1t22 (void) { return 2; }
+
+IFUNC_GLOBAL (lib1t2, lib1t21, lib1t22);
+
+static int lib1t31 (void) { return 3; }
+static int lib1t32 (void) { return 4; }
+
+IFUNC_GLOBAL (lib1t3, lib1t31, lib1t32);
+
+extern void abort (void);
+
+int (*lib1p1) (void) = lib1t1;
+
+int
+lib1test (void)
+{
+ if (lib1t1 () != PICKNO + 10)
+ abort ();
+ if (lib1t3 () != PICKNO)
+ abort ();
+ if (lib1p1 () != PICKNO + 10)
+ abort ();
+ return 0;
+}
diff --git a/trunk/testsuite/ifunc1lib2.c b/trunk/testsuite/ifunc1lib2.c
new file mode 100644
index 0000000..ca12e3d
--- /dev/null
+++ b/trunk/testsuite/ifunc1lib2.c
@@ -0,0 +1,39 @@
+#include "ifunc.h"
+
+static int lib2t11 (void) { return 1; }
+static int lib2t12 (void) { return 2; }
+
+IFUNC_LOCAL (lib2t1, lib2t11, lib2t12);
+
+static int lib2t21 (void) { return 3; }
+static int lib2t22 (void) { return 4; }
+
+IFUNC_GLOBAL (lib2t2, lib2t21, lib2t22);
+
+static int lib2t31 (void) { return 1; }
+static int lib2t32 (void) { return 2; }
+
+IFUNC_GLOBAL (lib2t3, lib2t31, lib2t32);
+
+static int lib1t31 (void) { return 1; }
+static int lib1t32 (void) { return 2; }
+
+IFUNC_GLOBAL (lib1t3, lib1t31, lib1t32);
+
+int (*lib2p1) (void) = lib2t2;
+
+extern void abort (void);
+
+int
+lib2test (void)
+{
+ if (lib2t1 () != PICKNO)
+ abort ();
+ if (lib2t2 () != PICKNO)
+ abort ();
+ if (lib2t3 () != PICKNO)
+ abort ();
+ if (lib2p1 () != PICKNO)
+ abort ();
+ return 0;
+}
diff --git a/trunk/testsuite/ifunc2.sh b/trunk/testsuite/ifunc2.sh
new file mode 100755
index 0000000..dea5bf4
--- /dev/null
+++ b/trunk/testsuite/ifunc2.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+. `dirname $0`/functions.sh
+# First check if __thread is supported by ld.so/gcc/ld/as:
+$CCLINK -o ifunctest $srcdir/ifunctest.c -Wl,--rpath-link,. > /dev/null 2>&1 || exit 77
+( ./ifunctest || { rm -f ifunctest; exit 77; } ) 2>/dev/null || exit 77
+rm -f ifunctest ifunc2 ifunc2lib*.so ifunc2.log
+rm -f prelink.cache
+$CC -shared -O2 -fpic -o ifunc2lib1.so $srcdir/ifunc1lib1.c -DPICKNO=2
+$CC -shared -O2 -fpic -o ifunc2lib2.so $srcdir/ifunc1lib2.c ifunc2lib1.so -DPICKNO=2
+BINS="ifunc2"
+LIBS="ifunc2lib1.so ifunc2lib2.so"
+$CCLINK -o ifunc2 $srcdir/ifunc1.c -Wl,--rpath-link,. ifunc2lib2.so -DPICKNO=2
+savelibs
+echo $PRELINK ${PRELINK_OPTS--vm} ./ifunc2 >> ifunc2.log
+$PRELINK ${PRELINK_OPTS--vm} ./ifunc2 >> ifunc2.log 2>&1 || exit 1
+grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` ifunc2.log && exit 2
+LD_LIBRARY_PATH=. ./ifunc2 || exit 3
+readelf -a ./ifunc2 >> ifunc2.log 2>&1 || exit 4
+# So that it is not prelinked again
+chmod -x ./ifunc2
+comparelibs >> ifunc2.log 2>&1 || exit 5
diff --git a/trunk/testsuite/ifunc3.c b/trunk/testsuite/ifunc3.c
new file mode 100644
index 0000000..1f243d8
--- /dev/null
+++ b/trunk/testsuite/ifunc3.c
@@ -0,0 +1,32 @@
+#include "ifunc.h"
+
+static int bint11 (void) { return 1; }
+static int bint12 (void) { return 2; }
+
+IFUNC_LOCAL (bint1, bint11, bint12);
+
+static int lib2t21 (void) { return 1; }
+static int lib2t22 (void) { return 2; }
+
+IFUNC_GLOBAL (lib2t2, lib2t21, lib2t22);
+
+extern int lib1t2 (void);
+extern int lib1test (void);
+extern int lib2test (void);
+extern int (*lib1p1) (void);
+
+extern void abort (void);
+
+int
+main (void)
+{
+ lib1test ();
+ lib2test ();
+ if (bint1 () != PICKNO)
+ abort ();
+ if (lib1t2 () != PICKNO)
+ abort ();
+ if (lib1p1 () != PICKNO + 10)
+ abort ();
+ return 0;
+}
diff --git a/trunk/testsuite/ifunc3.sh b/trunk/testsuite/ifunc3.sh
new file mode 100755
index 0000000..a54d4ec
--- /dev/null
+++ b/trunk/testsuite/ifunc3.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+. `dirname $0`/functions.sh
+# First check if __thread is supported by ld.so/gcc/ld/as:
+$CCLINK -o ifunctest $srcdir/ifunctest.c -Wl,--rpath-link,. > /dev/null 2>&1 || exit 77
+( ./ifunctest || { rm -f ifunctest; exit 77; } ) 2>/dev/null || exit 77
+rm -f ifunctest ifunc3 ifunc3lib*.so ifunc3.log
+rm -f prelink.cache
+$CC -shared -O2 -fpic -o ifunc3lib1.so $srcdir/ifunc3lib1.c
+$CC -shared -O2 -fpic -o ifunc3lib2.so $srcdir/ifunc1lib2.c ifunc3lib1.so
+BINS="ifunc3"
+LIBS="ifunc3lib1.so ifunc3lib2.so"
+$CCLINK -o ifunc3 $srcdir/ifunc3.c -Wl,--rpath-link,. ifunc3lib2.so
+savelibs
+echo $PRELINK ${PRELINK_OPTS--vm} ./ifunc3 >> ifunc3.log
+$PRELINK ${PRELINK_OPTS--vm} ./ifunc3 >> ifunc3.log 2>&1 || exit 1
+grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` ifunc3.log && exit 2
+LD_LIBRARY_PATH=. ./ifunc3 || exit 3
+readelf -a ./ifunc3 >> ifunc3.log 2>&1 || exit 4
+# So that it is not prelinked again
+chmod -x ./ifunc3
+comparelibs >> ifunc3.log 2>&1 || exit 5
diff --git a/trunk/testsuite/ifunc3lib1.c b/trunk/testsuite/ifunc3lib1.c
new file mode 100644
index 0000000..133b389
--- /dev/null
+++ b/trunk/testsuite/ifunc3lib1.c
@@ -0,0 +1,37 @@
+#include "ifunc.h"
+
+static int lib1t11 (void) { return 11; }
+static int lib1t12 (void) { return 12; }
+
+IFUNC_LOCAL (lib1t1, lib1t11, lib1t12);
+
+static int lib1t21 (void) { return 1; }
+static int lib1t22 (void) { return 2; }
+
+IFUNC_GLOBAL (lib1t2, lib1t21, lib1t22);
+
+static int lib1t31 (void) { return 3; }
+static int lib1t32 (void) { return 4; }
+
+IFUNC_GLOBAL (lib1t3, lib1t31, lib1t32);
+
+char lib1b1[4];
+char *lib1b2 = &lib1b1[2];
+
+extern void abort (void);
+
+int (*lib1p1) (void) = lib1t1;
+
+int
+lib1test (void)
+{
+ if (lib1t1 () != PICKNO + 10)
+ abort ();
+ if (lib1t3 () != PICKNO)
+ abort ();
+ if (lib1p1 () != PICKNO + 10)
+ abort ();
+ if (lib1b2 != lib1b1 + 2)
+ abort ();
+ return 0;
+}
diff --git a/trunk/testsuite/ifunctest.c b/trunk/testsuite/ifunctest.c
new file mode 100644
index 0000000..9ce7b1a
--- /dev/null
+++ b/trunk/testsuite/ifunctest.c
@@ -0,0 +1,16 @@
+#include "ifunc.h"
+
+static int foo1 (void) { return 1; }
+static int foo2 (void) { return 2; }
+
+IFUNC_LOCAL (foo, foo1, foo2);
+
+extern void abort (void);
+
+int
+main (void)
+{
+ if (foo () != PICKNO)
+ abort ();
+ return 0;
+}