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> 24b9555a9251467bc2d0b05a4e2f011531c1d3bd4adimitry#if __has_include(<sys/auxv.h>) 25b9555a9251467bc2d0b05a4e2f011531c1d3bd4adimitry#include <sys/auxv.h> 26b9555a9251467bc2d0b05a4e2f011531c1d3bd4adimitry#endif 27109040c868230d2f37c2f3964c6b62f63ff30c6cdimitry#include <sys/user.h> 288e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 298e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes#include <string> 30c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov#include <thread> 31acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao 32b8ab61804cec48e4ca585f4508fb1b7c6c5a04c5Tom Cherry#include <android-base/scopeguard.h> 33b8ab61804cec48e4ca585f4508fb1b7c6c5a04c5Tom Cherry 34927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov#include "gtest_globals.h" 35708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov#include "dlfcn_symlink_support.h" 36aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov#include "utils.h" 37aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov 38ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov#if defined(__BIONIC__) && (defined(__arm__) || defined(__i386__)) 39ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov#pragma clang diagnostic push 40ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov#pragma clang diagnostic ignored "-Wunused-parameter" 41ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov 42ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov#include <llvm/ADT/StringRef.h> 43ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov#include <llvm/Object/Binary.h> 44ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov#include <llvm/Object/ELFObjectFile.h> 45ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov#include <llvm/Object/ObjectFile.h> 46ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov 47ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov#pragma clang diagnostic pop 48ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov#endif // defined(__ANDROID__) && (defined(__arm__) || defined(__i386__)) 49ac4bd2f79316e8ee79e9a69463e5d12d0f792aadDimitry Ivanov 503b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes#define ASSERT_SUBSTR(needle, haystack) \ 513b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_PRED_FORMAT2(::testing::IsSubstring, needle, haystack) 523b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 53aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov 541728b2396591853345507a063ed6075dfd251706Elliott Hughesstatic bool g_called = false; 55acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhaoextern "C" void DlSymTestFunction() { 561728b2396591853345507a063ed6075dfd251706Elliott Hughes g_called = true; 57acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao} 58acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao 59f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanovstatic int g_ctor_function_called = 0; 60554374693408cd7c74d0cae596fca7349661edeaDimitry Ivanovstatic int g_ctor_argc = 0; 61554374693408cd7c74d0cae596fca7349661edeaDimitry Ivanovstatic char** g_ctor_argv = reinterpret_cast<char**>(0xDEADBEEF); 62554374693408cd7c74d0cae596fca7349661edeaDimitry Ivanovstatic char** g_ctor_envp = g_ctor_envp; 63f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanov 64554374693408cd7c74d0cae596fca7349661edeaDimitry Ivanovextern "C" void ctor_function(int argc, char** argv, char** envp) __attribute__ ((constructor)); 65f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanov 66554374693408cd7c74d0cae596fca7349661edeaDimitry Ivanovextern "C" void ctor_function(int argc, char** argv, char** envp) { 67f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanov g_ctor_function_called = 17; 68554374693408cd7c74d0cae596fca7349661edeaDimitry Ivanov g_ctor_argc = argc; 69554374693408cd7c74d0cae596fca7349661edeaDimitry Ivanov g_ctor_argv = argv; 70554374693408cd7c74d0cae596fca7349661edeaDimitry Ivanov g_ctor_envp = envp; 71f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanov} 72f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanov 73f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy IvanovTEST(dlfcn, ctor_function_call) { 74f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanov ASSERT_EQ(17, g_ctor_function_called); 75554374693408cd7c74d0cae596fca7349661edeaDimitry Ivanov ASSERT_TRUE(g_ctor_argc = get_argc()); 76554374693408cd7c74d0cae596fca7349661edeaDimitry Ivanov ASSERT_TRUE(g_ctor_argv = get_argv()); 77554374693408cd7c74d0cae596fca7349661edeaDimitry Ivanov ASSERT_TRUE(g_ctor_envp = get_envp()); 78f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanov} 79f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanov 8076ac1acdacc045cf1e56504e011dca68137dcd61Dmitriy IvanovTEST(dlfcn, dlsym_in_executable) { 813b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes dlerror(); // Clear any pending errors. 82aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov void* self = dlopen(nullptr, RTLD_NOW); 83aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(self != nullptr); 84aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(dlerror() == nullptr); 85acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao 86acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao void* sym = dlsym(self, "DlSymTestFunction"); 87aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(sym != nullptr); 88acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao 89acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao void (*function)() = reinterpret_cast<void(*)()>(sym); 90acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao 911728b2396591853345507a063ed6075dfd251706Elliott Hughes g_called = false; 92acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao function(); 931728b2396591853345507a063ed6075dfd251706Elliott Hughes ASSERT_TRUE(g_called); 941a6961650c82168864afe040dbdc05977db701dfElliott Hughes 951a6961650c82168864afe040dbdc05977db701dfElliott Hughes ASSERT_EQ(0, dlclose(self)); 96acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao} 978e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 9876ac1acdacc045cf1e56504e011dca68137dcd61Dmitriy IvanovTEST(dlfcn, dlsym_from_sofile) { 9976ac1acdacc045cf1e56504e011dca68137dcd61Dmitriy Ivanov void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_LAZY | RTLD_LOCAL); 10076ac1acdacc045cf1e56504e011dca68137dcd61Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 10176ac1acdacc045cf1e56504e011dca68137dcd61Dmitriy Ivanov 102697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov // check that we can't find '_test_dlsym_symbol' via dlsym(RTLD_DEFAULT) 10376ac1acdacc045cf1e56504e011dca68137dcd61Dmitriy Ivanov void* symbol = dlsym(RTLD_DEFAULT, "test_dlsym_symbol"); 10476ac1acdacc045cf1e56504e011dca68137dcd61Dmitriy Ivanov ASSERT_TRUE(symbol == nullptr); 10576ac1acdacc045cf1e56504e011dca68137dcd61Dmitriy Ivanov ASSERT_SUBSTR("undefined symbol: test_dlsym_symbol", dlerror()); 10676ac1acdacc045cf1e56504e011dca68137dcd61Dmitriy Ivanov 10776ac1acdacc045cf1e56504e011dca68137dcd61Dmitriy Ivanov typedef int* (*fn_t)(); 108697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov fn_t lookup_dlsym_symbol_using_RTLD_DEFAULT = 109697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol_using_RTLD_DEFAULT")); 110697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_TRUE(lookup_dlsym_symbol_using_RTLD_DEFAULT != nullptr) << dlerror(); 11176ac1acdacc045cf1e56504e011dca68137dcd61Dmitriy Ivanov 112697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov int* ptr = lookup_dlsym_symbol_using_RTLD_DEFAULT(); 113697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_TRUE(ptr != nullptr) << dlerror(); 114697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_EQ(42, *ptr); 115697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov 116697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov fn_t lookup_dlsym_symbol2_using_RTLD_DEFAULT = 117697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol2_using_RTLD_DEFAULT")); 118697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_TRUE(lookup_dlsym_symbol2_using_RTLD_DEFAULT != nullptr) << dlerror(); 119697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov 120697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ptr = lookup_dlsym_symbol2_using_RTLD_DEFAULT(); 121697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_TRUE(ptr != nullptr) << dlerror(); 122697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_EQ(44, *ptr); 123697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov 124697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov fn_t lookup_dlsym_symbol_using_RTLD_NEXT = 125697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol_using_RTLD_NEXT")); 126697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_TRUE(lookup_dlsym_symbol_using_RTLD_NEXT != nullptr) << dlerror(); 127697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov 128697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ptr = lookup_dlsym_symbol_using_RTLD_NEXT(); 129697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_TRUE(ptr != nullptr) << dlerror(); 130697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_EQ(43, *ptr); 131697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov 132697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov dlclose(handle); 133697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov} 134697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov 135697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy IvanovTEST(dlfcn, dlsym_from_sofile_with_preload) { 136697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov void* preload = dlopen("libtest_dlsym_from_this_grandchild.so", RTLD_NOW | RTLD_LOCAL); 137697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_TRUE(preload != nullptr) << dlerror(); 138697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov 139697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_NOW | RTLD_LOCAL); 140697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 141697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov 142697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov // check that we can't find '_test_dlsym_symbol' via dlsym(RTLD_DEFAULT) 143697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov void* symbol = dlsym(RTLD_DEFAULT, "test_dlsym_symbol"); 144697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_TRUE(symbol == nullptr); 145697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_SUBSTR("undefined symbol: test_dlsym_symbol", dlerror()); 146697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov 147697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov typedef int* (*fn_t)(); 148697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov fn_t lookup_dlsym_symbol_using_RTLD_DEFAULT = 149697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol_using_RTLD_DEFAULT")); 150697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_TRUE(lookup_dlsym_symbol_using_RTLD_DEFAULT != nullptr) << dlerror(); 15176ac1acdacc045cf1e56504e011dca68137dcd61Dmitriy Ivanov 152697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov int* ptr = lookup_dlsym_symbol_using_RTLD_DEFAULT(); 15376ac1acdacc045cf1e56504e011dca68137dcd61Dmitriy Ivanov ASSERT_TRUE(ptr != nullptr) << dlerror(); 15476ac1acdacc045cf1e56504e011dca68137dcd61Dmitriy Ivanov ASSERT_EQ(42, *ptr); 15576ac1acdacc045cf1e56504e011dca68137dcd61Dmitriy Ivanov 156697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov fn_t lookup_dlsym_symbol2_using_RTLD_DEFAULT = 157697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol2_using_RTLD_DEFAULT")); 158697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_TRUE(lookup_dlsym_symbol2_using_RTLD_DEFAULT != nullptr) << dlerror(); 159697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov 160697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ptr = lookup_dlsym_symbol2_using_RTLD_DEFAULT(); 161697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_TRUE(ptr != nullptr) << dlerror(); 162697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_EQ(44, *ptr); 163697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov 164697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov fn_t lookup_dlsym_symbol_using_RTLD_NEXT = 165697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol_using_RTLD_NEXT")); 166697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_TRUE(lookup_dlsym_symbol_using_RTLD_NEXT != nullptr) << dlerror(); 167697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov 168697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ptr = lookup_dlsym_symbol_using_RTLD_NEXT(); 169697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_TRUE(ptr != nullptr) << dlerror(); 170697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov ASSERT_EQ(43, *ptr); 171697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov 17276ac1acdacc045cf1e56504e011dca68137dcd61Dmitriy Ivanov dlclose(handle); 173697bd9fd38ab078a117ad9a5777cf286c467b9b9Dmitriy Ivanov dlclose(preload); 17476ac1acdacc045cf1e56504e011dca68137dcd61Dmitriy Ivanov} 17576ac1acdacc045cf1e56504e011dca68137dcd61Dmitriy Ivanov 176f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy IvanovTEST(dlfcn, dlsym_handle_global_sym) { 177f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov // check that we do not look into global group 178f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov // when looking up symbol by handle 179f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov void* handle = dlopen("libtest_empty.so", RTLD_NOW); 180f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov dlopen("libtest_with_dependency.so", RTLD_NOW | RTLD_GLOBAL); 181f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov void* sym = dlsym(handle, "getRandomNumber"); 182f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov ASSERT_TRUE(sym == nullptr); 183f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov ASSERT_SUBSTR("undefined symbol: getRandomNumber", dlerror()); 184f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov 185f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov sym = dlsym(handle, "DlSymTestFunction"); 186f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov ASSERT_TRUE(sym == nullptr); 187f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov ASSERT_SUBSTR("undefined symbol: DlSymTestFunction", dlerror()); 188f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov dlclose(handle); 189f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov} 190f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov 191d5b578ac15330d7a872c198427628b723e0cc1cbDimitry IvanovTEST(dlfcn, dlsym_handle_empty_symbol) { 192d5b578ac15330d7a872c198427628b723e0cc1cbDimitry Ivanov // check that dlsym of an empty symbol fails (see http://b/33530622) 193d5b578ac15330d7a872c198427628b723e0cc1cbDimitry Ivanov void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_NOW); 194d5b578ac15330d7a872c198427628b723e0cc1cbDimitry Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 195d5b578ac15330d7a872c198427628b723e0cc1cbDimitry Ivanov void* sym = dlsym(handle, ""); 196d5b578ac15330d7a872c198427628b723e0cc1cbDimitry Ivanov ASSERT_TRUE(sym == nullptr); 197d5b578ac15330d7a872c198427628b723e0cc1cbDimitry Ivanov ASSERT_SUBSTR("undefined symbol: ", dlerror()); 198d5b578ac15330d7a872c198427628b723e0cc1cbDimitry Ivanov dlclose(handle); 199d5b578ac15330d7a872c198427628b723e0cc1cbDimitry Ivanov} 200d5b578ac15330d7a872c198427628b723e0cc1cbDimitry Ivanov 201aa0f2bdbc22d4b7aec5d3f8f5f01eaeaa13414c2Dmitriy IvanovTEST(dlfcn, dlsym_with_dependencies) { 202aa0f2bdbc22d4b7aec5d3f8f5f01eaeaa13414c2Dmitriy Ivanov void* handle = dlopen("libtest_with_dependency.so", RTLD_NOW); 203f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov ASSERT_TRUE(handle != nullptr); 204aa0f2bdbc22d4b7aec5d3f8f5f01eaeaa13414c2Dmitriy Ivanov dlerror(); 205aa0f2bdbc22d4b7aec5d3f8f5f01eaeaa13414c2Dmitriy Ivanov // This symbol is in DT_NEEDED library. 206aa0f2bdbc22d4b7aec5d3f8f5f01eaeaa13414c2Dmitriy Ivanov void* sym = dlsym(handle, "getRandomNumber"); 207f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov ASSERT_TRUE(sym != nullptr) << dlerror(); 208aa0f2bdbc22d4b7aec5d3f8f5f01eaeaa13414c2Dmitriy Ivanov int (*fn)(void); 209aa0f2bdbc22d4b7aec5d3f8f5f01eaeaa13414c2Dmitriy Ivanov fn = reinterpret_cast<int (*)(void)>(sym); 210aa0f2bdbc22d4b7aec5d3f8f5f01eaeaa13414c2Dmitriy Ivanov EXPECT_EQ(4, fn()); 211aa0f2bdbc22d4b7aec5d3f8f5f01eaeaa13414c2Dmitriy Ivanov dlclose(handle); 212aa0f2bdbc22d4b7aec5d3f8f5f01eaeaa13414c2Dmitriy Ivanov} 213aa0f2bdbc22d4b7aec5d3f8f5f01eaeaa13414c2Dmitriy Ivanov 214b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy IvanovTEST(dlfcn, dlopen_noload) { 215b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov void* handle = dlopen("libtest_simple.so", RTLD_NOW | RTLD_NOLOAD); 216aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(handle == nullptr); 217b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov handle = dlopen("libtest_simple.so", RTLD_NOW); 218b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov void* handle2 = dlopen("libtest_simple.so", RTLD_NOW | RTLD_NOLOAD); 219aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(handle != nullptr); 220aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(handle2 != nullptr); 221b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov ASSERT_TRUE(handle == handle2); 222b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov ASSERT_EQ(0, dlclose(handle)); 223b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov ASSERT_EQ(0, dlclose(handle2)); 224b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov} 225b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov 226618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy IvanovTEST(dlfcn, dlopen_by_soname) { 227618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov static const char* soname = "libdlext_test_soname.so"; 228618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov static const char* filename = "libdlext_test_different_soname.so"; 229618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov // 1. Make sure there is no library with soname in default search path 230618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov void* handle = dlopen(soname, RTLD_NOW); 231618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov ASSERT_TRUE(handle == nullptr); 232618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov 233618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov // 2. Load a library using filename 234618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov handle = dlopen(filename, RTLD_NOW); 235618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 236618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov 237618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov // 3. Find library by soname 238618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov void* handle_soname = dlopen(soname, RTLD_NOW | RTLD_NOLOAD); 239618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov ASSERT_TRUE(handle_soname != nullptr) << dlerror(); 240618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov ASSERT_EQ(handle, handle_soname); 241618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov 242618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov // 4. RTLD_NOLOAD should still work with filename 243618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov void* handle_filename = dlopen(filename, RTLD_NOW | RTLD_NOLOAD); 244618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov ASSERT_TRUE(handle_filename != nullptr) << dlerror(); 245618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov ASSERT_EQ(handle, handle_filename); 246618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov 247618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov dlclose(handle_filename); 248618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov dlclose(handle_soname); 249618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov dlclose(handle); 250618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov} 251618f1a36f8635fa0f2d60c621fbf79ead2c3f3deDmitriy Ivanov 252c18de1bd47a558c9a24c6a4645df27df2c4738b4dimitryTEST(dlfcn, dlopen_vdso) { 253b9555a9251467bc2d0b05a4e2f011531c1d3bd4adimitry#if __has_include(<sys/auxv.h>) 254b9555a9251467bc2d0b05a4e2f011531c1d3bd4adimitry if (getauxval(AT_SYSINFO_EHDR) == 0) { 255b9555a9251467bc2d0b05a4e2f011531c1d3bd4adimitry GTEST_LOG_(INFO) << "getauxval(AT_SYSINFO_EHDR) == 0, skipping this test."; 256b9555a9251467bc2d0b05a4e2f011531c1d3bd4adimitry return; 257b9555a9251467bc2d0b05a4e2f011531c1d3bd4adimitry } 258b9555a9251467bc2d0b05a4e2f011531c1d3bd4adimitry#endif 259da1bb113408030cebd1b7f2ce4b10b0e1852666dElliott Hughes 260da1bb113408030cebd1b7f2ce4b10b0e1852666dElliott Hughes const char* vdso_name = "linux-vdso.so.1"; 261da1bb113408030cebd1b7f2ce4b10b0e1852666dElliott Hughes#if defined(__i386__) 262da1bb113408030cebd1b7f2ce4b10b0e1852666dElliott Hughes vdso_name = "linux-gate.so.1"; 263da1bb113408030cebd1b7f2ce4b10b0e1852666dElliott Hughes#endif 264da1bb113408030cebd1b7f2ce4b10b0e1852666dElliott Hughes void* handle = dlopen(vdso_name, RTLD_NOW); 265c18de1bd47a558c9a24c6a4645df27df2c4738b4dimitry ASSERT_TRUE(handle != nullptr) << dlerror(); 266c18de1bd47a558c9a24c6a4645df27df2c4738b4dimitry dlclose(handle); 267c18de1bd47a558c9a24c6a4645df27df2c4738b4dimitry} 268c18de1bd47a558c9a24c6a4645df27df2c4738b4dimitry 2690a2ab0203cc12c9b4b7647b18caf0343af8ca1a4Dimitry Ivanov// mips doesn't support ifuncs 2700a2ab0203cc12c9b4b7647b18caf0343af8ca1a4Dimitry Ivanov#if !defined(__mips__) 27121975b2861d859fb580ddfba50d323740486b7bcDimitry IvanovTEST(dlfcn, ifunc_variable) { 27221975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov typedef const char* (*fn_ptr)(); 27321975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov 27421975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov // ifunc's choice depends on whether IFUNC_CHOICE has a value 27521975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov // first check the set case 27621975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov setenv("IFUNC_CHOICE", "set", 1); 27721975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov // preload libtest_ifunc_variable_impl.so 27821975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov void* handle_impl = dlopen("libtest_ifunc_variable_impl.so", RTLD_NOW); 27921975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov void* handle = dlopen("libtest_ifunc_variable.so", RTLD_NOW); 28021975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 28121975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov const char** foo_ptr = reinterpret_cast<const char**>(dlsym(handle, "foo")); 28221975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov fn_ptr foo_library_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo_library")); 28321975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov ASSERT_TRUE(foo_ptr != nullptr) << dlerror(); 28421975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov ASSERT_TRUE(foo_library_ptr != nullptr) << dlerror(); 28521975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov ASSERT_EQ(strncmp("set", *foo_ptr, 3), 0); 28621975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov ASSERT_EQ(strncmp("set", foo_library_ptr(), 3), 0); 28721975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov dlclose(handle); 28821975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov dlclose(handle_impl); 28921975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov 29021975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov // then check the unset case 29121975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov unsetenv("IFUNC_CHOICE"); 29221975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov handle_impl = dlopen("libtest_ifunc_variable_impl.so", RTLD_NOW); 29321975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov handle = dlopen("libtest_ifunc_variable.so", RTLD_NOW); 29421975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 29521975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov foo_ptr = reinterpret_cast<const char**>(dlsym(handle, "foo")); 29621975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov foo_library_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo_library")); 29721975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov ASSERT_TRUE(foo_ptr != nullptr) << dlerror(); 29821975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov ASSERT_TRUE(foo_library_ptr != nullptr) << dlerror(); 29921975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov ASSERT_EQ(strncmp("unset", *foo_ptr, 5), 0); 30021975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov ASSERT_EQ(strncmp("unset", foo_library_ptr(), 5), 0); 30121975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov dlclose(handle); 30221975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov dlclose(handle_impl); 30321975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov} 30421975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov 305c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid SmithTEST(dlfcn, ifunc) { 3069598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov typedef const char* (*fn_ptr)(); 307c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith 308c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith // ifunc's choice depends on whether IFUNC_CHOICE has a value 309c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith // first check the set case 310c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith setenv("IFUNC_CHOICE", "set", 1); 311c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith void* handle = dlopen("libtest_ifunc.so", RTLD_NOW); 31221975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 3139598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov fn_ptr foo_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo")); 3149598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov fn_ptr foo_library_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo_library")); 31521975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov ASSERT_TRUE(foo_ptr != nullptr) << dlerror(); 31621975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov ASSERT_TRUE(foo_library_ptr != nullptr) << dlerror(); 3179598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov ASSERT_EQ(strncmp("set", foo_ptr(), 3), 0); 3189598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov ASSERT_EQ(strncmp("set", foo_library_ptr(), 3), 0); 319c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith dlclose(handle); 320c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith 321c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith // then check the unset case 322c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith unsetenv("IFUNC_CHOICE"); 323c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith handle = dlopen("libtest_ifunc.so", RTLD_NOW); 32421975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 3259598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov foo_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo")); 3269598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov foo_library_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo_library")); 32721975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov ASSERT_TRUE(foo_ptr != nullptr) << dlerror(); 32821975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov ASSERT_TRUE(foo_library_ptr != nullptr) << dlerror(); 3299598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov ASSERT_EQ(strncmp("unset", foo_ptr(), 5), 0); 33021975b2861d859fb580ddfba50d323740486b7bcDimitry Ivanov ASSERT_EQ(strncmp("unset", foo_library_ptr(), 5), 0); 3319598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov dlclose(handle); 3329598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov} 3339598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov 3349598b8c415e2fa9f240508185fe8c964b83f538dDmitriy IvanovTEST(dlfcn, ifunc_ctor_call) { 3359598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov typedef const char* (*fn_ptr)(); 3369598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov 3379598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov void* handle = dlopen("libtest_ifunc.so", RTLD_NOW); 3389aea164457c269c475592da36b4655d45f55c7bcDmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 3399aea164457c269c475592da36b4655d45f55c7bcDmitriy Ivanov fn_ptr is_ctor_called = reinterpret_cast<fn_ptr>(dlsym(handle, "is_ctor_called_irelative")); 3409aea164457c269c475592da36b4655d45f55c7bcDmitriy Ivanov ASSERT_TRUE(is_ctor_called != nullptr) << dlerror(); 3419aea164457c269c475592da36b4655d45f55c7bcDmitriy Ivanov ASSERT_STREQ("false", is_ctor_called()); 3429aea164457c269c475592da36b4655d45f55c7bcDmitriy Ivanov 3439aea164457c269c475592da36b4655d45f55c7bcDmitriy Ivanov is_ctor_called = reinterpret_cast<fn_ptr>(dlsym(handle, "is_ctor_called_jump_slot")); 3449aea164457c269c475592da36b4655d45f55c7bcDmitriy Ivanov ASSERT_TRUE(is_ctor_called != nullptr) << dlerror(); 3459598b8c415e2fa9f240508185fe8c964b83f538dDmitriy Ivanov ASSERT_STREQ("true", is_ctor_called()); 346c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith dlclose(handle); 347c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith} 348ba35b2d1b91459568133c1f4729a6fff8359e3d9Dimitry Ivanov 349ba35b2d1b91459568133c1f4729a6fff8359e3d9Dimitry IvanovTEST(dlfcn, ifunc_ctor_call_rtld_lazy) { 350ba35b2d1b91459568133c1f4729a6fff8359e3d9Dimitry Ivanov typedef const char* (*fn_ptr)(); 351ba35b2d1b91459568133c1f4729a6fff8359e3d9Dimitry Ivanov 352ba35b2d1b91459568133c1f4729a6fff8359e3d9Dimitry Ivanov void* handle = dlopen("libtest_ifunc.so", RTLD_LAZY); 353ba35b2d1b91459568133c1f4729a6fff8359e3d9Dimitry Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 354ba35b2d1b91459568133c1f4729a6fff8359e3d9Dimitry Ivanov fn_ptr is_ctor_called = reinterpret_cast<fn_ptr>(dlsym(handle, "is_ctor_called_irelative")); 355ba35b2d1b91459568133c1f4729a6fff8359e3d9Dimitry Ivanov ASSERT_TRUE(is_ctor_called != nullptr) << dlerror(); 356ba35b2d1b91459568133c1f4729a6fff8359e3d9Dimitry Ivanov ASSERT_STREQ("false", is_ctor_called()); 357ba35b2d1b91459568133c1f4729a6fff8359e3d9Dimitry Ivanov 358ba35b2d1b91459568133c1f4729a6fff8359e3d9Dimitry Ivanov is_ctor_called = reinterpret_cast<fn_ptr>(dlsym(handle, "is_ctor_called_jump_slot")); 359ba35b2d1b91459568133c1f4729a6fff8359e3d9Dimitry Ivanov ASSERT_TRUE(is_ctor_called != nullptr) << dlerror(); 360ba35b2d1b91459568133c1f4729a6fff8359e3d9Dimitry Ivanov ASSERT_STREQ("true", is_ctor_called()); 361ba35b2d1b91459568133c1f4729a6fff8359e3d9Dimitry Ivanov dlclose(handle); 362ba35b2d1b91459568133c1f4729a6fff8359e3d9Dimitry Ivanov} 3630a2ab0203cc12c9b4b7647b18caf0343af8ca1a4Dimitry Ivanov#endif 364c5a13efa9bc4264be0a9a9e37c00633af01584edBrigid Smith 365b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy IvanovTEST(dlfcn, dlopen_check_relocation_dt_needed_order) { 366b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // This is the structure of the test library and 367b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // its dt_needed libraries 368b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // libtest_relo_check_dt_needed_order.so 369b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // | 370b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // +-> libtest_relo_check_dt_needed_order_1.so 371b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // | 372b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // +-> libtest_relo_check_dt_needed_order_2.so 373b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // 374b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // The root library references relo_test_get_answer_lib - which is defined 375b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // in both dt_needed libraries, the correct relocation should 376b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov // use the function defined in libtest_relo_check_dt_needed_order_1.so 377b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov void* handle = nullptr; 378b8ab61804cec48e4ca585f4508fb1b7c6c5a04c5Tom Cherry auto guard = android::base::make_scope_guard([&]() { dlclose(handle); }); 379b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov 380b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov handle = dlopen("libtest_relo_check_dt_needed_order.so", RTLD_NOW); 381b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 382b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov 383b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov typedef int (*fn_t) (void); 384b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "relo_test_get_answer")); 385b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov ASSERT_TRUE(fn != nullptr) << dlerror(); 386b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov ASSERT_EQ(1, fn()); 387b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov} 388b2a30ee8d209154efc367db11b4167a5d6db605fDmitriy Ivanov 389cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy IvanovTEST(dlfcn, dlopen_check_order_dlsym) { 39014669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // Here is how the test library and its dt_needed 39114669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // libraries are arranged 39214669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // 393cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // libtest_check_order_children.so 39414669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // | 395cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._1_left.so 39614669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // | | 397cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | +-> ..._a.so 39814669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // | | 399cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | +-> ...r_b.so 40014669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // | 401cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._2_right.so 40214669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // | | 403cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | +-> ..._d.so 40414669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // | | 405cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | +-> ..._b.so 40614669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // | 407cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._3_c.so 40814669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // 40914669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // load order should be (1, 2, 3, a, b, d) 41014669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // 41114669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // get_answer() is defined in (2, 3, a, b, c) 41214669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov // get_answer2() is defined in (b, d) 413cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov void* sym = dlsym(RTLD_DEFAULT, "check_order_dlsym_get_answer"); 41414669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov ASSERT_TRUE(sym == nullptr); 415cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov void* handle = dlopen("libtest_check_order_dlsym.so", RTLD_NOW | RTLD_GLOBAL); 416cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 41714669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov typedef int (*fn_t) (void); 41814669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov fn_t fn, fn2; 419cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov fn = reinterpret_cast<fn_t>(dlsym(RTLD_DEFAULT, "check_order_dlsym_get_answer")); 420aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(fn != nullptr) << dlerror(); 421cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov fn2 = reinterpret_cast<fn_t>(dlsym(RTLD_DEFAULT, "check_order_dlsym_get_answer2")); 422aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(fn2 != nullptr) << dlerror(); 42314669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov 42414669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov ASSERT_EQ(42, fn()); 42514669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov ASSERT_EQ(43, fn2()); 42614669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov dlclose(handle); 42714669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov} 42814669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov 429cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy IvanovTEST(dlfcn, dlopen_check_order_reloc_siblings) { 430cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // This is how this one works: 431cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // we lookup and call get_answer which is defined in '_2.so' 432cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // and in turn calls external get_answer_impl() defined in _1.so and in '_[a-f].so' 433cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // the correct _impl() is implemented by '_a.so'; 434cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // 435cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // Note that this is test for RTLD_LOCAL (TODO: test for GLOBAL?) 436cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // 437cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // Here is the picture: 438cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // 439cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // libtest_check_order_reloc_siblings.so 440cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | 441cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._1.so <- empty 442cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | | 443cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | +-> ..._a.so <- exports correct answer_impl() 444cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | | 445cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | +-> ..._b.so <- every other letter exporting incorrect one. 446cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | 447cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._2.so <- empty 448cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | | 449cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | +-> ..._c.so 450cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | | 451cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | +-> ..._d.so 452cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | 453cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._3.so <- empty 454cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | 455cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._e.so 456cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | 457cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._f.so <- exports get_answer() that calls get_anser_impl(); 458cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // implements incorrect get_answer_impl() 459cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 460cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov void* handle = dlopen("libtest_check_order_reloc_siblings.so", RTLD_NOW | RTLD_NOLOAD); 461cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(handle == nullptr); 462cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov#ifdef __BIONIC__ 463cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // TODO: glibc returns nullptr on dlerror() here. Is it bug? 464cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_STREQ("dlopen failed: library \"libtest_check_order_reloc_siblings.so\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror()); 465cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov#endif 466cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 467cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov handle = dlopen("libtest_check_order_reloc_siblings.so", RTLD_NOW | RTLD_LOCAL); 468cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 469cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 470cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov typedef int (*fn_t) (void); 471cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "check_order_reloc_get_answer")); 472cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(fn != nullptr) << dlerror(); 473cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_EQ(42, fn()); 474cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 475cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_EQ(0, dlclose(handle)); 476cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov} 477cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 478cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy IvanovTEST(dlfcn, dlopen_check_order_reloc_siblings_with_preload) { 479cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // This test uses the same library as dlopen_check_order_reloc_siblings. 480cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // Unlike dlopen_check_order_reloc_siblings it preloads 481cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // libtest_check_order_reloc_siblings_1.so (first dependency) prior to 482cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // dlopen(libtest_check_order_reloc_siblings.so) 483cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 484cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov void* handle = dlopen("libtest_check_order_reloc_siblings.so", RTLD_NOW | RTLD_NOLOAD); 485cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(handle == nullptr); 486cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov handle = dlopen("libtest_check_order_reloc_siblings_1.so", RTLD_NOW | RTLD_NOLOAD); 487cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(handle == nullptr); 488cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 489cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov void* handle_for_1 = dlopen("libtest_check_order_reloc_siblings_1.so", RTLD_NOW | RTLD_LOCAL); 490cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(handle_for_1 != nullptr) << dlerror(); 491cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 492cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov handle = dlopen("libtest_check_order_reloc_siblings.so", RTLD_NOW | RTLD_LOCAL); 493cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 494cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 495cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_EQ(0, dlclose(handle_for_1)); 496cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 497cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov typedef int (*fn_t) (void); 498cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "check_order_reloc_get_answer")); 499cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(fn != nullptr) << dlerror(); 500cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_EQ(42, fn()); 501cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 502cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_EQ(0, dlclose(handle)); 503cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov} 504cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 5057699d13a74769fe8063fcca95588c87c571226c0Dmitriy IvanovTEST(dlfcn, dlopen_check_order_reloc_grandchild) { 5067699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov // This is how this one works: 5077699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov // we lookup and call grandchild_get_answer which is defined in '_2.so' 5087699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov // and in turn calls external get_answer_impl() defined in '_c_1.so and _c_2.so' 5097699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov // the correct _impl() is implemented by '_c_1.so'; 5107699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov // 5117699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov // Here is the picture of subtree: 5127699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov // 5137699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov // libtest_check_order_reloc_siblings.so 5147699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov // | 5157699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov // +-> ..._2.so <- grandchild_get_answer() 5167699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov // | 5177699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov // +-> ..._c.so <- empty 5187699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov // | | 5197699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov // | +-> _c_1.so <- exports correct answer_impl() 5207699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov // | | 5217699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov // | +-> _c_2.so <- exports incorrect answer_impl() 5227699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov // | 5237699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov // +-> ..._d.so <- empty 5247699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov 5257699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov void* handle = dlopen("libtest_check_order_reloc_siblings.so", RTLD_NOW | RTLD_NOLOAD); 5267699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov ASSERT_TRUE(handle == nullptr); 5277699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov#ifdef __BIONIC__ 5287699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov // TODO: glibc returns nullptr on dlerror() here. Is it bug? 5297699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov ASSERT_STREQ("dlopen failed: library \"libtest_check_order_reloc_siblings.so\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror()); 5307699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov#endif 5317699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov 5327699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov handle = dlopen("libtest_check_order_reloc_siblings.so", RTLD_NOW | RTLD_LOCAL); 5337699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 5347699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov 5357699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov typedef int (*fn_t) (void); 5367699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "check_order_reloc_grandchild_get_answer")); 5377699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov ASSERT_TRUE(fn != nullptr) << dlerror(); 5387699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov ASSERT_EQ(42, fn()); 5397699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov 5407699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov ASSERT_EQ(0, dlclose(handle)); 5417699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov} 5427699d13a74769fe8063fcca95588c87c571226c0Dmitriy Ivanov 543cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy IvanovTEST(dlfcn, dlopen_check_order_reloc_nephew) { 544cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // This is how this one works: 545cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // we lookup and call nephew_get_answer which is defined in '_2.so' 546cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // and in turn calls external get_answer_impl() defined in '_[a-f].so' 547cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // the correct _impl() is implemented by '_a.so'; 548cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // 549cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // Here is the picture: 550cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // 551cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // libtest_check_order_reloc_siblings.so 552cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | 553cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._1.so <- empty 554cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | | 555cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | +-> ..._a.so <- exports correct answer_impl() 556cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | | 557cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | +-> ..._b.so <- every other letter exporting incorrect one. 558cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | 559cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._2.so <- empty 560cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | | 561cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | +-> ..._c.so 562cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | | 563cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | +-> ..._d.so 564cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | 565cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._3.so <- nephew_get_answer() that calls get_answer_impl(); 566cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | 567cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._e.so 568cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | 569cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._f.so 570cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 571cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov void* handle = dlopen("libtest_check_order_reloc_siblings.so", RTLD_NOW | RTLD_NOLOAD); 572cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(handle == nullptr); 573cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov#ifdef __BIONIC__ 574cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // TODO: glibc returns nullptr on dlerror() here. Is it bug? 575cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_STREQ("dlopen failed: library \"libtest_check_order_reloc_siblings.so\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror()); 576cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov#endif 577cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 578cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov handle = dlopen("libtest_check_order_reloc_siblings.so", RTLD_NOW | RTLD_LOCAL); 579cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 580cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 581cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov typedef int (*fn_t) (void); 582cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "check_order_reloc_nephew_get_answer")); 583cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(fn != nullptr) << dlerror(); 584cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_EQ(42, fn()); 585cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 586cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_EQ(0, dlclose(handle)); 587cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov} 588cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 589ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy IvanovTEST(dlfcn, check_unload_after_reloc) { 590ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov // This is how this one works: 591ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov // libtest_two_parents_parent1 <- answer_impl() used by libtest_two_parents_child 592ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov // | 593ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov // +-> libtest_two_parents_child 594ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov // 595ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov // libtest_two_parents_parent2 <- answer_impl() not used by libtest_two_parents_child 596ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov // | 597ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov // +-> libtest_two_parents_child 598ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov // 599ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov // Test dlopens parent1 which loads and relocates libtest_two_parents_child.so 600ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov // as a second step it dlopens parent2 and dlcloses parent1... 601ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov 602cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov void* handle = dlopen("libtest_two_parents_parent1.so", RTLD_NOW | RTLD_LOCAL); 603cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 604ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov 605cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov void* handle2 = dlopen("libtest_two_parents_parent2.so", RTLD_NOW | RTLD_LOCAL); 606cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov ASSERT_TRUE(handle2 != nullptr) << dlerror(); 607ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov 608cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov typedef int (*fn_t) (void); 609cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov fn_t fn = reinterpret_cast<fn_t>(dlsym(handle2, "check_order_reloc_get_answer")); 610cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov ASSERT_TRUE(fn != nullptr) << dlerror(); 611cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov ASSERT_EQ(42, fn()); 612ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov 613cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov ASSERT_EQ(0, dlclose(handle)); 614ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov 615cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov handle = dlopen("libtest_two_parents_parent1.so", RTLD_NOW | RTLD_LOCAL | RTLD_NOLOAD); 616cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov ASSERT_TRUE(handle != nullptr); 617cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov ASSERT_EQ(0, dlclose(handle)); 618ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov 619cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov fn = reinterpret_cast<fn_t>(dlsym(handle2, "check_order_reloc_get_answer")); 620cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov ASSERT_TRUE(fn != nullptr) << dlerror(); 621cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov ASSERT_EQ(42, fn()); 622ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov 623cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov ASSERT_EQ(0, dlclose(handle2)); 624ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov 625cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov handle = dlopen("libtest_two_parents_parent1.so", RTLD_NOW | RTLD_LOCAL | RTLD_NOLOAD); 626cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov ASSERT_TRUE(handle == nullptr); 627ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov} 628ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov 629cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanovextern "C" int check_order_reloc_root_get_answer_impl() { 630cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov return 42; 631cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov} 632cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 633cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy IvanovTEST(dlfcn, dlopen_check_order_reloc_main_executable) { 634cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // This is how this one works: 635cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // we lookup and call get_answer3 which is defined in 'root.so' 636cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // and in turn calls external root_get_answer_impl() defined in _2.so and 637cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // above the correct _impl() is one in the executable. 638cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // 639cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // libtest_check_order_reloc_root.so 640cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | 641cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._1.so <- empty 642cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // | 643cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // +-> ..._2.so <- gives incorrect answer for answer_main_impl() 644cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // 645cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 646cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov void* handle = dlopen("libtest_check_order_reloc_root.so", RTLD_NOW | RTLD_NOLOAD); 647cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(handle == nullptr); 648cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov#ifdef __BIONIC__ 649cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov // TODO: glibc returns nullptr on dlerror() here. Is it bug? 650cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_STREQ("dlopen failed: library \"libtest_check_order_reloc_root.so\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror()); 651cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov#endif 652cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 653cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov handle = dlopen("libtest_check_order_reloc_root.so", RTLD_NOW | RTLD_LOCAL); 654cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 655cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 656cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov typedef int (*fn_t) (void); 657cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "check_order_reloc_root_get_answer")); 658cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_TRUE(fn != nullptr) << dlerror(); 659cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_EQ(42, fn()); 660cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 661cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov ASSERT_EQ(0, dlclose(handle)); 662cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov} 663cfa97f172dc1b10d650fefbb6ccffd88ce72a5fbDmitriy Ivanov 664e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy IvanovTEST(dlfcn, dlopen_check_rtld_local) { 665e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov void* sym = dlsym(RTLD_DEFAULT, "dlopen_testlib_simple_func"); 666e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov ASSERT_TRUE(sym == nullptr); 667e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov 668e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov // implicit RTLD_LOCAL 669e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov void* handle = dlopen("libtest_simple.so", RTLD_NOW); 670e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov sym = dlsym(RTLD_DEFAULT, "dlopen_testlib_simple_func"); 671e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov ASSERT_TRUE(sym == nullptr); 672e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov ASSERT_SUBSTR("undefined symbol: dlopen_testlib_simple_func", dlerror()); 673e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov sym = dlsym(handle, "dlopen_testlib_simple_func"); 674e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov ASSERT_TRUE(sym != nullptr); 675e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov ASSERT_TRUE(reinterpret_cast<bool (*)(void)>(sym)()); 676e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov dlclose(handle); 677e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov 678e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov // explicit RTLD_LOCAL 679e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov handle = dlopen("libtest_simple.so", RTLD_NOW | RTLD_LOCAL); 680e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov sym = dlsym(RTLD_DEFAULT, "dlopen_testlib_simple_func"); 681e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov ASSERT_TRUE(sym == nullptr); 682e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov ASSERT_SUBSTR("undefined symbol: dlopen_testlib_simple_func", dlerror()); 683e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov sym = dlsym(handle, "dlopen_testlib_simple_func"); 684e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov ASSERT_TRUE(sym != nullptr); 685e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov ASSERT_TRUE(reinterpret_cast<bool (*)(void)>(sym)()); 686e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov dlclose(handle); 687e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov} 688e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov 689e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy IvanovTEST(dlfcn, dlopen_check_rtld_global) { 690e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov void* sym = dlsym(RTLD_DEFAULT, "dlopen_testlib_simple_func"); 691e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov ASSERT_TRUE(sym == nullptr); 692e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov 693e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov void* handle = dlopen("libtest_simple.so", RTLD_NOW | RTLD_GLOBAL); 6941b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 695e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov sym = dlsym(RTLD_DEFAULT, "dlopen_testlib_simple_func"); 696e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov ASSERT_TRUE(sym != nullptr) << dlerror(); 697e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov ASSERT_TRUE(reinterpret_cast<bool (*)(void)>(sym)()); 698e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov dlclose(handle); 6991b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 7001b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov // RTLD_GLOBAL implies RTLD_NODELETE, let's check that 7011b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov void* sym_after_dlclose = dlsym(RTLD_DEFAULT, "dlopen_testlib_simple_func"); 7021b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_EQ(sym, sym_after_dlclose); 703f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov 704f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov // Check if dlsym() for main program's handle searches RTLD_GLOBAL 705f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov // shared libraries after symbol was not found in the main executable 706f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov // and dependent libraries. 707f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov void* handle_for_main_executable = dlopen(nullptr, RTLD_NOW); 708f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov sym = dlsym(handle_for_main_executable, "dlopen_testlib_simple_func"); 709f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov ASSERT_TRUE(sym != nullptr) << dlerror(); 710f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov 711f439b5a3186ca0fef1092f45770abc716da9d87aDmitriy Ivanov dlclose(handle_for_main_executable); 712e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov} 713e8ba50fe0d51fbefee1a8f5bb62bf51d841512c8Dmitriy Ivanov 71414669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov// libtest_with_dependency_loop.so -> libtest_with_dependency_loop_a.so -> 71514669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov// libtest_with_dependency_loop_b.so -> libtest_with_dependency_loop_c.so -> 71614669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov// libtest_with_dependency_loop_a.so 71714669a939d113214a4a20b9318fca0992d5453f0Dmitriy IvanovTEST(dlfcn, dlopen_check_loop) { 718cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov void* handle = dlopen("libtest_with_dependency_loop.so", RTLD_NOW); 719cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 720cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov void* f = dlsym(handle, "dlopen_test_loopy_function"); 721cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov ASSERT_TRUE(f != nullptr) << dlerror(); 722cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov EXPECT_TRUE(reinterpret_cast<bool (*)(void)>(f)()); 723cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov ASSERT_EQ(0, dlclose(handle)); 724cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov 725cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov // dlopen second time to make sure that the library was unloaded correctly 726cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov handle = dlopen("libtest_with_dependency_loop.so", RTLD_NOW | RTLD_NOLOAD); 727cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov ASSERT_TRUE(handle == nullptr); 728ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov#ifdef __BIONIC__ 729cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov ASSERT_STREQ("dlopen failed: library \"libtest_with_dependency_loop.so\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror()); 7309cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov#else 7319cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov // TODO: glibc returns nullptr on dlerror() here. Is it bug? 7329cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov ASSERT_TRUE(dlerror() == nullptr); 733eb27bbae8f0edc6b62ca2db73256c7fb53b9e9bfDmitriy Ivanov#endif 734ab972b9adf8789a9e1b03129cd7f0c22e6bba117Dmitriy Ivanov 735cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov handle = dlopen("libtest_with_dependency_a.so", RTLD_NOW | RTLD_NOLOAD); 736cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov ASSERT_TRUE(handle == nullptr); 73714669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov} 73814669a939d113214a4a20b9318fca0992d5453f0Dmitriy Ivanov 7391b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy IvanovTEST(dlfcn, dlopen_nodelete) { 7401b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov static bool is_unloaded = false; 7411b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 7421b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov void* handle = dlopen("libtest_nodelete_1.so", RTLD_NOW | RTLD_NODELETE); 7431b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 7441b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov void (*set_unload_flag_ptr)(bool*); 7451b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov set_unload_flag_ptr = reinterpret_cast<void (*)(bool*)>(dlsym(handle, "dlopen_nodelete_1_set_unload_flag_ptr")); 7461b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(set_unload_flag_ptr != nullptr) << dlerror(); 7471b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov set_unload_flag_ptr(&is_unloaded); 7481b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 7491b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_nodelete_1_taxicab_number")); 7501b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(taxicab_number != nullptr) << dlerror(); 7511b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_EQ(1729U, *taxicab_number); 7521b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov *taxicab_number = 2; 7531b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 7541b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov dlclose(handle); 7551b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(!is_unloaded); 7561b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 7571b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov uint32_t* taxicab_number_after_dlclose = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_nodelete_1_taxicab_number")); 7581b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_EQ(taxicab_number_after_dlclose, taxicab_number); 7591b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_EQ(2U, *taxicab_number_after_dlclose); 7601b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 7611b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 7621b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov handle = dlopen("libtest_nodelete_1.so", RTLD_NOW); 7631b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov uint32_t* taxicab_number2 = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_nodelete_1_taxicab_number")); 7641b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_EQ(taxicab_number2, taxicab_number); 7651b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 7661b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_EQ(2U, *taxicab_number2); 7671b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 7681b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov dlclose(handle); 7691b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(!is_unloaded); 7701b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov} 7711b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 7721b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy IvanovTEST(dlfcn, dlopen_nodelete_on_second_dlopen) { 7731b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov static bool is_unloaded = false; 7741b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 7751b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov void* handle = dlopen("libtest_nodelete_2.so", RTLD_NOW); 7761b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 7771b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov void (*set_unload_flag_ptr)(bool*); 7781b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov set_unload_flag_ptr = reinterpret_cast<void (*)(bool*)>(dlsym(handle, "dlopen_nodelete_2_set_unload_flag_ptr")); 7791b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(set_unload_flag_ptr != nullptr) << dlerror(); 7801b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov set_unload_flag_ptr(&is_unloaded); 7811b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 7821b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_nodelete_2_taxicab_number")); 7831b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(taxicab_number != nullptr) << dlerror(); 7841b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 7851b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_EQ(1729U, *taxicab_number); 7861b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov *taxicab_number = 2; 7871b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 7881b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov // This RTLD_NODELETE should be ignored 7891b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov void* handle1 = dlopen("libtest_nodelete_2.so", RTLD_NOW | RTLD_NODELETE); 7901b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(handle1 != nullptr) << dlerror(); 7911b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_EQ(handle, handle1); 7921b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 7931b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov dlclose(handle1); 7941b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov dlclose(handle); 7951b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 7961b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(is_unloaded); 7971b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov} 7981b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 7991b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy IvanovTEST(dlfcn, dlopen_nodelete_dt_flags_1) { 8001b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov static bool is_unloaded = false; 8011b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 8021b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov void* handle = dlopen("libtest_nodelete_dt_flags_1.so", RTLD_NOW); 8031b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 8041b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov void (*set_unload_flag_ptr)(bool*); 8051b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov set_unload_flag_ptr = reinterpret_cast<void (*)(bool*)>(dlsym(handle, "dlopen_nodelete_dt_flags_1_set_unload_flag_ptr")); 8061b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(set_unload_flag_ptr != nullptr) << dlerror(); 8071b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov set_unload_flag_ptr(&is_unloaded); 8081b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 8091b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov dlclose(handle); 8101b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov ASSERT_TRUE(!is_unloaded); 8111b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov} 8121b20dafdbe65e43b9f4c95057e8482380833ea91Dmitriy Ivanov 813d225a5e65223b375a63548c4b780f04d8f3d7b60Dmitriy IvanovTEST(dlfcn, dlsym_df_1_global) { 814d225a5e65223b375a63548c4b780f04d8f3d7b60Dmitriy Ivanov void* handle = dlopen("libtest_dlsym_df_1_global.so", RTLD_NOW); 815d225a5e65223b375a63548c4b780f04d8f3d7b60Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 816d225a5e65223b375a63548c4b780f04d8f3d7b60Dmitriy Ivanov int (*get_answer)(); 817d225a5e65223b375a63548c4b780f04d8f3d7b60Dmitriy Ivanov get_answer = reinterpret_cast<int (*)()>(dlsym(handle, "dl_df_1_global_get_answer")); 818d225a5e65223b375a63548c4b780f04d8f3d7b60Dmitriy Ivanov ASSERT_TRUE(get_answer != nullptr) << dlerror(); 819d225a5e65223b375a63548c4b780f04d8f3d7b60Dmitriy Ivanov ASSERT_EQ(42, get_answer()); 820d225a5e65223b375a63548c4b780f04d8f3d7b60Dmitriy Ivanov ASSERT_EQ(0, dlclose(handle)); 821d225a5e65223b375a63548c4b780f04d8f3d7b60Dmitriy Ivanov} 822d225a5e65223b375a63548c4b780f04d8f3d7b60Dmitriy Ivanov 823e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott HughesTEST(dlfcn, dlopen_failure) { 8243b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes void* self = dlopen("/does/not/exist", RTLD_NOW); 825aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(self == nullptr); 826063525c61d24776094d76971f33920e2a2079530Elliott Hughes#if defined(__BIONIC__) 8273b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_STREQ("dlopen failed: library \"/does/not/exist\" not found", dlerror()); 8283b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes#else 8293b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_STREQ("/does/not/exist: cannot open shared object file: No such file or directory", dlerror()); 8303b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes#endif 8313b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes} 8323b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 833109040c868230d2f37c2f3964c6b62f63ff30c6cdimitryTEST(dlfcn, dlclose_unload) { 834109040c868230d2f37c2f3964c6b62f63ff30c6cdimitry void* handle = dlopen("libtest_simple.so", RTLD_NOW); 835109040c868230d2f37c2f3964c6b62f63ff30c6cdimitry ASSERT_TRUE(handle != nullptr) << dlerror(); 836109040c868230d2f37c2f3964c6b62f63ff30c6cdimitry uint32_t* taxicab_number = static_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number")); 837109040c868230d2f37c2f3964c6b62f63ff30c6cdimitry ASSERT_TRUE(taxicab_number != nullptr) << dlerror(); 838109040c868230d2f37c2f3964c6b62f63ff30c6cdimitry EXPECT_EQ(1729U, *taxicab_number); 839109040c868230d2f37c2f3964c6b62f63ff30c6cdimitry dlclose(handle); 840109040c868230d2f37c2f3964c6b62f63ff30c6cdimitry // Making sure that the library has been unmapped as part of library unload 841109040c868230d2f37c2f3964c6b62f63ff30c6cdimitry // process. Note that mprotect somewhat counter-intuitively returns ENOMEM in 842109040c868230d2f37c2f3964c6b62f63ff30c6cdimitry // this case. 843109040c868230d2f37c2f3964c6b62f63ff30c6cdimitry uintptr_t page_start = reinterpret_cast<uintptr_t>(taxicab_number) & ~(PAGE_SIZE - 1); 844109040c868230d2f37c2f3964c6b62f63ff30c6cdimitry ASSERT_TRUE(mprotect(reinterpret_cast<void*>(page_start), PAGE_SIZE, PROT_NONE) != 0); 845109040c868230d2f37c2f3964c6b62f63ff30c6cdimitry ASSERT_EQ(ENOMEM, errno) << strerror(errno); 846109040c868230d2f37c2f3964c6b62f63ff30c6cdimitry} 847109040c868230d2f37c2f3964c6b62f63ff30c6cdimitry 848c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanovstatic void ConcurrentDlErrorFn(std::string& error) { 849c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov ASSERT_TRUE(dlerror() == nullptr); 850c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov 851c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov void* handle = dlopen("/child/thread", RTLD_NOW); 852c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov ASSERT_TRUE(handle == nullptr); 853c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov 854c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov const char* err = dlerror(); 855c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov ASSERT_TRUE(err != nullptr); 856c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov 857c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov error = err; 8585419b9474753d25dff947c7740532f86d130c0beElliott Hughes} 8595419b9474753d25dff947c7740532f86d130c0beElliott Hughes 860c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry IvanovTEST(dlfcn, dlerror_concurrent_buffer) { 861c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov void* handle = dlopen("/main/thread", RTLD_NOW); 862c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov ASSERT_TRUE(handle == nullptr); 8635419b9474753d25dff947c7740532f86d130c0beElliott Hughes const char* main_thread_error = dlerror(); 864c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov ASSERT_TRUE(main_thread_error != nullptr); 8655419b9474753d25dff947c7740532f86d130c0beElliott Hughes ASSERT_SUBSTR("/main/thread", main_thread_error); 8665419b9474753d25dff947c7740532f86d130c0beElliott Hughes 867c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov std::string child_thread_error; 868c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov std::thread t(ConcurrentDlErrorFn, std::ref(child_thread_error)); 869c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov t.join(); 870c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov ASSERT_SUBSTR("/child/thread", child_thread_error.c_str()); 8715419b9474753d25dff947c7740532f86d130c0beElliott Hughes 872c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov // Check that main thread local buffer was not modified. 873c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov ASSERT_SUBSTR("/main/thread", main_thread_error); 874c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov} 875c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov 876c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry IvanovTEST(dlfcn, dlerror_concurrent) { 877c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov void* handle = dlopen("/main/thread", RTLD_NOW); 878c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov ASSERT_TRUE(handle == nullptr); 879c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov 880c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov std::string child_thread_error; 881c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov std::thread t(ConcurrentDlErrorFn, std::ref(child_thread_error)); 882c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov t.join(); 883c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov ASSERT_SUBSTR("/child/thread", child_thread_error.c_str()); 884c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov 885c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov const char* main_thread_error = dlerror(); 886c7365eb2fa996e72c5ea7f4e20222d6b48b9c6e0Dimitry Ivanov ASSERT_TRUE(main_thread_error != nullptr); 8875419b9474753d25dff947c7740532f86d130c0beElliott Hughes ASSERT_SUBSTR("/main/thread", main_thread_error); 8885419b9474753d25dff947c7740532f86d130c0beElliott Hughes} 8895419b9474753d25dff947c7740532f86d130c0beElliott Hughes 890e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott HughesTEST(dlfcn, dlsym_failures) { 8913b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes dlerror(); // Clear any pending errors. 892aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov void* self = dlopen(nullptr, RTLD_NOW); 893aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(self != nullptr); 894aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(dlerror() == nullptr); 8953b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 8963b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes void* sym; 8973b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 89844adf93b8eddb3a7965a3e9abc189408a1f5a7eaDmitriy Ivanov#if defined(__BIONIC__) && !defined(__LP64__) 89944adf93b8eddb3a7965a3e9abc189408a1f5a7eaDmitriy Ivanov // RTLD_DEFAULT in lp32 bionic is not (void*)0 90044adf93b8eddb3a7965a3e9abc189408a1f5a7eaDmitriy Ivanov // so it can be distinguished from the NULL handle. 901aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov sym = dlsym(nullptr, "test"); 902aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(sym == nullptr); 9034a2c5aa30ceea2aaf8dcaee2feb4879978af4fceDimitry Ivanov ASSERT_STREQ("dlsym failed: library handle is null", dlerror()); 9043b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes#endif 9053b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 9063b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes // Symbol that doesn't exist. 9073b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes sym = dlsym(self, "ThisSymbolDoesNotExist"); 908aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(sym == nullptr); 9093b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_SUBSTR("undefined symbol: ThisSymbolDoesNotExist", dlerror()); 9101a6961650c82168864afe040dbdc05977db701dfElliott Hughes 9111a6961650c82168864afe040dbdc05977db701dfElliott Hughes ASSERT_EQ(0, dlclose(self)); 9123b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes} 9133b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 914aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy IvanovTEST(dlfcn, dladdr_executable) { 9153b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes dlerror(); // Clear any pending errors. 916aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov void* self = dlopen(nullptr, RTLD_NOW); 917aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(self != nullptr); 918aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(dlerror() == nullptr); 9198e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 9208e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes void* sym = dlsym(self, "DlSymTestFunction"); 921aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(sym != nullptr); 9228e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 9238e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // Deliberately ask dladdr for an address inside a symbol, rather than the symbol base address. 9248e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes void* addr = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(sym) + 2); 9258e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 9268e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes Dl_info info; 9278e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes int rc = dladdr(addr, &info); 9288e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_NE(rc, 0); // Zero on error, non-zero on success. 9298e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 9308e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // Get the name of this executable. 9312ba1cf39ae6087249a839ec7b3793d4d4fa75438Dimitry Ivanov const std::string& executable_path = get_executable_path(); 9328e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 9338e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // The filename should be that of this executable. 934aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov char dli_realpath[PATH_MAX]; 935aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov ASSERT_TRUE(realpath(info.dli_fname, dli_realpath) != nullptr); 9362ba1cf39ae6087249a839ec7b3793d4d4fa75438Dimitry Ivanov ASSERT_STREQ(executable_path.c_str(), dli_realpath); 9378e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 9388e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // The symbol name should be the symbol we looked up. 9398e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_STREQ(info.dli_sname, "DlSymTestFunction"); 9408e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 9418e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // The address should be the exact address of the symbol. 9428e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_EQ(info.dli_saddr, sym); 9438e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 944aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov std::vector<map_record> maps; 945aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov ASSERT_TRUE(Maps::parse_maps(&maps)); 946aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov 947aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov void* base_address = nullptr; 948aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov for (const map_record& rec : maps) { 949aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov if (executable_path == rec.pathname) { 950aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov base_address = reinterpret_cast<void*>(rec.addr_start); 9518e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes break; 9528e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes } 9538e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes } 9548e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 9558e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // The base address should be the address we were loaded at. 9568e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_EQ(info.dli_fbase, base_address); 9571a6961650c82168864afe040dbdc05977db701dfElliott Hughes 9581a6961650c82168864afe040dbdc05977db701dfElliott Hughes ASSERT_EQ(0, dlclose(self)); 9598e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes} 9608e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 9612ba1cf39ae6087249a839ec7b3793d4d4fa75438Dimitry IvanovTEST(dlfcn, dlopen_executable_by_absolute_path) { 9622ba1cf39ae6087249a839ec7b3793d4d4fa75438Dimitry Ivanov void* handle1 = dlopen(nullptr, RTLD_NOW); 9632ba1cf39ae6087249a839ec7b3793d4d4fa75438Dimitry Ivanov ASSERT_TRUE(handle1 != nullptr) << dlerror(); 9642ba1cf39ae6087249a839ec7b3793d4d4fa75438Dimitry Ivanov 9652ba1cf39ae6087249a839ec7b3793d4d4fa75438Dimitry Ivanov void* handle2 = dlopen(get_executable_path().c_str(), RTLD_NOW); 9662ba1cf39ae6087249a839ec7b3793d4d4fa75438Dimitry Ivanov ASSERT_TRUE(handle2 != nullptr) << dlerror(); 9672ba1cf39ae6087249a839ec7b3793d4d4fa75438Dimitry Ivanov 9682ba1cf39ae6087249a839ec7b3793d4d4fa75438Dimitry Ivanov#if defined(__BIONIC__) 9692ba1cf39ae6087249a839ec7b3793d4d4fa75438Dimitry Ivanov ASSERT_EQ(handle1, handle2); 9702ba1cf39ae6087249a839ec7b3793d4d4fa75438Dimitry Ivanov#else 9712ba1cf39ae6087249a839ec7b3793d4d4fa75438Dimitry Ivanov GTEST_LOG_(INFO) << "Skipping ASSERT_EQ(handle1, handle2) for glibc: " 9722ba1cf39ae6087249a839ec7b3793d4d4fa75438Dimitry Ivanov "it loads a separate copy of the main executable " 9732ba1cf39ae6087249a839ec7b3793d4d4fa75438Dimitry Ivanov "on dlopen by absolute path."; 9742ba1cf39ae6087249a839ec7b3793d4d4fa75438Dimitry Ivanov#endif 9752ba1cf39ae6087249a839ec7b3793d4d4fa75438Dimitry Ivanov} 9762ba1cf39ae6087249a839ec7b3793d4d4fa75438Dimitry Ivanov 97714b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko#if defined (__aarch64__) 97814b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko#define ALTERNATE_PATH_TO_SYSTEM_LIB "/system/lib/arm64/" 97914b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko#elif defined (__arm__) 98014b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko#define ALTERNATE_PATH_TO_SYSTEM_LIB "/system/lib/arm/" 98114b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko#elif defined (__i386__) 98214b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko#define ALTERNATE_PATH_TO_SYSTEM_LIB "/system/lib/x86/" 98314b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko#elif defined (__x86_64__) 98414b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko#define ALTERNATE_PATH_TO_SYSTEM_LIB "/system/lib/x86_64/" 98514b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko#elif defined (__mips__) 98614b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko#if defined(__LP64__) 98714b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko#define ALTERNATE_PATH_TO_SYSTEM_LIB "/system/lib/mips64/" 98814b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko#else 98914b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko#define ALTERNATE_PATH_TO_SYSTEM_LIB "/system/lib/mips/" 99014b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko#endif 99114b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko#else 99214b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko#error "Unknown architecture" 99314b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko#endif 9946f2d3104c82f81c1f0123a3cfb25ae670841d0baLazar Trsic#define PATH_TO_LIBC PATH_TO_SYSTEM_LIB "libc.so" 99514b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko#define ALTERNATE_PATH_TO_LIBC ALTERNATE_PATH_TO_SYSTEM_LIB "libc.so" 996aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov 997aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy IvanovTEST(dlfcn, dladdr_libc) { 998aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov#if defined(__BIONIC__) 999aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov Dl_info info; 1000aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov void* addr = reinterpret_cast<void*>(puts); // well-known libc function 1001aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov ASSERT_TRUE(dladdr(addr, &info) != 0); 1002aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov 1003ef25592f14d23ce6294ea103e9edf894779d141dDmitriy Ivanov char libc_realpath[PATH_MAX]; 100414b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko 100514b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko // Check if libc is in canonical path or in alternate path. 100614b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko if (strncmp(ALTERNATE_PATH_TO_SYSTEM_LIB, 100714b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko info.dli_fname, 100814b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko sizeof(ALTERNATE_PATH_TO_SYSTEM_LIB) - 1) == 0) { 100914b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko // Platform with emulated architecture. Symlink on ARC++. 101014b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko ASSERT_TRUE(realpath(ALTERNATE_PATH_TO_LIBC, libc_realpath) == libc_realpath); 101114b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko } else { 101214b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko // /system/lib is symlink when this test is executed on host. 101314b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko ASSERT_TRUE(realpath(PATH_TO_LIBC, libc_realpath) == libc_realpath); 101414b9d7199c1b147ef6ce6e522ff14413930d2127Victor Khimenko } 1015ef25592f14d23ce6294ea103e9edf894779d141dDmitriy Ivanov 1016ef25592f14d23ce6294ea103e9edf894779d141dDmitriy Ivanov ASSERT_STREQ(libc_realpath, info.dli_fname); 1017aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov // TODO: add check for dfi_fbase 1018aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov ASSERT_STREQ("puts", info.dli_sname); 1019aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov ASSERT_EQ(addr, info.dli_saddr); 1020aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov#else 1021aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov GTEST_LOG_(INFO) << "This test does nothing for glibc. Glibc returns path from ldconfig " 1022aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov "for libc.so, which is symlink itself (not a realpath).\n"; 1023aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov#endif 1024aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov} 1025aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov 1026e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott HughesTEST(dlfcn, dladdr_invalid) { 10278e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes Dl_info info; 10288e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 10293b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes dlerror(); // Clear any pending errors. 10303b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 10318e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // No symbol corresponding to NULL. 1032aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_EQ(dladdr(nullptr, &info), 0); // Zero on error, non-zero on success. 1033aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(dlerror() == nullptr); // dladdr(3) doesn't set dlerror(3). 10348e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 10358e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // No symbol corresponding to a stack address. 10368e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_EQ(dladdr(&info, &info), 0); // Zero on error, non-zero on success. 1037aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(dlerror() == nullptr); // dladdr(3) doesn't set dlerror(3). 10388e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes} 1039124fae9eabd7a25d80dfa8c3b56bed0f0fba16f1Elliott Hughes 1040a43e906221a3e9c70a66118a8692cd46f77e144eElliott Hughes// GNU-style ELF hash tables are incompatible with the MIPS ABI. 1041a43e906221a3e9c70a66118a8692cd46f77e144eElliott Hughes// MIPS requires .dynsym to be sorted to match the GOT but GNU-style requires sorting by hash code. 1042e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott HughesTEST(dlfcn, dlopen_library_with_only_gnu_hash) { 1043ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov#if !defined(__mips__) 1044124fae9eabd7a25d80dfa8c3b56bed0f0fba16f1Elliott Hughes dlerror(); // Clear any pending errors. 1045ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov void* handle = dlopen("libgnu-hash-table-library.so", RTLD_NOW); 1046ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 1047b8ab61804cec48e4ca585f4508fb1b7c6c5a04c5Tom Cherry auto guard = android::base::make_scope_guard([&]() { dlclose(handle); }); 1048ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov void* sym = dlsym(handle, "getRandomNumber"); 1049ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov ASSERT_TRUE(sym != nullptr) << dlerror(); 1050ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov int (*fn)(void); 1051ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov fn = reinterpret_cast<int (*)(void)>(sym); 1052ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov EXPECT_EQ(4, fn()); 1053ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov 1054ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov Dl_info dlinfo; 1055ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov ASSERT_TRUE(0 != dladdr(reinterpret_cast<void*>(fn), &dlinfo)); 1056ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov 1057ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov ASSERT_TRUE(fn == dlinfo.dli_saddr); 1058ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov ASSERT_STREQ("getRandomNumber", dlinfo.dli_sname); 1059b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov ASSERT_SUBSTR("libgnu-hash-table-library.so", dlinfo.dli_fname); 1060ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov#else 1061ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov GTEST_LOG_(INFO) << "This test does nothing for mips/mips64; mips toolchain does not support '--hash-style=gnu'\n"; 1062a43e906221a3e9c70a66118a8692cd46f77e144eElliott Hughes#endif 1063ec18ce06f2d007be40ad6f043058f5a4c7236573Dmitriy Ivanov} 1064e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes 1065b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy IvanovTEST(dlfcn, dlopen_library_with_only_sysv_hash) { 1066b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov void* handle = dlopen("libsysv-hash-table-library.so", RTLD_NOW); 1067b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 1068b8ab61804cec48e4ca585f4508fb1b7c6c5a04c5Tom Cherry auto guard = android::base::make_scope_guard([&]() { dlclose(handle); }); 1069b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov void* sym = dlsym(handle, "getRandomNumber"); 1070b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov ASSERT_TRUE(sym != nullptr) << dlerror(); 1071b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov int (*fn)(void); 1072b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov fn = reinterpret_cast<int (*)(void)>(sym); 1073b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov EXPECT_EQ(4, fn()); 1074b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov 1075b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov Dl_info dlinfo; 1076b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov ASSERT_TRUE(0 != dladdr(reinterpret_cast<void*>(fn), &dlinfo)); 1077b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov 1078b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov ASSERT_TRUE(fn == dlinfo.dli_saddr); 1079b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov ASSERT_STREQ("getRandomNumber", dlinfo.dli_sname); 1080b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov ASSERT_SUBSTR("libsysv-hash-table-library.so", dlinfo.dli_fname); 1081b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov} 1082b3356773c6b5fbbbb26d22b3d6c6e0e598840e44Dmitriy Ivanov 108345a93c13bfa15e8621010570bb98aaee8c5803fcElliott HughesTEST(dlfcn, dlopen_library_with_ELF_TLS) { 108445a93c13bfa15e8621010570bb98aaee8c5803fcElliott Hughes dlerror(); // Clear any pending errors. 108545a93c13bfa15e8621010570bb98aaee8c5803fcElliott Hughes void* handle = dlopen("libelf-tls-library.so", RTLD_NOW); 108645a93c13bfa15e8621010570bb98aaee8c5803fcElliott Hughes ASSERT_TRUE(handle == nullptr); 108745a93c13bfa15e8621010570bb98aaee8c5803fcElliott Hughes ASSERT_SUBSTR("unsupported ELF TLS", dlerror()); 108845a93c13bfa15e8621010570bb98aaee8c5803fcElliott Hughes} 108945a93c13bfa15e8621010570bb98aaee8c5803fcElliott Hughes 1090e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott HughesTEST(dlfcn, dlopen_bad_flags) { 1091e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes dlerror(); // Clear any pending errors. 1092e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes void* handle; 1093e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes 1094063525c61d24776094d76971f33920e2a2079530Elliott Hughes#if defined(__GLIBC__) 1095e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes // glibc was smart enough not to define RTLD_NOW as 0, so it can detect missing flags. 1096aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov handle = dlopen(nullptr, 0); 1097aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(handle == nullptr); 1098e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes ASSERT_SUBSTR("invalid", dlerror()); 1099e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes#endif 1100e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes 1101aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov handle = dlopen(nullptr, 0xffffffff); 1102aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(handle == nullptr); 1103e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes ASSERT_SUBSTR("invalid", dlerror()); 1104e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes 1105e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes // glibc actually allows you to choose both RTLD_NOW and RTLD_LAZY at the same time, and so do we. 1106aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov handle = dlopen(nullptr, RTLD_NOW|RTLD_LAZY); 1107aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(handle != nullptr); 1108aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_SUBSTR(nullptr, dlerror()); 1109e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes} 1110ebd506c69e12b6dcaf5be94cc8ed1b53af299f9fSergey Melnikov 1111ebd506c69e12b6dcaf5be94cc8ed1b53af299f9fSergey MelnikovTEST(dlfcn, rtld_default_unknown_symbol) { 11122ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes void* addr = dlsym(RTLD_DEFAULT, "ANY_UNKNOWN_SYMBOL_NAME"); 1113aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(addr == nullptr); 1114ebd506c69e12b6dcaf5be94cc8ed1b53af299f9fSergey Melnikov} 1115ebd506c69e12b6dcaf5be94cc8ed1b53af299f9fSergey Melnikov 1116ebd506c69e12b6dcaf5be94cc8ed1b53af299f9fSergey MelnikovTEST(dlfcn, rtld_default_known_symbol) { 11172ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes void* addr = dlsym(RTLD_DEFAULT, "fopen"); 1118aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(addr != nullptr); 11192ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes} 11202ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes 11212ed710976cb0ace31aab565c95a42d4e75623894Elliott HughesTEST(dlfcn, rtld_next_unknown_symbol) { 11222ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes void* addr = dlsym(RTLD_NEXT, "ANY_UNKNOWN_SYMBOL_NAME"); 1123aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(addr == nullptr); 11242ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes} 11252ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes 11262ed710976cb0ace31aab565c95a42d4e75623894Elliott HughesTEST(dlfcn, rtld_next_known_symbol) { 11272ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes void* addr = dlsym(RTLD_NEXT, "fopen"); 1128aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(addr != nullptr); 1129ebd506c69e12b6dcaf5be94cc8ed1b53af299f9fSergey Melnikov} 11307db180919c335287b201e859faa8ee0dbe281cdeDmitriy Ivanov 1131d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov// Check that RTLD_NEXT of a libc symbol works in dlopened library 1132d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry IvanovTEST(dlfcn, rtld_next_from_library) { 1133153168c855962082d23b3124286005f90ccb39f8dimitry void* library_with_fclose = dlopen("libtest_check_rtld_next_from_library.so", RTLD_NOW | RTLD_GLOBAL); 1134527229cb72121dbd09e40369f67d2cf636d3bf03Raj Mamadgi ASSERT_TRUE(library_with_fclose != nullptr) << dlerror(); 1135527229cb72121dbd09e40369f67d2cf636d3bf03Raj Mamadgi void* expected_addr = dlsym(RTLD_DEFAULT, "fclose"); 1136d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov ASSERT_TRUE(expected_addr != nullptr) << dlerror(); 1137527229cb72121dbd09e40369f67d2cf636d3bf03Raj Mamadgi typedef void* (*get_libc_fclose_ptr_fn_t)(); 1138527229cb72121dbd09e40369f67d2cf636d3bf03Raj Mamadgi get_libc_fclose_ptr_fn_t get_libc_fclose_ptr = 1139527229cb72121dbd09e40369f67d2cf636d3bf03Raj Mamadgi reinterpret_cast<get_libc_fclose_ptr_fn_t>(dlsym(library_with_fclose, "get_libc_fclose_ptr")); 1140527229cb72121dbd09e40369f67d2cf636d3bf03Raj Mamadgi ASSERT_TRUE(get_libc_fclose_ptr != nullptr) << dlerror(); 1141527229cb72121dbd09e40369f67d2cf636d3bf03Raj Mamadgi ASSERT_EQ(expected_addr, get_libc_fclose_ptr()); 1142d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov 1143527229cb72121dbd09e40369f67d2cf636d3bf03Raj Mamadgi dlclose(library_with_fclose); 1144d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov} 1145d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov 1146d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov 1147ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy IvanovTEST(dlfcn, dlsym_weak_func) { 1148ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov dlerror(); 1149bfa88bca5ca387d6b3560074050856527cfc7514Dmitriy Ivanov void* handle = dlopen("libtest_dlsym_weak_func.so", RTLD_NOW); 1150aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(handle != nullptr); 1151ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov 1152ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov int (*weak_func)(); 1153ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov weak_func = reinterpret_cast<int (*)()>(dlsym(handle, "weak_func")); 1154aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(weak_func != nullptr) << "dlerror: " << dlerror(); 1155ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov EXPECT_EQ(42, weak_func()); 1156ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov dlclose(handle); 1157ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov} 1158ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov 1159bfa88bca5ca387d6b3560074050856527cfc7514Dmitriy IvanovTEST(dlfcn, dlopen_undefined_weak_func) { 1160cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov void* handle = dlopen("libtest_dlopen_weak_undefined_func.so", RTLD_NOW); 1161cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 1162cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov int (*weak_func)(); 1163cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov weak_func = reinterpret_cast<int (*)()>(dlsym(handle, "use_weak_undefined_func")); 1164cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov ASSERT_TRUE(weak_func != nullptr) << dlerror(); 1165cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov EXPECT_EQ(6551, weak_func()); 1166cb0443c0fa07e4c049f426e3041894df522732dfDmitriy Ivanov dlclose(handle); 1167bfa88bca5ca387d6b3560074050856527cfc7514Dmitriy Ivanov} 1168bfa88bca5ca387d6b3560074050856527cfc7514Dmitriy Ivanov 11697db180919c335287b201e859faa8ee0dbe281cdeDmitriy IvanovTEST(dlfcn, dlopen_symlink) { 1170708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov DlfcnSymlink symlink("dlopen_symlink"); 1171708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov const std::string symlink_name = basename(symlink.get_symlink_path().c_str()); 11727db180919c335287b201e859faa8ee0dbe281cdeDmitriy Ivanov void* handle1 = dlopen("libdlext_test.so", RTLD_NOW); 1173708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov void* handle2 = dlopen(symlink_name.c_str(), RTLD_NOW); 1174aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(handle1 != nullptr); 1175aff18fd60804e177c319d04dd4c12f3ee1c0cba8Dmitriy Ivanov ASSERT_TRUE(handle2 != nullptr); 11767db180919c335287b201e859faa8ee0dbe281cdeDmitriy Ivanov ASSERT_EQ(handle1, handle2); 1177319356e39cc91b4eb94b1974756f1cfc0a137351Dmitriy Ivanov dlclose(handle1); 1178319356e39cc91b4eb94b1974756f1cfc0a137351Dmitriy Ivanov dlclose(handle2); 11797db180919c335287b201e859faa8ee0dbe281cdeDmitriy Ivanov} 1180279a22f96e639e76c801bdb39aee5576f2280fe0Dmitriy Ivanov 1181279a22f96e639e76c801bdb39aee5576f2280fe0Dmitriy Ivanov// libtest_dlopen_from_ctor_main.so depends on 1182279a22f96e639e76c801bdb39aee5576f2280fe0Dmitriy Ivanov// libtest_dlopen_from_ctor.so which has a constructor 1183279a22f96e639e76c801bdb39aee5576f2280fe0Dmitriy Ivanov// that calls dlopen(libc...). This is to test the situation 1184279a22f96e639e76c801bdb39aee5576f2280fe0Dmitriy Ivanov// described in b/7941716. 1185279a22f96e639e76c801bdb39aee5576f2280fe0Dmitriy IvanovTEST(dlfcn, dlopen_dlopen_from_ctor) { 1186279a22f96e639e76c801bdb39aee5576f2280fe0Dmitriy Ivanov#if defined(__BIONIC__) 1187279a22f96e639e76c801bdb39aee5576f2280fe0Dmitriy Ivanov void* handle = dlopen("libtest_dlopen_from_ctor_main.so", RTLD_NOW); 1188279a22f96e639e76c801bdb39aee5576f2280fe0Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 1189279a22f96e639e76c801bdb39aee5576f2280fe0Dmitriy Ivanov dlclose(handle); 1190279a22f96e639e76c801bdb39aee5576f2280fe0Dmitriy Ivanov#else 1191279a22f96e639e76c801bdb39aee5576f2280fe0Dmitriy Ivanov GTEST_LOG_(INFO) << "This test is disabled for glibc (glibc segfaults if you try to call dlopen from a constructor).\n"; 1192279a22f96e639e76c801bdb39aee5576f2280fe0Dmitriy Ivanov#endif 1193279a22f96e639e76c801bdb39aee5576f2280fe0Dmitriy Ivanov} 11942a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov 1195ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanovstatic std::string g_fini_call_order_str; 1196ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanov 1197ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanovstatic void register_fini_call(const char* s) { 1198ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanov g_fini_call_order_str += s; 1199ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanov} 1200ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanov 1201ec90e24d33837e107b45e7c98b2f5fb4bc115a5eDimitry Ivanovstatic void test_init_fini_call_order_for(const char* libname) { 1202ec90e24d33837e107b45e7c98b2f5fb4bc115a5eDimitry Ivanov g_fini_call_order_str.clear(); 1203ec90e24d33837e107b45e7c98b2f5fb4bc115a5eDimitry Ivanov void* handle = dlopen(libname, RTLD_NOW); 1204ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 1205ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanov typedef int (*get_init_order_number_t)(); 1206ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanov get_init_order_number_t get_init_order_number = 1207ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanov reinterpret_cast<get_init_order_number_t>(dlsym(handle, "get_init_order_number")); 1208ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanov ASSERT_EQ(321, get_init_order_number()); 1209ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanov 1210ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanov typedef void (*set_fini_callback_t)(void (*f)(const char*)); 1211ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanov set_fini_callback_t set_fini_callback = 1212ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanov reinterpret_cast<set_fini_callback_t>(dlsym(handle, "set_fini_callback")); 1213ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanov set_fini_callback(register_fini_call); 1214ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanov dlclose(handle); 1215ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanov ASSERT_EQ("(root)(child)(grandchild)", g_fini_call_order_str); 1216ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanov} 1217ea8f396c59f824993044d9474c2dc04423003c59Dimitry Ivanov 1218ec90e24d33837e107b45e7c98b2f5fb4bc115a5eDimitry IvanovTEST(dlfcn, init_fini_call_order) { 1219ec90e24d33837e107b45e7c98b2f5fb4bc115a5eDimitry Ivanov test_init_fini_call_order_for("libtest_init_fini_order_root.so"); 1220ec90e24d33837e107b45e7c98b2f5fb4bc115a5eDimitry Ivanov test_init_fini_call_order_for("libtest_init_fini_order_root2.so"); 1221ec90e24d33837e107b45e7c98b2f5fb4bc115a5eDimitry Ivanov} 1222ec90e24d33837e107b45e7c98b2f5fb4bc115a5eDimitry Ivanov 12232a815361448d01b0f4e575f507ce31913214c536Dmitriy IvanovTEST(dlfcn, symbol_versioning_use_v1) { 12242a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov void* handle = dlopen("libtest_versioned_uselibv1.so", RTLD_NOW); 12252a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 12262a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov typedef int (*fn_t)(); 12272a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "get_function_version")); 12282a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov ASSERT_TRUE(fn != nullptr) << dlerror(); 12292a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov ASSERT_EQ(1, fn()); 12302a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov dlclose(handle); 12312a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov} 12322a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov 12332a815361448d01b0f4e575f507ce31913214c536Dmitriy IvanovTEST(dlfcn, symbol_versioning_use_v2) { 12342a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov void* handle = dlopen("libtest_versioned_uselibv2.so", RTLD_NOW); 12352a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 12362a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov typedef int (*fn_t)(); 12372a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "get_function_version")); 12382a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov ASSERT_TRUE(fn != nullptr) << dlerror(); 12392a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov ASSERT_EQ(2, fn()); 12402a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov dlclose(handle); 12412a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov} 12422a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov 12432a815361448d01b0f4e575f507ce31913214c536Dmitriy IvanovTEST(dlfcn, symbol_versioning_use_other_v2) { 12442a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov void* handle = dlopen("libtest_versioned_uselibv2_other.so", RTLD_NOW); 12452a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 12462a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov typedef int (*fn_t)(); 12472a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "get_function_version")); 12482a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov ASSERT_TRUE(fn != nullptr) << dlerror(); 12492a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov ASSERT_EQ(20, fn()); 12502a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov dlclose(handle); 12512a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov} 12522a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov 12532a815361448d01b0f4e575f507ce31913214c536Dmitriy IvanovTEST(dlfcn, symbol_versioning_use_other_v3) { 12542a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov void* handle = dlopen("libtest_versioned_uselibv3_other.so", RTLD_NOW); 12552a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 12562a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov typedef int (*fn_t)(); 12572a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "get_function_version")); 12582a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov ASSERT_TRUE(fn != nullptr) << dlerror(); 12592a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov ASSERT_EQ(3, fn()); 12602a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov dlclose(handle); 12612a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov} 12622a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov 12632a815361448d01b0f4e575f507ce31913214c536Dmitriy IvanovTEST(dlfcn, symbol_versioning_default_via_dlsym) { 12642a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov void* handle = dlopen("libtest_versioned_lib.so", RTLD_NOW); 12652a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 12662a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov typedef int (*fn_t)(); 12672a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "versioned_function")); 12682a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov ASSERT_TRUE(fn != nullptr) << dlerror(); 12692a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov ASSERT_EQ(3, fn()); // the default version is 3 12702a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov dlclose(handle); 12712a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov} 12722a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov 12739cf99cbad89c8495828788ce693a99ced434f66fDimitry IvanovTEST(dlfcn, dlvsym_smoke) { 12749cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov void* handle = dlopen("libtest_versioned_lib.so", RTLD_NOW); 12759cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 12769cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov typedef int (*fn_t)(); 12779cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov 12789cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov { 12799cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov fn_t fn = reinterpret_cast<fn_t>(dlvsym(handle, "versioned_function", "nonversion")); 12809cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov ASSERT_TRUE(fn == nullptr); 12819cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov ASSERT_SUBSTR("undefined symbol: versioned_function, version nonversion", dlerror()); 12829cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov } 12839cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov 12849cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov { 12859cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov fn_t fn = reinterpret_cast<fn_t>(dlvsym(handle, "versioned_function", "TESTLIB_V2")); 12869cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov ASSERT_TRUE(fn != nullptr) << dlerror(); 12879cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov ASSERT_EQ(2, fn()); 12889cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov } 12899cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov 12909cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov dlclose(handle); 12919cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov} 12929cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov 12932a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov// This preempts the implementation from libtest_versioned_lib.so 12942a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanovextern "C" int version_zero_function() { 12952a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov return 0; 12962a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov} 12972a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov 12982a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov// This preempts the implementation from libtest_versioned_uselibv*.so 12992a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanovextern "C" int version_zero_function2() { 13002a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov return 0; 13012a815361448d01b0f4e575f507ce31913214c536Dmitriy Ivanov} 13026865082ca6d887766c6651ed2d079dca56a99d32Evgenii Stepanov 13036f2d3104c82f81c1f0123a3cfb25ae670841d0baLazar TrsicTEST(dlfcn, dt_runpath_smoke) { 13046865082ca6d887766c6651ed2d079dca56a99d32Evgenii Stepanov void* handle = dlopen("libtest_dt_runpath_d.so", RTLD_NOW); 13056865082ca6d887766c6651ed2d079dca56a99d32Evgenii Stepanov ASSERT_TRUE(handle != nullptr) << dlerror(); 13066865082ca6d887766c6651ed2d079dca56a99d32Evgenii Stepanov 13076865082ca6d887766c6651ed2d079dca56a99d32Evgenii Stepanov typedef void *(* dlopen_b_fn)(); 13086865082ca6d887766c6651ed2d079dca56a99d32Evgenii Stepanov dlopen_b_fn fn = (dlopen_b_fn)dlsym(handle, "dlopen_b"); 13096865082ca6d887766c6651ed2d079dca56a99d32Evgenii Stepanov ASSERT_TRUE(fn != nullptr) << dlerror(); 13106865082ca6d887766c6651ed2d079dca56a99d32Evgenii Stepanov 13116865082ca6d887766c6651ed2d079dca56a99d32Evgenii Stepanov void *p = fn(); 13120cdef7e7f3c6837b56a969120d9098463d1df8d8Evgenii Stepanov ASSERT_TRUE(p != nullptr); 13136865082ca6d887766c6651ed2d079dca56a99d32Evgenii Stepanov 13146865082ca6d887766c6651ed2d079dca56a99d32Evgenii Stepanov dlclose(handle); 13156865082ca6d887766c6651ed2d079dca56a99d32Evgenii Stepanov} 13166f2d3104c82f81c1f0123a3cfb25ae670841d0baLazar Trsic 1317db6ab3d5ecfe9934cb91a09bc4ccdbf2d15b49fcDimitry IvanovTEST(dlfcn, dt_runpath_absolute_path) { 1318db6ab3d5ecfe9934cb91a09bc4ccdbf2d15b49fcDimitry Ivanov std::string libpath = get_testlib_root() + "/libtest_dt_runpath_d.so"; 1319db6ab3d5ecfe9934cb91a09bc4ccdbf2d15b49fcDimitry Ivanov void* handle = dlopen(libpath.c_str(), RTLD_NOW); 1320db6ab3d5ecfe9934cb91a09bc4ccdbf2d15b49fcDimitry Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 1321db6ab3d5ecfe9934cb91a09bc4ccdbf2d15b49fcDimitry Ivanov 1322db6ab3d5ecfe9934cb91a09bc4ccdbf2d15b49fcDimitry Ivanov typedef void *(* dlopen_b_fn)(); 1323db6ab3d5ecfe9934cb91a09bc4ccdbf2d15b49fcDimitry Ivanov dlopen_b_fn fn = (dlopen_b_fn)dlsym(handle, "dlopen_b"); 1324db6ab3d5ecfe9934cb91a09bc4ccdbf2d15b49fcDimitry Ivanov ASSERT_TRUE(fn != nullptr) << dlerror(); 1325db6ab3d5ecfe9934cb91a09bc4ccdbf2d15b49fcDimitry Ivanov 1326db6ab3d5ecfe9934cb91a09bc4ccdbf2d15b49fcDimitry Ivanov void *p = fn(); 1327db6ab3d5ecfe9934cb91a09bc4ccdbf2d15b49fcDimitry Ivanov ASSERT_TRUE(p != nullptr); 1328db6ab3d5ecfe9934cb91a09bc4ccdbf2d15b49fcDimitry Ivanov 1329db6ab3d5ecfe9934cb91a09bc4ccdbf2d15b49fcDimitry Ivanov dlclose(handle); 1330db6ab3d5ecfe9934cb91a09bc4ccdbf2d15b49fcDimitry Ivanov} 1331db6ab3d5ecfe9934cb91a09bc4ccdbf2d15b49fcDimitry Ivanov 133206016f226efe7aff2736643cb8e719c513948eccdimitryTEST(dlfcn, dlclose_after_thread_local_dtor) { 133306016f226efe7aff2736643cb8e719c513948eccdimitry bool is_dtor_triggered = false; 133406016f226efe7aff2736643cb8e719c513948eccdimitry 133506016f226efe7aff2736643cb8e719c513948eccdimitry auto f = [](void* handle, bool* is_dtor_triggered) { 133606016f226efe7aff2736643cb8e719c513948eccdimitry typedef void (*fn_t)(bool*); 133706016f226efe7aff2736643cb8e719c513948eccdimitry fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "init_thread_local_variable")); 133806016f226efe7aff2736643cb8e719c513948eccdimitry ASSERT_TRUE(fn != nullptr) << dlerror(); 133906016f226efe7aff2736643cb8e719c513948eccdimitry 134006016f226efe7aff2736643cb8e719c513948eccdimitry fn(is_dtor_triggered); 134106016f226efe7aff2736643cb8e719c513948eccdimitry 134206016f226efe7aff2736643cb8e719c513948eccdimitry ASSERT_TRUE(!*is_dtor_triggered); 134306016f226efe7aff2736643cb8e719c513948eccdimitry }; 134406016f226efe7aff2736643cb8e719c513948eccdimitry 134506016f226efe7aff2736643cb8e719c513948eccdimitry void* handle = dlopen("libtest_thread_local_dtor.so", RTLD_NOW | RTLD_NOLOAD); 134606016f226efe7aff2736643cb8e719c513948eccdimitry ASSERT_TRUE(handle == nullptr); 134706016f226efe7aff2736643cb8e719c513948eccdimitry 134806016f226efe7aff2736643cb8e719c513948eccdimitry handle = dlopen("libtest_thread_local_dtor.so", RTLD_NOW); 134906016f226efe7aff2736643cb8e719c513948eccdimitry ASSERT_TRUE(handle != nullptr) << dlerror(); 135006016f226efe7aff2736643cb8e719c513948eccdimitry 135106016f226efe7aff2736643cb8e719c513948eccdimitry std::thread t(f, handle, &is_dtor_triggered); 135206016f226efe7aff2736643cb8e719c513948eccdimitry t.join(); 135306016f226efe7aff2736643cb8e719c513948eccdimitry 135406016f226efe7aff2736643cb8e719c513948eccdimitry ASSERT_TRUE(is_dtor_triggered); 135506016f226efe7aff2736643cb8e719c513948eccdimitry dlclose(handle); 135606016f226efe7aff2736643cb8e719c513948eccdimitry 135706016f226efe7aff2736643cb8e719c513948eccdimitry handle = dlopen("libtest_thread_local_dtor.so", RTLD_NOW | RTLD_NOLOAD); 135806016f226efe7aff2736643cb8e719c513948eccdimitry ASSERT_TRUE(handle == nullptr); 135906016f226efe7aff2736643cb8e719c513948eccdimitry} 136006016f226efe7aff2736643cb8e719c513948eccdimitry 136106016f226efe7aff2736643cb8e719c513948eccdimitryTEST(dlfcn, dlclose_before_thread_local_dtor) { 136206016f226efe7aff2736643cb8e719c513948eccdimitry bool is_dtor_triggered = false; 136306016f226efe7aff2736643cb8e719c513948eccdimitry 136406016f226efe7aff2736643cb8e719c513948eccdimitry auto f = [](bool* is_dtor_triggered) { 136506016f226efe7aff2736643cb8e719c513948eccdimitry void* handle = dlopen("libtest_thread_local_dtor.so", RTLD_NOW | RTLD_NOLOAD); 136606016f226efe7aff2736643cb8e719c513948eccdimitry ASSERT_TRUE(handle == nullptr); 136706016f226efe7aff2736643cb8e719c513948eccdimitry 136806016f226efe7aff2736643cb8e719c513948eccdimitry handle = dlopen("libtest_thread_local_dtor.so", RTLD_NOW); 136906016f226efe7aff2736643cb8e719c513948eccdimitry ASSERT_TRUE(handle != nullptr) << dlerror(); 137006016f226efe7aff2736643cb8e719c513948eccdimitry 137106016f226efe7aff2736643cb8e719c513948eccdimitry typedef void (*fn_t)(bool*); 137206016f226efe7aff2736643cb8e719c513948eccdimitry fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "init_thread_local_variable")); 137306016f226efe7aff2736643cb8e719c513948eccdimitry ASSERT_TRUE(fn != nullptr) << dlerror(); 137406016f226efe7aff2736643cb8e719c513948eccdimitry 137506016f226efe7aff2736643cb8e719c513948eccdimitry fn(is_dtor_triggered); 137606016f226efe7aff2736643cb8e719c513948eccdimitry 137706016f226efe7aff2736643cb8e719c513948eccdimitry dlclose(handle); 137806016f226efe7aff2736643cb8e719c513948eccdimitry 137906016f226efe7aff2736643cb8e719c513948eccdimitry ASSERT_TRUE(!*is_dtor_triggered); 138006016f226efe7aff2736643cb8e719c513948eccdimitry 138106016f226efe7aff2736643cb8e719c513948eccdimitry // Since we have thread_atexit dtors associated with handle - the library should 138206016f226efe7aff2736643cb8e719c513948eccdimitry // still be availabe. 138306016f226efe7aff2736643cb8e719c513948eccdimitry handle = dlopen("libtest_thread_local_dtor.so", RTLD_NOW | RTLD_NOLOAD); 138406016f226efe7aff2736643cb8e719c513948eccdimitry ASSERT_TRUE(handle != nullptr) << dlerror(); 138506016f226efe7aff2736643cb8e719c513948eccdimitry dlclose(handle); 138606016f226efe7aff2736643cb8e719c513948eccdimitry }; 138706016f226efe7aff2736643cb8e719c513948eccdimitry 138806016f226efe7aff2736643cb8e719c513948eccdimitry void* handle = dlopen("libtest_thread_local_dtor.so", RTLD_NOW); 138906016f226efe7aff2736643cb8e719c513948eccdimitry ASSERT_TRUE(handle != nullptr) << dlerror(); 139006016f226efe7aff2736643cb8e719c513948eccdimitry dlclose(handle); 139106016f226efe7aff2736643cb8e719c513948eccdimitry 139206016f226efe7aff2736643cb8e719c513948eccdimitry handle = dlopen("libtest_thread_local_dtor.so", RTLD_NOW | RTLD_NOLOAD); 139306016f226efe7aff2736643cb8e719c513948eccdimitry ASSERT_TRUE(handle == nullptr); 139406016f226efe7aff2736643cb8e719c513948eccdimitry 139506016f226efe7aff2736643cb8e719c513948eccdimitry std::thread t(f, &is_dtor_triggered); 139606016f226efe7aff2736643cb8e719c513948eccdimitry t.join(); 139706016f226efe7aff2736643cb8e719c513948eccdimitry#if defined(__BIONIC__) 139806016f226efe7aff2736643cb8e719c513948eccdimitry // ld-android.so unloads unreferenced libraries on pthread_exit() 139906016f226efe7aff2736643cb8e719c513948eccdimitry ASSERT_TRUE(is_dtor_triggered); 140006016f226efe7aff2736643cb8e719c513948eccdimitry handle = dlopen("libtest_thread_local_dtor.so", RTLD_NOW | RTLD_NOLOAD); 140106016f226efe7aff2736643cb8e719c513948eccdimitry ASSERT_TRUE(handle == nullptr); 140206016f226efe7aff2736643cb8e719c513948eccdimitry#else 140306016f226efe7aff2736643cb8e719c513948eccdimitry // GLIBC does not unload libraries with ref_count = 0 on pthread_exit 140406016f226efe7aff2736643cb8e719c513948eccdimitry ASSERT_TRUE(is_dtor_triggered); 140506016f226efe7aff2736643cb8e719c513948eccdimitry handle = dlopen("libtest_thread_local_dtor.so", RTLD_NOW | RTLD_NOLOAD); 140606016f226efe7aff2736643cb8e719c513948eccdimitry ASSERT_TRUE(handle != nullptr) << dlerror(); 140706016f226efe7aff2736643cb8e719c513948eccdimitry#endif 140806016f226efe7aff2736643cb8e719c513948eccdimitry} 140906016f226efe7aff2736643cb8e719c513948eccdimitry 14108ad40936597c94901b6acb0b21bfe0e2a0689224Elliott HughesTEST(dlfcn, RTLD_macros) { 14118ad40936597c94901b6acb0b21bfe0e2a0689224Elliott Hughes#if !defined(RTLD_LOCAL) 14128ad40936597c94901b6acb0b21bfe0e2a0689224Elliott Hughes#error no RTLD_LOCAL 14138ad40936597c94901b6acb0b21bfe0e2a0689224Elliott Hughes#elif !defined(RTLD_LAZY) 14148ad40936597c94901b6acb0b21bfe0e2a0689224Elliott Hughes#error no RTLD_LAZY 14158ad40936597c94901b6acb0b21bfe0e2a0689224Elliott Hughes#elif !defined(RTLD_NOW) 14168ad40936597c94901b6acb0b21bfe0e2a0689224Elliott Hughes#error no RTLD_NOW 14178ad40936597c94901b6acb0b21bfe0e2a0689224Elliott Hughes#elif !defined(RTLD_NOLOAD) 14188ad40936597c94901b6acb0b21bfe0e2a0689224Elliott Hughes#error no RTLD_NOLOAD 14198ad40936597c94901b6acb0b21bfe0e2a0689224Elliott Hughes#elif !defined(RTLD_GLOBAL) 14208ad40936597c94901b6acb0b21bfe0e2a0689224Elliott Hughes#error no RTLD_GLOBAL 14218ad40936597c94901b6acb0b21bfe0e2a0689224Elliott Hughes#elif !defined(RTLD_NODELETE) 14228ad40936597c94901b6acb0b21bfe0e2a0689224Elliott Hughes#error no RTLD_NODELETE 14238ad40936597c94901b6acb0b21bfe0e2a0689224Elliott Hughes#endif 14248ad40936597c94901b6acb0b21bfe0e2a0689224Elliott Hughes} 14258ad40936597c94901b6acb0b21bfe0e2a0689224Elliott Hughes 1426a36e59bb9973aaae2e3487e0bfadd1f79814097eDimitry Ivanov// Bionic specific tests 1427a36e59bb9973aaae2e3487e0bfadd1f79814097eDimitry Ivanov#if defined(__BIONIC__) 1428a36e59bb9973aaae2e3487e0bfadd1f79814097eDimitry Ivanov 1429b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz#if defined(__arm__) 1430b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitzconst llvm::ELF::Elf32_Dyn* to_dynamic_table(const char* p) { 1431b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz return reinterpret_cast<const llvm::ELF::Elf32_Dyn*>(p); 1432b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz} 1433b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz 1434b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz// Duplicate these definitions here because they are android specific 1435b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz// note that we cannot include <elf.h> because #defines conflict with 1436b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz// enum names provided by LLVM. 1437b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz#define DT_ANDROID_REL (llvm::ELF::DT_LOOS + 2) 1438b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz#define DT_ANDROID_RELA (llvm::ELF::DT_LOOS + 4) 1439b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz 1440b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitztemplate<typename ELFT> 14419dac3e9efdf6b00766b992940c831ca3881b48d5Ryan Prichardvoid validate_compatibility_of_native_library(const std::string& soname, 14429dac3e9efdf6b00766b992940c831ca3881b48d5Ryan Prichard const std::string& path, ELFT* elf) { 1443b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz bool has_elf_hash = false; 1444b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz bool has_android_rel = false; 1445b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz bool has_rel = false; 1446b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz // Find dynamic section and check that DT_HASH and there is no DT_ANDROID_REL 1447b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz for (auto it = elf->section_begin(); it != elf->section_end(); ++it) { 1448b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz const llvm::object::ELFSectionRef& section_ref = *it; 1449b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz if (section_ref.getType() == llvm::ELF::SHT_DYNAMIC) { 1450b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz llvm::StringRef data; 1451b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz ASSERT_TRUE(!it->getContents(data)) << "unable to get SHT_DYNAMIC section data"; 1452b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz for (auto d = to_dynamic_table(data.data()); d->d_tag != llvm::ELF::DT_NULL; ++d) { 1453b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz if (d->d_tag == llvm::ELF::DT_HASH) { 1454b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz has_elf_hash = true; 1455b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz } else if (d->d_tag == DT_ANDROID_REL || d->d_tag == DT_ANDROID_RELA) { 1456b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz has_android_rel = true; 1457b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz } else if (d->d_tag == llvm::ELF::DT_REL || d->d_tag == llvm::ELF::DT_RELA) { 1458b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz has_rel = true; 1459b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz } 1460b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz } 1461b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz 1462b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz break; 1463b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz } 1464b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz } 1465b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz 1466b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz ASSERT_TRUE(has_elf_hash) << path.c_str() << ": missing elf hash (DT_HASH)"; 1467b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz ASSERT_TRUE(!has_android_rel) << path.c_str() << ": has packed relocations"; 14689dac3e9efdf6b00766b992940c831ca3881b48d5Ryan Prichard // libdl.so is simple enough that it might not have any relocations, so 14699dac3e9efdf6b00766b992940c831ca3881b48d5Ryan Prichard // exempt it from the DT_REL/DT_RELA check. 14709dac3e9efdf6b00766b992940c831ca3881b48d5Ryan Prichard if (soname != "libdl.so") { 14719dac3e9efdf6b00766b992940c831ca3881b48d5Ryan Prichard ASSERT_TRUE(has_rel) << path.c_str() << ": missing DT_REL/DT_RELA"; 14729dac3e9efdf6b00766b992940c831ca3881b48d5Ryan Prichard } 1473b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz} 1474b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz 14759dac3e9efdf6b00766b992940c831ca3881b48d5Ryan Prichardvoid validate_compatibility_of_native_library(const std::string& soname) { 1476b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz // On the systems with emulation system libraries would be of different 1477b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz // architecture. Try to use alternate paths first. 1478b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz std::string path = std::string(ALTERNATE_PATH_TO_SYSTEM_LIB) + soname; 1479b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz auto binary_or_error = llvm::object::createBinary(path); 1480b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz if (!binary_or_error) { 1481b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz path = std::string(PATH_TO_SYSTEM_LIB) + soname; 1482b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz binary_or_error = llvm::object::createBinary(path); 1483b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz } 1484b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz ASSERT_FALSE(!binary_or_error); 1485b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz 1486b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz llvm::object::Binary* binary = binary_or_error.get().getBinary(); 1487b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz 1488b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz auto obj = llvm::dyn_cast<llvm::object::ObjectFile>(binary); 1489b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz ASSERT_TRUE(obj != nullptr); 1490b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz 1491b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz auto elf = llvm::dyn_cast<llvm::object::ELF32LEObjectFile>(obj); 1492b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz 1493b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz ASSERT_TRUE(elf != nullptr); 1494b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz 14959dac3e9efdf6b00766b992940c831ca3881b48d5Ryan Prichard validate_compatibility_of_native_library(soname, path, elf); 1496b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz} 1497b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz 1498b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz// This is a test for app compatibility workaround for arm apps 1499b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz// affected by http://b/24465209 1500b6310c2aa704bd30990f4e3152e494b5290972b2Ian PedowitzTEST(dlext, compat_elf_hash_and_relocation_tables) { 1501b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz validate_compatibility_of_native_library("libc.so"); 1502b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz validate_compatibility_of_native_library("liblog.so"); 1503b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz validate_compatibility_of_native_library("libstdc++.so"); 1504b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz validate_compatibility_of_native_library("libdl.so"); 1505b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz validate_compatibility_of_native_library("libm.so"); 1506b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz validate_compatibility_of_native_library("libz.so"); 1507b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz validate_compatibility_of_native_library("libjnigraphics.so"); 1508b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz} 1509b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz 1510b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz#endif // defined(__arm__) 1511b6310c2aa704bd30990f4e3152e494b5290972b2Ian Pedowitz 15129700babc051f5839b4fc861587d63bf06bab6324Dimitry IvanovTEST(dlfcn, dlopen_invalid_rw_load_segment) { 1513d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov const std::string libpath = get_testlib_root() + 1514927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov "/" + kPrebuiltElfDir + 1515927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov "/libtest_invalid-rw_load_segment.so"; 15169700babc051f5839b4fc861587d63bf06bab6324Dimitry Ivanov void* handle = dlopen(libpath.c_str(), RTLD_NOW); 15179700babc051f5839b4fc861587d63bf06bab6324Dimitry Ivanov ASSERT_TRUE(handle == nullptr); 15189076b0c4e78e8680ce40ce48321e8ab81a87705bElliott Hughes std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\": W+E load segments are not allowed"; 15199700babc051f5839b4fc861587d63bf06bab6324Dimitry Ivanov ASSERT_STREQ(expected_dlerror.c_str(), dlerror()); 15209700babc051f5839b4fc861587d63bf06bab6324Dimitry Ivanov} 1521972e3d0787cf177450cdc1b52e177c747b94cabaDimitry Ivanov 1522972e3d0787cf177450cdc1b52e177c747b94cabaDimitry IvanovTEST(dlfcn, dlopen_invalid_unaligned_shdr_offset) { 1523d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov const std::string libpath = get_testlib_root() + 1524927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov "/" + kPrebuiltElfDir + 1525927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov "/libtest_invalid-unaligned_shdr_offset.so"; 1526927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov 1527972e3d0787cf177450cdc1b52e177c747b94cabaDimitry Ivanov void* handle = dlopen(libpath.c_str(), RTLD_NOW); 1528972e3d0787cf177450cdc1b52e177c747b94cabaDimitry Ivanov ASSERT_TRUE(handle == nullptr); 1529972e3d0787cf177450cdc1b52e177c747b94cabaDimitry Ivanov std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\" has invalid shdr offset/size: "; 1530972e3d0787cf177450cdc1b52e177c747b94cabaDimitry Ivanov ASSERT_SUBSTR(expected_dlerror.c_str(), dlerror()); 1531972e3d0787cf177450cdc1b52e177c747b94cabaDimitry Ivanov} 1532972e3d0787cf177450cdc1b52e177c747b94cabaDimitry Ivanov 1533cb86c3128f5e59348d91f2edfa2de908d69cd384Dimitry IvanovTEST(dlfcn, dlopen_invalid_zero_shentsize) { 1534d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov const std::string libpath = get_testlib_root() + 1535927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov "/" + kPrebuiltElfDir + 1536927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov "/libtest_invalid-zero_shentsize.so"; 1537927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov 1538cb86c3128f5e59348d91f2edfa2de908d69cd384Dimitry Ivanov void* handle = dlopen(libpath.c_str(), RTLD_NOW); 1539cb86c3128f5e59348d91f2edfa2de908d69cd384Dimitry Ivanov ASSERT_TRUE(handle == nullptr); 1540cb86c3128f5e59348d91f2edfa2de908d69cd384Dimitry Ivanov std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\" has unsupported e_shentsize: 0x0 (expected 0x"; 1541cb86c3128f5e59348d91f2edfa2de908d69cd384Dimitry Ivanov ASSERT_SUBSTR(expected_dlerror.c_str(), dlerror()); 1542cb86c3128f5e59348d91f2edfa2de908d69cd384Dimitry Ivanov} 1543cb86c3128f5e59348d91f2edfa2de908d69cd384Dimitry Ivanov 1544c9a95613a95b1a275ff897594abb89786ae387edDimitry IvanovTEST(dlfcn, dlopen_invalid_zero_shstrndx) { 1545d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov const std::string libpath = get_testlib_root() + 1546927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov "/" + kPrebuiltElfDir + 1547927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov "/libtest_invalid-zero_shstrndx.so"; 1548927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov 1549c9a95613a95b1a275ff897594abb89786ae387edDimitry Ivanov void* handle = dlopen(libpath.c_str(), RTLD_NOW); 1550c9a95613a95b1a275ff897594abb89786ae387edDimitry Ivanov ASSERT_TRUE(handle == nullptr); 1551c9a95613a95b1a275ff897594abb89786ae387edDimitry Ivanov std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\" has invalid e_shstrndx"; 1552c9a95613a95b1a275ff897594abb89786ae387edDimitry Ivanov ASSERT_STREQ(expected_dlerror.c_str(), dlerror()); 1553c9a95613a95b1a275ff897594abb89786ae387edDimitry Ivanov} 1554c9a95613a95b1a275ff897594abb89786ae387edDimitry Ivanov 15558bdf70e6e481d4ff0c1097f738d8e857a43c1b16Dimitry IvanovTEST(dlfcn, dlopen_invalid_empty_shdr_table) { 1556d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov const std::string libpath = get_testlib_root() + 1557927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov "/" + kPrebuiltElfDir + 1558927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov "/libtest_invalid-empty_shdr_table.so"; 1559927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov 15608bdf70e6e481d4ff0c1097f738d8e857a43c1b16Dimitry Ivanov void* handle = dlopen(libpath.c_str(), RTLD_NOW); 15618bdf70e6e481d4ff0c1097f738d8e857a43c1b16Dimitry Ivanov ASSERT_TRUE(handle == nullptr); 15628bdf70e6e481d4ff0c1097f738d8e857a43c1b16Dimitry Ivanov std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\" has no section headers"; 15638bdf70e6e481d4ff0c1097f738d8e857a43c1b16Dimitry Ivanov ASSERT_STREQ(expected_dlerror.c_str(), dlerror()); 15648bdf70e6e481d4ff0c1097f738d8e857a43c1b16Dimitry Ivanov} 15658bdf70e6e481d4ff0c1097f738d8e857a43c1b16Dimitry Ivanov 156646230445172d3cd72c38102d57f5a1b725c80367Dimitry IvanovTEST(dlfcn, dlopen_invalid_zero_shdr_table_offset) { 1567d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov const std::string libpath = get_testlib_root() + 1568927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov "/" + kPrebuiltElfDir + 1569927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov "/libtest_invalid-zero_shdr_table_offset.so"; 1570927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov 157146230445172d3cd72c38102d57f5a1b725c80367Dimitry Ivanov void* handle = dlopen(libpath.c_str(), RTLD_NOW); 157246230445172d3cd72c38102d57f5a1b725c80367Dimitry Ivanov ASSERT_TRUE(handle == nullptr); 157346230445172d3cd72c38102d57f5a1b725c80367Dimitry Ivanov std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\" has invalid shdr offset/size: 0/"; 157446230445172d3cd72c38102d57f5a1b725c80367Dimitry Ivanov ASSERT_SUBSTR(expected_dlerror.c_str(), dlerror()); 157546230445172d3cd72c38102d57f5a1b725c80367Dimitry Ivanov} 157646230445172d3cd72c38102d57f5a1b725c80367Dimitry Ivanov 1577559583469cd6425cdf3f63bcfc453d7d885ce131Dimitry IvanovTEST(dlfcn, dlopen_invalid_zero_shdr_table_content) { 1578d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov const std::string libpath = get_testlib_root() + 1579927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov "/" + kPrebuiltElfDir + 1580927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov "/libtest_invalid-zero_shdr_table_content.so"; 1581927877c7d3173c1259732e51428f4ae38dc6bc4fDimitry Ivanov 1582559583469cd6425cdf3f63bcfc453d7d885ce131Dimitry Ivanov void* handle = dlopen(libpath.c_str(), RTLD_NOW); 1583559583469cd6425cdf3f63bcfc453d7d885ce131Dimitry Ivanov ASSERT_TRUE(handle == nullptr); 1584559583469cd6425cdf3f63bcfc453d7d885ce131Dimitry Ivanov std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\" .dynamic section header was not found"; 1585559583469cd6425cdf3f63bcfc453d7d885ce131Dimitry Ivanov ASSERT_SUBSTR(expected_dlerror.c_str(), dlerror()); 1586559583469cd6425cdf3f63bcfc453d7d885ce131Dimitry Ivanov} 1587559583469cd6425cdf3f63bcfc453d7d885ce131Dimitry Ivanov 1588816676e70da0e00761b0d23f512ea3571211b3aeDimitry IvanovTEST(dlfcn, dlopen_invalid_textrels) { 1589d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov const std::string libpath = get_testlib_root() + 1590816676e70da0e00761b0d23f512ea3571211b3aeDimitry Ivanov "/" + kPrebuiltElfDir + 1591816676e70da0e00761b0d23f512ea3571211b3aeDimitry Ivanov "/libtest_invalid-textrels.so"; 1592816676e70da0e00761b0d23f512ea3571211b3aeDimitry Ivanov 1593816676e70da0e00761b0d23f512ea3571211b3aeDimitry Ivanov void* handle = dlopen(libpath.c_str(), RTLD_NOW); 1594816676e70da0e00761b0d23f512ea3571211b3aeDimitry Ivanov ASSERT_TRUE(handle == nullptr); 1595816676e70da0e00761b0d23f512ea3571211b3aeDimitry Ivanov std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\" has text relocations"; 1596816676e70da0e00761b0d23f512ea3571211b3aeDimitry Ivanov ASSERT_SUBSTR(expected_dlerror.c_str(), dlerror()); 1597816676e70da0e00761b0d23f512ea3571211b3aeDimitry Ivanov} 1598816676e70da0e00761b0d23f512ea3571211b3aeDimitry Ivanov 1599816676e70da0e00761b0d23f512ea3571211b3aeDimitry IvanovTEST(dlfcn, dlopen_invalid_textrels2) { 1600d0b5c3ad65accd2c0298edbdfd527ede63e68ba1Dimitry Ivanov const std::string libpath = get_testlib_root() + 1601816676e70da0e00761b0d23f512ea3571211b3aeDimitry Ivanov "/" + kPrebuiltElfDir + 1602816676e70da0e00761b0d23f512ea3571211b3aeDimitry Ivanov "/libtest_invalid-textrels2.so"; 1603816676e70da0e00761b0d23f512ea3571211b3aeDimitry Ivanov 1604816676e70da0e00761b0d23f512ea3571211b3aeDimitry Ivanov void* handle = dlopen(libpath.c_str(), RTLD_NOW); 1605816676e70da0e00761b0d23f512ea3571211b3aeDimitry Ivanov ASSERT_TRUE(handle == nullptr); 1606816676e70da0e00761b0d23f512ea3571211b3aeDimitry Ivanov std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\" has text relocations"; 1607816676e70da0e00761b0d23f512ea3571211b3aeDimitry Ivanov ASSERT_SUBSTR(expected_dlerror.c_str(), dlerror()); 1608816676e70da0e00761b0d23f512ea3571211b3aeDimitry Ivanov} 1609816676e70da0e00761b0d23f512ea3571211b3aeDimitry Ivanov 161001162f24696aedd0f80fde006596bec7786ac684Jiyong ParkTEST(dlfcn, dlopen_df_1_global) { 161101162f24696aedd0f80fde006596bec7786ac684Jiyong Park void* handle = dlopen("libtest_dlopen_df_1_global.so", RTLD_NOW); 161201162f24696aedd0f80fde006596bec7786ac684Jiyong Park ASSERT_TRUE(handle != nullptr) << dlerror(); 161301162f24696aedd0f80fde006596bec7786ac684Jiyong Park} 161401162f24696aedd0f80fde006596bec7786ac684Jiyong Park 16159700babc051f5839b4fc861587d63bf06bab6324Dimitry Ivanov#endif 1616