diff options
Diffstat (limited to 'trunk/testsuite')
-rw-r--r-- | trunk/testsuite/Makefile.am | 1 | ||||
-rw-r--r-- | trunk/testsuite/Makefile.in | 1 | ||||
-rw-r--r-- | trunk/testsuite/ifunc.h | 33 | ||||
-rw-r--r-- | trunk/testsuite/ifunc1.c | 29 | ||||
-rwxr-xr-x | trunk/testsuite/ifunc1.sh | 21 | ||||
-rw-r--r-- | trunk/testsuite/ifunc1lib1.c | 32 | ||||
-rw-r--r-- | trunk/testsuite/ifunc1lib2.c | 39 | ||||
-rwxr-xr-x | trunk/testsuite/ifunc2.sh | 21 | ||||
-rw-r--r-- | trunk/testsuite/ifunc3.c | 32 | ||||
-rwxr-xr-x | trunk/testsuite/ifunc3.sh | 21 | ||||
-rw-r--r-- | trunk/testsuite/ifunc3lib1.c | 37 | ||||
-rw-r--r-- | trunk/testsuite/ifunctest.c | 16 |
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; +} |