This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PATCH: Add STT_GNU_IFUNC tests


Hi,

This patch adds some STT_GNU_IFUNC tests. Tested on Linux/ia32 and
Linux/Intel64. The Linux binutils 2.19.51.0.8 is needed to pass all
tests.

Thanks.


H.J.
---
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.
	$(objpfx)ifuncmain1vispie.out.
	(modules-names): Add ifuncmod1 ifuncmod3.
	(ifuncmod1.so-no-z-defs): New.
	(CFLAGS-ifuncmain1pic.c): Likewise.
	(CFLAGS-ifuncmain1picstatic.c): Likewise.
	(CFLAGS-ifuncmain1staticpic.c): Likewise.
	(CFLAGS-ifuncdep1pic.c): Likewise.
	(CFLAGS-ifuncmain1vispic.c): Likewise.
	(CFLAGS-ifuncmain2pic.c): Likewise.
	(CFLAGS-ifuncmain2picstatic.c): Likewise.
	(CFLAGS-ifuncdep2pic.c): Likewise.
	(CFLAGS-ifuncmain4picstatic.c): Likewise.
	(LDFLAGS-ifuncmain3): Likewise.
	(CFLAGS-ifuncmain1pie.c): Likewise.
	(CFLAGS-ifuncmain1vispie.c): Likewise.
	($(objpfx)ifuncmain1pie.out): Likewise.
	($(objpfx)ifuncmain1pie): Likewise.
	($(objpfx)ifuncmain1vispie.out): Likewise.
	($(objpfx)ifuncmain1vispie): Likewise.
	($(objpfx)ifuncmain1): Likewise.
	($(objpfx)ifuncmain1pic): Likewise.
	($(objpfx)ifuncmain1staticpic): Likewise.
	($(objpfx)ifuncmain1static): Likewise.
	($(objpfx)ifuncmain1picstatic): Likewise.
	($(objpfx)ifuncmain1vis): Likewise.
	($(objpfx)ifuncmain1vispic): Likewise.
	($(objpfx)ifuncmain2): Likewise.
	($(objpfx)ifuncmain2pic): Likewise.
	($(objpfx)ifuncmain2stati): Likewise.
	($(objpfx)ifuncmain2picstatic): Likewise.
	($(objpfx)ifuncmain3): Likewise.
	($(objpfx)ifuncmain3.out): Likewise.
	(generated): Add ifuncmain1pie ifuncmain1pie.out
	ifuncmain1vispie ifuncmain1vispie.out.

	* elf/ifuncdep1.c: New.
	* elf/ifuncdep1pic.c: Likewise.
	* elf/ifuncdep2.c: Likewise.
	* elf/ifuncdep2pic.c: Likewise.
	* elf/ifuncmain1.c: Likewise.
	* elf/ifuncmain1pic.c: Likewise.
	* elf/ifuncmain1picstatic.c: Likewise.
	* elf/ifuncmain1pie.c: Likewise.
	* elf/ifuncmain1static.c: Likewise.
	* elf/ifuncmain1staticpic.c: Likewise.
	* elf/ifuncmain1vis.c: Likewise.
	* elf/ifuncmain1vispic.c: Likewise.
	* elf/ifuncmain1vispie.c: Likewise.
	* elf/ifuncmain2.c: Likewise.
	* elf/ifuncmain2pic.c: Likewise.
	* elf/ifuncmain2picstatic.c: Likewise.
	* elf/ifuncmain2static.c: Likewise.
	* elf/ifuncmain3.c: Likewise.
	* elf/ifuncmain4.c: Likewise.
	* elf/ifuncmain4picstatic.c: Likewise.
	* elf/ifuncmain4static.c: Likewise.
	* elf/ifuncmod1.c: Likewise.
	* elf/ifuncmod3.c: Likewise.

index 94b9d06..6bcbb51 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 0000000..77d663d
--- /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 0000000..b6381e4
--- /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 0000000..fb21eef
--- /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 0000000..a84253d
--- /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 0000000..de7ffe8
--- /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 0000000..db19dc9
--- /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 0000000..c937933
--- /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 0000000..c16ef6d
--- /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 0000000..fdd1e09
--- /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 0000000..39e0cbb
--- /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 0000000..a239d2d
--- /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 0000000..f8c104d
--- /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 0000000..ad06d2b
--- /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 0000000..cd9b2c8
--- /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 0000000..0006012
--- /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 0000000..3e89db5
--- /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 0000000..6932ae8
--- /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 0000000..5d067cc
--- /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 0000000..e55fee2
--- /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 0000000..977d7f9
--- /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 0000000..c399977
--- /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 0000000..a1697b5
--- /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 0000000..379d2c8
--- /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;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]