elf: Ignore LD_AUDIT interfaces if la_version returns 0 [BZ #24122]
[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 static int
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>