Mention IFUNC enhancements to testsuite in NEWS.
[platform/upstream/glibc.git] / elf / nodelete.c
1 #include <dlfcn.h>
2 #include <setjmp.h>
3 #include <signal.h>
4 #include <stdio.h>
5
6
7 static sigjmp_buf jmpbuf;
8
9
10 int fini_ran;
11
12
13 static void
14 __attribute__ ((noreturn))
15 handler (int sig)
16 {
17   siglongjmp (jmpbuf, 1);
18 }
19
20
21 #define TEST_FUNCTION do_test ()
22 static int
23 do_test (void)
24 {
25   /* We are testing the two possibilities to mark an object as not deletable:
26      - marked on the linker commandline with `-z nodelete'
27      - with the RTLD_NODELETE flag at dlopen()-time.
28
29      The test we are performing should be safe.  We are loading the objects,
30      get the address of variables in the respective object, unload the object
31      and then try to read the variable.  If the object is unloaded this
32      should lead to an segmentation fault.  */
33   int result = 0;
34   void *p;
35   struct sigaction sa;
36
37   sa.sa_handler = handler;
38   sigfillset (&sa.sa_mask);
39   sa.sa_flags = SA_RESTART;
40
41   if (sigaction (SIGSEGV, &sa, NULL) == -1)
42     printf ("cannot install signal handler: %m\n");
43
44   p = dlopen ("nodelmod1.so", RTLD_LAZY);
45   if (p == NULL)
46     {
47       printf ("failed to load \"nodelmod1.so\": %s\n", dlerror ());
48       result = 1;
49     }
50   else
51     {
52       int *varp;
53
54       puts ("succeeded loading \"nodelmod1.so\"");
55
56       varp = dlsym (p, "var1");
57       if (varp == NULL)
58         {
59           puts ("failed to get address of \"var1\" in \"nodelmod1.so\"");
60           result = 1;
61         }
62       else
63         {
64           *varp = 20000720;
65
66           /* Now close the object.  */
67           fini_ran = 0;
68           if (dlclose (p) != 0)
69             {
70               puts ("failed to close \"nodelmod1.so\"");
71               result = 1;
72             }
73           else if (! sigsetjmp (jmpbuf, 1))
74             {
75               /* Access the variable again.  */
76               if (*varp != 20000720)
77                 {
78                   puts ("\"var1\" value not correct");
79                   result = 1;
80                 }
81               else if (fini_ran != 0)
82                 {
83                   puts ("destructor of \"nodelmod1.so\" ran");
84                   result = 1;
85                 }
86               else
87                 puts ("-z nodelete test succeeded");
88             }
89           else
90             {
91               /* We caught an segmentation fault.  */
92               puts ("\"nodelmod1.so\" got deleted");
93               result = 1;
94             }
95         }
96     }
97
98   p = dlopen ("nodelmod2.so", RTLD_LAZY | RTLD_NODELETE);
99   if (p == NULL)
100     {
101       printf ("failed to load \"nodelmod2.so\": %s\n", dlerror ());
102       result = 1;
103     }
104   else
105     {
106       int *varp;
107
108       puts ("succeeded loading \"nodelmod2.so\"");
109
110       varp = dlsym (p, "var2");
111       if (varp == NULL)
112         {
113           puts ("failed to get address of \"var2\" in \"nodelmod2.so\"");
114           result = 1;
115         }
116       else
117         {
118           *varp = 42;
119
120           /* Now close the object.  */
121           fini_ran = 0;
122           if (dlclose (p) != 0)
123             {
124               puts ("failed to close \"nodelmod2.so\"");
125               result = 1;
126             }
127           else if (! sigsetjmp (jmpbuf, 1))
128             {
129               /* Access the variable again.  */
130               if (*varp != 42)
131                 {
132                   puts ("\"var2\" value not correct");
133                   result = 1;
134                 }
135               else if (fini_ran != 0)
136                 {
137                   puts ("destructor of \"nodelmod2.so\" ran");
138                   result = 1;
139                 }
140               else
141                 puts ("RTLD_NODELETE test succeeded");
142             }
143           else
144             {
145               /* We caught an segmentation fault.  */
146               puts ("\"nodelmod2.so\" got deleted");
147               result = 1;
148             }
149         }
150     }
151
152   p = dlopen ("nodelmod3.so", RTLD_LAZY);
153   if (p == NULL)
154     {
155       printf ("failed to load \"nodelmod3.so\": %s\n", dlerror ());
156       result = 1;
157     }
158   else
159     {
160       int *(*fctp) (void);
161
162       puts ("succeeded loading \"nodelmod3.so\"");
163
164       fctp = dlsym (p, "addr");
165       if (fctp == NULL)
166         {
167           puts ("failed to get address of \"addr\" in \"nodelmod3.so\"");
168           result = 1;
169         }
170       else
171         {
172           int *varp = fctp ();
173
174           *varp = -1;
175
176           /* Now close the object.  */
177           fini_ran = 0;
178           if (dlclose (p) != 0)
179             {
180               puts ("failed to close \"nodelmod3.so\"");
181               result = 1;
182             }
183           else if (! sigsetjmp (jmpbuf, 1))
184             {
185               /* Access the variable again.  */
186               if (*varp != -1)
187                 {
188                   puts ("\"var_in_mod4\" value not correct");
189                   result = 1;
190                 }
191               else if (fini_ran != 0)
192                 {
193                   puts ("destructor of \"nodelmod4.so\" ran");
194                   result = 1;
195                 }
196               else
197                 puts ("-z nodelete in dependency succeeded");
198             }
199           else
200             {
201               /* We caught an segmentation fault.  */
202               puts ("\"nodelmod4.so\" got deleted");
203               result = 1;
204             }
205         }
206     }
207
208   return result;
209 }
210
211 #include "../test-skeleton.c"