Merge "Reapply "[MTE] allocate ring buffer for stack history"" into main
diff --git a/android-changes-for-ndk-developers.md b/android-changes-for-ndk-developers.md
index 8d507d1..e9cfbac 100644
--- a/android-changes-for-ndk-developers.md
+++ b/android-changes-for-ndk-developers.md
@@ -445,6 +445,18 @@
 | No `dlclose`      | Works                      | Works   | Works |
 
 
+## ELF TLS (Available for API level >= 29)
+
+Android supports [ELF TLS](docs/elf-tls.md) starting at API level 29. Since
+NDK r26, clang will automatically enable ELF TLS for `minSdkVersion 29` or
+higher. Otherwise, the existing emutls implementation (which uses
+`pthread_key_create()` behind the scenes) will continue to be used. This
+means that convenient C/C++ thread-local syntax is available at any API level;
+at worst it will perform similarly to "roll your own" thread locals using
+`pthread_key_create()` but at best you'll get the performance benefit of
+ELF TLS, and the NDK will take care of the details.
+
+
 ## Use of IFUNC in libc (True for all API levels on devices running Android 10)
 
 On devices running API level 29, libc uses
diff --git a/benchmarks/bionic_benchmarks.cpp b/benchmarks/bionic_benchmarks.cpp
index 81f1842..b88c6e5 100644
--- a/benchmarks/bionic_benchmarks.cpp
+++ b/benchmarks/bionic_benchmarks.cpp
@@ -372,7 +372,7 @@
 
 void RegisterGoogleBenchmarks(bench_opts_t primary_opts, bench_opts_t secondary_opts,
                               const std::string& fn_name, args_vector_t* run_args) {
-  if (g_str_to_func.find(fn_name) == g_str_to_func.end()) {
+  if (!g_str_to_func.contains(fn_name)) {
     errx(1, "ERROR: No benchmark for function %s", fn_name.c_str());
   }
   long iterations_to_use = primary_opts.num_iterations ? primary_opts.num_iterations :
diff --git a/docs/elf-tls.md b/docs/elf-tls.md
index 6b03841..450f362 100644
--- a/docs/elf-tls.md
+++ b/docs/elf-tls.md
@@ -1,5 +1,11 @@
 # Android ELF TLS
 
+App developers probably just want to read the
+[quick ELS TLS status summary](../android-changes-for-ndk-developers.md#elf-tls-available-for-api-level-29)
+instead.
+
+This document covers the detailed design and implementation choices.
+
 [TOC]
 
 # Overview
@@ -210,7 +216,7 @@
  * https://bugzilla.redhat.com/show_bug.cgi?id=1124987
  * web search: [`"dlopen: cannot load any more object with static TLS"`][glibc-static-tls-error]
 
-Neither musl nor the Bionic TLS prototype currently allocate any surplus TLS memory.
+Neither bionic nor musl currently allocate any surplus TLS memory.
 
 In general, supporting surplus TLS memory probably requires maintaining a thread list so that
 `dlopen` can initialize the new static TLS memory in all existing threads. A thread list could be
@@ -484,19 +490,6 @@
 [quietly ignored]: https://android.googlesource.com/platform/bionic/+/android-8.1.0_r48/linker/linker.cpp#2784
 [added compatibility checks]: https://android-review.googlesource.com/c/platform/bionic/+/648760
 
-# Bionic Prototype Notes
-
-There is an [ELF TLS prototype] uploaded on Gerrit. It implements:
- * Static TLS Block allocation for static and dynamic executables
- * TLS for dynamically loaded and unloaded modules (`__tls_get_addr`)
- * TLSDESC for arm64 only
-
-Missing:
- * `dlsym` of a TLS variable
- * debugger support
-
-[ELF TLS prototype]: https://android-review.googlesource.com/q/topic:%22elf-tls-prototype%22+(status:open%20OR%20status:merged)
-
 ## Loader/libc Communication
 
 The loader exposes a list of TLS modules ([`struct TlsModules`][TlsModules]) to `libc.so` using the
@@ -510,13 +503,14 @@
 
 ## TLS Allocator
 
-The prototype currently allocates a `pthread_internal_t` object and static TLS in a single mmap'ed
+bionic currently allocates a `pthread_internal_t` object and static TLS in a single mmap'ed
 region, along with a thread's stack if it needs one allocated. It doesn't place TLS memory on a
 preallocated stack (either the main thread's stack or one provided with `pthread_attr_setstack`).
 
 The DTV and blocks for dlopen'ed modules are instead allocated using the Bionic loader's
-`LinkerMemoryAllocator`, adapted to avoid the STL and to provide `memalign`. The prototype tries to
-achieve async-signal safety by blocking signals and acquiring a lock.
+`LinkerMemoryAllocator`, adapted to avoid the STL and to provide `memalign`.
+The implementation tries to achieve async-signal safety by blocking signals and
+acquiring a lock.
 
 There are three "entry points" to dynamically locate a TLS variable's address:
  * libc.so: `__tls_get_addr`
@@ -524,10 +518,10 @@
  * loader: dlsym
 
 The loader's entry points need to call `__tls_get_addr`, which needs to allocate memory. Currently,
-the prototype uses a [special function pointer] to call libc.so's `__tls_get_addr` from the loader.
+the implementation uses a [special function pointer] to call libc.so's `__tls_get_addr` from the loader.
 (This should probably be removed.)
 
-The prototype currently allows for arbitrarily-large TLS variable alignment. IIRC, different
+The implementation currently allows for arbitrarily-large TLS variable alignment. IIRC, different
 implementations (glibc, musl, FreeBSD) vary in their level of respect for TLS alignment. It looks
 like the Bionic loader ignores segments' alignment and aligns loaded libraries to 256 KiB. See
 `ReserveAligned`.
@@ -536,7 +530,7 @@
 
 ## Async-Signal Safety
 
-The prototype's `__tls_get_addr` might be async-signal safe. Making it AS-safe is a good idea if
+The implementation's `__tls_get_addr` might be async-signal safe. Making it AS-safe is a good idea if
 it's feasible. musl's function is AS-safe, but glibc's isn't (or wasn't). Google had a patch to make
 glibc AS-safe back in 2012-2013. See:
  * https://sourceware.org/glibc/wiki/TLSandSignals
@@ -545,7 +539,7 @@
 
 ## Out-of-Memory Handling (abort)
 
-The prototype lazily allocates TLS memory for dlopen'ed modules (see `__tls_get_addr`), and an
+The implementation lazily allocates TLS memory for dlopen'ed modules (see `__tls_get_addr`), and an
 out-of-memory error on a TLS access aborts the process. musl, on the other hand, preallocates TLS
 memory on `pthread_create` and `dlopen`, so either function can return out-of-memory. Both functions
 probably need to acquire the same lock.
@@ -567,7 +561,7 @@
 
 FWIW: emutls also aborts on out-of-memory.
 
-## ELF TLS Not Usable in libc
+## ELF TLS Not Usable in libc Itself
 
 The dynamic loader currently can't use ELF TLS, so any part of libc linked into the loader (i.e.
 most of it) also can't use ELF TLS. It might be possible to lift this restriction, perhaps with
@@ -644,7 +638,7 @@
 It seems easy to fix the incompatibility for variant 2 (x86 and x86_64) by splitting out the Bionic
 slots into a new data structure. Variant 1 is a harder problem.
 
-The TLS prototype currently uses a patched LLD that uses a variant 1 TLS layout with a 16-word TCB
+The TLS prototype used a patched LLD that uses a variant 1 TLS layout with a 16-word TCB
 on all architectures.
 
 Aside: gcc's arm64ilp32 target uses a 32-bit unsigned offset for a TLS IE access
@@ -816,8 +810,8 @@
 
 ### Workaround for Go: place pthread keys after the executable's TLS
 
-Most Android executables do not use any `thread_local` variables. In the current prototype, with the
-AOSP hikey960 build, only `/system/bin/netd` has a TLS segment, and it's only 32 bytes. As long as
+Most Android executables do not use any `thread_local` variables. In the prototype, with the
+AOSP hikey960 build, only `/system/bin/netd` had a TLS segment, and it was only 32 bytes. As long as
 `/system/bin/app_process{32,64}` limits its use of TLS memory, then the pthread keys could be
 allocated after `app_process`' TLS segment, and Go will still find them.
 
@@ -842,6 +836,12 @@
  * It looks like glibc's ld.so re-relocates itself after loading a program, so a program's symbols
    can interpose call in the loader: https://sourceware.org/ml/libc-alpha/2014-01/msg00501.html
 
+## TODO: Other
+
+Missing:
+ * `dlsym` of a TLS variable
+ * debugger support
+
 # References
 
 General (and x86/x86-64)
diff --git a/docs/fdsan.md b/docs/fdsan.md
index f5d1ab5..5aeb7de 100644
--- a/docs/fdsan.md
+++ b/docs/fdsan.md
@@ -62,7 +62,9 @@
  - fatal (`ANDROID_FDSAN_ERROR_LEVEL_FATAL`)
    - Abort upon detecting an error.
 
-In Android Q, fdsan has a global default of warn-once. fdsan can be made more or less strict at runtime via the `android_fdsan_set_error_level` function in [`<android/fdsan.h>`](https://android.googlesource.com/platform/bionic/+/main/libc/include/android/fdsan.h).
+In API level 29, fdsan had a global default of warn-once.
+In API level 30 and higher, fdsan has a global default of fatal.
+fdsan can be made more or less strict at runtime via the `android_fdsan_set_error_level` function in [`<android/fdsan.h>`](https://android.googlesource.com/platform/bionic/+/main/libc/include/android/fdsan.h).
 
 The likelihood of fdsan catching a file descriptor error is proportional to the percentage of file descriptors in your process that are tagged with an owner.
 
@@ -344,7 +346,8 @@
 
     // These functions are marked with __attribute__((weak)), so that their
     // availability can be determined at runtime. These wrappers will use them
-    // if available, and fall back to no-ops or regular close on pre-Q devices.
+    // if available, and fall back to no-ops or regular close on devices older
+    // than API level 29.
     static void exchange_tag(int fd, uint64_t old_tag, uint64_t new_tag) {
         if (android_fdsan_exchange_owner_tag) {
             android_fdsan_exchange_owner_tag(fd, old_tag, new_tag);
diff --git a/libc/bionic/NetdClientDispatch.cpp b/libc/bionic/NetdClientDispatch.cpp
index e6f4a97..be5fb11 100644
--- a/libc/bionic/NetdClientDispatch.cpp
+++ b/libc/bionic/NetdClientDispatch.cpp
@@ -20,18 +20,12 @@
 
 #include "private/bionic_fdtrack.h"
 
-#ifdef __i386__
-#define __socketcall __attribute__((__cdecl__))
-#else
-#define __socketcall
-#endif
-
-extern "C" __socketcall int __accept4(int, sockaddr*, socklen_t*, int);
-extern "C" __socketcall int __connect(int, const sockaddr*, socklen_t);
-extern "C" __socketcall int __sendmmsg(int, const mmsghdr*, unsigned int, int);
-extern "C" __socketcall ssize_t __sendmsg(int, const msghdr*, unsigned int);
-extern "C" __socketcall int __sendto(int, const void*, size_t, int, const sockaddr*, socklen_t);
-extern "C" __socketcall int __socket(int, int, int);
+extern "C" int __accept4(int, sockaddr*, socklen_t*, int);
+extern "C" int __connect(int, const sockaddr*, socklen_t);
+extern "C" int __sendmmsg(int, const mmsghdr*, unsigned int, int);
+extern "C" ssize_t __sendmsg(int, const msghdr*, unsigned int);
+extern "C" int __sendto(int, const void*, size_t, int, const sockaddr*, socklen_t);
+extern "C" int __socket(int, int, int);
 
 static unsigned fallBackNetIdForResolv(unsigned netId) {
     return netId;
diff --git a/libc/dns/include/resolv_private.h b/libc/dns/include/resolv_private.h
index 3054555..1593aca 100644
--- a/libc/dns/include/resolv_private.h
+++ b/libc/dns/include/resolv_private.h
@@ -504,15 +504,7 @@
 // ...but NetBSD calls it res_randomid.
 #define res_randomid __res_randomid
 
-#ifdef __i386__
-# define __socketcall extern __attribute__((__cdecl__))
-#else
-# define __socketcall extern
-#endif
-
-__socketcall int __connect(int, const struct sockaddr*, socklen_t);
-
-#undef __socketcall
+int __connect(int, const struct sockaddr*, socklen_t);
 
 // Symbols that are supposed to be in resolv.h, but that we aren't exporting.
 int ns_parserr2(ns_msg*, ns_sect, int, ns_rr2*);
diff --git a/libc/include/sys/socket.h b/libc/include/sys/socket.h
index 9402e70..47ddce0 100644
--- a/libc/include/sys/socket.h
+++ b/libc/include/sys/socket.h
@@ -277,41 +277,33 @@
 
 #define IPX_TYPE 1
 
-#ifdef __i386__
-# define __socketcall extern __attribute__((__cdecl__))
-#else
-# define __socketcall extern
-#endif
-
-__socketcall int accept(int __fd, struct sockaddr* _Nullable __addr, socklen_t* _Nullable __addr_length);
-__socketcall int accept4(int __fd, struct sockaddr* _Nullable __addr, socklen_t* _Nullable __addr_length, int __flags);
-__socketcall int bind(int __fd, const struct sockaddr* _Nonnull __addr, socklen_t __addr_length);
-__socketcall int connect(int __fd, const struct sockaddr* _Nonnull __addr, socklen_t __addr_length);
-__socketcall int getpeername(int __fd, struct sockaddr* _Nonnull __addr, socklen_t* _Nonnull __addr_length);
-__socketcall int getsockname(int __fd, struct sockaddr* _Nonnull __addr, socklen_t* _Nonnull __addr_length);
-__socketcall int getsockopt(int __fd, int __level, int __option, void* _Nullable __value, socklen_t* _Nonnull __value_length);
-__socketcall int listen(int __fd, int __backlog);
-__socketcall int recvmmsg(int __fd, struct mmsghdr* _Nonnull __msgs, unsigned int __msg_count, int __flags, const struct timespec* _Nullable __timeout);
-__socketcall ssize_t recvmsg(int __fd, struct msghdr* _Nonnull __msg, int __flags);
-__socketcall int sendmmsg(int __fd, const struct mmsghdr* _Nonnull __msgs, unsigned int __msg_count, int __flags);
-__socketcall ssize_t sendmsg(int __fd, const struct msghdr* _Nonnull __msg, int __flags);
-__socketcall int setsockopt(int __fd, int __level, int __option, const void* _Nullable __value, socklen_t __value_length);
-__socketcall int shutdown(int __fd, int __how);
-__socketcall int socket(int __af, int __type, int __protocol);
-__socketcall int socketpair(int __af, int __type, int __protocol, int __fds[_Nonnull 2]);
+int accept(int __fd, struct sockaddr* _Nullable __addr, socklen_t* _Nullable __addr_length);
+int accept4(int __fd, struct sockaddr* _Nullable __addr, socklen_t* _Nullable __addr_length, int __flags);
+int bind(int __fd, const struct sockaddr* _Nonnull __addr, socklen_t __addr_length);
+int connect(int __fd, const struct sockaddr* _Nonnull __addr, socklen_t __addr_length);
+int getpeername(int __fd, struct sockaddr* _Nonnull __addr, socklen_t* _Nonnull __addr_length);
+int getsockname(int __fd, struct sockaddr* _Nonnull __addr, socklen_t* _Nonnull __addr_length);
+int getsockopt(int __fd, int __level, int __option, void* _Nullable __value, socklen_t* _Nonnull __value_length);
+int listen(int __fd, int __backlog);
+int recvmmsg(int __fd, struct mmsghdr* _Nonnull __msgs, unsigned int __msg_count, int __flags, const struct timespec* _Nullable __timeout);
+ssize_t recvmsg(int __fd, struct msghdr* _Nonnull __msg, int __flags);
+int sendmmsg(int __fd, const struct mmsghdr* _Nonnull __msgs, unsigned int __msg_count, int __flags);
+ssize_t sendmsg(int __fd, const struct msghdr* _Nonnull __msg, int __flags);
+int setsockopt(int __fd, int __level, int __option, const void* _Nullable __value, socklen_t __value_length);
+int shutdown(int __fd, int __how);
+int socket(int __af, int __type, int __protocol);
+int socketpair(int __af, int __type, int __protocol, int __fds[_Nonnull 2]);
 
 ssize_t recv(int __fd, void* _Nullable __buf, size_t __n, int __flags);
 ssize_t send(int __fd, const void* _Nonnull __buf, size_t __n, int __flags);
 
-__socketcall ssize_t sendto(int __fd, const void* _Nonnull __buf, size_t __n, int __flags, const struct sockaddr* _Nullable __dst_addr, socklen_t __dst_addr_length);
-__socketcall ssize_t recvfrom(int __fd, void* _Nullable __buf, size_t __n, int __flags, struct sockaddr* _Nullable __src_addr, socklen_t* _Nullable __src_addr_length);
+ssize_t sendto(int __fd, const void* _Nonnull __buf, size_t __n, int __flags, const struct sockaddr* _Nullable __dst_addr, socklen_t __dst_addr_length);
+ssize_t recvfrom(int __fd, void* _Nullable __buf, size_t __n, int __flags, struct sockaddr* _Nullable __src_addr, socklen_t* _Nullable __src_addr_length);
 
 #if defined(__BIONIC_INCLUDE_FORTIFY_HEADERS)
 #include <bits/fortify/socket.h>
 #endif
 
-#undef __socketcall
-
 __END_DECLS
 
 #endif
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 8b467a3..e13d37d 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -3595,7 +3595,7 @@
   // 2. Initialize other namespaces
 
   for (auto& ns_config : namespace_configs) {
-    if (namespaces.find(ns_config->name()) != namespaces.end()) {
+    if (namespaces.contains(ns_config->name())) {
       continue;
     }
 
diff --git a/linker/linker_config.cpp b/linker/linker_config.cpp
index ad40c50..70430b8 100644
--- a/linker/linker_config.cpp
+++ b/linker/linker_config.cpp
@@ -304,7 +304,7 @@
     }
 
     if (result == ConfigParser::kPropertyAssign) {
-      if (properties->find(name) != properties->end()) {
+      if (properties->contains(name)) {
         DL_WARN("%s:%zd: warning: redefining property \"%s\" (overriding previous value)",
                 ld_config_file_path,
                 cp.lineno(),
@@ -313,7 +313,7 @@
 
       (*properties)[name] = PropertyValue(std::move(value), cp.lineno());
     } else if (result == ConfigParser::kPropertyAppend) {
-      if (properties->find(name) == properties->end()) {
+      if (!properties->contains(name)) {
         DL_WARN("%s:%zd: warning: appending to undefined property \"%s\" (treating as assignment)",
                 ld_config_file_path,
                 cp.lineno(),
@@ -526,7 +526,7 @@
         properties.get_strings(property_name_prefix + ".links", &lineno);
 
     for (const auto& linked_ns_name : linked_namespaces) {
-      if (namespace_configs.find(linked_ns_name) == namespace_configs.end()) {
+      if (!namespace_configs.contains(linked_ns_name)) {
         *error_msg = create_error_msg(ld_config_file_path,
                                       lineno,
                                       std::string("undefined namespace: ") + linked_ns_name);
diff --git a/linker/linker_namespaces.cpp b/linker/linker_namespaces.cpp
index 5182129..eb9dae9 100644
--- a/linker/linker_namespaces.cpp
+++ b/linker/linker_namespaces.cpp
@@ -100,7 +100,7 @@
     // be searched.
     if (allow_secondary) {
       const android_namespace_list_t& secondary_namespaces = si->get_secondary_namespaces();
-      if (secondary_namespaces.find(this) != secondary_namespaces.end()) {
+      if (secondary_namespaces.contains(this)) {
         return true;
       }
     }
diff --git a/linker/linker_soinfo.cpp b/linker/linker_soinfo.cpp
index 802c06a..d915503 100644
--- a/linker/linker_soinfo.cpp
+++ b/linker/linker_soinfo.cpp
@@ -887,7 +887,7 @@
     handle_ = handle_ | 1;
   } while (handle_ == reinterpret_cast<uintptr_t>(RTLD_DEFAULT) ||
            handle_ == reinterpret_cast<uintptr_t>(RTLD_NEXT) ||
-           g_soinfo_handles_map.find(handle_) != g_soinfo_handles_map.end());
+           g_soinfo_handles_map.contains(handle_));
 
   g_soinfo_handles_map[handle_] = this;
 }
diff --git a/tests/dirent_test.cpp b/tests/dirent_test.cpp
index 4d21246..cde2d11 100644
--- a/tests/dirent_test.cpp
+++ b/tests/dirent_test.cpp
@@ -33,11 +33,11 @@
 
 static void CheckProcSelf(std::set<std::string>& names) {
   // We have a good idea of what should be in /proc/self.
-  ASSERT_TRUE(names.find(".") != names.end());
-  ASSERT_TRUE(names.find("..") != names.end());
-  ASSERT_TRUE(names.find("cmdline") != names.end());
-  ASSERT_TRUE(names.find("fd") != names.end());
-  ASSERT_TRUE(names.find("stat") != names.end());
+  ASSERT_TRUE(names.contains("."));
+  ASSERT_TRUE(names.contains(".."));
+  ASSERT_TRUE(names.contains("cmdline"));
+  ASSERT_TRUE(names.contains("fd"));
+  ASSERT_TRUE(names.contains("stat"));
 }
 
 template <typename DirEntT>
diff --git a/tests/ifaddrs_test.cpp b/tests/ifaddrs_test.cpp
index b3ab94d..da64770 100644
--- a/tests/ifaddrs_test.cpp
+++ b/tests/ifaddrs_test.cpp
@@ -137,7 +137,7 @@
   sockaddr_in* sock = reinterpret_cast<sockaddr_in*>(&ifr.ifr_addr);
   in_addr_t addr = sock->sin_addr.s_addr;
 
-  EXPECT_TRUE(addrs.find(addr) != addrs.end()) << if_name << ' ' << std::hex << ntohl(addr);
+  EXPECT_TRUE(addrs.contains(addr)) << if_name << ' ' << std::hex << ntohl(addr);
 }
 
 TEST(ifaddrs, getifaddrs_INET) {
diff --git a/tests/link_test.cpp b/tests/link_test.cpp
index 127a3d9..ae3a1cd 100644
--- a/tests/link_test.cpp
+++ b/tests/link_test.cpp
@@ -195,7 +195,7 @@
     }
     void AddModule(dl_phdr_info* info, size_t s) {
       ASSERT_EQ(sizeof(dl_phdr_info), s);
-      ASSERT_TRUE(dl_iter_mods.find(info->dlpi_addr) == dl_iter_mods.end());
+      ASSERT_FALSE(dl_iter_mods.contains(info->dlpi_addr));
       ASSERT_TRUE(info->dlpi_name != nullptr);
       dl_iter_mods[info->dlpi_addr] = {
         .name = info->dlpi_name,
diff --git a/tests/stack_protector_test.cpp b/tests/stack_protector_test.cpp
index aea791c..5817a27 100644
--- a/tests/stack_protector_test.cpp
+++ b/tests/stack_protector_test.cpp
@@ -48,7 +48,7 @@
     printf("[thread %d] TLS stack guard = %p\n", tid, guard);
 
     // Duplicate tid. gettid(2) bug? Seeing this would be very upsetting.
-    ASSERT_TRUE(tids.find(tid) == tids.end());
+    ASSERT_FALSE(tids.contains(tid));
 
     // Uninitialized guard. Our bug. Note this is potentially flaky; we _could_
     // get four random zero bytes, but it should be vanishingly unlikely.
diff --git a/tools/versioner/src/versioner.cpp b/tools/versioner/src/versioner.cpp
index 5afa00b..320c19c 100644
--- a/tools/versioner/src/versioner.cpp
+++ b/tools/versioner/src/versioner.cpp
@@ -142,7 +142,7 @@
 
   auto new_end = std::remove_if(headers.begin(), headers.end(), [&arch](llvm::StringRef header) {
     for (const auto& it : ignored_headers) {
-      if (it.second.find(arch) == it.second.end()) {
+      if (!it.second.contains(arch)) {
         continue;
       }