dlfcn_test.cpp revision b3356773c6b5fbbbb26d22b3d6c6e0e598840e44
1acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao/* 2acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao * Copyright (C) 2012 The Android Open Source Project 3acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao * 4acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao * Licensed under the Apache License, Version 2.0 (the "License"); 5acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao * you may not use this file except in compliance with the License. 6acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao * You may obtain a copy of the License at 7acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao * 8acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao * http://www.apache.org/licenses/LICENSE-2.0 9acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao * 10acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao * Unless required by applicable law or agreed to in writing, software 11acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao * distributed under the License is distributed on an "AS IS" BASIS, 12acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao * See the License for the specific language governing permissions and 14acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao * limitations under the License. 15acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao */ 16acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao 17acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao#include <gtest/gtest.h> 18acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao 19acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao#include <dlfcn.h> 208e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes#include <libgen.h> 218e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes#include <limits.h> 228e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes#include <stdio.h> 238e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes#include <stdint.h> 248e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 25b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov#include "private/ScopeGuard.h" 26b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov 278e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes#include <string> 28acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao 293b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes#define ASSERT_SUBSTR(needle, haystack) \ 303b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_PRED_FORMAT2(::testing::IsSubstring, needle, haystack) 313b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 321728b2396591853345507a063ed6075dfd251706Elliott Hughesstatic bool g_called = false; 33acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhaoextern "C" void DlSymTestFunction() { 341728b2396591853345507a063ed6075dfd251706Elliott Hughes g_called = true; 35acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao} 36acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao 37f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanovstatic int g_ctor_function_called = 0; 38f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanov 39f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanovextern "C" void ctor_function() __attribute__ ((constructor)); 40f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanov 41f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanovextern "C" void ctor_function() { 42f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanov g_ctor_function_called = 17; 43f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanov} 44f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanov 45f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy IvanovTEST(dlfcn, ctor_function_call) { 46f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanov ASSERT_EQ(17, g_ctor_function_called); 47f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanov} 48f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanov 49e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott HughesTEST(dlfcn, dlsym_in_self) { 503b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes dlerror(); // Clear any pending errors. 51acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao void* self = dlopen(NULL, RTLD_NOW); 52acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao ASSERT_TRUE(self != NULL); 533b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_TRUE(dlerror() == NULL); 54acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao 55acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao void* sym = dlsym(self, "DlSymTestFunction"); 56acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao ASSERT_TRUE(sym != NULL); 57acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao 58acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao void (*function)() = reinterpret_cast<void(*)()>(sym); 59acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao 601728b2396591853345507a063ed6075dfd251706Elliott Hughes g_called = false; 61acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao function(); 621728b2396591853345507a063ed6075dfd251706Elliott Hughes ASSERT_TRUE(g_called); 631a6961650c82168864afe040dbdc05977db701dfElliott Hughes 641a6961650c82168864afe040dbdc05977db701dfElliott Hughes ASSERT_EQ(0, dlclose(self)); 65acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao} 668e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 67aa0f2bdbc22d4b7aec5d3f8f5f01eaeaa13414c2Dmitriy IvanovTEST(dlfcn, dlsym_with_dependencies) { 68aa0f2bdbc22d4b7aec5d3f8f5f01eaeaa13414c2Dmitriy Ivanov void* handle = dlopen("libtest_with_dependency.so", RTLD_NOW); 69aa0f2bdbc22d4b7aec5d3f8f5f01eaeaa13414c2Dmitriy Ivanov ASSERT_TRUE(handle != NULL); 70aa0f2bdbc22d4b7aec5d3f8f5f01eaeaa13414c2Dmitriy Ivanov dlerror(); 71aa0f2bdbc22d4b7aec5d3f8f5f01eaeaa13414c2Dmitriy Ivanov // This symbol is in DT_NEEDED library. 72aa0f2bdbc22d4b7aec5d3f8f5f01eaeaa13414c2Dmitriy Ivanov void* sym = dlsym(handle, "getRandomNumber"); 73aa0f2bdbc22d4b7aec5d3f8f5f01eaeaa13414c2Dmitriy Ivanov ASSERT_TRUE(sym != NULL); 74aa0f2bdbc22d4b7aec5d3f8f5f01eaeaa13414c2Dmitriy Ivanov int (*fn)(void); 75aa0f2bdbc22d4b7aec5d3f8f5f01eaeaa13414c2Dmitriy Ivanov fn = reinterpret_cast<int (*)(void)>(sym); 76aa0f2bdbc22d4b7aec5d3f8f5f01eaeaa13414c2Dmitriy Ivanov EXPECT_EQ(4, fn()); 77aa0f2bdbc22d4b7aec5d3f8f5f01eaeaa13414c2Dmitriy Ivanov dlclose(handle); 78aa0f2bdbc22d4b7aec5d3f8f5f01eaeaa13414c2Dmitriy Ivanov} 79aa0f2bdbc22d4b7aec5d3f8f5f01eaeaa13414c2Dmitriy Ivanov 80b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy IvanovTEST(dlfcn, dlopen_noload) { 81b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov void* handle = dlopen("libtest_simple.so", RTLD_NOW | RTLD_NOLOAD); 82b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov ASSERT_TRUE(handle == NULL); 83b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov handle = dlopen("libtest_simple.so", RTLD_NOW); 84b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov void* handle2 = dlopen("libtest_simple.so", RTLD_NOW | RTLD_NOLOAD); 85b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov ASSERT_TRUE(handle != NULL); 86b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov ASSERT_TRUE(handle2 != NULL); 87b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov ASSERT_TRUE(handle == handle2); 88b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov ASSERT_EQ(0, dlclose(handle)); 89b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov ASSERT_EQ(0, dlclose(handle2)); 90b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov} 91b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov 929aea164457c269c475592da36b4655d45f55c7bcDmitriy Ivanov// ifuncs are only supported on intel and arm64 for now 939aea164457c269c475592da36b4655d45f55c7bcDmitriy Ivanov#if defined (__aarch64__) || defined(__i386__) || defined(__x86_64__) 94c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid SmithTEST(dlfcn, ifunc) { 959598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov typedef const char* (*fn_ptr)(); 96c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith 97c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith // ifunc's choice depends on whether IFUNC_CHOICE has a value 98c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith // first check the set case 99c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith setenv("IFUNC_CHOICE", "set", 1); 100c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith void* handle = dlopen("libtest_ifunc.so", RTLD_NOW); 101c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith ASSERT_TRUE(handle != NULL); 1029598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov fn_ptr foo_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo")); 1039598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov fn_ptr foo_library_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo_library")); 104c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith ASSERT_TRUE(foo_ptr != NULL); 105c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith ASSERT_TRUE(foo_library_ptr != NULL); 1069598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov ASSERT_EQ(strncmp("set", foo_ptr(), 3), 0); 1079598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov ASSERT_EQ(strncmp("set", foo_library_ptr(), 3), 0); 108c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith dlclose(handle); 109c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith 110c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith // then check the unset case 111c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith unsetenv("IFUNC_CHOICE"); 112c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith handle = dlopen("libtest_ifunc.so", RTLD_NOW); 113c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith ASSERT_TRUE(handle != NULL); 1149598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov foo_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo")); 1159598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov foo_library_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo_library")); 116c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith ASSERT_TRUE(foo_ptr != NULL); 117c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith ASSERT_TRUE(foo_library_ptr != NULL); 1189598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov ASSERT_EQ(strncmp("unset", foo_ptr(), 5), 0); 1199598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov ASSERT_EQ(strncmp("unset", foo_library_ptr(), 3), 0); 1209598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov dlclose(handle); 1219598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov} 1229598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov 1239598b8c415e2fa9f240508185fe8c964b83f538dDmitriy IvanovTEST(dlfcn, ifunc_ctor_call) { 1249598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov typedef const char* (*fn_ptr)(); 1259598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov 1269598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov void* handle = dlopen("libtest_ifunc.so", RTLD_NOW); 1279aea164457c269c475592da36b4655d45f55c7bcDmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 1289aea164457c269c475592da36b4655d45f55c7bcDmitriy Ivanov fn_ptr is_ctor_called = reinterpret_cast<fn_ptr>(dlsym(handle, "is_ctor_called_irelative")); 1299aea164457c269c475592da36b4655d45f55c7bcDmitriy Ivanov ASSERT_TRUE(is_ctor_called != nullptr) << dlerror(); 1309aea164457c269c475592da36b4655d45f55c7bcDmitriy Ivanov ASSERT_STREQ("false", is_ctor_called()); 1319aea164457c269c475592da36b4655d45f55c7bcDmitriy Ivanov 1329aea164457c269c475592da36b4655d45f55c7bcDmitriy Ivanov is_ctor_called = reinterpret_cast<fn_ptr>(dlsym(handle, "is_ctor_called_jump_slot")); 1339aea164457c269c475592da36b4655d45f55c7bcDmitriy Ivanov ASSERT_TRUE(is_ctor_called != nullptr) << dlerror(); 1349598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov ASSERT_STREQ("true", is_ctor_called()); 135c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith dlclose(handle); 136c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith} 137c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith#endif 138c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith 139b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy IvanovTEST(dlfcn, dlopen_check_relocation_dt_needed_order) { 140b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // This is the structure of the test library and 141b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // its dt_needed libraries 142b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // libtest_relo_check_dt_needed_order.so 143b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // | 144b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // +-> libtest_relo_check_dt_needed_order_1.so 145b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // | 146b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // +-> libtest_relo_check_dt_needed_order_2.so 147b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // 148b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // The root library references relo_test_get_answer_lib - which is defined 149b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // in both dt_needed libraries, the correct relocation should 150b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // use the function defined in libtest_relo_check_dt_needed_order_1.so 151b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov void* handle = nullptr; 152d9ff7226613014056c9edd79a68dc5af939107a0Dmitriy Ivanov auto guard = make_scope_guard([&]() { 153b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov dlclose(handle); 154b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov }); 155b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov 156b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov handle = dlopen("libtest_relo_check_dt_needed_order.so", RTLD_NOW); 157b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 158b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov 159b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov typedef int (*fn_t) (void); 160b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "relo_test_get_answer")); 161b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov ASSERT_TRUE(fn != nullptr) << dlerror(); 162b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov ASSERT_EQ(1, fn()); 163b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov} 164b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov 165cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy IvanovTEST(dlfcn, dlopen_check_order_dlsym) { 16614669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // Here is how the test library and its dt_needed 16714669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // libraries are arranged 16814669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // 169cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // libtest_check_order_children.so 17014669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // | 171cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._1_left.so 17214669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // | | 173cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | +-> ..._a.so 17414669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // | | 175cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | +-> ...r_b.so 17614669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // | 177cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._2_right.so 17814669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // | | 179cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | +-> ..._d.so 18014669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // | | 181cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | +-> ..._b.so 18214669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // | 183cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._3_c.so 18414669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // 18514669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // load order should be (1, 2, 3, a, b, d) 18614669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // 18714669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // get_answer() is defined in (2, 3, a, b, c) 18814669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // get_answer2() is defined in (b, d) 189cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov void* sym = dlsym(RTLD_DEFAULT, "check_order_dlsym_get_answer"); 19014669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov ASSERT_TRUE(sym == nullptr); 191cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov void* handle = dlopen("libtest_check_order_dlsym.so", RTLD_NOW | RTLD_GLOBAL); 192cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 19314669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov typedef int (*fn_t) (void); 19414669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov fn_t fn, fn2; 195cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov fn = reinterpret_cast<fn_t>(dlsym(RTLD_DEFAULT, "check_order_dlsym_get_answer")); 196eb27bbae8f0edc6b62ca2db73256c7fb53b9e9bfDmitriy Ivanov ASSERT_TRUE(fn != NULL) << dlerror(); 197cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov fn2 = reinterpret_cast<fn_t>(dlsym(RTLD_DEFAULT, "check_order_dlsym_get_answer2")); 198eb27bbae8f0edc6b62ca2db73256c7fb53b9e9bfDmitriy Ivanov ASSERT_TRUE(fn2 != NULL) << dlerror(); 19914669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov 20014669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov ASSERT_EQ(42, fn()); 20114669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov ASSERT_EQ(43, fn2()); 20214669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov dlclose(handle); 20314669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov} 20414669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov 205cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy IvanovTEST(dlfcn, dlopen_check_order_reloc_siblings) { 206cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // This is how this one works: 207cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // we lookup and call get_answer which is defined in '_2.so' 208cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // and in turn calls external get_answer_impl() defined in _1.so and in '_[a-f].so' 209cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // the correct _impl() is implemented by '_a.so'; 210cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // 211cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // Note that this is test for RTLD_LOCAL (TODO: test for GLOBAL?) 212cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // 213cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // Here is the picture: 214cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // 215cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // libtest_check_order_reloc_siblings.so 216cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | 217cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._1.so <- empty 218cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | | 219cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | +-> ..._a.so <- exports correct answer_impl() 220cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | | 221cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | +-> ..._b.so <- every other letter exporting incorrect one. 222cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | 223cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._2.so <- empty 224cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | | 225cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | +-> ..._c.so 226cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | | 227cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | +-> ..._d.so 228cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | 229cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._3.so <- empty 230cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | 231cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._e.so 232cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | 233cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._f.so <- exports get_answer() that calls get_anser_impl(); 234cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // implements incorrect get_answer_impl() 235cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 236cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov void* handle = dlopen("libtest_check_order_reloc_siblings.so", RTLD_NOW | RTLD_NOLOAD); 237cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(handle == nullptr); 238cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov#ifdef __BIONIC__ 239cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // TODO: glibc returns nullptr on dlerror() here. Is it bug? 240cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_STREQ("dlopen failed: library \"libtest_check_order_reloc_siblings.so\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror()); 241cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov#endif 242cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 243cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov handle = dlopen("libtest_check_order_reloc_siblings.so", RTLD_NOW | RTLD_LOCAL); 244cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 245cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 246cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov typedef int (*fn_t) (void); 247cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "check_order_reloc_get_answer")); 248cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(fn != nullptr) << dlerror(); 249cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_EQ(42, fn()); 250cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 251cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_EQ(0, dlclose(handle)); 252cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov} 253cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 254cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy IvanovTEST(dlfcn, dlopen_check_order_reloc_siblings_with_preload) { 255cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // This test uses the same library as dlopen_check_order_reloc_siblings. 256cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // Unlike dlopen_check_order_reloc_siblings it preloads 257cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // libtest_check_order_reloc_siblings_1.so (first dependency) prior to 258cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // dlopen(libtest_check_order_reloc_siblings.so) 259cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 260cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov void* handle = dlopen("libtest_check_order_reloc_siblings.so", RTLD_NOW | RTLD_NOLOAD); 261cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(handle == nullptr); 262cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov handle = dlopen("libtest_check_order_reloc_siblings_1.so", RTLD_NOW | RTLD_NOLOAD); 263cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(handle == nullptr); 264cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 265cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov void* handle_for_1 = dlopen("libtest_check_order_reloc_siblings_1.so", RTLD_NOW | RTLD_LOCAL); 266cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(handle_for_1 != nullptr) << dlerror(); 267cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 268cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov handle = dlopen("libtest_check_order_reloc_siblings.so", RTLD_NOW | RTLD_LOCAL); 269cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 270cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 271cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_EQ(0, dlclose(handle_for_1)); 272cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 273cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov typedef int (*fn_t) (void); 274cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "check_order_reloc_get_answer")); 275cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(fn != nullptr) << dlerror(); 276cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_EQ(42, fn()); 277cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 278cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_EQ(0, dlclose(handle)); 279cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov} 280cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 281cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy IvanovTEST(dlfcn, dlopen_check_order_reloc_nephew) { 282cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // This is how this one works: 283cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // we lookup and call nephew_get_answer which is defined in '_2.so' 284cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // and in turn calls external get_answer_impl() defined in '_[a-f].so' 285cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // the correct _impl() is implemented by '_a.so'; 286cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // 287cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // Here is the picture: 288cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // 289cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // libtest_check_order_reloc_siblings.so 290cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | 291cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._1.so <- empty 292cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | | 293cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | +-> ..._a.so <- exports correct answer_impl() 294cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | | 295cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | +-> ..._b.so <- every other letter exporting incorrect one. 296cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | 297cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._2.so <- empty 298cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | | 299cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | +-> ..._c.so 300cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | | 301cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | +-> ..._d.so 302cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | 303cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._3.so <- nephew_get_answer() that calls get_answer_impl(); 304cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | 305cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._e.so 306cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | 307cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._f.so 308cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 309cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov void* handle = dlopen("libtest_check_order_reloc_siblings.so", RTLD_NOW | RTLD_NOLOAD); 310cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(handle == nullptr); 311cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov#ifdef __BIONIC__ 312cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // TODO: glibc returns nullptr on dlerror() here. Is it bug? 313cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_STREQ("dlopen failed: library \"libtest_check_order_reloc_siblings.so\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror()); 314cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov#endif 315cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 316cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov handle = dlopen("libtest_check_order_reloc_siblings.so", RTLD_NOW | RTLD_LOCAL); 317cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 318cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 319cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov typedef int (*fn_t) (void); 320cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "check_order_reloc_nephew_get_answer")); 321cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(fn != nullptr) << dlerror(); 322cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_EQ(42, fn()); 323cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 324cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_EQ(0, dlclose(handle)); 325cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov} 326cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 327cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanovextern "C" int check_order_reloc_root_get_answer_impl() { 328cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov return 42; 329cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov} 330cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 331cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy IvanovTEST(dlfcn, dlopen_check_order_reloc_main_executable) { 332cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // This is how this one works: 333cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // we lookup and call get_answer3 which is defined in 'root.so' 334cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // and in turn calls external root_get_answer_impl() defined in _2.so and 335cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // above the correct _impl() is one in the executable. 336cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // 337cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // libtest_check_order_reloc_root.so 338cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | 339cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._1.so <- empty 340cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | 341cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._2.so <- gives incorrect answer for answer_main_impl() 342cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // 343cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 344cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov void* handle = dlopen("libtest_check_order_reloc_root.so", RTLD_NOW | RTLD_NOLOAD); 345cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(handle == nullptr); 346cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov#ifdef __BIONIC__ 347cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // TODO: glibc returns nullptr on dlerror() here. Is it bug? 348cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_STREQ("dlopen failed: library \"libtest_check_order_reloc_root.so\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror()); 349cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov#endif 350cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 351cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov handle = dlopen("libtest_check_order_reloc_root.so", RTLD_NOW | RTLD_LOCAL); 352cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 353cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 354cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov typedef int (*fn_t) (void); 355cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "check_order_reloc_root_get_answer")); 356cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(fn != nullptr) << dlerror(); 357cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_EQ(42, fn()); 358cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 359cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_EQ(0, dlclose(handle)); 360cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov} 361cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 362e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy IvanovTEST(dlfcn, dlopen_check_rtld_local) { 363e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov void* sym = dlsym(RTLD_DEFAULT, "dlopen_testlib_simple_func"); 364e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov ASSERT_TRUE(sym == nullptr); 365e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov 366e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov // implicit RTLD_LOCAL 367e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov void* handle = dlopen("libtest_simple.so", RTLD_NOW); 368e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov sym = dlsym(RTLD_DEFAULT, "dlopen_testlib_simple_func"); 369e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov ASSERT_TRUE(sym == nullptr); 370e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov ASSERT_SUBSTR("undefined symbol: dlopen_testlib_simple_func", dlerror()); 371e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov sym = dlsym(handle, "dlopen_testlib_simple_func"); 372e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov ASSERT_TRUE(sym != nullptr); 373e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov ASSERT_TRUE(reinterpret_cast<bool (*)(void)>(sym)()); 374e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov dlclose(handle); 375e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov 376e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov // explicit RTLD_LOCAL 377e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov handle = dlopen("libtest_simple.so", RTLD_NOW | RTLD_LOCAL); 378e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov sym = dlsym(RTLD_DEFAULT, "dlopen_testlib_simple_func"); 379e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov ASSERT_TRUE(sym == nullptr); 380e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov ASSERT_SUBSTR("undefined symbol: dlopen_testlib_simple_func", dlerror()); 381e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov sym = dlsym(handle, "dlopen_testlib_simple_func"); 382e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov ASSERT_TRUE(sym != nullptr); 383e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov ASSERT_TRUE(reinterpret_cast<bool (*)(void)>(sym)()); 384e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov dlclose(handle); 385e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov} 386e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov 387e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy IvanovTEST(dlfcn, dlopen_check_rtld_global) { 388e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov void* sym = dlsym(RTLD_DEFAULT, "dlopen_testlib_simple_func"); 389e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov ASSERT_TRUE(sym == nullptr); 390e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov 391e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov void* handle = dlopen("libtest_simple.so", RTLD_NOW | RTLD_GLOBAL); 3921b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 393e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov sym = dlsym(RTLD_DEFAULT, "dlopen_testlib_simple_func"); 394e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov ASSERT_TRUE(sym != nullptr) << dlerror(); 395e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov ASSERT_TRUE(reinterpret_cast<bool (*)(void)>(sym)()); 396e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov dlclose(handle); 3971b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 3981b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov // RTLD_GLOBAL implies RTLD_NODELETE, let's check that 3991b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov void* sym_after_dlclose = dlsym(RTLD_DEFAULT, "dlopen_testlib_simple_func"); 4001b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_EQ(sym, sym_after_dlclose); 401e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov} 402e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov 40314669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov// libtest_with_dependency_loop.so -> libtest_with_dependency_loop_a.so -> 40414669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov// libtest_with_dependency_loop_b.so -> libtest_with_dependency_loop_c.so -> 40514669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov// libtest_with_dependency_loop_a.so 40614669a939d113214a4a20b9318fca0992d5453f0Dmitriy IvanovTEST(dlfcn, dlopen_check_loop) { 40714669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov void* handle = dlopen("libtest_with_dependency_loop.so", RTLD_NOW); 408eb27bbae8f0edc6b62ca2db73256c7fb53b9e9bfDmitriy Ivanov#if defined(__BIONIC__) 409a6ac54a215d6b64f5cc5a59b66c1dbfbb41ea9f5Dmitriy Ivanov ASSERT_TRUE(handle == nullptr); 41014669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov ASSERT_STREQ("dlopen failed: recursive link to \"libtest_with_dependency_loop_a.so\"", dlerror()); 411a6ac54a215d6b64f5cc5a59b66c1dbfbb41ea9f5Dmitriy Ivanov // This symbol should never be exposed 412a6ac54a215d6b64f5cc5a59b66c1dbfbb41ea9f5Dmitriy Ivanov void* f = dlsym(RTLD_DEFAULT, "dlopen_test_invalid_function"); 413a6ac54a215d6b64f5cc5a59b66c1dbfbb41ea9f5Dmitriy Ivanov ASSERT_TRUE(f == nullptr); 414a6ac54a215d6b64f5cc5a59b66c1dbfbb41ea9f5Dmitriy Ivanov ASSERT_SUBSTR("undefined symbol: dlopen_test_invalid_function", dlerror()); 415a6ac54a215d6b64f5cc5a59b66c1dbfbb41ea9f5Dmitriy Ivanov 416a6ac54a215d6b64f5cc5a59b66c1dbfbb41ea9f5Dmitriy Ivanov // dlopen second time to make sure that the library wasn't loaded even though dlopen returned null. 417a6ac54a215d6b64f5cc5a59b66c1dbfbb41ea9f5Dmitriy Ivanov // This may happen if during cleanup the root library or one of the depended libs were not removed 418a6ac54a215d6b64f5cc5a59b66c1dbfbb41ea9f5Dmitriy Ivanov // from soinfo list. 419a6ac54a215d6b64f5cc5a59b66c1dbfbb41ea9f5Dmitriy Ivanov handle = dlopen("libtest_with_dependency_loop.so", RTLD_NOW | RTLD_NOLOAD); 420a6ac54a215d6b64f5cc5a59b66c1dbfbb41ea9f5Dmitriy Ivanov ASSERT_TRUE(handle == nullptr); 421a6ac54a215d6b64f5cc5a59b66c1dbfbb41ea9f5Dmitriy Ivanov ASSERT_STREQ("dlopen failed: library \"libtest_with_dependency_loop.so\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror()); 422eb27bbae8f0edc6b62ca2db73256c7fb53b9e9bfDmitriy Ivanov#else // glibc allows recursive links 423eb27bbae8f0edc6b62ca2db73256c7fb53b9e9bfDmitriy Ivanov ASSERT_TRUE(handle != nullptr); 424eb27bbae8f0edc6b62ca2db73256c7fb53b9e9bfDmitriy Ivanov dlclose(handle); 425eb27bbae8f0edc6b62ca2db73256c7fb53b9e9bfDmitriy Ivanov#endif 42614669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov} 42714669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov 4281b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy IvanovTEST(dlfcn, dlopen_nodelete) { 4291b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov static bool is_unloaded = false; 4301b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 4311b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov void* handle = dlopen("libtest_nodelete_1.so", RTLD_NOW | RTLD_NODELETE); 4321b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 4331b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov void (*set_unload_flag_ptr)(bool*); 4341b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov set_unload_flag_ptr = reinterpret_cast<void (*)(bool*)>(dlsym(handle, "dlopen_nodelete_1_set_unload_flag_ptr")); 4351b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(set_unload_flag_ptr != nullptr) << dlerror(); 4361b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov set_unload_flag_ptr(&is_unloaded); 4371b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 4381b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_nodelete_1_taxicab_number")); 4391b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(taxicab_number != nullptr) << dlerror(); 4401b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_EQ(1729U, *taxicab_number); 4411b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov *taxicab_number = 2; 4421b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 4431b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov dlclose(handle); 4441b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(!is_unloaded); 4451b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 4461b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov uint32_t* taxicab_number_after_dlclose = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_nodelete_1_taxicab_number")); 4471b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_EQ(taxicab_number_after_dlclose, taxicab_number); 4481b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_EQ(2U, *taxicab_number_after_dlclose); 4491b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 4501b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 4511b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov handle = dlopen("libtest_nodelete_1.so", RTLD_NOW); 4521b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov uint32_t* taxicab_number2 = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_nodelete_1_taxicab_number")); 4531b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_EQ(taxicab_number2, taxicab_number); 4541b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 4551b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_EQ(2U, *taxicab_number2); 4561b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 4571b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov dlclose(handle); 4581b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(!is_unloaded); 4591b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov} 4601b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 4611b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy IvanovTEST(dlfcn, dlopen_nodelete_on_second_dlopen) { 4621b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov static bool is_unloaded = false; 4631b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 4641b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov void* handle = dlopen("libtest_nodelete_2.so", RTLD_NOW); 4651b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 4661b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov void (*set_unload_flag_ptr)(bool*); 4671b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov set_unload_flag_ptr = reinterpret_cast<void (*)(bool*)>(dlsym(handle, "dlopen_nodelete_2_set_unload_flag_ptr")); 4681b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(set_unload_flag_ptr != nullptr) << dlerror(); 4691b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov set_unload_flag_ptr(&is_unloaded); 4701b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 4711b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_nodelete_2_taxicab_number")); 4721b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(taxicab_number != nullptr) << dlerror(); 4731b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 4741b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_EQ(1729U, *taxicab_number); 4751b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov *taxicab_number = 2; 4761b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 4771b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov // This RTLD_NODELETE should be ignored 4781b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov void* handle1 = dlopen("libtest_nodelete_2.so", RTLD_NOW | RTLD_NODELETE); 4791b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(handle1 != nullptr) << dlerror(); 4801b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_EQ(handle, handle1); 4811b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 4821b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov dlclose(handle1); 4831b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov dlclose(handle); 4841b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 4851b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(is_unloaded); 4861b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov} 4871b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 4881b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy IvanovTEST(dlfcn, dlopen_nodelete_dt_flags_1) { 4891b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov static bool is_unloaded = false; 4901b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 4911b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov void* handle = dlopen("libtest_nodelete_dt_flags_1.so", RTLD_NOW); 4921b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 4931b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov void (*set_unload_flag_ptr)(bool*); 4941b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov set_unload_flag_ptr = reinterpret_cast<void (*)(bool*)>(dlsym(handle, "dlopen_nodelete_dt_flags_1_set_unload_flag_ptr")); 4951b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(set_unload_flag_ptr != nullptr) << dlerror(); 4961b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov set_unload_flag_ptr(&is_unloaded); 4971b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 4981b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov dlclose(handle); 4991b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(!is_unloaded); 5001b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov} 5011b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 502d225a5e65223b375a63548c4b780f04d8f3d7b60Dmitriy IvanovTEST(dlfcn, dlsym_df_1_global) { 5034e446b19d8710cd2004785db4a00f18f249fe73fDmitriy Ivanov#if !defined(__arm__) && !defined(__aarch64__) 504d225a5e65223b375a63548c4b780f04d8f3d7b60Dmitriy Ivanov void* handle = dlopen("libtest_dlsym_df_1_global.so", RTLD_NOW); 505d225a5e65223b375a63548c4b780f04d8f3d7b60Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 506d225a5e65223b375a63548c4b780f04d8f3d7b60Dmitriy Ivanov int (*get_answer)(); 507d225a5e65223b375a63548c4b780f04d8f3d7b60Dmitriy Ivanov get_answer = reinterpret_cast<int (*)()>(dlsym(handle, "dl_df_1_global_get_answer")); 508d225a5e65223b375a63548c4b780f04d8f3d7b60Dmitriy Ivanov ASSERT_TRUE(get_answer != nullptr) << dlerror(); 509d225a5e65223b375a63548c4b780f04d8f3d7b60Dmitriy Ivanov ASSERT_EQ(42, get_answer()); 510d225a5e65223b375a63548c4b780f04d8f3d7b60Dmitriy Ivanov ASSERT_EQ(0, dlclose(handle)); 511d225a5e65223b375a63548c4b780f04d8f3d7b60Dmitriy Ivanov#else 5124e446b19d8710cd2004785db4a00f18f249fe73fDmitriy Ivanov GTEST_LOG_(INFO) << "This test does nothing on arm/arm64 (to be reenabled once b/18137520 or b/18130452 are fixed).\n"; 513d225a5e65223b375a63548c4b780f04d8f3d7b60Dmitriy Ivanov#endif 514d225a5e65223b375a63548c4b780f04d8f3d7b60Dmitriy Ivanov} 515d225a5e65223b375a63548c4b780f04d8f3d7b60Dmitriy Ivanov 516e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott HughesTEST(dlfcn, dlopen_failure) { 5173b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes void* self = dlopen("/does/not/exist", RTLD_NOW); 5183b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_TRUE(self == NULL); 519063525c61d24776094d76971f33920e2a2079530Elliott Hughes#if defined(__BIONIC__) 5203b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_STREQ("dlopen failed: library \"/does/not/exist\" not found", dlerror()); 5213b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes#else 5223b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_STREQ("/does/not/exist: cannot open shared object file: No such file or directory", dlerror()); 5233b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes#endif 5243b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes} 5253b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 526ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughesstatic void* ConcurrentDlErrorFn(void*) { 5275419b9474753d25dff947c7740532f86d130c0beElliott Hughes dlopen("/child/thread", RTLD_NOW); 5285419b9474753d25dff947c7740532f86d130c0beElliott Hughes return reinterpret_cast<void*>(strdup(dlerror())); 5295419b9474753d25dff947c7740532f86d130c0beElliott Hughes} 5305419b9474753d25dff947c7740532f86d130c0beElliott Hughes 531e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott HughesTEST(dlfcn, dlerror_concurrent) { 5325419b9474753d25dff947c7740532f86d130c0beElliott Hughes dlopen("/main/thread", RTLD_NOW); 5335419b9474753d25dff947c7740532f86d130c0beElliott Hughes const char* main_thread_error = dlerror(); 5345419b9474753d25dff947c7740532f86d130c0beElliott Hughes ASSERT_SUBSTR("/main/thread", main_thread_error); 5355419b9474753d25dff947c7740532f86d130c0beElliott Hughes 5365419b9474753d25dff947c7740532f86d130c0beElliott Hughes pthread_t t; 5375419b9474753d25dff947c7740532f86d130c0beElliott Hughes ASSERT_EQ(0, pthread_create(&t, NULL, ConcurrentDlErrorFn, NULL)); 5385419b9474753d25dff947c7740532f86d130c0beElliott Hughes void* result; 5395419b9474753d25dff947c7740532f86d130c0beElliott Hughes ASSERT_EQ(0, pthread_join(t, &result)); 5405419b9474753d25dff947c7740532f86d130c0beElliott Hughes char* child_thread_error = static_cast<char*>(result); 5415419b9474753d25dff947c7740532f86d130c0beElliott Hughes ASSERT_SUBSTR("/child/thread", child_thread_error); 5425419b9474753d25dff947c7740532f86d130c0beElliott Hughes free(child_thread_error); 5435419b9474753d25dff947c7740532f86d130c0beElliott Hughes 5445419b9474753d25dff947c7740532f86d130c0beElliott Hughes ASSERT_SUBSTR("/main/thread", main_thread_error); 5455419b9474753d25dff947c7740532f86d130c0beElliott Hughes} 5465419b9474753d25dff947c7740532f86d130c0beElliott Hughes 547e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott HughesTEST(dlfcn, dlsym_failures) { 5483b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes dlerror(); // Clear any pending errors. 5493b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes void* self = dlopen(NULL, RTLD_NOW); 5503b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_TRUE(self != NULL); 5513b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_TRUE(dlerror() == NULL); 5523b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 5533b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes void* sym; 5543b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 55544adf93b8eddb3a7965a3e9abc189408a1f5a7eaDmitriy Ivanov#if defined(__BIONIC__) && !defined(__LP64__) 55644adf93b8eddb3a7965a3e9abc189408a1f5a7eaDmitriy Ivanov // RTLD_DEFAULT in lp32 bionic is not (void*)0 55744adf93b8eddb3a7965a3e9abc189408a1f5a7eaDmitriy Ivanov // so it can be distinguished from the NULL handle. 5583b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes sym = dlsym(NULL, "test"); 5593b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_TRUE(sym == NULL); 5603b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_SUBSTR("dlsym library handle is null", dlerror()); 5613b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes#endif 5623b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 5633b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes // NULL symbol name. 564063525c61d24776094d76971f33920e2a2079530Elliott Hughes#if defined(__BIONIC__) 5653b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes // glibc marks this parameter non-null and SEGVs if you cheat. 5663b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes sym = dlsym(self, NULL); 5673b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_TRUE(sym == NULL); 5683b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_SUBSTR("", dlerror()); 5693b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes#endif 5703b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 5713b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes // Symbol that doesn't exist. 5723b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes sym = dlsym(self, "ThisSymbolDoesNotExist"); 5733b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_TRUE(sym == NULL); 5743b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_SUBSTR("undefined symbol: ThisSymbolDoesNotExist", dlerror()); 5751a6961650c82168864afe040dbdc05977db701dfElliott Hughes 5761a6961650c82168864afe040dbdc05977db701dfElliott Hughes ASSERT_EQ(0, dlclose(self)); 5773b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes} 5783b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 579e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott HughesTEST(dlfcn, dladdr) { 5803b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes dlerror(); // Clear any pending errors. 5818e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes void* self = dlopen(NULL, RTLD_NOW); 5828e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_TRUE(self != NULL); 5833b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_TRUE(dlerror() == NULL); 5848e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 5858e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes void* sym = dlsym(self, "DlSymTestFunction"); 5868e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_TRUE(sym != NULL); 5878e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 5888e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // Deliberately ask dladdr for an address inside a symbol, rather than the symbol base address. 5898e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes void* addr = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(sym) + 2); 5908e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 5918e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes Dl_info info; 5928e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes int rc = dladdr(addr, &info); 5938e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_NE(rc, 0); // Zero on error, non-zero on success. 5948e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 5958e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // Get the name of this executable. 5968e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes char executable_path[PATH_MAX]; 5978e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes rc = readlink("/proc/self/exe", executable_path, sizeof(executable_path)); 5988e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_NE(rc, -1); 5998e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes executable_path[rc] = '\0'; 6008e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes std::string executable_name(basename(executable_path)); 6018e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 6028e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // The filename should be that of this executable. 6038e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // Note that we don't know whether or not we have the full path, so we want an "ends_with" test. 6048e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes std::string dli_fname(info.dli_fname); 6058e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes dli_fname = basename(&dli_fname[0]); 6068e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_EQ(dli_fname, executable_name); 6078e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 6088e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // The symbol name should be the symbol we looked up. 6098e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_STREQ(info.dli_sname, "DlSymTestFunction"); 6108e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 6118e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // The address should be the exact address of the symbol. 6128e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_EQ(info.dli_saddr, sym); 6138e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 6148e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // Look in /proc/pid/maps to find out what address we were loaded at. 6158e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // TODO: factor /proc/pid/maps parsing out into a class and reuse all over bionic. 6168e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes void* base_address = NULL; 6178e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes char line[BUFSIZ]; 61857b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes FILE* fp = fopen("/proc/self/maps", "r"); 6198e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_TRUE(fp != NULL); 6208e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes while (fgets(line, sizeof(line), fp) != NULL) { 6218e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes uintptr_t start = strtoul(line, 0, 16); 6228e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes line[strlen(line) - 1] = '\0'; // Chomp the '\n'. 6238e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes char* path = strchr(line, '/'); 624156da966214957c5616a0b83cc84686eedfc4e31Elliott Hughes if (path != NULL && strcmp(executable_path, path) == 0) { 6258e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes base_address = reinterpret_cast<void*>(start); 6268e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes break; 6278e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes } 6288e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes } 6298e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes fclose(fp); 6308e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 6318e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // The base address should be the address we were loaded at. 6328e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_EQ(info.dli_fbase, base_address); 6331a6961650c82168864afe040dbdc05977db701dfElliott Hughes 6341a6961650c82168864afe040dbdc05977db701dfElliott Hughes ASSERT_EQ(0, dlclose(self)); 6358e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes} 6368e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 637e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott HughesTEST(dlfcn, dladdr_invalid) { 6388e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes Dl_info info; 6398e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 6403b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes dlerror(); // Clear any pending errors. 6413b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 6428e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // No symbol corresponding to NULL. 6438e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_EQ(dladdr(NULL, &info), 0); // Zero on error, non-zero on success. 6443b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_TRUE(dlerror() == NULL); // dladdr(3) doesn't set dlerror(3). 6458e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 6468e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // No symbol corresponding to a stack address. 6478e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_EQ(dladdr(&info, &info), 0); // Zero on error, non-zero on success. 6483b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_TRUE(dlerror() == NULL); // dladdr(3) doesn't set dlerror(3). 6498e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes} 650124fae9eabd7a25d80dfa8c3b56bed0f0fba16f1Elliott Hughes 651a43e906221a3e9c70a66118a8692cd46f77e144eElliott Hughes// GNU-style ELF hash tables are incompatible with the MIPS ABI. 652a43e906221a3e9c70a66118a8692cd46f77e144eElliott Hughes// MIPS requires .dynsym to be sorted to match the GOT but GNU-style requires sorting by hash code. 653e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott HughesTEST(dlfcn, dlopen_library_with_only_gnu_hash) { 654ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov#if !defined(__mips__) 655124fae9eabd7a25d80dfa8c3b56bed0f0fba16f1Elliott Hughes dlerror(); // Clear any pending errors. 656ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov void* handle = dlopen("libgnu-hash-table-library.so", RTLD_NOW); 657ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 658ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov auto guard = make_scope_guard([&]() { 659ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov dlclose(handle); 660ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov }); 661ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov void* sym = dlsym(handle, "getRandomNumber"); 662ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov ASSERT_TRUE(sym != nullptr) << dlerror(); 663ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov int (*fn)(void); 664ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov fn = reinterpret_cast<int (*)(void)>(sym); 665ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov EXPECT_EQ(4, fn()); 666ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov 667ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov Dl_info dlinfo; 668ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov ASSERT_TRUE(0 != dladdr(reinterpret_cast<void*>(fn), &dlinfo)); 669ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov 670ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov ASSERT_TRUE(fn == dlinfo.dli_saddr); 671ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov ASSERT_STREQ("getRandomNumber", dlinfo.dli_sname); 672b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov ASSERT_SUBSTR("libgnu-hash-table-library.so", dlinfo.dli_fname); 673ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov#else 674ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov GTEST_LOG_(INFO) << "This test does nothing for mips/mips64; mips toolchain does not support '--hash-style=gnu'\n"; 675a43e906221a3e9c70a66118a8692cd46f77e144eElliott Hughes#endif 676ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov} 677e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes 678b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy IvanovTEST(dlfcn, dlopen_library_with_only_sysv_hash) { 679b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov void* handle = dlopen("libsysv-hash-table-library.so", RTLD_NOW); 680b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 681b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov auto guard = make_scope_guard([&]() { 682b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov dlclose(handle); 683b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov }); 684b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov void* sym = dlsym(handle, "getRandomNumber"); 685b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov ASSERT_TRUE(sym != nullptr) << dlerror(); 686b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov int (*fn)(void); 687b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov fn = reinterpret_cast<int (*)(void)>(sym); 688b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov EXPECT_EQ(4, fn()); 689b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov 690b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov Dl_info dlinfo; 691b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov ASSERT_TRUE(0 != dladdr(reinterpret_cast<void*>(fn), &dlinfo)); 692b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov 693b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov ASSERT_TRUE(fn == dlinfo.dli_saddr); 694b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov ASSERT_STREQ("getRandomNumber", dlinfo.dli_sname); 695b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov ASSERT_SUBSTR("libsysv-hash-table-library.so", dlinfo.dli_fname); 696b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov} 697b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov 698e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott HughesTEST(dlfcn, dlopen_bad_flags) { 699e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes dlerror(); // Clear any pending errors. 700e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes void* handle; 701e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes 702063525c61d24776094d76971f33920e2a2079530Elliott Hughes#if defined(__GLIBC__) 703e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes // glibc was smart enough not to define RTLD_NOW as 0, so it can detect missing flags. 704e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes handle = dlopen(NULL, 0); 705e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes ASSERT_TRUE(handle == NULL); 706e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes ASSERT_SUBSTR("invalid", dlerror()); 707e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes#endif 708e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes 709e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes handle = dlopen(NULL, 0xffffffff); 710e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes ASSERT_TRUE(handle == NULL); 711e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes ASSERT_SUBSTR("invalid", dlerror()); 712e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes 713e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes // glibc actually allows you to choose both RTLD_NOW and RTLD_LAZY at the same time, and so do we. 714e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes handle = dlopen(NULL, RTLD_NOW|RTLD_LAZY); 715e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes ASSERT_TRUE(handle != NULL); 716e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes ASSERT_SUBSTR(NULL, dlerror()); 717e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes} 718ebd506c69e12b6dcaf5be94cc8ed1b53af299f9fSergey Melnikov 719ebd506c69e12b6dcaf5be94cc8ed1b53af299f9fSergey MelnikovTEST(dlfcn, rtld_default_unknown_symbol) { 7202ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes void* addr = dlsym(RTLD_DEFAULT, "ANY_UNKNOWN_SYMBOL_NAME"); 721ebd506c69e12b6dcaf5be94cc8ed1b53af299f9fSergey Melnikov ASSERT_TRUE(addr == NULL); 722ebd506c69e12b6dcaf5be94cc8ed1b53af299f9fSergey Melnikov} 723ebd506c69e12b6dcaf5be94cc8ed1b53af299f9fSergey Melnikov 724ebd506c69e12b6dcaf5be94cc8ed1b53af299f9fSergey MelnikovTEST(dlfcn, rtld_default_known_symbol) { 7252ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes void* addr = dlsym(RTLD_DEFAULT, "fopen"); 7262ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes ASSERT_TRUE(addr != NULL); 7272ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes} 7282ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes 7292ed710976cb0ace31aab565c95a42d4e75623894Elliott HughesTEST(dlfcn, rtld_next_unknown_symbol) { 7302ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes void* addr = dlsym(RTLD_NEXT, "ANY_UNKNOWN_SYMBOL_NAME"); 7312ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes ASSERT_TRUE(addr == NULL); 7322ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes} 7332ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes 7342ed710976cb0ace31aab565c95a42d4e75623894Elliott HughesTEST(dlfcn, rtld_next_known_symbol) { 7352ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes void* addr = dlsym(RTLD_NEXT, "fopen"); 736ebd506c69e12b6dcaf5be94cc8ed1b53af299f9fSergey Melnikov ASSERT_TRUE(addr != NULL); 737ebd506c69e12b6dcaf5be94cc8ed1b53af299f9fSergey Melnikov} 7387db180919c335287b201e859faa8ee0dbe281cdeDmitriy Ivanov 739ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy IvanovTEST(dlfcn, dlsym_weak_func) { 740ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov dlerror(); 741ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov void* handle = dlopen("libtest_dlsym_weak_func.so",RTLD_NOW); 742ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov ASSERT_TRUE(handle != NULL); 743ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov 744ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov int (*weak_func)(); 745ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov weak_func = reinterpret_cast<int (*)()>(dlsym(handle, "weak_func")); 746ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov ASSERT_TRUE(weak_func != NULL) << "dlerror: " << dlerror(); 747ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov EXPECT_EQ(42, weak_func()); 748ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov dlclose(handle); 749ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov} 750ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov 7517db180919c335287b201e859faa8ee0dbe281cdeDmitriy IvanovTEST(dlfcn, dlopen_symlink) { 7527db180919c335287b201e859faa8ee0dbe281cdeDmitriy Ivanov void* handle1 = dlopen("libdlext_test.so", RTLD_NOW); 7537db180919c335287b201e859faa8ee0dbe281cdeDmitriy Ivanov void* handle2 = dlopen("libdlext_test_v2.so", RTLD_NOW); 7547db180919c335287b201e859faa8ee0dbe281cdeDmitriy Ivanov ASSERT_TRUE(handle1 != NULL); 7557db180919c335287b201e859faa8ee0dbe281cdeDmitriy Ivanov ASSERT_TRUE(handle2 != NULL); 7567db180919c335287b201e859faa8ee0dbe281cdeDmitriy Ivanov ASSERT_EQ(handle1, handle2); 757319356e39cc91b4eb94b1974756f1cfc0a137351Dmitriy Ivanov dlclose(handle1); 758319356e39cc91b4eb94b1974756f1cfc0a137351Dmitriy Ivanov dlclose(handle2); 7597db180919c335287b201e859faa8ee0dbe281cdeDmitriy Ivanov} 760