1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <gtest/gtest.h>
18 
19 #include <dlfcn.h>
20 #include <elf.h>
21 #include <limits.h>
22 #include <link.h>
23 #include <stdint.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <sys/cdefs.h>
27 #if __has_include(<sys/auxv.h>)
28 #include <sys/auxv.h>
29 #endif
30 #include <sys/user.h>
31 
32 #include <string>
33 #include <thread>
34 
35 #include <android-base/file.h>
36 #include <android-base/macros.h>
37 #include <android-base/scopeguard.h>
38 
39 #include "gtest_globals.h"
40 #include "gtest_utils.h"
41 #include "dlfcn_symlink_support.h"
42 #include "utils.h"
43 
44 #define ASSERT_SUBSTR(needle, haystack) \
45     ASSERT_PRED_FORMAT2(::testing::IsSubstring, needle, haystack)
46 
47 
48 static bool g_called = false;
DlSymTestFunction()49 extern "C" void DlSymTestFunction() {
50   g_called = true;
51 }
52 
53 static int g_ctor_function_called = 0;
54 static int g_ctor_argc = 0;
55 static char** g_ctor_argv = reinterpret_cast<char**>(0xDEADBEEF);
56 static char** g_ctor_envp = g_ctor_envp;
57 
58 extern "C" void ctor_function(int argc, char** argv, char** envp) __attribute__ ((constructor));
59 
ctor_function(int argc,char ** argv,char ** envp)60 extern "C" void ctor_function(int argc, char** argv, char** envp) {
61   g_ctor_function_called = 17;
62   g_ctor_argc = argc;
63   g_ctor_argv = argv;
64   g_ctor_envp = envp;
65 }
66 
TEST(dlfcn,ctor_function_call)67 TEST(dlfcn, ctor_function_call) {
68   ASSERT_EQ(17, g_ctor_function_called);
69   ASSERT_TRUE(g_ctor_argc = GetArgc());
70   ASSERT_TRUE(g_ctor_argv = GetArgv());
71   ASSERT_TRUE(g_ctor_envp = GetEnvp());
72 }
73 
TEST(dlfcn,dlsym_in_executable)74 TEST(dlfcn, dlsym_in_executable) {
75   dlerror(); // Clear any pending errors.
76   void* self = dlopen(nullptr, RTLD_NOW);
77   ASSERT_TRUE(self != nullptr);
78   ASSERT_TRUE(dlerror() == nullptr);
79 
80   void* sym = dlsym(self, "DlSymTestFunction");
81   ASSERT_TRUE(sym != nullptr);
82 
83   void (*function)() = reinterpret_cast<void(*)()>(sym);
84 
85   g_called = false;
86   function();
87   ASSERT_TRUE(g_called);
88 
89   ASSERT_EQ(0, dlclose(self));
90 }
91 
TEST(dlfcn,dlsym_from_sofile)92 TEST(dlfcn, dlsym_from_sofile) {
93   void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_LAZY | RTLD_LOCAL);
94   ASSERT_TRUE(handle != nullptr) << dlerror();
95 
96   // check that we can't find '_test_dlsym_symbol' via dlsym(RTLD_DEFAULT)
97   void* symbol = dlsym(RTLD_DEFAULT, "test_dlsym_symbol");
98   ASSERT_TRUE(symbol == nullptr);
99   ASSERT_SUBSTR("undefined symbol: test_dlsym_symbol", dlerror());
100 
101   typedef int* (*fn_t)();
102   fn_t lookup_dlsym_symbol_using_RTLD_DEFAULT =
103       reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol_using_RTLD_DEFAULT"));
104   ASSERT_TRUE(lookup_dlsym_symbol_using_RTLD_DEFAULT != nullptr) << dlerror();
105 
106   int* ptr = lookup_dlsym_symbol_using_RTLD_DEFAULT();
107   ASSERT_TRUE(ptr != nullptr) << dlerror();
108   ASSERT_EQ(42, *ptr);
109 
110   fn_t lookup_dlsym_symbol2_using_RTLD_DEFAULT =
111       reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol2_using_RTLD_DEFAULT"));
112   ASSERT_TRUE(lookup_dlsym_symbol2_using_RTLD_DEFAULT != nullptr) << dlerror();
113 
114   ptr = lookup_dlsym_symbol2_using_RTLD_DEFAULT();
115   ASSERT_TRUE(ptr != nullptr) << dlerror();
116   ASSERT_EQ(44, *ptr);
117 
118   fn_t lookup_dlsym_symbol_using_RTLD_NEXT =
119       reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol_using_RTLD_NEXT"));
120   ASSERT_TRUE(lookup_dlsym_symbol_using_RTLD_NEXT != nullptr) << dlerror();
121 
122   ptr = lookup_dlsym_symbol_using_RTLD_NEXT();
123   ASSERT_TRUE(ptr != nullptr) << dlerror();
124   ASSERT_EQ(43, *ptr);
125 
126   dlclose(handle);
127 }
128 
TEST(dlfcn,dlsym_from_sofile_with_preload)129 TEST(dlfcn, dlsym_from_sofile_with_preload) {
130   void* preload = dlopen("libtest_dlsym_from_this_grandchild.so", RTLD_NOW | RTLD_LOCAL);
131   ASSERT_TRUE(preload != nullptr) << dlerror();
132 
133   void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_NOW | RTLD_LOCAL);
134   ASSERT_TRUE(handle != nullptr) << dlerror();
135 
136   // check that we can't find '_test_dlsym_symbol' via dlsym(RTLD_DEFAULT)
137   void* symbol = dlsym(RTLD_DEFAULT, "test_dlsym_symbol");
138   ASSERT_TRUE(symbol == nullptr);
139   ASSERT_SUBSTR("undefined symbol: test_dlsym_symbol", dlerror());
140 
141   typedef int* (*fn_t)();
142   fn_t lookup_dlsym_symbol_using_RTLD_DEFAULT =
143       reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol_using_RTLD_DEFAULT"));
144   ASSERT_TRUE(lookup_dlsym_symbol_using_RTLD_DEFAULT != nullptr) << dlerror();
145 
146   int* ptr = lookup_dlsym_symbol_using_RTLD_DEFAULT();
147   ASSERT_TRUE(ptr != nullptr) << dlerror();
148   ASSERT_EQ(42, *ptr);
149 
150   fn_t lookup_dlsym_symbol2_using_RTLD_DEFAULT =
151       reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol2_using_RTLD_DEFAULT"));
152   ASSERT_TRUE(lookup_dlsym_symbol2_using_RTLD_DEFAULT != nullptr) << dlerror();
153 
154   ptr = lookup_dlsym_symbol2_using_RTLD_DEFAULT();
155   ASSERT_TRUE(ptr != nullptr) << dlerror();
156   ASSERT_EQ(44, *ptr);
157 
158   fn_t lookup_dlsym_symbol_using_RTLD_NEXT =
159       reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol_using_RTLD_NEXT"));
160   ASSERT_TRUE(lookup_dlsym_symbol_using_RTLD_NEXT != nullptr) << dlerror();
161 
162   ptr = lookup_dlsym_symbol_using_RTLD_NEXT();
163   ASSERT_TRUE(ptr != nullptr) << dlerror();
164   ASSERT_EQ(43, *ptr);
165 
166   dlclose(handle);
167   dlclose(preload);
168 }
169 
TEST(dlfcn,dlsym_handle_global_sym)170 TEST(dlfcn, dlsym_handle_global_sym) {
171   // check that we do not look into global group
172   // when looking up symbol by handle
173   void* handle = dlopen("libtest_empty.so", RTLD_NOW);
174   dlopen("libtest_with_dependency.so", RTLD_NOW | RTLD_GLOBAL);
175   void* sym = dlsym(handle, "getRandomNumber");
176   ASSERT_TRUE(sym == nullptr);
177   ASSERT_SUBSTR("undefined symbol: getRandomNumber", dlerror());
178 
179   sym = dlsym(handle, "DlSymTestFunction");
180   ASSERT_TRUE(sym == nullptr);
181   ASSERT_SUBSTR("undefined symbol: DlSymTestFunction", dlerror());
182   dlclose(handle);
183 }
184 
TEST(dlfcn,dlsym_handle_empty_symbol)185 TEST(dlfcn, dlsym_handle_empty_symbol) {
186   // check that dlsym of an empty symbol fails (see http://b/33530622)
187   void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_NOW);
188   ASSERT_TRUE(handle != nullptr) << dlerror();
189   void* sym = dlsym(handle, "");
190   ASSERT_TRUE(sym == nullptr);
191   ASSERT_SUBSTR("undefined symbol: ", dlerror());
192   dlclose(handle);
193 }
194 
TEST(dlfcn,dlsym_with_dependencies)195 TEST(dlfcn, dlsym_with_dependencies) {
196   void* handle = dlopen("libtest_with_dependency.so", RTLD_NOW);
197   ASSERT_TRUE(handle != nullptr);
198   dlerror();
199   // This symbol is in DT_NEEDED library.
200   void* sym = dlsym(handle, "getRandomNumber");
201   ASSERT_TRUE(sym != nullptr) << dlerror();
202   int (*fn)(void);
203   fn = reinterpret_cast<int (*)(void)>(sym);
204   EXPECT_EQ(4, fn());
205   dlclose(handle);
206 }
207 
TEST(dlfcn,dlopen_noload)208 TEST(dlfcn, dlopen_noload) {
209   void* handle = dlopen("libtest_simple.so", RTLD_NOW | RTLD_NOLOAD);
210   ASSERT_TRUE(handle == nullptr);
211   handle = dlopen("libtest_simple.so", RTLD_NOW);
212   void* handle2 = dlopen("libtest_simple.so", RTLD_NOW | RTLD_NOLOAD);
213   ASSERT_TRUE(handle != nullptr);
214   ASSERT_TRUE(handle2 != nullptr);
215   ASSERT_TRUE(handle == handle2);
216   ASSERT_EQ(0, dlclose(handle));
217   ASSERT_EQ(0, dlclose(handle2));
218 }
219 
TEST(dlfcn,dlopen_by_soname)220 TEST(dlfcn, dlopen_by_soname) {
221   static const char* soname = "libdlext_test_soname.so";
222   static const char* filename = "libdlext_test_different_soname.so";
223   // 1. Make sure there is no library with soname in default search path
224   void* handle = dlopen(soname, RTLD_NOW);
225   ASSERT_TRUE(handle == nullptr);
226 
227   // 2. Load a library using filename
228   handle = dlopen(filename, RTLD_NOW);
229   ASSERT_TRUE(handle != nullptr) << dlerror();
230 
231   // 3. Find library by soname
232   void* handle_soname = dlopen(soname, RTLD_NOW | RTLD_NOLOAD);
233   ASSERT_TRUE(handle_soname != nullptr) << dlerror();
234   ASSERT_EQ(handle, handle_soname);
235 
236   // 4. RTLD_NOLOAD should still work with filename
237   void* handle_filename = dlopen(filename, RTLD_NOW | RTLD_NOLOAD);
238   ASSERT_TRUE(handle_filename != nullptr) << dlerror();
239   ASSERT_EQ(handle, handle_filename);
240 
241   dlclose(handle_filename);
242   dlclose(handle_soname);
243   dlclose(handle);
244 }
245 
TEST(dlfcn,dlopen_vdso)246 TEST(dlfcn, dlopen_vdso) {
247 #if __has_include(<sys/auxv.h>)
248   if (getauxval(AT_SYSINFO_EHDR) == 0) {
249     GTEST_SKIP() << "getauxval(AT_SYSINFO_EHDR) == 0, skipping this test";
250   }
251 #endif
252 
253   const char* vdso_name = "linux-vdso.so.1";
254 #if defined(__i386__)
255   vdso_name = "linux-gate.so.1";
256 #endif
257   void* handle = dlopen(vdso_name, RTLD_NOW);
258   ASSERT_TRUE(handle != nullptr) << dlerror();
259   dlclose(handle);
260 }
261 
262 // HWASan uses an ifunc to describe the location of its shadow memory,
263 // so even though it's an unusual case, Android needs to support
264 // "ifunc variables".
TEST(dlfcn,ifunc_variable)265 TEST(dlfcn, ifunc_variable) {
266   typedef const char* (*fn_ptr)();
267 
268   // ifunc's choice depends on whether IFUNC_CHOICE has a value
269   // first check the set case
270   setenv("IFUNC_CHOICE", "set", 1);
271   // preload libtest_ifunc_variable_impl.so
272   void* handle_impl = dlopen("libtest_ifunc_variable_impl.so", RTLD_NOW);
273   void* handle = dlopen("libtest_ifunc_variable.so", RTLD_NOW);
274   ASSERT_TRUE(handle != nullptr) << dlerror();
275   const char** foo_ptr = reinterpret_cast<const char**>(dlsym(handle, "foo"));
276   fn_ptr foo_library_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo_library"));
277   ASSERT_TRUE(foo_ptr != nullptr) << dlerror();
278   ASSERT_TRUE(foo_library_ptr != nullptr) << dlerror();
279   ASSERT_EQ(strncmp("set", *foo_ptr, 3), 0);
280   ASSERT_EQ(strncmp("set", foo_library_ptr(), 3), 0);
281   dlclose(handle);
282   dlclose(handle_impl);
283 
284   // then check the unset case
285   unsetenv("IFUNC_CHOICE");
286   handle_impl = dlopen("libtest_ifunc_variable_impl.so", RTLD_NOW);
287   handle = dlopen("libtest_ifunc_variable.so", RTLD_NOW);
288   ASSERT_TRUE(handle != nullptr) << dlerror();
289   foo_ptr = reinterpret_cast<const char**>(dlsym(handle, "foo"));
290   foo_library_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo_library"));
291   ASSERT_TRUE(foo_ptr != nullptr) << dlerror();
292   ASSERT_TRUE(foo_library_ptr != nullptr) << dlerror();
293   ASSERT_EQ(strncmp("unset", *foo_ptr, 5), 0);
294   ASSERT_EQ(strncmp("unset", foo_library_ptr(), 5), 0);
295   dlclose(handle);
296   dlclose(handle_impl);
297 }
298 
TEST(dlfcn,ifunc)299 TEST(dlfcn, ifunc) {
300   typedef const char* (*fn_ptr)();
301 
302   // ifunc's choice depends on whether IFUNC_CHOICE has a value
303   // first check the set case
304   setenv("IFUNC_CHOICE", "set", 1);
305   void* handle = dlopen("libtest_ifunc.so", RTLD_NOW);
306   ASSERT_TRUE(handle != nullptr) << dlerror();
307   fn_ptr foo_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo"));
308   fn_ptr foo_library_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo_library"));
309   ASSERT_TRUE(foo_ptr != nullptr) << dlerror();
310   ASSERT_TRUE(foo_library_ptr != nullptr) << dlerror();
311   ASSERT_EQ(strncmp("set", foo_ptr(), 3), 0);
312   ASSERT_EQ(strncmp("set", foo_library_ptr(), 3), 0);
313   dlclose(handle);
314 
315   // then check the unset case
316   unsetenv("IFUNC_CHOICE");
317   handle = dlopen("libtest_ifunc.so", RTLD_NOW);
318   ASSERT_TRUE(handle != nullptr) << dlerror();
319   foo_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo"));
320   foo_library_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo_library"));
321   ASSERT_TRUE(foo_ptr != nullptr) << dlerror();
322   ASSERT_TRUE(foo_library_ptr != nullptr) << dlerror();
323   ASSERT_EQ(strncmp("unset", foo_ptr(), 5), 0);
324   ASSERT_EQ(strncmp("unset", foo_library_ptr(), 5), 0);
325   dlclose(handle);
326 }
327 
TEST(dlfcn,ifunc_ctor_call)328 TEST(dlfcn, ifunc_ctor_call) {
329   typedef const char* (*fn_ptr)();
330 
331   void* handle = dlopen("libtest_ifunc.so", RTLD_NOW);
332   ASSERT_TRUE(handle != nullptr) << dlerror();
333   fn_ptr is_ctor_called =  reinterpret_cast<fn_ptr>(dlsym(handle, "is_ctor_called_irelative"));
334   ASSERT_TRUE(is_ctor_called != nullptr) << dlerror();
335   ASSERT_STREQ("false", is_ctor_called());
336 
337   is_ctor_called =  reinterpret_cast<fn_ptr>(dlsym(handle, "is_ctor_called_jump_slot"));
338   ASSERT_TRUE(is_ctor_called != nullptr) << dlerror();
339   ASSERT_STREQ("true", is_ctor_called());
340   dlclose(handle);
341 }
342 
TEST(dlfcn,ifunc_ctor_call_rtld_lazy)343 TEST(dlfcn, ifunc_ctor_call_rtld_lazy) {
344   typedef const char* (*fn_ptr)();
345 
346   void* handle = dlopen("libtest_ifunc.so", RTLD_LAZY);
347   ASSERT_TRUE(handle != nullptr) << dlerror();
348   fn_ptr is_ctor_called =  reinterpret_cast<fn_ptr>(dlsym(handle, "is_ctor_called_irelative"));
349   ASSERT_TRUE(is_ctor_called != nullptr) << dlerror();
350   ASSERT_STREQ("false", is_ctor_called());
351 
352   is_ctor_called =  reinterpret_cast<fn_ptr>(dlsym(handle, "is_ctor_called_jump_slot"));
353   ASSERT_TRUE(is_ctor_called != nullptr) << dlerror();
354   ASSERT_STREQ("true", is_ctor_called());
355   dlclose(handle);
356 }
357 
TEST(dlfcn,dlopen_check_relocation_dt_needed_order)358 TEST(dlfcn, dlopen_check_relocation_dt_needed_order) {
359   // This is the structure of the test library and
360   // its dt_needed libraries
361   // libtest_relo_check_dt_needed_order.so
362   // |
363   // +-> libtest_relo_check_dt_needed_order_1.so
364   // |
365   // +-> libtest_relo_check_dt_needed_order_2.so
366   //
367   // The root library references relo_test_get_answer_lib - which is defined
368   // in both dt_needed libraries, the correct relocation should
369   // use the function defined in libtest_relo_check_dt_needed_order_1.so
370   void* handle = nullptr;
371   auto guard = android::base::make_scope_guard([&]() { dlclose(handle); });
372 
373   handle = dlopen("libtest_relo_check_dt_needed_order.so", RTLD_NOW);
374   ASSERT_TRUE(handle != nullptr) << dlerror();
375 
376   typedef int (*fn_t) (void);
377   fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "relo_test_get_answer"));
378   ASSERT_TRUE(fn != nullptr) << dlerror();
379   ASSERT_EQ(1, fn());
380 }
381 
TEST(dlfcn,dlopen_check_order_dlsym)382 TEST(dlfcn, dlopen_check_order_dlsym) {
383   // Here is how the test library and its dt_needed
384   // libraries are arranged
385   //
386   //  libtest_check_order_children.so
387   //  |
388   //  +-> ..._1_left.so
389   //  |   |
390   //  |   +-> ..._a.so
391   //  |   |
392   //  |   +-> ...r_b.so
393   //  |
394   //  +-> ..._2_right.so
395   //  |   |
396   //  |   +-> ..._d.so
397   //  |       |
398   //  |       +-> ..._b.so
399   //  |
400   //  +-> ..._3_c.so
401   //
402   //  load order should be (1, 2, 3, a, b, d)
403   //
404   // get_answer() is defined in (2, 3, a, b, c)
405   // get_answer2() is defined in (b, d)
406   void* sym = dlsym(RTLD_DEFAULT, "check_order_dlsym_get_answer");
407   ASSERT_TRUE(sym == nullptr);
408   void* handle = dlopen("libtest_check_order_dlsym.so", RTLD_NOW | RTLD_GLOBAL);
409   ASSERT_TRUE(handle != nullptr) << dlerror();
410   typedef int (*fn_t) (void);
411   fn_t fn, fn2;
412   fn = reinterpret_cast<fn_t>(dlsym(RTLD_DEFAULT, "check_order_dlsym_get_answer"));
413   ASSERT_TRUE(fn != nullptr) << dlerror();
414   fn2 = reinterpret_cast<fn_t>(dlsym(RTLD_DEFAULT, "check_order_dlsym_get_answer2"));
415   ASSERT_TRUE(fn2 != nullptr) << dlerror();
416 
417   ASSERT_EQ(42, fn());
418   ASSERT_EQ(43, fn2());
419   dlclose(handle);
420 }
421 
TEST(dlfcn,dlopen_check_order_reloc_siblings)422 TEST(dlfcn, dlopen_check_order_reloc_siblings) {
423   // This is how this one works:
424   // we lookup and call get_answer which is defined in '_2.so'
425   // and in turn calls external get_answer_impl() defined in _1.so and in '_[a-f].so'
426   // the correct _impl() is implemented by '_a.so';
427   //
428   // Note that this is test for RTLD_LOCAL (TODO: test for GLOBAL?)
429   //
430   // Here is the picture:
431   //
432   // libtest_check_order_reloc_siblings.so
433   // |
434   // +-> ..._1.so <- empty
435   // |   |
436   // |   +-> ..._a.so <- exports correct answer_impl()
437   // |   |
438   // |   +-> ..._b.so <- every other letter exporting incorrect one.
439   // |
440   // +-> ..._2.so <- empty
441   // |   |
442   // |   +-> ..._c.so
443   // |   |
444   // |   +-> ..._d.so
445   // |
446   // +-> ..._3.so <- empty
447   //     |
448   //     +-> ..._e.so
449   //     |
450   //     +-> ..._f.so <- exports get_answer() that calls get_anser_impl();
451   //                     implements incorrect get_answer_impl()
452 
453   void* handle = dlopen("libtest_check_order_reloc_siblings.so", RTLD_NOW | RTLD_NOLOAD);
454   ASSERT_TRUE(handle == nullptr);
455 #ifdef __BIONIC__
456   // TODO: glibc returns nullptr on dlerror() here. Is it bug?
457   ASSERT_STREQ("dlopen failed: library \"libtest_check_order_reloc_siblings.so\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
458 #endif
459 
460   handle = dlopen("libtest_check_order_reloc_siblings.so", RTLD_NOW | RTLD_LOCAL);
461   ASSERT_TRUE(handle != nullptr) << dlerror();
462 
463   typedef int (*fn_t) (void);
464   fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "check_order_reloc_get_answer"));
465   ASSERT_TRUE(fn != nullptr) << dlerror();
466   ASSERT_EQ(42, fn());
467 
468   ASSERT_EQ(0, dlclose(handle));
469 }
470 
TEST(dlfcn,dlopen_check_order_reloc_siblings_with_preload)471 TEST(dlfcn, dlopen_check_order_reloc_siblings_with_preload) {
472   // This test uses the same library as dlopen_check_order_reloc_siblings.
473   // Unlike dlopen_check_order_reloc_siblings it preloads
474   // libtest_check_order_reloc_siblings_1.so (first dependency) prior to
475   // dlopen(libtest_check_order_reloc_siblings.so)
476 
477   void* handle = dlopen("libtest_check_order_reloc_siblings.so", RTLD_NOW | RTLD_NOLOAD);
478   ASSERT_TRUE(handle == nullptr);
479   handle = dlopen("libtest_check_order_reloc_siblings_1.so", RTLD_NOW | RTLD_NOLOAD);
480   ASSERT_TRUE(handle == nullptr);
481 
482   void* handle_for_1 = dlopen("libtest_check_order_reloc_siblings_1.so", RTLD_NOW | RTLD_LOCAL);
483   ASSERT_TRUE(handle_for_1 != nullptr) << dlerror();
484 
485   handle = dlopen("libtest_check_order_reloc_siblings.so", RTLD_NOW | RTLD_LOCAL);
486   ASSERT_TRUE(handle != nullptr) << dlerror();
487 
488   ASSERT_EQ(0, dlclose(handle_for_1));
489 
490   typedef int (*fn_t) (void);
491   fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "check_order_reloc_get_answer"));
492   ASSERT_TRUE(fn != nullptr) << dlerror();
493   ASSERT_EQ(42, fn());
494 
495   ASSERT_EQ(0, dlclose(handle));
496 }
497 
TEST(dlfcn,dlopen_check_order_reloc_grandchild)498 TEST(dlfcn, dlopen_check_order_reloc_grandchild) {
499   // This is how this one works:
500   // we lookup and call grandchild_get_answer which is defined in '_2.so'
501   // and in turn calls external get_answer_impl() defined in '_c_1.so and _c_2.so'
502   // the correct _impl() is implemented by '_c_1.so';
503   //
504   // Here is the picture of subtree:
505   //
506   // libtest_check_order_reloc_siblings.so
507   // |
508   // +-> ..._2.so <- grandchild_get_answer()
509   //     |
510   //     +-> ..._c.so <- empty
511   //     |   |
512   //     |   +-> _c_1.so <- exports correct answer_impl()
513   //     |   |
514   //     |   +-> _c_2.so <- exports incorrect answer_impl()
515   //     |
516   //     +-> ..._d.so <- empty
517 
518   void* handle = dlopen("libtest_check_order_reloc_siblings.so", RTLD_NOW | RTLD_NOLOAD);
519   ASSERT_TRUE(handle == nullptr);
520 #ifdef __BIONIC__
521   // TODO: glibc returns nullptr on dlerror() here. Is it bug?
522   ASSERT_STREQ("dlopen failed: library \"libtest_check_order_reloc_siblings.so\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
523 #endif
524 
525   handle = dlopen("libtest_check_order_reloc_siblings.so", RTLD_NOW | RTLD_LOCAL);
526   ASSERT_TRUE(handle != nullptr) << dlerror();
527 
528   typedef int (*fn_t) (void);
529   fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "check_order_reloc_grandchild_get_answer"));
530   ASSERT_TRUE(fn != nullptr) << dlerror();
531   ASSERT_EQ(42, fn());
532 
533   ASSERT_EQ(0, dlclose(handle));
534 }
535 
TEST(dlfcn,dlopen_check_order_reloc_nephew)536 TEST(dlfcn, dlopen_check_order_reloc_nephew) {
537   // This is how this one works:
538   // we lookup and call nephew_get_answer which is defined in '_2.so'
539   // and in turn calls external get_answer_impl() defined in '_[a-f].so'
540   // the correct _impl() is implemented by '_a.so';
541   //
542   // Here is the picture:
543   //
544   // libtest_check_order_reloc_siblings.so
545   // |
546   // +-> ..._1.so <- empty
547   // |   |
548   // |   +-> ..._a.so <- exports correct answer_impl()
549   // |   |
550   // |   +-> ..._b.so <- every other letter exporting incorrect one.
551   // |
552   // +-> ..._2.so <- empty
553   // |   |
554   // |   +-> ..._c.so
555   // |   |
556   // |   +-> ..._d.so
557   // |
558   // +-> ..._3.so <- nephew_get_answer() that calls get_answer_impl();
559   //     |
560   //     +-> ..._e.so
561   //     |
562   //     +-> ..._f.so
563 
564   void* handle = dlopen("libtest_check_order_reloc_siblings.so", RTLD_NOW | RTLD_NOLOAD);
565   ASSERT_TRUE(handle == nullptr);
566 #ifdef __BIONIC__
567   // TODO: glibc returns nullptr on dlerror() here. Is it bug?
568   ASSERT_STREQ("dlopen failed: library \"libtest_check_order_reloc_siblings.so\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
569 #endif
570 
571   handle = dlopen("libtest_check_order_reloc_siblings.so", RTLD_NOW | RTLD_LOCAL);
572   ASSERT_TRUE(handle != nullptr) << dlerror();
573 
574   typedef int (*fn_t) (void);
575   fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "check_order_reloc_nephew_get_answer"));
576   ASSERT_TRUE(fn != nullptr) << dlerror();
577   ASSERT_EQ(42, fn());
578 
579   ASSERT_EQ(0, dlclose(handle));
580 }
581 
TEST(dlfcn,check_unload_after_reloc)582 TEST(dlfcn, check_unload_after_reloc) {
583   // This is how this one works:
584   // libtest_two_parents_parent1 <- answer_impl() used by libtest_two_parents_child
585   // |
586   // +-> libtest_two_parents_child
587   //
588   // libtest_two_parents_parent2 <- answer_impl() not used by libtest_two_parents_child
589   // |
590   // +-> libtest_two_parents_child
591   //
592   // Test dlopens parent1 which loads and relocates libtest_two_parents_child.so
593   // as a second step it dlopens parent2 and dlcloses parent1...
594 
595   void* handle = dlopen("libtest_two_parents_parent1.so", RTLD_NOW | RTLD_LOCAL);
596   ASSERT_TRUE(handle != nullptr) << dlerror();
597 
598   void* handle2 = dlopen("libtest_two_parents_parent2.so", RTLD_NOW | RTLD_LOCAL);
599   ASSERT_TRUE(handle2 != nullptr) << dlerror();
600 
601   typedef int (*fn_t) (void);
602   fn_t fn = reinterpret_cast<fn_t>(dlsym(handle2, "check_order_reloc_get_answer"));
603   ASSERT_TRUE(fn != nullptr) << dlerror();
604   ASSERT_EQ(42, fn());
605 
606   ASSERT_EQ(0, dlclose(handle));
607 
608   handle = dlopen("libtest_two_parents_parent1.so", RTLD_NOW | RTLD_LOCAL | RTLD_NOLOAD);
609   ASSERT_TRUE(handle != nullptr);
610   ASSERT_EQ(0, dlclose(handle));
611 
612   fn = reinterpret_cast<fn_t>(dlsym(handle2, "check_order_reloc_get_answer"));
613   ASSERT_TRUE(fn != nullptr) << dlerror();
614   ASSERT_EQ(42, fn());
615 
616   ASSERT_EQ(0, dlclose(handle2));
617 
618   handle = dlopen("libtest_two_parents_parent1.so", RTLD_NOW | RTLD_LOCAL | RTLD_NOLOAD);
619   ASSERT_TRUE(handle == nullptr);
620 }
621 
check_order_reloc_root_get_answer_impl()622 extern "C" int check_order_reloc_root_get_answer_impl() {
623   return 42;
624 }
625 
TEST(dlfcn,dlopen_check_order_reloc_main_executable)626 TEST(dlfcn, dlopen_check_order_reloc_main_executable) {
627   // This is how this one works:
628   // we lookup and call get_answer3 which is defined in 'root.so'
629   // and in turn calls external root_get_answer_impl() defined in _2.so and
630   // above the correct _impl() is one in the executable.
631   //
632   // libtest_check_order_reloc_root.so
633   // |
634   // +-> ..._1.so <- empty
635   // |
636   // +-> ..._2.so <- gives incorrect answer for answer_main_impl()
637   //
638 
639   void* handle = dlopen("libtest_check_order_reloc_root.so", RTLD_NOW | RTLD_NOLOAD);
640   ASSERT_TRUE(handle == nullptr);
641 #ifdef __BIONIC__
642   // TODO: glibc returns nullptr on dlerror() here. Is it bug?
643   ASSERT_STREQ("dlopen failed: library \"libtest_check_order_reloc_root.so\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
644 #endif
645 
646   handle = dlopen("libtest_check_order_reloc_root.so", RTLD_NOW | RTLD_LOCAL);
647   ASSERT_TRUE(handle != nullptr) << dlerror();
648 
649   typedef int (*fn_t) (void);
650   fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "check_order_reloc_root_get_answer"));
651   ASSERT_TRUE(fn != nullptr) << dlerror();
652   ASSERT_EQ(42, fn());
653 
654   ASSERT_EQ(0, dlclose(handle));
655 }
656 
TEST(dlfcn,dlopen_check_rtld_local)657 TEST(dlfcn, dlopen_check_rtld_local) {
658   void* sym = dlsym(RTLD_DEFAULT, "dlopen_testlib_simple_func");
659   ASSERT_TRUE(sym == nullptr);
660 
661   // implicit RTLD_LOCAL
662   void* handle = dlopen("libtest_simple.so", RTLD_NOW);
663   sym = dlsym(RTLD_DEFAULT, "dlopen_testlib_simple_func");
664   ASSERT_TRUE(sym == nullptr);
665   ASSERT_SUBSTR("undefined symbol: dlopen_testlib_simple_func", dlerror());
666   sym = dlsym(handle, "dlopen_testlib_simple_func");
667   ASSERT_TRUE(sym != nullptr);
668   ASSERT_TRUE(reinterpret_cast<bool (*)(void)>(sym)());
669   dlclose(handle);
670 
671   // explicit RTLD_LOCAL
672   handle = dlopen("libtest_simple.so", RTLD_NOW | RTLD_LOCAL);
673   sym = dlsym(RTLD_DEFAULT, "dlopen_testlib_simple_func");
674   ASSERT_TRUE(sym == nullptr);
675   ASSERT_SUBSTR("undefined symbol: dlopen_testlib_simple_func", dlerror());
676   sym = dlsym(handle, "dlopen_testlib_simple_func");
677   ASSERT_TRUE(sym != nullptr);
678   ASSERT_TRUE(reinterpret_cast<bool (*)(void)>(sym)());
679   dlclose(handle);
680 }
681 
TEST(dlfcn,dlopen_check_rtld_global)682 TEST(dlfcn, dlopen_check_rtld_global) {
683   void* sym = dlsym(RTLD_DEFAULT, "dlopen_testlib_simple_func");
684   ASSERT_TRUE(sym == nullptr);
685 
686   void* handle = dlopen("libtest_simple.so", RTLD_NOW | RTLD_GLOBAL);
687   ASSERT_TRUE(handle != nullptr) << dlerror();
688   sym = dlsym(RTLD_DEFAULT, "dlopen_testlib_simple_func");
689   ASSERT_TRUE(sym != nullptr) << dlerror();
690   ASSERT_TRUE(reinterpret_cast<bool (*)(void)>(sym)());
691   dlclose(handle);
692 
693   // RTLD_GLOBAL implies RTLD_NODELETE, let's check that
694   void* sym_after_dlclose = dlsym(RTLD_DEFAULT, "dlopen_testlib_simple_func");
695   ASSERT_EQ(sym, sym_after_dlclose);
696 
697   // Check if dlsym() for main program's handle searches RTLD_GLOBAL
698   // shared libraries after symbol was not found in the main executable
699   // and dependent libraries.
700   void* handle_for_main_executable = dlopen(nullptr, RTLD_NOW);
701   sym = dlsym(handle_for_main_executable, "dlopen_testlib_simple_func");
702   ASSERT_TRUE(sym != nullptr) << dlerror();
703 
704   dlclose(handle_for_main_executable);
705 }
706 
707 // libtest_with_dependency_loop.so -> libtest_with_dependency_loop_a.so ->
708 // libtest_with_dependency_loop_b.so -> libtest_with_dependency_loop_c.so ->
709 // libtest_with_dependency_loop_a.so
TEST(dlfcn,dlopen_check_loop)710 TEST(dlfcn, dlopen_check_loop) {
711   void* handle = dlopen("libtest_with_dependency_loop.so", RTLD_NOW);
712   ASSERT_TRUE(handle != nullptr) << dlerror();
713   void* f = dlsym(handle, "dlopen_test_loopy_function");
714   ASSERT_TRUE(f != nullptr) << dlerror();
715   EXPECT_TRUE(reinterpret_cast<bool (*)(void)>(f)());
716   ASSERT_EQ(0, dlclose(handle));
717 
718   // dlopen second time to make sure that the library was unloaded correctly
719   handle = dlopen("libtest_with_dependency_loop.so", RTLD_NOW | RTLD_NOLOAD);
720   ASSERT_TRUE(handle == nullptr);
721 #ifdef __BIONIC__
722   ASSERT_STREQ("dlopen failed: library \"libtest_with_dependency_loop.so\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
723 #else
724   // TODO: glibc returns nullptr on dlerror() here. Is it bug?
725   ASSERT_TRUE(dlerror() == nullptr);
726 #endif
727 
728   handle = dlopen("libtest_with_dependency_a.so", RTLD_NOW | RTLD_NOLOAD);
729   ASSERT_TRUE(handle == nullptr);
730 }
731 
TEST(dlfcn,dlopen_nodelete)732 TEST(dlfcn, dlopen_nodelete) {
733   static bool is_unloaded = false;
734 
735   void* handle = dlopen("libtest_nodelete_1.so", RTLD_NOW | RTLD_NODELETE);
736   ASSERT_TRUE(handle != nullptr) << dlerror();
737   void (*set_unload_flag_ptr)(bool*);
738   set_unload_flag_ptr = reinterpret_cast<void (*)(bool*)>(dlsym(handle, "dlopen_nodelete_1_set_unload_flag_ptr"));
739   ASSERT_TRUE(set_unload_flag_ptr != nullptr) << dlerror();
740   set_unload_flag_ptr(&is_unloaded);
741 
742   uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_nodelete_1_taxicab_number"));
743   ASSERT_TRUE(taxicab_number != nullptr) << dlerror();
744   ASSERT_EQ(1729U, *taxicab_number);
745   *taxicab_number = 2;
746 
747   dlclose(handle);
748   ASSERT_TRUE(!is_unloaded);
749 
750   uint32_t* taxicab_number_after_dlclose = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_nodelete_1_taxicab_number"));
751   ASSERT_EQ(taxicab_number_after_dlclose, taxicab_number);
752   ASSERT_EQ(2U, *taxicab_number_after_dlclose);
753 
754 
755   handle = dlopen("libtest_nodelete_1.so", RTLD_NOW);
756   uint32_t* taxicab_number2 = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_nodelete_1_taxicab_number"));
757   ASSERT_EQ(taxicab_number2, taxicab_number);
758 
759   ASSERT_EQ(2U, *taxicab_number2);
760 
761   dlclose(handle);
762   ASSERT_TRUE(!is_unloaded);
763 }
764 
TEST(dlfcn,dlopen_nodelete_on_second_dlopen)765 TEST(dlfcn, dlopen_nodelete_on_second_dlopen) {
766   static bool is_unloaded = false;
767 
768   void* handle = dlopen("libtest_nodelete_2.so", RTLD_NOW);
769   ASSERT_TRUE(handle != nullptr) << dlerror();
770   void (*set_unload_flag_ptr)(bool*);
771   set_unload_flag_ptr = reinterpret_cast<void (*)(bool*)>(dlsym(handle, "dlopen_nodelete_2_set_unload_flag_ptr"));
772   ASSERT_TRUE(set_unload_flag_ptr != nullptr) << dlerror();
773   set_unload_flag_ptr(&is_unloaded);
774 
775   uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_nodelete_2_taxicab_number"));
776   ASSERT_TRUE(taxicab_number != nullptr) << dlerror();
777 
778   ASSERT_EQ(1729U, *taxicab_number);
779   *taxicab_number = 2;
780 
781   // This RTLD_NODELETE should be ignored
782   void* handle1 = dlopen("libtest_nodelete_2.so", RTLD_NOW | RTLD_NODELETE);
783   ASSERT_TRUE(handle1 != nullptr) << dlerror();
784   ASSERT_EQ(handle, handle1);
785 
786   dlclose(handle1);
787   dlclose(handle);
788 
789   ASSERT_TRUE(is_unloaded);
790 }
791 
TEST(dlfcn,dlopen_nodelete_dt_flags_1)792 TEST(dlfcn, dlopen_nodelete_dt_flags_1) {
793   static bool is_unloaded = false;
794 
795   void* handle = dlopen("libtest_nodelete_dt_flags_1.so", RTLD_NOW);
796   ASSERT_TRUE(handle != nullptr) << dlerror();
797   void (*set_unload_flag_ptr)(bool*);
798   set_unload_flag_ptr = reinterpret_cast<void (*)(bool*)>(dlsym(handle, "dlopen_nodelete_dt_flags_1_set_unload_flag_ptr"));
799   ASSERT_TRUE(set_unload_flag_ptr != nullptr) << dlerror();
800   set_unload_flag_ptr(&is_unloaded);
801 
802   dlclose(handle);
803   ASSERT_TRUE(!is_unloaded);
804 }
805 
TEST(dlfcn,dlsym_df_1_global)806 TEST(dlfcn, dlsym_df_1_global) {
807   void* handle = dlopen("libtest_dlsym_df_1_global.so", RTLD_NOW);
808   ASSERT_TRUE(handle != nullptr) << dlerror();
809   int (*get_answer)();
810   get_answer = reinterpret_cast<int (*)()>(dlsym(handle, "dl_df_1_global_get_answer"));
811   ASSERT_TRUE(get_answer != nullptr) << dlerror();
812   ASSERT_EQ(42, get_answer());
813   ASSERT_EQ(0, dlclose(handle));
814 }
815 
TEST(dlfcn,dlopen_failure)816 TEST(dlfcn, dlopen_failure) {
817   void* self = dlopen("/does/not/exist", RTLD_NOW);
818   ASSERT_TRUE(self == nullptr);
819 #if defined(__BIONIC__)
820   ASSERT_STREQ("dlopen failed: library \"/does/not/exist\" not found", dlerror());
821 #else
822   ASSERT_STREQ("/does/not/exist: cannot open shared object file: No such file or directory", dlerror());
823 #endif
824 }
825 
TEST(dlfcn,dlclose_unload)826 TEST(dlfcn, dlclose_unload) {
827   const size_t kPageSize = getpagesize();
828 
829   void* handle = dlopen("libtest_simple.so", RTLD_NOW);
830   ASSERT_TRUE(handle != nullptr) << dlerror();
831   uint32_t* taxicab_number = static_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
832   ASSERT_TRUE(taxicab_number != nullptr) << dlerror();
833   EXPECT_EQ(1729U, *taxicab_number);
834   dlclose(handle);
835   // Making sure that the library has been unmapped as part of library unload
836   // process. Note that mprotect somewhat counter-intuitively returns ENOMEM in
837   // this case.
838   uintptr_t page_start = reinterpret_cast<uintptr_t>(taxicab_number) & ~(kPageSize - 1);
839   ASSERT_TRUE(mprotect(reinterpret_cast<void*>(page_start), kPageSize, PROT_NONE) != 0);
840   ASSERT_ERRNO(ENOMEM);
841 }
842 
ConcurrentDlErrorFn(std::string & error)843 static void ConcurrentDlErrorFn(std::string& error) {
844   ASSERT_TRUE(dlerror() == nullptr);
845 
846   void* handle = dlopen("/child/thread", RTLD_NOW);
847   ASSERT_TRUE(handle == nullptr);
848 
849   const char* err = dlerror();
850   ASSERT_TRUE(err != nullptr);
851 
852   error = err;
853 }
854 
TEST(dlfcn,dlerror_concurrent_buffer)855 TEST(dlfcn, dlerror_concurrent_buffer) {
856   void* handle = dlopen("/main/thread", RTLD_NOW);
857   ASSERT_TRUE(handle == nullptr);
858   const char* main_thread_error = dlerror();
859   ASSERT_TRUE(main_thread_error != nullptr);
860   ASSERT_SUBSTR("/main/thread", main_thread_error);
861 
862   std::string child_thread_error;
863   std::thread t(ConcurrentDlErrorFn, std::ref(child_thread_error));
864   t.join();
865   ASSERT_SUBSTR("/child/thread", child_thread_error.c_str());
866 
867   // Check that main thread local buffer was not modified.
868   ASSERT_SUBSTR("/main/thread", main_thread_error);
869 }
870 
TEST(dlfcn,dlerror_concurrent)871 TEST(dlfcn, dlerror_concurrent) {
872   void* handle = dlopen("/main/thread", RTLD_NOW);
873   ASSERT_TRUE(handle == nullptr);
874 
875   std::string child_thread_error;
876   std::thread t(ConcurrentDlErrorFn, std::ref(child_thread_error));
877   t.join();
878   ASSERT_SUBSTR("/child/thread", child_thread_error.c_str());
879 
880   const char* main_thread_error = dlerror();
881   ASSERT_TRUE(main_thread_error != nullptr);
882   ASSERT_SUBSTR("/main/thread", main_thread_error);
883 }
884 
TEST(dlfcn,dlsym_failures)885 TEST(dlfcn, dlsym_failures) {
886   dlerror(); // Clear any pending errors.
887   void* self = dlopen(nullptr, RTLD_NOW);
888   ASSERT_TRUE(self != nullptr);
889   ASSERT_TRUE(dlerror() == nullptr);
890 
891   void* sym;
892 
893 #if defined(__BIONIC__) && !defined(__LP64__)
894 #pragma clang diagnostic push
895 #pragma clang diagnostic ignored "-Wnonnull"
896   // RTLD_DEFAULT in lp32 bionic is not (void*)0
897   // so it can be distinguished from the NULL handle.
898   sym = dlsym(nullptr, "test");
899   ASSERT_TRUE(sym == nullptr);
900   ASSERT_STREQ("dlsym failed: library handle is null", dlerror());
901 #pragma clang diagnostic pop
902 #endif
903 
904   // Symbol that doesn't exist.
905   sym = dlsym(self, "ThisSymbolDoesNotExist");
906   ASSERT_TRUE(sym == nullptr);
907   ASSERT_SUBSTR("undefined symbol: ThisSymbolDoesNotExist", dlerror());
908 
909   ASSERT_EQ(0, dlclose(self));
910 }
911 
TEST(dlfcn,dladdr_executable)912 TEST(dlfcn, dladdr_executable) {
913   dlerror(); // Clear any pending errors.
914   void* self = dlopen(nullptr, RTLD_NOW);
915   ASSERT_TRUE(self != nullptr);
916   ASSERT_TRUE(dlerror() == nullptr);
917 
918   void* sym = dlsym(self, "DlSymTestFunction");
919   ASSERT_TRUE(sym != nullptr);
920 
921   // Deliberately ask dladdr for an address inside a symbol, rather than the symbol base address.
922   void* addr = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(sym) + 2);
923 
924   Dl_info info;
925   int rc = dladdr(addr, &info);
926   ASSERT_NE(rc, 0); // Zero on error, non-zero on success.
927 
928   // Get the name of this executable.
929   const std::string executable_path = android::base::GetExecutablePath();
930 
931   // The filename should be that of this executable.
932   char dli_realpath[PATH_MAX];
933   ASSERT_TRUE(realpath(info.dli_fname, dli_realpath) != nullptr);
934   ASSERT_STREQ(executable_path.c_str(), dli_realpath);
935 
936   // The symbol name should be the symbol we looked up.
937   ASSERT_STREQ(info.dli_sname, "DlSymTestFunction");
938 
939   // The address should be the exact address of the symbol.
940   ASSERT_EQ(info.dli_saddr, sym);
941 
942   std::vector<map_record> maps;
943   ASSERT_TRUE(Maps::parse_maps(&maps));
944 
945   void* base_address = nullptr;
946   for (const map_record& rec : maps) {
947     if (executable_path == rec.pathname) {
948       base_address = reinterpret_cast<void*>(rec.addr_start);
949       break;
950     }
951   }
952 
953   // The base address should be the address we were loaded at.
954   ASSERT_EQ(info.dli_fbase, base_address);
955 
956   ASSERT_EQ(0, dlclose(self));
957 }
958 
TEST(dlfcn,dlopen_executable_by_absolute_path)959 TEST(dlfcn, dlopen_executable_by_absolute_path) {
960   void* handle1 = dlopen(nullptr, RTLD_NOW);
961   ASSERT_TRUE(handle1 != nullptr) << dlerror();
962 
963   void* handle2 = dlopen(android::base::GetExecutablePath().c_str(), RTLD_NOW);
964   ASSERT_TRUE(handle2 != nullptr) << dlerror();
965 
966 #if defined(__BIONIC__)
967   ASSERT_EQ(handle1, handle2);
968 #else
969   GTEST_SKIP() << "Skipping ASSERT_EQ(handle1, handle2) for glibc: "
970                   "it loads a separate copy of the main executable "
971                   "on dlopen by absolute path";
972 #endif
973 }
974 
975 #define ALTERNATE_PATH_TO_SYSTEM_LIB "/system/lib64/" ABI_STRING "/"
976 #if __has_feature(hwaddress_sanitizer)
977 #define PATH_TO_LIBC PATH_TO_SYSTEM_LIB "hwasan/libc.so"
978 #define PATH_TO_BOOTSTRAP_LIBC PATH_TO_SYSTEM_LIB "bootstrap/hwasan/libc.so"
979 #define ALTERNATE_PATH_TO_LIBC ALTERNATE_PATH_TO_SYSTEM_LIB "hwasan/libc.so"
980 #else
981 #define PATH_TO_LIBC PATH_TO_SYSTEM_LIB "libc.so"
982 #define PATH_TO_BOOTSTRAP_LIBC PATH_TO_SYSTEM_LIB "bootstrap/libc.so"
983 #define ALTERNATE_PATH_TO_LIBC ALTERNATE_PATH_TO_SYSTEM_LIB "libc.so"
984 #endif
985 
TEST(dlfcn,dladdr_libc)986 TEST(dlfcn, dladdr_libc) {
987 #if defined(__GLIBC__)
988   GTEST_SKIP() << "glibc returns libc.so's ldconfig path, which is a symlink (not a realpath)";
989 #endif
990 
991   Dl_info info;
992   void* addr = reinterpret_cast<void*>(puts);  // An arbitrary libc function.
993   ASSERT_TRUE(dladdr(addr, &info) != 0);
994 
995   // Check if libc is in canonical path or in alternate path.
996   const char* expected_path;
997   if (strncmp(ALTERNATE_PATH_TO_SYSTEM_LIB,
998               info.dli_fname,
999               sizeof(ALTERNATE_PATH_TO_SYSTEM_LIB) - 1) == 0) {
1000     // Platform with emulated architecture.  Symlink on ARC++.
1001     expected_path = ALTERNATE_PATH_TO_LIBC;
1002   } else if (strncmp(PATH_TO_BOOTSTRAP_LIBC, info.dli_fname,
1003                      sizeof(PATH_TO_BOOTSTRAP_LIBC) - 1) == 0) {
1004     expected_path = PATH_TO_BOOTSTRAP_LIBC;
1005   } else {
1006     // /system/lib is symlink when this test is executed on host.
1007     expected_path = PATH_TO_LIBC;
1008   }
1009   char libc_realpath[PATH_MAX];
1010   ASSERT_TRUE(realpath(expected_path, libc_realpath) != nullptr) << strerror(errno);
1011 
1012   ASSERT_STREQ(libc_realpath, info.dli_fname);
1013   // TODO: add check for dfi_fbase
1014   ASSERT_STREQ("puts", info.dli_sname);
1015   ASSERT_EQ(addr, info.dli_saddr);
1016 }
1017 
TEST(dlfcn,dladdr_invalid)1018 TEST(dlfcn, dladdr_invalid) {
1019   Dl_info info;
1020 
1021   dlerror(); // Clear any pending errors.
1022 
1023 #pragma clang diagnostic push
1024 #pragma clang diagnostic ignored "-Wnonnull"
1025   // No symbol corresponding to NULL.
1026   ASSERT_EQ(dladdr(nullptr, &info), 0); // Zero on error, non-zero on success.
1027   ASSERT_TRUE(dlerror() == nullptr); // dladdr(3) doesn't set dlerror(3).
1028 #pragma clang diagnostic pop
1029 
1030   // No symbol corresponding to a stack address.
1031   ASSERT_EQ(dladdr(&info, &info), 0); // Zero on error, non-zero on success.
1032   ASSERT_TRUE(dlerror() == nullptr); // dladdr(3) doesn't set dlerror(3).
1033 }
1034 
TEST(dlfcn,dlopen_library_with_only_gnu_hash)1035 TEST(dlfcn, dlopen_library_with_only_gnu_hash) {
1036   dlerror(); // Clear any pending errors.
1037   void* handle = dlopen("libgnu-hash-table-library.so", RTLD_NOW);
1038   ASSERT_TRUE(handle != nullptr) << dlerror();
1039   auto guard = android::base::make_scope_guard([&]() { dlclose(handle); });
1040   void* sym = dlsym(handle, "getRandomNumber");
1041   ASSERT_TRUE(sym != nullptr) << dlerror();
1042   int (*fn)(void);
1043   fn = reinterpret_cast<int (*)(void)>(sym);
1044   EXPECT_EQ(4, fn());
1045 
1046   Dl_info dlinfo;
1047   ASSERT_TRUE(0 != dladdr(reinterpret_cast<void*>(fn), &dlinfo));
1048 
1049   ASSERT_TRUE(fn == dlinfo.dli_saddr);
1050   ASSERT_STREQ("getRandomNumber", dlinfo.dli_sname);
1051   ASSERT_SUBSTR("libgnu-hash-table-library.so", dlinfo.dli_fname);
1052 }
1053 
TEST(dlfcn,dlopen_library_with_only_sysv_hash)1054 TEST(dlfcn, dlopen_library_with_only_sysv_hash) {
1055   void* handle = dlopen("libsysv-hash-table-library.so", RTLD_NOW);
1056   ASSERT_TRUE(handle != nullptr) << dlerror();
1057   auto guard = android::base::make_scope_guard([&]() { dlclose(handle); });
1058   void* sym = dlsym(handle, "getRandomNumber");
1059   ASSERT_TRUE(sym != nullptr) << dlerror();
1060   int (*fn)(void);
1061   fn = reinterpret_cast<int (*)(void)>(sym);
1062   EXPECT_EQ(4, fn());
1063 
1064   Dl_info dlinfo;
1065   ASSERT_TRUE(0 != dladdr(reinterpret_cast<void*>(fn), &dlinfo));
1066 
1067   ASSERT_TRUE(fn == dlinfo.dli_saddr);
1068   ASSERT_STREQ("getRandomNumber", dlinfo.dli_sname);
1069   ASSERT_SUBSTR("libsysv-hash-table-library.so", dlinfo.dli_fname);
1070 }
1071 
TEST(dlfcn,dlopen_bad_flags)1072 TEST(dlfcn, dlopen_bad_flags) {
1073   dlerror(); // Clear any pending errors.
1074   void* handle;
1075 
1076 #if defined(__GLIBC__)
1077   // glibc was smart enough not to define RTLD_NOW as 0, so it can detect missing flags.
1078   handle = dlopen(nullptr, 0);
1079   ASSERT_TRUE(handle == nullptr);
1080   ASSERT_SUBSTR("invalid", dlerror());
1081 #endif
1082 
1083   handle = dlopen(nullptr, 0xffffffff);
1084   ASSERT_TRUE(handle == nullptr);
1085   ASSERT_SUBSTR("invalid", dlerror());
1086 
1087   // glibc actually allows you to choose both RTLD_NOW and RTLD_LAZY at the same time, and so do we.
1088   handle = dlopen(nullptr, RTLD_NOW|RTLD_LAZY);
1089   ASSERT_TRUE(handle != nullptr);
1090   ASSERT_SUBSTR(nullptr, dlerror());
1091 }
1092 
TEST(dlfcn,rtld_default_unknown_symbol)1093 TEST(dlfcn, rtld_default_unknown_symbol) {
1094   void* addr = dlsym(RTLD_DEFAULT, "ANY_UNKNOWN_SYMBOL_NAME");
1095   ASSERT_TRUE(addr == nullptr);
1096 }
1097 
TEST(dlfcn,rtld_default_known_symbol)1098 TEST(dlfcn, rtld_default_known_symbol) {
1099   void* addr = dlsym(RTLD_DEFAULT, "fopen");
1100   ASSERT_TRUE(addr != nullptr);
1101 }
1102 
TEST(dlfcn,rtld_next_unknown_symbol)1103 TEST(dlfcn, rtld_next_unknown_symbol) {
1104   void* addr = dlsym(RTLD_NEXT, "ANY_UNKNOWN_SYMBOL_NAME");
1105   ASSERT_TRUE(addr == nullptr);
1106 }
1107 
TEST(dlfcn,rtld_next_known_symbol)1108 TEST(dlfcn, rtld_next_known_symbol) {
1109   void* addr = dlsym(RTLD_NEXT, "fopen");
1110   ASSERT_TRUE(addr != nullptr);
1111 }
1112 
1113 // Check that RTLD_NEXT of a libc symbol works in dlopened library
TEST(dlfcn,rtld_next_from_library)1114 TEST(dlfcn, rtld_next_from_library) {
1115   void* library_with_fclose = dlopen("libtest_check_rtld_next_from_library.so", RTLD_NOW | RTLD_GLOBAL);
1116   ASSERT_TRUE(library_with_fclose != nullptr) << dlerror();
1117   void* expected_addr = dlsym(RTLD_DEFAULT, "fclose");
1118   ASSERT_TRUE(expected_addr != nullptr) << dlerror();
1119   typedef void* (*get_libc_fclose_ptr_fn_t)();
1120   get_libc_fclose_ptr_fn_t get_libc_fclose_ptr =
1121       reinterpret_cast<get_libc_fclose_ptr_fn_t>(dlsym(library_with_fclose, "get_libc_fclose_ptr"));
1122   ASSERT_TRUE(get_libc_fclose_ptr != nullptr) << dlerror();
1123   ASSERT_EQ(expected_addr, get_libc_fclose_ptr());
1124 
1125   dlclose(library_with_fclose);
1126 }
1127 
1128 
TEST(dlfcn,dlsym_weak_func)1129 TEST(dlfcn, dlsym_weak_func) {
1130   dlerror();
1131   void* handle = dlopen("libtest_dlsym_weak_func.so", RTLD_NOW);
1132   ASSERT_TRUE(handle != nullptr);
1133 
1134   int (*weak_func)();
1135   weak_func = reinterpret_cast<int (*)()>(dlsym(handle, "weak_func"));
1136   ASSERT_TRUE(weak_func != nullptr) << "dlerror: " << dlerror();
1137   EXPECT_EQ(42, weak_func());
1138   dlclose(handle);
1139 }
1140 
TEST(dlfcn,dlopen_undefined_weak_func)1141 TEST(dlfcn, dlopen_undefined_weak_func) {
1142   void* handle = dlopen("libtest_dlopen_weak_undefined_func.so", RTLD_NOW);
1143   ASSERT_TRUE(handle != nullptr) << dlerror();
1144   int (*weak_func)();
1145   weak_func = reinterpret_cast<int (*)()>(dlsym(handle, "use_weak_undefined_func"));
1146   ASSERT_TRUE(weak_func != nullptr) << dlerror();
1147   EXPECT_EQ(6551, weak_func());
1148   dlclose(handle);
1149 }
1150 
TEST(dlfcn,dlopen_symlink)1151 TEST(dlfcn, dlopen_symlink) {
1152   DlfcnSymlink symlink("dlopen_symlink");
1153   const std::string symlink_name = android::base::Basename(symlink.get_symlink_path());
1154   void* handle1 = dlopen("libdlext_test.so", RTLD_NOW);
1155   void* handle2 = dlopen(symlink_name.c_str(), RTLD_NOW);
1156   ASSERT_TRUE(handle1 != nullptr);
1157   ASSERT_TRUE(handle2 != nullptr);
1158   ASSERT_EQ(handle1, handle2);
1159   dlclose(handle1);
1160   dlclose(handle2);
1161 }
1162 
1163 // libtest_dlopen_from_ctor_main.so depends on
1164 // libtest_dlopen_from_ctor.so which has a constructor
1165 // that calls dlopen(libc...). This is to test the situation
1166 // described in b/7941716.
TEST(dlfcn,dlopen_dlopen_from_ctor)1167 TEST(dlfcn, dlopen_dlopen_from_ctor) {
1168 #if defined(__GLIBC__)
1169   GTEST_SKIP() << "glibc segfaults if you try to call dlopen from a constructor";
1170 #endif
1171 
1172   void* handle = dlopen("libtest_dlopen_from_ctor_main.so", RTLD_NOW);
1173   ASSERT_TRUE(handle != nullptr) << dlerror();
1174   dlclose(handle);
1175 }
1176 
1177 static std::string g_fini_call_order_str;
1178 
register_fini_call(const char * s)1179 static void register_fini_call(const char* s) {
1180   g_fini_call_order_str += s;
1181 }
1182 
test_init_fini_call_order_for(const char * libname)1183 static void test_init_fini_call_order_for(const char* libname) {
1184   g_fini_call_order_str.clear();
1185   void* handle = dlopen(libname, RTLD_NOW);
1186   ASSERT_TRUE(handle != nullptr) << dlerror();
1187   typedef int (*get_init_order_number_t)();
1188   get_init_order_number_t get_init_order_number =
1189           reinterpret_cast<get_init_order_number_t>(dlsym(handle, "get_init_order_number"));
1190   ASSERT_EQ(321, get_init_order_number());
1191 
1192   typedef void (*set_fini_callback_t)(void (*f)(const char*));
1193   set_fini_callback_t set_fini_callback =
1194           reinterpret_cast<set_fini_callback_t>(dlsym(handle, "set_fini_callback"));
1195   set_fini_callback(register_fini_call);
1196   dlclose(handle);
1197   ASSERT_EQ("(root)(child)(grandchild)", g_fini_call_order_str);
1198 }
1199 
TEST(dlfcn,init_fini_call_order)1200 TEST(dlfcn, init_fini_call_order) {
1201   test_init_fini_call_order_for("libtest_init_fini_order_root.so");
1202   test_init_fini_call_order_for("libtest_init_fini_order_root2.so");
1203 }
1204 
TEST(dlfcn,symbol_versioning_use_v1)1205 TEST(dlfcn, symbol_versioning_use_v1) {
1206   void* handle = dlopen("libtest_versioned_uselibv1.so", RTLD_NOW);
1207   ASSERT_TRUE(handle != nullptr) << dlerror();
1208   typedef int (*fn_t)();
1209   fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "get_function_version"));
1210   ASSERT_TRUE(fn != nullptr) << dlerror();
1211   ASSERT_EQ(1, fn());
1212   dlclose(handle);
1213 }
1214 
TEST(dlfcn,symbol_versioning_use_v2)1215 TEST(dlfcn, symbol_versioning_use_v2) {
1216   void* handle = dlopen("libtest_versioned_uselibv2.so", RTLD_NOW);
1217   ASSERT_TRUE(handle != nullptr) << dlerror();
1218   typedef int (*fn_t)();
1219   fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "get_function_version"));
1220   ASSERT_TRUE(fn != nullptr) << dlerror();
1221   ASSERT_EQ(2, fn());
1222   dlclose(handle);
1223 }
1224 
TEST(dlfcn,symbol_versioning_use_other_v2)1225 TEST(dlfcn, symbol_versioning_use_other_v2) {
1226   void* handle = dlopen("libtest_versioned_uselibv2_other.so", RTLD_NOW);
1227   ASSERT_TRUE(handle != nullptr) << dlerror();
1228   typedef int (*fn_t)();
1229   fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "get_function_version"));
1230   ASSERT_TRUE(fn != nullptr) << dlerror();
1231   ASSERT_EQ(20, fn());
1232   dlclose(handle);
1233 }
1234 
TEST(dlfcn,symbol_versioning_use_other_v3)1235 TEST(dlfcn, symbol_versioning_use_other_v3) {
1236   void* handle = dlopen("libtest_versioned_uselibv3_other.so", RTLD_NOW);
1237   ASSERT_TRUE(handle != nullptr) << dlerror();
1238   typedef int (*fn_t)();
1239   fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "get_function_version"));
1240   ASSERT_TRUE(fn != nullptr) << dlerror();
1241   ASSERT_EQ(3, fn());
1242   dlclose(handle);
1243 }
1244 
TEST(dlfcn,symbol_versioning_default_via_dlsym)1245 TEST(dlfcn, symbol_versioning_default_via_dlsym) {
1246   void* handle = dlopen("libtest_versioned_lib.so", RTLD_NOW);
1247   ASSERT_TRUE(handle != nullptr) << dlerror();
1248   typedef int (*fn_t)();
1249   fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "versioned_function"));
1250   ASSERT_TRUE(fn != nullptr) << dlerror();
1251   ASSERT_EQ(3, fn()); // the default version is 3
1252   dlclose(handle);
1253 }
1254 
TEST(dlfcn,dlvsym_smoke)1255 TEST(dlfcn, dlvsym_smoke) {
1256 #if !defined(ANDROID_HOST_MUSL)
1257   void* handle = dlopen("libtest_versioned_lib.so", RTLD_NOW);
1258   ASSERT_TRUE(handle != nullptr) << dlerror();
1259   typedef int (*fn_t)();
1260 
1261   {
1262     fn_t fn = reinterpret_cast<fn_t>(dlvsym(handle, "versioned_function", "nonversion"));
1263     ASSERT_TRUE(fn == nullptr);
1264     ASSERT_SUBSTR("undefined symbol: versioned_function, version nonversion", dlerror());
1265   }
1266 
1267   {
1268     fn_t fn = reinterpret_cast<fn_t>(dlvsym(handle, "versioned_function", "TESTLIB_V2"));
1269     ASSERT_TRUE(fn != nullptr) << dlerror();
1270     ASSERT_EQ(2, fn());
1271   }
1272 
1273   dlclose(handle);
1274 #else
1275   GTEST_SKIP() << "musl doesn't have dlvsym";
1276 #endif
1277 }
1278 
1279 // This preempts the implementation from libtest_versioned_lib.so
version_zero_function()1280 extern "C" int version_zero_function() {
1281   return 0;
1282 }
1283 
1284 // This preempts the implementation from libtest_versioned_uselibv*.so
version_zero_function2()1285 extern "C" int version_zero_function2() {
1286   return 0;
1287 }
1288 
TEST(dlfcn,dt_runpath_smoke)1289 TEST(dlfcn, dt_runpath_smoke) {
1290   void* handle = dlopen("libtest_dt_runpath_d.so", RTLD_NOW);
1291   ASSERT_TRUE(handle != nullptr) << dlerror();
1292 
1293   typedef void *(* dlopen_b_fn)();
1294   dlopen_b_fn fn = (dlopen_b_fn)dlsym(handle, "dlopen_b");
1295   ASSERT_TRUE(fn != nullptr) << dlerror();
1296 
1297   void *p = fn();
1298   ASSERT_TRUE(p != nullptr);
1299 
1300   dlclose(handle);
1301 }
1302 
TEST(dlfcn,dt_runpath_absolute_path)1303 TEST(dlfcn, dt_runpath_absolute_path) {
1304   std::string libpath = GetTestLibRoot() + "/libtest_dt_runpath_d.so";
1305   void* handle = dlopen(libpath.c_str(), RTLD_NOW);
1306   ASSERT_TRUE(handle != nullptr) << dlerror();
1307 
1308   typedef void *(* dlopen_b_fn)();
1309   dlopen_b_fn fn = (dlopen_b_fn)dlsym(handle, "dlopen_b");
1310   ASSERT_TRUE(fn != nullptr) << dlerror();
1311 
1312   void *p = fn();
1313   ASSERT_TRUE(p != nullptr);
1314 
1315   dlclose(handle);
1316 }
1317 
test_dlclose_after_thread_local_dtor(const char * library_name)1318 static void test_dlclose_after_thread_local_dtor(const char* library_name) {
1319   bool is_dtor_triggered = false;
1320 
1321   auto f = [](void* handle, bool* is_dtor_triggered) {
1322     typedef void (*fn_t)(bool*);
1323     fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "init_thread_local_variable"));
1324     ASSERT_TRUE(fn != nullptr) << dlerror();
1325 
1326     fn(is_dtor_triggered);
1327 
1328     ASSERT_TRUE(!*is_dtor_triggered);
1329   };
1330 
1331   void* handle = dlopen(library_name, RTLD_NOW | RTLD_NOLOAD);
1332   ASSERT_TRUE(handle == nullptr);
1333 
1334   handle = dlopen(library_name, RTLD_NOW);
1335   ASSERT_TRUE(handle != nullptr) << dlerror();
1336 
1337   std::thread t(f, handle, &is_dtor_triggered);
1338   t.join();
1339 
1340   ASSERT_TRUE(is_dtor_triggered);
1341   dlclose(handle);
1342 
1343   handle = dlopen(library_name, RTLD_NOW | RTLD_NOLOAD);
1344   ASSERT_TRUE(handle == nullptr);
1345 }
1346 
TEST(dlfcn,dlclose_after_thread_local_dtor)1347 TEST(dlfcn, dlclose_after_thread_local_dtor) {
1348   test_dlclose_after_thread_local_dtor("libtest_thread_local_dtor.so");
1349 }
1350 
TEST(dlfcn,dlclose_after_thread_local_dtor_indirect)1351 TEST(dlfcn, dlclose_after_thread_local_dtor_indirect) {
1352   test_dlclose_after_thread_local_dtor("libtest_indirect_thread_local_dtor.so");
1353 }
1354 
test_dlclose_before_thread_local_dtor(const char * library_name)1355 static void test_dlclose_before_thread_local_dtor(const char* library_name) {
1356   bool is_dtor_triggered = false;
1357 
1358   auto f = [library_name](bool* is_dtor_triggered) {
1359     void* handle = dlopen(library_name, RTLD_NOW | RTLD_NOLOAD);
1360     ASSERT_TRUE(handle == nullptr);
1361 
1362     handle = dlopen(library_name, RTLD_NOW);
1363     ASSERT_TRUE(handle != nullptr) << dlerror();
1364 
1365     typedef void (*fn_t)(bool*);
1366     fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "init_thread_local_variable"));
1367     ASSERT_TRUE(fn != nullptr) << dlerror();
1368 
1369     fn(is_dtor_triggered);
1370 
1371     dlclose(handle);
1372 
1373     ASSERT_TRUE(!*is_dtor_triggered);
1374 
1375     // Since we have thread_atexit dtors associated with handle - the library should
1376     // still be availabe.
1377     handle = dlopen(library_name, RTLD_NOW | RTLD_NOLOAD);
1378     ASSERT_TRUE(handle != nullptr) << dlerror();
1379     dlclose(handle);
1380   };
1381 
1382   void* handle = dlopen(library_name, RTLD_NOW);
1383   ASSERT_TRUE(handle != nullptr) << dlerror();
1384   dlclose(handle);
1385 
1386   handle = dlopen(library_name, RTLD_NOW | RTLD_NOLOAD);
1387   ASSERT_TRUE(handle == nullptr);
1388 
1389   std::thread t(f, &is_dtor_triggered);
1390   t.join();
1391 #if defined(__BIONIC__)
1392   // ld-android.so unloads unreferenced libraries on pthread_exit()
1393   ASSERT_TRUE(is_dtor_triggered);
1394   handle = dlopen(library_name, RTLD_NOW | RTLD_NOLOAD);
1395   ASSERT_TRUE(handle == nullptr);
1396 #else
1397   // GLIBC does not unload libraries with ref_count = 0 on pthread_exit
1398   ASSERT_TRUE(is_dtor_triggered);
1399   handle = dlopen(library_name, RTLD_NOW | RTLD_NOLOAD);
1400   ASSERT_TRUE(handle != nullptr) << dlerror();
1401 #endif
1402 }
1403 
TEST(dlfcn,dlclose_before_thread_local_dtor)1404 TEST(dlfcn, dlclose_before_thread_local_dtor) {
1405   test_dlclose_before_thread_local_dtor("libtest_thread_local_dtor.so");
1406 }
1407 
TEST(dlfcn,dlclose_before_thread_local_dtor_indirect)1408 TEST(dlfcn, dlclose_before_thread_local_dtor_indirect) {
1409   test_dlclose_before_thread_local_dtor("libtest_indirect_thread_local_dtor.so");
1410 }
1411 
TEST(dlfcn,dlclose_before_thread_local_dtor_multiple_dsos)1412 TEST(dlfcn, dlclose_before_thread_local_dtor_multiple_dsos) {
1413   const constexpr char* library_name = "libtest_indirect_thread_local_dtor.so";
1414 
1415   bool is_dtor1_triggered = false;
1416   bool is_dtor2_triggered = false;
1417 
1418   std::mutex mtx;
1419   std::condition_variable cv;
1420   void* library_handle = nullptr;
1421   bool thread1_dlopen_complete = false;
1422   bool thread2_thread_local_dtor_initialized = false;
1423   bool thread1_complete = false;
1424 
1425   auto f1 = [&]() {
1426     void* handle = dlopen(library_name, RTLD_NOW | RTLD_NOLOAD);
1427     ASSERT_TRUE(handle == nullptr);
1428 
1429     handle = dlopen(library_name, RTLD_NOW);
1430     ASSERT_TRUE(handle != nullptr) << dlerror();
1431     std::unique_lock<std::mutex> lock(mtx);
1432     thread1_dlopen_complete = true;
1433     library_handle = handle;
1434     lock.unlock();
1435     cv.notify_one();
1436 
1437     typedef void (*fn_t)(bool*);
1438     fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "init_thread_local_variable"));
1439     ASSERT_TRUE(fn != nullptr) << dlerror();
1440 
1441     fn(&is_dtor1_triggered);
1442 
1443     lock.lock();
1444     cv.wait(lock, [&] { return thread2_thread_local_dtor_initialized; });
1445     lock.unlock();
1446 
1447     dlclose(handle);
1448 
1449     ASSERT_TRUE(!is_dtor1_triggered);
1450 
1451     // Since we have thread_atexit dtors associated with handle - the library should
1452     // still be availabe.
1453     handle = dlopen(library_name, RTLD_NOW | RTLD_NOLOAD);
1454     ASSERT_TRUE(handle != nullptr) << dlerror();
1455     dlclose(handle);
1456   };
1457 
1458   auto f2 = [&]() {
1459     std::unique_lock<std::mutex> lock(mtx);
1460     cv.wait(lock, [&] { return thread1_dlopen_complete; });
1461     void* handle = library_handle;
1462     lock.unlock();
1463 
1464     typedef void (*fn_t)(bool*);
1465     fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "init_thread_local_variable2"));
1466     ASSERT_TRUE(fn != nullptr) << dlerror();
1467 
1468     fn(&is_dtor2_triggered);
1469 
1470     lock.lock();
1471     thread2_thread_local_dtor_initialized = true;
1472     lock.unlock();
1473     cv.notify_one();
1474 
1475     lock.lock();
1476     cv.wait(lock, [&] { return thread1_complete; });
1477     lock.unlock();
1478 
1479     ASSERT_TRUE(!is_dtor2_triggered);
1480   };
1481 
1482   void* handle = dlopen(library_name, RTLD_NOW);
1483   ASSERT_TRUE(handle != nullptr) << dlerror();
1484   dlclose(handle);
1485 
1486   handle = dlopen(library_name, RTLD_NOW | RTLD_NOLOAD);
1487   ASSERT_TRUE(handle == nullptr);
1488 
1489   std::thread t1(f1);
1490   std::thread t2(f2);
1491   t1.join();
1492   ASSERT_TRUE(is_dtor1_triggered);
1493   ASSERT_TRUE(!is_dtor2_triggered);
1494 
1495   handle = dlopen(library_name, RTLD_NOW | RTLD_NOLOAD);
1496   ASSERT_TRUE(handle != nullptr) << dlerror();
1497   dlclose(handle);
1498 
1499   std::unique_lock<std::mutex> lock(mtx);
1500   thread1_complete = true;
1501   lock.unlock();
1502   cv.notify_one();
1503 
1504   t2.join();
1505   ASSERT_TRUE(is_dtor2_triggered);
1506 
1507 #if defined(__BIONIC__)
1508   // ld-android.so unloads unreferenced libraries on pthread_exit()
1509   handle = dlopen(library_name, RTLD_NOW | RTLD_NOLOAD);
1510   ASSERT_TRUE(handle == nullptr);
1511 #else
1512   // GLIBC does not unload libraries with ref_count = 0 on pthread_exit
1513   handle = dlopen(library_name, RTLD_NOW | RTLD_NOLOAD);
1514   ASSERT_TRUE(handle != nullptr) << dlerror();
1515 #endif
1516 }
1517 
TEST(dlfcn,RTLD_macros)1518 TEST(dlfcn, RTLD_macros) {
1519 #if !defined(RTLD_LOCAL)
1520 #error no RTLD_LOCAL
1521 #elif !defined(RTLD_LAZY)
1522 #error no RTLD_LAZY
1523 #elif !defined(RTLD_NOW)
1524 #error no RTLD_NOW
1525 #elif !defined(RTLD_NOLOAD)
1526 #error no RTLD_NOLOAD
1527 #elif !defined(RTLD_GLOBAL)
1528 #error no RTLD_GLOBAL
1529 #elif !defined(RTLD_NODELETE)
1530 #error no RTLD_NODELETE
1531 #endif
1532 }
1533 
1534 // Bionic specific tests
1535 #if defined(__BIONIC__)
1536 
1537 #if defined(__arm__)
1538 
validate_compatibility_of_native_library(const std::string & soname,const std::string & path)1539 void validate_compatibility_of_native_library(const std::string& soname, const std::string& path) {
1540   // Grab the dynamic section in text form...
1541   ExecTestHelper eth;
1542   eth.SetArgs({"readelf", "-dW", path.c_str(), nullptr});
1543   eth.Run([&]() { execvpe("readelf", eth.GetArgs(), eth.GetEnv()); }, 0, nullptr);
1544   std::string output = eth.GetOutput();
1545 
1546   // Check that there *is* a legacy DT_HASH (not just a GNU hash)...
1547   ASSERT_TRUE(std::regex_search(output, std::regex("\\(HASH\\)"))) << output;
1548   // Check that there is no DT_ANDROID_REL or DT_ANDROID_RELA...
1549   ASSERT_FALSE(std::regex_search(output, std::regex("\\(ANDROID_REL\\)"))) << output;
1550   ASSERT_FALSE(std::regex_search(output, std::regex("\\(ANDROID_RELA\\)"))) << output;
1551 
1552   // Check that we have regular non-packed relocations.
1553   // libdl.so is simple enough that it doesn't have any relocations.
1554   ASSERT_TRUE(std::regex_search(output, std::regex("\\(RELA?\\)")) || soname == "libdl.so")
1555       << output;
1556 }
1557 
validate_compatibility_of_native_library(const std::string & soname)1558 void validate_compatibility_of_native_library(const std::string& soname) {
1559   // On the systems with emulation system libraries would be of different
1560   // architecture.  Try to use alternate paths first.
1561   std::string path = std::string(ALTERNATE_PATH_TO_SYSTEM_LIB) + soname;
1562   if (access(path.c_str(), R_OK) != 0) {
1563     path = std::string(PATH_TO_SYSTEM_LIB) + soname;
1564     ASSERT_EQ(0, access(path.c_str(), R_OK));
1565   }
1566   validate_compatibility_of_native_library(soname, path);
1567 }
1568 
1569 // This is a test for app compatibility workaround for arm apps
1570 // affected by http://b/24465209
TEST(dlext,compat_elf_hash_and_relocation_tables)1571 TEST(dlext, compat_elf_hash_and_relocation_tables) {
1572   validate_compatibility_of_native_library("libc.so");
1573   validate_compatibility_of_native_library("liblog.so");
1574   validate_compatibility_of_native_library("libstdc++.so");
1575   validate_compatibility_of_native_library("libdl.so");
1576   validate_compatibility_of_native_library("libm.so");
1577   validate_compatibility_of_native_library("libz.so");
1578   validate_compatibility_of_native_library("libjnigraphics.so");
1579 }
1580 
1581 #endif //  defined(__arm__)
1582 
TEST(dlfcn,dlopen_invalid_rw_load_segment)1583 TEST(dlfcn, dlopen_invalid_rw_load_segment) {
1584   const std::string libpath = GetPrebuiltElfDir() + "/libtest_invalid-rw_load_segment.so";
1585   void* handle = dlopen(libpath.c_str(), RTLD_NOW);
1586   ASSERT_TRUE(handle == nullptr);
1587   std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\": W+E load segments are not allowed";
1588   ASSERT_STREQ(expected_dlerror.c_str(), dlerror());
1589 }
1590 
TEST(dlfcn,dlopen_invalid_unaligned_shdr_offset)1591 TEST(dlfcn, dlopen_invalid_unaligned_shdr_offset) {
1592   const std::string libpath = GetPrebuiltElfDir() + "/libtest_invalid-unaligned_shdr_offset.so";
1593 
1594   void* handle = dlopen(libpath.c_str(), RTLD_NOW);
1595   ASSERT_TRUE(handle == nullptr);
1596   std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\" has invalid shdr offset/size: ";
1597   ASSERT_SUBSTR(expected_dlerror.c_str(), dlerror());
1598 }
1599 
TEST(dlfcn,dlopen_invalid_zero_shentsize)1600 TEST(dlfcn, dlopen_invalid_zero_shentsize) {
1601   const std::string libpath = GetPrebuiltElfDir() + "/libtest_invalid-zero_shentsize.so";
1602 
1603   void* handle = dlopen(libpath.c_str(), RTLD_NOW);
1604   ASSERT_TRUE(handle == nullptr);
1605   std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\" has unsupported e_shentsize: 0x0 (expected 0x";
1606   ASSERT_SUBSTR(expected_dlerror.c_str(), dlerror());
1607 }
1608 
TEST(dlfcn,dlopen_invalid_zero_shstrndx)1609 TEST(dlfcn, dlopen_invalid_zero_shstrndx) {
1610   const std::string libpath = GetPrebuiltElfDir() + "/libtest_invalid-zero_shstrndx.so";
1611 
1612   void* handle = dlopen(libpath.c_str(), RTLD_NOW);
1613   ASSERT_TRUE(handle == nullptr);
1614   std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\" has invalid e_shstrndx";
1615   ASSERT_STREQ(expected_dlerror.c_str(), dlerror());
1616 }
1617 
TEST(dlfcn,dlopen_invalid_empty_shdr_table)1618 TEST(dlfcn, dlopen_invalid_empty_shdr_table) {
1619   const std::string libpath = GetPrebuiltElfDir() + "/libtest_invalid-empty_shdr_table.so";
1620 
1621   void* handle = dlopen(libpath.c_str(), RTLD_NOW);
1622   ASSERT_TRUE(handle == nullptr);
1623   std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\" has no section headers";
1624   ASSERT_STREQ(expected_dlerror.c_str(), dlerror());
1625 }
1626 
TEST(dlfcn,dlopen_invalid_zero_shdr_table_offset)1627 TEST(dlfcn, dlopen_invalid_zero_shdr_table_offset) {
1628   const std::string libpath = GetPrebuiltElfDir() + "/libtest_invalid-zero_shdr_table_offset.so";
1629 
1630   void* handle = dlopen(libpath.c_str(), RTLD_NOW);
1631   ASSERT_TRUE(handle == nullptr);
1632   std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\" has invalid shdr offset/size: 0/";
1633   ASSERT_SUBSTR(expected_dlerror.c_str(), dlerror());
1634 }
1635 
TEST(dlfcn,dlopen_invalid_zero_shdr_table_content)1636 TEST(dlfcn, dlopen_invalid_zero_shdr_table_content) {
1637   const std::string libpath = GetPrebuiltElfDir() + "/libtest_invalid-zero_shdr_table_content.so";
1638 
1639   void* handle = dlopen(libpath.c_str(), RTLD_NOW);
1640   ASSERT_TRUE(handle == nullptr);
1641   std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\" .dynamic section header was not found";
1642   ASSERT_SUBSTR(expected_dlerror.c_str(), dlerror());
1643 }
1644 
TEST(dlfcn,dlopen_invalid_textrels)1645 TEST(dlfcn, dlopen_invalid_textrels) {
1646   const std::string libpath = GetPrebuiltElfDir() + "/libtest_invalid-textrels.so";
1647 
1648   void* handle = dlopen(libpath.c_str(), RTLD_NOW);
1649   ASSERT_TRUE(handle == nullptr);
1650   std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\" has text relocations";
1651   ASSERT_SUBSTR(expected_dlerror.c_str(), dlerror());
1652 }
1653 
TEST(dlfcn,dlopen_invalid_textrels2)1654 TEST(dlfcn, dlopen_invalid_textrels2) {
1655   const std::string libpath = GetPrebuiltElfDir() + "/libtest_invalid-textrels2.so";
1656 
1657   void* handle = dlopen(libpath.c_str(), RTLD_NOW);
1658   ASSERT_TRUE(handle == nullptr);
1659   std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\" has text relocations";
1660   ASSERT_SUBSTR(expected_dlerror.c_str(), dlerror());
1661 }
1662 
TEST(dlfcn,dlopen_invalid_local_tls)1663 TEST(dlfcn, dlopen_invalid_local_tls) {
1664 #if defined(__riscv)
1665   // This is a test for bad gold behavior, and gold doesn't support riscv64.
1666 #else
1667   const std::string libpath = GetPrebuiltElfDir() + "/libtest_invalid-local-tls.so";
1668 
1669   void* handle = dlopen(libpath.c_str(), RTLD_NOW);
1670   ASSERT_TRUE(handle == nullptr);
1671 #if defined(__arm__)
1672   const char* referent = "local section";
1673 #else
1674   const char* referent = "local symbol \"tls_var_2\"";
1675 #endif
1676   std::string expected_dlerror = std::string("dlopen failed: unexpected TLS reference to ") +
1677                                  referent + " in \"" + libpath + "\"";
1678   ASSERT_SUBSTR(expected_dlerror.c_str(), dlerror());
1679 #endif
1680 }
1681 
TEST(dlfcn,dlopen_df_1_global)1682 TEST(dlfcn, dlopen_df_1_global) {
1683   void* handle = dlopen("libtest_dlopen_df_1_global.so", RTLD_NOW);
1684   ASSERT_TRUE(handle != nullptr) << dlerror();
1685 }
1686 
TEST(dlfcn,segment_gap)1687 TEST(dlfcn, segment_gap) {
1688   void* handle = dlopen("libsegment_gap_outer.so", RTLD_NOW);
1689   ASSERT_TRUE(handle != nullptr) << dlerror();
1690 
1691   auto get_inner = reinterpret_cast<void* (*)()>(dlsym(handle, "get_inner"));
1692   void* inner = get_inner();
1693   (void)inner;
1694 
1695 #if __arm__
1696   int count;
1697   _Unwind_Ptr outer_exidx = dl_unwind_find_exidx(reinterpret_cast<_Unwind_Ptr>(get_inner), &count);
1698   _Unwind_Ptr inner_exidx = dl_unwind_find_exidx(reinterpret_cast<_Unwind_Ptr>(inner), &count);
1699   EXPECT_NE(0u, outer_exidx);
1700   EXPECT_NE(0u, inner_exidx);
1701   EXPECT_NE(inner_exidx, outer_exidx);
1702 #endif
1703 
1704   Dl_info info;
1705   int rc = dladdr(inner, &info);
1706   ASSERT_NE(rc, 0);
1707 
1708   EXPECT_NE(nullptr, strstr(info.dli_fname, "libsegment_gap_inner.so"));
1709 }
1710 
1711 #endif
1712