1 /* _dl_find_object test with parallelism.
2 Copyright (C) 2021-2023 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
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/>. */
19 #include <array_length.h>
21 #include <elf/dl-find_object.h>
24 #include <support/check.h>
25 #include <support/support.h>
26 #include <support/xdlfcn.h>
27 #include <support/xthread.h>
28 #include <support/xunistd.h>
30 /* Computes the expected _dl_find_object result directly from the
33 from_map (struct link_map
*l
, struct dl_find_object
*expected
)
35 struct dl_find_object_internal internal
;
36 _dl_find_object_from_map (l
, &internal
);
37 _dl_find_object_to_external (&internal
, expected
);
40 /* Returns the soname for the test object NUMBER. */
44 return xasprintf ("tst-dl_find_object-mod%d.so", number
);
47 /* Returns the data symbol name for the test object NUMBER. */
51 return xasprintf ("mod%d_data", number
);
57 void *address
; /* Address in the shared object. */
58 struct dl_find_object dlfo
;
62 /* Compare _dl_find_object result at ADDRESS with *EXPECTED. */
64 check (void *address
, struct dl_find_object
*expected
, int line
)
66 struct dl_find_object actual
;
67 int ret
= _dl_find_object (address
, &actual
);
72 support_record_failure ();
73 printf ("%s:%d: unexpected success for %p\n",
74 __FILE__
, line
, address
);
80 support_record_failure ();
81 printf ("%s:%d: unexpected failure for %p\n",
82 __FILE__
, line
, address
);
86 if (actual
.dlfo_flags
!= expected
->dlfo_flags
)
88 support_record_failure ();
89 printf ("%s:%d: error: %p: flags is %llu, expected %llu\n",
90 __FILE__
, line
, address
,
91 actual
.dlfo_flags
, expected
->dlfo_flags
);
93 if (actual
.dlfo_flags
!= expected
->dlfo_flags
)
95 support_record_failure ();
96 printf ("%s:%d: error: %p: map start is %p, expected %p\n",
98 address
, actual
.dlfo_map_start
, expected
->dlfo_map_start
);
100 if (actual
.dlfo_map_end
!= expected
->dlfo_map_end
)
102 support_record_failure ();
103 printf ("%s:%d: error: %p: map end is %p, expected %p\n",
105 address
, actual
.dlfo_map_end
, expected
->dlfo_map_end
);
107 if (actual
.dlfo_link_map
!= expected
->dlfo_link_map
)
109 support_record_failure ();
110 printf ("%s:%d: error: %p: link map is %p, expected %p\n",
112 address
, actual
.dlfo_link_map
, expected
->dlfo_link_map
);
114 if (actual
.dlfo_eh_frame
!= expected
->dlfo_eh_frame
)
116 support_record_failure ();
117 printf ("%s:%d: error: %p: EH frame is %p, expected %p\n",
119 address
, actual
.dlfo_eh_frame
, expected
->dlfo_eh_frame
);
121 #if DLFO_STRUCT_HAS_EH_DBASE
122 if (actual
.dlfo_eh_dbase
!= expected
->dlfo_eh_dbase
)
124 support_record_failure ();
125 printf ("%s:%d: error: %p: data base is %p, expected %p\n",
127 address
, actual
.dlfo_eh_dbase
, expected
->dlfo_eh_dbase
);
130 #if DLFO_STRUCT_HAS_EH_COUNT
131 if (actual
.dlfo_eh_count
!= expected
->dlfo_eh_count
)
133 support_record_failure ();
134 printf ("%s:%d: error: %p: count is %d, expected %d\n",
136 address
, actual
.dlfo_eh_count
, expected
->dlfo_eh_count
);
141 /* Request process termination after 0.3 seconds. */
142 static bool exit_requested
;
144 exit_thread (void *ignored
)
147 __atomic_store_n (&exit_requested
, true, __ATOMIC_RELAXED
);
152 verify_thread (void *closure
)
154 struct verify_data
*data
= closure
;
156 while (!__atomic_load_n (&exit_requested
, __ATOMIC_RELAXED
))
158 check (data
->address
, &data
->dlfo
, __LINE__
);
159 check (data
->dlfo
.dlfo_map_start
, &data
->dlfo
, __LINE__
);
160 check (data
->dlfo
.dlfo_map_end
- 1, &data
->dlfo
, __LINE__
);
166 /* Sets up the verification data, dlopen'ing shared object NUMBER, and
167 launches a verification thread. */
169 start_verify (int number
, struct verify_data
*data
)
171 data
->soname
= soname (number
);
172 struct link_map
*l
= xdlopen (data
->soname
, RTLD_NOW
);
173 from_map (l
, &data
->dlfo
);
174 TEST_VERIFY_EXIT (data
->dlfo
.dlfo_link_map
== l
);
175 char *sym
= symbol (number
);
176 data
->address
= xdlsym (data
->dlfo
.dlfo_link_map
, sym
);
178 data
->thr
= xpthread_create (NULL
, verify_thread
, data
);
185 struct verify_data data_mod2
;
186 struct verify_data data_mod4
;
187 struct verify_data data_mod7
;
189 /* Load the modules with gaps. */
191 void *mod1
= xdlopen ("tst-dl_find_object-mod1.so", RTLD_NOW
);
192 start_verify (2, &data_mod2
);
193 void *mod3
= xdlopen ("tst-dl_find_object-mod3.so", RTLD_NOW
);
194 start_verify (4, &data_mod4
);
195 void *mod5
= xdlopen ("tst-dl_find_object-mod5.so", RTLD_NOW
);
196 void *mod6
= xdlopen ("tst-dl_find_object-mod6.so", RTLD_NOW
);
197 start_verify (7, &data_mod7
);
204 /* Objects that continuously opened and closed. */
209 struct link_map
*link_map
;
213 { soname (1), symbol (1), },
214 { soname (3), symbol (3), },
215 { soname (5), symbol (5), },
216 { soname (6), symbol (6), },
217 { soname (8), symbol (8), },
218 { soname (9), symbol (9), },
221 pthread_t exit_thr
= xpthread_create (NULL
, exit_thread
, NULL
);
223 struct drand48_data state
;
224 srand48_r (1, &state
);
225 while (!__atomic_load_n (&exit_requested
, __ATOMIC_RELAXED
))
228 lrand48_r (&state
, &idx
);
229 idx
%= array_length (temp_objects
);
230 if (temp_objects
[idx
].link_map
== NULL
)
232 temp_objects
[idx
].link_map
= xdlopen (temp_objects
[idx
].soname
,
234 temp_objects
[idx
].address
= xdlsym (temp_objects
[idx
].link_map
,
235 temp_objects
[idx
].symbol
);
239 xdlclose (temp_objects
[idx
].link_map
);
240 temp_objects
[idx
].link_map
= NULL
;
241 struct dl_find_object dlfo
;
242 int ret
= _dl_find_object (temp_objects
[idx
].address
, &dlfo
);
245 TEST_VERIFY_EXIT (ret
== 0);
246 support_record_failure ();
247 printf ("%s: error: %s EH found after dlclose, link map %p\n",
248 __FILE__
, temp_objects
[idx
].soname
, dlfo
.dlfo_link_map
);
253 xpthread_join (data_mod2
.thr
);
254 xpthread_join (data_mod4
.thr
);
255 xpthread_join (data_mod7
.thr
);
256 xpthread_join (exit_thr
);
258 for (size_t i
= 0; i
< array_length (temp_objects
); ++i
)
260 free (temp_objects
[i
].soname
);
261 free (temp_objects
[i
].symbol
);
262 if (temp_objects
[i
].link_map
!= NULL
)
263 xdlclose (temp_objects
[i
].link_map
);
266 free (data_mod2
.soname
);
267 free (data_mod4
.soname
);
268 xdlclose (data_mod4
.dlfo
.dlfo_link_map
);
269 free (data_mod7
.soname
);
270 xdlclose (data_mod7
.dlfo
.dlfo_link_map
);
275 #include <support/test-driver.c>