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