Merge "Turn off XOM on libnstest_root.so"
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 6687d23..412b8eb 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -2925,8 +2925,9 @@
             // Unresolved weak relocation. Leave tpoff at 0 to resolve
             // &weak_tls_symbol to __get_tls().
           } else if (soinfo_tls* lsi_tls = lsi->get_tls()) {
-            if (lsi_tls->module->static_offset != SIZE_MAX) {
-              tpoff += lsi_tls->module->static_offset - tls_tp_base;
+            const TlsModule& mod = get_tls_module(lsi_tls->module_id);
+            if (mod.static_offset != SIZE_MAX) {
+              tpoff += mod.static_offset - tls_tp_base;
             } else {
               DL_ERR("TLS symbol \"%s\" in dlopened \"%s\" referenced from \"%s\" using IE access model",
                      sym_name, lsi->get_realpath(), get_realpath());
diff --git a/linker/linker_logger.cpp b/linker/linker_logger.cpp
index d0e5072..ec07a55 100644
--- a/linker/linker_logger.cpp
+++ b/linker/linker_logger.cpp
@@ -118,11 +118,7 @@
   flags_ |= ParseProperty(debug_ld_app);
 }
 
-void LinkerLogger::Log(uint32_t type, const char* format, ...) {
-  if ((flags_ & type) == 0) {
-    return;
-  }
-
+void LinkerLogger::Log(const char* format, ...) {
   va_list ap;
   va_start(ap, format);
   async_safe_format_log_va_list(ANDROID_LOG_DEBUG, "linker", format, ap);
diff --git a/linker/linker_logger.h b/linker/linker_logger.h
index 1828799..f9fc38e 100644
--- a/linker/linker_logger.h
+++ b/linker/linker_logger.h
@@ -35,10 +35,10 @@
 
 #include <android-base/macros.h>
 
-#define LD_LOG(type, x...) \
-  { \
-    g_linker_logger.Log(type, x); \
-  }
+#define LD_LOG(type, x...)                                       \
+  do {                                                           \
+    if (g_linker_logger.IsEnabled(type)) g_linker_logger.Log(x); \
+  } while (0)
 
 constexpr const uint32_t kLogErrors = 1 << 0;
 constexpr const uint32_t kLogDlopen = 1 << 1;
@@ -49,7 +49,12 @@
   LinkerLogger() : flags_(0) { }
 
   void ResetState();
-  void Log(uint32_t type, const char* format, ...);
+  void Log(const char* format, ...);
+
+  uint32_t IsEnabled(uint32_t type) {
+    return flags_ & type;
+  }
+
  private:
   uint32_t flags_;
 
diff --git a/linker/linker_soinfo.h b/linker/linker_soinfo.h
index 87e385d..14571de 100644
--- a/linker/linker_soinfo.h
+++ b/linker/linker_soinfo.h
@@ -110,7 +110,6 @@
 struct soinfo_tls {
   TlsSegment segment;
   size_t module_id = kUninitializedModuleId;
-  TlsModule* module = nullptr;
 };
 
 #if defined(__work_around_b_24465209__)
diff --git a/linker/linker_tls.cpp b/linker/linker_tls.cpp
index a50d926..0d1796b 100644
--- a/linker/linker_tls.cpp
+++ b/linker/linker_tls.cpp
@@ -41,6 +41,9 @@
 static bool g_static_tls_finished;
 static std::vector<TlsModule> g_tls_modules;
 
+static inline size_t module_id_to_idx(size_t id) { return id - 1; }
+static inline size_t module_idx_to_id(size_t idx) { return idx + 1; }
+
 static size_t get_unused_module_index() {
   for (size_t i = 0; i < g_tls_modules.size(); ++i) {
     if (g_tls_modules[i].soinfo_ptr == nullptr) {
@@ -59,13 +62,11 @@
   ScopedWriteLock locker(&__libc_shared_globals()->tls_modules.rwlock);
 
   size_t module_idx = get_unused_module_index();
-  TlsModule* module = &g_tls_modules[module_idx];
 
   soinfo_tls* si_tls = si->get_tls();
-  si_tls->module_id = module_idx + 1;
-  si_tls->module = module;
+  si_tls->module_id = module_idx_to_id(module_idx);
 
-  *module = {
+  g_tls_modules[module_idx] = {
     .segment = si_tls->segment,
     .static_offset = static_offset,
     .first_generation = ++__libc_shared_globals()->tls_modules.generation,
@@ -77,11 +78,18 @@
   ScopedWriteLock locker(&__libc_shared_globals()->tls_modules.rwlock);
 
   soinfo_tls* si_tls = si->get_tls();
-  CHECK(si_tls->module->static_offset == SIZE_MAX);
-  CHECK(si_tls->module->soinfo_ptr == si);
-  *si_tls->module = {};
+  TlsModule& mod = g_tls_modules[module_id_to_idx(si_tls->module_id)];
+  CHECK(mod.static_offset == SIZE_MAX);
+  CHECK(mod.soinfo_ptr == si);
+  mod = {};
   si_tls->module_id = kUninitializedModuleId;
-  si_tls->module = nullptr;
+}
+
+// The reference is valid until a TLS module is registered or unregistered.
+const TlsModule& get_tls_module(size_t module_id) {
+  size_t module_idx = module_id_to_idx(module_id);
+  CHECK(module_idx < g_tls_modules.size());
+  return g_tls_modules[module_idx];
 }
 
 __BIONIC_WEAK_FOR_NATIVE_BRIDGE
diff --git a/linker/linker_tls.h b/linker/linker_tls.h
index 4f48337..fbb1dcf 100644
--- a/linker/linker_tls.h
+++ b/linker/linker_tls.h
@@ -28,6 +28,9 @@
 
 #pragma once
 
+#include <stdlib.h>
+
+struct TlsModule;
 struct soinfo;
 
 void linker_setup_exe_static_tls(const char* progname);
@@ -35,3 +38,5 @@
 
 void register_soinfo_tls(soinfo* si);
 void unregister_soinfo_tls(soinfo* si);
+
+const TlsModule& get_tls_module(size_t module_id);
diff --git a/tests/sys_time_test.cpp b/tests/sys_time_test.cpp
index d033364..5dda7ab 100644
--- a/tests/sys_time_test.cpp
+++ b/tests/sys_time_test.cpp
@@ -147,7 +147,7 @@
     tv2.tv_usec += 1000000;
   }
 
-  // Should be less than (a very generous, to try to avoid flakiness) 5ms (5000us).
+  // To try to avoid flakiness we'll accept answers within 10,000us (0.01s).
   ASSERT_EQ(0, tv2.tv_sec);
-  ASSERT_LT(tv2.tv_usec, 5000);
+  ASSERT_LT(tv2.tv_usec, 10'000);
 }