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 <limits.h> 218e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes#include <stdio.h> 228e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes#include <stdint.h> 23708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov#include <string.h> 248e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 25b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov#include "private/ScopeGuard.h" 26b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov 278e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes#include <string> 28c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov#include <thread> 29acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao 30927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov#include "gtest_globals.h" 31708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov#include "dlfcn_symlink_support.h" 32aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov#include "utils.h" 33aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov 34ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov#if defined(__BIONIC__) && (defined(__arm__) || defined(__i386__)) 35ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov#pragma clang diagnostic push 36ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov#pragma clang diagnostic ignored "-Wunused-parameter" 37ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov 38ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov#include <llvm/ADT/StringRef.h> 39ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov#include <llvm/Object/Binary.h> 40ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov#include <llvm/Object/ELFObjectFile.h> 41ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov#include <llvm/Object/ObjectFile.h> 42ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov 43ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov#pragma clang diagnostic pop 44ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov#endif // defined(__ANDROID__) && (defined(__arm__) || defined(__i386__)) 45ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov 463b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes#define ASSERT_SUBSTR(needle, haystack) \ 473b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_PRED_FORMAT2(::testing::IsSubstring, needle, haystack) 483b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 49aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov 501728b2396591853345507a063ed6075dfd251706Elliott Hughesstatic bool g_called = false; 51acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhaoextern "C" void DlSymTestFunction() { 521728b2396591853345507a063ed6075dfd251706Elliott Hughes g_called = true; 53acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao} 54acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao 55f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanovstatic int g_ctor_function_called = 0; 56554374693408cd7c74d0cae596fca7349661edeaDimitry Ivanovstatic int g_ctor_argc = 0; 57554374693408cd7c74d0cae596fca7349661edeaDimitry Ivanovstatic char** g_ctor_argv = reinterpret_cast<char**>(0xDEADBEEF); 58554374693408cd7c74d0cae596fca7349661edeaDimitry Ivanovstatic char** g_ctor_envp = g_ctor_envp; 59f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanov 60554374693408cd7c74d0cae596fca7349661edeaDimitry Ivanovextern "C" void ctor_function(int argc, char** argv, char** envp) __attribute__ ((constructor)); 61f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanov 62554374693408cd7c74d0cae596fca7349661edeaDimitry Ivanovextern "C" void ctor_function(int argc, char** argv, char** envp) { 63f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanov g_ctor_function_called = 17; 64554374693408cd7c74d0cae596fca7349661edeaDimitry Ivanov g_ctor_argc = argc; 65554374693408cd7c74d0cae596fca7349661edeaDimitry Ivanov g_ctor_argv = argv; 66554374693408cd7c74d0cae596fca7349661edeaDimitry Ivanov g_ctor_envp = envp; 67f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanov} 68f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanov 69f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy IvanovTEST(dlfcn, ctor_function_call) { 70f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanov ASSERT_EQ(17, g_ctor_function_called); 71554374693408cd7c74d0cae596fca7349661edeaDimitry Ivanov ASSERT_TRUE(g_ctor_argc = get_argc()); 72554374693408cd7c74d0cae596fca7349661edeaDimitry Ivanov ASSERT_TRUE(g_ctor_argv = get_argv()); 73554374693408cd7c74d0cae596fca7349661edeaDimitry Ivanov ASSERT_TRUE(g_ctor_envp = get_envp()); 74f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanov} 75f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanov 7676ac1acdacc045cf1e56504e011dca68137dcd61Dmitriy IvanovTEST(dlfcn, dlsym_in_executable) { 773b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes dlerror(); // Clear any pending errors. 78aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov void* self = dlopen(nullptr, RTLD_NOW); 79aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(self != nullptr); 80aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(dlerror() == nullptr); 81acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao 82acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao void* sym = dlsym(self, "DlSymTestFunction"); 83aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(sym != nullptr); 84acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao 85acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao void (*function)() = reinterpret_cast<void(*)()>(sym); 86acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao 871728b2396591853345507a063ed6075dfd251706Elliott Hughes g_called = false; 88acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao function(); 891728b2396591853345507a063ed6075dfd251706Elliott Hughes ASSERT_TRUE(g_called); 901a6961650c82168864afe040dbdc05977db701dfElliott Hughes 911a6961650c82168864afe040dbdc05977db701dfElliott Hughes ASSERT_EQ(0, dlclose(self)); 92acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao} 938e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 9476ac1acdacc045cf1e56504e011dca68137dcd61Dmitriy IvanovTEST(dlfcn, dlsym_from_sofile) { 9576ac1acdacc045cf1e56504e011dca68137dcd61Dmitriy Ivanov void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_LAZY | RTLD_LOCAL); 9676ac1acdacc045cf1e56504e011dca68137dcd61Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 9776ac1acdacc045cf1e56504e011dca68137dcd61Dmitriy Ivanov 98697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov // check that we can't find '_test_dlsym_symbol' via dlsym(RTLD_DEFAULT) 9976ac1acdacc045cf1e56504e011dca68137dcd61Dmitriy Ivanov void* symbol = dlsym(RTLD_DEFAULT, "test_dlsym_symbol"); 10076ac1acdacc045cf1e56504e011dca68137dcd61Dmitriy Ivanov ASSERT_TRUE(symbol == nullptr); 10176ac1acdacc045cf1e56504e011dca68137dcd61Dmitriy Ivanov ASSERT_SUBSTR("undefined symbol: test_dlsym_symbol", dlerror()); 10276ac1acdacc045cf1e56504e011dca68137dcd61Dmitriy Ivanov 10376ac1acdacc045cf1e56504e011dca68137dcd61Dmitriy Ivanov typedef int* (*fn_t)(); 104697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov fn_t lookup_dlsym_symbol_using_RTLD_DEFAULT = 105697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol_using_RTLD_DEFAULT")); 106697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_TRUE(lookup_dlsym_symbol_using_RTLD_DEFAULT != nullptr) << dlerror(); 10776ac1acdacc045cf1e56504e011dca68137dcd61Dmitriy Ivanov 108697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov int* ptr = lookup_dlsym_symbol_using_RTLD_DEFAULT(); 109697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_TRUE(ptr != nullptr) << dlerror(); 110697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_EQ(42, *ptr); 111697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov 112697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov fn_t lookup_dlsym_symbol2_using_RTLD_DEFAULT = 113697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol2_using_RTLD_DEFAULT")); 114697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_TRUE(lookup_dlsym_symbol2_using_RTLD_DEFAULT != nullptr) << dlerror(); 115697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov 116697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ptr = lookup_dlsym_symbol2_using_RTLD_DEFAULT(); 117697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_TRUE(ptr != nullptr) << dlerror(); 118697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_EQ(44, *ptr); 119697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov 120697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov fn_t lookup_dlsym_symbol_using_RTLD_NEXT = 121697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol_using_RTLD_NEXT")); 122697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_TRUE(lookup_dlsym_symbol_using_RTLD_NEXT != nullptr) << dlerror(); 123697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov 124697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ptr = lookup_dlsym_symbol_using_RTLD_NEXT(); 125697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_TRUE(ptr != nullptr) << dlerror(); 126697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_EQ(43, *ptr); 127697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov 128697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov dlclose(handle); 129697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov} 130697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov 131697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy IvanovTEST(dlfcn, dlsym_from_sofile_with_preload) { 132697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov void* preload = dlopen("libtest_dlsym_from_this_grandchild.so", RTLD_NOW | RTLD_LOCAL); 133697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_TRUE(preload != nullptr) << dlerror(); 134697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov 135697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_NOW | RTLD_LOCAL); 136697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 137697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov 138697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov // check that we can't find '_test_dlsym_symbol' via dlsym(RTLD_DEFAULT) 139697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov void* symbol = dlsym(RTLD_DEFAULT, "test_dlsym_symbol"); 140697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_TRUE(symbol == nullptr); 141697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_SUBSTR("undefined symbol: test_dlsym_symbol", dlerror()); 142697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov 143697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov typedef int* (*fn_t)(); 144697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov fn_t lookup_dlsym_symbol_using_RTLD_DEFAULT = 145697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol_using_RTLD_DEFAULT")); 146697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_TRUE(lookup_dlsym_symbol_using_RTLD_DEFAULT != nullptr) << dlerror(); 14776ac1acdacc045cf1e56504e011dca68137dcd61Dmitriy Ivanov 148697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov int* ptr = lookup_dlsym_symbol_using_RTLD_DEFAULT(); 14976ac1acdacc045cf1e56504e011dca68137dcd61Dmitriy Ivanov ASSERT_TRUE(ptr != nullptr) << dlerror(); 15076ac1acdacc045cf1e56504e011dca68137dcd61Dmitriy Ivanov ASSERT_EQ(42, *ptr); 15176ac1acdacc045cf1e56504e011dca68137dcd61Dmitriy Ivanov 152697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov fn_t lookup_dlsym_symbol2_using_RTLD_DEFAULT = 153697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol2_using_RTLD_DEFAULT")); 154697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_TRUE(lookup_dlsym_symbol2_using_RTLD_DEFAULT != nullptr) << dlerror(); 155697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov 156697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ptr = lookup_dlsym_symbol2_using_RTLD_DEFAULT(); 157697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_TRUE(ptr != nullptr) << dlerror(); 158697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_EQ(44, *ptr); 159697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov 160697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov fn_t lookup_dlsym_symbol_using_RTLD_NEXT = 161697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol_using_RTLD_NEXT")); 162697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_TRUE(lookup_dlsym_symbol_using_RTLD_NEXT != nullptr) << dlerror(); 163697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov 164697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ptr = lookup_dlsym_symbol_using_RTLD_NEXT(); 165697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_TRUE(ptr != nullptr) << dlerror(); 166697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_EQ(43, *ptr); 167697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov 16876ac1acdacc045cf1e56504e011dca68137dcd61Dmitriy Ivanov dlclose(handle); 169697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov dlclose(preload); 17076ac1acdacc045cf1e56504e011dca68137dcd61Dmitriy Ivanov} 17176ac1acdacc045cf1e56504e011dca68137dcd61Dmitriy Ivanov 172f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy IvanovTEST(dlfcn, dlsym_handle_global_sym) { 173f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov // check that we do not look into global group 174f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov // when looking up symbol by handle 175f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov void* handle = dlopen("libtest_empty.so", RTLD_NOW); 176f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov dlopen("libtest_with_dependency.so", RTLD_NOW | RTLD_GLOBAL); 177f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov void* sym = dlsym(handle, "getRandomNumber"); 178f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov ASSERT_TRUE(sym == nullptr); 179f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov ASSERT_SUBSTR("undefined symbol: getRandomNumber", dlerror()); 180f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov 181f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov sym = dlsym(handle, "DlSymTestFunction"); 182f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov ASSERT_TRUE(sym == nullptr); 183f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov ASSERT_SUBSTR("undefined symbol: DlSymTestFunction", dlerror()); 184f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov dlclose(handle); 185f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov} 186f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov 187d5b578ac15330d7a872c198427628b723e0cc1cbDimitry IvanovTEST(dlfcn, dlsym_handle_empty_symbol) { 188d5b578ac15330d7a872c198427628b723e0cc1cbDimitry Ivanov // check that dlsym of an empty symbol fails (see http://b/33530622) 189d5b578ac15330d7a872c198427628b723e0cc1cbDimitry Ivanov void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_NOW); 190d5b578ac15330d7a872c198427628b723e0cc1cbDimitry Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 191d5b578ac15330d7a872c198427628b723e0cc1cbDimitry Ivanov void* sym = dlsym(handle, ""); 192d5b578ac15330d7a872c198427628b723e0cc1cbDimitry Ivanov ASSERT_TRUE(sym == nullptr); 193d5b578ac15330d7a872c198427628b723e0cc1cbDimitry Ivanov ASSERT_SUBSTR("undefined symbol: ", dlerror()); 194d5b578ac15330d7a872c198427628b723e0cc1cbDimitry Ivanov dlclose(handle); 195d5b578ac15330d7a872c198427628b723e0cc1cbDimitry Ivanov} 196d5b578ac15330d7a872c198427628b723e0cc1cbDimitry Ivanov 197aa0f2bdbc22d4b7aec5d3f8f5f01eaeaa13414c2Dmitriy IvanovTEST(dlfcn, dlsym_with_dependencies) { 198aa0f2bdbc22d4b7aec5d3f8f5f01eaeaa13414c2Dmitriy Ivanov void* handle = dlopen("libtest_with_dependency.so", RTLD_NOW); 199f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov ASSERT_TRUE(handle != nullptr); 200aa0f2bdbc22d4b7aec5d3f8f5f01eaeaa13414c2Dmitriy Ivanov dlerror(); 201aa0f2bdbc22d4b7aec5d3f8f5f01eaeaa13414c2Dmitriy Ivanov // This symbol is in DT_NEEDED library. 202aa0f2bdbc22d4b7aec5d3f8f5f01eaeaa13414c2Dmitriy Ivanov void* sym = dlsym(handle, "getRandomNumber"); 203f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov ASSERT_TRUE(sym != nullptr) << dlerror(); 204aa0f2bdbc22d4b7aec5d3f8f5f01eaeaa13414c2Dmitriy Ivanov int (*fn)(void); 205aa0f2bdbc22d4b7aec5d3f8f5f01eaeaa13414c2Dmitriy Ivanov fn = reinterpret_cast<int (*)(void)>(sym); 206aa0f2bdbc22d4b7aec5d3f8f5f01eaeaa13414c2Dmitriy Ivanov EXPECT_EQ(4, fn()); 207aa0f2bdbc22d4b7aec5d3f8f5f01eaeaa13414c2Dmitriy Ivanov dlclose(handle); 208aa0f2bdbc22d4b7aec5d3f8f5f01eaeaa13414c2Dmitriy Ivanov} 209aa0f2bdbc22d4b7aec5d3f8f5f01eaeaa13414c2Dmitriy Ivanov 210b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy IvanovTEST(dlfcn, dlopen_noload) { 211b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov void* handle = dlopen("libtest_simple.so", RTLD_NOW | RTLD_NOLOAD); 212aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(handle == nullptr); 213b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov handle = dlopen("libtest_simple.so", RTLD_NOW); 214b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov void* handle2 = dlopen("libtest_simple.so", RTLD_NOW | RTLD_NOLOAD); 215aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(handle != nullptr); 216aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(handle2 != nullptr); 217b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov ASSERT_TRUE(handle == handle2); 218b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov ASSERT_EQ(0, dlclose(handle)); 219b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov ASSERT_EQ(0, dlclose(handle2)); 220b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov} 221b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov 222618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy IvanovTEST(dlfcn, dlopen_by_soname) { 223618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov static const char* soname = "libdlext_test_soname.so"; 224618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov static const char* filename = "libdlext_test_different_soname.so"; 225618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov // 1. Make sure there is no library with soname in default search path 226618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov void* handle = dlopen(soname, RTLD_NOW); 227618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov ASSERT_TRUE(handle == nullptr); 228618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov 229618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov // 2. Load a library using filename 230618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov handle = dlopen(filename, RTLD_NOW); 231618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 232618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov 233618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov // 3. Find library by soname 234618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov void* handle_soname = dlopen(soname, RTLD_NOW | RTLD_NOLOAD); 235618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov ASSERT_TRUE(handle_soname != nullptr) << dlerror(); 236618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov ASSERT_EQ(handle, handle_soname); 237618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov 238618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov // 4. RTLD_NOLOAD should still work with filename 239618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov void* handle_filename = dlopen(filename, RTLD_NOW | RTLD_NOLOAD); 240618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov ASSERT_TRUE(handle_filename != nullptr) << dlerror(); 241618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov ASSERT_EQ(handle, handle_filename); 242618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov 243618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov dlclose(handle_filename); 244618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov dlclose(handle_soname); 245618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov dlclose(handle); 246618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov} 247618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov 2480a2ab0203cc12c9b4b7647b18caf0343af8ca1a4Dimitry Ivanov// mips doesn't support ifuncs 2490a2ab0203cc12c9b4b7647b18caf0343af8ca1a4Dimitry Ivanov#if !defined(__mips__) 250c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid SmithTEST(dlfcn, ifunc) { 2519598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov typedef const char* (*fn_ptr)(); 252c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith 253c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith // ifunc's choice depends on whether IFUNC_CHOICE has a value 254c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith // first check the set case 255c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith setenv("IFUNC_CHOICE", "set", 1); 256c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith void* handle = dlopen("libtest_ifunc.so", RTLD_NOW); 257aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(handle != nullptr); 2589598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov fn_ptr foo_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo")); 2599598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov fn_ptr foo_library_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo_library")); 260aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(foo_ptr != nullptr); 261aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(foo_library_ptr != nullptr); 2629598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov ASSERT_EQ(strncmp("set", foo_ptr(), 3), 0); 2639598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov ASSERT_EQ(strncmp("set", foo_library_ptr(), 3), 0); 264c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith dlclose(handle); 265c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith 266c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith // then check the unset case 267c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith unsetenv("IFUNC_CHOICE"); 268c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith handle = dlopen("libtest_ifunc.so", RTLD_NOW); 269aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(handle != nullptr); 2709598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov foo_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo")); 2719598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov foo_library_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo_library")); 272aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(foo_ptr != nullptr); 273aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(foo_library_ptr != nullptr); 2749598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov ASSERT_EQ(strncmp("unset", foo_ptr(), 5), 0); 2759598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov ASSERT_EQ(strncmp("unset", foo_library_ptr(), 3), 0); 2769598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov dlclose(handle); 2779598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov} 2789598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov 27901c888c857f6f19837c5db581be83cc06f13fa1cDimitry Ivanov// ld.gold for arm produces incorrect binary (see http://b/27930475 for details) 28001c888c857f6f19837c5db581be83cc06f13fa1cDimitry Ivanov#if defined(__arm__) 28101c888c857f6f19837c5db581be83cc06f13fa1cDimitry IvanovTEST(dlfcn, KNOWN_FAILURE_ON_BIONIC(ifunc_ctor_call)) { 28201c888c857f6f19837c5db581be83cc06f13fa1cDimitry Ivanov#else 2839598b8c415e2fa9f240508185fe8c964b83f538dDmitriy IvanovTEST(dlfcn, ifunc_ctor_call) { 28401c888c857f6f19837c5db581be83cc06f13fa1cDimitry Ivanov#endif 2859598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov typedef const char* (*fn_ptr)(); 2869598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov 2879598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov void* handle = dlopen("libtest_ifunc.so", RTLD_NOW); 2889aea164457c269c475592da36b4655d45f55c7bcDmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 2899aea164457c269c475592da36b4655d45f55c7bcDmitriy Ivanov fn_ptr is_ctor_called = reinterpret_cast<fn_ptr>(dlsym(handle, "is_ctor_called_irelative")); 2909aea164457c269c475592da36b4655d45f55c7bcDmitriy Ivanov ASSERT_TRUE(is_ctor_called != nullptr) << dlerror(); 2919aea164457c269c475592da36b4655d45f55c7bcDmitriy Ivanov ASSERT_STREQ("false", is_ctor_called()); 2929aea164457c269c475592da36b4655d45f55c7bcDmitriy Ivanov 2939aea164457c269c475592da36b4655d45f55c7bcDmitriy Ivanov is_ctor_called = reinterpret_cast<fn_ptr>(dlsym(handle, "is_ctor_called_jump_slot")); 2949aea164457c269c475592da36b4655d45f55c7bcDmitriy Ivanov ASSERT_TRUE(is_ctor_called != nullptr) << dlerror(); 2959598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov ASSERT_STREQ("true", is_ctor_called()); 296c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith dlclose(handle); 297c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith} 298ba35b2d1b91459568133c1f4729a6fff8359e3d9Dimitry Ivanov 29901c888c857f6f19837c5db581be83cc06f13fa1cDimitry Ivanov// ld.gold for arm produces incorrect binary (see http://b/27930475 for details) 30001c888c857f6f19837c5db581be83cc06f13fa1cDimitry Ivanov#if defined(__arm__) 30101c888c857f6f19837c5db581be83cc06f13fa1cDimitry IvanovTEST(dlfcn, KNOWN_FAILURE_ON_BIONIC(ifunc_ctor_call_rtld_lazy)) { 30201c888c857f6f19837c5db581be83cc06f13fa1cDimitry Ivanov#else 303ba35b2d1b91459568133c1f4729a6fff8359e3d9Dimitry IvanovTEST(dlfcn, ifunc_ctor_call_rtld_lazy) { 30401c888c857f6f19837c5db581be83cc06f13fa1cDimitry Ivanov#endif 305ba35b2d1b91459568133c1f4729a6fff8359e3d9Dimitry Ivanov typedef const char* (*fn_ptr)(); 306ba35b2d1b91459568133c1f4729a6fff8359e3d9Dimitry Ivanov 307ba35b2d1b91459568133c1f4729a6fff8359e3d9Dimitry Ivanov void* handle = dlopen("libtest_ifunc.so", RTLD_LAZY); 308ba35b2d1b91459568133c1f4729a6fff8359e3d9Dimitry Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 309ba35b2d1b91459568133c1f4729a6fff8359e3d9Dimitry Ivanov fn_ptr is_ctor_called = reinterpret_cast<fn_ptr>(dlsym(handle, "is_ctor_called_irelative")); 310ba35b2d1b91459568133c1f4729a6fff8359e3d9Dimitry Ivanov ASSERT_TRUE(is_ctor_called != nullptr) << dlerror(); 311ba35b2d1b91459568133c1f4729a6fff8359e3d9Dimitry Ivanov ASSERT_STREQ("false", is_ctor_called()); 312ba35b2d1b91459568133c1f4729a6fff8359e3d9Dimitry Ivanov 313ba35b2d1b91459568133c1f4729a6fff8359e3d9Dimitry Ivanov is_ctor_called = reinterpret_cast<fn_ptr>(dlsym(handle, "is_ctor_called_jump_slot")); 314ba35b2d1b91459568133c1f4729a6fff8359e3d9Dimitry Ivanov ASSERT_TRUE(is_ctor_called != nullptr) << dlerror(); 315ba35b2d1b91459568133c1f4729a6fff8359e3d9Dimitry Ivanov ASSERT_STREQ("true", is_ctor_called()); 316ba35b2d1b91459568133c1f4729a6fff8359e3d9Dimitry Ivanov dlclose(handle); 317ba35b2d1b91459568133c1f4729a6fff8359e3d9Dimitry Ivanov} 3180a2ab0203cc12c9b4b7647b18caf0343af8ca1a4Dimitry Ivanov#endif 319c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith 320b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy IvanovTEST(dlfcn, dlopen_check_relocation_dt_needed_order) { 321b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // This is the structure of the test library and 322b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // its dt_needed libraries 323b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // libtest_relo_check_dt_needed_order.so 324b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // | 325b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // +-> libtest_relo_check_dt_needed_order_1.so 326b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // | 327b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // +-> libtest_relo_check_dt_needed_order_2.so 328b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // 329b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // The root library references relo_test_get_answer_lib - which is defined 330b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // in both dt_needed libraries, the correct relocation should 331b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // use the function defined in libtest_relo_check_dt_needed_order_1.so 332b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov void* handle = nullptr; 333d9ff7226613014056c9edd79a68dc5af939107a0Dmitriy Ivanov auto guard = make_scope_guard([&]() { 334b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov dlclose(handle); 335b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov }); 336b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov 337b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov handle = dlopen("libtest_relo_check_dt_needed_order.so", RTLD_NOW); 338b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 339b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov 340b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov typedef int (*fn_t) (void); 341b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "relo_test_get_answer")); 342b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov ASSERT_TRUE(fn != nullptr) << dlerror(); 343b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov ASSERT_EQ(1, fn()); 344b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov} 345b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov 346cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy IvanovTEST(dlfcn, dlopen_check_order_dlsym) { 34714669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // Here is how the test library and its dt_needed 34814669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // libraries are arranged 34914669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // 350cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // libtest_check_order_children.so 35114669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // | 352cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._1_left.so 35314669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // | | 354cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | +-> ..._a.so 35514669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // | | 356cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | +-> ...r_b.so 35714669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // | 358cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._2_right.so 35914669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // | | 360cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | +-> ..._d.so 36114669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // | | 362cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | +-> ..._b.so 36314669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // | 364cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._3_c.so 36514669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // 36614669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // load order should be (1, 2, 3, a, b, d) 36714669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // 36814669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // get_answer() is defined in (2, 3, a, b, c) 36914669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // get_answer2() is defined in (b, d) 370cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov void* sym = dlsym(RTLD_DEFAULT, "check_order_dlsym_get_answer"); 37114669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov ASSERT_TRUE(sym == nullptr); 372cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov void* handle = dlopen("libtest_check_order_dlsym.so", RTLD_NOW | RTLD_GLOBAL); 373cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 37414669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov typedef int (*fn_t) (void); 37514669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov fn_t fn, fn2; 376cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov fn = reinterpret_cast<fn_t>(dlsym(RTLD_DEFAULT, "check_order_dlsym_get_answer")); 377aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(fn != nullptr) << dlerror(); 378cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov fn2 = reinterpret_cast<fn_t>(dlsym(RTLD_DEFAULT, "check_order_dlsym_get_answer2")); 379aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(fn2 != nullptr) << dlerror(); 38014669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov 38114669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov ASSERT_EQ(42, fn()); 38214669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov ASSERT_EQ(43, fn2()); 38314669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov dlclose(handle); 38414669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov} 38514669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov 386cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy IvanovTEST(dlfcn, dlopen_check_order_reloc_siblings) { 387cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // This is how this one works: 388cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // we lookup and call get_answer which is defined in '_2.so' 389cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // and in turn calls external get_answer_impl() defined in _1.so and in '_[a-f].so' 390cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // the correct _impl() is implemented by '_a.so'; 391cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // 392cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // Note that this is test for RTLD_LOCAL (TODO: test for GLOBAL?) 393cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // 394cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // Here is the picture: 395cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // 396cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // libtest_check_order_reloc_siblings.so 397cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | 398cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._1.so <- empty 399cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | | 400cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | +-> ..._a.so <- exports correct answer_impl() 401cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | | 402cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | +-> ..._b.so <- every other letter exporting incorrect one. 403cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | 404cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._2.so <- empty 405cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | | 406cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | +-> ..._c.so 407cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | | 408cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | +-> ..._d.so 409cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | 410cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._3.so <- empty 411cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | 412cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._e.so 413cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | 414cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._f.so <- exports get_answer() that calls get_anser_impl(); 415cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // implements incorrect get_answer_impl() 416cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 417cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov void* handle = dlopen("libtest_check_order_reloc_siblings.so", RTLD_NOW | RTLD_NOLOAD); 418cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(handle == nullptr); 419cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov#ifdef __BIONIC__ 420cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // TODO: glibc returns nullptr on dlerror() here. Is it bug? 421cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_STREQ("dlopen failed: library \"libtest_check_order_reloc_siblings.so\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror()); 422cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov#endif 423cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 424cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov handle = dlopen("libtest_check_order_reloc_siblings.so", RTLD_NOW | RTLD_LOCAL); 425cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 426cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 427cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov typedef int (*fn_t) (void); 428cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "check_order_reloc_get_answer")); 429cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(fn != nullptr) << dlerror(); 430cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_EQ(42, fn()); 431cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 432cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_EQ(0, dlclose(handle)); 433cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov} 434cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 435cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy IvanovTEST(dlfcn, dlopen_check_order_reloc_siblings_with_preload) { 436cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // This test uses the same library as dlopen_check_order_reloc_siblings. 437cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // Unlike dlopen_check_order_reloc_siblings it preloads 438cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // libtest_check_order_reloc_siblings_1.so (first dependency) prior to 439cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // dlopen(libtest_check_order_reloc_siblings.so) 440cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 441cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov void* handle = dlopen("libtest_check_order_reloc_siblings.so", RTLD_NOW | RTLD_NOLOAD); 442cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(handle == nullptr); 443cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov handle = dlopen("libtest_check_order_reloc_siblings_1.so", RTLD_NOW | RTLD_NOLOAD); 444cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(handle == nullptr); 445cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 446cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov void* handle_for_1 = dlopen("libtest_check_order_reloc_siblings_1.so", RTLD_NOW | RTLD_LOCAL); 447cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(handle_for_1 != nullptr) << dlerror(); 448cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 449cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov handle = dlopen("libtest_check_order_reloc_siblings.so", RTLD_NOW | RTLD_LOCAL); 450cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 451cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 452cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_EQ(0, dlclose(handle_for_1)); 453cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 454cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov typedef int (*fn_t) (void); 455cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "check_order_reloc_get_answer")); 456cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(fn != nullptr) << dlerror(); 457cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_EQ(42, fn()); 458cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 459cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_EQ(0, dlclose(handle)); 460cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov} 461cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 4627699d13a74769fe8063fcca95588c87c571226c0Dmitriy IvanovTEST(dlfcn, dlopen_check_order_reloc_grandchild) { 4637699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov // This is how this one works: 4647699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov // we lookup and call grandchild_get_answer which is defined in '_2.so' 4657699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov // and in turn calls external get_answer_impl() defined in '_c_1.so and _c_2.so' 4667699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov // the correct _impl() is implemented by '_c_1.so'; 4677699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov // 4687699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov // Here is the picture of subtree: 4697699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov // 4707699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov // libtest_check_order_reloc_siblings.so 4717699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov // | 4727699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov // +-> ..._2.so <- grandchild_get_answer() 4737699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov // | 4747699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov // +-> ..._c.so <- empty 4757699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov // | | 4767699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov // | +-> _c_1.so <- exports correct answer_impl() 4777699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov // | | 4787699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov // | +-> _c_2.so <- exports incorrect answer_impl() 4797699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov // | 4807699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov // +-> ..._d.so <- empty 4817699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov 4827699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov void* handle = dlopen("libtest_check_order_reloc_siblings.so", RTLD_NOW | RTLD_NOLOAD); 4837699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov ASSERT_TRUE(handle == nullptr); 4847699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov#ifdef __BIONIC__ 4857699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov // TODO: glibc returns nullptr on dlerror() here. Is it bug? 4867699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov ASSERT_STREQ("dlopen failed: library \"libtest_check_order_reloc_siblings.so\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror()); 4877699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov#endif 4887699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov 4897699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov handle = dlopen("libtest_check_order_reloc_siblings.so", RTLD_NOW | RTLD_LOCAL); 4907699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 4917699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov 4927699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov typedef int (*fn_t) (void); 4937699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "check_order_reloc_grandchild_get_answer")); 4947699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov ASSERT_TRUE(fn != nullptr) << dlerror(); 4957699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov ASSERT_EQ(42, fn()); 4967699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov 4977699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov ASSERT_EQ(0, dlclose(handle)); 4987699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov} 4997699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov 500cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy IvanovTEST(dlfcn, dlopen_check_order_reloc_nephew) { 501cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // This is how this one works: 502cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // we lookup and call nephew_get_answer which is defined in '_2.so' 503cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // and in turn calls external get_answer_impl() defined in '_[a-f].so' 504cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // the correct _impl() is implemented by '_a.so'; 505cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // 506cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // Here is the picture: 507cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // 508cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // libtest_check_order_reloc_siblings.so 509cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | 510cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._1.so <- empty 511cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | | 512cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | +-> ..._a.so <- exports correct answer_impl() 513cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | | 514cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | +-> ..._b.so <- every other letter exporting incorrect one. 515cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | 516cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._2.so <- empty 517cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | | 518cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | +-> ..._c.so 519cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | | 520cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | +-> ..._d.so 521cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | 522cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._3.so <- nephew_get_answer() that calls get_answer_impl(); 523cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | 524cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._e.so 525cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | 526cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._f.so 527cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 528cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov void* handle = dlopen("libtest_check_order_reloc_siblings.so", RTLD_NOW | RTLD_NOLOAD); 529cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(handle == nullptr); 530cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov#ifdef __BIONIC__ 531cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // TODO: glibc returns nullptr on dlerror() here. Is it bug? 532cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_STREQ("dlopen failed: library \"libtest_check_order_reloc_siblings.so\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror()); 533cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov#endif 534cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 535cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov handle = dlopen("libtest_check_order_reloc_siblings.so", RTLD_NOW | RTLD_LOCAL); 536cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 537cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 538cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov typedef int (*fn_t) (void); 539cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "check_order_reloc_nephew_get_answer")); 540cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(fn != nullptr) << dlerror(); 541cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_EQ(42, fn()); 542cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 543cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_EQ(0, dlclose(handle)); 544cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov} 545cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 546ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy IvanovTEST(dlfcn, check_unload_after_reloc) { 547ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov // This is how this one works: 548ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov // libtest_two_parents_parent1 <- answer_impl() used by libtest_two_parents_child 549ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov // | 550ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov // +-> libtest_two_parents_child 551ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov // 552ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov // libtest_two_parents_parent2 <- answer_impl() not used by libtest_two_parents_child 553ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov // | 554ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov // +-> libtest_two_parents_child 555ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov // 556ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov // Test dlopens parent1 which loads and relocates libtest_two_parents_child.so 557ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov // as a second step it dlopens parent2 and dlcloses parent1... 558ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov 559cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov void* handle = dlopen("libtest_two_parents_parent1.so", RTLD_NOW | RTLD_LOCAL); 560cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 561ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov 562cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov void* handle2 = dlopen("libtest_two_parents_parent2.so", RTLD_NOW | RTLD_LOCAL); 563cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov ASSERT_TRUE(handle2 != nullptr) << dlerror(); 564ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov 565cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov typedef int (*fn_t) (void); 566cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov fn_t fn = reinterpret_cast<fn_t>(dlsym(handle2, "check_order_reloc_get_answer")); 567cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov ASSERT_TRUE(fn != nullptr) << dlerror(); 568cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov ASSERT_EQ(42, fn()); 569ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov 570cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov ASSERT_EQ(0, dlclose(handle)); 571ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov 572cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov handle = dlopen("libtest_two_parents_parent1.so", RTLD_NOW | RTLD_LOCAL | RTLD_NOLOAD); 573cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov ASSERT_TRUE(handle != nullptr); 574cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov ASSERT_EQ(0, dlclose(handle)); 575ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov 576cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov fn = reinterpret_cast<fn_t>(dlsym(handle2, "check_order_reloc_get_answer")); 577cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov ASSERT_TRUE(fn != nullptr) << dlerror(); 578cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov ASSERT_EQ(42, fn()); 579ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov 580cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov ASSERT_EQ(0, dlclose(handle2)); 581ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov 582cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov handle = dlopen("libtest_two_parents_parent1.so", RTLD_NOW | RTLD_LOCAL | RTLD_NOLOAD); 583cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov ASSERT_TRUE(handle == nullptr); 584ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov} 585ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov 586cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanovextern "C" int check_order_reloc_root_get_answer_impl() { 587cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov return 42; 588cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov} 589cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 590cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy IvanovTEST(dlfcn, dlopen_check_order_reloc_main_executable) { 591cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // This is how this one works: 592cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // we lookup and call get_answer3 which is defined in 'root.so' 593cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // and in turn calls external root_get_answer_impl() defined in _2.so and 594cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // above the correct _impl() is one in the executable. 595cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // 596cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // libtest_check_order_reloc_root.so 597cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | 598cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._1.so <- empty 599cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | 600cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._2.so <- gives incorrect answer for answer_main_impl() 601cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // 602cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 603cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov void* handle = dlopen("libtest_check_order_reloc_root.so", RTLD_NOW | RTLD_NOLOAD); 604cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(handle == nullptr); 605cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov#ifdef __BIONIC__ 606cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // TODO: glibc returns nullptr on dlerror() here. Is it bug? 607cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_STREQ("dlopen failed: library \"libtest_check_order_reloc_root.so\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror()); 608cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov#endif 609cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 610cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov handle = dlopen("libtest_check_order_reloc_root.so", RTLD_NOW | RTLD_LOCAL); 611cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 612cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 613cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov typedef int (*fn_t) (void); 614cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "check_order_reloc_root_get_answer")); 615cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(fn != nullptr) << dlerror(); 616cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_EQ(42, fn()); 617cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 618cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_EQ(0, dlclose(handle)); 619cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov} 620cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 621e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy IvanovTEST(dlfcn, dlopen_check_rtld_local) { 622e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov void* sym = dlsym(RTLD_DEFAULT, "dlopen_testlib_simple_func"); 623e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov ASSERT_TRUE(sym == nullptr); 624e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov 625e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov // implicit RTLD_LOCAL 626e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov void* handle = dlopen("libtest_simple.so", RTLD_NOW); 627e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov sym = dlsym(RTLD_DEFAULT, "dlopen_testlib_simple_func"); 628e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov ASSERT_TRUE(sym == nullptr); 629e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov ASSERT_SUBSTR("undefined symbol: dlopen_testlib_simple_func", dlerror()); 630e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov sym = dlsym(handle, "dlopen_testlib_simple_func"); 631e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov ASSERT_TRUE(sym != nullptr); 632e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov ASSERT_TRUE(reinterpret_cast<bool (*)(void)>(sym)()); 633e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov dlclose(handle); 634e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov 635e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov // explicit RTLD_LOCAL 636e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov handle = dlopen("libtest_simple.so", RTLD_NOW | RTLD_LOCAL); 637e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov sym = dlsym(RTLD_DEFAULT, "dlopen_testlib_simple_func"); 638e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov ASSERT_TRUE(sym == nullptr); 639e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov ASSERT_SUBSTR("undefined symbol: dlopen_testlib_simple_func", dlerror()); 640e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov sym = dlsym(handle, "dlopen_testlib_simple_func"); 641e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov ASSERT_TRUE(sym != nullptr); 642e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov ASSERT_TRUE(reinterpret_cast<bool (*)(void)>(sym)()); 643e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov dlclose(handle); 644e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov} 645e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov 646e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy IvanovTEST(dlfcn, dlopen_check_rtld_global) { 647e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov void* sym = dlsym(RTLD_DEFAULT, "dlopen_testlib_simple_func"); 648e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov ASSERT_TRUE(sym == nullptr); 649e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov 650e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov void* handle = dlopen("libtest_simple.so", RTLD_NOW | RTLD_GLOBAL); 6511b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 652e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov sym = dlsym(RTLD_DEFAULT, "dlopen_testlib_simple_func"); 653e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov ASSERT_TRUE(sym != nullptr) << dlerror(); 654e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov ASSERT_TRUE(reinterpret_cast<bool (*)(void)>(sym)()); 655e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov dlclose(handle); 6561b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 6571b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov // RTLD_GLOBAL implies RTLD_NODELETE, let's check that 6581b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov void* sym_after_dlclose = dlsym(RTLD_DEFAULT, "dlopen_testlib_simple_func"); 6591b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_EQ(sym, sym_after_dlclose); 660f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov 661f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov // Check if dlsym() for main program's handle searches RTLD_GLOBAL 662f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov // shared libraries after symbol was not found in the main executable 663f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov // and dependent libraries. 664f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov void* handle_for_main_executable = dlopen(nullptr, RTLD_NOW); 665f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov sym = dlsym(handle_for_main_executable, "dlopen_testlib_simple_func"); 666f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov ASSERT_TRUE(sym != nullptr) << dlerror(); 667f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov 668f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov dlclose(handle_for_main_executable); 669e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov} 670e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov 67114669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov// libtest_with_dependency_loop.so -> libtest_with_dependency_loop_a.so -> 67214669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov// libtest_with_dependency_loop_b.so -> libtest_with_dependency_loop_c.so -> 67314669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov// libtest_with_dependency_loop_a.so 67414669a939d113214a4a20b9318fca0992d5453f0Dmitriy IvanovTEST(dlfcn, dlopen_check_loop) { 675cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov void* handle = dlopen("libtest_with_dependency_loop.so", RTLD_NOW); 676cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 677cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov void* f = dlsym(handle, "dlopen_test_loopy_function"); 678cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov ASSERT_TRUE(f != nullptr) << dlerror(); 679cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov EXPECT_TRUE(reinterpret_cast<bool (*)(void)>(f)()); 680cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov ASSERT_EQ(0, dlclose(handle)); 681cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov 682cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov // dlopen second time to make sure that the library was unloaded correctly 683cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov handle = dlopen("libtest_with_dependency_loop.so", RTLD_NOW | RTLD_NOLOAD); 684cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov ASSERT_TRUE(handle == nullptr); 685ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov#ifdef __BIONIC__ 686cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov ASSERT_STREQ("dlopen failed: library \"libtest_with_dependency_loop.so\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror()); 6879cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov#else 6889cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov // TODO: glibc returns nullptr on dlerror() here. Is it bug? 6899cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov ASSERT_TRUE(dlerror() == nullptr); 690eb27bbae8f0edc6b62ca2db73256c7fb53b9e9bfDmitriy Ivanov#endif 691ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov 692cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov handle = dlopen("libtest_with_dependency_a.so", RTLD_NOW | RTLD_NOLOAD); 693cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov ASSERT_TRUE(handle == nullptr); 69414669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov} 69514669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov 6961b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy IvanovTEST(dlfcn, dlopen_nodelete) { 6971b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov static bool is_unloaded = false; 6981b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 6991b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov void* handle = dlopen("libtest_nodelete_1.so", RTLD_NOW | RTLD_NODELETE); 7001b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 7011b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov void (*set_unload_flag_ptr)(bool*); 7021b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov set_unload_flag_ptr = reinterpret_cast<void (*)(bool*)>(dlsym(handle, "dlopen_nodelete_1_set_unload_flag_ptr")); 7031b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(set_unload_flag_ptr != nullptr) << dlerror(); 7041b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov set_unload_flag_ptr(&is_unloaded); 7051b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 7061b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_nodelete_1_taxicab_number")); 7071b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(taxicab_number != nullptr) << dlerror(); 7081b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_EQ(1729U, *taxicab_number); 7091b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov *taxicab_number = 2; 7101b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 7111b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov dlclose(handle); 7121b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(!is_unloaded); 7131b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 7141b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov uint32_t* taxicab_number_after_dlclose = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_nodelete_1_taxicab_number")); 7151b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_EQ(taxicab_number_after_dlclose, taxicab_number); 7161b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_EQ(2U, *taxicab_number_after_dlclose); 7171b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 7181b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 7191b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov handle = dlopen("libtest_nodelete_1.so", RTLD_NOW); 7201b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov uint32_t* taxicab_number2 = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_nodelete_1_taxicab_number")); 7211b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_EQ(taxicab_number2, taxicab_number); 7221b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 7231b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_EQ(2U, *taxicab_number2); 7241b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 7251b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov dlclose(handle); 7261b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(!is_unloaded); 7271b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov} 7281b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 7291b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy IvanovTEST(dlfcn, dlopen_nodelete_on_second_dlopen) { 7301b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov static bool is_unloaded = false; 7311b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 7321b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov void* handle = dlopen("libtest_nodelete_2.so", RTLD_NOW); 7331b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 7341b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov void (*set_unload_flag_ptr)(bool*); 7351b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov set_unload_flag_ptr = reinterpret_cast<void (*)(bool*)>(dlsym(handle, "dlopen_nodelete_2_set_unload_flag_ptr")); 7361b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(set_unload_flag_ptr != nullptr) << dlerror(); 7371b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov set_unload_flag_ptr(&is_unloaded); 7381b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 7391b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_nodelete_2_taxicab_number")); 7401b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(taxicab_number != nullptr) << dlerror(); 7411b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 7421b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_EQ(1729U, *taxicab_number); 7431b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov *taxicab_number = 2; 7441b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 7451b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov // This RTLD_NODELETE should be ignored 7461b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov void* handle1 = dlopen("libtest_nodelete_2.so", RTLD_NOW | RTLD_NODELETE); 7471b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(handle1 != nullptr) << dlerror(); 7481b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_EQ(handle, handle1); 7491b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 7501b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov dlclose(handle1); 7511b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov dlclose(handle); 7521b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 7531b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(is_unloaded); 7541b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov} 7551b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 7561b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy IvanovTEST(dlfcn, dlopen_nodelete_dt_flags_1) { 7571b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov static bool is_unloaded = false; 7581b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 7591b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov void* handle = dlopen("libtest_nodelete_dt_flags_1.so", RTLD_NOW); 7601b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 7611b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov void (*set_unload_flag_ptr)(bool*); 7621b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov set_unload_flag_ptr = reinterpret_cast<void (*)(bool*)>(dlsym(handle, "dlopen_nodelete_dt_flags_1_set_unload_flag_ptr")); 7631b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(set_unload_flag_ptr != nullptr) << dlerror(); 7641b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov set_unload_flag_ptr(&is_unloaded); 7651b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 7661b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov dlclose(handle); 7671b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(!is_unloaded); 7681b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov} 7691b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 770d225a5e65223b375a63548c4b780f04d8f3d7b60Dmitriy IvanovTEST(dlfcn, dlsym_df_1_global) { 771d225a5e65223b375a63548c4b780f04d8f3d7b60Dmitriy Ivanov void* handle = dlopen("libtest_dlsym_df_1_global.so", RTLD_NOW); 772d225a5e65223b375a63548c4b780f04d8f3d7b60Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 773d225a5e65223b375a63548c4b780f04d8f3d7b60Dmitriy Ivanov int (*get_answer)(); 774d225a5e65223b375a63548c4b780f04d8f3d7b60Dmitriy Ivanov get_answer = reinterpret_cast<int (*)()>(dlsym(handle, "dl_df_1_global_get_answer")); 775d225a5e65223b375a63548c4b780f04d8f3d7b60Dmitriy Ivanov ASSERT_TRUE(get_answer != nullptr) << dlerror(); 776d225a5e65223b375a63548c4b780f04d8f3d7b60Dmitriy Ivanov ASSERT_EQ(42, get_answer()); 777d225a5e65223b375a63548c4b780f04d8f3d7b60Dmitriy Ivanov ASSERT_EQ(0, dlclose(handle)); 778d225a5e65223b375a63548c4b780f04d8f3d7b60Dmitriy Ivanov} 779d225a5e65223b375a63548c4b780f04d8f3d7b60Dmitriy Ivanov 780e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott HughesTEST(dlfcn, dlopen_failure) { 7813b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes void* self = dlopen("/does/not/exist", RTLD_NOW); 782aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(self == nullptr); 783063525c61d24776094d76971f33920e2a2079530Elliott Hughes#if defined(__BIONIC__) 7843b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_STREQ("dlopen failed: library \"/does/not/exist\" not found", dlerror()); 7853b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes#else 7863b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_STREQ("/does/not/exist: cannot open shared object file: No such file or directory", dlerror()); 7873b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes#endif 7883b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes} 7893b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 790c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanovstatic void ConcurrentDlErrorFn(std::string& error) { 791c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov ASSERT_TRUE(dlerror() == nullptr); 792c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov 793c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov void* handle = dlopen("/child/thread", RTLD_NOW); 794c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov ASSERT_TRUE(handle == nullptr); 795c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov 796c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov const char* err = dlerror(); 797c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov ASSERT_TRUE(err != nullptr); 798c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov 799c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov error = err; 8005419b9474753d25dff947c7740532f86d130c0beElliott Hughes} 8015419b9474753d25dff947c7740532f86d130c0beElliott Hughes 802c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry IvanovTEST(dlfcn, dlerror_concurrent_buffer) { 803c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov void* handle = dlopen("/main/thread", RTLD_NOW); 804c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov ASSERT_TRUE(handle == nullptr); 8055419b9474753d25dff947c7740532f86d130c0beElliott Hughes const char* main_thread_error = dlerror(); 806c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov ASSERT_TRUE(main_thread_error != nullptr); 8075419b9474753d25dff947c7740532f86d130c0beElliott Hughes ASSERT_SUBSTR("/main/thread", main_thread_error); 8085419b9474753d25dff947c7740532f86d130c0beElliott Hughes 809c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov std::string child_thread_error; 810c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov std::thread t(ConcurrentDlErrorFn, std::ref(child_thread_error)); 811c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov t.join(); 812c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov ASSERT_SUBSTR("/child/thread", child_thread_error.c_str()); 8135419b9474753d25dff947c7740532f86d130c0beElliott Hughes 814c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov // Check that main thread local buffer was not modified. 815c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov ASSERT_SUBSTR("/main/thread", main_thread_error); 816c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov} 817c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov 818c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry IvanovTEST(dlfcn, dlerror_concurrent) { 819c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov void* handle = dlopen("/main/thread", RTLD_NOW); 820c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov ASSERT_TRUE(handle == nullptr); 821c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov 822c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov std::string child_thread_error; 823c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov std::thread t(ConcurrentDlErrorFn, std::ref(child_thread_error)); 824c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov t.join(); 825c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov ASSERT_SUBSTR("/child/thread", child_thread_error.c_str()); 826c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov 827c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov const char* main_thread_error = dlerror(); 828c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov ASSERT_TRUE(main_thread_error != nullptr); 8295419b9474753d25dff947c7740532f86d130c0beElliott Hughes ASSERT_SUBSTR("/main/thread", main_thread_error); 8305419b9474753d25dff947c7740532f86d130c0beElliott Hughes} 8315419b9474753d25dff947c7740532f86d130c0beElliott Hughes 832e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott HughesTEST(dlfcn, dlsym_failures) { 8333b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes dlerror(); // Clear any pending errors. 834aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov void* self = dlopen(nullptr, RTLD_NOW); 835aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(self != nullptr); 836aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(dlerror() == nullptr); 8373b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 8383b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes void* sym; 8393b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 84044adf93b8eddb3a7965a3e9abc189408a1f5a7eaDmitriy Ivanov#if defined(__BIONIC__) && !defined(__LP64__) 84144adf93b8eddb3a7965a3e9abc189408a1f5a7eaDmitriy Ivanov // RTLD_DEFAULT in lp32 bionic is not (void*)0 84244adf93b8eddb3a7965a3e9abc189408a1f5a7eaDmitriy Ivanov // so it can be distinguished from the NULL handle. 843aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov sym = dlsym(nullptr, "test"); 844aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(sym == nullptr); 8454a2c5aa30ceea2aaf8dcaee2feb4879978af4fceDimitry Ivanov ASSERT_STREQ("dlsym failed: library handle is null", dlerror()); 8463b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes#endif 8473b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 8483b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes // Symbol that doesn't exist. 8493b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes sym = dlsym(self, "ThisSymbolDoesNotExist"); 850aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(sym == nullptr); 8513b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_SUBSTR("undefined symbol: ThisSymbolDoesNotExist", dlerror()); 8521a6961650c82168864afe040dbdc05977db701dfElliott Hughes 8531a6961650c82168864afe040dbdc05977db701dfElliott Hughes ASSERT_EQ(0, dlclose(self)); 8543b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes} 8553b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 856aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy IvanovTEST(dlfcn, dladdr_executable) { 8573b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes dlerror(); // Clear any pending errors. 858aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov void* self = dlopen(nullptr, RTLD_NOW); 859aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(self != nullptr); 860aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(dlerror() == nullptr); 8618e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 8628e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes void* sym = dlsym(self, "DlSymTestFunction"); 863aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(sym != nullptr); 8648e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 8658e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // Deliberately ask dladdr for an address inside a symbol, rather than the symbol base address. 8668e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes void* addr = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(sym) + 2); 8678e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 8688e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes Dl_info info; 8698e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes int rc = dladdr(addr, &info); 8708e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_NE(rc, 0); // Zero on error, non-zero on success. 8718e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 8728e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // Get the name of this executable. 8732ba1cf39ae6087249a839ec7b3793d4d4fa75438Dimitry Ivanov const std::string& executable_path = get_executable_path(); 8748e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 8758e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // The filename should be that of this executable. 876aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov char dli_realpath[PATH_MAX]; 877aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov ASSERT_TRUE(realpath(info.dli_fname, dli_realpath) != nullptr); 8782ba1cf39ae6087249a839ec7b3793d4d4fa75438Dimitry Ivanov ASSERT_STREQ(executable_path.c_str(), dli_realpath); 8798e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 8808e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // The symbol name should be the symbol we looked up. 8818e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_STREQ(info.dli_sname, "DlSymTestFunction"); 8828e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 8838e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // The address should be the exact address of the symbol. 8848e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_EQ(info.dli_saddr, sym); 8858e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 886aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov std::vector<map_record> maps; 887aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov ASSERT_TRUE(Maps::parse_maps(&maps)); 888aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov 889aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov void* base_address = nullptr; 890aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov for (const map_record& rec : maps) { 891aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov if (executable_path == rec.pathname) { 892aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov base_address = reinterpret_cast<void*>(rec.addr_start); 8938e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes break; 8948e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes } 8958e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes } 8968e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 8978e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // The base address should be the address we were loaded at. 8988e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_EQ(info.dli_fbase, base_address); 8991a6961650c82168864afe040dbdc05977db701dfElliott Hughes 9001a6961650c82168864afe040dbdc05977db701dfElliott Hughes ASSERT_EQ(0, dlclose(self)); 9018e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes} 9028e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 9032ba1cf39ae6087249a839ec7b3793d4d4fa75438Dimitry IvanovTEST(dlfcn, dlopen_executable_by_absolute_path) { 9042ba1cf39ae6087249a839ec7b3793d4d4fa75438Dimitry Ivanov void* handle1 = dlopen(nullptr, RTLD_NOW); 9052ba1cf39ae6087249a839ec7b3793d4d4fa75438Dimitry Ivanov ASSERT_TRUE(handle1 != nullptr) << dlerror(); 9062ba1cf39ae6087249a839ec7b3793d4d4fa75438Dimitry Ivanov 9072ba1cf39ae6087249a839ec7b3793d4d4fa75438Dimitry Ivanov void* handle2 = dlopen(get_executable_path().c_str(), RTLD_NOW); 9082ba1cf39ae6087249a839ec7b3793d4d4fa75438Dimitry Ivanov ASSERT_TRUE(handle2 != nullptr) << dlerror(); 9092ba1cf39ae6087249a839ec7b3793d4d4fa75438Dimitry Ivanov 9102ba1cf39ae6087249a839ec7b3793d4d4fa75438Dimitry Ivanov#if defined(__BIONIC__) 9112ba1cf39ae6087249a839ec7b3793d4d4fa75438Dimitry Ivanov ASSERT_EQ(handle1, handle2); 9122ba1cf39ae6087249a839ec7b3793d4d4fa75438Dimitry Ivanov#else 9132ba1cf39ae6087249a839ec7b3793d4d4fa75438Dimitry Ivanov GTEST_LOG_(INFO) << "Skipping ASSERT_EQ(handle1, handle2) for glibc: " 9142ba1cf39ae6087249a839ec7b3793d4d4fa75438Dimitry Ivanov "it loads a separate copy of the main executable " 9152ba1cf39ae6087249a839ec7b3793d4d4fa75438Dimitry Ivanov "on dlopen by absolute path."; 9162ba1cf39ae6087249a839ec7b3793d4d4fa75438Dimitry Ivanov#endif 9172ba1cf39ae6087249a839ec7b3793d4d4fa75438Dimitry Ivanov} 9182ba1cf39ae6087249a839ec7b3793d4d4fa75438Dimitry Ivanov 91914b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko#if defined (__aarch64__) 92014b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko#define ALTERNATE_PATH_TO_SYSTEM_LIB "/system/lib/arm64/" 92114b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko#elif defined (__arm__) 92214b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko#define ALTERNATE_PATH_TO_SYSTEM_LIB "/system/lib/arm/" 92314b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko#elif defined (__i386__) 92414b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko#define ALTERNATE_PATH_TO_SYSTEM_LIB "/system/lib/x86/" 92514b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko#elif defined (__x86_64__) 92614b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko#define ALTERNATE_PATH_TO_SYSTEM_LIB "/system/lib/x86_64/" 92714b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko#elif defined (__mips__) 92814b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko#if defined(__LP64__) 92914b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko#define ALTERNATE_PATH_TO_SYSTEM_LIB "/system/lib/mips64/" 93014b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko#else 93114b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko#define ALTERNATE_PATH_TO_SYSTEM_LIB "/system/lib/mips/" 93214b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko#endif 93314b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko#else 93414b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko#error "Unknown architecture" 93514b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko#endif 9366f2d3104c82f81c1f0123a3cfb25ae670841d0baLazar Trsic#define PATH_TO_LIBC PATH_TO_SYSTEM_LIB "libc.so" 93714b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko#define ALTERNATE_PATH_TO_LIBC ALTERNATE_PATH_TO_SYSTEM_LIB "libc.so" 938aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov 939aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy IvanovTEST(dlfcn, dladdr_libc) { 940aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov#if defined(__BIONIC__) 941aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov Dl_info info; 942aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov void* addr = reinterpret_cast<void*>(puts); // well-known libc function 943aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov ASSERT_TRUE(dladdr(addr, &info) != 0); 944aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov 945ef25592f14d23ce6294ea103e9edf894779d141dDmitriy Ivanov char libc_realpath[PATH_MAX]; 94614b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko 94714b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko // Check if libc is in canonical path or in alternate path. 94814b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko if (strncmp(ALTERNATE_PATH_TO_SYSTEM_LIB, 94914b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko info.dli_fname, 95014b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko sizeof(ALTERNATE_PATH_TO_SYSTEM_LIB) - 1) == 0) { 95114b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko // Platform with emulated architecture. Symlink on ARC++. 95214b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko ASSERT_TRUE(realpath(ALTERNATE_PATH_TO_LIBC, libc_realpath) == libc_realpath); 95314b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko } else { 95414b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko // /system/lib is symlink when this test is executed on host. 95514b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko ASSERT_TRUE(realpath(PATH_TO_LIBC, libc_realpath) == libc_realpath); 95614b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko } 957ef25592f14d23ce6294ea103e9edf894779d141dDmitriy Ivanov 958ef25592f14d23ce6294ea103e9edf894779d141dDmitriy Ivanov ASSERT_STREQ(libc_realpath, info.dli_fname); 959aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov // TODO: add check for dfi_fbase 960aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov ASSERT_STREQ("puts", info.dli_sname); 961aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov ASSERT_EQ(addr, info.dli_saddr); 962aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov#else 963aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov GTEST_LOG_(INFO) << "This test does nothing for glibc. Glibc returns path from ldconfig " 964aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov "for libc.so, which is symlink itself (not a realpath).\n"; 965aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov#endif 966aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov} 967aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov 968e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott HughesTEST(dlfcn, dladdr_invalid) { 9698e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes Dl_info info; 9708e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 9713b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes dlerror(); // Clear any pending errors. 9723b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 9738e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // No symbol corresponding to NULL. 974aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_EQ(dladdr(nullptr, &info), 0); // Zero on error, non-zero on success. 975aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(dlerror() == nullptr); // dladdr(3) doesn't set dlerror(3). 9768e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 9778e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // No symbol corresponding to a stack address. 9788e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_EQ(dladdr(&info, &info), 0); // Zero on error, non-zero on success. 979aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(dlerror() == nullptr); // dladdr(3) doesn't set dlerror(3). 9808e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes} 981124fae9eabd7a25d80dfa8c3b56bed0f0fba16f1Elliott Hughes 982a43e906221a3e9c70a66118a8692cd46f77e144eElliott Hughes// GNU-style ELF hash tables are incompatible with the MIPS ABI. 983a43e906221a3e9c70a66118a8692cd46f77e144eElliott Hughes// MIPS requires .dynsym to be sorted to match the GOT but GNU-style requires sorting by hash code. 984e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott HughesTEST(dlfcn, dlopen_library_with_only_gnu_hash) { 985ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov#if !defined(__mips__) 986124fae9eabd7a25d80dfa8c3b56bed0f0fba16f1Elliott Hughes dlerror(); // Clear any pending errors. 987ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov void* handle = dlopen("libgnu-hash-table-library.so", RTLD_NOW); 988ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 989ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov auto guard = make_scope_guard([&]() { 990ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov dlclose(handle); 991ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov }); 992ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov void* sym = dlsym(handle, "getRandomNumber"); 993ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov ASSERT_TRUE(sym != nullptr) << dlerror(); 994ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov int (*fn)(void); 995ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov fn = reinterpret_cast<int (*)(void)>(sym); 996ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov EXPECT_EQ(4, fn()); 997ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov 998ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov Dl_info dlinfo; 999ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov ASSERT_TRUE(0 != dladdr(reinterpret_cast<void*>(fn), &dlinfo)); 1000ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov 1001ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov ASSERT_TRUE(fn == dlinfo.dli_saddr); 1002ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov ASSERT_STREQ("getRandomNumber", dlinfo.dli_sname); 1003b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov ASSERT_SUBSTR("libgnu-hash-table-library.so", dlinfo.dli_fname); 1004ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov#else 1005ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov GTEST_LOG_(INFO) << "This test does nothing for mips/mips64; mips toolchain does not support '--hash-style=gnu'\n"; 1006a43e906221a3e9c70a66118a8692cd46f77e144eElliott Hughes#endif 1007ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov} 1008e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes 1009b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy IvanovTEST(dlfcn, dlopen_library_with_only_sysv_hash) { 1010b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov void* handle = dlopen("libsysv-hash-table-library.so", RTLD_NOW); 1011b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 1012b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov auto guard = make_scope_guard([&]() { 1013b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov dlclose(handle); 1014b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov }); 1015b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov void* sym = dlsym(handle, "getRandomNumber"); 1016b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov ASSERT_TRUE(sym != nullptr) << dlerror(); 1017b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov int (*fn)(void); 1018b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov fn = reinterpret_cast<int (*)(void)>(sym); 1019b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov EXPECT_EQ(4, fn()); 1020b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov 1021b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov Dl_info dlinfo; 1022b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov ASSERT_TRUE(0 != dladdr(reinterpret_cast<void*>(fn), &dlinfo)); 1023b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov 1024b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov ASSERT_TRUE(fn == dlinfo.dli_saddr); 1025b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov ASSERT_STREQ("getRandomNumber", dlinfo.dli_sname); 1026b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov ASSERT_SUBSTR("libsysv-hash-table-library.so", dlinfo.dli_fname); 1027b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov} 1028b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov 1029e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott HughesTEST(dlfcn, dlopen_bad_flags) { 1030e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes dlerror(); // Clear any pending errors. 1031e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes void* handle; 1032e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes 1033063525c61d24776094d76971f33920e2a2079530Elliott Hughes#if defined(__GLIBC__) 1034e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes // glibc was smart enough not to define RTLD_NOW as 0, so it can detect missing flags. 1035aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov handle = dlopen(nullptr, 0); 1036aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(handle == nullptr); 1037e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes ASSERT_SUBSTR("invalid", dlerror()); 1038e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes#endif 1039e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes 1040aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov handle = dlopen(nullptr, 0xffffffff); 1041aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(handle == nullptr); 1042e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes ASSERT_SUBSTR("invalid", dlerror()); 1043e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes 1044e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes // glibc actually allows you to choose both RTLD_NOW and RTLD_LAZY at the same time, and so do we. 1045aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov handle = dlopen(nullptr, RTLD_NOW|RTLD_LAZY); 1046aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(handle != nullptr); 1047aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_SUBSTR(nullptr, dlerror()); 1048e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes} 1049ebd506c69e12b6dcaf5be94cc8ed1b53af299f9fSergey Melnikov 1050ebd506c69e12b6dcaf5be94cc8ed1b53af299f9fSergey MelnikovTEST(dlfcn, rtld_default_unknown_symbol) { 10512ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes void* addr = dlsym(RTLD_DEFAULT, "ANY_UNKNOWN_SYMBOL_NAME"); 1052aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(addr == nullptr); 1053ebd506c69e12b6dcaf5be94cc8ed1b53af299f9fSergey Melnikov} 1054ebd506c69e12b6dcaf5be94cc8ed1b53af299f9fSergey Melnikov 1055ebd506c69e12b6dcaf5be94cc8ed1b53af299f9fSergey MelnikovTEST(dlfcn, rtld_default_known_symbol) { 10562ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes void* addr = dlsym(RTLD_DEFAULT, "fopen"); 1057aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(addr != nullptr); 10582ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes} 10592ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes 10602ed710976cb0ace31aab565c95a42d4e75623894Elliott HughesTEST(dlfcn, rtld_next_unknown_symbol) { 10612ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes void* addr = dlsym(RTLD_NEXT, "ANY_UNKNOWN_SYMBOL_NAME"); 1062aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(addr == nullptr); 10632ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes} 10642ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes 10652ed710976cb0ace31aab565c95a42d4e75623894Elliott HughesTEST(dlfcn, rtld_next_known_symbol) { 10662ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes void* addr = dlsym(RTLD_NEXT, "fopen"); 1067aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(addr != nullptr); 1068ebd506c69e12b6dcaf5be94cc8ed1b53af299f9fSergey Melnikov} 10697db180919c335287b201e859faa8ee0dbe281cdeDmitriy Ivanov 1070d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov// Check that RTLD_NEXT of a libc symbol works in dlopened library 1071d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry IvanovTEST(dlfcn, rtld_next_from_library) { 1072d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov void* library_with_close = dlopen("libtest_check_rtld_next_from_library.so", RTLD_NOW); 1073d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov ASSERT_TRUE(library_with_close != nullptr) << dlerror(); 1074d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov void* expected_addr = dlsym(RTLD_DEFAULT, "close"); 1075d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov ASSERT_TRUE(expected_addr != nullptr) << dlerror(); 1076d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov typedef void* (*get_libc_close_ptr_fn_t)(); 1077d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov get_libc_close_ptr_fn_t get_libc_close_ptr = 1078d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov reinterpret_cast<get_libc_close_ptr_fn_t>(dlsym(library_with_close, "get_libc_close_ptr")); 1079d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov ASSERT_TRUE(get_libc_close_ptr != nullptr) << dlerror(); 1080d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov ASSERT_EQ(expected_addr, get_libc_close_ptr()); 1081d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov 1082d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov dlclose(library_with_close); 1083d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov} 1084d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov 1085d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov 1086ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy IvanovTEST(dlfcn, dlsym_weak_func) { 1087ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov dlerror(); 1088bfa88bca5ca387d6b3560074050856527cfc7514Dmitriy Ivanov void* handle = dlopen("libtest_dlsym_weak_func.so", RTLD_NOW); 1089aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(handle != nullptr); 1090ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov 1091ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov int (*weak_func)(); 1092ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov weak_func = reinterpret_cast<int (*)()>(dlsym(handle, "weak_func")); 1093aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(weak_func != nullptr) << "dlerror: " << dlerror(); 1094ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov EXPECT_EQ(42, weak_func()); 1095ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov dlclose(handle); 1096ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov} 1097ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov 1098bfa88bca5ca387d6b3560074050856527cfc7514Dmitriy IvanovTEST(dlfcn, dlopen_undefined_weak_func) { 1099cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov void* handle = dlopen("libtest_dlopen_weak_undefined_func.so", RTLD_NOW); 1100cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 1101cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov int (*weak_func)(); 1102cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov weak_func = reinterpret_cast<int (*)()>(dlsym(handle, "use_weak_undefined_func")); 1103cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov ASSERT_TRUE(weak_func != nullptr) << dlerror(); 1104cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov EXPECT_EQ(6551, weak_func()); 1105cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov dlclose(handle); 1106bfa88bca5ca387d6b3560074050856527cfc7514Dmitriy Ivanov} 1107bfa88bca5ca387d6b3560074050856527cfc7514Dmitriy Ivanov 11087db180919c335287b201e859faa8ee0dbe281cdeDmitriy IvanovTEST(dlfcn, dlopen_symlink) { 1109708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov DlfcnSymlink symlink("dlopen_symlink"); 1110708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov const std::string symlink_name = basename(symlink.get_symlink_path().c_str()); 11117db180919c335287b201e859faa8ee0dbe281cdeDmitriy Ivanov void* handle1 = dlopen("libdlext_test.so", RTLD_NOW); 1112708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov void* handle2 = dlopen(symlink_name.c_str(), RTLD_NOW); 1113aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(handle1 != nullptr); 1114aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(handle2 != nullptr); 11157db180919c335287b201e859faa8ee0dbe281cdeDmitriy Ivanov ASSERT_EQ(handle1, handle2); 1116319356e39cc91b4eb94b1974756f1cfc0a137351Dmitriy Ivanov dlclose(handle1); 1117319356e39cc91b4eb94b1974756f1cfc0a137351Dmitriy Ivanov dlclose(handle2); 11187db180919c335287b201e859faa8ee0dbe281cdeDmitriy Ivanov} 1119279a22f96e639e76c801bdb39aee5576f2280fe0Dmitriy Ivanov 1120279a22f96e639e76c801bdb39aee5576f2280fe0Dmitriy Ivanov// libtest_dlopen_from_ctor_main.so depends on 1121279a22f96e639e76c801bdb39aee5576f2280fe0Dmitriy Ivanov// libtest_dlopen_from_ctor.so which has a constructor 1122279a22f96e639e76c801bdb39aee5576f2280fe0Dmitriy Ivanov// that calls dlopen(libc...). This is to test the situation 1123279a22f96e639e76c801bdb39aee5576f2280fe0Dmitriy Ivanov// described in b/7941716. 1124279a22f96e639e76c801bdb39aee5576f2280fe0Dmitriy IvanovTEST(dlfcn, dlopen_dlopen_from_ctor) { 1125279a22f96e639e76c801bdb39aee5576f2280fe0Dmitriy Ivanov#if defined(__BIONIC__) 1126279a22f96e639e76c801bdb39aee5576f2280fe0Dmitriy Ivanov void* handle = dlopen("libtest_dlopen_from_ctor_main.so", RTLD_NOW); 1127279a22f96e639e76c801bdb39aee5576f2280fe0Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 1128279a22f96e639e76c801bdb39aee5576f2280fe0Dmitriy Ivanov dlclose(handle); 1129279a22f96e639e76c801bdb39aee5576f2280fe0Dmitriy Ivanov#else 1130279a22f96e639e76c801bdb39aee5576f2280fe0Dmitriy Ivanov GTEST_LOG_(INFO) << "This test is disabled for glibc (glibc segfaults if you try to call dlopen from a constructor).\n"; 1131279a22f96e639e76c801bdb39aee5576f2280fe0Dmitriy Ivanov#endif 1132279a22f96e639e76c801bdb39aee5576f2280fe0Dmitriy Ivanov} 11332a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov 1134ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanovstatic std::string g_fini_call_order_str; 1135ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanov 1136ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanovstatic void register_fini_call(const char* s) { 1137ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanov g_fini_call_order_str += s; 1138ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanov} 1139ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanov 1140ec90e24d33837e107b45e7c98b2f5fb4bc115a5eDimitry Ivanovstatic void test_init_fini_call_order_for(const char* libname) { 1141ec90e24d33837e107b45e7c98b2f5fb4bc115a5eDimitry Ivanov g_fini_call_order_str.clear(); 1142ec90e24d33837e107b45e7c98b2f5fb4bc115a5eDimitry Ivanov void* handle = dlopen(libname, RTLD_NOW); 1143ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 1144ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanov typedef int (*get_init_order_number_t)(); 1145ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanov get_init_order_number_t get_init_order_number = 1146ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanov reinterpret_cast<get_init_order_number_t>(dlsym(handle, "get_init_order_number")); 1147ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanov ASSERT_EQ(321, get_init_order_number()); 1148ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanov 1149ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanov typedef void (*set_fini_callback_t)(void (*f)(const char*)); 1150ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanov set_fini_callback_t set_fini_callback = 1151ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanov reinterpret_cast<set_fini_callback_t>(dlsym(handle, "set_fini_callback")); 1152ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanov set_fini_callback(register_fini_call); 1153ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanov dlclose(handle); 1154ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanov ASSERT_EQ("(root)(child)(grandchild)", g_fini_call_order_str); 1155ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanov} 1156ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanov 1157ec90e24d33837e107b45e7c98b2f5fb4bc115a5eDimitry IvanovTEST(dlfcn, init_fini_call_order) { 1158ec90e24d33837e107b45e7c98b2f5fb4bc115a5eDimitry Ivanov test_init_fini_call_order_for("libtest_init_fini_order_root.so"); 1159ec90e24d33837e107b45e7c98b2f5fb4bc115a5eDimitry Ivanov test_init_fini_call_order_for("libtest_init_fini_order_root2.so"); 1160ec90e24d33837e107b45e7c98b2f5fb4bc115a5eDimitry Ivanov} 1161ec90e24d33837e107b45e7c98b2f5fb4bc115a5eDimitry Ivanov 11622a815361448d01b0f4e575f507ce31913214c536Dmitriy IvanovTEST(dlfcn, symbol_versioning_use_v1) { 11632a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov void* handle = dlopen("libtest_versioned_uselibv1.so", RTLD_NOW); 11642a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 11652a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov typedef int (*fn_t)(); 11662a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "get_function_version")); 11672a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov ASSERT_TRUE(fn != nullptr) << dlerror(); 11682a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov ASSERT_EQ(1, fn()); 11692a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov dlclose(handle); 11702a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov} 11712a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov 11722a815361448d01b0f4e575f507ce31913214c536Dmitriy IvanovTEST(dlfcn, symbol_versioning_use_v2) { 11732a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov void* handle = dlopen("libtest_versioned_uselibv2.so", RTLD_NOW); 11742a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 11752a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov typedef int (*fn_t)(); 11762a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "get_function_version")); 11772a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov ASSERT_TRUE(fn != nullptr) << dlerror(); 11782a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov ASSERT_EQ(2, fn()); 11792a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov dlclose(handle); 11802a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov} 11812a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov 11822a815361448d01b0f4e575f507ce31913214c536Dmitriy IvanovTEST(dlfcn, symbol_versioning_use_other_v2) { 11832a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov void* handle = dlopen("libtest_versioned_uselibv2_other.so", RTLD_NOW); 11842a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 11852a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov typedef int (*fn_t)(); 11862a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "get_function_version")); 11872a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov ASSERT_TRUE(fn != nullptr) << dlerror(); 11882a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov ASSERT_EQ(20, fn()); 11892a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov dlclose(handle); 11902a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov} 11912a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov 11922a815361448d01b0f4e575f507ce31913214c536Dmitriy IvanovTEST(dlfcn, symbol_versioning_use_other_v3) { 11932a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov void* handle = dlopen("libtest_versioned_uselibv3_other.so", RTLD_NOW); 11942a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 11952a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov typedef int (*fn_t)(); 11962a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "get_function_version")); 11972a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov ASSERT_TRUE(fn != nullptr) << dlerror(); 11982a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov ASSERT_EQ(3, fn()); 11992a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov dlclose(handle); 12002a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov} 12012a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov 12022a815361448d01b0f4e575f507ce31913214c536Dmitriy IvanovTEST(dlfcn, symbol_versioning_default_via_dlsym) { 12032a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov void* handle = dlopen("libtest_versioned_lib.so", RTLD_NOW); 12042a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 12052a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov typedef int (*fn_t)(); 12062a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "versioned_function")); 12072a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov ASSERT_TRUE(fn != nullptr) << dlerror(); 12082a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov ASSERT_EQ(3, fn()); // the default version is 3 12092a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov dlclose(handle); 12102a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov} 12112a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov 12129cf99cbad89c8495828788ce693a99ced434f66fDimitry IvanovTEST(dlfcn, dlvsym_smoke) { 12139cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov void* handle = dlopen("libtest_versioned_lib.so", RTLD_NOW); 12149cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 12159cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov typedef int (*fn_t)(); 12169cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov 12179cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov { 12189cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov fn_t fn = reinterpret_cast<fn_t>(dlvsym(handle, "versioned_function", "nonversion")); 12199cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov ASSERT_TRUE(fn == nullptr); 12209cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov ASSERT_SUBSTR("undefined symbol: versioned_function, version nonversion", dlerror()); 12219cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov } 12229cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov 12239cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov { 12249cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov fn_t fn = reinterpret_cast<fn_t>(dlvsym(handle, "versioned_function", "TESTLIB_V2")); 12259cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov ASSERT_TRUE(fn != nullptr) << dlerror(); 12269cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov ASSERT_EQ(2, fn()); 12279cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov } 12289cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov 12299cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov dlclose(handle); 12309cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov} 12319cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov 12322a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov// This preempts the implementation from libtest_versioned_lib.so 12332a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanovextern "C" int version_zero_function() { 12342a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov return 0; 12352a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov} 12362a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov 12372a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov// This preempts the implementation from libtest_versioned_uselibv*.so 12382a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanovextern "C" int version_zero_function2() { 12392a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov return 0; 12402a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov} 12416865082ca6d887766c6651ed2d079dca56a99d32Evgenii Stepanov 12426f2d3104c82f81c1f0123a3cfb25ae670841d0baLazar TrsicTEST(dlfcn, dt_runpath_smoke) { 12436865082ca6d887766c6651ed2d079dca56a99d32Evgenii Stepanov void* handle = dlopen("libtest_dt_runpath_d.so", RTLD_NOW); 12446865082ca6d887766c6651ed2d079dca56a99d32Evgenii Stepanov ASSERT_TRUE(handle != nullptr) << dlerror(); 12456865082ca6d887766c6651ed2d079dca56a99d32Evgenii Stepanov 12466865082ca6d887766c6651ed2d079dca56a99d32Evgenii Stepanov typedef void *(* dlopen_b_fn)(); 12476865082ca6d887766c6651ed2d079dca56a99d32Evgenii Stepanov dlopen_b_fn fn = (dlopen_b_fn)dlsym(handle, "dlopen_b"); 12486865082ca6d887766c6651ed2d079dca56a99d32Evgenii Stepanov ASSERT_TRUE(fn != nullptr) << dlerror(); 12496865082ca6d887766c6651ed2d079dca56a99d32Evgenii Stepanov 12506865082ca6d887766c6651ed2d079dca56a99d32Evgenii Stepanov void *p = fn(); 12510cdef7e7f3c6837b56a969120d9098463d1df8d8Evgenii Stepanov ASSERT_TRUE(p != nullptr); 12526865082ca6d887766c6651ed2d079dca56a99d32Evgenii Stepanov 12536865082ca6d887766c6651ed2d079dca56a99d32Evgenii Stepanov dlclose(handle); 12546865082ca6d887766c6651ed2d079dca56a99d32Evgenii Stepanov} 12556f2d3104c82f81c1f0123a3cfb25ae670841d0baLazar Trsic 1256a36e59bb9973aaae2e3487e0bfadd1f79814097eDimitry Ivanov// Bionic specific tests 1257a36e59bb9973aaae2e3487e0bfadd1f79814097eDimitry Ivanov#if defined(__BIONIC__) 1258a36e59bb9973aaae2e3487e0bfadd1f79814097eDimitry Ivanov 1259fc32dcb128efe35442830e2dcfa378f1d50fef1cDimitry Ivanov#if defined(__arm__) 1260ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanovconst llvm::ELF::Elf32_Dyn* to_dynamic_table(const char* p) { 1261ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov return reinterpret_cast<const llvm::ELF::Elf32_Dyn*>(p); 1262ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov} 1263ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov 1264ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov// Duplicate these definitions here because they are android specific 1265ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov// note that we cannot include <elf.h> because #defines conflict with 1266ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov// enum names provided by LLVM. 1267ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov#define DT_ANDROID_REL (llvm::ELF::DT_LOOS + 2) 1268ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov#define DT_ANDROID_RELA (llvm::ELF::DT_LOOS + 4) 1269ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov 1270ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanovtemplate<typename ELFT> 1271ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanovvoid validate_compatibility_of_native_library(const std::string& path, ELFT* elf) { 1272ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov bool has_elf_hash = false; 1273ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov bool has_android_rel = false; 1274ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov bool has_rel = false; 1275ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov // Find dynamic section and check that DT_HASH and there is no DT_ANDROID_REL 1276ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov for (auto it = elf->section_begin(); it != elf->section_end(); ++it) { 1277ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov const llvm::object::ELFSectionRef& section_ref = *it; 1278ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov if (section_ref.getType() == llvm::ELF::SHT_DYNAMIC) { 1279ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov llvm::StringRef data; 1280ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov ASSERT_TRUE(!it->getContents(data)) << "unable to get SHT_DYNAMIC section data"; 1281ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov for (auto d = to_dynamic_table(data.data()); d->d_tag != llvm::ELF::DT_NULL; ++d) { 1282ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov if (d->d_tag == llvm::ELF::DT_HASH) { 1283ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov has_elf_hash = true; 1284ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov } else if (d->d_tag == DT_ANDROID_REL || d->d_tag == DT_ANDROID_RELA) { 1285ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov has_android_rel = true; 1286ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov } else if (d->d_tag == llvm::ELF::DT_REL || d->d_tag == llvm::ELF::DT_RELA) { 1287ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov has_rel = true; 1288ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov } 1289ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov } 1290ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov 1291ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov break; 1292ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov } 1293ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov } 1294ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov 1295ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov ASSERT_TRUE(has_elf_hash) << path.c_str() << ": missing elf hash (DT_HASH)"; 1296ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov ASSERT_TRUE(!has_android_rel) << path.c_str() << ": has packed relocations"; 1297ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov ASSERT_TRUE(has_rel) << path.c_str() << ": missing DT_REL/DT_RELA"; 1298ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov} 1299ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov 1300ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanovvoid validate_compatibility_of_native_library(const char* soname) { 130114b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko // On the systems with emulation system libraries would be of different 130214b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko // architecture. Try to use alternate paths first. 130314b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko std::string path = std::string(ALTERNATE_PATH_TO_SYSTEM_LIB) + soname; 1304ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov auto binary_or_error = llvm::object::createBinary(path); 130514b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko if (!binary_or_error) { 130614b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko path = std::string(PATH_TO_SYSTEM_LIB) + soname; 130714b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko binary_or_error = llvm::object::createBinary(path); 130814b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko } 1309ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov ASSERT_FALSE(!binary_or_error); 1310ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov 1311ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov llvm::object::Binary* binary = binary_or_error.get().getBinary(); 1312ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov 1313ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov auto obj = llvm::dyn_cast<llvm::object::ObjectFile>(binary); 1314ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov ASSERT_TRUE(obj != nullptr); 1315ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov 1316ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov auto elf = llvm::dyn_cast<llvm::object::ELF32LEObjectFile>(obj); 1317ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov 1318ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov ASSERT_TRUE(elf != nullptr); 1319ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov 1320ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov validate_compatibility_of_native_library(path, elf); 1321ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov} 1322ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov 1323fc32dcb128efe35442830e2dcfa378f1d50fef1cDimitry Ivanov// This is a test for app compatibility workaround for arm apps 1324ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov// affected by http://b/24465209 1325ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry IvanovTEST(dlext, compat_elf_hash_and_relocation_tables) { 1326ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov validate_compatibility_of_native_library("libc.so"); 1327ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov validate_compatibility_of_native_library("liblog.so"); 1328ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov validate_compatibility_of_native_library("libstdc++.so"); 1329ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov validate_compatibility_of_native_library("libdl.so"); 1330ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov validate_compatibility_of_native_library("libm.so"); 1331ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov validate_compatibility_of_native_library("libz.so"); 1332ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov validate_compatibility_of_native_library("libjnigraphics.so"); 1333ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov} 1334ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov 1335fc32dcb128efe35442830e2dcfa378f1d50fef1cDimitry Ivanov#endif // defined(__arm__) 1336ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov 13376f2d3104c82f81c1f0123a3cfb25ae670841d0baLazar TrsicTEST(dlfcn, dt_runpath_absolute_path) { 1338d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov std::string libpath = get_testlib_root() + "/libtest_dt_runpath_d.so"; 1339a36e59bb9973aaae2e3487e0bfadd1f79814097eDimitry Ivanov void* handle = dlopen(libpath.c_str(), RTLD_NOW); 13406f2d3104c82f81c1f0123a3cfb25ae670841d0baLazar Trsic ASSERT_TRUE(handle != nullptr) << dlerror(); 13416f2d3104c82f81c1f0123a3cfb25ae670841d0baLazar Trsic 13426f2d3104c82f81c1f0123a3cfb25ae670841d0baLazar Trsic typedef void *(* dlopen_b_fn)(); 13436f2d3104c82f81c1f0123a3cfb25ae670841d0baLazar Trsic dlopen_b_fn fn = (dlopen_b_fn)dlsym(handle, "dlopen_b"); 13446f2d3104c82f81c1f0123a3cfb25ae670841d0baLazar Trsic ASSERT_TRUE(fn != nullptr) << dlerror(); 13456f2d3104c82f81c1f0123a3cfb25ae670841d0baLazar Trsic 13466f2d3104c82f81c1f0123a3cfb25ae670841d0baLazar Trsic void *p = fn(); 13476f2d3104c82f81c1f0123a3cfb25ae670841d0baLazar Trsic ASSERT_TRUE(p != nullptr); 13486f2d3104c82f81c1f0123a3cfb25ae670841d0baLazar Trsic 13496f2d3104c82f81c1f0123a3cfb25ae670841d0baLazar Trsic dlclose(handle); 13506f2d3104c82f81c1f0123a3cfb25ae670841d0baLazar Trsic} 13519700babc051f5839b4fc861587d63bf06bab6324Dimitry Ivanov 13529700babc051f5839b4fc861587d63bf06bab6324Dimitry IvanovTEST(dlfcn, dlopen_invalid_rw_load_segment) { 1353d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov const std::string libpath = get_testlib_root() + 1354927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov "/" + kPrebuiltElfDir + 1355927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov "/libtest_invalid-rw_load_segment.so"; 13569700babc051f5839b4fc861587d63bf06bab6324Dimitry Ivanov void* handle = dlopen(libpath.c_str(), RTLD_NOW); 13579700babc051f5839b4fc861587d63bf06bab6324Dimitry Ivanov ASSERT_TRUE(handle == nullptr); 13589700babc051f5839b4fc861587d63bf06bab6324Dimitry Ivanov std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\": W + E load segments are not allowed"; 13599700babc051f5839b4fc861587d63bf06bab6324Dimitry Ivanov ASSERT_STREQ(expected_dlerror.c_str(), dlerror()); 13609700babc051f5839b4fc861587d63bf06bab6324Dimitry Ivanov} 1361972e3d0787cf177450cdc1b52e177c747b94cabaDimitry Ivanov 1362972e3d0787cf177450cdc1b52e177c747b94cabaDimitry IvanovTEST(dlfcn, dlopen_invalid_unaligned_shdr_offset) { 1363d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov const std::string libpath = get_testlib_root() + 1364927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov "/" + kPrebuiltElfDir + 1365927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov "/libtest_invalid-unaligned_shdr_offset.so"; 1366927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov 1367972e3d0787cf177450cdc1b52e177c747b94cabaDimitry Ivanov void* handle = dlopen(libpath.c_str(), RTLD_NOW); 1368972e3d0787cf177450cdc1b52e177c747b94cabaDimitry Ivanov ASSERT_TRUE(handle == nullptr); 1369972e3d0787cf177450cdc1b52e177c747b94cabaDimitry Ivanov std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\" has invalid shdr offset/size: "; 1370972e3d0787cf177450cdc1b52e177c747b94cabaDimitry Ivanov ASSERT_SUBSTR(expected_dlerror.c_str(), dlerror()); 1371972e3d0787cf177450cdc1b52e177c747b94cabaDimitry Ivanov} 1372972e3d0787cf177450cdc1b52e177c747b94cabaDimitry Ivanov 1373cb86c3128f5e59348d91f2edfa2de908d69cd384Dimitry IvanovTEST(dlfcn, dlopen_invalid_zero_shentsize) { 1374d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov const std::string libpath = get_testlib_root() + 1375927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov "/" + kPrebuiltElfDir + 1376927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov "/libtest_invalid-zero_shentsize.so"; 1377927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov 1378cb86c3128f5e59348d91f2edfa2de908d69cd384Dimitry Ivanov void* handle = dlopen(libpath.c_str(), RTLD_NOW); 1379cb86c3128f5e59348d91f2edfa2de908d69cd384Dimitry Ivanov ASSERT_TRUE(handle == nullptr); 1380cb86c3128f5e59348d91f2edfa2de908d69cd384Dimitry Ivanov std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\" has unsupported e_shentsize: 0x0 (expected 0x"; 1381cb86c3128f5e59348d91f2edfa2de908d69cd384Dimitry Ivanov ASSERT_SUBSTR(expected_dlerror.c_str(), dlerror()); 1382cb86c3128f5e59348d91f2edfa2de908d69cd384Dimitry Ivanov} 1383cb86c3128f5e59348d91f2edfa2de908d69cd384Dimitry Ivanov 1384c9a95613a95b1a275ff897594abb89786ae387edDimitry IvanovTEST(dlfcn, dlopen_invalid_zero_shstrndx) { 1385d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov const std::string libpath = get_testlib_root() + 1386927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov "/" + kPrebuiltElfDir + 1387927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov "/libtest_invalid-zero_shstrndx.so"; 1388927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov 1389c9a95613a95b1a275ff897594abb89786ae387edDimitry Ivanov void* handle = dlopen(libpath.c_str(), RTLD_NOW); 1390c9a95613a95b1a275ff897594abb89786ae387edDimitry Ivanov ASSERT_TRUE(handle == nullptr); 1391c9a95613a95b1a275ff897594abb89786ae387edDimitry Ivanov std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\" has invalid e_shstrndx"; 1392c9a95613a95b1a275ff897594abb89786ae387edDimitry Ivanov ASSERT_STREQ(expected_dlerror.c_str(), dlerror()); 1393c9a95613a95b1a275ff897594abb89786ae387edDimitry Ivanov} 1394c9a95613a95b1a275ff897594abb89786ae387edDimitry Ivanov 13958bdf70e6e481d4ff0c1097f738d8e857a43c1b16Dimitry IvanovTEST(dlfcn, dlopen_invalid_empty_shdr_table) { 1396d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov const std::string libpath = get_testlib_root() + 1397927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov "/" + kPrebuiltElfDir + 1398927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov "/libtest_invalid-empty_shdr_table.so"; 1399927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov 14008bdf70e6e481d4ff0c1097f738d8e857a43c1b16Dimitry Ivanov void* handle = dlopen(libpath.c_str(), RTLD_NOW); 14018bdf70e6e481d4ff0c1097f738d8e857a43c1b16Dimitry Ivanov ASSERT_TRUE(handle == nullptr); 14028bdf70e6e481d4ff0c1097f738d8e857a43c1b16Dimitry Ivanov std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\" has no section headers"; 14038bdf70e6e481d4ff0c1097f738d8e857a43c1b16Dimitry Ivanov ASSERT_STREQ(expected_dlerror.c_str(), dlerror()); 14048bdf70e6e481d4ff0c1097f738d8e857a43c1b16Dimitry Ivanov} 14058bdf70e6e481d4ff0c1097f738d8e857a43c1b16Dimitry Ivanov 140646230445172d3cd72c38102d57f5a1b725c80367Dimitry IvanovTEST(dlfcn, dlopen_invalid_zero_shdr_table_offset) { 1407d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov const std::string libpath = get_testlib_root() + 1408927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov "/" + kPrebuiltElfDir + 1409927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov "/libtest_invalid-zero_shdr_table_offset.so"; 1410927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov 141146230445172d3cd72c38102d57f5a1b725c80367Dimitry Ivanov void* handle = dlopen(libpath.c_str(), RTLD_NOW); 141246230445172d3cd72c38102d57f5a1b725c80367Dimitry Ivanov ASSERT_TRUE(handle == nullptr); 141346230445172d3cd72c38102d57f5a1b725c80367Dimitry Ivanov std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\" has invalid shdr offset/size: 0/"; 141446230445172d3cd72c38102d57f5a1b725c80367Dimitry Ivanov ASSERT_SUBSTR(expected_dlerror.c_str(), dlerror()); 141546230445172d3cd72c38102d57f5a1b725c80367Dimitry Ivanov} 141646230445172d3cd72c38102d57f5a1b725c80367Dimitry Ivanov 1417559583469cd6425cdf3f63bcfc453d7d885ce131Dimitry IvanovTEST(dlfcn, dlopen_invalid_zero_shdr_table_content) { 1418d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov const std::string libpath = get_testlib_root() + 1419927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov "/" + kPrebuiltElfDir + 1420927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov "/libtest_invalid-zero_shdr_table_content.so"; 1421927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov 1422559583469cd6425cdf3f63bcfc453d7d885ce131Dimitry Ivanov void* handle = dlopen(libpath.c_str(), RTLD_NOW); 1423559583469cd6425cdf3f63bcfc453d7d885ce131Dimitry Ivanov ASSERT_TRUE(handle == nullptr); 1424559583469cd6425cdf3f63bcfc453d7d885ce131Dimitry Ivanov std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\" .dynamic section header was not found"; 1425559583469cd6425cdf3f63bcfc453d7d885ce131Dimitry Ivanov ASSERT_SUBSTR(expected_dlerror.c_str(), dlerror()); 1426559583469cd6425cdf3f63bcfc453d7d885ce131Dimitry Ivanov} 1427559583469cd6425cdf3f63bcfc453d7d885ce131Dimitry Ivanov 1428816676e70da0e00761b0d23f512ea3571211b3aeDimitry IvanovTEST(dlfcn, dlopen_invalid_textrels) { 1429d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov const std::string libpath = get_testlib_root() + 1430816676e70da0e00761b0d23f512ea3571211b3aeDimitry Ivanov "/" + kPrebuiltElfDir + 1431816676e70da0e00761b0d23f512ea3571211b3aeDimitry Ivanov "/libtest_invalid-textrels.so"; 1432816676e70da0e00761b0d23f512ea3571211b3aeDimitry Ivanov 1433816676e70da0e00761b0d23f512ea3571211b3aeDimitry Ivanov void* handle = dlopen(libpath.c_str(), RTLD_NOW); 1434816676e70da0e00761b0d23f512ea3571211b3aeDimitry Ivanov ASSERT_TRUE(handle == nullptr); 1435816676e70da0e00761b0d23f512ea3571211b3aeDimitry Ivanov std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\" has text relocations"; 1436816676e70da0e00761b0d23f512ea3571211b3aeDimitry Ivanov ASSERT_SUBSTR(expected_dlerror.c_str(), dlerror()); 1437816676e70da0e00761b0d23f512ea3571211b3aeDimitry Ivanov} 1438816676e70da0e00761b0d23f512ea3571211b3aeDimitry Ivanov 1439816676e70da0e00761b0d23f512ea3571211b3aeDimitry IvanovTEST(dlfcn, dlopen_invalid_textrels2) { 1440d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov const std::string libpath = get_testlib_root() + 1441816676e70da0e00761b0d23f512ea3571211b3aeDimitry Ivanov "/" + kPrebuiltElfDir + 1442816676e70da0e00761b0d23f512ea3571211b3aeDimitry Ivanov "/libtest_invalid-textrels2.so"; 1443816676e70da0e00761b0d23f512ea3571211b3aeDimitry Ivanov 1444816676e70da0e00761b0d23f512ea3571211b3aeDimitry Ivanov void* handle = dlopen(libpath.c_str(), RTLD_NOW); 1445816676e70da0e00761b0d23f512ea3571211b3aeDimitry Ivanov ASSERT_TRUE(handle == nullptr); 1446816676e70da0e00761b0d23f512ea3571211b3aeDimitry Ivanov std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\" has text relocations"; 1447816676e70da0e00761b0d23f512ea3571211b3aeDimitry Ivanov ASSERT_SUBSTR(expected_dlerror.c_str(), dlerror()); 1448816676e70da0e00761b0d23f512ea3571211b3aeDimitry Ivanov} 1449816676e70da0e00761b0d23f512ea3571211b3aeDimitry Ivanov 14509700babc051f5839b4fc861587d63bf06bab6324Dimitry Ivanov#endif 1451