elf: Add tst-ldconfig-ld_so_conf-update test
[platform/upstream/glibc.git] / elf / ifuncmain9.c
1 /* Test for IFUNC handling with local definitions.
2    Copyright (C) 2019-2020 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <https://www.gnu.org/licenses/>.  */
18
19 /* This test is based on gcc.dg/attr-ifunc-4.c.  */
20
21 #include <config.h>
22
23 #ifdef HAVE_GCC_IFUNC
24
25 # include <stdbool.h>
26 # include <stdio.h>
27
28 /* Do not use the test framework, so that the process setup is not
29    disturbed.  */
30
31 static volatile int implementation_called;
32 static volatile int resolver_called;
33
34 /* Just a random constant, to check that we called the right
35    function.  */
36 enum { random_constant = 0x3a88d66d };
37
38 static int
39 implementation (void)
40 {
41   ++implementation_called;
42   return random_constant;
43 }
44
45 static __typeof__ (implementation) *
46 resolver (void)
47 {
48   ++resolver_called;
49   return implementation;
50 }
51
52 static int magic (void) __attribute__ ((ifunc ("resolver")));
53
54 int
55 main (void)
56 {
57   bool errors = false;
58
59   if (implementation_called != 0)
60     {
61       printf ("error: initial value of implementation_called is not zero:"
62               " %d\n", implementation_called);
63       errors = true;
64     }
65
66   /* This can be zero if the reference is bound lazily.  */
67   printf ("info: initial value of resolver_called: %d\n", resolver_called);
68
69   int magic_value = magic ();
70   if (magic_value != random_constant)
71     {
72       printf ("error: invalid magic value: 0x%x\n", magic_value);
73       errors = true;
74     }
75
76   printf ("info: resolver_called value: %d\n", resolver_called);
77   if (resolver_called == 0)
78     {
79       /* In theory, the resolver could be called multiple times if
80          several relocations are needed.  */
81       puts ("error: invalid resolver_called value (must not be zero)");
82       errors = true;
83     }
84
85   printf ("info: implementation_called value: %d\n", implementation_called);
86   if (implementation_called != 1)
87     {
88       puts ("error: invalid implementation_called value (must be 1)");
89       errors = true;
90     }
91
92   return errors;
93 }
94
95 #else  /* !HAVE_GCC_IFUNC */
96
97 # include <support/check.h>
98
99 static int
100 do_test (void)
101 {
102   FAIL_UNSUPPORTED ("GCC does not support the ifunc attribute");
103   return 1;                     /* Not reachable.  */
104 }
105
106 # include <support/test-driver.c>
107 #endif