1*8d67ca89SAndroid Build Coastguard Worker /*
2*8d67ca89SAndroid Build Coastguard Worker * Copyright (C) 2012 The Android Open Source Project
3*8d67ca89SAndroid Build Coastguard Worker *
4*8d67ca89SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*8d67ca89SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*8d67ca89SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*8d67ca89SAndroid Build Coastguard Worker *
8*8d67ca89SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*8d67ca89SAndroid Build Coastguard Worker *
10*8d67ca89SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*8d67ca89SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*8d67ca89SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*8d67ca89SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*8d67ca89SAndroid Build Coastguard Worker * limitations under the License.
15*8d67ca89SAndroid Build Coastguard Worker */
16*8d67ca89SAndroid Build Coastguard Worker
17*8d67ca89SAndroid Build Coastguard Worker #include <gtest/gtest.h>
18*8d67ca89SAndroid Build Coastguard Worker
19*8d67ca89SAndroid Build Coastguard Worker #include <dlfcn.h>
20*8d67ca89SAndroid Build Coastguard Worker #include <elf.h>
21*8d67ca89SAndroid Build Coastguard Worker #include <limits.h>
22*8d67ca89SAndroid Build Coastguard Worker #include <link.h>
23*8d67ca89SAndroid Build Coastguard Worker #include <stdint.h>
24*8d67ca89SAndroid Build Coastguard Worker #include <stdio.h>
25*8d67ca89SAndroid Build Coastguard Worker #include <string.h>
26*8d67ca89SAndroid Build Coastguard Worker #include <sys/cdefs.h>
27*8d67ca89SAndroid Build Coastguard Worker #if __has_include(<sys/auxv.h>)
28*8d67ca89SAndroid Build Coastguard Worker #include <sys/auxv.h>
29*8d67ca89SAndroid Build Coastguard Worker #endif
30*8d67ca89SAndroid Build Coastguard Worker #include <sys/user.h>
31*8d67ca89SAndroid Build Coastguard Worker
32*8d67ca89SAndroid Build Coastguard Worker #include <string>
33*8d67ca89SAndroid Build Coastguard Worker #include <thread>
34*8d67ca89SAndroid Build Coastguard Worker
35*8d67ca89SAndroid Build Coastguard Worker #include <android-base/file.h>
36*8d67ca89SAndroid Build Coastguard Worker #include <android-base/macros.h>
37*8d67ca89SAndroid Build Coastguard Worker #include <android-base/scopeguard.h>
38*8d67ca89SAndroid Build Coastguard Worker
39*8d67ca89SAndroid Build Coastguard Worker #include "gtest_globals.h"
40*8d67ca89SAndroid Build Coastguard Worker #include "gtest_utils.h"
41*8d67ca89SAndroid Build Coastguard Worker #include "dlfcn_symlink_support.h"
42*8d67ca89SAndroid Build Coastguard Worker #include "utils.h"
43*8d67ca89SAndroid Build Coastguard Worker
44*8d67ca89SAndroid Build Coastguard Worker #define ASSERT_SUBSTR(needle, haystack) \
45*8d67ca89SAndroid Build Coastguard Worker ASSERT_PRED_FORMAT2(::testing::IsSubstring, needle, haystack)
46*8d67ca89SAndroid Build Coastguard Worker
47*8d67ca89SAndroid Build Coastguard Worker
48*8d67ca89SAndroid Build Coastguard Worker static bool g_called = false;
DlSymTestFunction()49*8d67ca89SAndroid Build Coastguard Worker extern "C" void DlSymTestFunction() {
50*8d67ca89SAndroid Build Coastguard Worker g_called = true;
51*8d67ca89SAndroid Build Coastguard Worker }
52*8d67ca89SAndroid Build Coastguard Worker
53*8d67ca89SAndroid Build Coastguard Worker static int g_ctor_function_called = 0;
54*8d67ca89SAndroid Build Coastguard Worker static int g_ctor_argc = 0;
55*8d67ca89SAndroid Build Coastguard Worker static char** g_ctor_argv = reinterpret_cast<char**>(0xDEADBEEF);
56*8d67ca89SAndroid Build Coastguard Worker static char** g_ctor_envp = g_ctor_envp;
57*8d67ca89SAndroid Build Coastguard Worker
58*8d67ca89SAndroid Build Coastguard Worker extern "C" void ctor_function(int argc, char** argv, char** envp) __attribute__ ((constructor));
59*8d67ca89SAndroid Build Coastguard Worker
ctor_function(int argc,char ** argv,char ** envp)60*8d67ca89SAndroid Build Coastguard Worker extern "C" void ctor_function(int argc, char** argv, char** envp) {
61*8d67ca89SAndroid Build Coastguard Worker g_ctor_function_called = 17;
62*8d67ca89SAndroid Build Coastguard Worker g_ctor_argc = argc;
63*8d67ca89SAndroid Build Coastguard Worker g_ctor_argv = argv;
64*8d67ca89SAndroid Build Coastguard Worker g_ctor_envp = envp;
65*8d67ca89SAndroid Build Coastguard Worker }
66*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,ctor_function_call)67*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, ctor_function_call) {
68*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(17, g_ctor_function_called);
69*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(g_ctor_argc = GetArgc());
70*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(g_ctor_argv = GetArgv());
71*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(g_ctor_envp = GetEnvp());
72*8d67ca89SAndroid Build Coastguard Worker }
73*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlsym_in_executable)74*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlsym_in_executable) {
75*8d67ca89SAndroid Build Coastguard Worker dlerror(); // Clear any pending errors.
76*8d67ca89SAndroid Build Coastguard Worker void* self = dlopen(nullptr, RTLD_NOW);
77*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(self != nullptr);
78*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(dlerror() == nullptr);
79*8d67ca89SAndroid Build Coastguard Worker
80*8d67ca89SAndroid Build Coastguard Worker void* sym = dlsym(self, "DlSymTestFunction");
81*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(sym != nullptr);
82*8d67ca89SAndroid Build Coastguard Worker
83*8d67ca89SAndroid Build Coastguard Worker void (*function)() = reinterpret_cast<void(*)()>(sym);
84*8d67ca89SAndroid Build Coastguard Worker
85*8d67ca89SAndroid Build Coastguard Worker g_called = false;
86*8d67ca89SAndroid Build Coastguard Worker function();
87*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(g_called);
88*8d67ca89SAndroid Build Coastguard Worker
89*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, dlclose(self));
90*8d67ca89SAndroid Build Coastguard Worker }
91*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlsym_from_sofile)92*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlsym_from_sofile) {
93*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_LAZY | RTLD_LOCAL);
94*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
95*8d67ca89SAndroid Build Coastguard Worker
96*8d67ca89SAndroid Build Coastguard Worker // check that we can't find '_test_dlsym_symbol' via dlsym(RTLD_DEFAULT)
97*8d67ca89SAndroid Build Coastguard Worker void* symbol = dlsym(RTLD_DEFAULT, "test_dlsym_symbol");
98*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(symbol == nullptr);
99*8d67ca89SAndroid Build Coastguard Worker ASSERT_SUBSTR("undefined symbol: test_dlsym_symbol", dlerror());
100*8d67ca89SAndroid Build Coastguard Worker
101*8d67ca89SAndroid Build Coastguard Worker typedef int* (*fn_t)();
102*8d67ca89SAndroid Build Coastguard Worker fn_t lookup_dlsym_symbol_using_RTLD_DEFAULT =
103*8d67ca89SAndroid Build Coastguard Worker reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol_using_RTLD_DEFAULT"));
104*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(lookup_dlsym_symbol_using_RTLD_DEFAULT != nullptr) << dlerror();
105*8d67ca89SAndroid Build Coastguard Worker
106*8d67ca89SAndroid Build Coastguard Worker int* ptr = lookup_dlsym_symbol_using_RTLD_DEFAULT();
107*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(ptr != nullptr) << dlerror();
108*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(42, *ptr);
109*8d67ca89SAndroid Build Coastguard Worker
110*8d67ca89SAndroid Build Coastguard Worker fn_t lookup_dlsym_symbol2_using_RTLD_DEFAULT =
111*8d67ca89SAndroid Build Coastguard Worker reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol2_using_RTLD_DEFAULT"));
112*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(lookup_dlsym_symbol2_using_RTLD_DEFAULT != nullptr) << dlerror();
113*8d67ca89SAndroid Build Coastguard Worker
114*8d67ca89SAndroid Build Coastguard Worker ptr = lookup_dlsym_symbol2_using_RTLD_DEFAULT();
115*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(ptr != nullptr) << dlerror();
116*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(44, *ptr);
117*8d67ca89SAndroid Build Coastguard Worker
118*8d67ca89SAndroid Build Coastguard Worker fn_t lookup_dlsym_symbol_using_RTLD_NEXT =
119*8d67ca89SAndroid Build Coastguard Worker reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol_using_RTLD_NEXT"));
120*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(lookup_dlsym_symbol_using_RTLD_NEXT != nullptr) << dlerror();
121*8d67ca89SAndroid Build Coastguard Worker
122*8d67ca89SAndroid Build Coastguard Worker ptr = lookup_dlsym_symbol_using_RTLD_NEXT();
123*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(ptr != nullptr) << dlerror();
124*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(43, *ptr);
125*8d67ca89SAndroid Build Coastguard Worker
126*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
127*8d67ca89SAndroid Build Coastguard Worker }
128*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlsym_from_sofile_with_preload)129*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlsym_from_sofile_with_preload) {
130*8d67ca89SAndroid Build Coastguard Worker void* preload = dlopen("libtest_dlsym_from_this_grandchild.so", RTLD_NOW | RTLD_LOCAL);
131*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(preload != nullptr) << dlerror();
132*8d67ca89SAndroid Build Coastguard Worker
133*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_NOW | RTLD_LOCAL);
134*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
135*8d67ca89SAndroid Build Coastguard Worker
136*8d67ca89SAndroid Build Coastguard Worker // check that we can't find '_test_dlsym_symbol' via dlsym(RTLD_DEFAULT)
137*8d67ca89SAndroid Build Coastguard Worker void* symbol = dlsym(RTLD_DEFAULT, "test_dlsym_symbol");
138*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(symbol == nullptr);
139*8d67ca89SAndroid Build Coastguard Worker ASSERT_SUBSTR("undefined symbol: test_dlsym_symbol", dlerror());
140*8d67ca89SAndroid Build Coastguard Worker
141*8d67ca89SAndroid Build Coastguard Worker typedef int* (*fn_t)();
142*8d67ca89SAndroid Build Coastguard Worker fn_t lookup_dlsym_symbol_using_RTLD_DEFAULT =
143*8d67ca89SAndroid Build Coastguard Worker reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol_using_RTLD_DEFAULT"));
144*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(lookup_dlsym_symbol_using_RTLD_DEFAULT != nullptr) << dlerror();
145*8d67ca89SAndroid Build Coastguard Worker
146*8d67ca89SAndroid Build Coastguard Worker int* ptr = lookup_dlsym_symbol_using_RTLD_DEFAULT();
147*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(ptr != nullptr) << dlerror();
148*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(42, *ptr);
149*8d67ca89SAndroid Build Coastguard Worker
150*8d67ca89SAndroid Build Coastguard Worker fn_t lookup_dlsym_symbol2_using_RTLD_DEFAULT =
151*8d67ca89SAndroid Build Coastguard Worker reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol2_using_RTLD_DEFAULT"));
152*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(lookup_dlsym_symbol2_using_RTLD_DEFAULT != nullptr) << dlerror();
153*8d67ca89SAndroid Build Coastguard Worker
154*8d67ca89SAndroid Build Coastguard Worker ptr = lookup_dlsym_symbol2_using_RTLD_DEFAULT();
155*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(ptr != nullptr) << dlerror();
156*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(44, *ptr);
157*8d67ca89SAndroid Build Coastguard Worker
158*8d67ca89SAndroid Build Coastguard Worker fn_t lookup_dlsym_symbol_using_RTLD_NEXT =
159*8d67ca89SAndroid Build Coastguard Worker reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol_using_RTLD_NEXT"));
160*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(lookup_dlsym_symbol_using_RTLD_NEXT != nullptr) << dlerror();
161*8d67ca89SAndroid Build Coastguard Worker
162*8d67ca89SAndroid Build Coastguard Worker ptr = lookup_dlsym_symbol_using_RTLD_NEXT();
163*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(ptr != nullptr) << dlerror();
164*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(43, *ptr);
165*8d67ca89SAndroid Build Coastguard Worker
166*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
167*8d67ca89SAndroid Build Coastguard Worker dlclose(preload);
168*8d67ca89SAndroid Build Coastguard Worker }
169*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlsym_handle_global_sym)170*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlsym_handle_global_sym) {
171*8d67ca89SAndroid Build Coastguard Worker // check that we do not look into global group
172*8d67ca89SAndroid Build Coastguard Worker // when looking up symbol by handle
173*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libtest_empty.so", RTLD_NOW);
174*8d67ca89SAndroid Build Coastguard Worker dlopen("libtest_with_dependency.so", RTLD_NOW | RTLD_GLOBAL);
175*8d67ca89SAndroid Build Coastguard Worker void* sym = dlsym(handle, "getRandomNumber");
176*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(sym == nullptr);
177*8d67ca89SAndroid Build Coastguard Worker ASSERT_SUBSTR("undefined symbol: getRandomNumber", dlerror());
178*8d67ca89SAndroid Build Coastguard Worker
179*8d67ca89SAndroid Build Coastguard Worker sym = dlsym(handle, "DlSymTestFunction");
180*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(sym == nullptr);
181*8d67ca89SAndroid Build Coastguard Worker ASSERT_SUBSTR("undefined symbol: DlSymTestFunction", dlerror());
182*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
183*8d67ca89SAndroid Build Coastguard Worker }
184*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlsym_handle_empty_symbol)185*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlsym_handle_empty_symbol) {
186*8d67ca89SAndroid Build Coastguard Worker // check that dlsym of an empty symbol fails (see http://b/33530622)
187*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_NOW);
188*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
189*8d67ca89SAndroid Build Coastguard Worker void* sym = dlsym(handle, "");
190*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(sym == nullptr);
191*8d67ca89SAndroid Build Coastguard Worker ASSERT_SUBSTR("undefined symbol: ", dlerror());
192*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
193*8d67ca89SAndroid Build Coastguard Worker }
194*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlsym_with_dependencies)195*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlsym_with_dependencies) {
196*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libtest_with_dependency.so", RTLD_NOW);
197*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr);
198*8d67ca89SAndroid Build Coastguard Worker dlerror();
199*8d67ca89SAndroid Build Coastguard Worker // This symbol is in DT_NEEDED library.
200*8d67ca89SAndroid Build Coastguard Worker void* sym = dlsym(handle, "getRandomNumber");
201*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(sym != nullptr) << dlerror();
202*8d67ca89SAndroid Build Coastguard Worker int (*fn)(void);
203*8d67ca89SAndroid Build Coastguard Worker fn = reinterpret_cast<int (*)(void)>(sym);
204*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(4, fn());
205*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
206*8d67ca89SAndroid Build Coastguard Worker }
207*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlopen_noload)208*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlopen_noload) {
209*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libtest_simple.so", RTLD_NOW | RTLD_NOLOAD);
210*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle == nullptr);
211*8d67ca89SAndroid Build Coastguard Worker handle = dlopen("libtest_simple.so", RTLD_NOW);
212*8d67ca89SAndroid Build Coastguard Worker void* handle2 = dlopen("libtest_simple.so", RTLD_NOW | RTLD_NOLOAD);
213*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr);
214*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle2 != nullptr);
215*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle == handle2);
216*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, dlclose(handle));
217*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, dlclose(handle2));
218*8d67ca89SAndroid Build Coastguard Worker }
219*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlopen_by_soname)220*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlopen_by_soname) {
221*8d67ca89SAndroid Build Coastguard Worker static const char* soname = "libdlext_test_soname.so";
222*8d67ca89SAndroid Build Coastguard Worker static const char* filename = "libdlext_test_different_soname.so";
223*8d67ca89SAndroid Build Coastguard Worker // 1. Make sure there is no library with soname in default search path
224*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen(soname, RTLD_NOW);
225*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle == nullptr);
226*8d67ca89SAndroid Build Coastguard Worker
227*8d67ca89SAndroid Build Coastguard Worker // 2. Load a library using filename
228*8d67ca89SAndroid Build Coastguard Worker handle = dlopen(filename, RTLD_NOW);
229*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
230*8d67ca89SAndroid Build Coastguard Worker
231*8d67ca89SAndroid Build Coastguard Worker // 3. Find library by soname
232*8d67ca89SAndroid Build Coastguard Worker void* handle_soname = dlopen(soname, RTLD_NOW | RTLD_NOLOAD);
233*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle_soname != nullptr) << dlerror();
234*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(handle, handle_soname);
235*8d67ca89SAndroid Build Coastguard Worker
236*8d67ca89SAndroid Build Coastguard Worker // 4. RTLD_NOLOAD should still work with filename
237*8d67ca89SAndroid Build Coastguard Worker void* handle_filename = dlopen(filename, RTLD_NOW | RTLD_NOLOAD);
238*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle_filename != nullptr) << dlerror();
239*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(handle, handle_filename);
240*8d67ca89SAndroid Build Coastguard Worker
241*8d67ca89SAndroid Build Coastguard Worker dlclose(handle_filename);
242*8d67ca89SAndroid Build Coastguard Worker dlclose(handle_soname);
243*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
244*8d67ca89SAndroid Build Coastguard Worker }
245*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlopen_vdso)246*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlopen_vdso) {
247*8d67ca89SAndroid Build Coastguard Worker #if __has_include(<sys/auxv.h>)
248*8d67ca89SAndroid Build Coastguard Worker if (getauxval(AT_SYSINFO_EHDR) == 0) {
249*8d67ca89SAndroid Build Coastguard Worker GTEST_SKIP() << "getauxval(AT_SYSINFO_EHDR) == 0, skipping this test";
250*8d67ca89SAndroid Build Coastguard Worker }
251*8d67ca89SAndroid Build Coastguard Worker #endif
252*8d67ca89SAndroid Build Coastguard Worker
253*8d67ca89SAndroid Build Coastguard Worker const char* vdso_name = "linux-vdso.so.1";
254*8d67ca89SAndroid Build Coastguard Worker #if defined(__i386__)
255*8d67ca89SAndroid Build Coastguard Worker vdso_name = "linux-gate.so.1";
256*8d67ca89SAndroid Build Coastguard Worker #endif
257*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen(vdso_name, RTLD_NOW);
258*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
259*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
260*8d67ca89SAndroid Build Coastguard Worker }
261*8d67ca89SAndroid Build Coastguard Worker
262*8d67ca89SAndroid Build Coastguard Worker // HWASan uses an ifunc to describe the location of its shadow memory,
263*8d67ca89SAndroid Build Coastguard Worker // so even though it's an unusual case, Android needs to support
264*8d67ca89SAndroid Build Coastguard Worker // "ifunc variables".
TEST(dlfcn,ifunc_variable)265*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, ifunc_variable) {
266*8d67ca89SAndroid Build Coastguard Worker typedef const char* (*fn_ptr)();
267*8d67ca89SAndroid Build Coastguard Worker
268*8d67ca89SAndroid Build Coastguard Worker // ifunc's choice depends on whether IFUNC_CHOICE has a value
269*8d67ca89SAndroid Build Coastguard Worker // first check the set case
270*8d67ca89SAndroid Build Coastguard Worker setenv("IFUNC_CHOICE", "set", 1);
271*8d67ca89SAndroid Build Coastguard Worker // preload libtest_ifunc_variable_impl.so
272*8d67ca89SAndroid Build Coastguard Worker void* handle_impl = dlopen("libtest_ifunc_variable_impl.so", RTLD_NOW);
273*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libtest_ifunc_variable.so", RTLD_NOW);
274*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
275*8d67ca89SAndroid Build Coastguard Worker const char** foo_ptr = reinterpret_cast<const char**>(dlsym(handle, "foo"));
276*8d67ca89SAndroid Build Coastguard Worker fn_ptr foo_library_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo_library"));
277*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(foo_ptr != nullptr) << dlerror();
278*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(foo_library_ptr != nullptr) << dlerror();
279*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(strncmp("set", *foo_ptr, 3), 0);
280*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(strncmp("set", foo_library_ptr(), 3), 0);
281*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
282*8d67ca89SAndroid Build Coastguard Worker dlclose(handle_impl);
283*8d67ca89SAndroid Build Coastguard Worker
284*8d67ca89SAndroid Build Coastguard Worker // then check the unset case
285*8d67ca89SAndroid Build Coastguard Worker unsetenv("IFUNC_CHOICE");
286*8d67ca89SAndroid Build Coastguard Worker handle_impl = dlopen("libtest_ifunc_variable_impl.so", RTLD_NOW);
287*8d67ca89SAndroid Build Coastguard Worker handle = dlopen("libtest_ifunc_variable.so", RTLD_NOW);
288*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
289*8d67ca89SAndroid Build Coastguard Worker foo_ptr = reinterpret_cast<const char**>(dlsym(handle, "foo"));
290*8d67ca89SAndroid Build Coastguard Worker foo_library_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo_library"));
291*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(foo_ptr != nullptr) << dlerror();
292*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(foo_library_ptr != nullptr) << dlerror();
293*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(strncmp("unset", *foo_ptr, 5), 0);
294*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(strncmp("unset", foo_library_ptr(), 5), 0);
295*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
296*8d67ca89SAndroid Build Coastguard Worker dlclose(handle_impl);
297*8d67ca89SAndroid Build Coastguard Worker }
298*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,ifunc)299*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, ifunc) {
300*8d67ca89SAndroid Build Coastguard Worker typedef const char* (*fn_ptr)();
301*8d67ca89SAndroid Build Coastguard Worker
302*8d67ca89SAndroid Build Coastguard Worker // ifunc's choice depends on whether IFUNC_CHOICE has a value
303*8d67ca89SAndroid Build Coastguard Worker // first check the set case
304*8d67ca89SAndroid Build Coastguard Worker setenv("IFUNC_CHOICE", "set", 1);
305*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libtest_ifunc.so", RTLD_NOW);
306*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
307*8d67ca89SAndroid Build Coastguard Worker fn_ptr foo_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo"));
308*8d67ca89SAndroid Build Coastguard Worker fn_ptr foo_library_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo_library"));
309*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(foo_ptr != nullptr) << dlerror();
310*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(foo_library_ptr != nullptr) << dlerror();
311*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(strncmp("set", foo_ptr(), 3), 0);
312*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(strncmp("set", foo_library_ptr(), 3), 0);
313*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
314*8d67ca89SAndroid Build Coastguard Worker
315*8d67ca89SAndroid Build Coastguard Worker // then check the unset case
316*8d67ca89SAndroid Build Coastguard Worker unsetenv("IFUNC_CHOICE");
317*8d67ca89SAndroid Build Coastguard Worker handle = dlopen("libtest_ifunc.so", RTLD_NOW);
318*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
319*8d67ca89SAndroid Build Coastguard Worker foo_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo"));
320*8d67ca89SAndroid Build Coastguard Worker foo_library_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo_library"));
321*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(foo_ptr != nullptr) << dlerror();
322*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(foo_library_ptr != nullptr) << dlerror();
323*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(strncmp("unset", foo_ptr(), 5), 0);
324*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(strncmp("unset", foo_library_ptr(), 5), 0);
325*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
326*8d67ca89SAndroid Build Coastguard Worker }
327*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,ifunc_ctor_call)328*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, ifunc_ctor_call) {
329*8d67ca89SAndroid Build Coastguard Worker typedef const char* (*fn_ptr)();
330*8d67ca89SAndroid Build Coastguard Worker
331*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libtest_ifunc.so", RTLD_NOW);
332*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
333*8d67ca89SAndroid Build Coastguard Worker fn_ptr is_ctor_called = reinterpret_cast<fn_ptr>(dlsym(handle, "is_ctor_called_irelative"));
334*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(is_ctor_called != nullptr) << dlerror();
335*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ("false", is_ctor_called());
336*8d67ca89SAndroid Build Coastguard Worker
337*8d67ca89SAndroid Build Coastguard Worker is_ctor_called = reinterpret_cast<fn_ptr>(dlsym(handle, "is_ctor_called_jump_slot"));
338*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(is_ctor_called != nullptr) << dlerror();
339*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ("true", is_ctor_called());
340*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
341*8d67ca89SAndroid Build Coastguard Worker }
342*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,ifunc_ctor_call_rtld_lazy)343*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, ifunc_ctor_call_rtld_lazy) {
344*8d67ca89SAndroid Build Coastguard Worker typedef const char* (*fn_ptr)();
345*8d67ca89SAndroid Build Coastguard Worker
346*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libtest_ifunc.so", RTLD_LAZY);
347*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
348*8d67ca89SAndroid Build Coastguard Worker fn_ptr is_ctor_called = reinterpret_cast<fn_ptr>(dlsym(handle, "is_ctor_called_irelative"));
349*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(is_ctor_called != nullptr) << dlerror();
350*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ("false", is_ctor_called());
351*8d67ca89SAndroid Build Coastguard Worker
352*8d67ca89SAndroid Build Coastguard Worker is_ctor_called = reinterpret_cast<fn_ptr>(dlsym(handle, "is_ctor_called_jump_slot"));
353*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(is_ctor_called != nullptr) << dlerror();
354*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ("true", is_ctor_called());
355*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
356*8d67ca89SAndroid Build Coastguard Worker }
357*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlopen_check_relocation_dt_needed_order)358*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlopen_check_relocation_dt_needed_order) {
359*8d67ca89SAndroid Build Coastguard Worker // This is the structure of the test library and
360*8d67ca89SAndroid Build Coastguard Worker // its dt_needed libraries
361*8d67ca89SAndroid Build Coastguard Worker // libtest_relo_check_dt_needed_order.so
362*8d67ca89SAndroid Build Coastguard Worker // |
363*8d67ca89SAndroid Build Coastguard Worker // +-> libtest_relo_check_dt_needed_order_1.so
364*8d67ca89SAndroid Build Coastguard Worker // |
365*8d67ca89SAndroid Build Coastguard Worker // +-> libtest_relo_check_dt_needed_order_2.so
366*8d67ca89SAndroid Build Coastguard Worker //
367*8d67ca89SAndroid Build Coastguard Worker // The root library references relo_test_get_answer_lib - which is defined
368*8d67ca89SAndroid Build Coastguard Worker // in both dt_needed libraries, the correct relocation should
369*8d67ca89SAndroid Build Coastguard Worker // use the function defined in libtest_relo_check_dt_needed_order_1.so
370*8d67ca89SAndroid Build Coastguard Worker void* handle = nullptr;
371*8d67ca89SAndroid Build Coastguard Worker auto guard = android::base::make_scope_guard([&]() { dlclose(handle); });
372*8d67ca89SAndroid Build Coastguard Worker
373*8d67ca89SAndroid Build Coastguard Worker handle = dlopen("libtest_relo_check_dt_needed_order.so", RTLD_NOW);
374*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
375*8d67ca89SAndroid Build Coastguard Worker
376*8d67ca89SAndroid Build Coastguard Worker typedef int (*fn_t) (void);
377*8d67ca89SAndroid Build Coastguard Worker fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "relo_test_get_answer"));
378*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(fn != nullptr) << dlerror();
379*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(1, fn());
380*8d67ca89SAndroid Build Coastguard Worker }
381*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlopen_check_order_dlsym)382*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlopen_check_order_dlsym) {
383*8d67ca89SAndroid Build Coastguard Worker // Here is how the test library and its dt_needed
384*8d67ca89SAndroid Build Coastguard Worker // libraries are arranged
385*8d67ca89SAndroid Build Coastguard Worker //
386*8d67ca89SAndroid Build Coastguard Worker // libtest_check_order_children.so
387*8d67ca89SAndroid Build Coastguard Worker // |
388*8d67ca89SAndroid Build Coastguard Worker // +-> ..._1_left.so
389*8d67ca89SAndroid Build Coastguard Worker // | |
390*8d67ca89SAndroid Build Coastguard Worker // | +-> ..._a.so
391*8d67ca89SAndroid Build Coastguard Worker // | |
392*8d67ca89SAndroid Build Coastguard Worker // | +-> ...r_b.so
393*8d67ca89SAndroid Build Coastguard Worker // |
394*8d67ca89SAndroid Build Coastguard Worker // +-> ..._2_right.so
395*8d67ca89SAndroid Build Coastguard Worker // | |
396*8d67ca89SAndroid Build Coastguard Worker // | +-> ..._d.so
397*8d67ca89SAndroid Build Coastguard Worker // | |
398*8d67ca89SAndroid Build Coastguard Worker // | +-> ..._b.so
399*8d67ca89SAndroid Build Coastguard Worker // |
400*8d67ca89SAndroid Build Coastguard Worker // +-> ..._3_c.so
401*8d67ca89SAndroid Build Coastguard Worker //
402*8d67ca89SAndroid Build Coastguard Worker // load order should be (1, 2, 3, a, b, d)
403*8d67ca89SAndroid Build Coastguard Worker //
404*8d67ca89SAndroid Build Coastguard Worker // get_answer() is defined in (2, 3, a, b, c)
405*8d67ca89SAndroid Build Coastguard Worker // get_answer2() is defined in (b, d)
406*8d67ca89SAndroid Build Coastguard Worker void* sym = dlsym(RTLD_DEFAULT, "check_order_dlsym_get_answer");
407*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(sym == nullptr);
408*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libtest_check_order_dlsym.so", RTLD_NOW | RTLD_GLOBAL);
409*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
410*8d67ca89SAndroid Build Coastguard Worker typedef int (*fn_t) (void);
411*8d67ca89SAndroid Build Coastguard Worker fn_t fn, fn2;
412*8d67ca89SAndroid Build Coastguard Worker fn = reinterpret_cast<fn_t>(dlsym(RTLD_DEFAULT, "check_order_dlsym_get_answer"));
413*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(fn != nullptr) << dlerror();
414*8d67ca89SAndroid Build Coastguard Worker fn2 = reinterpret_cast<fn_t>(dlsym(RTLD_DEFAULT, "check_order_dlsym_get_answer2"));
415*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(fn2 != nullptr) << dlerror();
416*8d67ca89SAndroid Build Coastguard Worker
417*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(42, fn());
418*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(43, fn2());
419*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
420*8d67ca89SAndroid Build Coastguard Worker }
421*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlopen_check_order_reloc_siblings)422*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlopen_check_order_reloc_siblings) {
423*8d67ca89SAndroid Build Coastguard Worker // This is how this one works:
424*8d67ca89SAndroid Build Coastguard Worker // we lookup and call get_answer which is defined in '_2.so'
425*8d67ca89SAndroid Build Coastguard Worker // and in turn calls external get_answer_impl() defined in _1.so and in '_[a-f].so'
426*8d67ca89SAndroid Build Coastguard Worker // the correct _impl() is implemented by '_a.so';
427*8d67ca89SAndroid Build Coastguard Worker //
428*8d67ca89SAndroid Build Coastguard Worker // Note that this is test for RTLD_LOCAL (TODO: test for GLOBAL?)
429*8d67ca89SAndroid Build Coastguard Worker //
430*8d67ca89SAndroid Build Coastguard Worker // Here is the picture:
431*8d67ca89SAndroid Build Coastguard Worker //
432*8d67ca89SAndroid Build Coastguard Worker // libtest_check_order_reloc_siblings.so
433*8d67ca89SAndroid Build Coastguard Worker // |
434*8d67ca89SAndroid Build Coastguard Worker // +-> ..._1.so <- empty
435*8d67ca89SAndroid Build Coastguard Worker // | |
436*8d67ca89SAndroid Build Coastguard Worker // | +-> ..._a.so <- exports correct answer_impl()
437*8d67ca89SAndroid Build Coastguard Worker // | |
438*8d67ca89SAndroid Build Coastguard Worker // | +-> ..._b.so <- every other letter exporting incorrect one.
439*8d67ca89SAndroid Build Coastguard Worker // |
440*8d67ca89SAndroid Build Coastguard Worker // +-> ..._2.so <- empty
441*8d67ca89SAndroid Build Coastguard Worker // | |
442*8d67ca89SAndroid Build Coastguard Worker // | +-> ..._c.so
443*8d67ca89SAndroid Build Coastguard Worker // | |
444*8d67ca89SAndroid Build Coastguard Worker // | +-> ..._d.so
445*8d67ca89SAndroid Build Coastguard Worker // |
446*8d67ca89SAndroid Build Coastguard Worker // +-> ..._3.so <- empty
447*8d67ca89SAndroid Build Coastguard Worker // |
448*8d67ca89SAndroid Build Coastguard Worker // +-> ..._e.so
449*8d67ca89SAndroid Build Coastguard Worker // |
450*8d67ca89SAndroid Build Coastguard Worker // +-> ..._f.so <- exports get_answer() that calls get_anser_impl();
451*8d67ca89SAndroid Build Coastguard Worker // implements incorrect get_answer_impl()
452*8d67ca89SAndroid Build Coastguard Worker
453*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libtest_check_order_reloc_siblings.so", RTLD_NOW | RTLD_NOLOAD);
454*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle == nullptr);
455*8d67ca89SAndroid Build Coastguard Worker #ifdef __BIONIC__
456*8d67ca89SAndroid Build Coastguard Worker // TODO: glibc returns nullptr on dlerror() here. Is it bug?
457*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ("dlopen failed: library \"libtest_check_order_reloc_siblings.so\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
458*8d67ca89SAndroid Build Coastguard Worker #endif
459*8d67ca89SAndroid Build Coastguard Worker
460*8d67ca89SAndroid Build Coastguard Worker handle = dlopen("libtest_check_order_reloc_siblings.so", RTLD_NOW | RTLD_LOCAL);
461*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
462*8d67ca89SAndroid Build Coastguard Worker
463*8d67ca89SAndroid Build Coastguard Worker typedef int (*fn_t) (void);
464*8d67ca89SAndroid Build Coastguard Worker fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "check_order_reloc_get_answer"));
465*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(fn != nullptr) << dlerror();
466*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(42, fn());
467*8d67ca89SAndroid Build Coastguard Worker
468*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, dlclose(handle));
469*8d67ca89SAndroid Build Coastguard Worker }
470*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlopen_check_order_reloc_siblings_with_preload)471*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlopen_check_order_reloc_siblings_with_preload) {
472*8d67ca89SAndroid Build Coastguard Worker // This test uses the same library as dlopen_check_order_reloc_siblings.
473*8d67ca89SAndroid Build Coastguard Worker // Unlike dlopen_check_order_reloc_siblings it preloads
474*8d67ca89SAndroid Build Coastguard Worker // libtest_check_order_reloc_siblings_1.so (first dependency) prior to
475*8d67ca89SAndroid Build Coastguard Worker // dlopen(libtest_check_order_reloc_siblings.so)
476*8d67ca89SAndroid Build Coastguard Worker
477*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libtest_check_order_reloc_siblings.so", RTLD_NOW | RTLD_NOLOAD);
478*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle == nullptr);
479*8d67ca89SAndroid Build Coastguard Worker handle = dlopen("libtest_check_order_reloc_siblings_1.so", RTLD_NOW | RTLD_NOLOAD);
480*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle == nullptr);
481*8d67ca89SAndroid Build Coastguard Worker
482*8d67ca89SAndroid Build Coastguard Worker void* handle_for_1 = dlopen("libtest_check_order_reloc_siblings_1.so", RTLD_NOW | RTLD_LOCAL);
483*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle_for_1 != nullptr) << dlerror();
484*8d67ca89SAndroid Build Coastguard Worker
485*8d67ca89SAndroid Build Coastguard Worker handle = dlopen("libtest_check_order_reloc_siblings.so", RTLD_NOW | RTLD_LOCAL);
486*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
487*8d67ca89SAndroid Build Coastguard Worker
488*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, dlclose(handle_for_1));
489*8d67ca89SAndroid Build Coastguard Worker
490*8d67ca89SAndroid Build Coastguard Worker typedef int (*fn_t) (void);
491*8d67ca89SAndroid Build Coastguard Worker fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "check_order_reloc_get_answer"));
492*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(fn != nullptr) << dlerror();
493*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(42, fn());
494*8d67ca89SAndroid Build Coastguard Worker
495*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, dlclose(handle));
496*8d67ca89SAndroid Build Coastguard Worker }
497*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlopen_check_order_reloc_grandchild)498*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlopen_check_order_reloc_grandchild) {
499*8d67ca89SAndroid Build Coastguard Worker // This is how this one works:
500*8d67ca89SAndroid Build Coastguard Worker // we lookup and call grandchild_get_answer which is defined in '_2.so'
501*8d67ca89SAndroid Build Coastguard Worker // and in turn calls external get_answer_impl() defined in '_c_1.so and _c_2.so'
502*8d67ca89SAndroid Build Coastguard Worker // the correct _impl() is implemented by '_c_1.so';
503*8d67ca89SAndroid Build Coastguard Worker //
504*8d67ca89SAndroid Build Coastguard Worker // Here is the picture of subtree:
505*8d67ca89SAndroid Build Coastguard Worker //
506*8d67ca89SAndroid Build Coastguard Worker // libtest_check_order_reloc_siblings.so
507*8d67ca89SAndroid Build Coastguard Worker // |
508*8d67ca89SAndroid Build Coastguard Worker // +-> ..._2.so <- grandchild_get_answer()
509*8d67ca89SAndroid Build Coastguard Worker // |
510*8d67ca89SAndroid Build Coastguard Worker // +-> ..._c.so <- empty
511*8d67ca89SAndroid Build Coastguard Worker // | |
512*8d67ca89SAndroid Build Coastguard Worker // | +-> _c_1.so <- exports correct answer_impl()
513*8d67ca89SAndroid Build Coastguard Worker // | |
514*8d67ca89SAndroid Build Coastguard Worker // | +-> _c_2.so <- exports incorrect answer_impl()
515*8d67ca89SAndroid Build Coastguard Worker // |
516*8d67ca89SAndroid Build Coastguard Worker // +-> ..._d.so <- empty
517*8d67ca89SAndroid Build Coastguard Worker
518*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libtest_check_order_reloc_siblings.so", RTLD_NOW | RTLD_NOLOAD);
519*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle == nullptr);
520*8d67ca89SAndroid Build Coastguard Worker #ifdef __BIONIC__
521*8d67ca89SAndroid Build Coastguard Worker // TODO: glibc returns nullptr on dlerror() here. Is it bug?
522*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ("dlopen failed: library \"libtest_check_order_reloc_siblings.so\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
523*8d67ca89SAndroid Build Coastguard Worker #endif
524*8d67ca89SAndroid Build Coastguard Worker
525*8d67ca89SAndroid Build Coastguard Worker handle = dlopen("libtest_check_order_reloc_siblings.so", RTLD_NOW | RTLD_LOCAL);
526*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
527*8d67ca89SAndroid Build Coastguard Worker
528*8d67ca89SAndroid Build Coastguard Worker typedef int (*fn_t) (void);
529*8d67ca89SAndroid Build Coastguard Worker fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "check_order_reloc_grandchild_get_answer"));
530*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(fn != nullptr) << dlerror();
531*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(42, fn());
532*8d67ca89SAndroid Build Coastguard Worker
533*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, dlclose(handle));
534*8d67ca89SAndroid Build Coastguard Worker }
535*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlopen_check_order_reloc_nephew)536*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlopen_check_order_reloc_nephew) {
537*8d67ca89SAndroid Build Coastguard Worker // This is how this one works:
538*8d67ca89SAndroid Build Coastguard Worker // we lookup and call nephew_get_answer which is defined in '_2.so'
539*8d67ca89SAndroid Build Coastguard Worker // and in turn calls external get_answer_impl() defined in '_[a-f].so'
540*8d67ca89SAndroid Build Coastguard Worker // the correct _impl() is implemented by '_a.so';
541*8d67ca89SAndroid Build Coastguard Worker //
542*8d67ca89SAndroid Build Coastguard Worker // Here is the picture:
543*8d67ca89SAndroid Build Coastguard Worker //
544*8d67ca89SAndroid Build Coastguard Worker // libtest_check_order_reloc_siblings.so
545*8d67ca89SAndroid Build Coastguard Worker // |
546*8d67ca89SAndroid Build Coastguard Worker // +-> ..._1.so <- empty
547*8d67ca89SAndroid Build Coastguard Worker // | |
548*8d67ca89SAndroid Build Coastguard Worker // | +-> ..._a.so <- exports correct answer_impl()
549*8d67ca89SAndroid Build Coastguard Worker // | |
550*8d67ca89SAndroid Build Coastguard Worker // | +-> ..._b.so <- every other letter exporting incorrect one.
551*8d67ca89SAndroid Build Coastguard Worker // |
552*8d67ca89SAndroid Build Coastguard Worker // +-> ..._2.so <- empty
553*8d67ca89SAndroid Build Coastguard Worker // | |
554*8d67ca89SAndroid Build Coastguard Worker // | +-> ..._c.so
555*8d67ca89SAndroid Build Coastguard Worker // | |
556*8d67ca89SAndroid Build Coastguard Worker // | +-> ..._d.so
557*8d67ca89SAndroid Build Coastguard Worker // |
558*8d67ca89SAndroid Build Coastguard Worker // +-> ..._3.so <- nephew_get_answer() that calls get_answer_impl();
559*8d67ca89SAndroid Build Coastguard Worker // |
560*8d67ca89SAndroid Build Coastguard Worker // +-> ..._e.so
561*8d67ca89SAndroid Build Coastguard Worker // |
562*8d67ca89SAndroid Build Coastguard Worker // +-> ..._f.so
563*8d67ca89SAndroid Build Coastguard Worker
564*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libtest_check_order_reloc_siblings.so", RTLD_NOW | RTLD_NOLOAD);
565*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle == nullptr);
566*8d67ca89SAndroid Build Coastguard Worker #ifdef __BIONIC__
567*8d67ca89SAndroid Build Coastguard Worker // TODO: glibc returns nullptr on dlerror() here. Is it bug?
568*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ("dlopen failed: library \"libtest_check_order_reloc_siblings.so\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
569*8d67ca89SAndroid Build Coastguard Worker #endif
570*8d67ca89SAndroid Build Coastguard Worker
571*8d67ca89SAndroid Build Coastguard Worker handle = dlopen("libtest_check_order_reloc_siblings.so", RTLD_NOW | RTLD_LOCAL);
572*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
573*8d67ca89SAndroid Build Coastguard Worker
574*8d67ca89SAndroid Build Coastguard Worker typedef int (*fn_t) (void);
575*8d67ca89SAndroid Build Coastguard Worker fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "check_order_reloc_nephew_get_answer"));
576*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(fn != nullptr) << dlerror();
577*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(42, fn());
578*8d67ca89SAndroid Build Coastguard Worker
579*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, dlclose(handle));
580*8d67ca89SAndroid Build Coastguard Worker }
581*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,check_unload_after_reloc)582*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, check_unload_after_reloc) {
583*8d67ca89SAndroid Build Coastguard Worker // This is how this one works:
584*8d67ca89SAndroid Build Coastguard Worker // libtest_two_parents_parent1 <- answer_impl() used by libtest_two_parents_child
585*8d67ca89SAndroid Build Coastguard Worker // |
586*8d67ca89SAndroid Build Coastguard Worker // +-> libtest_two_parents_child
587*8d67ca89SAndroid Build Coastguard Worker //
588*8d67ca89SAndroid Build Coastguard Worker // libtest_two_parents_parent2 <- answer_impl() not used by libtest_two_parents_child
589*8d67ca89SAndroid Build Coastguard Worker // |
590*8d67ca89SAndroid Build Coastguard Worker // +-> libtest_two_parents_child
591*8d67ca89SAndroid Build Coastguard Worker //
592*8d67ca89SAndroid Build Coastguard Worker // Test dlopens parent1 which loads and relocates libtest_two_parents_child.so
593*8d67ca89SAndroid Build Coastguard Worker // as a second step it dlopens parent2 and dlcloses parent1...
594*8d67ca89SAndroid Build Coastguard Worker
595*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libtest_two_parents_parent1.so", RTLD_NOW | RTLD_LOCAL);
596*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
597*8d67ca89SAndroid Build Coastguard Worker
598*8d67ca89SAndroid Build Coastguard Worker void* handle2 = dlopen("libtest_two_parents_parent2.so", RTLD_NOW | RTLD_LOCAL);
599*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle2 != nullptr) << dlerror();
600*8d67ca89SAndroid Build Coastguard Worker
601*8d67ca89SAndroid Build Coastguard Worker typedef int (*fn_t) (void);
602*8d67ca89SAndroid Build Coastguard Worker fn_t fn = reinterpret_cast<fn_t>(dlsym(handle2, "check_order_reloc_get_answer"));
603*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(fn != nullptr) << dlerror();
604*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(42, fn());
605*8d67ca89SAndroid Build Coastguard Worker
606*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, dlclose(handle));
607*8d67ca89SAndroid Build Coastguard Worker
608*8d67ca89SAndroid Build Coastguard Worker handle = dlopen("libtest_two_parents_parent1.so", RTLD_NOW | RTLD_LOCAL | RTLD_NOLOAD);
609*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr);
610*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, dlclose(handle));
611*8d67ca89SAndroid Build Coastguard Worker
612*8d67ca89SAndroid Build Coastguard Worker fn = reinterpret_cast<fn_t>(dlsym(handle2, "check_order_reloc_get_answer"));
613*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(fn != nullptr) << dlerror();
614*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(42, fn());
615*8d67ca89SAndroid Build Coastguard Worker
616*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, dlclose(handle2));
617*8d67ca89SAndroid Build Coastguard Worker
618*8d67ca89SAndroid Build Coastguard Worker handle = dlopen("libtest_two_parents_parent1.so", RTLD_NOW | RTLD_LOCAL | RTLD_NOLOAD);
619*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle == nullptr);
620*8d67ca89SAndroid Build Coastguard Worker }
621*8d67ca89SAndroid Build Coastguard Worker
check_order_reloc_root_get_answer_impl()622*8d67ca89SAndroid Build Coastguard Worker extern "C" int check_order_reloc_root_get_answer_impl() {
623*8d67ca89SAndroid Build Coastguard Worker return 42;
624*8d67ca89SAndroid Build Coastguard Worker }
625*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlopen_check_order_reloc_main_executable)626*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlopen_check_order_reloc_main_executable) {
627*8d67ca89SAndroid Build Coastguard Worker // This is how this one works:
628*8d67ca89SAndroid Build Coastguard Worker // we lookup and call get_answer3 which is defined in 'root.so'
629*8d67ca89SAndroid Build Coastguard Worker // and in turn calls external root_get_answer_impl() defined in _2.so and
630*8d67ca89SAndroid Build Coastguard Worker // above the correct _impl() is one in the executable.
631*8d67ca89SAndroid Build Coastguard Worker //
632*8d67ca89SAndroid Build Coastguard Worker // libtest_check_order_reloc_root.so
633*8d67ca89SAndroid Build Coastguard Worker // |
634*8d67ca89SAndroid Build Coastguard Worker // +-> ..._1.so <- empty
635*8d67ca89SAndroid Build Coastguard Worker // |
636*8d67ca89SAndroid Build Coastguard Worker // +-> ..._2.so <- gives incorrect answer for answer_main_impl()
637*8d67ca89SAndroid Build Coastguard Worker //
638*8d67ca89SAndroid Build Coastguard Worker
639*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libtest_check_order_reloc_root.so", RTLD_NOW | RTLD_NOLOAD);
640*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle == nullptr);
641*8d67ca89SAndroid Build Coastguard Worker #ifdef __BIONIC__
642*8d67ca89SAndroid Build Coastguard Worker // TODO: glibc returns nullptr on dlerror() here. Is it bug?
643*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ("dlopen failed: library \"libtest_check_order_reloc_root.so\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
644*8d67ca89SAndroid Build Coastguard Worker #endif
645*8d67ca89SAndroid Build Coastguard Worker
646*8d67ca89SAndroid Build Coastguard Worker handle = dlopen("libtest_check_order_reloc_root.so", RTLD_NOW | RTLD_LOCAL);
647*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
648*8d67ca89SAndroid Build Coastguard Worker
649*8d67ca89SAndroid Build Coastguard Worker typedef int (*fn_t) (void);
650*8d67ca89SAndroid Build Coastguard Worker fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "check_order_reloc_root_get_answer"));
651*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(fn != nullptr) << dlerror();
652*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(42, fn());
653*8d67ca89SAndroid Build Coastguard Worker
654*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, dlclose(handle));
655*8d67ca89SAndroid Build Coastguard Worker }
656*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlopen_check_rtld_local)657*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlopen_check_rtld_local) {
658*8d67ca89SAndroid Build Coastguard Worker void* sym = dlsym(RTLD_DEFAULT, "dlopen_testlib_simple_func");
659*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(sym == nullptr);
660*8d67ca89SAndroid Build Coastguard Worker
661*8d67ca89SAndroid Build Coastguard Worker // implicit RTLD_LOCAL
662*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libtest_simple.so", RTLD_NOW);
663*8d67ca89SAndroid Build Coastguard Worker sym = dlsym(RTLD_DEFAULT, "dlopen_testlib_simple_func");
664*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(sym == nullptr);
665*8d67ca89SAndroid Build Coastguard Worker ASSERT_SUBSTR("undefined symbol: dlopen_testlib_simple_func", dlerror());
666*8d67ca89SAndroid Build Coastguard Worker sym = dlsym(handle, "dlopen_testlib_simple_func");
667*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(sym != nullptr);
668*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(reinterpret_cast<bool (*)(void)>(sym)());
669*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
670*8d67ca89SAndroid Build Coastguard Worker
671*8d67ca89SAndroid Build Coastguard Worker // explicit RTLD_LOCAL
672*8d67ca89SAndroid Build Coastguard Worker handle = dlopen("libtest_simple.so", RTLD_NOW | RTLD_LOCAL);
673*8d67ca89SAndroid Build Coastguard Worker sym = dlsym(RTLD_DEFAULT, "dlopen_testlib_simple_func");
674*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(sym == nullptr);
675*8d67ca89SAndroid Build Coastguard Worker ASSERT_SUBSTR("undefined symbol: dlopen_testlib_simple_func", dlerror());
676*8d67ca89SAndroid Build Coastguard Worker sym = dlsym(handle, "dlopen_testlib_simple_func");
677*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(sym != nullptr);
678*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(reinterpret_cast<bool (*)(void)>(sym)());
679*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
680*8d67ca89SAndroid Build Coastguard Worker }
681*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlopen_check_rtld_global)682*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlopen_check_rtld_global) {
683*8d67ca89SAndroid Build Coastguard Worker void* sym = dlsym(RTLD_DEFAULT, "dlopen_testlib_simple_func");
684*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(sym == nullptr);
685*8d67ca89SAndroid Build Coastguard Worker
686*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libtest_simple.so", RTLD_NOW | RTLD_GLOBAL);
687*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
688*8d67ca89SAndroid Build Coastguard Worker sym = dlsym(RTLD_DEFAULT, "dlopen_testlib_simple_func");
689*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(sym != nullptr) << dlerror();
690*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(reinterpret_cast<bool (*)(void)>(sym)());
691*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
692*8d67ca89SAndroid Build Coastguard Worker
693*8d67ca89SAndroid Build Coastguard Worker // RTLD_GLOBAL implies RTLD_NODELETE, let's check that
694*8d67ca89SAndroid Build Coastguard Worker void* sym_after_dlclose = dlsym(RTLD_DEFAULT, "dlopen_testlib_simple_func");
695*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(sym, sym_after_dlclose);
696*8d67ca89SAndroid Build Coastguard Worker
697*8d67ca89SAndroid Build Coastguard Worker // Check if dlsym() for main program's handle searches RTLD_GLOBAL
698*8d67ca89SAndroid Build Coastguard Worker // shared libraries after symbol was not found in the main executable
699*8d67ca89SAndroid Build Coastguard Worker // and dependent libraries.
700*8d67ca89SAndroid Build Coastguard Worker void* handle_for_main_executable = dlopen(nullptr, RTLD_NOW);
701*8d67ca89SAndroid Build Coastguard Worker sym = dlsym(handle_for_main_executable, "dlopen_testlib_simple_func");
702*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(sym != nullptr) << dlerror();
703*8d67ca89SAndroid Build Coastguard Worker
704*8d67ca89SAndroid Build Coastguard Worker dlclose(handle_for_main_executable);
705*8d67ca89SAndroid Build Coastguard Worker }
706*8d67ca89SAndroid Build Coastguard Worker
707*8d67ca89SAndroid Build Coastguard Worker // libtest_with_dependency_loop.so -> libtest_with_dependency_loop_a.so ->
708*8d67ca89SAndroid Build Coastguard Worker // libtest_with_dependency_loop_b.so -> libtest_with_dependency_loop_c.so ->
709*8d67ca89SAndroid Build Coastguard Worker // libtest_with_dependency_loop_a.so
TEST(dlfcn,dlopen_check_loop)710*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlopen_check_loop) {
711*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libtest_with_dependency_loop.so", RTLD_NOW);
712*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
713*8d67ca89SAndroid Build Coastguard Worker void* f = dlsym(handle, "dlopen_test_loopy_function");
714*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(f != nullptr) << dlerror();
715*8d67ca89SAndroid Build Coastguard Worker EXPECT_TRUE(reinterpret_cast<bool (*)(void)>(f)());
716*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, dlclose(handle));
717*8d67ca89SAndroid Build Coastguard Worker
718*8d67ca89SAndroid Build Coastguard Worker // dlopen second time to make sure that the library was unloaded correctly
719*8d67ca89SAndroid Build Coastguard Worker handle = dlopen("libtest_with_dependency_loop.so", RTLD_NOW | RTLD_NOLOAD);
720*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle == nullptr);
721*8d67ca89SAndroid Build Coastguard Worker #ifdef __BIONIC__
722*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ("dlopen failed: library \"libtest_with_dependency_loop.so\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
723*8d67ca89SAndroid Build Coastguard Worker #else
724*8d67ca89SAndroid Build Coastguard Worker // TODO: glibc returns nullptr on dlerror() here. Is it bug?
725*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(dlerror() == nullptr);
726*8d67ca89SAndroid Build Coastguard Worker #endif
727*8d67ca89SAndroid Build Coastguard Worker
728*8d67ca89SAndroid Build Coastguard Worker handle = dlopen("libtest_with_dependency_a.so", RTLD_NOW | RTLD_NOLOAD);
729*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle == nullptr);
730*8d67ca89SAndroid Build Coastguard Worker }
731*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlopen_nodelete)732*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlopen_nodelete) {
733*8d67ca89SAndroid Build Coastguard Worker static bool is_unloaded = false;
734*8d67ca89SAndroid Build Coastguard Worker
735*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libtest_nodelete_1.so", RTLD_NOW | RTLD_NODELETE);
736*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
737*8d67ca89SAndroid Build Coastguard Worker void (*set_unload_flag_ptr)(bool*);
738*8d67ca89SAndroid Build Coastguard Worker set_unload_flag_ptr = reinterpret_cast<void (*)(bool*)>(dlsym(handle, "dlopen_nodelete_1_set_unload_flag_ptr"));
739*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(set_unload_flag_ptr != nullptr) << dlerror();
740*8d67ca89SAndroid Build Coastguard Worker set_unload_flag_ptr(&is_unloaded);
741*8d67ca89SAndroid Build Coastguard Worker
742*8d67ca89SAndroid Build Coastguard Worker uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_nodelete_1_taxicab_number"));
743*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(taxicab_number != nullptr) << dlerror();
744*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(1729U, *taxicab_number);
745*8d67ca89SAndroid Build Coastguard Worker *taxicab_number = 2;
746*8d67ca89SAndroid Build Coastguard Worker
747*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
748*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(!is_unloaded);
749*8d67ca89SAndroid Build Coastguard Worker
750*8d67ca89SAndroid Build Coastguard Worker uint32_t* taxicab_number_after_dlclose = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_nodelete_1_taxicab_number"));
751*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(taxicab_number_after_dlclose, taxicab_number);
752*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(2U, *taxicab_number_after_dlclose);
753*8d67ca89SAndroid Build Coastguard Worker
754*8d67ca89SAndroid Build Coastguard Worker
755*8d67ca89SAndroid Build Coastguard Worker handle = dlopen("libtest_nodelete_1.so", RTLD_NOW);
756*8d67ca89SAndroid Build Coastguard Worker uint32_t* taxicab_number2 = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_nodelete_1_taxicab_number"));
757*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(taxicab_number2, taxicab_number);
758*8d67ca89SAndroid Build Coastguard Worker
759*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(2U, *taxicab_number2);
760*8d67ca89SAndroid Build Coastguard Worker
761*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
762*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(!is_unloaded);
763*8d67ca89SAndroid Build Coastguard Worker }
764*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlopen_nodelete_on_second_dlopen)765*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlopen_nodelete_on_second_dlopen) {
766*8d67ca89SAndroid Build Coastguard Worker static bool is_unloaded = false;
767*8d67ca89SAndroid Build Coastguard Worker
768*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libtest_nodelete_2.so", RTLD_NOW);
769*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
770*8d67ca89SAndroid Build Coastguard Worker void (*set_unload_flag_ptr)(bool*);
771*8d67ca89SAndroid Build Coastguard Worker set_unload_flag_ptr = reinterpret_cast<void (*)(bool*)>(dlsym(handle, "dlopen_nodelete_2_set_unload_flag_ptr"));
772*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(set_unload_flag_ptr != nullptr) << dlerror();
773*8d67ca89SAndroid Build Coastguard Worker set_unload_flag_ptr(&is_unloaded);
774*8d67ca89SAndroid Build Coastguard Worker
775*8d67ca89SAndroid Build Coastguard Worker uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_nodelete_2_taxicab_number"));
776*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(taxicab_number != nullptr) << dlerror();
777*8d67ca89SAndroid Build Coastguard Worker
778*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(1729U, *taxicab_number);
779*8d67ca89SAndroid Build Coastguard Worker *taxicab_number = 2;
780*8d67ca89SAndroid Build Coastguard Worker
781*8d67ca89SAndroid Build Coastguard Worker // This RTLD_NODELETE should be ignored
782*8d67ca89SAndroid Build Coastguard Worker void* handle1 = dlopen("libtest_nodelete_2.so", RTLD_NOW | RTLD_NODELETE);
783*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle1 != nullptr) << dlerror();
784*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(handle, handle1);
785*8d67ca89SAndroid Build Coastguard Worker
786*8d67ca89SAndroid Build Coastguard Worker dlclose(handle1);
787*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
788*8d67ca89SAndroid Build Coastguard Worker
789*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(is_unloaded);
790*8d67ca89SAndroid Build Coastguard Worker }
791*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlopen_nodelete_dt_flags_1)792*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlopen_nodelete_dt_flags_1) {
793*8d67ca89SAndroid Build Coastguard Worker static bool is_unloaded = false;
794*8d67ca89SAndroid Build Coastguard Worker
795*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libtest_nodelete_dt_flags_1.so", RTLD_NOW);
796*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
797*8d67ca89SAndroid Build Coastguard Worker void (*set_unload_flag_ptr)(bool*);
798*8d67ca89SAndroid Build Coastguard Worker set_unload_flag_ptr = reinterpret_cast<void (*)(bool*)>(dlsym(handle, "dlopen_nodelete_dt_flags_1_set_unload_flag_ptr"));
799*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(set_unload_flag_ptr != nullptr) << dlerror();
800*8d67ca89SAndroid Build Coastguard Worker set_unload_flag_ptr(&is_unloaded);
801*8d67ca89SAndroid Build Coastguard Worker
802*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
803*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(!is_unloaded);
804*8d67ca89SAndroid Build Coastguard Worker }
805*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlsym_df_1_global)806*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlsym_df_1_global) {
807*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libtest_dlsym_df_1_global.so", RTLD_NOW);
808*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
809*8d67ca89SAndroid Build Coastguard Worker int (*get_answer)();
810*8d67ca89SAndroid Build Coastguard Worker get_answer = reinterpret_cast<int (*)()>(dlsym(handle, "dl_df_1_global_get_answer"));
811*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(get_answer != nullptr) << dlerror();
812*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(42, get_answer());
813*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, dlclose(handle));
814*8d67ca89SAndroid Build Coastguard Worker }
815*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlopen_failure)816*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlopen_failure) {
817*8d67ca89SAndroid Build Coastguard Worker void* self = dlopen("/does/not/exist", RTLD_NOW);
818*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(self == nullptr);
819*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
820*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ("dlopen failed: library \"/does/not/exist\" not found", dlerror());
821*8d67ca89SAndroid Build Coastguard Worker #else
822*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ("/does/not/exist: cannot open shared object file: No such file or directory", dlerror());
823*8d67ca89SAndroid Build Coastguard Worker #endif
824*8d67ca89SAndroid Build Coastguard Worker }
825*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlclose_unload)826*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlclose_unload) {
827*8d67ca89SAndroid Build Coastguard Worker const size_t kPageSize = getpagesize();
828*8d67ca89SAndroid Build Coastguard Worker
829*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libtest_simple.so", RTLD_NOW);
830*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
831*8d67ca89SAndroid Build Coastguard Worker uint32_t* taxicab_number = static_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
832*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(taxicab_number != nullptr) << dlerror();
833*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(1729U, *taxicab_number);
834*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
835*8d67ca89SAndroid Build Coastguard Worker // Making sure that the library has been unmapped as part of library unload
836*8d67ca89SAndroid Build Coastguard Worker // process. Note that mprotect somewhat counter-intuitively returns ENOMEM in
837*8d67ca89SAndroid Build Coastguard Worker // this case.
838*8d67ca89SAndroid Build Coastguard Worker uintptr_t page_start = reinterpret_cast<uintptr_t>(taxicab_number) & ~(kPageSize - 1);
839*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(mprotect(reinterpret_cast<void*>(page_start), kPageSize, PROT_NONE) != 0);
840*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERRNO(ENOMEM);
841*8d67ca89SAndroid Build Coastguard Worker }
842*8d67ca89SAndroid Build Coastguard Worker
ConcurrentDlErrorFn(std::string & error)843*8d67ca89SAndroid Build Coastguard Worker static void ConcurrentDlErrorFn(std::string& error) {
844*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(dlerror() == nullptr);
845*8d67ca89SAndroid Build Coastguard Worker
846*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("/child/thread", RTLD_NOW);
847*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle == nullptr);
848*8d67ca89SAndroid Build Coastguard Worker
849*8d67ca89SAndroid Build Coastguard Worker const char* err = dlerror();
850*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(err != nullptr);
851*8d67ca89SAndroid Build Coastguard Worker
852*8d67ca89SAndroid Build Coastguard Worker error = err;
853*8d67ca89SAndroid Build Coastguard Worker }
854*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlerror_concurrent_buffer)855*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlerror_concurrent_buffer) {
856*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("/main/thread", RTLD_NOW);
857*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle == nullptr);
858*8d67ca89SAndroid Build Coastguard Worker const char* main_thread_error = dlerror();
859*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(main_thread_error != nullptr);
860*8d67ca89SAndroid Build Coastguard Worker ASSERT_SUBSTR("/main/thread", main_thread_error);
861*8d67ca89SAndroid Build Coastguard Worker
862*8d67ca89SAndroid Build Coastguard Worker std::string child_thread_error;
863*8d67ca89SAndroid Build Coastguard Worker std::thread t(ConcurrentDlErrorFn, std::ref(child_thread_error));
864*8d67ca89SAndroid Build Coastguard Worker t.join();
865*8d67ca89SAndroid Build Coastguard Worker ASSERT_SUBSTR("/child/thread", child_thread_error.c_str());
866*8d67ca89SAndroid Build Coastguard Worker
867*8d67ca89SAndroid Build Coastguard Worker // Check that main thread local buffer was not modified.
868*8d67ca89SAndroid Build Coastguard Worker ASSERT_SUBSTR("/main/thread", main_thread_error);
869*8d67ca89SAndroid Build Coastguard Worker }
870*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlerror_concurrent)871*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlerror_concurrent) {
872*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("/main/thread", RTLD_NOW);
873*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle == nullptr);
874*8d67ca89SAndroid Build Coastguard Worker
875*8d67ca89SAndroid Build Coastguard Worker std::string child_thread_error;
876*8d67ca89SAndroid Build Coastguard Worker std::thread t(ConcurrentDlErrorFn, std::ref(child_thread_error));
877*8d67ca89SAndroid Build Coastguard Worker t.join();
878*8d67ca89SAndroid Build Coastguard Worker ASSERT_SUBSTR("/child/thread", child_thread_error.c_str());
879*8d67ca89SAndroid Build Coastguard Worker
880*8d67ca89SAndroid Build Coastguard Worker const char* main_thread_error = dlerror();
881*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(main_thread_error != nullptr);
882*8d67ca89SAndroid Build Coastguard Worker ASSERT_SUBSTR("/main/thread", main_thread_error);
883*8d67ca89SAndroid Build Coastguard Worker }
884*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlsym_failures)885*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlsym_failures) {
886*8d67ca89SAndroid Build Coastguard Worker dlerror(); // Clear any pending errors.
887*8d67ca89SAndroid Build Coastguard Worker void* self = dlopen(nullptr, RTLD_NOW);
888*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(self != nullptr);
889*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(dlerror() == nullptr);
890*8d67ca89SAndroid Build Coastguard Worker
891*8d67ca89SAndroid Build Coastguard Worker void* sym;
892*8d67ca89SAndroid Build Coastguard Worker
893*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__) && !defined(__LP64__)
894*8d67ca89SAndroid Build Coastguard Worker #pragma clang diagnostic push
895*8d67ca89SAndroid Build Coastguard Worker #pragma clang diagnostic ignored "-Wnonnull"
896*8d67ca89SAndroid Build Coastguard Worker // RTLD_DEFAULT in lp32 bionic is not (void*)0
897*8d67ca89SAndroid Build Coastguard Worker // so it can be distinguished from the NULL handle.
898*8d67ca89SAndroid Build Coastguard Worker sym = dlsym(nullptr, "test");
899*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(sym == nullptr);
900*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ("dlsym failed: library handle is null", dlerror());
901*8d67ca89SAndroid Build Coastguard Worker #pragma clang diagnostic pop
902*8d67ca89SAndroid Build Coastguard Worker #endif
903*8d67ca89SAndroid Build Coastguard Worker
904*8d67ca89SAndroid Build Coastguard Worker // Symbol that doesn't exist.
905*8d67ca89SAndroid Build Coastguard Worker sym = dlsym(self, "ThisSymbolDoesNotExist");
906*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(sym == nullptr);
907*8d67ca89SAndroid Build Coastguard Worker ASSERT_SUBSTR("undefined symbol: ThisSymbolDoesNotExist", dlerror());
908*8d67ca89SAndroid Build Coastguard Worker
909*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, dlclose(self));
910*8d67ca89SAndroid Build Coastguard Worker }
911*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dladdr_executable)912*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dladdr_executable) {
913*8d67ca89SAndroid Build Coastguard Worker dlerror(); // Clear any pending errors.
914*8d67ca89SAndroid Build Coastguard Worker void* self = dlopen(nullptr, RTLD_NOW);
915*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(self != nullptr);
916*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(dlerror() == nullptr);
917*8d67ca89SAndroid Build Coastguard Worker
918*8d67ca89SAndroid Build Coastguard Worker void* sym = dlsym(self, "DlSymTestFunction");
919*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(sym != nullptr);
920*8d67ca89SAndroid Build Coastguard Worker
921*8d67ca89SAndroid Build Coastguard Worker // Deliberately ask dladdr for an address inside a symbol, rather than the symbol base address.
922*8d67ca89SAndroid Build Coastguard Worker void* addr = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(sym) + 2);
923*8d67ca89SAndroid Build Coastguard Worker
924*8d67ca89SAndroid Build Coastguard Worker Dl_info info;
925*8d67ca89SAndroid Build Coastguard Worker int rc = dladdr(addr, &info);
926*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(rc, 0); // Zero on error, non-zero on success.
927*8d67ca89SAndroid Build Coastguard Worker
928*8d67ca89SAndroid Build Coastguard Worker // Get the name of this executable.
929*8d67ca89SAndroid Build Coastguard Worker const std::string executable_path = android::base::GetExecutablePath();
930*8d67ca89SAndroid Build Coastguard Worker
931*8d67ca89SAndroid Build Coastguard Worker // The filename should be that of this executable.
932*8d67ca89SAndroid Build Coastguard Worker char dli_realpath[PATH_MAX];
933*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(realpath(info.dli_fname, dli_realpath) != nullptr);
934*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(executable_path.c_str(), dli_realpath);
935*8d67ca89SAndroid Build Coastguard Worker
936*8d67ca89SAndroid Build Coastguard Worker // The symbol name should be the symbol we looked up.
937*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(info.dli_sname, "DlSymTestFunction");
938*8d67ca89SAndroid Build Coastguard Worker
939*8d67ca89SAndroid Build Coastguard Worker // The address should be the exact address of the symbol.
940*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(info.dli_saddr, sym);
941*8d67ca89SAndroid Build Coastguard Worker
942*8d67ca89SAndroid Build Coastguard Worker std::vector<map_record> maps;
943*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(Maps::parse_maps(&maps));
944*8d67ca89SAndroid Build Coastguard Worker
945*8d67ca89SAndroid Build Coastguard Worker void* base_address = nullptr;
946*8d67ca89SAndroid Build Coastguard Worker for (const map_record& rec : maps) {
947*8d67ca89SAndroid Build Coastguard Worker if (executable_path == rec.pathname) {
948*8d67ca89SAndroid Build Coastguard Worker base_address = reinterpret_cast<void*>(rec.addr_start);
949*8d67ca89SAndroid Build Coastguard Worker break;
950*8d67ca89SAndroid Build Coastguard Worker }
951*8d67ca89SAndroid Build Coastguard Worker }
952*8d67ca89SAndroid Build Coastguard Worker
953*8d67ca89SAndroid Build Coastguard Worker // The base address should be the address we were loaded at.
954*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(info.dli_fbase, base_address);
955*8d67ca89SAndroid Build Coastguard Worker
956*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, dlclose(self));
957*8d67ca89SAndroid Build Coastguard Worker }
958*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlopen_executable_by_absolute_path)959*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlopen_executable_by_absolute_path) {
960*8d67ca89SAndroid Build Coastguard Worker void* handle1 = dlopen(nullptr, RTLD_NOW);
961*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle1 != nullptr) << dlerror();
962*8d67ca89SAndroid Build Coastguard Worker
963*8d67ca89SAndroid Build Coastguard Worker void* handle2 = dlopen(android::base::GetExecutablePath().c_str(), RTLD_NOW);
964*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle2 != nullptr) << dlerror();
965*8d67ca89SAndroid Build Coastguard Worker
966*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
967*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(handle1, handle2);
968*8d67ca89SAndroid Build Coastguard Worker #else
969*8d67ca89SAndroid Build Coastguard Worker GTEST_SKIP() << "Skipping ASSERT_EQ(handle1, handle2) for glibc: "
970*8d67ca89SAndroid Build Coastguard Worker "it loads a separate copy of the main executable "
971*8d67ca89SAndroid Build Coastguard Worker "on dlopen by absolute path";
972*8d67ca89SAndroid Build Coastguard Worker #endif
973*8d67ca89SAndroid Build Coastguard Worker }
974*8d67ca89SAndroid Build Coastguard Worker
975*8d67ca89SAndroid Build Coastguard Worker #define ALTERNATE_PATH_TO_SYSTEM_LIB "/system/lib64/" ABI_STRING "/"
976*8d67ca89SAndroid Build Coastguard Worker #if __has_feature(hwaddress_sanitizer)
977*8d67ca89SAndroid Build Coastguard Worker #define PATH_TO_LIBC PATH_TO_SYSTEM_LIB "hwasan/libc.so"
978*8d67ca89SAndroid Build Coastguard Worker #define PATH_TO_BOOTSTRAP_LIBC PATH_TO_SYSTEM_LIB "bootstrap/hwasan/libc.so"
979*8d67ca89SAndroid Build Coastguard Worker #define ALTERNATE_PATH_TO_LIBC ALTERNATE_PATH_TO_SYSTEM_LIB "hwasan/libc.so"
980*8d67ca89SAndroid Build Coastguard Worker #else
981*8d67ca89SAndroid Build Coastguard Worker #define PATH_TO_LIBC PATH_TO_SYSTEM_LIB "libc.so"
982*8d67ca89SAndroid Build Coastguard Worker #define PATH_TO_BOOTSTRAP_LIBC PATH_TO_SYSTEM_LIB "bootstrap/libc.so"
983*8d67ca89SAndroid Build Coastguard Worker #define ALTERNATE_PATH_TO_LIBC ALTERNATE_PATH_TO_SYSTEM_LIB "libc.so"
984*8d67ca89SAndroid Build Coastguard Worker #endif
985*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dladdr_libc)986*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dladdr_libc) {
987*8d67ca89SAndroid Build Coastguard Worker #if defined(__GLIBC__)
988*8d67ca89SAndroid Build Coastguard Worker GTEST_SKIP() << "glibc returns libc.so's ldconfig path, which is a symlink (not a realpath)";
989*8d67ca89SAndroid Build Coastguard Worker #endif
990*8d67ca89SAndroid Build Coastguard Worker
991*8d67ca89SAndroid Build Coastguard Worker Dl_info info;
992*8d67ca89SAndroid Build Coastguard Worker void* addr = reinterpret_cast<void*>(puts); // An arbitrary libc function.
993*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(dladdr(addr, &info) != 0);
994*8d67ca89SAndroid Build Coastguard Worker
995*8d67ca89SAndroid Build Coastguard Worker // Check if libc is in canonical path or in alternate path.
996*8d67ca89SAndroid Build Coastguard Worker const char* expected_path;
997*8d67ca89SAndroid Build Coastguard Worker if (strncmp(ALTERNATE_PATH_TO_SYSTEM_LIB,
998*8d67ca89SAndroid Build Coastguard Worker info.dli_fname,
999*8d67ca89SAndroid Build Coastguard Worker sizeof(ALTERNATE_PATH_TO_SYSTEM_LIB) - 1) == 0) {
1000*8d67ca89SAndroid Build Coastguard Worker // Platform with emulated architecture. Symlink on ARC++.
1001*8d67ca89SAndroid Build Coastguard Worker expected_path = ALTERNATE_PATH_TO_LIBC;
1002*8d67ca89SAndroid Build Coastguard Worker } else if (strncmp(PATH_TO_BOOTSTRAP_LIBC, info.dli_fname,
1003*8d67ca89SAndroid Build Coastguard Worker sizeof(PATH_TO_BOOTSTRAP_LIBC) - 1) == 0) {
1004*8d67ca89SAndroid Build Coastguard Worker expected_path = PATH_TO_BOOTSTRAP_LIBC;
1005*8d67ca89SAndroid Build Coastguard Worker } else {
1006*8d67ca89SAndroid Build Coastguard Worker // /system/lib is symlink when this test is executed on host.
1007*8d67ca89SAndroid Build Coastguard Worker expected_path = PATH_TO_LIBC;
1008*8d67ca89SAndroid Build Coastguard Worker }
1009*8d67ca89SAndroid Build Coastguard Worker char libc_realpath[PATH_MAX];
1010*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(realpath(expected_path, libc_realpath) != nullptr) << strerror(errno);
1011*8d67ca89SAndroid Build Coastguard Worker
1012*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(libc_realpath, info.dli_fname);
1013*8d67ca89SAndroid Build Coastguard Worker // TODO: add check for dfi_fbase
1014*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ("puts", info.dli_sname);
1015*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(addr, info.dli_saddr);
1016*8d67ca89SAndroid Build Coastguard Worker }
1017*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dladdr_invalid)1018*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dladdr_invalid) {
1019*8d67ca89SAndroid Build Coastguard Worker Dl_info info;
1020*8d67ca89SAndroid Build Coastguard Worker
1021*8d67ca89SAndroid Build Coastguard Worker dlerror(); // Clear any pending errors.
1022*8d67ca89SAndroid Build Coastguard Worker
1023*8d67ca89SAndroid Build Coastguard Worker #pragma clang diagnostic push
1024*8d67ca89SAndroid Build Coastguard Worker #pragma clang diagnostic ignored "-Wnonnull"
1025*8d67ca89SAndroid Build Coastguard Worker // No symbol corresponding to NULL.
1026*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(dladdr(nullptr, &info), 0); // Zero on error, non-zero on success.
1027*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(dlerror() == nullptr); // dladdr(3) doesn't set dlerror(3).
1028*8d67ca89SAndroid Build Coastguard Worker #pragma clang diagnostic pop
1029*8d67ca89SAndroid Build Coastguard Worker
1030*8d67ca89SAndroid Build Coastguard Worker // No symbol corresponding to a stack address.
1031*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(dladdr(&info, &info), 0); // Zero on error, non-zero on success.
1032*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(dlerror() == nullptr); // dladdr(3) doesn't set dlerror(3).
1033*8d67ca89SAndroid Build Coastguard Worker }
1034*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlopen_library_with_only_gnu_hash)1035*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlopen_library_with_only_gnu_hash) {
1036*8d67ca89SAndroid Build Coastguard Worker dlerror(); // Clear any pending errors.
1037*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libgnu-hash-table-library.so", RTLD_NOW);
1038*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
1039*8d67ca89SAndroid Build Coastguard Worker auto guard = android::base::make_scope_guard([&]() { dlclose(handle); });
1040*8d67ca89SAndroid Build Coastguard Worker void* sym = dlsym(handle, "getRandomNumber");
1041*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(sym != nullptr) << dlerror();
1042*8d67ca89SAndroid Build Coastguard Worker int (*fn)(void);
1043*8d67ca89SAndroid Build Coastguard Worker fn = reinterpret_cast<int (*)(void)>(sym);
1044*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(4, fn());
1045*8d67ca89SAndroid Build Coastguard Worker
1046*8d67ca89SAndroid Build Coastguard Worker Dl_info dlinfo;
1047*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(0 != dladdr(reinterpret_cast<void*>(fn), &dlinfo));
1048*8d67ca89SAndroid Build Coastguard Worker
1049*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(fn == dlinfo.dli_saddr);
1050*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ("getRandomNumber", dlinfo.dli_sname);
1051*8d67ca89SAndroid Build Coastguard Worker ASSERT_SUBSTR("libgnu-hash-table-library.so", dlinfo.dli_fname);
1052*8d67ca89SAndroid Build Coastguard Worker }
1053*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlopen_library_with_only_sysv_hash)1054*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlopen_library_with_only_sysv_hash) {
1055*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libsysv-hash-table-library.so", RTLD_NOW);
1056*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
1057*8d67ca89SAndroid Build Coastguard Worker auto guard = android::base::make_scope_guard([&]() { dlclose(handle); });
1058*8d67ca89SAndroid Build Coastguard Worker void* sym = dlsym(handle, "getRandomNumber");
1059*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(sym != nullptr) << dlerror();
1060*8d67ca89SAndroid Build Coastguard Worker int (*fn)(void);
1061*8d67ca89SAndroid Build Coastguard Worker fn = reinterpret_cast<int (*)(void)>(sym);
1062*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(4, fn());
1063*8d67ca89SAndroid Build Coastguard Worker
1064*8d67ca89SAndroid Build Coastguard Worker Dl_info dlinfo;
1065*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(0 != dladdr(reinterpret_cast<void*>(fn), &dlinfo));
1066*8d67ca89SAndroid Build Coastguard Worker
1067*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(fn == dlinfo.dli_saddr);
1068*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ("getRandomNumber", dlinfo.dli_sname);
1069*8d67ca89SAndroid Build Coastguard Worker ASSERT_SUBSTR("libsysv-hash-table-library.so", dlinfo.dli_fname);
1070*8d67ca89SAndroid Build Coastguard Worker }
1071*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlopen_bad_flags)1072*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlopen_bad_flags) {
1073*8d67ca89SAndroid Build Coastguard Worker dlerror(); // Clear any pending errors.
1074*8d67ca89SAndroid Build Coastguard Worker void* handle;
1075*8d67ca89SAndroid Build Coastguard Worker
1076*8d67ca89SAndroid Build Coastguard Worker #if defined(__GLIBC__)
1077*8d67ca89SAndroid Build Coastguard Worker // glibc was smart enough not to define RTLD_NOW as 0, so it can detect missing flags.
1078*8d67ca89SAndroid Build Coastguard Worker handle = dlopen(nullptr, 0);
1079*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle == nullptr);
1080*8d67ca89SAndroid Build Coastguard Worker ASSERT_SUBSTR("invalid", dlerror());
1081*8d67ca89SAndroid Build Coastguard Worker #endif
1082*8d67ca89SAndroid Build Coastguard Worker
1083*8d67ca89SAndroid Build Coastguard Worker handle = dlopen(nullptr, 0xffffffff);
1084*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle == nullptr);
1085*8d67ca89SAndroid Build Coastguard Worker ASSERT_SUBSTR("invalid", dlerror());
1086*8d67ca89SAndroid Build Coastguard Worker
1087*8d67ca89SAndroid Build Coastguard Worker // glibc actually allows you to choose both RTLD_NOW and RTLD_LAZY at the same time, and so do we.
1088*8d67ca89SAndroid Build Coastguard Worker handle = dlopen(nullptr, RTLD_NOW|RTLD_LAZY);
1089*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr);
1090*8d67ca89SAndroid Build Coastguard Worker ASSERT_SUBSTR(nullptr, dlerror());
1091*8d67ca89SAndroid Build Coastguard Worker }
1092*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,rtld_default_unknown_symbol)1093*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, rtld_default_unknown_symbol) {
1094*8d67ca89SAndroid Build Coastguard Worker void* addr = dlsym(RTLD_DEFAULT, "ANY_UNKNOWN_SYMBOL_NAME");
1095*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(addr == nullptr);
1096*8d67ca89SAndroid Build Coastguard Worker }
1097*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,rtld_default_known_symbol)1098*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, rtld_default_known_symbol) {
1099*8d67ca89SAndroid Build Coastguard Worker void* addr = dlsym(RTLD_DEFAULT, "fopen");
1100*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(addr != nullptr);
1101*8d67ca89SAndroid Build Coastguard Worker }
1102*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,rtld_next_unknown_symbol)1103*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, rtld_next_unknown_symbol) {
1104*8d67ca89SAndroid Build Coastguard Worker void* addr = dlsym(RTLD_NEXT, "ANY_UNKNOWN_SYMBOL_NAME");
1105*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(addr == nullptr);
1106*8d67ca89SAndroid Build Coastguard Worker }
1107*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,rtld_next_known_symbol)1108*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, rtld_next_known_symbol) {
1109*8d67ca89SAndroid Build Coastguard Worker void* addr = dlsym(RTLD_NEXT, "fopen");
1110*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(addr != nullptr);
1111*8d67ca89SAndroid Build Coastguard Worker }
1112*8d67ca89SAndroid Build Coastguard Worker
1113*8d67ca89SAndroid Build Coastguard Worker // Check that RTLD_NEXT of a libc symbol works in dlopened library
TEST(dlfcn,rtld_next_from_library)1114*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, rtld_next_from_library) {
1115*8d67ca89SAndroid Build Coastguard Worker void* library_with_fclose = dlopen("libtest_check_rtld_next_from_library.so", RTLD_NOW | RTLD_GLOBAL);
1116*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(library_with_fclose != nullptr) << dlerror();
1117*8d67ca89SAndroid Build Coastguard Worker void* expected_addr = dlsym(RTLD_DEFAULT, "fclose");
1118*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(expected_addr != nullptr) << dlerror();
1119*8d67ca89SAndroid Build Coastguard Worker typedef void* (*get_libc_fclose_ptr_fn_t)();
1120*8d67ca89SAndroid Build Coastguard Worker get_libc_fclose_ptr_fn_t get_libc_fclose_ptr =
1121*8d67ca89SAndroid Build Coastguard Worker reinterpret_cast<get_libc_fclose_ptr_fn_t>(dlsym(library_with_fclose, "get_libc_fclose_ptr"));
1122*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(get_libc_fclose_ptr != nullptr) << dlerror();
1123*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(expected_addr, get_libc_fclose_ptr());
1124*8d67ca89SAndroid Build Coastguard Worker
1125*8d67ca89SAndroid Build Coastguard Worker dlclose(library_with_fclose);
1126*8d67ca89SAndroid Build Coastguard Worker }
1127*8d67ca89SAndroid Build Coastguard Worker
1128*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlsym_weak_func)1129*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlsym_weak_func) {
1130*8d67ca89SAndroid Build Coastguard Worker dlerror();
1131*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libtest_dlsym_weak_func.so", RTLD_NOW);
1132*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr);
1133*8d67ca89SAndroid Build Coastguard Worker
1134*8d67ca89SAndroid Build Coastguard Worker int (*weak_func)();
1135*8d67ca89SAndroid Build Coastguard Worker weak_func = reinterpret_cast<int (*)()>(dlsym(handle, "weak_func"));
1136*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(weak_func != nullptr) << "dlerror: " << dlerror();
1137*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(42, weak_func());
1138*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
1139*8d67ca89SAndroid Build Coastguard Worker }
1140*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlopen_undefined_weak_func)1141*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlopen_undefined_weak_func) {
1142*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libtest_dlopen_weak_undefined_func.so", RTLD_NOW);
1143*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
1144*8d67ca89SAndroid Build Coastguard Worker int (*weak_func)();
1145*8d67ca89SAndroid Build Coastguard Worker weak_func = reinterpret_cast<int (*)()>(dlsym(handle, "use_weak_undefined_func"));
1146*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(weak_func != nullptr) << dlerror();
1147*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(6551, weak_func());
1148*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
1149*8d67ca89SAndroid Build Coastguard Worker }
1150*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlopen_symlink)1151*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlopen_symlink) {
1152*8d67ca89SAndroid Build Coastguard Worker DlfcnSymlink symlink("dlopen_symlink");
1153*8d67ca89SAndroid Build Coastguard Worker const std::string symlink_name = android::base::Basename(symlink.get_symlink_path());
1154*8d67ca89SAndroid Build Coastguard Worker void* handle1 = dlopen("libdlext_test.so", RTLD_NOW);
1155*8d67ca89SAndroid Build Coastguard Worker void* handle2 = dlopen(symlink_name.c_str(), RTLD_NOW);
1156*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle1 != nullptr);
1157*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle2 != nullptr);
1158*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(handle1, handle2);
1159*8d67ca89SAndroid Build Coastguard Worker dlclose(handle1);
1160*8d67ca89SAndroid Build Coastguard Worker dlclose(handle2);
1161*8d67ca89SAndroid Build Coastguard Worker }
1162*8d67ca89SAndroid Build Coastguard Worker
1163*8d67ca89SAndroid Build Coastguard Worker // libtest_dlopen_from_ctor_main.so depends on
1164*8d67ca89SAndroid Build Coastguard Worker // libtest_dlopen_from_ctor.so which has a constructor
1165*8d67ca89SAndroid Build Coastguard Worker // that calls dlopen(libc...). This is to test the situation
1166*8d67ca89SAndroid Build Coastguard Worker // described in b/7941716.
TEST(dlfcn,dlopen_dlopen_from_ctor)1167*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlopen_dlopen_from_ctor) {
1168*8d67ca89SAndroid Build Coastguard Worker #if defined(__GLIBC__)
1169*8d67ca89SAndroid Build Coastguard Worker GTEST_SKIP() << "glibc segfaults if you try to call dlopen from a constructor";
1170*8d67ca89SAndroid Build Coastguard Worker #endif
1171*8d67ca89SAndroid Build Coastguard Worker
1172*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libtest_dlopen_from_ctor_main.so", RTLD_NOW);
1173*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
1174*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
1175*8d67ca89SAndroid Build Coastguard Worker }
1176*8d67ca89SAndroid Build Coastguard Worker
1177*8d67ca89SAndroid Build Coastguard Worker static std::string g_fini_call_order_str;
1178*8d67ca89SAndroid Build Coastguard Worker
register_fini_call(const char * s)1179*8d67ca89SAndroid Build Coastguard Worker static void register_fini_call(const char* s) {
1180*8d67ca89SAndroid Build Coastguard Worker g_fini_call_order_str += s;
1181*8d67ca89SAndroid Build Coastguard Worker }
1182*8d67ca89SAndroid Build Coastguard Worker
test_init_fini_call_order_for(const char * libname)1183*8d67ca89SAndroid Build Coastguard Worker static void test_init_fini_call_order_for(const char* libname) {
1184*8d67ca89SAndroid Build Coastguard Worker g_fini_call_order_str.clear();
1185*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen(libname, RTLD_NOW);
1186*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
1187*8d67ca89SAndroid Build Coastguard Worker typedef int (*get_init_order_number_t)();
1188*8d67ca89SAndroid Build Coastguard Worker get_init_order_number_t get_init_order_number =
1189*8d67ca89SAndroid Build Coastguard Worker reinterpret_cast<get_init_order_number_t>(dlsym(handle, "get_init_order_number"));
1190*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(321, get_init_order_number());
1191*8d67ca89SAndroid Build Coastguard Worker
1192*8d67ca89SAndroid Build Coastguard Worker typedef void (*set_fini_callback_t)(void (*f)(const char*));
1193*8d67ca89SAndroid Build Coastguard Worker set_fini_callback_t set_fini_callback =
1194*8d67ca89SAndroid Build Coastguard Worker reinterpret_cast<set_fini_callback_t>(dlsym(handle, "set_fini_callback"));
1195*8d67ca89SAndroid Build Coastguard Worker set_fini_callback(register_fini_call);
1196*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
1197*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ("(root)(child)(grandchild)", g_fini_call_order_str);
1198*8d67ca89SAndroid Build Coastguard Worker }
1199*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,init_fini_call_order)1200*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, init_fini_call_order) {
1201*8d67ca89SAndroid Build Coastguard Worker test_init_fini_call_order_for("libtest_init_fini_order_root.so");
1202*8d67ca89SAndroid Build Coastguard Worker test_init_fini_call_order_for("libtest_init_fini_order_root2.so");
1203*8d67ca89SAndroid Build Coastguard Worker }
1204*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,symbol_versioning_use_v1)1205*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, symbol_versioning_use_v1) {
1206*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libtest_versioned_uselibv1.so", RTLD_NOW);
1207*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
1208*8d67ca89SAndroid Build Coastguard Worker typedef int (*fn_t)();
1209*8d67ca89SAndroid Build Coastguard Worker fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "get_function_version"));
1210*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(fn != nullptr) << dlerror();
1211*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(1, fn());
1212*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
1213*8d67ca89SAndroid Build Coastguard Worker }
1214*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,symbol_versioning_use_v2)1215*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, symbol_versioning_use_v2) {
1216*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libtest_versioned_uselibv2.so", RTLD_NOW);
1217*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
1218*8d67ca89SAndroid Build Coastguard Worker typedef int (*fn_t)();
1219*8d67ca89SAndroid Build Coastguard Worker fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "get_function_version"));
1220*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(fn != nullptr) << dlerror();
1221*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(2, fn());
1222*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
1223*8d67ca89SAndroid Build Coastguard Worker }
1224*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,symbol_versioning_use_other_v2)1225*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, symbol_versioning_use_other_v2) {
1226*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libtest_versioned_uselibv2_other.so", RTLD_NOW);
1227*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
1228*8d67ca89SAndroid Build Coastguard Worker typedef int (*fn_t)();
1229*8d67ca89SAndroid Build Coastguard Worker fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "get_function_version"));
1230*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(fn != nullptr) << dlerror();
1231*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(20, fn());
1232*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
1233*8d67ca89SAndroid Build Coastguard Worker }
1234*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,symbol_versioning_use_other_v3)1235*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, symbol_versioning_use_other_v3) {
1236*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libtest_versioned_uselibv3_other.so", RTLD_NOW);
1237*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
1238*8d67ca89SAndroid Build Coastguard Worker typedef int (*fn_t)();
1239*8d67ca89SAndroid Build Coastguard Worker fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "get_function_version"));
1240*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(fn != nullptr) << dlerror();
1241*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(3, fn());
1242*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
1243*8d67ca89SAndroid Build Coastguard Worker }
1244*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,symbol_versioning_default_via_dlsym)1245*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, symbol_versioning_default_via_dlsym) {
1246*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libtest_versioned_lib.so", RTLD_NOW);
1247*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
1248*8d67ca89SAndroid Build Coastguard Worker typedef int (*fn_t)();
1249*8d67ca89SAndroid Build Coastguard Worker fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "versioned_function"));
1250*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(fn != nullptr) << dlerror();
1251*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(3, fn()); // the default version is 3
1252*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
1253*8d67ca89SAndroid Build Coastguard Worker }
1254*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlvsym_smoke)1255*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlvsym_smoke) {
1256*8d67ca89SAndroid Build Coastguard Worker #if !defined(ANDROID_HOST_MUSL)
1257*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libtest_versioned_lib.so", RTLD_NOW);
1258*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
1259*8d67ca89SAndroid Build Coastguard Worker typedef int (*fn_t)();
1260*8d67ca89SAndroid Build Coastguard Worker
1261*8d67ca89SAndroid Build Coastguard Worker {
1262*8d67ca89SAndroid Build Coastguard Worker fn_t fn = reinterpret_cast<fn_t>(dlvsym(handle, "versioned_function", "nonversion"));
1263*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(fn == nullptr);
1264*8d67ca89SAndroid Build Coastguard Worker ASSERT_SUBSTR("undefined symbol: versioned_function, version nonversion", dlerror());
1265*8d67ca89SAndroid Build Coastguard Worker }
1266*8d67ca89SAndroid Build Coastguard Worker
1267*8d67ca89SAndroid Build Coastguard Worker {
1268*8d67ca89SAndroid Build Coastguard Worker fn_t fn = reinterpret_cast<fn_t>(dlvsym(handle, "versioned_function", "TESTLIB_V2"));
1269*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(fn != nullptr) << dlerror();
1270*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(2, fn());
1271*8d67ca89SAndroid Build Coastguard Worker }
1272*8d67ca89SAndroid Build Coastguard Worker
1273*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
1274*8d67ca89SAndroid Build Coastguard Worker #else
1275*8d67ca89SAndroid Build Coastguard Worker GTEST_SKIP() << "musl doesn't have dlvsym";
1276*8d67ca89SAndroid Build Coastguard Worker #endif
1277*8d67ca89SAndroid Build Coastguard Worker }
1278*8d67ca89SAndroid Build Coastguard Worker
1279*8d67ca89SAndroid Build Coastguard Worker // This preempts the implementation from libtest_versioned_lib.so
version_zero_function()1280*8d67ca89SAndroid Build Coastguard Worker extern "C" int version_zero_function() {
1281*8d67ca89SAndroid Build Coastguard Worker return 0;
1282*8d67ca89SAndroid Build Coastguard Worker }
1283*8d67ca89SAndroid Build Coastguard Worker
1284*8d67ca89SAndroid Build Coastguard Worker // This preempts the implementation from libtest_versioned_uselibv*.so
version_zero_function2()1285*8d67ca89SAndroid Build Coastguard Worker extern "C" int version_zero_function2() {
1286*8d67ca89SAndroid Build Coastguard Worker return 0;
1287*8d67ca89SAndroid Build Coastguard Worker }
1288*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dt_runpath_smoke)1289*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dt_runpath_smoke) {
1290*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libtest_dt_runpath_d.so", RTLD_NOW);
1291*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
1292*8d67ca89SAndroid Build Coastguard Worker
1293*8d67ca89SAndroid Build Coastguard Worker typedef void *(* dlopen_b_fn)();
1294*8d67ca89SAndroid Build Coastguard Worker dlopen_b_fn fn = (dlopen_b_fn)dlsym(handle, "dlopen_b");
1295*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(fn != nullptr) << dlerror();
1296*8d67ca89SAndroid Build Coastguard Worker
1297*8d67ca89SAndroid Build Coastguard Worker void *p = fn();
1298*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(p != nullptr);
1299*8d67ca89SAndroid Build Coastguard Worker
1300*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
1301*8d67ca89SAndroid Build Coastguard Worker }
1302*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dt_runpath_absolute_path)1303*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dt_runpath_absolute_path) {
1304*8d67ca89SAndroid Build Coastguard Worker std::string libpath = GetTestLibRoot() + "/libtest_dt_runpath_d.so";
1305*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen(libpath.c_str(), RTLD_NOW);
1306*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
1307*8d67ca89SAndroid Build Coastguard Worker
1308*8d67ca89SAndroid Build Coastguard Worker typedef void *(* dlopen_b_fn)();
1309*8d67ca89SAndroid Build Coastguard Worker dlopen_b_fn fn = (dlopen_b_fn)dlsym(handle, "dlopen_b");
1310*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(fn != nullptr) << dlerror();
1311*8d67ca89SAndroid Build Coastguard Worker
1312*8d67ca89SAndroid Build Coastguard Worker void *p = fn();
1313*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(p != nullptr);
1314*8d67ca89SAndroid Build Coastguard Worker
1315*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
1316*8d67ca89SAndroid Build Coastguard Worker }
1317*8d67ca89SAndroid Build Coastguard Worker
test_dlclose_after_thread_local_dtor(const char * library_name)1318*8d67ca89SAndroid Build Coastguard Worker static void test_dlclose_after_thread_local_dtor(const char* library_name) {
1319*8d67ca89SAndroid Build Coastguard Worker bool is_dtor_triggered = false;
1320*8d67ca89SAndroid Build Coastguard Worker
1321*8d67ca89SAndroid Build Coastguard Worker auto f = [](void* handle, bool* is_dtor_triggered) {
1322*8d67ca89SAndroid Build Coastguard Worker typedef void (*fn_t)(bool*);
1323*8d67ca89SAndroid Build Coastguard Worker fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "init_thread_local_variable"));
1324*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(fn != nullptr) << dlerror();
1325*8d67ca89SAndroid Build Coastguard Worker
1326*8d67ca89SAndroid Build Coastguard Worker fn(is_dtor_triggered);
1327*8d67ca89SAndroid Build Coastguard Worker
1328*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(!*is_dtor_triggered);
1329*8d67ca89SAndroid Build Coastguard Worker };
1330*8d67ca89SAndroid Build Coastguard Worker
1331*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen(library_name, RTLD_NOW | RTLD_NOLOAD);
1332*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle == nullptr);
1333*8d67ca89SAndroid Build Coastguard Worker
1334*8d67ca89SAndroid Build Coastguard Worker handle = dlopen(library_name, RTLD_NOW);
1335*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
1336*8d67ca89SAndroid Build Coastguard Worker
1337*8d67ca89SAndroid Build Coastguard Worker std::thread t(f, handle, &is_dtor_triggered);
1338*8d67ca89SAndroid Build Coastguard Worker t.join();
1339*8d67ca89SAndroid Build Coastguard Worker
1340*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(is_dtor_triggered);
1341*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
1342*8d67ca89SAndroid Build Coastguard Worker
1343*8d67ca89SAndroid Build Coastguard Worker handle = dlopen(library_name, RTLD_NOW | RTLD_NOLOAD);
1344*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle == nullptr);
1345*8d67ca89SAndroid Build Coastguard Worker }
1346*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlclose_after_thread_local_dtor)1347*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlclose_after_thread_local_dtor) {
1348*8d67ca89SAndroid Build Coastguard Worker test_dlclose_after_thread_local_dtor("libtest_thread_local_dtor.so");
1349*8d67ca89SAndroid Build Coastguard Worker }
1350*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlclose_after_thread_local_dtor_indirect)1351*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlclose_after_thread_local_dtor_indirect) {
1352*8d67ca89SAndroid Build Coastguard Worker test_dlclose_after_thread_local_dtor("libtest_indirect_thread_local_dtor.so");
1353*8d67ca89SAndroid Build Coastguard Worker }
1354*8d67ca89SAndroid Build Coastguard Worker
test_dlclose_before_thread_local_dtor(const char * library_name)1355*8d67ca89SAndroid Build Coastguard Worker static void test_dlclose_before_thread_local_dtor(const char* library_name) {
1356*8d67ca89SAndroid Build Coastguard Worker bool is_dtor_triggered = false;
1357*8d67ca89SAndroid Build Coastguard Worker
1358*8d67ca89SAndroid Build Coastguard Worker auto f = [library_name](bool* is_dtor_triggered) {
1359*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen(library_name, RTLD_NOW | RTLD_NOLOAD);
1360*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle == nullptr);
1361*8d67ca89SAndroid Build Coastguard Worker
1362*8d67ca89SAndroid Build Coastguard Worker handle = dlopen(library_name, RTLD_NOW);
1363*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
1364*8d67ca89SAndroid Build Coastguard Worker
1365*8d67ca89SAndroid Build Coastguard Worker typedef void (*fn_t)(bool*);
1366*8d67ca89SAndroid Build Coastguard Worker fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "init_thread_local_variable"));
1367*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(fn != nullptr) << dlerror();
1368*8d67ca89SAndroid Build Coastguard Worker
1369*8d67ca89SAndroid Build Coastguard Worker fn(is_dtor_triggered);
1370*8d67ca89SAndroid Build Coastguard Worker
1371*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
1372*8d67ca89SAndroid Build Coastguard Worker
1373*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(!*is_dtor_triggered);
1374*8d67ca89SAndroid Build Coastguard Worker
1375*8d67ca89SAndroid Build Coastguard Worker // Since we have thread_atexit dtors associated with handle - the library should
1376*8d67ca89SAndroid Build Coastguard Worker // still be availabe.
1377*8d67ca89SAndroid Build Coastguard Worker handle = dlopen(library_name, RTLD_NOW | RTLD_NOLOAD);
1378*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
1379*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
1380*8d67ca89SAndroid Build Coastguard Worker };
1381*8d67ca89SAndroid Build Coastguard Worker
1382*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen(library_name, RTLD_NOW);
1383*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
1384*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
1385*8d67ca89SAndroid Build Coastguard Worker
1386*8d67ca89SAndroid Build Coastguard Worker handle = dlopen(library_name, RTLD_NOW | RTLD_NOLOAD);
1387*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle == nullptr);
1388*8d67ca89SAndroid Build Coastguard Worker
1389*8d67ca89SAndroid Build Coastguard Worker std::thread t(f, &is_dtor_triggered);
1390*8d67ca89SAndroid Build Coastguard Worker t.join();
1391*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
1392*8d67ca89SAndroid Build Coastguard Worker // ld-android.so unloads unreferenced libraries on pthread_exit()
1393*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(is_dtor_triggered);
1394*8d67ca89SAndroid Build Coastguard Worker handle = dlopen(library_name, RTLD_NOW | RTLD_NOLOAD);
1395*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle == nullptr);
1396*8d67ca89SAndroid Build Coastguard Worker #else
1397*8d67ca89SAndroid Build Coastguard Worker // GLIBC does not unload libraries with ref_count = 0 on pthread_exit
1398*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(is_dtor_triggered);
1399*8d67ca89SAndroid Build Coastguard Worker handle = dlopen(library_name, RTLD_NOW | RTLD_NOLOAD);
1400*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
1401*8d67ca89SAndroid Build Coastguard Worker #endif
1402*8d67ca89SAndroid Build Coastguard Worker }
1403*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlclose_before_thread_local_dtor)1404*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlclose_before_thread_local_dtor) {
1405*8d67ca89SAndroid Build Coastguard Worker test_dlclose_before_thread_local_dtor("libtest_thread_local_dtor.so");
1406*8d67ca89SAndroid Build Coastguard Worker }
1407*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlclose_before_thread_local_dtor_indirect)1408*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlclose_before_thread_local_dtor_indirect) {
1409*8d67ca89SAndroid Build Coastguard Worker test_dlclose_before_thread_local_dtor("libtest_indirect_thread_local_dtor.so");
1410*8d67ca89SAndroid Build Coastguard Worker }
1411*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlclose_before_thread_local_dtor_multiple_dsos)1412*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlclose_before_thread_local_dtor_multiple_dsos) {
1413*8d67ca89SAndroid Build Coastguard Worker const constexpr char* library_name = "libtest_indirect_thread_local_dtor.so";
1414*8d67ca89SAndroid Build Coastguard Worker
1415*8d67ca89SAndroid Build Coastguard Worker bool is_dtor1_triggered = false;
1416*8d67ca89SAndroid Build Coastguard Worker bool is_dtor2_triggered = false;
1417*8d67ca89SAndroid Build Coastguard Worker
1418*8d67ca89SAndroid Build Coastguard Worker std::mutex mtx;
1419*8d67ca89SAndroid Build Coastguard Worker std::condition_variable cv;
1420*8d67ca89SAndroid Build Coastguard Worker void* library_handle = nullptr;
1421*8d67ca89SAndroid Build Coastguard Worker bool thread1_dlopen_complete = false;
1422*8d67ca89SAndroid Build Coastguard Worker bool thread2_thread_local_dtor_initialized = false;
1423*8d67ca89SAndroid Build Coastguard Worker bool thread1_complete = false;
1424*8d67ca89SAndroid Build Coastguard Worker
1425*8d67ca89SAndroid Build Coastguard Worker auto f1 = [&]() {
1426*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen(library_name, RTLD_NOW | RTLD_NOLOAD);
1427*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle == nullptr);
1428*8d67ca89SAndroid Build Coastguard Worker
1429*8d67ca89SAndroid Build Coastguard Worker handle = dlopen(library_name, RTLD_NOW);
1430*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
1431*8d67ca89SAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock(mtx);
1432*8d67ca89SAndroid Build Coastguard Worker thread1_dlopen_complete = true;
1433*8d67ca89SAndroid Build Coastguard Worker library_handle = handle;
1434*8d67ca89SAndroid Build Coastguard Worker lock.unlock();
1435*8d67ca89SAndroid Build Coastguard Worker cv.notify_one();
1436*8d67ca89SAndroid Build Coastguard Worker
1437*8d67ca89SAndroid Build Coastguard Worker typedef void (*fn_t)(bool*);
1438*8d67ca89SAndroid Build Coastguard Worker fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "init_thread_local_variable"));
1439*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(fn != nullptr) << dlerror();
1440*8d67ca89SAndroid Build Coastguard Worker
1441*8d67ca89SAndroid Build Coastguard Worker fn(&is_dtor1_triggered);
1442*8d67ca89SAndroid Build Coastguard Worker
1443*8d67ca89SAndroid Build Coastguard Worker lock.lock();
1444*8d67ca89SAndroid Build Coastguard Worker cv.wait(lock, [&] { return thread2_thread_local_dtor_initialized; });
1445*8d67ca89SAndroid Build Coastguard Worker lock.unlock();
1446*8d67ca89SAndroid Build Coastguard Worker
1447*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
1448*8d67ca89SAndroid Build Coastguard Worker
1449*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(!is_dtor1_triggered);
1450*8d67ca89SAndroid Build Coastguard Worker
1451*8d67ca89SAndroid Build Coastguard Worker // Since we have thread_atexit dtors associated with handle - the library should
1452*8d67ca89SAndroid Build Coastguard Worker // still be availabe.
1453*8d67ca89SAndroid Build Coastguard Worker handle = dlopen(library_name, RTLD_NOW | RTLD_NOLOAD);
1454*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
1455*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
1456*8d67ca89SAndroid Build Coastguard Worker };
1457*8d67ca89SAndroid Build Coastguard Worker
1458*8d67ca89SAndroid Build Coastguard Worker auto f2 = [&]() {
1459*8d67ca89SAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock(mtx);
1460*8d67ca89SAndroid Build Coastguard Worker cv.wait(lock, [&] { return thread1_dlopen_complete; });
1461*8d67ca89SAndroid Build Coastguard Worker void* handle = library_handle;
1462*8d67ca89SAndroid Build Coastguard Worker lock.unlock();
1463*8d67ca89SAndroid Build Coastguard Worker
1464*8d67ca89SAndroid Build Coastguard Worker typedef void (*fn_t)(bool*);
1465*8d67ca89SAndroid Build Coastguard Worker fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "init_thread_local_variable2"));
1466*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(fn != nullptr) << dlerror();
1467*8d67ca89SAndroid Build Coastguard Worker
1468*8d67ca89SAndroid Build Coastguard Worker fn(&is_dtor2_triggered);
1469*8d67ca89SAndroid Build Coastguard Worker
1470*8d67ca89SAndroid Build Coastguard Worker lock.lock();
1471*8d67ca89SAndroid Build Coastguard Worker thread2_thread_local_dtor_initialized = true;
1472*8d67ca89SAndroid Build Coastguard Worker lock.unlock();
1473*8d67ca89SAndroid Build Coastguard Worker cv.notify_one();
1474*8d67ca89SAndroid Build Coastguard Worker
1475*8d67ca89SAndroid Build Coastguard Worker lock.lock();
1476*8d67ca89SAndroid Build Coastguard Worker cv.wait(lock, [&] { return thread1_complete; });
1477*8d67ca89SAndroid Build Coastguard Worker lock.unlock();
1478*8d67ca89SAndroid Build Coastguard Worker
1479*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(!is_dtor2_triggered);
1480*8d67ca89SAndroid Build Coastguard Worker };
1481*8d67ca89SAndroid Build Coastguard Worker
1482*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen(library_name, RTLD_NOW);
1483*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
1484*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
1485*8d67ca89SAndroid Build Coastguard Worker
1486*8d67ca89SAndroid Build Coastguard Worker handle = dlopen(library_name, RTLD_NOW | RTLD_NOLOAD);
1487*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle == nullptr);
1488*8d67ca89SAndroid Build Coastguard Worker
1489*8d67ca89SAndroid Build Coastguard Worker std::thread t1(f1);
1490*8d67ca89SAndroid Build Coastguard Worker std::thread t2(f2);
1491*8d67ca89SAndroid Build Coastguard Worker t1.join();
1492*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(is_dtor1_triggered);
1493*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(!is_dtor2_triggered);
1494*8d67ca89SAndroid Build Coastguard Worker
1495*8d67ca89SAndroid Build Coastguard Worker handle = dlopen(library_name, RTLD_NOW | RTLD_NOLOAD);
1496*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
1497*8d67ca89SAndroid Build Coastguard Worker dlclose(handle);
1498*8d67ca89SAndroid Build Coastguard Worker
1499*8d67ca89SAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock(mtx);
1500*8d67ca89SAndroid Build Coastguard Worker thread1_complete = true;
1501*8d67ca89SAndroid Build Coastguard Worker lock.unlock();
1502*8d67ca89SAndroid Build Coastguard Worker cv.notify_one();
1503*8d67ca89SAndroid Build Coastguard Worker
1504*8d67ca89SAndroid Build Coastguard Worker t2.join();
1505*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(is_dtor2_triggered);
1506*8d67ca89SAndroid Build Coastguard Worker
1507*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
1508*8d67ca89SAndroid Build Coastguard Worker // ld-android.so unloads unreferenced libraries on pthread_exit()
1509*8d67ca89SAndroid Build Coastguard Worker handle = dlopen(library_name, RTLD_NOW | RTLD_NOLOAD);
1510*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle == nullptr);
1511*8d67ca89SAndroid Build Coastguard Worker #else
1512*8d67ca89SAndroid Build Coastguard Worker // GLIBC does not unload libraries with ref_count = 0 on pthread_exit
1513*8d67ca89SAndroid Build Coastguard Worker handle = dlopen(library_name, RTLD_NOW | RTLD_NOLOAD);
1514*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
1515*8d67ca89SAndroid Build Coastguard Worker #endif
1516*8d67ca89SAndroid Build Coastguard Worker }
1517*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,RTLD_macros)1518*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, RTLD_macros) {
1519*8d67ca89SAndroid Build Coastguard Worker #if !defined(RTLD_LOCAL)
1520*8d67ca89SAndroid Build Coastguard Worker #error no RTLD_LOCAL
1521*8d67ca89SAndroid Build Coastguard Worker #elif !defined(RTLD_LAZY)
1522*8d67ca89SAndroid Build Coastguard Worker #error no RTLD_LAZY
1523*8d67ca89SAndroid Build Coastguard Worker #elif !defined(RTLD_NOW)
1524*8d67ca89SAndroid Build Coastguard Worker #error no RTLD_NOW
1525*8d67ca89SAndroid Build Coastguard Worker #elif !defined(RTLD_NOLOAD)
1526*8d67ca89SAndroid Build Coastguard Worker #error no RTLD_NOLOAD
1527*8d67ca89SAndroid Build Coastguard Worker #elif !defined(RTLD_GLOBAL)
1528*8d67ca89SAndroid Build Coastguard Worker #error no RTLD_GLOBAL
1529*8d67ca89SAndroid Build Coastguard Worker #elif !defined(RTLD_NODELETE)
1530*8d67ca89SAndroid Build Coastguard Worker #error no RTLD_NODELETE
1531*8d67ca89SAndroid Build Coastguard Worker #endif
1532*8d67ca89SAndroid Build Coastguard Worker }
1533*8d67ca89SAndroid Build Coastguard Worker
1534*8d67ca89SAndroid Build Coastguard Worker // Bionic specific tests
1535*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
1536*8d67ca89SAndroid Build Coastguard Worker
1537*8d67ca89SAndroid Build Coastguard Worker #if defined(__arm__)
1538*8d67ca89SAndroid Build Coastguard Worker
validate_compatibility_of_native_library(const std::string & soname,const std::string & path)1539*8d67ca89SAndroid Build Coastguard Worker void validate_compatibility_of_native_library(const std::string& soname, const std::string& path) {
1540*8d67ca89SAndroid Build Coastguard Worker // Grab the dynamic section in text form...
1541*8d67ca89SAndroid Build Coastguard Worker ExecTestHelper eth;
1542*8d67ca89SAndroid Build Coastguard Worker eth.SetArgs({"readelf", "-dW", path.c_str(), nullptr});
1543*8d67ca89SAndroid Build Coastguard Worker eth.Run([&]() { execvpe("readelf", eth.GetArgs(), eth.GetEnv()); }, 0, nullptr);
1544*8d67ca89SAndroid Build Coastguard Worker std::string output = eth.GetOutput();
1545*8d67ca89SAndroid Build Coastguard Worker
1546*8d67ca89SAndroid Build Coastguard Worker // Check that there *is* a legacy DT_HASH (not just a GNU hash)...
1547*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(std::regex_search(output, std::regex("\\(HASH\\)"))) << output;
1548*8d67ca89SAndroid Build Coastguard Worker // Check that there is no DT_ANDROID_REL or DT_ANDROID_RELA...
1549*8d67ca89SAndroid Build Coastguard Worker ASSERT_FALSE(std::regex_search(output, std::regex("\\(ANDROID_REL\\)"))) << output;
1550*8d67ca89SAndroid Build Coastguard Worker ASSERT_FALSE(std::regex_search(output, std::regex("\\(ANDROID_RELA\\)"))) << output;
1551*8d67ca89SAndroid Build Coastguard Worker
1552*8d67ca89SAndroid Build Coastguard Worker // Check that we have regular non-packed relocations.
1553*8d67ca89SAndroid Build Coastguard Worker // libdl.so is simple enough that it doesn't have any relocations.
1554*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(std::regex_search(output, std::regex("\\(RELA?\\)")) || soname == "libdl.so")
1555*8d67ca89SAndroid Build Coastguard Worker << output;
1556*8d67ca89SAndroid Build Coastguard Worker }
1557*8d67ca89SAndroid Build Coastguard Worker
validate_compatibility_of_native_library(const std::string & soname)1558*8d67ca89SAndroid Build Coastguard Worker void validate_compatibility_of_native_library(const std::string& soname) {
1559*8d67ca89SAndroid Build Coastguard Worker // On the systems with emulation system libraries would be of different
1560*8d67ca89SAndroid Build Coastguard Worker // architecture. Try to use alternate paths first.
1561*8d67ca89SAndroid Build Coastguard Worker std::string path = std::string(ALTERNATE_PATH_TO_SYSTEM_LIB) + soname;
1562*8d67ca89SAndroid Build Coastguard Worker if (access(path.c_str(), R_OK) != 0) {
1563*8d67ca89SAndroid Build Coastguard Worker path = std::string(PATH_TO_SYSTEM_LIB) + soname;
1564*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, access(path.c_str(), R_OK));
1565*8d67ca89SAndroid Build Coastguard Worker }
1566*8d67ca89SAndroid Build Coastguard Worker validate_compatibility_of_native_library(soname, path);
1567*8d67ca89SAndroid Build Coastguard Worker }
1568*8d67ca89SAndroid Build Coastguard Worker
1569*8d67ca89SAndroid Build Coastguard Worker // This is a test for app compatibility workaround for arm apps
1570*8d67ca89SAndroid Build Coastguard Worker // affected by http://b/24465209
TEST(dlext,compat_elf_hash_and_relocation_tables)1571*8d67ca89SAndroid Build Coastguard Worker TEST(dlext, compat_elf_hash_and_relocation_tables) {
1572*8d67ca89SAndroid Build Coastguard Worker validate_compatibility_of_native_library("libc.so");
1573*8d67ca89SAndroid Build Coastguard Worker validate_compatibility_of_native_library("liblog.so");
1574*8d67ca89SAndroid Build Coastguard Worker validate_compatibility_of_native_library("libstdc++.so");
1575*8d67ca89SAndroid Build Coastguard Worker validate_compatibility_of_native_library("libdl.so");
1576*8d67ca89SAndroid Build Coastguard Worker validate_compatibility_of_native_library("libm.so");
1577*8d67ca89SAndroid Build Coastguard Worker validate_compatibility_of_native_library("libz.so");
1578*8d67ca89SAndroid Build Coastguard Worker validate_compatibility_of_native_library("libjnigraphics.so");
1579*8d67ca89SAndroid Build Coastguard Worker }
1580*8d67ca89SAndroid Build Coastguard Worker
1581*8d67ca89SAndroid Build Coastguard Worker #endif // defined(__arm__)
1582*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlopen_invalid_rw_load_segment)1583*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlopen_invalid_rw_load_segment) {
1584*8d67ca89SAndroid Build Coastguard Worker const std::string libpath = GetPrebuiltElfDir() + "/libtest_invalid-rw_load_segment.so";
1585*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen(libpath.c_str(), RTLD_NOW);
1586*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle == nullptr);
1587*8d67ca89SAndroid Build Coastguard Worker std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\": W+E load segments are not allowed";
1588*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(expected_dlerror.c_str(), dlerror());
1589*8d67ca89SAndroid Build Coastguard Worker }
1590*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlopen_invalid_unaligned_shdr_offset)1591*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlopen_invalid_unaligned_shdr_offset) {
1592*8d67ca89SAndroid Build Coastguard Worker const std::string libpath = GetPrebuiltElfDir() + "/libtest_invalid-unaligned_shdr_offset.so";
1593*8d67ca89SAndroid Build Coastguard Worker
1594*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen(libpath.c_str(), RTLD_NOW);
1595*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle == nullptr);
1596*8d67ca89SAndroid Build Coastguard Worker std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\" has invalid shdr offset/size: ";
1597*8d67ca89SAndroid Build Coastguard Worker ASSERT_SUBSTR(expected_dlerror.c_str(), dlerror());
1598*8d67ca89SAndroid Build Coastguard Worker }
1599*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlopen_invalid_zero_shentsize)1600*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlopen_invalid_zero_shentsize) {
1601*8d67ca89SAndroid Build Coastguard Worker const std::string libpath = GetPrebuiltElfDir() + "/libtest_invalid-zero_shentsize.so";
1602*8d67ca89SAndroid Build Coastguard Worker
1603*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen(libpath.c_str(), RTLD_NOW);
1604*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle == nullptr);
1605*8d67ca89SAndroid Build Coastguard Worker std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\" has unsupported e_shentsize: 0x0 (expected 0x";
1606*8d67ca89SAndroid Build Coastguard Worker ASSERT_SUBSTR(expected_dlerror.c_str(), dlerror());
1607*8d67ca89SAndroid Build Coastguard Worker }
1608*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlopen_invalid_zero_shstrndx)1609*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlopen_invalid_zero_shstrndx) {
1610*8d67ca89SAndroid Build Coastguard Worker const std::string libpath = GetPrebuiltElfDir() + "/libtest_invalid-zero_shstrndx.so";
1611*8d67ca89SAndroid Build Coastguard Worker
1612*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen(libpath.c_str(), RTLD_NOW);
1613*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle == nullptr);
1614*8d67ca89SAndroid Build Coastguard Worker std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\" has invalid e_shstrndx";
1615*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(expected_dlerror.c_str(), dlerror());
1616*8d67ca89SAndroid Build Coastguard Worker }
1617*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlopen_invalid_empty_shdr_table)1618*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlopen_invalid_empty_shdr_table) {
1619*8d67ca89SAndroid Build Coastguard Worker const std::string libpath = GetPrebuiltElfDir() + "/libtest_invalid-empty_shdr_table.so";
1620*8d67ca89SAndroid Build Coastguard Worker
1621*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen(libpath.c_str(), RTLD_NOW);
1622*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle == nullptr);
1623*8d67ca89SAndroid Build Coastguard Worker std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\" has no section headers";
1624*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(expected_dlerror.c_str(), dlerror());
1625*8d67ca89SAndroid Build Coastguard Worker }
1626*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlopen_invalid_zero_shdr_table_offset)1627*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlopen_invalid_zero_shdr_table_offset) {
1628*8d67ca89SAndroid Build Coastguard Worker const std::string libpath = GetPrebuiltElfDir() + "/libtest_invalid-zero_shdr_table_offset.so";
1629*8d67ca89SAndroid Build Coastguard Worker
1630*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen(libpath.c_str(), RTLD_NOW);
1631*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle == nullptr);
1632*8d67ca89SAndroid Build Coastguard Worker std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\" has invalid shdr offset/size: 0/";
1633*8d67ca89SAndroid Build Coastguard Worker ASSERT_SUBSTR(expected_dlerror.c_str(), dlerror());
1634*8d67ca89SAndroid Build Coastguard Worker }
1635*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlopen_invalid_zero_shdr_table_content)1636*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlopen_invalid_zero_shdr_table_content) {
1637*8d67ca89SAndroid Build Coastguard Worker const std::string libpath = GetPrebuiltElfDir() + "/libtest_invalid-zero_shdr_table_content.so";
1638*8d67ca89SAndroid Build Coastguard Worker
1639*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen(libpath.c_str(), RTLD_NOW);
1640*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle == nullptr);
1641*8d67ca89SAndroid Build Coastguard Worker std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\" .dynamic section header was not found";
1642*8d67ca89SAndroid Build Coastguard Worker ASSERT_SUBSTR(expected_dlerror.c_str(), dlerror());
1643*8d67ca89SAndroid Build Coastguard Worker }
1644*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlopen_invalid_textrels)1645*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlopen_invalid_textrels) {
1646*8d67ca89SAndroid Build Coastguard Worker const std::string libpath = GetPrebuiltElfDir() + "/libtest_invalid-textrels.so";
1647*8d67ca89SAndroid Build Coastguard Worker
1648*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen(libpath.c_str(), RTLD_NOW);
1649*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle == nullptr);
1650*8d67ca89SAndroid Build Coastguard Worker std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\" has text relocations";
1651*8d67ca89SAndroid Build Coastguard Worker ASSERT_SUBSTR(expected_dlerror.c_str(), dlerror());
1652*8d67ca89SAndroid Build Coastguard Worker }
1653*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlopen_invalid_textrels2)1654*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlopen_invalid_textrels2) {
1655*8d67ca89SAndroid Build Coastguard Worker const std::string libpath = GetPrebuiltElfDir() + "/libtest_invalid-textrels2.so";
1656*8d67ca89SAndroid Build Coastguard Worker
1657*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen(libpath.c_str(), RTLD_NOW);
1658*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle == nullptr);
1659*8d67ca89SAndroid Build Coastguard Worker std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\" has text relocations";
1660*8d67ca89SAndroid Build Coastguard Worker ASSERT_SUBSTR(expected_dlerror.c_str(), dlerror());
1661*8d67ca89SAndroid Build Coastguard Worker }
1662*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlopen_invalid_local_tls)1663*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlopen_invalid_local_tls) {
1664*8d67ca89SAndroid Build Coastguard Worker #if defined(__riscv)
1665*8d67ca89SAndroid Build Coastguard Worker // This is a test for bad gold behavior, and gold doesn't support riscv64.
1666*8d67ca89SAndroid Build Coastguard Worker #else
1667*8d67ca89SAndroid Build Coastguard Worker const std::string libpath = GetPrebuiltElfDir() + "/libtest_invalid-local-tls.so";
1668*8d67ca89SAndroid Build Coastguard Worker
1669*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen(libpath.c_str(), RTLD_NOW);
1670*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle == nullptr);
1671*8d67ca89SAndroid Build Coastguard Worker #if defined(__arm__)
1672*8d67ca89SAndroid Build Coastguard Worker const char* referent = "local section";
1673*8d67ca89SAndroid Build Coastguard Worker #else
1674*8d67ca89SAndroid Build Coastguard Worker const char* referent = "local symbol \"tls_var_2\"";
1675*8d67ca89SAndroid Build Coastguard Worker #endif
1676*8d67ca89SAndroid Build Coastguard Worker std::string expected_dlerror = std::string("dlopen failed: unexpected TLS reference to ") +
1677*8d67ca89SAndroid Build Coastguard Worker referent + " in \"" + libpath + "\"";
1678*8d67ca89SAndroid Build Coastguard Worker ASSERT_SUBSTR(expected_dlerror.c_str(), dlerror());
1679*8d67ca89SAndroid Build Coastguard Worker #endif
1680*8d67ca89SAndroid Build Coastguard Worker }
1681*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,dlopen_df_1_global)1682*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, dlopen_df_1_global) {
1683*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libtest_dlopen_df_1_global.so", RTLD_NOW);
1684*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
1685*8d67ca89SAndroid Build Coastguard Worker }
1686*8d67ca89SAndroid Build Coastguard Worker
TEST(dlfcn,segment_gap)1687*8d67ca89SAndroid Build Coastguard Worker TEST(dlfcn, segment_gap) {
1688*8d67ca89SAndroid Build Coastguard Worker void* handle = dlopen("libsegment_gap_outer.so", RTLD_NOW);
1689*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(handle != nullptr) << dlerror();
1690*8d67ca89SAndroid Build Coastguard Worker
1691*8d67ca89SAndroid Build Coastguard Worker auto get_inner = reinterpret_cast<void* (*)()>(dlsym(handle, "get_inner"));
1692*8d67ca89SAndroid Build Coastguard Worker void* inner = get_inner();
1693*8d67ca89SAndroid Build Coastguard Worker (void)inner;
1694*8d67ca89SAndroid Build Coastguard Worker
1695*8d67ca89SAndroid Build Coastguard Worker #if __arm__
1696*8d67ca89SAndroid Build Coastguard Worker int count;
1697*8d67ca89SAndroid Build Coastguard Worker _Unwind_Ptr outer_exidx = dl_unwind_find_exidx(reinterpret_cast<_Unwind_Ptr>(get_inner), &count);
1698*8d67ca89SAndroid Build Coastguard Worker _Unwind_Ptr inner_exidx = dl_unwind_find_exidx(reinterpret_cast<_Unwind_Ptr>(inner), &count);
1699*8d67ca89SAndroid Build Coastguard Worker EXPECT_NE(0u, outer_exidx);
1700*8d67ca89SAndroid Build Coastguard Worker EXPECT_NE(0u, inner_exidx);
1701*8d67ca89SAndroid Build Coastguard Worker EXPECT_NE(inner_exidx, outer_exidx);
1702*8d67ca89SAndroid Build Coastguard Worker #endif
1703*8d67ca89SAndroid Build Coastguard Worker
1704*8d67ca89SAndroid Build Coastguard Worker Dl_info info;
1705*8d67ca89SAndroid Build Coastguard Worker int rc = dladdr(inner, &info);
1706*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(rc, 0);
1707*8d67ca89SAndroid Build Coastguard Worker
1708*8d67ca89SAndroid Build Coastguard Worker EXPECT_NE(nullptr, strstr(info.dli_fname, "libsegment_gap_inner.so"));
1709*8d67ca89SAndroid Build Coastguard Worker }
1710*8d67ca89SAndroid Build Coastguard Worker
1711*8d67ca89SAndroid Build Coastguard Worker #endif
1712