diff options
author | H.J. Lu <hongjiu.lu@intel.com> | 2009-06-03 16:21:40 -0700 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2009-06-03 16:21:40 -0700 |
commit | 2f083d7511460b3beea2df165c3e43742f73f3c9 (patch) | |
tree | db6421cac30909a7a0546460ca271d0b54158ea0 | |
parent | fbb04b35e7997070feec74e0fd46953faef71f9e (diff) | |
download | glibc-2f083d7511460b3beea2df165c3e43742f73f3c9.tar.gz glibc-2f083d7511460b3beea2df165c3e43742f73f3c9.tar.xz glibc-2f083d7511460b3beea2df165c3e43742f73f3c9.zip |
Test for ELF IFUNC functionality.
-rw-r--r-- | ChangeLog | 46 | ||||
-rw-r--r-- | elf/Makefile | 94 | ||||
-rw-r--r-- | elf/ifuncdep1.c | 3 | ||||
-rw-r--r-- | elf/ifuncdep1pic.c | 3 | ||||
-rw-r--r-- | elf/ifuncdep2.c | 72 | ||||
-rw-r--r-- | elf/ifuncdep2pic.c | 3 | ||||
-rw-r--r-- | elf/ifuncmain1.c | 66 | ||||
-rw-r--r-- | elf/ifuncmain1pic.c | 3 | ||||
-rw-r--r-- | elf/ifuncmain1picstatic.c | 3 | ||||
-rw-r--r-- | elf/ifuncmain1pie.c | 3 | ||||
-rw-r--r-- | elf/ifuncmain1static.c | 3 | ||||
-rw-r--r-- | elf/ifuncmain1staticpic.c | 3 | ||||
-rw-r--r-- | elf/ifuncmain1vis.c | 89 | ||||
-rw-r--r-- | elf/ifuncmain1vispic.c | 3 | ||||
-rw-r--r-- | elf/ifuncmain1vispie.c | 3 | ||||
-rw-r--r-- | elf/ifuncmain2.c | 16 | ||||
-rw-r--r-- | elf/ifuncmain2pic.c | 3 | ||||
-rw-r--r-- | elf/ifuncmain2picstatic.c | 3 | ||||
-rw-r--r-- | elf/ifuncmain2static.c | 3 | ||||
-rw-r--r-- | elf/ifuncmain3.c | 120 | ||||
-rw-r--r-- | elf/ifuncmain4.c | 4 | ||||
-rw-r--r-- | elf/ifuncmain4picstatic.c | 3 | ||||
-rw-r--r-- | elf/ifuncmain4static.c | 3 | ||||
-rw-r--r-- | elf/ifuncmod1.c | 114 | ||||
-rw-r--r-- | elf/ifuncmod3.c | 8 |
25 files changed, 673 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog index 5e98327e14..72910ce610 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,49 @@ +2009-06-02 H.J. Lu <hongjiu.lu@intel.com> + + * elf/Makefile (distribute): Add ifuncmain1.c, ifuncmain1pic.c, + ifuncmain1vis.c, ifuncmain1vispic.c, ifuncmain1static.c, + ifuncmain1staticpic.c, ifuncmain1picstatic.c, ifuncdep1.c, + ifuncdep1pic.c, ifuncmod1.c, ifuncmain1pie.c, ifuncmain1vispie.c, + ifuncmain2.c, ifuncmain2static.c, ifuncdep2.c, + funcmain2pic.c, ifuncmain2picstatic.c, ifuncdep2pic.c, + ifuncmain3.c, ifuncmod3.c,. + ifuncmain4.c, ifuncmain4static.c, ifuncmain4picstatic.c. + (tests-static): Add ifuncmain1static, ifuncmain1picstatic, + ifuncmain2static, ifuncmain2picstatic, ifuncmain4static, + ifuncmain4picstatic. + (tests): Add ifuncmain1, ifuncmain1pic, ifuncmain1vis, + ifuncmain1vispic, ifuncmain1staticpic, ifuncmain2, ifuncmain2pic, + ifuncmain3, ifuncmain4. + (tests): Depend on $(objpfx)ifuncmain1pie.out and + $(objpfx)ifuncmain1vispie.out. + (modules-names): Add ifuncmod1 ifuncmod3. + (generated): Add ifuncmain1pie ifuncmain1pie.out + ifuncmain1vispie ifuncmain1vispie.out. + Define rules to build and run the tests. + * elf/ifuncdep1.c: New file. + * elf/ifuncdep1pic.c: New file. + * elf/ifuncdep2.c: New file. + * elf/ifuncdep2pic.c: New file. + * elf/ifuncmain1.c: New file. + * elf/ifuncmain1pic.c: New file. + * elf/ifuncmain1picstatic.c: New file. + * elf/ifuncmain1pie.c: New file. + * elf/ifuncmain1static.c: New file. + * elf/ifuncmain1staticpic.c: New file. + * elf/ifuncmain1vis.c: New file.. + * elf/ifuncmain1vispic.c: New file.. + * elf/ifuncmain1vispie.c: New file. + * elf/ifuncmain2.c: New file. + * elf/ifuncmain2pic.c: New file. + * elf/ifuncmain2picstatic.c: New file. + * elf/ifuncmain2static.c: New file. + * elf/ifuncmain3.c: New file. + * elf/ifuncmain4.c: New file. + * elf/ifuncmain4picstatic.c: New file. + * elf/ifuncmain4static.c: New file. + * elf/ifuncmod1.c: New file. + * elf/ifuncmod3.c: New file. + 2009-06-03 Ulrich Drepper <drepper@redhat.com> * elf/dl-sysdep.c (_dl_show_auxv): Terminate correct string. diff --git a/elf/Makefile b/elf/Makefile index 94b9d069bf..6bcbb5142f 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -93,7 +93,16 @@ distribute := rtld-Rules \ order2mod1.c order2mod2.c order2mod3.c order2mod4.c \ tst-stackguard1.c tst-stackguard1-static.c \ tst-array5.c tst-array5-static.c tst-array5dep.c \ - tst-array5.exp tst-leaks1.c check-execstack.c + tst-array5.exp tst-leaks1.c check-execstack.c \ + ifuncmain1.c ifuncmain1pic.c ifuncmain1vis.c \ + ifuncmain1vispic.c ifuncmain1static.c \ + ifuncmain1staticpic.c ifuncmain1picstatic.c \ + ifuncdep1.c ifuncdep1pic.c ifuncmod1.c \ + ifuncmain1pie.c ifuncmain1vispie.c \ + ifuncmain2.c ifuncmain2static.c ifuncdep2.c \ + ifuncmain2pic.c ifuncmain2picstatic.c ifuncdep2pic.c \ + ifuncmain3.c ifuncmod3.c \ + ifuncmain4.c ifuncmain4static.c ifuncmain4picstatic.c CFLAGS-dl-runtime.c = -fexceptions -fasynchronous-unwind-tables CFLAGS-dl-lookup.c = -fexceptions -fasynchronous-unwind-tables @@ -232,6 +241,22 @@ test-extras += $(modules-names) # filtmod1.so has a special rule modules-names-nobuild := filtmod1 +ifeq (yes,$(multi-arch)) +tests-static += ifuncmain1static ifuncmain1picstatic \ + ifuncmain2static ifuncmain2picstatic \ + ifuncmain4static ifuncmain4picstatic + +ifeq (yes,$(build-shared)) +tests += ifuncmain1 ifuncmain1pic ifuncmain1vis ifuncmain1vispic \ + ifuncmain1staticpic \ + ifuncmain2 ifuncmain2pic ifuncmain3 ifuncmain4 +ifeq (yes,$(have-fpie)) +tests: $(objpfx)ifuncmain1pie.out $(objpfx)ifuncmain1vispie.out +endif +modules-names += ifuncmod1 ifuncmod3 +endif +endif + include ../Rules @@ -504,6 +529,7 @@ reldep8mod2.so-no-z-defs = yes reldep9mod1.so-no-z-defs = yes unload3mod4.so-no-z-defs = yes unload4mod1.so-no-z-defs = yes +ifuncmod1.so-no-z-defs = yes ifeq ($(build-shared),yes) # Build all the modules even when not actually running test programs. @@ -951,3 +977,69 @@ tst-leaks1-ENV = MALLOC_TRACE=$(objpfx)tst-leaks1.mtrace $(objpfx)tst-addr1: $(libdl) $(objpfx)tst-thrlock: $(libdl) $(shared-thread-library) + +CFLAGS-ifuncmain1pic.c += $(pic-ccflag) +CFLAGS-ifuncmain1picstatic.c += $(pic-ccflag) +CFLAGS-ifuncmain1staticpic.c += $(pic-ccflag) +CFLAGS-ifuncdep1pic.c += $(pic-ccflag) +CFLAGS-ifuncmain1vispic.c += $(pic-ccflag) +CFLAGS-ifuncmain2pic.c += $(pic-ccflag) +CFLAGS-ifuncmain2picstatic.c += $(pic-ccflag) +CFLAGS-ifuncdep2pic.c += $(pic-ccflag) +CFLAGS-ifuncmain4picstatic.c += $(pic-ccflag) + +LDFLAGS-ifuncmain3 = -Wl,-export-dynamic + +ifeq (yesyes,$(have-fpie)$(build-shared)) +CFLAGS-ifuncmain1pie.c += $(pie-ccflag) +CFLAGS-ifuncmain1vispie.c += $(pie-ccflag) + +$(objpfx)ifuncmain1pie.out: $(objpfx)ifuncmain1pie + $(elf-objpfx)$(rtld-installed-name) \ + --library-path $(rpath-link)$(patsubst %,:%,$(sysdep-library-path)) \ + $< > $@ + +$(objpfx)ifuncmain1pie: $(objpfx)ifuncmain1pie.o $(objpfx)ifuncmod1.so + $(LINK.o) -pie -Wl,-O1 \ + $(sysdep-LDFLAGS) $(config-LDFLAGS) \ + $(extra-B-$(@F:lib%.so=%).so) -B$(csu-objpfx) \ + $(extra-B-$(@F:lib%.so=%).so) $(load-map-file) \ + $(LDFLAGS) $(LDFLAGS-$(@F)) \ + -L$(subst :, -L,$(rpath-link)) -Wl,-rpath-link=$(rpath-link) \ + -o $@ $(objpfx)tst-pie1.o $(objpfx)tst-piemod1.so \ + $(common-objpfx)libc_nonshared.a + +generated += ifuncmain1pie ifuncmain1pie.out + +$(objpfx)ifuncmain1vispie.out: $(objpfx)ifuncmain1vispie + $(elf-objpfx)$(rtld-installed-name) \ + --library-path $(rpath-link)$(patsubst %,:%,$(sysdep-library-path)) \ + $< > $@ + +$(objpfx)ifuncmain1vispie: $(objpfx)ifuncmain1vispie.o $(objpfx)ifuncmod1.so + $(LINK.o) -pie -Wl,-O1 \ + $(sysdep-LDFLAGS) $(config-LDFLAGS) \ + $(extra-B-$(@F:lib%.so=%).so) -B$(csu-objpfx) \ + $(extra-B-$(@F:lib%.so=%).so) $(load-map-file) \ + $(LDFLAGS) $(LDFLAGS-$(@F)) \ + -L$(subst :, -L,$(rpath-link)) -Wl,-rpath-link=$(rpath-link) \ + -o $@ $(objpfx)tst-pie1.o $(objpfx)tst-piemod1.so \ + $(common-objpfx)libc_nonshared.a + +generated += ifuncmain1vispie ifuncmain1vispie.out +endif + +$(objpfx)ifuncmain1: $(addprefix $(objpfx),ifuncmod1.so) +$(objpfx)ifuncmain1pic: $(addprefix $(objpfx),ifuncmod1.so) +$(objpfx)ifuncmain1staticpic: $(addprefix $(objpfx),ifuncdep1pic.o) +$(objpfx)ifuncmain1static: $(addprefix $(objpfx),ifuncdep1.o) +$(objpfx)ifuncmain1picstatic: $(addprefix $(objpfx),ifuncdep1pic.o) +$(objpfx)ifuncmain1vis: $(addprefix $(objpfx),ifuncmod1.so) +$(objpfx)ifuncmain1vispic: $(addprefix $(objpfx),ifuncmod1.so) +$(objpfx)ifuncmain2: $(addprefix $(objpfx),ifuncdep2.o) +$(objpfx)ifuncmain2pic: $(addprefix $(objpfx),ifuncdep2pic.o) +$(objpfx)ifuncmain2static: $(addprefix $(objpfx),ifuncdep2.o) +$(objpfx)ifuncmain2picstatic: $(addprefix $(objpfx),ifuncdep2pic.o) + +$(objpfx)ifuncmain3: $(libdl) +$(objpfx)ifuncmain3.out: $(objpfx)ifuncmod3.so diff --git a/elf/ifuncdep1.c b/elf/ifuncdep1.c new file mode 100644 index 0000000000..77d663dcec --- /dev/null +++ b/elf/ifuncdep1.c @@ -0,0 +1,3 @@ +/* Test STT_GNU_IFUNC symbols without -fPIC. */ + +#include "ifuncmod1.c" diff --git a/elf/ifuncdep1pic.c b/elf/ifuncdep1pic.c new file mode 100644 index 0000000000..b6381e4868 --- /dev/null +++ b/elf/ifuncdep1pic.c @@ -0,0 +1,3 @@ +/* Test STT_GNU_IFUNC symbols with -fPIC. */ + +#include "ifuncmod1.c" diff --git a/elf/ifuncdep2.c b/elf/ifuncdep2.c new file mode 100644 index 0000000000..fb21eef5cb --- /dev/null +++ b/elf/ifuncdep2.c @@ -0,0 +1,72 @@ +/* Test 3 STT_GNU_IFUNC symbols. */ + +extern int global; + +static int +one (void) +{ + return 1; +} + +static int +minus_one (void) +{ + return -1; +} + +static int +zero (void) +{ + return 0; +} + +void * foo1_ifunc (void) __asm__ ("foo1"); +__asm__(".type foo1, %gnu_indirect_function"); + +void * +foo1_ifunc (void) +{ + switch (global) + { + case 1: + return one; + case -1: + return minus_one; + default: + return zero; + } +} + +void * foo2_ifunc (void) __asm__ ("foo2"); +__asm__(".type foo2, %gnu_indirect_function"); + +void * +foo2_ifunc (void) +{ + switch (global) + { + case 1: + return minus_one; + case -1: + return one; + default: + return zero; + } +} + +void * foo3_ifunc (void) __asm__ ("foo3"); +__asm__(".type foo3, %gnu_indirect_function"); + +void * +foo3_ifunc (void) +{ + switch (global) + { + case 1: + return one; + case -1: + return zero; + default: + return minus_one; + } +} diff --git a/elf/ifuncdep2pic.c b/elf/ifuncdep2pic.c new file mode 100644 index 0000000000..a84253dbc4 --- /dev/null +++ b/elf/ifuncdep2pic.c @@ -0,0 +1,3 @@ +/* Test STT_GNU_IFUNC symbols with -fPIC. */ + +#include "ifuncdep2.c" diff --git a/elf/ifuncmain1.c b/elf/ifuncmain1.c new file mode 100644 index 0000000000..de7ffe8779 --- /dev/null +++ b/elf/ifuncmain1.c @@ -0,0 +1,66 @@ +/* Test STT_GNU_IFUNC symbols: + + 1. Direct function call. + 2. Function pointer. + 3. Visibility without override. + */ + +#include <stdlib.h> + +int global = -1; + +int ret_foo; +int ret_foo_hidden; +int ret_foo_protected; + +extern int foo (void); +extern int foo_protected (void); + +#ifndef FOO_P +typedef int (*foo_p) (void); +#endif + +foo_p foo_ptr = foo; +foo_p foo_procted_ptr = foo_protected; + +extern foo_p get_foo_p (void); +extern foo_p get_foo_hidden_p (void); +extern foo_p get_foo_protected_p (void); + +int +main (void) +{ + foo_p p; + + if (foo_ptr != foo) + abort (); + if (foo () != -1) + abort (); + if ((*foo_ptr) () != -1) + abort (); + + if (foo_procted_ptr != foo_protected) + abort (); + if (foo_protected () != 0) + abort (); + if ((*foo_procted_ptr) () != 0) + abort (); + + p = get_foo_p (); + if (p != foo) + abort (); + if (ret_foo != -1 || (*p) () != ret_foo) + abort (); + + p = get_foo_hidden_p (); + if (ret_foo_hidden != 1 || (*p) () != ret_foo_hidden) + abort (); + + p = get_foo_protected_p (); + if (p != foo_protected) + abort (); + if (ret_foo_protected != 0 || (*p) () != ret_foo_protected) + abort (); + + return 0; +} diff --git a/elf/ifuncmain1pic.c b/elf/ifuncmain1pic.c new file mode 100644 index 0000000000..db19dc9678 --- /dev/null +++ b/elf/ifuncmain1pic.c @@ -0,0 +1,3 @@ +/* Test STT_GNU_IFUNC symbols with -fPIC. */ + +#include "ifuncmain1.c" diff --git a/elf/ifuncmain1picstatic.c b/elf/ifuncmain1picstatic.c new file mode 100644 index 0000000000..c937933029 --- /dev/null +++ b/elf/ifuncmain1picstatic.c @@ -0,0 +1,3 @@ +/* Test STT_GNU_IFUNC symbols with -fPIC and -static. */ + +#include "ifuncmain1.c" diff --git a/elf/ifuncmain1pie.c b/elf/ifuncmain1pie.c new file mode 100644 index 0000000000..c16ef6dd09 --- /dev/null +++ b/elf/ifuncmain1pie.c @@ -0,0 +1,3 @@ +/* Test STT_GNU_IFUNC symbols with PIE. */ + +#include "ifuncmain1.c" diff --git a/elf/ifuncmain1static.c b/elf/ifuncmain1static.c new file mode 100644 index 0000000000..fdd1e09024 --- /dev/null +++ b/elf/ifuncmain1static.c @@ -0,0 +1,3 @@ +/* Test STT_GNU_IFUNC symbols with -static. */ + +#include "ifuncmain1.c" diff --git a/elf/ifuncmain1staticpic.c b/elf/ifuncmain1staticpic.c new file mode 100644 index 0000000000..39e0cbb4b8 --- /dev/null +++ b/elf/ifuncmain1staticpic.c @@ -0,0 +1,3 @@ +/* Test STT_GNU_IFUNC symbols with -fPIC and no DSO. */ + +#include "ifuncmain1.c" diff --git a/elf/ifuncmain1vis.c b/elf/ifuncmain1vis.c new file mode 100644 index 0000000000..a239d2dd0d --- /dev/null +++ b/elf/ifuncmain1vis.c @@ -0,0 +1,89 @@ +/* Test STT_GNU_IFUNC symbols: + + 1. Direct function call. + 2. Function pointer. + 3. Visibility with override. + */ + +#include <stdlib.h> + +int global = -1; + +int ret_foo; +int ret_foo_hidden; +int ret_foo_protected; + +extern int foo (void); +extern int foo_protected (void); + +#ifndef FOO_P +typedef int (*foo_p) (void); +#endif + +foo_p foo_ptr = foo; +foo_p foo_procted_ptr = foo_protected; + +extern foo_p get_foo_p (void); +extern foo_p get_foo_hidden_p (void); +extern foo_p get_foo_protected_p (void); + +int +__attribute__ ((noinline)) +foo (void) +{ + return -30; +} + +int +__attribute__ ((noinline)) +foo_hidden (void) +{ + return -20; +} + +int +__attribute__ ((noinline)) +foo_protected (void) +{ + return -40; +} + +int +main (void) +{ + foo_p p; + + if (foo_ptr != foo) + abort (); + if ((*foo_ptr) () != -30) + abort (); + + if (foo_procted_ptr != foo_protected) + abort (); + if ((*foo_procted_ptr) () != -40) + abort (); + + p = get_foo_p (); + if (p != foo) + abort (); + if (foo () != -30) + abort (); + if (ret_foo != -30 || (*p) () != ret_foo) + abort (); + + p = get_foo_hidden_p (); + if (foo_hidden () != -20) + abort (); + if (ret_foo_hidden != 1 || (*p) () != ret_foo_hidden) + abort (); + + p = get_foo_protected_p (); + if (p == foo_protected) + abort (); + if (foo_protected () != -40) + abort (); + if (ret_foo_protected != 0 || (*p) () != ret_foo_protected) + abort (); + + return 0; +} diff --git a/elf/ifuncmain1vispic.c b/elf/ifuncmain1vispic.c new file mode 100644 index 0000000000..f8c104d560 --- /dev/null +++ b/elf/ifuncmain1vispic.c @@ -0,0 +1,3 @@ +/* Test STT_GNU_IFUNC symbols with -fPIC. */ + +#include "ifuncmain1vis.c" diff --git a/elf/ifuncmain1vispie.c b/elf/ifuncmain1vispie.c new file mode 100644 index 0000000000..ad06d2ba1c --- /dev/null +++ b/elf/ifuncmain1vispie.c @@ -0,0 +1,3 @@ +/* Test STT_GNU_IFUNC symbols with PIE. */ + +#include "ifuncmain1vis.c" diff --git a/elf/ifuncmain2.c b/elf/ifuncmain2.c new file mode 100644 index 0000000000..cd9b2c8352 --- /dev/null +++ b/elf/ifuncmain2.c @@ -0,0 +1,16 @@ +/* Test calling one STT_GNU_IFUNC function with 3 different + STT_GNU_IFUNC definitions. */ + +#include <stdlib.h> + +int global = -1; + +extern int foo1 (void); + +int +main (void) +{ + if (foo1 () != -1) + abort (); + return 0; +} diff --git a/elf/ifuncmain2pic.c b/elf/ifuncmain2pic.c new file mode 100644 index 0000000000..0006012a96 --- /dev/null +++ b/elf/ifuncmain2pic.c @@ -0,0 +1,3 @@ +/* Test STT_GNU_IFUNC symbols with -fPIC. */ + +#include "ifuncmain2.c" diff --git a/elf/ifuncmain2picstatic.c b/elf/ifuncmain2picstatic.c new file mode 100644 index 0000000000..3e89db536d --- /dev/null +++ b/elf/ifuncmain2picstatic.c @@ -0,0 +1,3 @@ +/* Test STT_GNU_IFUNC symbols with -fPIC and -static. */ + +#include "ifuncmain2.c" diff --git a/elf/ifuncmain2static.c b/elf/ifuncmain2static.c new file mode 100644 index 0000000000..6932ae8066 --- /dev/null +++ b/elf/ifuncmain2static.c @@ -0,0 +1,3 @@ +/* Test STT_GNU_IFUNC symbols with -static. */ + +#include "ifuncmain2.c" diff --git a/elf/ifuncmain3.c b/elf/ifuncmain3.c new file mode 100644 index 0000000000..5d067cced9 --- /dev/null +++ b/elf/ifuncmain3.c @@ -0,0 +1,120 @@ +/* Test STT_GNU_IFUNC symbols with dlopen: + + 1. Direct function call. + 2. Function pointer. + 3. Visibility with override. + */ + +#include <dlfcn.h> +#include <stdlib.h> +#include <stdio.h> + +typedef int (*foo_p) (void); + +int +__attribute__ ((noinline)) +foo (void) +{ + return -30; +} + +int +__attribute__ ((noinline)) +foo_hidden (void) +{ + return -20; +} + +int +__attribute__ ((noinline)) +foo_protected (void) +{ + return -40; +} + +int +main (void) +{ + foo_p p; + foo_p (*f) (void); + int *ret; + + void *h = dlopen ("ifuncmod3.so", RTLD_LAZY); + if (h == NULL) + { + printf ("cannot load: %s\n", dlerror ()); + return 1; + } + + f = dlsym (h, "get_foo_p"); + if (f == NULL) + { + printf ("symbol not found: %s\n", dlerror ()); + return 1; + } + + ret = dlsym (h, "ret_foo"); + if (ret == NULL) + { + printf ("symbol not found: %s\n", dlerror ()); + return 1; + } + + p = (*f) (); + if (p != foo) + abort (); + if (foo () != -30) + abort (); + if (*ret != -30 || (*p) () != *ret) + abort (); + + f = dlsym (h, "get_foo_hidden_p"); + if (f == NULL) + { + printf ("symbol not found: %s\n", dlerror ()); + return 1; + } + + ret = dlsym (h, "ret_foo_hidden"); + if (ret == NULL) + { + printf ("symbol not found: %s\n", dlerror ()); + return 1; + } + + p = (*f) (); + if (foo_hidden () != -20) + abort (); + if (*ret != 1 || (*p) () != *ret) + abort (); + + f = dlsym (h, "get_foo_protected_p"); + if (f == NULL) + { + printf ("symbol not found: %s\n", dlerror ()); + return 1; + } + + ret = dlsym (h, "ret_foo_protected"); + if (ret == NULL) + { + printf ("symbol not found: %s\n", dlerror ()); + return 1; + } + + p = (*f) (); + if (p == foo_protected) + abort (); + if (foo_protected () != -40) + abort (); + if (*ret != 0 || (*p) () != *ret) + abort (); + + if (dlclose (h) != 0) + { + printf ("cannot close: %s\n", dlerror ()); + return 1; + } + + return 0; +} diff --git a/elf/ifuncmain4.c b/elf/ifuncmain4.c new file mode 100644 index 0000000000..e55fee2eb3 --- /dev/null +++ b/elf/ifuncmain4.c @@ -0,0 +1,4 @@ +/* Test STT_GNU_IFUNC symbols in a single source file. */ + +#include "ifuncmod1.c" +#include "ifuncmain1.c" diff --git a/elf/ifuncmain4picstatic.c b/elf/ifuncmain4picstatic.c new file mode 100644 index 0000000000..977d7f97fc --- /dev/null +++ b/elf/ifuncmain4picstatic.c @@ -0,0 +1,3 @@ +/* Test STT_GNU_IFUNC symbols with -fPIC and -static. */ + +#include "ifuncmain4.c" diff --git a/elf/ifuncmain4static.c b/elf/ifuncmain4static.c new file mode 100644 index 0000000000..c399977013 --- /dev/null +++ b/elf/ifuncmain4static.c @@ -0,0 +1,3 @@ +/* Test STT_GNU_IFUNC symbols with -static. */ + +#include "ifuncmain4.c" diff --git a/elf/ifuncmod1.c b/elf/ifuncmod1.c new file mode 100644 index 0000000000..a1697b596d --- /dev/null +++ b/elf/ifuncmod1.c @@ -0,0 +1,114 @@ +/* Test STT_GNU_IFUNC symbols: + + 1. Direct function call. + 2. Function pointer. + 3. Visibility. + */ + +extern int global; + +static int +one (void) +{ + return 1; +} + +static int +minus_one (void) +{ + return -1; +} + +static int +zero (void) +{ + return 0; +} + +void * foo_ifunc (void) __asm__ ("foo"); +__asm__(".type foo, %gnu_indirect_function"); + +void * +foo_ifunc (void) +{ + switch (global) + { + case 1: + return one; + case -1: + return minus_one; + default: + return zero; + } +} + +void * foo_hidden_ifunc (void) __asm__ ("foo_hidden"); +__asm__(".type foo_hidden, %gnu_indirect_function"); + +void * +foo_hidden_ifunc (void) +{ + switch (global) + { + case 1: + return minus_one; + case -1: + return one; + default: + return zero; + } +} + +void * foo_protected_ifunc (void) __asm__ ("foo_protected"); +__asm__(".type foo_protected, %gnu_indirect_function"); + +void * +foo_protected_ifunc (void) +{ + switch (global) + { + case 1: + return one; + case -1: + return zero; + default: + return minus_one; + } +} + +/* Test hidden indirect function. */ +__asm__(".hidden foo_hidden"); + +/* Test protected indirect function. */ +__asm__(".protected foo_protected"); + +extern int foo (void); +extern int foo_hidden (void); +extern int foo_protected (void); +extern int ret_foo; +extern int ret_foo_hidden; +extern int ret_foo_protected; + +#define FOO_P +typedef int (*foo_p) (void); + +foo_p +get_foo_p (void) +{ + ret_foo = foo (); + return foo; +} + +foo_p +get_foo_hidden_p (void) +{ + ret_foo_hidden = foo_hidden (); + return foo_hidden; +} + +foo_p +get_foo_protected_p (void) +{ + ret_foo_protected = foo_protected (); + return foo_protected; +} diff --git a/elf/ifuncmod3.c b/elf/ifuncmod3.c new file mode 100644 index 0000000000..379d2c8d53 --- /dev/null +++ b/elf/ifuncmod3.c @@ -0,0 +1,8 @@ +/* Test STT_GNU_IFUNC symbols with dlopen. */ + +#include "ifuncmod1.c" + +int ret_foo; +int ret_foo_hidden; +int ret_foo_protected; +int global = -1; |