Fix bug in finding another thread's TCB.
Change-Id: I06c86ca0c077b464fc6c9fbdf5b89889a26da5fb
diff --git a/tests/libs/tls_properties_helper.cpp b/tests/libs/tls_properties_helper.cpp
index 3f8d118..5982de4 100644
--- a/tests/libs/tls_properties_helper.cpp
+++ b/tests/libs/tls_properties_helper.cpp
@@ -34,8 +34,19 @@
#include <assert.h>
#include <dlfcn.h>
+#include <elf.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sched.h>
#include <stdio.h>
-#include <unistd.h> // for gettid
+#include <string.h>
+#include <sys/prctl.h>
+#include <sys/ptrace.h>
+#include <sys/uio.h>
+#include <sys/user.h>
+#include <sys/wait.h>
+#include <unistd.h>
// Helper binary to use TLS-related functions in thread_properties
@@ -59,20 +70,54 @@
// Tests iterate_dynamic tls chunks.
// Export a var from the shared so.
__thread char large_tls_var[4 * 1024 * 1024];
+// found_count has to be Global variable so that the non-capturing lambda
+// can access it.
+int found_count = 0;
void test_iter_tls() {
void* lib = dlopen("libtest_elftls_dynamic.so", RTLD_LOCAL | RTLD_NOW);
-
- int i = 0;
- auto cb = [&](void* dtls_begin, void* dtls_end, size_t dso_id, void* arg) {
- printf("iterate_cb i = %d\n", i++);
+ large_tls_var[1025] = 'a';
+ auto cb = +[](void* dtls_begin, void* dtls_end, size_t dso_id, void* arg) {
+ if (&large_tls_var >= dtls_begin && &large_tls_var < dtls_end) ++found_count;
};
__libc_iterate_dynamic_tls(gettid(), cb, nullptr);
+
+ // It should be found exactly once.
+ assert(found_count == 1);
printf("done_iterate_dynamic_tls\n");
}
+void* parent_addr = nullptr;
+void test_iterate_another_thread_tls() {
+ large_tls_var[1025] = 'b';
+ parent_addr = &large_tls_var;
+ found_count = 0;
+
+ pid_t pid = fork();
+ assert(pid != -1);
+ int status;
+ if (pid) {
+ // Parent.
+ assert(pid == wait(&status));
+ assert(0 == status);
+ } else {
+ // Child.
+ pid_t parent_pid = getppid();
+ assert(0 == ptrace(PTRACE_ATTACH, parent_pid));
+ assert(parent_pid == waitpid(parent_pid, &status, 0));
+
+ auto cb = +[](void* dtls_begin, void* dtls_end, size_t dso_id, void* arg) {
+ if (parent_addr >= dtls_begin && parent_addr < dtls_end) ++found_count;
+ };
+ __libc_iterate_dynamic_tls(parent_pid, cb, nullptr);
+ // It should be found exactly once.
+ assert(found_count == 1);
+ printf("done_iterate_another_thread_tls\n");
+ }
+}
int main() {
test_static_tls_bounds();
test_iter_tls();
+ test_iterate_another_thread_tls();
return 0;
}