1acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao/* 2acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao * Copyright (C) 2012 The Android Open Source Project 3acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao * 4acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao * Licensed under the Apache License, Version 2.0 (the "License"); 5acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao * you may not use this file except in compliance with the License. 6acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao * You may obtain a copy of the License at 7acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao * 8acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao * http://www.apache.org/licenses/LICENSE-2.0 9acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao * 10acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao * Unless required by applicable law or agreed to in writing, software 11acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao * distributed under the License is distributed on an "AS IS" BASIS, 12acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao * See the License for the specific language governing permissions and 14acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao * limitations under the License. 15acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao */ 16acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao 17acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao#include <gtest/gtest.h> 18acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao 19acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao#include <dlfcn.h> 208e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes#include <libgen.h> 218e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes#include <limits.h> 228e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes#include <stdio.h> 238e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes#include <stdint.h> 248e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 258e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes#include <string> 26acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao 273b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes#define ASSERT_SUBSTR(needle, haystack) \ 283b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_PRED_FORMAT2(::testing::IsSubstring, needle, haystack) 293b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 301728b2396591853345507a063ed6075dfd251706Elliott Hughesstatic bool g_called = false; 31acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhaoextern "C" void DlSymTestFunction() { 321728b2396591853345507a063ed6075dfd251706Elliott Hughes g_called = true; 33acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao} 34acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao 35f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanovstatic int g_ctor_function_called = 0; 36f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanov 37f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanovextern "C" void ctor_function() __attribute__ ((constructor)); 38f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanov 39f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanovextern "C" void ctor_function() { 40f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanov g_ctor_function_called = 17; 41f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanov} 42f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanov 43f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy IvanovTEST(dlfcn, ctor_function_call) { 44f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanov ASSERT_EQ(17, g_ctor_function_called); 45f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanov} 46f8846a45878faa9eb51fab3a2b347e9a36ecd250Dmitriy Ivanov 47e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott HughesTEST(dlfcn, dlsym_in_self) { 483b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes dlerror(); // Clear any pending errors. 49acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao void* self = dlopen(NULL, RTLD_NOW); 50acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao ASSERT_TRUE(self != NULL); 513b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_TRUE(dlerror() == NULL); 52acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao 53acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao void* sym = dlsym(self, "DlSymTestFunction"); 54acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao ASSERT_TRUE(sym != NULL); 55acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao 56acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao void (*function)() = reinterpret_cast<void(*)()>(sym); 57acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao 581728b2396591853345507a063ed6075dfd251706Elliott Hughes g_called = false; 59acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao function(); 601728b2396591853345507a063ed6075dfd251706Elliott Hughes ASSERT_TRUE(g_called); 611a6961650c82168864afe040dbdc05977db701dfElliott Hughes 621a6961650c82168864afe040dbdc05977db701dfElliott Hughes ASSERT_EQ(0, dlclose(self)); 63acf5aa76a56f101607aeb8e6d1fbea24d0d4f68cjeffhao} 648e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 65db7a17d4ff56a05af01ee2fee1f3c55245bfc630Dmitriy IvanovTEST(dlfcn, dlsym_with_dependencies) { 66db7a17d4ff56a05af01ee2fee1f3c55245bfc630Dmitriy Ivanov void* handle = dlopen("libtest_with_dependency.so", RTLD_NOW); 67db7a17d4ff56a05af01ee2fee1f3c55245bfc630Dmitriy Ivanov ASSERT_TRUE(handle != NULL); 68db7a17d4ff56a05af01ee2fee1f3c55245bfc630Dmitriy Ivanov dlerror(); 69db7a17d4ff56a05af01ee2fee1f3c55245bfc630Dmitriy Ivanov // This symbol is in DT_NEEDED library. 70db7a17d4ff56a05af01ee2fee1f3c55245bfc630Dmitriy Ivanov void* sym = dlsym(handle, "getRandomNumber"); 71db7a17d4ff56a05af01ee2fee1f3c55245bfc630Dmitriy Ivanov ASSERT_TRUE(sym != NULL); 72db7a17d4ff56a05af01ee2fee1f3c55245bfc630Dmitriy Ivanov int (*fn)(void); 73db7a17d4ff56a05af01ee2fee1f3c55245bfc630Dmitriy Ivanov fn = reinterpret_cast<int (*)(void)>(sym); 74db7a17d4ff56a05af01ee2fee1f3c55245bfc630Dmitriy Ivanov EXPECT_EQ(4, fn()); 75db7a17d4ff56a05af01ee2fee1f3c55245bfc630Dmitriy Ivanov dlclose(handle); 76db7a17d4ff56a05af01ee2fee1f3c55245bfc630Dmitriy Ivanov} 77db7a17d4ff56a05af01ee2fee1f3c55245bfc630Dmitriy Ivanov 78b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy IvanovTEST(dlfcn, dlopen_noload) { 79b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov void* handle = dlopen("libtest_simple.so", RTLD_NOW | RTLD_NOLOAD); 80b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov ASSERT_TRUE(handle == NULL); 81b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov handle = dlopen("libtest_simple.so", RTLD_NOW); 82b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov void* handle2 = dlopen("libtest_simple.so", RTLD_NOW | RTLD_NOLOAD); 83b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov ASSERT_TRUE(handle != NULL); 84b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov ASSERT_TRUE(handle2 != NULL); 85b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov ASSERT_TRUE(handle == handle2); 86b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov ASSERT_EQ(0, dlclose(handle)); 87b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov ASSERT_EQ(0, dlclose(handle2)); 88b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov} 89b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov 90e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott HughesTEST(dlfcn, dlopen_failure) { 913b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes void* self = dlopen("/does/not/exist", RTLD_NOW); 923b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_TRUE(self == NULL); 93063525c61d24776094d76971f33920e2a2079530Elliott Hughes#if defined(__BIONIC__) 943b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_STREQ("dlopen failed: library \"/does/not/exist\" not found", dlerror()); 953b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes#else 963b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_STREQ("/does/not/exist: cannot open shared object file: No such file or directory", dlerror()); 973b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes#endif 983b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes} 993b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 100ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughesstatic void* ConcurrentDlErrorFn(void*) { 1015419b9474753d25dff947c7740532f86d130c0beElliott Hughes dlopen("/child/thread", RTLD_NOW); 1025419b9474753d25dff947c7740532f86d130c0beElliott Hughes return reinterpret_cast<void*>(strdup(dlerror())); 1035419b9474753d25dff947c7740532f86d130c0beElliott Hughes} 1045419b9474753d25dff947c7740532f86d130c0beElliott Hughes 105e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott HughesTEST(dlfcn, dlerror_concurrent) { 1065419b9474753d25dff947c7740532f86d130c0beElliott Hughes dlopen("/main/thread", RTLD_NOW); 1075419b9474753d25dff947c7740532f86d130c0beElliott Hughes const char* main_thread_error = dlerror(); 1085419b9474753d25dff947c7740532f86d130c0beElliott Hughes ASSERT_SUBSTR("/main/thread", main_thread_error); 1095419b9474753d25dff947c7740532f86d130c0beElliott Hughes 1105419b9474753d25dff947c7740532f86d130c0beElliott Hughes pthread_t t; 1115419b9474753d25dff947c7740532f86d130c0beElliott Hughes ASSERT_EQ(0, pthread_create(&t, NULL, ConcurrentDlErrorFn, NULL)); 1125419b9474753d25dff947c7740532f86d130c0beElliott Hughes void* result; 1135419b9474753d25dff947c7740532f86d130c0beElliott Hughes ASSERT_EQ(0, pthread_join(t, &result)); 1145419b9474753d25dff947c7740532f86d130c0beElliott Hughes char* child_thread_error = static_cast<char*>(result); 1155419b9474753d25dff947c7740532f86d130c0beElliott Hughes ASSERT_SUBSTR("/child/thread", child_thread_error); 1165419b9474753d25dff947c7740532f86d130c0beElliott Hughes free(child_thread_error); 1175419b9474753d25dff947c7740532f86d130c0beElliott Hughes 1185419b9474753d25dff947c7740532f86d130c0beElliott Hughes ASSERT_SUBSTR("/main/thread", main_thread_error); 1195419b9474753d25dff947c7740532f86d130c0beElliott Hughes} 1205419b9474753d25dff947c7740532f86d130c0beElliott Hughes 121e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott HughesTEST(dlfcn, dlsym_failures) { 1223b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes dlerror(); // Clear any pending errors. 1233b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes void* self = dlopen(NULL, RTLD_NOW); 1243b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_TRUE(self != NULL); 1253b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_TRUE(dlerror() == NULL); 1263b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 1273b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes void* sym; 1283b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 12944adf93b8eddb3a7965a3e9abc189408a1f5a7eaDmitriy Ivanov#if defined(__BIONIC__) && !defined(__LP64__) 13044adf93b8eddb3a7965a3e9abc189408a1f5a7eaDmitriy Ivanov // RTLD_DEFAULT in lp32 bionic is not (void*)0 13144adf93b8eddb3a7965a3e9abc189408a1f5a7eaDmitriy Ivanov // so it can be distinguished from the NULL handle. 1323b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes sym = dlsym(NULL, "test"); 1333b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_TRUE(sym == NULL); 1343b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_SUBSTR("dlsym library handle is null", dlerror()); 1353b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes#endif 1363b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 1373b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes // NULL symbol name. 138063525c61d24776094d76971f33920e2a2079530Elliott Hughes#if defined(__BIONIC__) 1393b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes // glibc marks this parameter non-null and SEGVs if you cheat. 1403b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes sym = dlsym(self, NULL); 1413b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_TRUE(sym == NULL); 1423b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_SUBSTR("", dlerror()); 1433b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes#endif 1443b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 1453b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes // Symbol that doesn't exist. 1463b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes sym = dlsym(self, "ThisSymbolDoesNotExist"); 1473b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_TRUE(sym == NULL); 1483b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_SUBSTR("undefined symbol: ThisSymbolDoesNotExist", dlerror()); 1491a6961650c82168864afe040dbdc05977db701dfElliott Hughes 1501a6961650c82168864afe040dbdc05977db701dfElliott Hughes ASSERT_EQ(0, dlclose(self)); 1513b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes} 1523b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 153e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott HughesTEST(dlfcn, dladdr) { 1543b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes dlerror(); // Clear any pending errors. 1558e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes void* self = dlopen(NULL, RTLD_NOW); 1568e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_TRUE(self != NULL); 1573b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_TRUE(dlerror() == NULL); 1588e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 1598e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes void* sym = dlsym(self, "DlSymTestFunction"); 1608e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_TRUE(sym != NULL); 1618e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 1628e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // Deliberately ask dladdr for an address inside a symbol, rather than the symbol base address. 1638e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes void* addr = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(sym) + 2); 1648e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 1658e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes Dl_info info; 1668e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes int rc = dladdr(addr, &info); 1678e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_NE(rc, 0); // Zero on error, non-zero on success. 1688e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 1698e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // Get the name of this executable. 1708e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes char executable_path[PATH_MAX]; 1718e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes rc = readlink("/proc/self/exe", executable_path, sizeof(executable_path)); 1728e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_NE(rc, -1); 1738e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes executable_path[rc] = '\0'; 1748e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes std::string executable_name(basename(executable_path)); 1758e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 1768e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // The filename should be that of this executable. 1778e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // Note that we don't know whether or not we have the full path, so we want an "ends_with" test. 1788e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes std::string dli_fname(info.dli_fname); 1798e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes dli_fname = basename(&dli_fname[0]); 1808e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_EQ(dli_fname, executable_name); 1818e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 1828e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // The symbol name should be the symbol we looked up. 1838e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_STREQ(info.dli_sname, "DlSymTestFunction"); 1848e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 1858e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // The address should be the exact address of the symbol. 1868e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_EQ(info.dli_saddr, sym); 1878e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 1888e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // Look in /proc/pid/maps to find out what address we were loaded at. 1898e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // TODO: factor /proc/pid/maps parsing out into a class and reuse all over bionic. 1908e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes void* base_address = NULL; 1918e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes char line[BUFSIZ]; 192642182341018b282148280a7bdb771493e15bd7dElliott Hughes FILE* fp = fopen("/proc/self/maps", "r"); 1938e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_TRUE(fp != NULL); 1948e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes while (fgets(line, sizeof(line), fp) != NULL) { 1958e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes uintptr_t start = strtoul(line, 0, 16); 1968e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes line[strlen(line) - 1] = '\0'; // Chomp the '\n'. 1978e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes char* path = strchr(line, '/'); 198156da966214957c5616a0b83cc84686eedfc4e31Elliott Hughes if (path != NULL && strcmp(executable_path, path) == 0) { 1998e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes base_address = reinterpret_cast<void*>(start); 2008e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes break; 2018e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes } 2028e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes } 2038e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes fclose(fp); 2048e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 2058e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // The base address should be the address we were loaded at. 2068e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_EQ(info.dli_fbase, base_address); 2071a6961650c82168864afe040dbdc05977db701dfElliott Hughes 2081a6961650c82168864afe040dbdc05977db701dfElliott Hughes ASSERT_EQ(0, dlclose(self)); 2098e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes} 2108e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 211e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott HughesTEST(dlfcn, dladdr_invalid) { 2128e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes Dl_info info; 2138e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 2143b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes dlerror(); // Clear any pending errors. 2153b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 2168e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // No symbol corresponding to NULL. 2178e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_EQ(dladdr(NULL, &info), 0); // Zero on error, non-zero on success. 2183b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_TRUE(dlerror() == NULL); // dladdr(3) doesn't set dlerror(3). 2198e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes 2208e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes // No symbol corresponding to a stack address. 2218e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes ASSERT_EQ(dladdr(&info, &info), 0); // Zero on error, non-zero on success. 2223b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes ASSERT_TRUE(dlerror() == NULL); // dladdr(3) doesn't set dlerror(3). 2238e15b08ae22a5230c1fea4779410de0420fa939cElliott Hughes} 224124fae9eabd7a25d80dfa8c3b56bed0f0fba16f1Elliott Hughes 225124fae9eabd7a25d80dfa8c3b56bed0f0fba16f1Elliott Hughes// Our dynamic linker doesn't support GNU hash tables. 226a43e906221a3e9c70a66118a8692cd46f77e144eElliott Hughes#if defined(__BIONIC__) 227a43e906221a3e9c70a66118a8692cd46f77e144eElliott Hughes// GNU-style ELF hash tables are incompatible with the MIPS ABI. 228a43e906221a3e9c70a66118a8692cd46f77e144eElliott Hughes// MIPS requires .dynsym to be sorted to match the GOT but GNU-style requires sorting by hash code. 229a43e906221a3e9c70a66118a8692cd46f77e144eElliott Hughes#if !defined(__mips__) 230e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott HughesTEST(dlfcn, dlopen_library_with_only_gnu_hash) { 231124fae9eabd7a25d80dfa8c3b56bed0f0fba16f1Elliott Hughes dlerror(); // Clear any pending errors. 2326e33b0296d23c75bdefa53f0bf0b08c0d877a652Elliott Hughes void* handle = dlopen("no-elf-hash-table-library.so", RTLD_NOW); 233124fae9eabd7a25d80dfa8c3b56bed0f0fba16f1Elliott Hughes ASSERT_TRUE(handle == NULL); 2346e33b0296d23c75bdefa53f0bf0b08c0d877a652Elliott Hughes ASSERT_STREQ("dlopen failed: empty/missing DT_HASH in \"no-elf-hash-table-library.so\" (built with --hash-style=gnu?)", dlerror()); 235124fae9eabd7a25d80dfa8c3b56bed0f0fba16f1Elliott Hughes} 236124fae9eabd7a25d80dfa8c3b56bed0f0fba16f1Elliott Hughes#endif 237a43e906221a3e9c70a66118a8692cd46f77e144eElliott Hughes#endif 238e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes 239e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott HughesTEST(dlfcn, dlopen_bad_flags) { 240e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes dlerror(); // Clear any pending errors. 241e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes void* handle; 242e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes 243063525c61d24776094d76971f33920e2a2079530Elliott Hughes#if defined(__GLIBC__) 244e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes // glibc was smart enough not to define RTLD_NOW as 0, so it can detect missing flags. 245e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes handle = dlopen(NULL, 0); 246e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes ASSERT_TRUE(handle == NULL); 247e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes ASSERT_SUBSTR("invalid", dlerror()); 248e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes#endif 249e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes 250e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes handle = dlopen(NULL, 0xffffffff); 251e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes ASSERT_TRUE(handle == NULL); 252e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes ASSERT_SUBSTR("invalid", dlerror()); 253e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes 254e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes // glibc actually allows you to choose both RTLD_NOW and RTLD_LAZY at the same time, and so do we. 255e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes handle = dlopen(NULL, RTLD_NOW|RTLD_LAZY); 256e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes ASSERT_TRUE(handle != NULL); 257e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes ASSERT_SUBSTR(NULL, dlerror()); 258e66190d2a97a713ae4b4786e60ca3d67ab8aa192Elliott Hughes} 259ebd506c69e12b6dcaf5be94cc8ed1b53af299f9fSergey Melnikov 260ebd506c69e12b6dcaf5be94cc8ed1b53af299f9fSergey MelnikovTEST(dlfcn, rtld_default_unknown_symbol) { 2612ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes void* addr = dlsym(RTLD_DEFAULT, "ANY_UNKNOWN_SYMBOL_NAME"); 262ebd506c69e12b6dcaf5be94cc8ed1b53af299f9fSergey Melnikov ASSERT_TRUE(addr == NULL); 263ebd506c69e12b6dcaf5be94cc8ed1b53af299f9fSergey Melnikov} 264ebd506c69e12b6dcaf5be94cc8ed1b53af299f9fSergey Melnikov 265ebd506c69e12b6dcaf5be94cc8ed1b53af299f9fSergey MelnikovTEST(dlfcn, rtld_default_known_symbol) { 2662ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes void* addr = dlsym(RTLD_DEFAULT, "fopen"); 2672ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes ASSERT_TRUE(addr != NULL); 2682ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes} 2692ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes 2702ed710976cb0ace31aab565c95a42d4e75623894Elliott HughesTEST(dlfcn, rtld_next_unknown_symbol) { 2712ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes void* addr = dlsym(RTLD_NEXT, "ANY_UNKNOWN_SYMBOL_NAME"); 2722ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes ASSERT_TRUE(addr == NULL); 2732ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes} 2742ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes 2752ed710976cb0ace31aab565c95a42d4e75623894Elliott HughesTEST(dlfcn, rtld_next_known_symbol) { 2762ed710976cb0ace31aab565c95a42d4e75623894Elliott Hughes void* addr = dlsym(RTLD_NEXT, "fopen"); 277ebd506c69e12b6dcaf5be94cc8ed1b53af299f9fSergey Melnikov ASSERT_TRUE(addr != NULL); 278ebd506c69e12b6dcaf5be94cc8ed1b53af299f9fSergey Melnikov} 2797db180919c335287b201e859faa8ee0dbe281cdeDmitriy Ivanov 280ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy IvanovTEST(dlfcn, dlsym_weak_func) { 281ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov dlerror(); 282ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov void* handle = dlopen("libtest_dlsym_weak_func.so",RTLD_NOW); 283ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov ASSERT_TRUE(handle != NULL); 284ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov 285ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov int (*weak_func)(); 286ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov weak_func = reinterpret_cast<int (*)()>(dlsym(handle, "weak_func")); 287ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov ASSERT_TRUE(weak_func != NULL) << "dlerror: " << dlerror(); 288ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov EXPECT_EQ(42, weak_func()); 289ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov dlclose(handle); 290ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov} 291ce44166c737b6737c3a0820bef10b074a5e36cf8Dmitriy Ivanov 2927db180919c335287b201e859faa8ee0dbe281cdeDmitriy IvanovTEST(dlfcn, dlopen_symlink) { 2937db180919c335287b201e859faa8ee0dbe281cdeDmitriy Ivanov void* handle1 = dlopen("libdlext_test.so", RTLD_NOW); 2947db180919c335287b201e859faa8ee0dbe281cdeDmitriy Ivanov void* handle2 = dlopen("libdlext_test_v2.so", RTLD_NOW); 2957db180919c335287b201e859faa8ee0dbe281cdeDmitriy Ivanov ASSERT_TRUE(handle1 != NULL); 2967db180919c335287b201e859faa8ee0dbe281cdeDmitriy Ivanov ASSERT_TRUE(handle2 != NULL); 2977db180919c335287b201e859faa8ee0dbe281cdeDmitriy Ivanov ASSERT_EQ(handle1, handle2); 2987db180919c335287b201e859faa8ee0dbe281cdeDmitriy Ivanov} 299