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