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))
handler(int sig)15 handler (int sig)
16 {
17   siglongjmp (jmpbuf, 1);
18 }
19 
20 
21 static int
do_test(void)22 do_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 (&sa.sa_mask);
38   sa.sa_flags = SA_RESTART;
39 
40   if (sigaction (SIGSEGV, &sa, NULL) == -1)
41     printf ("cannot install signal handler: %m\n");
42 
43   p = dlopen ("nodelmod1.so", RTLD_LAZY);
44   if (p == NULL)
45     {
46       printf ("failed to load \"nodelmod1.so\": %s\n", dlerror ());
47       result = 1;
48     }
49   else
50     {
51       int *varp;
52 
53       puts ("succeeded loading \"nodelmod1.so\"");
54 
55       varp = dlsym (p, "var1");
56       if (varp == NULL)
57 	{
58 	  puts ("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 (p) != 0)
68 	    {
69 	      puts ("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 ("\"var1\" value not correct");
78 		  result = 1;
79 		}
80 	      else if (fini_ran != 0)
81 		{
82 		  puts ("destructor of \"nodelmod1.so\" ran");
83 		  result = 1;
84 		}
85 	      else
86 		puts ("-z nodelete test succeeded");
87 	    }
88 	  else
89 	    {
90 	      /* We caught an segmentation fault.  */
91 	      puts ("\"nodelmod1.so\" got deleted");
92 	      result = 1;
93 	    }
94 	}
95     }
96 
97   p = dlopen ("nodelmod2.so", RTLD_LAZY | RTLD_NODELETE);
98   if (p == NULL)
99     {
100       printf ("failed to load \"nodelmod2.so\": %s\n", dlerror ());
101       result = 1;
102     }
103   else
104     {
105       int *varp;
106 
107       puts ("succeeded loading \"nodelmod2.so\"");
108 
109       varp = dlsym (p, "var2");
110       if (varp == NULL)
111 	{
112 	  puts ("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 (p) != 0)
122 	    {
123 	      puts ("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 ("\"var2\" value not correct");
132 		  result = 1;
133 		}
134 	      else if (fini_ran != 0)
135 		{
136 		  puts ("destructor of \"nodelmod2.so\" ran");
137 		  result = 1;
138 		}
139 	      else
140 		puts ("RTLD_NODELETE test succeeded");
141 	    }
142 	  else
143 	    {
144 	      /* We caught an segmentation fault.  */
145 	      puts ("\"nodelmod2.so\" got deleted");
146 	      result = 1;
147 	    }
148 	}
149     }
150 
151   p = dlopen ("nodelmod3.so", RTLD_LAZY);
152   if (p == NULL)
153     {
154       printf ("failed to load \"nodelmod3.so\": %s\n", dlerror ());
155       result = 1;
156     }
157   else
158     {
159       int *(*fctp) (void);
160 
161       puts ("succeeded loading \"nodelmod3.so\"");
162 
163       fctp = dlsym (p, "addr");
164       if (fctp == NULL)
165 	{
166 	  puts ("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 (p) != 0)
178 	    {
179 	      puts ("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 ("\"var_in_mod4\" value not correct");
188 		  result = 1;
189 		}
190 	      else if (fini_ran != 0)
191 		{
192 		  puts ("destructor of \"nodelmod4.so\" ran");
193 		  result = 1;
194 		}
195 	      else
196 		puts ("-z nodelete in dependency succeeded");
197 	    }
198 	  else
199 	    {
200 	      /* We caught an segmentation fault.  */
201 	      puts ("\"nodelmod4.so\" got deleted");
202 	      result = 1;
203 	    }
204 	}
205     }
206 
207   return result;
208 }
209 
210 #include <support/test-driver.c>
211