1 /* Test STT_GNU_IFUNC symbols with dlopen:
2 
3    1. Direct function call.
4    2. Function pointer.
5    3. Visibility with override.
6  */
7 
8 #include <dlfcn.h>
9 #include <stdlib.h>
10 #include <stdio.h>
11 
12 typedef int (*foo_p) (void);
13 
14 int
15 __attribute__ ((noinline))
foo(void)16 foo (void)
17 {
18   return -30;
19 }
20 
21 int
22 __attribute__ ((noinline))
foo_hidden(void)23 foo_hidden (void)
24 {
25   return -20;
26 }
27 
28 int
29 __attribute__ ((noinline))
foo_protected(void)30 foo_protected (void)
31 {
32   return -40;
33 }
34 
35 int
main(void)36 main (void)
37 {
38   foo_p p;
39   foo_p (*f) (void);
40   int *ret;
41 
42   void *h = dlopen ("ifuncmod3.so", RTLD_LAZY);
43   if (h == NULL)
44     {
45       printf ("cannot load: %s\n", dlerror ());
46       return 1;
47     }
48 
49   p = dlsym (h, "foo");
50   if (p == NULL)
51     {
52       printf ("symbol not found: %s\n", dlerror ());
53       return 1;
54     }
55   if ((*p) () != -1)
56     abort ();
57 
58   f = dlsym (h, "get_foo_p");
59   if (f == NULL)
60     {
61       printf ("symbol not found: %s\n", dlerror ());
62       return 1;
63     }
64 
65   ret = dlsym (h, "ret_foo");
66   if (ret == NULL)
67     {
68       printf ("symbol not found: %s\n", dlerror ());
69       return 1;
70     }
71 
72   p = (*f) ();
73   if (p != foo)
74     abort ();
75   if (foo () != -30)
76     abort ();
77   if (*ret != -30 || (*p) () != *ret)
78     abort ();
79 
80   f = dlsym (h, "get_foo_hidden_p");
81   if (f == NULL)
82     {
83       printf ("symbol not found: %s\n", dlerror ());
84       return 1;
85     }
86 
87   ret = dlsym (h, "ret_foo_hidden");
88   if (ret == NULL)
89     {
90       printf ("symbol not found: %s\n", dlerror ());
91       return 1;
92     }
93 
94   p = (*f) ();
95   if (foo_hidden () != -20)
96     abort ();
97   if (*ret != 1 || (*p) () != *ret)
98     abort ();
99 
100   f = dlsym (h, "get_foo_protected_p");
101   if (f == NULL)
102     {
103       printf ("symbol not found: %s\n", dlerror ());
104       return 1;
105     }
106 
107   ret = dlsym (h, "ret_foo_protected");
108   if (ret == NULL)
109     {
110       printf ("symbol not found: %s\n", dlerror ());
111       return 1;
112     }
113 
114   p = (*f) ();
115   if (p == foo_protected)
116     abort ();
117   if (foo_protected () != -40)
118     abort ();
119   if (*ret != 0 || (*p) () != *ret)
120     abort ();
121 
122   if (dlclose (h) != 0)
123     {
124       printf ("cannot close: %s\n", dlerror ());
125       return 1;
126     }
127 
128   return 0;
129 }
130