Merge changes I221b1342,I1d1276da,I89b128df,Icb348a11,Ifb3b2d8d
* changes:
Add a __bionic_get_tls_segment function
Factor out ScopedRWLock into its own header
Build the linker with -D_USING_LIBCXX
Provide a stub aeabi.read_tp on other archs
Remove TLS_SLOT_TSAN(8)
diff --git a/libc/bionic/bionic_elf_tls.cpp b/libc/bionic/bionic_elf_tls.cpp
index 55c2c31..2d2cbe3 100644
--- a/libc/bionic/bionic_elf_tls.cpp
+++ b/libc/bionic/bionic_elf_tls.cpp
@@ -28,11 +28,43 @@
#include "private/bionic_elf_tls.h"
+#include <async_safe/log.h>
#include <sys/param.h>
+#include <unistd.h>
#include "private/bionic_macros.h"
#include "private/bionic_tls.h"
+// Search for a TLS segment in the given phdr table. Returns true if it has a
+// TLS segment and false otherwise.
+bool __bionic_get_tls_segment(const ElfW(Phdr)* phdr_table, size_t phdr_count,
+ ElfW(Addr) load_bias, const char* mod_name,
+ TlsSegment* out) {
+ for (size_t i = 0; i < phdr_count; ++i) {
+ const ElfW(Phdr)& phdr = phdr_table[i];
+ if (phdr.p_type == PT_TLS) {
+ // N.B. The size does not need to be a multiple of the alignment. With
+ // ld.bfd (or after using binutils' strip), the TLS segment's size isn't
+ // rounded up.
+ size_t alignment = phdr.p_align;
+ if (alignment == 0 || !powerof2(alignment)) {
+ async_safe_fatal("error: \"%s\": TLS segment alignment is not a power of 2: %zu",
+ mod_name, alignment);
+ }
+ // Bionic only respects TLS alignment up to one page.
+ alignment = MIN(alignment, PAGE_SIZE);
+ *out = TlsSegment {
+ phdr.p_memsz,
+ alignment,
+ reinterpret_cast<void*>(load_bias + phdr.p_vaddr),
+ phdr.p_filesz,
+ };
+ return true;
+ }
+ }
+ return false;
+}
+
void StaticTlsLayout::reserve_tcb() {
offset_bionic_tcb_ = reserve_type<bionic_tcb>();
}
diff --git a/libc/bionic/pthread_internal.cpp b/libc/bionic/pthread_internal.cpp
index 870a526..46fa630 100644
--- a/libc/bionic/pthread_internal.cpp
+++ b/libc/bionic/pthread_internal.cpp
@@ -35,30 +35,13 @@
#include <async_safe/log.h>
+#include "private/ScopedRWLock.h"
#include "private/bionic_futex.h"
#include "private/bionic_tls.h"
static pthread_internal_t* g_thread_list = nullptr;
static pthread_rwlock_t g_thread_list_lock = PTHREAD_RWLOCK_INITIALIZER;
-template <bool write> class ScopedRWLock {
- public:
- explicit ScopedRWLock(pthread_rwlock_t* rwlock) : rwlock_(rwlock) {
- (write ? pthread_rwlock_wrlock : pthread_rwlock_rdlock)(rwlock_);
- }
-
- ~ScopedRWLock() {
- pthread_rwlock_unlock(rwlock_);
- }
-
- private:
- pthread_rwlock_t* rwlock_;
- BIONIC_DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedRWLock);
-};
-
-typedef ScopedRWLock<true> ScopedWriteLock;
-typedef ScopedRWLock<false> ScopedReadLock;
-
pthread_t __pthread_internal_add(pthread_internal_t* thread) {
ScopedWriteLock locker(&g_thread_list_lock);
diff --git a/libc/private/ScopedRWLock.h b/libc/private/ScopedRWLock.h
new file mode 100644
index 0000000..f034505
--- /dev/null
+++ b/libc/private/ScopedRWLock.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <pthread.h>
+
+#include "private/bionic_macros.h"
+
+template <bool write> class ScopedRWLock {
+ public:
+ explicit ScopedRWLock(pthread_rwlock_t* rwlock) : rwlock_(rwlock) {
+ (write ? pthread_rwlock_wrlock : pthread_rwlock_rdlock)(rwlock_);
+ }
+
+ ~ScopedRWLock() {
+ pthread_rwlock_unlock(rwlock_);
+ }
+
+ private:
+ pthread_rwlock_t* rwlock_;
+ BIONIC_DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedRWLock);
+};
+
+typedef ScopedRWLock<true> ScopedWriteLock;
+typedef ScopedRWLock<false> ScopedReadLock;
diff --git a/libc/private/bionic_asm_tls.h b/libc/private/bionic_asm_tls.h
index 06e3dce..0f0873f 100644
--- a/libc/private/bionic_asm_tls.h
+++ b/libc/private/bionic_asm_tls.h
@@ -87,11 +87,9 @@
#define TLS_SLOT_STACK_GUARD 5
#define TLS_SLOT_SANITIZER 6 // was historically used for dlerror
#define TLS_SLOT_ART_THREAD_SELF 7
-#define TLS_SLOT_TSAN 8 // should be replaced with TLS_SLOT_SANITIZER
// The maximum slot is fixed by the minimum TLS alignment in Bionic executables.
-// It should be changed to 7 once TLS_SLOT_TSAN is removed.
-#define MAX_TLS_SLOT 8
+#define MAX_TLS_SLOT 7
#elif defined(__i386__) || defined(__x86_64__)
@@ -109,10 +107,9 @@
#define TLS_SLOT_STACK_GUARD 5
#define TLS_SLOT_SANITIZER 6 // was historically used for dlerror
#define TLS_SLOT_ART_THREAD_SELF 7
-#define TLS_SLOT_TSAN 8 // should be replaced with TLS_SLOT_SANITIZER
-#define TLS_SLOT_DTV 9
-#define TLS_SLOT_BIONIC_TLS 10
-#define MAX_TLS_SLOT 10 // update this value when reserving a slot
+#define TLS_SLOT_DTV 8
+#define TLS_SLOT_BIONIC_TLS 9
+#define MAX_TLS_SLOT 9 // update this value when reserving a slot
#endif
diff --git a/libc/private/bionic_elf_tls.h b/libc/private/bionic_elf_tls.h
index e847669..48a4d25 100644
--- a/libc/private/bionic_elf_tls.h
+++ b/libc/private/bionic_elf_tls.h
@@ -28,7 +28,20 @@
#pragma once
+#include <link.h>
#include <stdint.h>
+#include <sys/cdefs.h>
+
+struct TlsSegment {
+ size_t size = 0;
+ size_t alignment = 1;
+ const void* init_ptr = ""; // Field is non-null even when init_size is 0.
+ size_t init_size = 0;
+};
+
+__LIBC_HIDDEN__ bool __bionic_get_tls_segment(const ElfW(Phdr)* phdr_table, size_t phdr_count,
+ ElfW(Addr) load_bias, const char* mod_name,
+ TlsSegment* out);
struct StaticTlsLayout {
constexpr StaticTlsLayout() {}
diff --git a/linker/Android.bp b/linker/Android.bp
index 38a53f8..e103ade 100644
--- a/linker/Android.bp
+++ b/linker/Android.bp
@@ -176,6 +176,11 @@
"-Wextra",
"-Wunused",
"-Werror",
+
+ // Define _USING_LIBCXX so <stdatomic.h> defers to the <atomic> header. When a Soong module
+ // uses the platform libc++, Soong automatically passes this macro, but the dynamic linker
+ // links against libc++ manually.
+ "-D_USING_LIBCXX",
],
// TODO: split out the asflags.
diff --git a/tests/__aeabi_read_tp_test.cpp b/tests/__aeabi_read_tp_test.cpp
index ab96af9..6974658 100644
--- a/tests/__aeabi_read_tp_test.cpp
+++ b/tests/__aeabi_read_tp_test.cpp
@@ -32,7 +32,12 @@
#if defined(__arm__)
extern "C" void* __aeabi_read_tp();
-TEST(aeabi, read_tp) {
- ASSERT_EQ(__aeabi_read_tp(), static_cast<void*>(__get_tls()));
-}
#endif
+
+TEST(aeabi, read_tp) {
+#if defined(__arm__)
+ ASSERT_EQ(__aeabi_read_tp(), static_cast<void*>(__get_tls()));
+#else
+ GTEST_LOG_(INFO) << "__aeabi_read_tp is only available on arm32.\n";
+#endif
+}