blob: e2fa3a087b6e2f06eb72c76d97ab8b7bf4097b9b [file] [log] [blame]
Ryan Pricharde4ee12f2019-01-15 20:35:00 -08001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <dlfcn.h>
Ryan Pricharda2e83ab2019-08-16 17:25:43 -070030#include <link.h>
Ryan Pricharde4ee12f2019-01-15 20:35:00 -080031
Colin Cross7da20342021-07-28 11:18:11 -070032#include <android-base/file.h>
Florian Mayer2b670142023-03-01 21:40:13 +000033#include <android-base/test_utils.h>
Colin Cross7da20342021-07-28 11:18:11 -070034#include <gtest/gtest.h>
35
Ryan Pricharde4ee12f2019-01-15 20:35:00 -080036#include <thread>
37
38#include "gtest_globals.h"
Christopher Ferrisc5d3a432019-09-25 17:50:36 -070039#include "platform/bionic/tls.h"
Ryan Pricharde4ee12f2019-01-15 20:35:00 -080040#include "utils.h"
41
Ryan Prichard06d2d792019-01-23 23:19:19 -080042#if defined(__BIONIC__)
43#include "bionic/pthread_internal.h"
44#endif
45
Ryan Pricharde4ee12f2019-01-15 20:35:00 -080046// Access libtest_elftls_shared_var.so's TLS variable using an IE access.
47__attribute__((tls_model("initial-exec"))) extern "C" __thread int elftls_shared_var;
48
49TEST(elftls_dl, dlopen_shared_var_ie) {
50 // libtest_elftls_shared_var_ie.so can be dlopen'ed, even though it contains a
51 // TLS IE access, because its IE access references a TLS variable from
52 // libtest_elftls_shared_var.so, which is DT_NEEDED by the executable. This
53 // pattern appears in sanitizers, which use TLS IE instrumentation in shared
54 // objects to access special variables exported from the executable or from a
55 // preloaded solib.
56 void* lib = dlopen("libtest_elftls_shared_var_ie.so", RTLD_LOCAL | RTLD_NOW);
57 ASSERT_NE(nullptr, lib);
58
59 auto bump_shared_var = reinterpret_cast<int(*)()>(dlsym(lib, "bump_shared_var"));
60 ASSERT_NE(nullptr, bump_shared_var);
61
62 ASSERT_EQ(21, ++elftls_shared_var);
63 ASSERT_EQ(22, bump_shared_var());
64
65 std::thread([bump_shared_var] {
66 ASSERT_EQ(21, ++elftls_shared_var);
67 ASSERT_EQ(22, bump_shared_var());
68 }).join();
69}
70
71TEST(elftls_dl, dlopen_ie_error) {
Colin Crossbadcb382021-09-24 17:49:58 -070072 std::string helper = GetTestlibRoot() + "/elftls_dlopen_ie_error_helper";
Ryan Pricharde4ee12f2019-01-15 20:35:00 -080073 std::string src_path = GetTestlibRoot() + "/libtest_elftls_shared_var_ie.so";
74 std::string dst_path = GetTestlibRoot() + "/libtest_elftls_shared_var.so";
75#if defined(__BIONIC__)
76 std::string error =
77 "dlerror: dlopen failed: TLS symbol \"elftls_shared_var\" in dlopened \"" + dst_path + "\" " +
78 "referenced from \"" + src_path + "\" using IE access model\n";
79#else
80 // glibc will reserve some surplus static TLS memory, allowing this test to pass.
81 std::string error = "success\n";
82#endif
83
84 chmod(helper.c_str(), 0755); // TODO: "x" lost in CTS, b/34945607
85 ExecTestHelper eth;
86 eth.SetArgs({ helper.c_str(), nullptr });
87 eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0, error.c_str());
88}
Ryan Prichard06d2d792019-01-23 23:19:19 -080089
90// Use a GD access (__tls_get_addr or TLSDESC) to modify a variable in static
91// TLS memory.
92TEST(elftls_dl, access_static_tls) {
93 void* lib = dlopen("libtest_elftls_dynamic.so", RTLD_LOCAL | RTLD_NOW);
94 ASSERT_NE(nullptr, lib);
95
96 auto bump_shared_var = reinterpret_cast<int(*)()>(dlsym(lib, "bump_shared_var"));
97 ASSERT_NE(nullptr, bump_shared_var);
98
99 ASSERT_EQ(21, ++elftls_shared_var);
100 ASSERT_EQ(22, bump_shared_var());
101
102 std::thread([bump_shared_var] {
103 ASSERT_EQ(21, ++elftls_shared_var);
104 ASSERT_EQ(22, bump_shared_var());
105 }).join();
106}
107
108TEST(elftls_dl, bump_local_vars) {
109 void* lib = dlopen("libtest_elftls_dynamic.so", RTLD_LOCAL | RTLD_NOW);
110 ASSERT_NE(nullptr, lib);
111
112 auto bump_local_vars = reinterpret_cast<int(*)()>(dlsym(lib, "bump_local_vars"));
113 ASSERT_NE(nullptr, bump_local_vars);
114
115 ASSERT_EQ(42, bump_local_vars());
116 std::thread([bump_local_vars] {
117 ASSERT_EQ(42, bump_local_vars());
118 }).join();
119}
120
Ryan Prichard7fda2c92019-02-11 18:25:41 -0800121extern "C" int* missing_weak_tls_addr();
122
123// The Bionic linker resolves a TPREL relocation to an unresolved weak TLS
124// symbol to 0, which is added to the thread pointer. N.B.: A TPREL relocation
125// in a static executable is resolved by the static linker instead, and static
126// linker behavior varies (especially with bfd and gold). See
127// https://bugs.llvm.org/show_bug.cgi?id=40570.
128TEST(elftls_dl, tprel_missing_weak) {
129 ASSERT_EQ(static_cast<void*>(__get_tls()), missing_weak_tls_addr());
130 std::thread([] {
131 ASSERT_EQ(static_cast<void*>(__get_tls()), missing_weak_tls_addr());
132 }).join();
133}
134
Ryan Prichard06d2d792019-01-23 23:19:19 -0800135// The behavior of accessing an unresolved weak TLS symbol using a dynamic TLS
136// relocation depends on which kind of implementation the target uses. With
137// TLSDESC, the result is NULL. With __tls_get_addr, the result is the
138// generation count (or maybe undefined behavior)? This test only tests TLSDESC.
Ryan Prichard7fda2c92019-02-11 18:25:41 -0800139TEST(elftls_dl, tlsdesc_missing_weak) {
Ryan Prichard06d2d792019-01-23 23:19:19 -0800140#if defined(__aarch64__)
141 void* lib = dlopen("libtest_elftls_dynamic.so", RTLD_LOCAL | RTLD_NOW);
142 ASSERT_NE(nullptr, lib);
143
144 auto missing_weak_dyn_tls_addr = reinterpret_cast<int*(*)()>(dlsym(lib, "missing_weak_dyn_tls_addr"));
145 ASSERT_NE(nullptr, missing_weak_dyn_tls_addr);
146
147 ASSERT_EQ(nullptr, missing_weak_dyn_tls_addr());
148 std::thread([missing_weak_dyn_tls_addr] {
149 ASSERT_EQ(nullptr, missing_weak_dyn_tls_addr());
150 }).join();
151#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800152 GTEST_SKIP() << "This test is only run on TLSDESC-based targets";
Ryan Prichard06d2d792019-01-23 23:19:19 -0800153#endif
154}
155
156TEST(elftls_dl, dtv_resize) {
157#if defined(__BIONIC__)
158#define LOAD_LIB(soname) ({ \
159 auto lib = dlopen(soname, RTLD_LOCAL | RTLD_NOW); \
160 ASSERT_NE(nullptr, lib); \
161 reinterpret_cast<int(*)()>(dlsym(lib, "bump")); \
162 })
163
164 auto dtv = []() -> TlsDtv* { return __get_tcb_dtv(__get_bionic_tcb()); };
165
166 static_assert(sizeof(TlsDtv) == 3 * sizeof(void*),
167 "This test assumes that the Dtv has a 3-word header");
168
Florian Mayer2df8ae02023-05-26 12:53:48 -0700169 // Initially there are 4 modules (5 w/ hwasan):
Ryan Prichard06d2d792019-01-23 23:19:19 -0800170 // - the main test executable
Mitch Phillips892d0282020-01-30 14:49:11 -0800171 // - libc
Ryan Prichard06d2d792019-01-23 23:19:19 -0800172 // - libtest_elftls_shared_var
173 // - libtest_elftls_tprel
Florian Mayer2df8ae02023-05-26 12:53:48 -0700174 // - w/ hwasan: libclang_rt.hwasan
Ryan Prichard06d2d792019-01-23 23:19:19 -0800175
176 // The initial DTV is an empty DTV with no generation and a size of 0.
177 TlsDtv* zero_dtv = dtv();
178 ASSERT_EQ(0u, zero_dtv->count);
179 ASSERT_EQ(nullptr, zero_dtv->next);
180 ASSERT_EQ(kTlsGenerationNone, zero_dtv->generation);
181
Florian Mayer2df8ae02023-05-26 12:53:48 -0700182 // Load module 5 (6 w/ hwasan).
Ryan Prichard06d2d792019-01-23 23:19:19 -0800183 auto func1 = LOAD_LIB("libtest_elftls_dynamic_filler_1.so");
184 ASSERT_EQ(101, func1());
185
186 // After loading one module, the DTV should be initialized to the next
187 // power-of-2 size (including the header).
188 TlsDtv* initial_dtv = dtv();
Florian Mayer2df8ae02023-05-26 12:53:48 -0700189 ASSERT_EQ(running_with_hwasan() ? 13u : 5u, dtv()->count);
Ryan Prichard06d2d792019-01-23 23:19:19 -0800190 ASSERT_EQ(zero_dtv, initial_dtv->next);
191 ASSERT_LT(0u, initial_dtv->generation);
192
Florian Mayer2df8ae02023-05-26 12:53:48 -0700193 // Load module 6 (7 w/ hwasan).
Ryan Prichard06d2d792019-01-23 23:19:19 -0800194 auto func2 = LOAD_LIB("libtest_elftls_dynamic_filler_2.so");
195 ASSERT_EQ(102, func1());
Ryan Prichard06d2d792019-01-23 23:19:19 -0800196
197#if defined(__aarch64__)
198 // The arm64 TLSDESC resolver doesn't update the DTV if it is new enough for
199 // the given access.
Florian Mayer2df8ae02023-05-26 12:53:48 -0700200 ASSERT_EQ(running_with_hwasan() ? 13u : 5u, dtv()->count);
Ryan Prichard06d2d792019-01-23 23:19:19 -0800201#else
202 // __tls_get_addr updates the DTV anytime the generation counter changes.
203 ASSERT_EQ(13u, dtv()->count);
204#endif
205
Mitch Phillips892d0282020-01-30 14:49:11 -0800206 ASSERT_EQ(201, func2());
Ryan Prichard06d2d792019-01-23 23:19:19 -0800207 TlsDtv* new_dtv = dtv();
Florian Mayer2df8ae02023-05-26 12:53:48 -0700208 if (!running_with_hwasan()) {
209 ASSERT_NE(initial_dtv, new_dtv);
210 ASSERT_EQ(initial_dtv, new_dtv->next);
211 }
Mitch Phillips892d0282020-01-30 14:49:11 -0800212 ASSERT_EQ(13u, new_dtv->count);
213
Florian Mayer2df8ae02023-05-26 12:53:48 -0700214 // Load module 7 (8 w/ hwasan).
Mitch Phillips892d0282020-01-30 14:49:11 -0800215 auto func3 = LOAD_LIB("libtest_elftls_dynamic_filler_3.so");
216 ASSERT_EQ(103, func1());
217 ASSERT_EQ(202, func2());
218 ASSERT_EQ(301, func3());
219
220 ASSERT_EQ(new_dtv, dtv());
Ryan Prichard06d2d792019-01-23 23:19:19 -0800221
222#undef LOAD_LIB
223#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800224 GTEST_SKIP() << "test doesn't apply to glibc";
Ryan Prichard06d2d792019-01-23 23:19:19 -0800225#endif
226}
227
228// Verify that variables are reset to their initial values after the library
229// containing them is closed.
230TEST(elftls_dl, dlclose_resets_values) {
231 for (int round = 0; round < 2; ++round) {
232 void* lib = dlopen("libtest_elftls_dynamic.so", RTLD_LOCAL | RTLD_NOW);
233 ASSERT_NE(nullptr, lib);
234
235 auto bump_local_vars = reinterpret_cast<int(*)()>(dlsym(lib, "bump_local_vars"));
236 ASSERT_NE(nullptr, bump_local_vars);
237
238 ASSERT_EQ(42, bump_local_vars());
239 ASSERT_EQ(44, bump_local_vars());
240
241 ASSERT_EQ(0, dlclose(lib));
242 }
243}
244
245// Calling dlclose should remove the entry for the solib from the global list of
246// ELF TLS modules. Test that repeatedly loading and unloading a library doesn't
247// increase the DTV size.
248TEST(elftls_dl, dlclose_removes_entry) {
249#if defined(__BIONIC__)
250 auto dtv = []() -> TlsDtv* { return __get_tcb_dtv(__get_bionic_tcb()); };
251
252 bool first = true;
253 size_t count = 0;
254
255 // Use a large number of rounds in case the DTV is initially larger than
256 // expected.
257 for (int round = 0; round < 32; ++round) {
258 void* lib = dlopen("libtest_elftls_dynamic.so", RTLD_LOCAL | RTLD_NOW);
259 ASSERT_NE(nullptr, lib);
260
261 auto bump_local_vars = reinterpret_cast<int(*)()>(dlsym(lib, "bump_local_vars"));
262 ASSERT_NE(nullptr, bump_local_vars);
263
264 ASSERT_EQ(42, bump_local_vars());
265 if (first) {
266 first = false;
267 count = dtv()->count;
268 } else {
269 ASSERT_EQ(count, dtv()->count);
270 }
271
272 dlclose(lib);
273 }
274#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800275 GTEST_SKIP() << "test doesn't apply to glibc";
Ryan Prichard06d2d792019-01-23 23:19:19 -0800276#endif
277}
Ryan Pricharde4d620b2019-04-01 17:42:14 -0700278
279// Use dlsym to get the address of a TLS variable in static TLS and compare it
280// against the ordinary address of the variable.
281TEST(elftls_dl, dlsym_static_tls) {
282 void* lib = dlopen("libtest_elftls_shared_var.so", RTLD_LOCAL | RTLD_NOW);
283 ASSERT_NE(nullptr, lib);
284
285 int* var_addr = static_cast<int*>(dlsym(lib, "elftls_shared_var"));
286 ASSERT_EQ(&elftls_shared_var, var_addr);
287
288 std::thread([lib] {
289 int* var_addr = static_cast<int*>(dlsym(lib, "elftls_shared_var"));
290 ASSERT_EQ(&elftls_shared_var, var_addr);
291 }).join();
292}
293
294// Use dlsym to get the address of a TLS variable in dynamic TLS and compare it
295// against the ordinary address of the variable.
296TEST(elftls_dl, dlsym_dynamic_tls) {
297 void* lib = dlopen("libtest_elftls_dynamic.so", RTLD_LOCAL | RTLD_NOW);
298 ASSERT_NE(nullptr, lib);
299 auto get_var_addr = reinterpret_cast<int*(*)()>(dlsym(lib, "get_large_tls_var_addr"));
300 ASSERT_NE(nullptr, get_var_addr);
301
302 int* var_addr = static_cast<int*>(dlsym(lib, "large_tls_var"));
303 ASSERT_EQ(get_var_addr(), var_addr);
304
305 std::thread([lib, get_var_addr] {
306 int* var_addr = static_cast<int*>(dlsym(lib, "large_tls_var"));
307 ASSERT_EQ(get_var_addr(), var_addr);
308 }).join();
309}
310
311// Calling dladdr on a TLS variable's address doesn't find anything.
312TEST(elftls_dl, dladdr_on_tls_var) {
313 Dl_info info;
314
315 // Static TLS variable
316 ASSERT_EQ(0, dladdr(&elftls_shared_var, &info));
317
318 // Dynamic TLS variable
319 void* lib = dlopen("libtest_elftls_dynamic.so", RTLD_LOCAL | RTLD_NOW);
320 ASSERT_NE(nullptr, lib);
321 int* var_addr = static_cast<int*>(dlsym(lib, "large_tls_var"));
322 ASSERT_EQ(0, dladdr(var_addr, &info));
323}
324
325// Verify that dladdr does not misinterpret a TLS symbol's value as a virtual
326// address.
327TEST(elftls_dl, dladdr_skip_tls_symbol) {
328 void* lib = dlopen("libtest_elftls_dynamic.so", RTLD_LOCAL | RTLD_NOW);
329
330 auto get_local_addr = reinterpret_cast<void*(*)()>(dlsym(lib, "get_local_addr"));
331 ASSERT_NE(nullptr, get_local_addr);
332 void* local_addr = get_local_addr();
333
334 Dl_info info;
335 ASSERT_NE(0, dladdr(local_addr, &info));
336
337 std::string libpath = GetTestlibRoot() + "/libtest_elftls_dynamic.so";
338 char dli_realpath[PATH_MAX];
339 ASSERT_TRUE(realpath(info.dli_fname, dli_realpath));
340 ASSERT_STREQ(libpath.c_str(), dli_realpath);
341 ASSERT_STREQ(nullptr, info.dli_sname);
342 ASSERT_EQ(nullptr, info.dli_saddr);
343}
Ryan Pricharda2e83ab2019-08-16 17:25:43 -0700344
345TEST(elftls_dl, dl_iterate_phdr) {
346 void* lib = dlopen("libtest_elftls_dynamic.so", RTLD_LOCAL | RTLD_NOW);
347
348 auto get_var_addr = reinterpret_cast<void*(*)()>(dlsym(lib, "get_large_tls_var_addr"));
349 ASSERT_NE(nullptr, get_var_addr);
350
351 struct TlsInfo {
352 bool found;
353 size_t modid;
354 void* data;
355 size_t memsz;
356 };
357
358 auto get_tls_info = []() {
359 auto callback = [](dl_phdr_info* info, size_t, void* data) {
360 TlsInfo& tls_info = *static_cast<TlsInfo*>(data);
361
362 // This test is also run with glibc, where dlpi_name may have relative path components, so
363 // examine just the basename when searching for the library.
Colin Cross7da20342021-07-28 11:18:11 -0700364 if (strcmp(android::base::Basename(info->dlpi_name).c_str(), "libtest_elftls_dynamic.so") != 0) return 0;
Ryan Pricharda2e83ab2019-08-16 17:25:43 -0700365
366 tls_info.found = true;
367 tls_info.modid = info->dlpi_tls_modid;
368 tls_info.data = info->dlpi_tls_data;
369 for (ElfW(Half) i = 0; i < info->dlpi_phnum; ++i) {
370 if (info->dlpi_phdr[i].p_type == PT_TLS) {
371 tls_info.memsz = info->dlpi_phdr[i].p_memsz;
372 }
373 }
374 EXPECT_NE(static_cast<size_t>(0), tls_info.memsz);
375 return 1;
376 };
377
378 TlsInfo result {};
379 dl_iterate_phdr(callback, &result);
380 return result;
381 };
382
383 // The executable has a TLS segment, so it will use module ID #1, and the DSO's ID will be larger
384 // than 1. Initially, the data field is nullptr, because this thread's instance hasn't been
385 // allocated yet.
386 TlsInfo tls_info = get_tls_info();
387 ASSERT_TRUE(tls_info.found);
388 ASSERT_GT(tls_info.modid, static_cast<size_t>(1));
389 ASSERT_EQ(nullptr, tls_info.data);
390
391 void* var_addr = get_var_addr();
392
393 // Verify that dl_iterate_phdr returns a range of memory covering the allocated TLS variable.
394 tls_info = get_tls_info();
395 ASSERT_TRUE(tls_info.found);
396 ASSERT_GE(var_addr, tls_info.data);
397 ASSERT_LT(var_addr, static_cast<char*>(tls_info.data) + tls_info.memsz);
398}