Revamp the elftls_dl.dtv_resize test
Split the test out into a separate executable to reduce the number of
ELF modules in the DTV, so that the test can more easily observe the
behavior of loading a module that requires doubling the DTV size. We
want to see the DTV expand from 5 entries (8 words w/header) to
13 entries (16 words w/header).
Make the test work with an initial number of ELF TLS modules between
2 and 4.
Bug: http://b/175635923
Test: bionic-unit-tests
Change-Id: I1e91b4462987a5c80e13838669c359053f5a62f6
diff --git a/tests/elftls_dl_test.cpp b/tests/elftls_dl_test.cpp
index e2fa3a0..bcb2b40 100644
--- a/tests/elftls_dl_test.cpp
+++ b/tests/elftls_dl_test.cpp
@@ -29,10 +29,9 @@
#include <dlfcn.h>
#include <link.h>
-#include <android-base/file.h>
-#include <android-base/test_utils.h>
#include <gtest/gtest.h>
+#include <string>
#include <thread>
#include "gtest_globals.h"
@@ -155,71 +154,11 @@
TEST(elftls_dl, dtv_resize) {
#if defined(__BIONIC__)
-#define LOAD_LIB(soname) ({ \
- auto lib = dlopen(soname, RTLD_LOCAL | RTLD_NOW); \
- ASSERT_NE(nullptr, lib); \
- reinterpret_cast<int(*)()>(dlsym(lib, "bump")); \
- })
-
- auto dtv = []() -> TlsDtv* { return __get_tcb_dtv(__get_bionic_tcb()); };
-
- static_assert(sizeof(TlsDtv) == 3 * sizeof(void*),
- "This test assumes that the Dtv has a 3-word header");
-
- // Initially there are 4 modules (5 w/ hwasan):
- // - the main test executable
- // - libc
- // - libtest_elftls_shared_var
- // - libtest_elftls_tprel
- // - w/ hwasan: libclang_rt.hwasan
-
- // The initial DTV is an empty DTV with no generation and a size of 0.
- TlsDtv* zero_dtv = dtv();
- ASSERT_EQ(0u, zero_dtv->count);
- ASSERT_EQ(nullptr, zero_dtv->next);
- ASSERT_EQ(kTlsGenerationNone, zero_dtv->generation);
-
- // Load module 5 (6 w/ hwasan).
- auto func1 = LOAD_LIB("libtest_elftls_dynamic_filler_1.so");
- ASSERT_EQ(101, func1());
-
- // After loading one module, the DTV should be initialized to the next
- // power-of-2 size (including the header).
- TlsDtv* initial_dtv = dtv();
- ASSERT_EQ(running_with_hwasan() ? 13u : 5u, dtv()->count);
- ASSERT_EQ(zero_dtv, initial_dtv->next);
- ASSERT_LT(0u, initial_dtv->generation);
-
- // Load module 6 (7 w/ hwasan).
- auto func2 = LOAD_LIB("libtest_elftls_dynamic_filler_2.so");
- ASSERT_EQ(102, func1());
-
-#if defined(__aarch64__)
- // The arm64 TLSDESC resolver doesn't update the DTV if it is new enough for
- // the given access.
- ASSERT_EQ(running_with_hwasan() ? 13u : 5u, dtv()->count);
-#else
- // __tls_get_addr updates the DTV anytime the generation counter changes.
- ASSERT_EQ(13u, dtv()->count);
-#endif
-
- ASSERT_EQ(201, func2());
- TlsDtv* new_dtv = dtv();
- if (!running_with_hwasan()) {
- ASSERT_NE(initial_dtv, new_dtv);
- ASSERT_EQ(initial_dtv, new_dtv->next);
- }
- ASSERT_EQ(13u, new_dtv->count);
-
- // Load module 7 (8 w/ hwasan).
- auto func3 = LOAD_LIB("libtest_elftls_dynamic_filler_3.so");
- ASSERT_EQ(103, func1());
- ASSERT_EQ(202, func2());
- ASSERT_EQ(301, func3());
-
- ASSERT_EQ(new_dtv, dtv());
-
-#undef LOAD_LIB
+ std::string helper = GetTestlibRoot() + "/elftls_dtv_resize_helper";
+ chmod(helper.c_str(), 0755); // TODO: "x" lost in CTS, b/34945607
+ ExecTestHelper eth;
+ eth.SetArgs({helper.c_str(), nullptr});
+ eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0, nullptr);
#else
GTEST_SKIP() << "test doesn't apply to glibc";
#endif