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