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