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