dlfcn_test.cpp revision 14669a939d113214a4a20b9318fca0992d5453f0
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 92c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith// ifuncs are only supported on intel for now 93c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith#if 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); 1279598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov ASSERT_TRUE(handle != NULL) << dlerror(); 1289598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov fn_ptr is_ctor_called = reinterpret_cast<fn_ptr>(dlsym(handle, "is_ctor_called")); 1299598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov ASSERT_TRUE(is_ctor_called != NULL) << dlerror(); 1309598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov ASSERT_STREQ("true", is_ctor_called()); 131c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith dlclose(handle); 132c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith} 133c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith#endif 134c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith 135b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy IvanovTEST(dlfcn, dlopen_check_relocation_dt_needed_order) { 136b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // This is the structure of the test library and 137b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // its dt_needed libraries 138b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // libtest_relo_check_dt_needed_order.so 139b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // | 140b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // +-> libtest_relo_check_dt_needed_order_1.so 141b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // | 142b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // +-> libtest_relo_check_dt_needed_order_2.so 143b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // 144b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // The root library references relo_test_get_answer_lib - which is defined 145b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // in both dt_needed libraries, the correct relocation should 146b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // use the function defined in libtest_relo_check_dt_needed_order_1.so 147b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov void* handle = nullptr; 148b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov auto guard = create_scope_guard([&]() { 149b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov dlclose(handle); 150b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov }); 151b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov 152b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov handle = dlopen("libtest_relo_check_dt_needed_order.so", RTLD_NOW); 153b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 154b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov 155b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov typedef int (*fn_t) (void); 156b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "relo_test_get_answer")); 157b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov ASSERT_TRUE(fn != nullptr) << dlerror(); 158b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov ASSERT_EQ(1, fn()); 159b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov} 160b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov 16114669a939d113214a4a20b9318fca0992d5453f0Dmitriy IvanovTEST(dlfcn, dlopen_check_order) { 16214669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // Here is how the test library and its dt_needed 16314669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // libraries are arranged 16414669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // 16514669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // libtest_check_order.so 16614669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // | 16714669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // +-> libtest_check_order_1_left.so 16814669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // | | 16914669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // | +-> libtest_check_order_a.so 17014669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // | | 17114669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // | +-> libtest_check_order_b.so 17214669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // | 17314669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // +-> libtest_check_order_2_right.so 17414669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // | | 17514669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // | +-> libtest_check_order_d.so 17614669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // | | 17714669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // | +-> libtest_check_order_b.so 17814669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // | 17914669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // +-> libtest_check_order_3_c.so 18014669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // 18114669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // load order should be (1, 2, 3, a, b, d) 18214669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // 18314669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // get_answer() is defined in (2, 3, a, b, c) 18414669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // get_answer2() is defined in (b, d) 18514669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov void* sym = dlsym(RTLD_DEFAULT, "dlopen_test_get_answer"); 18614669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov ASSERT_TRUE(sym == nullptr); 18714669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov void* handle = dlopen("libtest_check_order.so", RTLD_NOW); 18814669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov ASSERT_TRUE(handle != nullptr); 18914669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov typedef int (*fn_t) (void); 19014669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov fn_t fn, fn2; 19114669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov fn = reinterpret_cast<fn_t>(dlsym(RTLD_DEFAULT, "dlopen_test_get_answer")); 19214669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov ASSERT_TRUE(fn != NULL); 19314669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov fn2 = reinterpret_cast<fn_t>(dlsym(RTLD_DEFAULT, "dlopen_test_get_answer2")); 19414669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov ASSERT_TRUE(fn2 != NULL); 19514669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov 19614669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov ASSERT_EQ(42, fn()); 19714669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov ASSERT_EQ(43, fn2()); 19814669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov dlclose(handle); 19914669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov} 20014669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov 20114669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov// libtest_with_dependency_loop.so -> libtest_with_dependency_loop_a.so -> 20214669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov// libtest_with_dependency_loop_b.so -> libtest_with_dependency_loop_c.so -> 20314669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov// libtest_with_dependency_loop_a.so 20414669a939d113214a4a20b9318fca0992d5453f0Dmitriy IvanovTEST(dlfcn, dlopen_check_loop) { 20514669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov void* handle = dlopen("libtest_with_dependency_loop.so", RTLD_NOW); 20614669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov ASSERT_TRUE(handle == NULL); 20714669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov ASSERT_STREQ("dlopen failed: recursive link to \"libtest_with_dependency_loop_a.so\"", dlerror()); 20814669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov} 20914669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov 210e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott HughesTEST(dlfcn, dlopen_failure) { 2113b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes void* self = dlopen("/does/not/exist", RTLD_NOW); 2123b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_TRUE(self == NULL); 213063525c61d24776094d76971f33920e2a2079530Elliott Hughes#if defined(__BIONIC__) 2143b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_STREQ("dlopen failed: library \"/does/not/exist\" not found", dlerror()); 2153b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes#else 2163b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_STREQ("/does/not/exist: cannot open shared object file: No such file or directory", dlerror()); 2173b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes#endif 2183b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes} 2193b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 220ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughesstatic void* ConcurrentDlErrorFn(void*) { 2215419b9474753d25dff947c7740532f86d130c0beElliott Hughes dlopen("/child/thread", RTLD_NOW); 2225419b9474753d25dff947c7740532f86d130c0beElliott Hughes return reinterpret_cast<void*>(strdup(dlerror())); 2235419b9474753d25dff947c7740532f86d130c0beElliott Hughes} 2245419b9474753d25dff947c7740532f86d130c0beElliott Hughes 225e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott HughesTEST(dlfcn, dlerror_concurrent) { 2265419b9474753d25dff947c7740532f86d130c0beElliott Hughes dlopen("/main/thread", RTLD_NOW); 2275419b9474753d25dff947c7740532f86d130c0beElliott Hughes const char* main_thread_error = dlerror(); 2285419b9474753d25dff947c7740532f86d130c0beElliott Hughes ASSERT_SUBSTR("/main/thread", main_thread_error); 2295419b9474753d25dff947c7740532f86d130c0beElliott Hughes 2305419b9474753d25dff947c7740532f86d130c0beElliott Hughes pthread_t t; 2315419b9474753d25dff947c7740532f86d130c0beElliott Hughes ASSERT_EQ(0, pthread_create(&t, NULL, ConcurrentDlErrorFn, NULL)); 2325419b9474753d25dff947c7740532f86d130c0beElliott Hughes void* result; 2335419b9474753d25dff947c7740532f86d130c0beElliott Hughes ASSERT_EQ(0, pthread_join(t, &result)); 2345419b9474753d25dff947c7740532f86d130c0beElliott Hughes char* child_thread_error = static_cast<char*>(result); 2355419b9474753d25dff947c7740532f86d130c0beElliott Hughes ASSERT_SUBSTR("/child/thread", child_thread_error); 2365419b9474753d25dff947c7740532f86d130c0beElliott Hughes free(child_thread_error); 2375419b9474753d25dff947c7740532f86d130c0beElliott Hughes 2385419b9474753d25dff947c7740532f86d130c0beElliott Hughes ASSERT_SUBSTR("/main/thread", main_thread_error); 2395419b9474753d25dff947c7740532f86d130c0beElliott Hughes} 2405419b9474753d25dff947c7740532f86d130c0beElliott Hughes 241e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott HughesTEST(dlfcn, dlsym_failures) { 2423b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes dlerror(); // Clear any pending errors. 2433b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes void* self = dlopen(NULL, RTLD_NOW); 2443b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_TRUE(self != NULL); 2453b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_TRUE(dlerror() == NULL); 2463b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 2473b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes void* sym; 2483b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 24944adf93b8eddb3a7965a3e9abc189408a1f5a7eaDmitriy Ivanov#if defined(__BIONIC__) && !defined(__LP64__) 25044adf93b8eddb3a7965a3e9abc189408a1f5a7eaDmitriy Ivanov // RTLD_DEFAULT in lp32 bionic is not (void*)0 25144adf93b8eddb3a7965a3e9abc189408a1f5a7eaDmitriy Ivanov // so it can be distinguished from the NULL handle. 2523b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes sym = dlsym(NULL, "test"); 2533b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_TRUE(sym == NULL); 2543b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_SUBSTR("dlsym library handle is null", dlerror()); 2553b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes#endif 2563b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 2573b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes // NULL symbol name. 258063525c61d24776094d76971f33920e2a2079530Elliott Hughes#if defined(__BIONIC__) 2593b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes // glibc marks this parameter non-null and SEGVs if you cheat. 2603b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes sym = dlsym(self, NULL); 2613b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_TRUE(sym == NULL); 2623b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_SUBSTR("", dlerror()); 2633b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes#endif 2643b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 2653b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes // Symbol that doesn't exist. 2663b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes sym = dlsym(self, "ThisSymbolDoesNotExist"); 2673b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_TRUE(sym == NULL); 2683b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_SUBSTR("undefined symbol: ThisSymbolDoesNotExist", dlerror()); 2691a6961650c82168864afe040dbdc05977db701dfElliott Hughes 2701a6961650c82168864afe040dbdc05977db701dfElliott Hughes ASSERT_EQ(0, dlclose(self)); 2713b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes} 2723b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 273e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott HughesTEST(dlfcn, dladdr) { 2743b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes dlerror(); // Clear any pending errors. 2758e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes void* self = dlopen(NULL, RTLD_NOW); 2768e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_TRUE(self != NULL); 2773b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_TRUE(dlerror() == NULL); 2788e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 2798e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes void* sym = dlsym(self, "DlSymTestFunction"); 2808e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_TRUE(sym != NULL); 2818e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 2828e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // Deliberately ask dladdr for an address inside a symbol, rather than the symbol base address. 2838e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes void* addr = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(sym) + 2); 2848e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 2858e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes Dl_info info; 2868e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes int rc = dladdr(addr, &info); 2878e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_NE(rc, 0); // Zero on error, non-zero on success. 2888e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 2898e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // Get the name of this executable. 2908e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes char executable_path[PATH_MAX]; 2918e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes rc = readlink("/proc/self/exe", executable_path, sizeof(executable_path)); 2928e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_NE(rc, -1); 2938e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes executable_path[rc] = '\0'; 2948e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes std::string executable_name(basename(executable_path)); 2958e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 2968e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // The filename should be that of this executable. 2978e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // Note that we don't know whether or not we have the full path, so we want an "ends_with" test. 2988e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes std::string dli_fname(info.dli_fname); 2998e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes dli_fname = basename(&dli_fname[0]); 3008e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_EQ(dli_fname, executable_name); 3018e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 3028e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // The symbol name should be the symbol we looked up. 3038e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_STREQ(info.dli_sname, "DlSymTestFunction"); 3048e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 3058e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // The address should be the exact address of the symbol. 3068e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_EQ(info.dli_saddr, sym); 3078e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 3088e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // Look in /proc/pid/maps to find out what address we were loaded at. 3098e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // TODO: factor /proc/pid/maps parsing out into a class and reuse all over bionic. 3108e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes void* base_address = NULL; 3118e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes char line[BUFSIZ]; 31257b7a6110e7e8b446fc23cce4765ff625ee0a105Elliott Hughes FILE* fp = fopen("/proc/self/maps", "r"); 3138e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_TRUE(fp != NULL); 3148e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes while (fgets(line, sizeof(line), fp) != NULL) { 3158e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes uintptr_t start = strtoul(line, 0, 16); 3168e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes line[strlen(line) - 1] = '\0'; // Chomp the '\n'. 3178e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes char* path = strchr(line, '/'); 318156da966214957c5616a0b83cc84686eedfc4e31Elliott Hughes if (path != NULL && strcmp(executable_path, path) == 0) { 3198e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes base_address = reinterpret_cast<void*>(start); 3208e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes break; 3218e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes } 3228e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes } 3238e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes fclose(fp); 3248e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 3258e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // The base address should be the address we were loaded at. 3268e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_EQ(info.dli_fbase, base_address); 3271a6961650c82168864afe040dbdc05977db701dfElliott Hughes 3281a6961650c82168864afe040dbdc05977db701dfElliott Hughes ASSERT_EQ(0, dlclose(self)); 3298e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes} 3308e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 331e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott HughesTEST(dlfcn, dladdr_invalid) { 3328e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes Dl_info info; 3338e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 3343b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes dlerror(); // Clear any pending errors. 3353b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 3368e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // No symbol corresponding to NULL. 3378e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_EQ(dladdr(NULL, &info), 0); // Zero on error, non-zero on success. 3383b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_TRUE(dlerror() == NULL); // dladdr(3) doesn't set dlerror(3). 3398e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 3408e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // No symbol corresponding to a stack address. 3418e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_EQ(dladdr(&info, &info), 0); // Zero on error, non-zero on success. 3423b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_TRUE(dlerror() == NULL); // dladdr(3) doesn't set dlerror(3). 3438e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes} 344124fae9eabd7a25d80dfa8c3b56bed0f0fba16f1Elliott Hughes 345124fae9eabd7a25d80dfa8c3b56bed0f0fba16f1Elliott Hughes// Our dynamic linker doesn't support GNU hash tables. 346a43e906221a3e9c70a66118a8692cd46f77e144eElliott Hughes#if defined(__BIONIC__) 347a43e906221a3e9c70a66118a8692cd46f77e144eElliott Hughes// GNU-style ELF hash tables are incompatible with the MIPS ABI. 348a43e906221a3e9c70a66118a8692cd46f77e144eElliott Hughes// MIPS requires .dynsym to be sorted to match the GOT but GNU-style requires sorting by hash code. 349a43e906221a3e9c70a66118a8692cd46f77e144eElliott Hughes#if !defined(__mips__) 350e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott HughesTEST(dlfcn, dlopen_library_with_only_gnu_hash) { 351124fae9eabd7a25d80dfa8c3b56bed0f0fba16f1Elliott Hughes dlerror(); // Clear any pending errors. 3526e33b0296d23c75bdefa53f0bf0b08c0d877a652Elliott Hughes void* handle = dlopen("no-elf-hash-table-library.so", RTLD_NOW); 353124fae9eabd7a25d80dfa8c3b56bed0f0fba16f1Elliott Hughes ASSERT_TRUE(handle == NULL); 3546e33b0296d23c75bdefa53f0bf0b08c0d877a652Elliott Hughes ASSERT_STREQ("dlopen failed: empty/missing DT_HASH in \"no-elf-hash-table-library.so\" (built with --hash-style=gnu?)", dlerror()); 355124fae9eabd7a25d80dfa8c3b56bed0f0fba16f1Elliott Hughes} 356124fae9eabd7a25d80dfa8c3b56bed0f0fba16f1Elliott Hughes#endif 357a43e906221a3e9c70a66118a8692cd46f77e144eElliott Hughes#endif 358e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes 359e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott HughesTEST(dlfcn, dlopen_bad_flags) { 360e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes dlerror(); // Clear any pending errors. 361e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes void* handle; 362e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes 363063525c61d24776094d76971f33920e2a2079530Elliott Hughes#if defined(__GLIBC__) 364e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes // glibc was smart enough not to define RTLD_NOW as 0, so it can detect missing flags. 365e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes handle = dlopen(NULL, 0); 366e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes ASSERT_TRUE(handle == NULL); 367e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes ASSERT_SUBSTR("invalid", dlerror()); 368e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes#endif 369e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes 370e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes handle = dlopen(NULL, 0xffffffff); 371e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes ASSERT_TRUE(handle == NULL); 372e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes ASSERT_SUBSTR("invalid", dlerror()); 373e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes 374e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes // glibc actually allows you to choose both RTLD_NOW and RTLD_LAZY at the same time, and so do we. 375e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes handle = dlopen(NULL, RTLD_NOW|RTLD_LAZY); 376e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes ASSERT_TRUE(handle != NULL); 377e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes ASSERT_SUBSTR(NULL, dlerror()); 378e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes} 379ebd506c69e12b6dcaf5be94cc8ed1b53af299f9fSergey Melnikov 380ebd506c69e12b6dcaf5be94cc8ed1b53af299f9fSergey MelnikovTEST(dlfcn, rtld_default_unknown_symbol) { 3812ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes void* addr = dlsym(RTLD_DEFAULT, "ANY_UNKNOWN_SYMBOL_NAME"); 382ebd506c69e12b6dcaf5be94cc8ed1b53af299f9fSergey Melnikov ASSERT_TRUE(addr == NULL); 383ebd506c69e12b6dcaf5be94cc8ed1b53af299f9fSergey Melnikov} 384ebd506c69e12b6dcaf5be94cc8ed1b53af299f9fSergey Melnikov 385ebd506c69e12b6dcaf5be94cc8ed1b53af299f9fSergey MelnikovTEST(dlfcn, rtld_default_known_symbol) { 3862ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes void* addr = dlsym(RTLD_DEFAULT, "fopen"); 3872ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes ASSERT_TRUE(addr != NULL); 3882ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes} 3892ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes 3902ed710976cb0ace31aab565c95a42d4e75623894Elliott HughesTEST(dlfcn, rtld_next_unknown_symbol) { 3912ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes void* addr = dlsym(RTLD_NEXT, "ANY_UNKNOWN_SYMBOL_NAME"); 3922ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes ASSERT_TRUE(addr == NULL); 3932ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes} 3942ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes 3952ed710976cb0ace31aab565c95a42d4e75623894Elliott HughesTEST(dlfcn, rtld_next_known_symbol) { 3962ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes void* addr = dlsym(RTLD_NEXT, "fopen"); 397ebd506c69e12b6dcaf5be94cc8ed1b53af299f9fSergey Melnikov ASSERT_TRUE(addr != NULL); 398ebd506c69e12b6dcaf5be94cc8ed1b53af299f9fSergey Melnikov} 3997db180919c335287b201e859faa8ee0dbe281cdeDmitriy Ivanov 400ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy IvanovTEST(dlfcn, dlsym_weak_func) { 401ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov dlerror(); 402ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov void* handle = dlopen("libtest_dlsym_weak_func.so",RTLD_NOW); 403ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov ASSERT_TRUE(handle != NULL); 404ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov 405ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov int (*weak_func)(); 406ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov weak_func = reinterpret_cast<int (*)()>(dlsym(handle, "weak_func")); 407ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov ASSERT_TRUE(weak_func != NULL) << "dlerror: " << dlerror(); 408ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov EXPECT_EQ(42, weak_func()); 409ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov dlclose(handle); 410ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov} 411ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov 4127db180919c335287b201e859faa8ee0dbe281cdeDmitriy IvanovTEST(dlfcn, dlopen_symlink) { 4137db180919c335287b201e859faa8ee0dbe281cdeDmitriy Ivanov void* handle1 = dlopen("libdlext_test.so", RTLD_NOW); 4147db180919c335287b201e859faa8ee0dbe281cdeDmitriy Ivanov void* handle2 = dlopen("libdlext_test_v2.so", RTLD_NOW); 4157db180919c335287b201e859faa8ee0dbe281cdeDmitriy Ivanov ASSERT_TRUE(handle1 != NULL); 4167db180919c335287b201e859faa8ee0dbe281cdeDmitriy Ivanov ASSERT_TRUE(handle2 != NULL); 4177db180919c335287b201e859faa8ee0dbe281cdeDmitriy Ivanov ASSERT_EQ(handle1, handle2); 418319356e39cc91b4eb94b1974756f1cfc0a137351Dmitriy Ivanov dlclose(handle1); 419319356e39cc91b4eb94b1974756f1cfc0a137351Dmitriy Ivanov dlclose(handle2); 4207db180919c335287b201e859faa8ee0dbe281cdeDmitriy Ivanov} 421