1 | /* Test local STT_GNU_IFUNC symbols: |
2 | |
3 | 1. Direct function call. |
4 | 2. Function pointer. |
5 | */ |
6 | |
7 | #include <stdlib.h> |
8 | #include "ifunc-sel.h" |
9 | |
10 | extern int foo (void); |
11 | |
12 | static int |
13 | one (void) |
14 | { |
15 | return -30; |
16 | } |
17 | |
18 | static void * foo_ifunc (void) __asm__ ("foo" ); |
19 | __asm__(".type foo, %gnu_indirect_function" ); |
20 | |
21 | static void * |
22 | __attribute__ ((used)) |
23 | inhibit_stack_protector |
24 | foo_ifunc (void) |
25 | { |
26 | return ifunc_one (f1: one); |
27 | } |
28 | |
29 | typedef int (*foo_p) (void); |
30 | |
31 | foo_p foo_ptr = foo; |
32 | |
33 | foo_p |
34 | __attribute__ ((noinline)) |
35 | get_foo_p (void) |
36 | { |
37 | return foo_ptr; |
38 | } |
39 | |
40 | foo_p |
41 | __attribute__ ((noinline)) |
42 | get_foo (void) |
43 | { |
44 | return foo; |
45 | } |
46 | |
47 | int |
48 | main (void) |
49 | { |
50 | foo_p p; |
51 | |
52 | p = get_foo (); |
53 | if (p != foo) |
54 | abort (); |
55 | if ((*p) () != -30) |
56 | abort (); |
57 | |
58 | p = get_foo_p (); |
59 | if (p != foo) |
60 | abort (); |
61 | if ((*p) () != -30) |
62 | abort (); |
63 | |
64 | if (foo_ptr != foo) |
65 | abort (); |
66 | if ((*foo_ptr) () != -30) |
67 | abort (); |
68 | if (foo () != -30) |
69 | abort (); |
70 | |
71 | return 0; |
72 | } |
73 | |