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

source code of glibc/elf/nodelete.c