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
12typedef int (*foo_p) (void);
13
14int
15__attribute__ ((noinline))
16foo (void)
17{
18 return -30;
19}
20
21int
22__attribute__ ((noinline))
23foo_hidden (void)
24{
25 return -20;
26}
27
28int
29__attribute__ ((noinline))
30foo_protected (void)
31{
32 return -40;
33}
34
35int
36main (void)
37{
38 foo_p p;
39 foo_p (*f) (void);
40 int *ret;
41
42 void *h = dlopen (file: "ifuncmod3.so", RTLD_LAZY);
43 if (h == NULL)
44 {
45 printf (format: "cannot load: %s\n", dlerror ());
46 return 1;
47 }
48
49 p = dlsym (handle: h, name: "foo");
50 if (p == NULL)
51 {
52 printf (format: "symbol not found: %s\n", dlerror ());
53 return 1;
54 }
55 if ((*p) () != -1)
56 abort ();
57
58 f = dlsym (handle: h, name: "get_foo_p");
59 if (f == NULL)
60 {
61 printf (format: "symbol not found: %s\n", dlerror ());
62 return 1;
63 }
64
65 ret = dlsym (handle: h, name: "ret_foo");
66 if (ret == NULL)
67 {
68 printf (format: "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 (handle: h, name: "get_foo_hidden_p");
81 if (f == NULL)
82 {
83 printf (format: "symbol not found: %s\n", dlerror ());
84 return 1;
85 }
86
87 ret = dlsym (handle: h, name: "ret_foo_hidden");
88 if (ret == NULL)
89 {
90 printf (format: "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 (handle: h, name: "get_foo_protected_p");
101 if (f == NULL)
102 {
103 printf (format: "symbol not found: %s\n", dlerror ());
104 return 1;
105 }
106
107 ret = dlsym (handle: h, name: "ret_foo_protected");
108 if (ret == NULL)
109 {
110 printf (format: "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 (handle: h) != 0)
123 {
124 printf (format: "cannot close: %s\n", dlerror ());
125 return 1;
126 }
127
128 return 0;
129}
130

source code of glibc/elf/ifuncmain3.c