Libsanitizer: merge from trunk with merge.sh.
authorMartin Liska <mliska@suse.cz>
Tue, 5 Nov 2019 13:54:57 +0000 (14:54 +0100)
committerMartin Liska <marxin@gcc.gnu.org>
Tue, 5 Nov 2019 13:54:57 +0000 (13:54 +0000)
2019-11-05  Martin Liska  <mliska@suse.cz>

* all source files: Merge from upstream r375507.

From-SVN: r277834

128 files changed:
libsanitizer/ChangeLog
libsanitizer/MERGE
libsanitizer/asan/asan_allocator.cpp
libsanitizer/asan/asan_debugging.cpp
libsanitizer/asan/asan_descriptions.h
libsanitizer/asan/asan_errors.cpp
libsanitizer/asan/asan_errors.h
libsanitizer/asan/asan_flags.inc
libsanitizer/asan/asan_globals.cpp
libsanitizer/asan/asan_globals_win.cpp
libsanitizer/asan/asan_interceptors.cpp
libsanitizer/asan/asan_interceptors.h
libsanitizer/asan/asan_interceptors_memintrinsics.cpp
libsanitizer/asan/asan_mac.cpp
libsanitizer/asan/asan_malloc_linux.cpp
libsanitizer/asan/asan_malloc_win.cpp
libsanitizer/asan/asan_mapping.h
libsanitizer/asan/asan_new_delete.cpp
libsanitizer/asan/asan_poisoning.cpp
libsanitizer/asan/asan_report.cpp
libsanitizer/asan/asan_rtems.cpp
libsanitizer/asan/asan_rtl.cpp
libsanitizer/asan/asan_scariness_score.h
libsanitizer/asan/asan_shadow_setup.cpp
libsanitizer/asan/asan_stats.cpp
libsanitizer/asan/asan_suppressions.cpp
libsanitizer/asan/asan_thread.cpp
libsanitizer/asan/asan_win.cpp
libsanitizer/asan/asan_win_dll_thunk.cpp
libsanitizer/asan/asan_win_dynamic_runtime_thunk.cpp
libsanitizer/include/sanitizer/dfsan_interface.h
libsanitizer/include/sanitizer/tsan_interface_atomic.h
libsanitizer/include/sanitizer/ubsan_interface.h [new file with mode: 0644]
libsanitizer/interception/interception.h
libsanitizer/interception/interception_win.cpp
libsanitizer/lsan/lsan.cpp
libsanitizer/lsan/lsan_common.cpp
libsanitizer/lsan/lsan_common.h
libsanitizer/lsan/lsan_common_linux.cpp
libsanitizer/lsan/lsan_common_mac.cpp
libsanitizer/lsan/lsan_interceptors.cpp
libsanitizer/lsan/lsan_mac.cpp
libsanitizer/merge.sh
libsanitizer/sanitizer_common/sanitizer_allocator_checks.h
libsanitizer/sanitizer_common/sanitizer_allocator_report.cpp
libsanitizer/sanitizer_common/sanitizer_asm.h
libsanitizer/sanitizer_common/sanitizer_atomic_msvc.h
libsanitizer/sanitizer_common/sanitizer_common.cpp
libsanitizer/sanitizer_common/sanitizer_common.h
libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc
libsanitizer/sanitizer_common/sanitizer_common_interface.inc
libsanitizer/sanitizer_common/sanitizer_coverage_fuchsia.cpp
libsanitizer/sanitizer_common/sanitizer_coverage_libcdep_new.cpp
libsanitizer/sanitizer_common/sanitizer_coverage_win_sections.cpp
libsanitizer/sanitizer_common/sanitizer_file.cpp
libsanitizer/sanitizer_common/sanitizer_flag_parser.cpp
libsanitizer/sanitizer_common/sanitizer_flag_parser.h
libsanitizer/sanitizer_common/sanitizer_flags.cpp
libsanitizer/sanitizer_common/sanitizer_fuchsia.cpp
libsanitizer/sanitizer_common/sanitizer_getauxval.h
libsanitizer/sanitizer_common/sanitizer_glibc_version.h [new file with mode: 0644]
libsanitizer/sanitizer_common/sanitizer_interceptors_ioctl_netbsd.inc
libsanitizer/sanitizer_common/sanitizer_internal_defs.h
libsanitizer/sanitizer_common/sanitizer_libc.cpp
libsanitizer/sanitizer_common/sanitizer_linux.cpp
libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cpp
libsanitizer/sanitizer_common/sanitizer_mac.cpp
libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h
libsanitizer/sanitizer_common/sanitizer_platform_limits_freebsd.h
libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cpp
libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cpp
libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h
libsanitizer/sanitizer_common/sanitizer_platform_limits_solaris.h
libsanitizer/sanitizer_common/sanitizer_posix.cpp
libsanitizer/sanitizer_common/sanitizer_posix.h
libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cpp
libsanitizer/sanitizer_common/sanitizer_printf.cpp
libsanitizer/sanitizer_common/sanitizer_procmaps.h
libsanitizer/sanitizer_common/sanitizer_procmaps_mac.cpp
libsanitizer/sanitizer_common/sanitizer_stacktrace.cpp
libsanitizer/sanitizer_common/sanitizer_stacktrace_libcdep.cpp
libsanitizer/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp
libsanitizer/sanitizer_common/sanitizer_suppressions.h
libsanitizer/sanitizer_common/sanitizer_symbolizer_internal.h
libsanitizer/sanitizer_common/sanitizer_symbolizer_libcdep.cpp
libsanitizer/sanitizer_common/sanitizer_symbolizer_mac.cpp
libsanitizer/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp
libsanitizer/sanitizer_common/sanitizer_symbolizer_report.cpp
libsanitizer/sanitizer_common/sanitizer_termination.cpp
libsanitizer/sanitizer_common/sanitizer_unwind_linux_libcdep.cpp
libsanitizer/sanitizer_common/sanitizer_vector.h
libsanitizer/sanitizer_common/sanitizer_win.cpp
libsanitizer/sanitizer_common/sanitizer_win_defs.h
libsanitizer/sanitizer_common/sanitizer_win_dll_thunk.cpp
libsanitizer/sanitizer_common/sanitizer_win_weak_interception.cpp
libsanitizer/tsan/tsan_dispatch_defs.h
libsanitizer/tsan/tsan_external.cpp
libsanitizer/tsan/tsan_fd.cpp
libsanitizer/tsan/tsan_interceptors.cpp [deleted file]
libsanitizer/tsan/tsan_interceptors_libdispatch.cpp [new file with mode: 0644]
libsanitizer/tsan/tsan_interceptors_mac.cpp
libsanitizer/tsan/tsan_interceptors_mach_vm.cpp [new file with mode: 0644]
libsanitizer/tsan/tsan_interceptors_posix.cpp [new file with mode: 0644]
libsanitizer/tsan/tsan_interface.cpp
libsanitizer/tsan/tsan_interface.h
libsanitizer/tsan/tsan_interface_ann.cpp
libsanitizer/tsan/tsan_interface_atomic.cpp
libsanitizer/tsan/tsan_interface_inl.h
libsanitizer/tsan/tsan_interface_java.cpp
libsanitizer/tsan/tsan_interface_java.h
libsanitizer/tsan/tsan_libdispatch.cpp [deleted file]
libsanitizer/tsan/tsan_md5.cpp
libsanitizer/tsan/tsan_mman.h
libsanitizer/tsan/tsan_new_delete.cpp
libsanitizer/tsan/tsan_platform.h
libsanitizer/tsan/tsan_report.cpp
libsanitizer/tsan/tsan_rtl.cpp
libsanitizer/tsan/tsan_rtl.h
libsanitizer/tsan/tsan_rtl_ppc64.S
libsanitizer/tsan/tsan_rtl_report.cpp
libsanitizer/tsan/tsan_suppressions.cpp
libsanitizer/ubsan/ubsan_checks.inc
libsanitizer/ubsan/ubsan_diag.cpp
libsanitizer/ubsan/ubsan_flags.cpp
libsanitizer/ubsan/ubsan_handlers.cpp
libsanitizer/ubsan/ubsan_handlers.h
libsanitizer/ubsan/ubsan_platform.h
libsanitizer/ubsan/ubsan_signals_standalone.cpp

index 2724f2829b344c34b865068a92c3d37c5fc7415a..3a926394b733c2ea2f315d0d6bf6471a434bbb7a 100644 (file)
@@ -1,3 +1,7 @@
+2019-11-05  Martin Liska  <mliska@suse.cz>
+
+       * all source files: Merge from upstream r375507.
+
 2019-10-22  Tamar Christina  <tamar.christina@arm.com>
 
        PR sanitizer/92154
index bb1b045f488933d15b46320dec3901af53149499..b7bf2529910987419ff3980c0415e1223a8b0abe 100644 (file)
@@ -1,4 +1,4 @@
-368656
+375507
 
 The first line of this file holds the svn revision number of the
 last merge done from the master library sources.
index b58116e17b756a23f803bd4e1d40ca8c1c61ddec..c9e9f5a93d0d123c48bb0e8b62a2218813ca3e69 100644 (file)
@@ -1075,7 +1075,7 @@ IgnoreObjectResult IgnoreObjectLocked(const void *p) {
 }  // namespace __lsan
 
 // ---------------------- Interface ---------------- {{{1
-using namespace __asan;  // NOLINT
+using namespace __asan;
 
 // ASan allocator doesn't reserve extra bytes, so normally we would
 // just return "size". We don't want to expose our redzone sizes, etc here.
index 3fc15adf7b8cbf59a3e9ca57d30fb2cbf65c10aa..c01360b52fc948342dc5d2236b36b5865a34033b 100644 (file)
@@ -25,7 +25,7 @@ using namespace __asan;
 
 static void FindInfoForStackVar(uptr addr, const char *frame_descr, uptr offset,
                                 char *name, uptr name_size,
-                                uptr &region_address, uptr &region_size) {
+                                uptr *region_address, uptr *region_size) {
   InternalMmapVector<StackVarDescr> vars;
   vars.reserve(16);
   if (!ParseFrameDescription(frame_descr, &vars)) {
@@ -39,8 +39,8 @@ static void FindInfoForStackVar(uptr addr, const char *frame_descr, uptr offset,
       // the whole name and then terminate with '\0'.
       internal_strlcpy(name, vars[i].name_pos,
                        Min(name_size, vars[i].name_len + 1));
-      region_address = addr - (offset - vars[i].beg);
-      region_size = vars[i].size;
+      *region_address = addr - (offset - vars[i].beg);
+      *region_size = vars[i].size;
       return;
     }
   }
@@ -108,7 +108,7 @@ const char *__asan_locate_address(uptr addr, char *name, uptr name_size,
       // region_{address,size} are already 0
     } else {
       FindInfoForStackVar(addr, stack->frame_descr, stack->offset, name,
-                          name_size, region_address, region_size);
+                          name_size, &region_address, &region_size);
     }
   } else if (auto global = descr.AsGlobal()) {
     region_kind = "global";
index 28b38100b85db8829e9d480153bebea365ec5600..ee0e2061559e0641a57b5d7f939b3982fcdf5019 100644 (file)
@@ -203,7 +203,7 @@ class AddressDescription {
   AddressDescription() = default;
   // shouldLockThreadRegistry allows us to skip locking if we're sure we already
   // have done it.
-  AddressDescription(uptr addr, bool shouldLockThreadRegistry = true)
+  explicit AddressDescription(uptr addr, bool shouldLockThreadRegistry = true)
       : AddressDescription(addr, 1, shouldLockThreadRegistry) {}
   AddressDescription(uptr addr, uptr access_size,
                      bool shouldLockThreadRegistry = true);
index 75ee996ceef014449b1500d35cff7f8887c8ea64..541c6e0353b57ac08a7147c658eed11f94540335 100644 (file)
@@ -35,7 +35,8 @@ static void OnStackUnwind(const SignalContext &sig,
   // corresponding code in the sanitizer_common and we use this callback to
   // print it.
   static_cast<const ScarinessScoreBase *>(callback_context)->Print();
-  stack->Unwind(sig.pc, sig.bp, sig.context, fast);
+  stack->Unwind(StackTrace::GetNextInstructionPc(sig.pc), sig.bp, sig.context,
+                fast);
 }
 
 void ErrorDeadlySignal::Print() {
@@ -244,7 +245,7 @@ void ErrorInvalidPosixMemalignAlignment::Print() {
       "ERROR: AddressSanitizer: invalid alignment requested in posix_memalign: "
       "%zd, alignment must be a power of two and a multiple of sizeof(void*) "
       "== %zd (thread %s)\n",
-      alignment, sizeof(void*), AsanThreadIdAndName(tid).c_str());  // NOLINT
+      alignment, sizeof(void *), AsanThreadIdAndName(tid).c_str());
   Printf("%s", d.Default());
   stack->Print();
   PrintHintAllocatorCannotReturnNull();
index b84f56c18535de5ad2a3f9eca2560f14a6216fed..a7fda2fd9f5d6bca1dbe4bdae9d35eda7528debd 100644 (file)
@@ -48,7 +48,8 @@ struct ErrorDeadlySignal : ErrorBase {
       scariness.Scare(10, "stack-overflow");
     } else if (!signal.is_memory_access) {
       scariness.Scare(10, "signal");
-    } else if (signal.addr < GetPageSizeCached()) {
+    } else if (signal.is_true_faulting_addr &&
+               signal.addr < GetPageSizeCached()) {
       scariness.Scare(10, "null-deref");
     } else if (signal.addr == signal.pc) {
       scariness.Scare(60, "wild-jump");
index d360e03ca55ead1d4a5b0cda774823a98f193489..43c70dbca56ba5440a69fbc907b8b65b64a3d7f1 100644 (file)
@@ -139,10 +139,10 @@ ASAN_FLAG(
     "If >= 2, detect operations like <, <=, >, >= and - on invalid pointer "
     "pairs (e.g. when pointers belong to different objects); "
     "If == 1, detect invalid operations only when both pointers are non-null.")
-ASAN_FLAG(
-    bool, detect_container_overflow, true,
-    "If true, honor the container overflow annotations. See "
-    "https://github.com/google/sanitizers/wiki/AddressSanitizerContainerOverflow")
+ASAN_FLAG(bool, detect_container_overflow, true,
+          "If true, honor the container overflow annotations. See "
+          "https://github.com/google/sanitizers/wiki/"
+          "AddressSanitizerContainerOverflow")
 ASAN_FLAG(int, detect_odr_violation, 2,
           "If >=2, detect violation of One-Definition-Rule (ODR); "
           "If ==1, detect ODR-violation only if the two variables "
@@ -158,5 +158,6 @@ ASAN_FLAG(bool, allocator_frees_and_returns_null_on_realloc_zero, true,
 ASAN_FLAG(bool, verify_asan_link_order, true,
           "Check position of ASan runtime in library list (needs to be disabled"
           " when other library has to be preloaded system-wide)")
-ASAN_FLAG(bool, windows_hook_rtl_allocators, false,
-          "(Windows only) enable hooking of Rtl(Allocate|Free|Size|ReAllocate)Heap.")
+ASAN_FLAG(
+    bool, windows_hook_rtl_allocators, false,
+    "(Windows only) enable hooking of Rtl(Allocate|Free|Size|ReAllocate)Heap.")
index c77e5357bf90d605cc021a2bea6e6015685cb105..9d7dbc6f264cea7b80a71a91da37cfa0cfbbd0db 100644 (file)
@@ -154,6 +154,23 @@ static void CheckODRViolationViaIndicator(const Global *g) {
   }
 }
 
+// Check ODR violation for given global G by checking if it's already poisoned.
+// We use this method in case compiler doesn't use private aliases for global
+// variables.
+static void CheckODRViolationViaPoisoning(const Global *g) {
+  if (__asan_region_is_poisoned(g->beg, g->size_with_redzone)) {
+    // This check may not be enough: if the first global is much larger
+    // the entire redzone of the second global may be within the first global.
+    for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) {
+      if (g->beg == l->g->beg &&
+          (flags()->detect_odr_violation >= 2 || g->size != l->g->size) &&
+          !IsODRViolationSuppressed(g->name))
+        ReportODRViolation(g, FindRegistrationSite(g),
+                           l->g, FindRegistrationSite(l->g));
+    }
+  }
+}
+
 // Clang provides two different ways for global variables protection:
 // it can poison the global itself or its private alias. In former
 // case we may poison same symbol multiple times, that can help us to
@@ -199,6 +216,8 @@ static void RegisterGlobal(const Global *g) {
     // where two globals with the same name are defined in different modules.
     if (UseODRIndicator(g))
       CheckODRViolationViaIndicator(g);
+    else
+      CheckODRViolationViaPoisoning(g);
   }
   if (CanPoisonMemory())
     PoisonRedZones(*g);
@@ -208,8 +227,7 @@ static void RegisterGlobal(const Global *g) {
   list_of_all_globals = l;
   if (g->has_dynamic_init) {
     if (!dynamic_init_globals) {
-      dynamic_init_globals =
-          new (allocator_for_globals) VectorOfGlobals;  // NOLINT
+      dynamic_init_globals = new (allocator_for_globals) VectorOfGlobals;
       dynamic_init_globals->reserve(kDynamicInitGlobalsInitialCapacity);
     }
     DynInitGlobal dyn_global = { *g, false };
@@ -296,8 +314,7 @@ void PrintGlobalLocation(InternalScopedString *str, const __asan_global &g) {
 } // namespace __asan
 
 // ---------------------- Interface ---------------- {{{1
-using namespace __asan;  // NOLINT
-
+using namespace __asan;
 
 // Apply __asan_register_globals to all globals found in the same loaded
 // executable or shared library as `flag'. The flag tracks whether globals have
@@ -345,7 +362,7 @@ void __asan_register_globals(__asan_global *globals, uptr n) {
   BlockingMutexLock lock(&mu_for_globals);
   if (!global_registration_site_vector) {
     global_registration_site_vector =
-        new (allocator_for_globals) GlobalRegistrationSiteVector;  // NOLINT
+        new (allocator_for_globals) GlobalRegistrationSiteVector;
     global_registration_site_vector->reserve(128);
   }
   GlobalRegistrationSite site = {stack_id, &globals[0], &globals[n - 1]};
index ff5fe226b53b74e52685cebfa83d1266d83443b4..19af88ab12b40ab2dbe6b572a3119b79711cb2e6 100644 (file)
@@ -15,8 +15,8 @@
 
 namespace __asan {
 
-#pragma section(".ASAN$GA", read, write)  // NOLINT
-#pragma section(".ASAN$GZ", read, write)  // NOLINT
+#pragma section(".ASAN$GA", read, write)
+#pragma section(".ASAN$GZ", read, write)
 extern "C" __declspec(allocate(".ASAN$GA"))
     ALIGNED(sizeof(__asan_global)) __asan_global __asan_globals_start = {};
 extern "C" __declspec(allocate(".ASAN$GZ"))
@@ -49,8 +49,8 @@ static void unregister_dso_globals() {
 }
 
 // Register globals
-#pragma section(".CRT$XCU", long, read)  // NOLINT
-#pragma section(".CRT$XTX", long, read)  // NOLINT
+#pragma section(".CRT$XCU", long, read)
+#pragma section(".CRT$XTX", long, read)
 extern "C" __declspec(allocate(".CRT$XCU"))
 void (*const __asan_dso_reg_hook)() = &register_dso_globals;
 extern "C" __declspec(allocate(".CRT$XTX"))
index 482e44d83b732bdd1d0ca749773ba00fa0f22a61..b19cf25c7cd00ddede212ee932b4f8d0065814c9 100644 (file)
@@ -79,7 +79,7 @@ int OnExit() {
 } // namespace __asan
 
 // ---------------------- Wrappers ---------------- {{{1
-using namespace __asan;  // NOLINT
+using namespace __asan;
 
 DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr)
 DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
@@ -164,6 +164,11 @@ DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
     ASAN_MEMSET_IMPL(ctx, block, c, size);                  \
   } while (false)
 
+#if CAN_SANITIZE_LEAKS
+#define COMMON_INTERCEPTOR_STRERROR()                       \
+  __lsan::ScopedInterceptorDisabler disabler
+#endif
+
 #include "sanitizer_common/sanitizer_common_interceptors.inc"
 #include "sanitizer_common/sanitizer_signal_interceptors.inc"
 
@@ -373,26 +378,26 @@ DEFINE_REAL(char*, index, const char *string, int c)
 
 // For both strcat() and strncat() we need to check the validity of |to|
 // argument irrespective of the |from| length.
-INTERCEPTOR(char*, strcat, char *to, const char *from) {  // NOLINT
-  void *ctx;
-  ASAN_INTERCEPTOR_ENTER(ctx, strcat);  // NOLINT
-  ENSURE_ASAN_INITED();
-  if (flags()->replace_str) {
-    uptr from_length = REAL(strlen)(from);
-    ASAN_READ_RANGE(ctx, from, from_length + 1);
-    uptr to_length = REAL(strlen)(to);
-    ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
-    ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
-    // If the copying actually happens, the |from| string should not overlap
-    // with the resulting string starting at |to|, which has a length of
-    // to_length + from_length + 1.
-    if (from_length > 0) {
-      CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1,
-                           from, from_length + 1);
+  INTERCEPTOR(char *, strcat, char *to, const char *from) {
+    void *ctx;
+    ASAN_INTERCEPTOR_ENTER(ctx, strcat);
+    ENSURE_ASAN_INITED();
+    if (flags()->replace_str) {
+      uptr from_length = REAL(strlen)(from);
+      ASAN_READ_RANGE(ctx, from, from_length + 1);
+      uptr to_length = REAL(strlen)(to);
+      ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
+      ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
+      // If the copying actually happens, the |from| string should not overlap
+      // with the resulting string starting at |to|, which has a length of
+      // to_length + from_length + 1.
+      if (from_length > 0) {
+        CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1, from,
+                             from_length + 1);
+      }
     }
+    return REAL(strcat)(to, from);
   }
-  return REAL(strcat)(to, from);  // NOLINT
-}
 
 INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
   void *ctx;
@@ -413,16 +418,17 @@ INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
   return REAL(strncat)(to, from, size);
 }
 
-INTERCEPTOR(char*, strcpy, char *to, const char *from) {  // NOLINT
+INTERCEPTOR(char *, strcpy, char *to, const char *from) {
   void *ctx;
-  ASAN_INTERCEPTOR_ENTER(ctx, strcpy);  // NOLINT
+  ASAN_INTERCEPTOR_ENTER(ctx, strcpy);
 #if SANITIZER_MAC
-  if (UNLIKELY(!asan_inited)) return REAL(strcpy)(to, from);  // NOLINT
+  if (UNLIKELY(!asan_inited))
+    return REAL(strcpy)(to, from);
 #endif
   // strcpy is called from malloc_default_purgeable_zone()
   // in __asan::ReplaceSystemAlloc() on Mac.
   if (asan_init_is_running) {
-    return REAL(strcpy)(to, from);  // NOLINT
+    return REAL(strcpy)(to, from);
   }
   ENSURE_ASAN_INITED();
   if (flags()->replace_str) {
@@ -431,7 +437,7 @@ INTERCEPTOR(char*, strcpy, char *to, const char *from) {  // NOLINT
     ASAN_READ_RANGE(ctx, from, from_size);
     ASAN_WRITE_RANGE(ctx, to, from_size);
   }
-  return REAL(strcpy)(to, from);  // NOLINT
+  return REAL(strcpy)(to, from);
 }
 
 INTERCEPTOR(char*, strdup, const char *s) {
@@ -479,8 +485,7 @@ INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
   return REAL(strncpy)(to, from, size);
 }
 
-INTERCEPTOR(long, strtol, const char *nptr,  // NOLINT
-            char **endptr, int base) {
+INTERCEPTOR(long, strtol, const char *nptr, char **endptr, int base) {
   void *ctx;
   ASAN_INTERCEPTOR_ENTER(ctx, strtol);
   ENSURE_ASAN_INITED();
@@ -488,7 +493,7 @@ INTERCEPTOR(long, strtol, const char *nptr,  // NOLINT
     return REAL(strtol)(nptr, endptr, base);
   }
   char *real_endptr;
-  long result = REAL(strtol)(nptr, &real_endptr, base);  // NOLINT
+  long result = REAL(strtol)(nptr, &real_endptr, base);
   StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
   return result;
 }
@@ -514,7 +519,7 @@ INTERCEPTOR(int, atoi, const char *nptr) {
   return result;
 }
 
-INTERCEPTOR(long, atol, const char *nptr) {  // NOLINT
+INTERCEPTOR(long, atol, const char *nptr) {
   void *ctx;
   ASAN_INTERCEPTOR_ENTER(ctx, atol);
 #if SANITIZER_MAC
@@ -525,15 +530,14 @@ INTERCEPTOR(long, atol, const char *nptr) {  // NOLINT
     return REAL(atol)(nptr);
   }
   char *real_endptr;
-  long result = REAL(strtol)(nptr, &real_endptr, 10);  // NOLINT
+  long result = REAL(strtol)(nptr, &real_endptr, 10);
   FixRealStrtolEndptr(nptr, &real_endptr);
   ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
   return result;
 }
 
 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
-INTERCEPTOR(long long, strtoll, const char *nptr,  // NOLINT
-            char **endptr, int base) {
+INTERCEPTOR(long long, strtoll, const char *nptr, char **endptr, int base) {
   void *ctx;
   ASAN_INTERCEPTOR_ENTER(ctx, strtoll);
   ENSURE_ASAN_INITED();
@@ -541,12 +545,12 @@ INTERCEPTOR(long long, strtoll, const char *nptr,  // NOLINT
     return REAL(strtoll)(nptr, endptr, base);
   }
   char *real_endptr;
-  long long result = REAL(strtoll)(nptr, &real_endptr, base);  // NOLINT
+  long long result = REAL(strtoll)(nptr, &real_endptr, base);
   StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
   return result;
 }
 
-INTERCEPTOR(long long, atoll, const char *nptr) {  // NOLINT
+INTERCEPTOR(long long, atoll, const char *nptr) {
   void *ctx;
   ASAN_INTERCEPTOR_ENTER(ctx, atoll);
   ENSURE_ASAN_INITED();
@@ -554,31 +558,66 @@ INTERCEPTOR(long long, atoll, const char *nptr) {  // NOLINT
     return REAL(atoll)(nptr);
   }
   char *real_endptr;
-  long long result = REAL(strtoll)(nptr, &real_endptr, 10);  // NOLINT
+  long long result = REAL(strtoll)(nptr, &real_endptr, 10);
   FixRealStrtolEndptr(nptr, &real_endptr);
   ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
   return result;
 }
 #endif  // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
 
-#if ASAN_INTERCEPT___CXA_ATEXIT
+#if ASAN_INTERCEPT___CXA_ATEXIT || ASAN_INTERCEPT_ATEXIT
 static void AtCxaAtexit(void *unused) {
   (void)unused;
   StopInitOrderChecking();
 }
+#endif
 
+#if ASAN_INTERCEPT___CXA_ATEXIT
 INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
             void *dso_handle) {
 #if SANITIZER_MAC
   if (UNLIKELY(!asan_inited)) return REAL(__cxa_atexit)(func, arg, dso_handle);
 #endif
   ENSURE_ASAN_INITED();
+#if CAN_SANITIZE_LEAKS
+  __lsan::ScopedInterceptorDisabler disabler;
+#endif
   int res = REAL(__cxa_atexit)(func, arg, dso_handle);
   REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr);
   return res;
 }
 #endif  // ASAN_INTERCEPT___CXA_ATEXIT
 
+#if ASAN_INTERCEPT_ATEXIT
+INTERCEPTOR(int, atexit, void (*func)()) {
+  ENSURE_ASAN_INITED();
+#if CAN_SANITIZE_LEAKS
+  __lsan::ScopedInterceptorDisabler disabler;
+#endif
+  // Avoid calling real atexit as it is unrechable on at least on Linux.
+  int res = REAL(__cxa_atexit)((void (*)(void *a))func, nullptr, nullptr);
+  REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr);
+  return res;
+}
+#endif
+
+#if ASAN_INTERCEPT_PTHREAD_ATFORK
+extern "C" {
+extern int _pthread_atfork(void (*prepare)(), void (*parent)(),
+                           void (*child)());
+};
+
+INTERCEPTOR(int, pthread_atfork, void (*prepare)(), void (*parent)(),
+            void (*child)()) {
+#if CAN_SANITIZE_LEAKS
+  __lsan::ScopedInterceptorDisabler disabler;
+#endif
+  // REAL(pthread_atfork) cannot be called due to symbol indirections at least
+  // on NetBSD
+  return _pthread_atfork(prepare, parent, child);
+}
+#endif
+
 #if ASAN_INTERCEPT_VFORK
 DEFINE_REAL(int, vfork)
 DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(int, vfork)
@@ -594,8 +633,8 @@ void InitializeAsanInterceptors() {
   InitializeSignalInterceptors();
 
   // Intercept str* functions.
-  ASAN_INTERCEPT_FUNC(strcat);  // NOLINT
-  ASAN_INTERCEPT_FUNC(strcpy);  // NOLINT
+  ASAN_INTERCEPT_FUNC(strcat);
+  ASAN_INTERCEPT_FUNC(strcpy);
   ASAN_INTERCEPT_FUNC(strncat);
   ASAN_INTERCEPT_FUNC(strncpy);
   ASAN_INTERCEPT_FUNC(strdup);
@@ -661,6 +700,14 @@ void InitializeAsanInterceptors() {
   ASAN_INTERCEPT_FUNC(__cxa_atexit);
 #endif
 
+#if ASAN_INTERCEPT_ATEXIT
+  ASAN_INTERCEPT_FUNC(atexit);
+#endif
+
+#if ASAN_INTERCEPT_PTHREAD_ATFORK
+  ASAN_INTERCEPT_FUNC(pthread_atfork);
+#endif
+
 #if ASAN_INTERCEPT_VFORK
   ASAN_INTERCEPT_FUNC(vfork);
 #endif
index 035a84e1a421fbe36aeffc240ddb3936e809d15f..344a64bd83d330553bca41f066b004092b6632df 100644 (file)
@@ -80,12 +80,7 @@ void InitializePlatformInterceptors();
 #if ASAN_HAS_EXCEPTIONS && !SANITIZER_WINDOWS && !SANITIZER_SOLARIS && \
     !SANITIZER_NETBSD
 # define ASAN_INTERCEPT___CXA_THROW 1
-# if ! defined(ASAN_HAS_CXA_RETHROW_PRIMARY_EXCEPTION) \
-     || ASAN_HAS_CXA_RETHROW_PRIMARY_EXCEPTION
-#   define ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 1
-# else
-#   define ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 0
-# endif
+# define ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 1
 # if defined(_GLIBCXX_SJLJ_EXCEPTIONS) || (SANITIZER_IOS && defined(__arm__))
 #  define ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION 1
 # else
@@ -104,6 +99,12 @@ void InitializePlatformInterceptors();
 # define ASAN_INTERCEPT___CXA_ATEXIT 0
 #endif
 
+#if SANITIZER_NETBSD
+# define ASAN_INTERCEPT_ATEXIT 1
+#else
+# define ASAN_INTERCEPT_ATEXIT 0
+#endif
+
 #if SANITIZER_LINUX && !SANITIZER_ANDROID
 # define ASAN_INTERCEPT___STRDUP 1
 #else
@@ -117,6 +118,12 @@ void InitializePlatformInterceptors();
 # define ASAN_INTERCEPT_VFORK 0
 #endif
 
+#if SANITIZER_NETBSD
+# define ASAN_INTERCEPT_PTHREAD_ATFORK 1
+#else
+# define ASAN_INTERCEPT_PTHREAD_ATFORK 0
+#endif
+
 DECLARE_REAL(int, memcmp, const void *a1, const void *a2, uptr size)
 DECLARE_REAL(char*, strchr, const char *str, int c)
 DECLARE_REAL(SIZE_T, strlen, const char *s)
index 56df60ba6818b7e675434e71007780968c0c05e5..ccdd5159042cf895688d7e23951990504eba6c6c 100644 (file)
@@ -16,7 +16,7 @@
 #include "asan_stack.h"
 #include "asan_suppressions.h"
 
-using namespace __asan;  // NOLINT
+using namespace __asan;
 
 void *__asan_memcpy(void *to, const void *from, uptr size) {
   ASAN_MEMCPY_IMPL(nullptr, to, from, size);
index 769d499672d69e7700e1c6afcc65f702414114e2..a8d3f5d3473c4018add5a431a63435afc4a37294 100644 (file)
@@ -205,7 +205,7 @@ void asan_dispatch_call_block_and_release(void *block) {
 
 }  // namespace __asan
 
-using namespace __asan;  // NOLINT
+using namespace __asan;
 
 // Wrap |ctxt| and |func| into an asan_block_context_t.
 // The caller retains control of the allocated context.
index 706bc39f0c47be44a4cc13c8aabe31ea16689d0c..faa8968a5d009208edd051cf6b7ac7940bffa967 100644 (file)
@@ -27,7 +27,7 @@
 #include "asan_stack.h"
 
 // ---------------------- Replacement functions ---------------- {{{1
-using namespace __asan;  // NOLINT
+using namespace __asan;
 
 static uptr allocated_for_dlsym;
 static uptr last_dlsym_alloc_size_in_words;
index 291d411ea7910c19d2fd99862cdeb83e27d97943..13c6f652119bb9ed5e7121e6cd4adb56c63123ff 100644 (file)
@@ -54,7 +54,7 @@ size_t WINAPI HeapSize(HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem);
 BOOL WINAPI HeapValidate(HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem);
 }
 
-using namespace __asan;  // NOLINT
+using namespace __asan;
 
 // MT: Simply defining functions with the same signature in *.obj
 // files overrides the standard functions in the CRT.
@@ -528,10 +528,11 @@ void ReplaceSystemMalloc() {
                                      (uptr)WRAP(RtlAllocateHeap),
                                      (uptr *)&REAL(RtlAllocateHeap));
   } else {
-#define INTERCEPT_UCRT_FUNCTION(func)                                         \
-  if (!INTERCEPT_FUNCTION_DLLIMPORT("ucrtbase.dll",                           \
-                                    "api-ms-win-core-heap-l1-1-0.dll", func)) \
-    VPrintf(2, "Failed to intercept ucrtbase.dll import %s\n", #func);
+#define INTERCEPT_UCRT_FUNCTION(func)                                  \
+  if (!INTERCEPT_FUNCTION_DLLIMPORT(                                   \
+          "ucrtbase.dll", "api-ms-win-core-heap-l1-1-0.dll", func)) {  \
+    VPrintf(2, "Failed to intercept ucrtbase.dll import %s\n", #func); \
+  }
     INTERCEPT_UCRT_FUNCTION(HeapAlloc);
     INTERCEPT_UCRT_FUNCTION(HeapFree);
     INTERCEPT_UCRT_FUNCTION(HeapReAlloc);
index 09be904270cedbb1bed9736dd3a616463180c83b..41fb49ee46d460774a487c638b2c58531b8ac8d0 100644 (file)
@@ -163,7 +163,7 @@ static const u64 kDefaultShort64bitShadowOffset =
 static const u64 kAArch64_ShadowOffset64 = 1ULL << 36;
 static const u64 kMIPS32_ShadowOffset32 = 0x0aaa0000;
 static const u64 kMIPS64_ShadowOffset64 = 1ULL << 37;
-static const u64 kPPC64_ShadowOffset64 = 1ULL << 41;
+static const u64 kPPC64_ShadowOffset64 = 1ULL << 44;
 static const u64 kSystemZ_ShadowOffset64 = 1ULL << 52;
 static const u64 kSPARC64_ShadowOffset64 = 1ULL << 43;  // 0x80000000000
 static const u64 kFreeBSD_ShadowOffset32 = 1ULL << 30;  // 0x40000000
index c15e208094ef84d9882f3420ee6b7e534a1a8372..5dfcc00fd5d1450285902d072571535ca6013929 100644 (file)
@@ -48,7 +48,7 @@ COMMENT_EXPORT("??_V@YAXPAX@Z")                   // operator delete[]
 #define CXX_OPERATOR_ATTRIBUTE INTERCEPTOR_ATTRIBUTE
 #endif
 
-using namespace __asan;  // NOLINT
+using namespace __asan;
 
 // FreeBSD prior v9.2 have wrong definition of 'size_t'.
 // http://svnweb.freebsd.org/base?view=revision&revision=232261
index 6b36be7d1cd8c611ff05c6279338b6925cb583c8..f3fbe684e2cbc75930502fb5b4424df8034b2660 100644 (file)
@@ -92,7 +92,7 @@ void AsanPoisonOrUnpoisonIntraObjectRedzone(uptr ptr, uptr size, bool poison) {
 }  // namespace __asan
 
 // ---------------------- Interface ---------------- {{{1
-using namespace __asan;  // NOLINT
+using namespace __asan;
 
 // Current implementation of __asan_(un)poison_memory_region doesn't check
 // that user program (un)poisons the memory it owns. It poisons memory
index d36b0b4c5948fa5a9b4decd93cc5bc6b75db92e5..2e6ce436d03061f7c3054d9c0f2474c7f309dfc4 100644 (file)
@@ -410,8 +410,12 @@ static bool IsInvalidPointerPair(uptr a1, uptr a2) {
 
 static INLINE void CheckForInvalidPointerPair(void *p1, void *p2) {
   switch (flags()->detect_invalid_pointer_pairs) {
-    case 0 : return;
-    case 1 : if (p1 == nullptr || p2 == nullptr) return; break;
+    case 0:
+      return;
+    case 1:
+      if (p1 == nullptr || p2 == nullptr)
+        return;
+      break;
   }
 
   uptr a1 = reinterpret_cast<uptr>(p1);
@@ -472,7 +476,7 @@ void ReportGenericError(uptr pc, uptr bp, uptr sp, uptr addr, bool is_write,
 }  // namespace __asan
 
 // --------------------------- Interface --------------------- {{{1
-using namespace __asan;  // NOLINT
+using namespace __asan;
 
 void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write,
                          uptr access_size, u32 exp) {
index 360d5780a3f2e8f621ea1e710620c13f09004d7e..ecd568c5981bbc0ece6403a287b8689d9602a012 100644 (file)
@@ -181,11 +181,11 @@ static void ThreadStartHook(void *hook, uptr os_id) {
       asanThreadRegistry().GetThreadLocked(thread->tid())->status;
   DCHECK(status == ThreadStatusCreated || status == ThreadStatusRunning);
   // Determine whether we are starting or restarting the thread.
-  if (status == ThreadStatusCreated)
+  if (status == ThreadStatusCreated) {
     // In lieu of AsanThread::ThreadStart.
     asanThreadRegistry().StartThread(thread->tid(), os_id, ThreadType::Regular,
                                      nullptr);
-  else {
+  else {
     // In a thread restart, a thread may resume execution at an
     // arbitrary function entry point, with its stack and TLS state
     // reset.  We unpoison the stack in that case.
index b16ca950518ced99acccdb52d40efb4958f87401..594d7752eea627d8f0bf8b7988871623687c363f 100644 (file)
@@ -402,7 +402,6 @@ static void AsanInitInternal() {
   asan_init_is_running = true;
 
   CacheBinaryName();
-  CheckASLR();
 
   // Initialize flags. This must be done early, because most of the
   // initialization steps look at flags().
@@ -450,6 +449,7 @@ static void AsanInitInternal() {
   SetLowLevelAllocateCallback(OnLowLevelAllocate);
 
   InitializeAsanInterceptors();
+  CheckASLR();
 
   // Enable system log ("adb logcat") on Android.
   // Doing this before interceptors are initialized crashes in:
@@ -542,7 +542,7 @@ void AsanInitFromRtl() {
 // (and thus normal initializers from .preinit_array or modules haven't run).
 
 class AsanInitializer {
-public:  // NOLINT
+ public:
   AsanInitializer() {
     AsanInitFromRtl();
   }
@@ -554,7 +554,7 @@ static AsanInitializer asan_initializer;
 } // namespace __asan
 
 // ---------------------- Interface ---------------- {{{1
-using namespace __asan;  // NOLINT
+using namespace __asan;
 
 void NOINLINE __asan_handle_no_return() {
   if (asan_init_is_running)
index 9e7ba47d82dc3dd6354460304803e8c8e6a2a826..3932973c225e2be9ecfc2c7eae285e0f93e68a11 100644 (file)
@@ -43,7 +43,7 @@ struct ScarinessScoreBase {
       internal_strlcat(descr, "-", sizeof(descr));
     internal_strlcat(descr, reason, sizeof(descr));
     score += add_to_score;
-  };
+  }
   int GetScore() const { return score; }
   const char *GetDescription() const { return descr; }
   void Print() const {
index fc9bf51e1b585b94c2f62ebecf06ea38346896ab..17324932a86f92e7be95acf821c31011fbe1bb16 100644 (file)
@@ -30,14 +30,13 @@ void ReserveShadowMemoryRange(uptr beg, uptr end, const char *name) {
   CHECK_EQ(((end + 1) % GetMmapGranularity()), 0);
   uptr size = end - beg + 1;
   DecreaseTotalMmap(size);  // Don't count the shadow against mmap_limit_mb.
-  if (!MmapFixedNoReserve(beg, size, name)) {
+  if (!MmapFixedSuperNoReserve(beg, size, name)) {
     Report(
         "ReserveShadowMemoryRange failed while trying to map 0x%zx bytes. "
         "Perhaps you're using ulimit -v\n",
         size);
     Abort();
   }
-  SetShadowRegionHugePageMode(beg, size);
   if (common_flags()->use_madv_dontdump) DontDumpShadowMemory(beg, size);
 }
 
index bc4e8c15cc156af9d6a32f16c4752b3fde6c2808..00ded8f5ef50700c5814ba7d4c3b646dac7086b5 100644 (file)
@@ -133,7 +133,7 @@ static void PrintAccumulatedStats() {
 }  // namespace __asan
 
 // ---------------------- Interface ---------------- {{{1
-using namespace __asan;  // NOLINT
+using namespace __asan;
 
 uptr __sanitizer_get_current_allocated_bytes() {
   AsanStats stats;
index a9c0d1076940f9e7885b8e5bf624b53012254820..8cb2c3e3b9b6a49132d24e7a8669591bee111b40 100644 (file)
@@ -36,7 +36,7 @@ SANITIZER_INTERFACE_WEAK_DEF(const char *, __asan_default_suppressions, void) {
 
 void InitializeSuppressions() {
   CHECK_EQ(nullptr, suppression_ctx);
-  suppression_ctx = new (suppression_placeholder)  // NOLINT
+  suppression_ctx = new (suppression_placeholder)
       SuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes));
   suppression_ctx->ParseFromFile(flags()->suppressions);
   if (&__asan_default_suppressions)
index d48b3414dd57994f40d791c69b90fc506f43162f..6734d9a1668c7ccbd7f6f75ccea394bc755d95e9 100644 (file)
@@ -367,8 +367,9 @@ uptr AsanThread::GetStackVariableShadowStart(uptr addr) {
   } else if (has_fake_stack()) {
     bottom = fake_stack()->AddrIsInFakeStack(addr);
     CHECK(bottom);
-  } else
+  } else {
     return 0;
+  }
 
   uptr aligned_addr = RoundDownTo(addr, SANITIZER_WORDSIZE / 8);  // align addr.
   u8 *shadow_ptr = (u8*)MemToShadow(aligned_addr);
@@ -505,7 +506,7 @@ void EnsureMainThreadIDIsCorrect() {
 } // namespace __lsan
 
 // ---------------------- Interface ---------------- {{{1
-using namespace __asan;  // NOLINT
+using namespace __asan;
 
 extern "C" {
 SANITIZER_INTERFACE_ATTRIBUTE
index f8b98ca336693d89f7ad0cba0283cc44559a9dd1..417892aaedd8edc1fb754c892bb9d44fa6ddbfa4 100644 (file)
@@ -29,7 +29,7 @@
 #include "sanitizer_common/sanitizer_win.h"
 #include "sanitizer_common/sanitizer_win_defs.h"
 
-using namespace __asan;  // NOLINT
+using namespace __asan;
 
 extern "C" {
 SANITIZER_INTERFACE_ATTRIBUTE
@@ -106,7 +106,7 @@ INTERCEPTOR_WINAPI(void, RaiseException, void *a, void *b, void *c, void *d) {
 
 INTERCEPTOR_WINAPI(EXCEPTION_DISPOSITION, __C_specific_handler,
                    _EXCEPTION_RECORD *a, void *b, _CONTEXT *c,
-                   _DISPATCHER_CONTEXT *d) {  // NOLINT
+                   _DISPATCHER_CONTEXT *d) {
   CHECK(REAL(__C_specific_handler));
   __asan_handle_no_return();
   return REAL(__C_specific_handler)(a, b, c, d);
@@ -362,7 +362,7 @@ bool HandleDlopenInit() {
 // beginning of C++ initialization. We set our priority to XCAB to run
 // immediately after the CRT runs. This way, our exception filter is called
 // first and we can delegate to their filter if appropriate.
-#pragma section(".CRT$XCAB", long, read)  // NOLINT
+#pragma section(".CRT$XCAB", long, read)
 __declspec(allocate(".CRT$XCAB")) int (*__intercept_seh)() =
     __asan_set_seh_filter;
 
@@ -375,7 +375,7 @@ static void NTAPI asan_thread_init(void *module, DWORD reason, void *reserved) {
     __asan_init();
 }
 
-#pragma section(".CRT$XLAB", long, read)  // NOLINT
+#pragma section(".CRT$XLAB", long, read)
 __declspec(allocate(".CRT$XLAB")) void(NTAPI *__asan_tls_init)(
     void *, unsigned long, void *) = asan_thread_init;
 #endif
@@ -389,7 +389,7 @@ static void NTAPI asan_thread_exit(void *module, DWORD reason, void *reserved) {
   }
 }
 
-#pragma section(".CRT$XLY", long, read)  // NOLINT
+#pragma section(".CRT$XLY", long, read)
 __declspec(allocate(".CRT$XLY")) void(NTAPI *__asan_tls_exit)(
     void *, unsigned long, void *) = asan_thread_exit;
 
index 95eee5eed0d3dd8363701dc8f838e57e922bc60c..a5671cc9dffd5dc1b2a2998c3f320979a98a63d5 100644 (file)
@@ -67,10 +67,10 @@ INTERCEPT_LIBRARY_FUNCTION(memcmp);
 INTERCEPT_LIBRARY_FUNCTION(memcpy);
 INTERCEPT_LIBRARY_FUNCTION(memmove);
 INTERCEPT_LIBRARY_FUNCTION(memset);
-INTERCEPT_LIBRARY_FUNCTION(strcat);  // NOLINT
+INTERCEPT_LIBRARY_FUNCTION(strcat);
 INTERCEPT_LIBRARY_FUNCTION(strchr);
 INTERCEPT_LIBRARY_FUNCTION(strcmp);
-INTERCEPT_LIBRARY_FUNCTION(strcpy);  // NOLINT
+INTERCEPT_LIBRARY_FUNCTION(strcpy);
 INTERCEPT_LIBRARY_FUNCTION(strcspn);
 INTERCEPT_LIBRARY_FUNCTION(strdup);
 INTERCEPT_LIBRARY_FUNCTION(strlen);
@@ -135,7 +135,7 @@ static int asan_dll_thunk_init() {
   return 0;
 }
 
-#pragma section(".CRT$XIB", long, read)  // NOLINT
+#pragma section(".CRT$XIB", long, read)
 __declspec(allocate(".CRT$XIB")) int (*__asan_preinit)() = asan_dll_thunk_init;
 
 static void WINAPI asan_thread_init(void *mod, unsigned long reason,
@@ -143,7 +143,7 @@ static void WINAPI asan_thread_init(void *mod, unsigned long reason,
   if (reason == /*DLL_PROCESS_ATTACH=*/1) asan_dll_thunk_init();
 }
 
-#pragma section(".CRT$XLAB", long, read)  // NOLINT
+#pragma section(".CRT$XLAB", long, read)
 __declspec(allocate(".CRT$XLAB")) void (WINAPI *__asan_tls_init)(void *,
     unsigned long, void *) = asan_thread_init;
 
index 5bd457a22b65ac1da08c5c22f81b212532ac7224..f0b5ec9eef7f99db7b139cabc78e7ba24c72eeed 100644 (file)
 #include "asan_interface.inc"
 
 // First, declare CRT sections we'll be using in this file
-#pragma section(".CRT$XIB", long, read)  // NOLINT
-#pragma section(".CRT$XID", long, read)  // NOLINT
-#pragma section(".CRT$XCAB", long, read)  // NOLINT
-#pragma section(".CRT$XTW", long, read)  // NOLINT
-#pragma section(".CRT$XTY", long, read)  // NOLINT
-#pragma section(".CRT$XLAB", long, read)  // NOLINT
+#pragma section(".CRT$XIB", long, read)
+#pragma section(".CRT$XID", long, read)
+#pragma section(".CRT$XCAB", long, read)
+#pragma section(".CRT$XTW", long, read)
+#pragma section(".CRT$XTY", long, read)
+#pragma section(".CRT$XLAB", long, read)
 
 ////////////////////////////////////////////////////////////////////////////////
 // Define a copy of __asan_option_detect_stack_use_after_return that should be
index c189ee55790afb09274c98f2ff02be716001940e..81546e5df71aff3e896e2651a6779d33935a7d28 100644 (file)
@@ -112,7 +112,7 @@ void dfsan_weak_hook_strncmp(void *caller_pc, const char *s1, const char *s2,
 }  // extern "C"
 
 template <typename T>
-void dfsan_set_label(dfsan_label label, T &data) {  // NOLINT
+void dfsan_set_label(dfsan_label label, T &data) { // NOLINT
   dfsan_set_label(label, (void *)&data, sizeof(T));
 }
 
index 9ce0411917df698358fd1936a71556c51123d8f8..8052bc1d56b38c5861f252f2f999ca4a0f0ee747 100644 (file)
 extern "C" {
 #endif
 
-typedef char     __tsan_atomic8;
-typedef short    __tsan_atomic16;  // NOLINT
-typedef int      __tsan_atomic32;
-typedef long     __tsan_atomic64;  // NOLINT
+typedef char __tsan_atomic8;
+typedef short __tsan_atomic16;
+typedef int __tsan_atomic32;
+typedef long __tsan_atomic64;
 #if defined(__SIZEOF_INT128__) \
     || (__clang_major__ * 100 + __clang_minor__ >= 302)
 __extension__ typedef __int128 __tsan_atomic128;
diff --git a/libsanitizer/include/sanitizer/ubsan_interface.h b/libsanitizer/include/sanitizer/ubsan_interface.h
new file mode 100644 (file)
index 0000000..59fc6c3
--- /dev/null
@@ -0,0 +1,32 @@
+//===-- sanitizer/ubsan_interface.h -----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of UBSanitizer (UBSan).
+//
+// Public interface header.
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_UBSAN_INTERFACE_H
+#define SANITIZER_UBSAN_INTERFACE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/// User-provided default option settings.
+///
+/// You can provide your own implementation of this function to return a string
+/// containing UBSan runtime options (for example,
+/// <c>verbosity=1:halt_on_error=0</c>).
+///
+/// \returns Default options string.
+const char* __ubsan_default_options(void);
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // SANITIZER_UBSAN_INTERFACE_H
index dacfa5ede28df3f81d64e28f646699cdc351084c..d27a8ccf92a8e9381da0087d3481f208a4e6a1a4 100644 (file)
@@ -272,9 +272,9 @@ const interpose_substitution substitution_##func_name[] \
 // INTERCEPT_FUNCTION macro, only its name.
 namespace __interception {
 #if defined(_WIN64)
-typedef unsigned long long uptr;  // NOLINT
+typedef unsigned long long uptr;
 #else
-typedef unsigned long uptr;  // NOLINT
+typedef unsigned long uptr;
 #endif  // _WIN64
 }  // namespace __interception
 
index b94e214fdff80d3dcae7b1a124931fb621ce0f1c..1a1c327e61240867869f0b749f99d6813f62f279 100644 (file)
@@ -883,8 +883,8 @@ uptr InternalGetProcAddress(void *module, const char *func_name) {
   // Check that the module header is full and present.
   RVAPtr<IMAGE_DOS_HEADER> dos_stub(module, 0);
   RVAPtr<IMAGE_NT_HEADERS> headers(module, dos_stub->e_lfanew);
-  if (!module || dos_stub->e_magic != IMAGE_DOS_SIGNATURE || // "MZ"
-      headers->Signature != IMAGE_NT_SIGNATURE ||           // "PE\0\0"
+  if (!module || dos_stub->e_magic != IMAGE_DOS_SIGNATURE ||  // "MZ"
+      headers->Signature != IMAGE_NT_SIGNATURE ||             // "PE\0\0"
       headers->FileHeader.SizeOfOptionalHeader <
           sizeof(IMAGE_OPTIONAL_HEADER)) {
     return 0;
@@ -963,8 +963,8 @@ bool OverrideImportedFunction(const char *module_to_patch,
   // Check that the module header is full and present.
   RVAPtr<IMAGE_DOS_HEADER> dos_stub(module, 0);
   RVAPtr<IMAGE_NT_HEADERS> headers(module, dos_stub->e_lfanew);
-  if (!module || dos_stub->e_magic != IMAGE_DOS_SIGNATURE || // "MZ"
-      headers->Signature != IMAGE_NT_SIGNATURE ||            // "PE\0\0"
+  if (!module || dos_stub->e_magic != IMAGE_DOS_SIGNATURE ||  // "MZ"
+      headers->Signature != IMAGE_NT_SIGNATURE ||             // "PE\0\0"
       headers->FileHeader.SizeOfOptionalHeader <
           sizeof(IMAGE_OPTIONAL_HEADER)) {
     return false;
index 5b5f6198a693694bdea630f69029e4463a71644c..4ce03046ffb7fbe550da6f3d274ae80fa54d135b 100644 (file)
@@ -50,7 +50,7 @@ void __sanitizer::BufferedStackTrace::UnwindImpl(
   }
 }
 
-using namespace __lsan;  // NOLINT
+using namespace __lsan;
 
 static void InitializeFlags() {
   // Set all the default values.
@@ -89,7 +89,7 @@ static void InitializeFlags() {
 
 static void OnStackUnwind(const SignalContext &sig, const void *,
                           BufferedStackTrace *stack) {
-  stack->Unwind(sig.pc, sig.bp, sig.context,
+  stack->Unwind(StackTrace::GetNextInstructionPc(sig.pc), sig.bp, sig.context,
                 common_flags()->fast_unwind_on_fatal);
 }
 
index c39fab97c6425ecc4ca8f8f500cde75a7c7a05da..9ff9f4c5d1c977d32b7ce668e7a810691bae3215 100644 (file)
@@ -84,7 +84,7 @@ static const char kStdSuppressions[] =
 
 void InitializeSuppressions() {
   CHECK_EQ(nullptr, suppression_ctx);
-  suppression_ctx = new (suppression_placeholder) // NOLINT
+  suppression_ctx = new (suppression_placeholder)
       SuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes));
   suppression_ctx->ParseFromFile(flags()->suppressions);
   if (&__lsan_default_suppressions)
@@ -104,7 +104,7 @@ InternalMmapVector<RootRegion> const *GetRootRegions() { return root_regions; }
 void InitializeRootRegions() {
   CHECK(!root_regions);
   ALIGNED(64) static char placeholder[sizeof(InternalMmapVector<RootRegion>)];
-  root_regions = new (placeholder) InternalMmapVector<RootRegion>();  // NOLINT
+  root_regions = new (placeholder) InternalMmapVector<RootRegion>();
 }
 
 const char *MaybeCallLsanDefaultOptions() {
@@ -162,7 +162,7 @@ void ScanRangeForPointers(uptr begin, uptr end,
   uptr pp = begin;
   if (pp % alignment)
     pp = pp + alignment - pp % alignment;
-  for (; pp + sizeof(void *) <= end; pp += alignment) {  // NOLINT
+  for (; pp + sizeof(void *) <= end; pp += alignment) {
     void *p = *reinterpret_cast<void **>(pp);
     if (!CanBeAHeapPointer(reinterpret_cast<uptr>(p))) continue;
     uptr chunk = PointsIntoChunk(p);
@@ -535,7 +535,7 @@ static void ReportIfNotSuspended(ThreadContextBase *tctx, void *arg) {
     if (i >= suspended_threads.size() || suspended_threads[i] != tctx->os_id)
       Report("Running thread %d was not suspended. False leaks are possible.\n",
              tctx->os_id);
-  };
+  }
 }
 
 static void ReportUnsuspendedThreads(
@@ -570,11 +570,7 @@ static bool CheckForLeaks() {
   EnsureMainThreadIDIsCorrect();
   CheckForLeaksParam param;
   param.success = false;
-  LockThreadRegistry();
-  LockAllocator();
-  DoStopTheWorld(CheckForLeaksCallback, &param);
-  UnlockAllocator();
-  UnlockThreadRegistry();
+  LockStuffAndStopTheWorld(CheckForLeaksCallback, &param);
 
   if (!param.success) {
     Report("LeakSanitizer has encountered a fatal error.\n");
@@ -794,7 +790,7 @@ void EnableInThisThread() { }
 }
 #endif // CAN_SANITIZE_LEAKS
 
-using namespace __lsan;  // NOLINT
+using namespace __lsan;
 
 extern "C" {
 SANITIZER_INTERFACE_ATTRIBUTE
index 58dc00faaee5cdd8796785cef34e7be6e746c4ae..d24abe31b71b524e3f545410e772ce6744170ba8 100644 (file)
@@ -129,8 +129,9 @@ struct RootRegion {
 InternalMmapVector<RootRegion> const *GetRootRegions();
 void ScanRootRegion(Frontier *frontier, RootRegion const &region,
                     uptr region_begin, uptr region_end, bool is_readable);
-// Run stoptheworld while holding any platform-specific locks.
-void DoStopTheWorld(StopTheWorldCallback callback, void* argument);
+// Run stoptheworld while holding any platform-specific locks, as well as the
+// allocator and thread registry locks.
+void LockStuffAndStopTheWorld(StopTheWorldCallback callback, void* argument);
 
 void ScanRangeForPointers(uptr begin, uptr end,
                           Frontier *frontier,
index 9ce27a983b502c503dd001c61a5d02e4886a97dc..ea1a4a2f569d0648a06b3b25d6e73a865dbab14d 100644 (file)
@@ -115,10 +115,14 @@ void HandleLeaks() {
   if (common_flags()->exitcode) Die();
 }
 
-static int DoStopTheWorldCallback(struct dl_phdr_info *info, size_t size,
-                                  void *data) {
+static int LockStuffAndStopTheWorldCallback(struct dl_phdr_info *info,
+                                            size_t size, void *data) {
+  LockThreadRegistry();
+  LockAllocator();
   DoStopTheWorldParam *param = reinterpret_cast<DoStopTheWorldParam *>(data);
   StopTheWorld(param->callback, param->argument);
+  UnlockAllocator();
+  UnlockThreadRegistry();
   return 1;
 }
 
@@ -130,9 +134,9 @@ static int DoStopTheWorldCallback(struct dl_phdr_info *info, size_t size,
 // while holding the libdl lock in the parent thread, we can safely reenter it
 // in the tracer. The solution is to run stoptheworld from a dl_iterate_phdr()
 // callback in the parent thread.
-void DoStopTheWorld(StopTheWorldCallback callback, void *argument) {
+void LockStuffAndStopTheWorld(StopTheWorldCallback callback, void *argument) {
   DoStopTheWorldParam param = {callback, argument};
-  dl_iterate_phdr(DoStopTheWorldCallback, &param);
+  dl_iterate_phdr(LockStuffAndStopTheWorldCallback, &param);
 }
 
 } // namespace __lsan
index 5204a6624edcc2d5c3638558b2978784f8ef8d28..c1804e93c11db7ce667102bbe925300815d9891b 100644 (file)
@@ -193,8 +193,12 @@ void ProcessPlatformSpecificAllocations(Frontier *frontier) {
 // causes rare race conditions.
 void HandleLeaks() {}
 
-void DoStopTheWorld(StopTheWorldCallback callback, void *argument) {
+void LockStuffAndStopTheWorld(StopTheWorldCallback callback, void *argument) {
+  LockThreadRegistry();
+  LockAllocator();
   StopTheWorld(callback, argument);
+  UnlockAllocator();
+  UnlockThreadRegistry();
 }
 
 } // namespace __lsan
index f06d5fff7063597bb3226a672bd3622cf7b48166..f642bb807bc88ff6f14bb13cfbd7640ebbd4c050 100644 (file)
@@ -345,6 +345,55 @@ INTERCEPTOR(void, thr_exit, tid_t *state) {
 #define LSAN_MAYBE_INTERCEPT_THR_EXIT
 #endif
 
+#if SANITIZER_INTERCEPT___CXA_ATEXIT
+INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
+            void *dso_handle) {
+  __lsan::ScopedInterceptorDisabler disabler;
+  return REAL(__cxa_atexit)(func, arg, dso_handle);
+}
+#define LSAN_MAYBE_INTERCEPT___CXA_ATEXIT INTERCEPT_FUNCTION(__cxa_atexit)
+#else
+#define LSAN_MAYBE_INTERCEPT___CXA_ATEXIT
+#endif
+
+#if SANITIZER_INTERCEPT_ATEXIT
+INTERCEPTOR(int, atexit, void (*f)()) {
+  __lsan::ScopedInterceptorDisabler disabler;
+  return REAL(__cxa_atexit)((void (*)(void *a))f, 0, 0);
+}
+#define LSAN_MAYBE_INTERCEPT_ATEXIT INTERCEPT_FUNCTION(atexit)
+#else
+#define LSAN_MAYBE_INTERCEPT_ATEXIT
+#endif
+
+#if SANITIZER_INTERCEPT_PTHREAD_ATFORK
+extern "C" {
+extern int _pthread_atfork(void (*prepare)(), void (*parent)(),
+                           void (*child)());
+};
+
+INTERCEPTOR(int, pthread_atfork, void (*prepare)(), void (*parent)(),
+            void (*child)()) {
+  __lsan::ScopedInterceptorDisabler disabler;
+  // REAL(pthread_atfork) cannot be called due to symbol indirections at least
+  // on NetBSD
+  return _pthread_atfork(prepare, parent, child);
+}
+#define LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK INTERCEPT_FUNCTION(pthread_atfork)
+#else
+#define LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK
+#endif
+
+#if SANITIZER_INTERCEPT_STRERROR
+INTERCEPTOR(char *, strerror, int errnum) {
+  __lsan::ScopedInterceptorDisabler disabler;
+  return REAL(strerror)(errnum);
+}
+#define LSAN_MAYBE_INTERCEPT_STRERROR INTERCEPT_FUNCTION(strerror)
+#else
+#define LSAN_MAYBE_INTERCEPT_STRERROR
+#endif
+
 struct ThreadParam {
   void *(*callback)(void *arg);
   void *param;
@@ -454,6 +503,12 @@ void InitializeInterceptors() {
   LSAN_MAYBE_INTERCEPT__LWP_EXIT;
   LSAN_MAYBE_INTERCEPT_THR_EXIT;
 
+  LSAN_MAYBE_INTERCEPT___CXA_ATEXIT;
+  LSAN_MAYBE_INTERCEPT_ATEXIT;
+  LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK;
+
+  LSAN_MAYBE_INTERCEPT_STRERROR;
+
 #if !SANITIZER_NETBSD && !SANITIZER_FREEBSD
   if (pthread_key_create(&g_thread_finalize_key, &thread_finalize)) {
     Report("LeakSanitizer: failed to create thread key.\n");
index 7bcd9c828ef4d815716e26bd5186a9a333cf3d6e..b96893e2801b3b226c32ab308c1bfd12313ed130 100644 (file)
@@ -90,7 +90,7 @@ extern "C" void lsan_dispatch_call_block_and_release(void *block) {
 
 }  // namespace __lsan
 
-using namespace __lsan;  // NOLINT
+using namespace __lsan;
 
 // Wrap |ctxt| and |func| into an lsan_block_context_t.
 // The caller retains control of the allocated context.
index 168fbbc9729d9873c4ca858f41db01e4f22cfedb..2f74fbef260fdfaf146121477f3f38c371597a3f 100755 (executable)
@@ -74,7 +74,6 @@ merge lib/tsan/rtl tsan
 merge lib/sanitizer_common sanitizer_common
 merge lib/interception interception
 merge lib/ubsan ubsan
-merge lib/BlocksRuntime/ BlocksRuntime
 
 # Need to merge lib/builtins/assembly.h file:
 mkdir -p builtins
index f436ce9ecdea402fff83958bc66a107de2185b5b..fc426f0e74f48297139c83d032d5583a5437bd50 100644 (file)
@@ -54,7 +54,7 @@ INLINE bool CheckAlignedAllocAlignmentAndSize(uptr alignment, uptr size) {
 // and a multiple of sizeof(void *).
 INLINE bool CheckPosixMemalignAlignment(uptr alignment) {
   return alignment != 0 && IsPowerOfTwo(alignment) &&
-         (alignment % sizeof(void *)) == 0; // NOLINT
+         (alignment % sizeof(void *)) == 0;
 }
 
 // Returns true if calloc(size, n) call overflows on size*n calculation.
index dbcf2b7bf260da261f6e994694f045c2583bc13d..d74e08010d5de2d562e8aff4902fc0ca72e4e24a 100644 (file)
@@ -106,10 +106,11 @@ void NORETURN ReportInvalidPosixMemalignAlignment(uptr alignment,
   {
     ScopedAllocatorErrorReport report("invalid-posix-memalign-alignment",
                                       stack);
-    Report("ERROR: %s: invalid alignment requested in "
-           "posix_memalign: %zd, alignment must be a power of two and a "
-           "multiple of sizeof(void*) == %zd\n", SanitizerToolName, alignment,
-           sizeof(void*));  // NOLINT
+    Report(
+        "ERROR: %s: invalid alignment requested in "
+        "posix_memalign: %zd, alignment must be a power of two and a "
+        "multiple of sizeof(void*) == %zd\n",
+        SanitizerToolName, alignment, sizeof(void *));
   }
   Die();
 }
index 184d118d97d81a1786bf34e6e8deaf109dd49538..803af3285e189b581be1dd28766d3ffb0f21b7df 100644 (file)
@@ -60,7 +60,9 @@
 
 #if defined(__ELF__) && (defined(__GNU__) || defined(__FreeBSD__) || \
                          defined(__Fuchsia__) || defined(__linux__))
-#define NO_EXEC_STACK_DIRECTIVE .section .note.GNU-stack,"",%progbits // NOLINT
+// clang-format off
+#define NO_EXEC_STACK_DIRECTIVE .section .note.GNU-stack,"",%progbits  // NOLINT
+// clang-format on
 #else
 #define NO_EXEC_STACK_DIRECTIVE
 #endif
index a249657d66170ae7c962b996d7caff838f6b007c..6a7c5465dcbbc17b0d5daeb084caecb82662e4bb 100644 (file)
@@ -20,44 +20,35 @@ extern "C" void _mm_mfence();
 #pragma intrinsic(_mm_mfence)
 extern "C" void _mm_pause();
 #pragma intrinsic(_mm_pause)
-extern "C" char _InterlockedExchange8(   // NOLINT
-    char volatile *Addend, char Value);  // NOLINT
+extern "C" char _InterlockedExchange8(char volatile *Addend, char Value);
 #pragma intrinsic(_InterlockedExchange8)
-extern "C" short _InterlockedExchange16(   // NOLINT
-    short volatile *Addend, short Value);  // NOLINT
+extern "C" short _InterlockedExchange16(short volatile *Addend, short Value);
 #pragma intrinsic(_InterlockedExchange16)
-extern "C" long _InterlockedExchange(    // NOLINT
-    long volatile *Addend, long Value);  // NOLINT
+extern "C" long _InterlockedExchange(long volatile *Addend, long Value);
 #pragma intrinsic(_InterlockedExchange)
-extern "C" long _InterlockedExchangeAdd(  // NOLINT
-    long volatile * Addend, long Value);  // NOLINT
+extern "C" long _InterlockedExchangeAdd(long volatile *Addend, long Value);
 #pragma intrinsic(_InterlockedExchangeAdd)
-extern "C" char _InterlockedCompareExchange8(  // NOLINT
-    char volatile *Destination,                // NOLINT
-    char Exchange, char Comparand);            // NOLINT
+extern "C" char _InterlockedCompareExchange8(char volatile *Destination,
+                                             char Exchange, char Comparand);
 #pragma intrinsic(_InterlockedCompareExchange8)
-extern "C" short _InterlockedCompareExchange16(  // NOLINT
-    short volatile *Destination,                 // NOLINT
-    short Exchange, short Comparand);            // NOLINT
+extern "C" short _InterlockedCompareExchange16(short volatile *Destination,
+                                               short Exchange, short Comparand);
 #pragma intrinsic(_InterlockedCompareExchange16)
-extern "C"
-long long _InterlockedCompareExchange64(  // NOLINT
-    long long volatile *Destination,              // NOLINT
-    long long Exchange, long long Comparand);     // NOLINT
+extern "C" long long _InterlockedCompareExchange64(
+    long long volatile *Destination, long long Exchange, long long Comparand);
 #pragma intrinsic(_InterlockedCompareExchange64)
 extern "C" void *_InterlockedCompareExchangePointer(
     void *volatile *Destination,
     void *Exchange, void *Comparand);
 #pragma intrinsic(_InterlockedCompareExchangePointer)
-extern "C"
-long __cdecl _InterlockedCompareExchange(  // NOLINT
-    long volatile *Destination,            // NOLINT
-    long Exchange, long Comparand);        // NOLINT
+extern "C" long __cdecl _InterlockedCompareExchange(long volatile *Destination,
+                                                    long Exchange,
+                                                    long Comparand);
 #pragma intrinsic(_InterlockedCompareExchange)
 
 #ifdef _WIN64
-extern "C" long long _InterlockedExchangeAdd64(     // NOLINT
-    long long volatile * Addend, long long Value);  // NOLINT
+extern "C" long long _InterlockedExchangeAdd64(long long volatile *Addend,
+                                               long long Value);
 #pragma intrinsic(_InterlockedExchangeAdd64)
 #endif
 
@@ -115,8 +106,8 @@ INLINE u32 atomic_fetch_add(volatile atomic_uint32_t *a,
     u32 v, memory_order mo) {
   (void)mo;
   DCHECK(!((uptr)a % sizeof(*a)));
-  return (u32)_InterlockedExchangeAdd(
-      (volatile long*)&a->val_dont_use, (long)v);  // NOLINT
+  return (u32)_InterlockedExchangeAdd((volatile long *)&a->val_dont_use,
+                                      (long)v);
 }
 
 INLINE uptr atomic_fetch_add(volatile atomic_uintptr_t *a,
@@ -124,11 +115,11 @@ INLINE uptr atomic_fetch_add(volatile atomic_uintptr_t *a,
   (void)mo;
   DCHECK(!((uptr)a % sizeof(*a)));
 #ifdef _WIN64
-  return (uptr)_InterlockedExchangeAdd64(
-      (volatile long long*)&a->val_dont_use, (long long)v);  // NOLINT
+  return (uptr)_InterlockedExchangeAdd64((volatile long long *)&a->val_dont_use,
+                                         (long long)v);
 #else
-  return (uptr)_InterlockedExchangeAdd(
-      (volatile long*)&a->val_dont_use, (long)v);  // NOLINT
+  return (uptr)_InterlockedExchangeAdd((volatile long *)&a->val_dont_use,
+                                       (long)v);
 #endif
 }
 
@@ -136,8 +127,8 @@ INLINE u32 atomic_fetch_sub(volatile atomic_uint32_t *a,
     u32 v, memory_order mo) {
   (void)mo;
   DCHECK(!((uptr)a % sizeof(*a)));
-  return (u32)_InterlockedExchangeAdd(
-      (volatile long*)&a->val_dont_use, -(long)v);  // NOLINT
+  return (u32)_InterlockedExchangeAdd((volatile long *)&a->val_dont_use,
+                                      -(long)v);
 }
 
 INLINE uptr atomic_fetch_sub(volatile atomic_uintptr_t *a,
@@ -145,11 +136,11 @@ INLINE uptr atomic_fetch_sub(volatile atomic_uintptr_t *a,
   (void)mo;
   DCHECK(!((uptr)a % sizeof(*a)));
 #ifdef _WIN64
-  return (uptr)_InterlockedExchangeAdd64(
-      (volatile long long*)&a->val_dont_use, -(long long)v);  // NOLINT
+  return (uptr)_InterlockedExchangeAdd64((volatile long long *)&a->val_dont_use,
+                                         -(long long)v);
 #else
-  return (uptr)_InterlockedExchangeAdd(
-      (volatile long*)&a->val_dont_use, -(long)v);  // NOLINT
+  return (uptr)_InterlockedExchangeAdd((volatile long *)&a->val_dont_use,
+                                       -(long)v);
 #endif
 }
 
index 451c9e526e061321a5fc1b70fae9009537868dca..f5f9f49d8cffc4168bd50240ed0bf077436634f8 100644 (file)
@@ -323,7 +323,7 @@ static int InstallMallocFreeHooks(void (*malloc_hook)(const void *, uptr),
 
 } // namespace __sanitizer
 
-using namespace __sanitizer;  // NOLINT
+using namespace __sanitizer;
 
 extern "C" {
 SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_report_error_summary,
index 4f0f16d353280612bdd322546032d5c564538d10..87b8f02b5b730158f61569fb5d9b8dfceb898ec5 100644 (file)
@@ -100,6 +100,8 @@ void UnmapOrDie(void *addr, uptr size);
 void *MmapOrDieOnFatalError(uptr size, const char *mem_type);
 bool MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name = nullptr)
      WARN_UNUSED_RESULT;
+bool MmapFixedSuperNoReserve(uptr fixed_addr, uptr size,
+                             const char *name = nullptr) WARN_UNUSED_RESULT;
 void *MmapNoReserveOrDie(uptr size, const char *mem_type);
 void *MmapFixedOrDie(uptr fixed_addr, uptr size, const char *name = nullptr);
 // Behaves just like MmapFixedOrDie, but tolerates out of memory condition, in
@@ -337,18 +339,18 @@ void ReportMmapWriteExec(int prot);
 // Math
 #if SANITIZER_WINDOWS && !defined(__clang__) && !defined(__GNUC__)
 extern "C" {
-unsigned char _BitScanForward(unsigned long *index, unsigned long mask);  // NOLINT
-unsigned char _BitScanReverse(unsigned long *index, unsigned long mask);  // NOLINT
+unsigned char _BitScanForward(unsigned long *index, unsigned long mask);
+unsigned char _BitScanReverse(unsigned long *index, unsigned long mask);
 #if defined(_WIN64)
-unsigned char _BitScanForward64(unsigned long *index, unsigned __int64 mask);  // NOLINT
-unsigned char _BitScanReverse64(unsigned long *index, unsigned __int64 mask);  // NOLINT
+unsigned char _BitScanForward64(unsigned long *index, unsigned __int64 mask);
+unsigned char _BitScanReverse64(unsigned long *index, unsigned __int64 mask);
 #endif
 }
 #endif
 
 INLINE uptr MostSignificantSetBitIndex(uptr x) {
   CHECK_NE(x, 0U);
-  unsigned long up;  // NOLINT
+  unsigned long up;
 #if !SANITIZER_WINDOWS || defined(__clang__) || defined(__GNUC__)
 # ifdef _WIN64
   up = SANITIZER_WORDSIZE - 1 - __builtin_clzll(x);
@@ -365,7 +367,7 @@ INLINE uptr MostSignificantSetBitIndex(uptr x) {
 
 INLINE uptr LeastSignificantSetBitIndex(uptr x) {
   CHECK_NE(x, 0U);
-  unsigned long up;  // NOLINT
+  unsigned long up;
 #if !SANITIZER_WINDOWS || defined(__clang__) || defined(__GNUC__)
 # ifdef _WIN64
   up = __builtin_ctzll(x);
@@ -879,6 +881,11 @@ struct SignalContext {
   bool is_memory_access;
   enum WriteFlag { UNKNOWN, READ, WRITE } write_flag;
 
+  // In some cases the kernel cannot provide the true faulting address; `addr`
+  // will be zero then.  This field allows to distinguish between these cases
+  // and dereferences of null.
+  bool is_true_faulting_addr;
+
   // VS2013 doesn't implement unrestricted unions, so we need a trivial default
   // constructor
   SignalContext() = default;
@@ -891,7 +898,8 @@ struct SignalContext {
         context(context),
         addr(GetAddress()),
         is_memory_access(IsMemoryAccess()),
-        write_flag(GetWriteFlag()) {
+        write_flag(GetWriteFlag()),
+        is_true_faulting_addr(IsTrueFaultingAddress()) {
     InitPcSpBp();
   }
 
@@ -912,6 +920,7 @@ struct SignalContext {
   uptr GetAddress() const;
   WriteFlag GetWriteFlag() const;
   bool IsMemoryAccess() const;
+  bool IsTrueFaultingAddress() const;
 };
 
 void InitializePlatformEarly();
@@ -971,7 +980,7 @@ INLINE u32 GetNumberOfCPUsCached() {
 }  // namespace __sanitizer
 
 inline void *operator new(__sanitizer::operator_new_size_type size,
-                          __sanitizer::LowLevelAllocator &alloc) {
+                          __sanitizer::LowLevelAllocator &alloc) {  // NOLINT
   return alloc.Allocate(size);
 }
 
index 9975f5321a59b25b60d6f7f8151ab5a3a4d840a2..50e3558b52e87275987a6ba4522a0ea66e02e382 100644 (file)
@@ -36,6 +36,7 @@
 //   COMMON_INTERCEPTOR_MMAP_IMPL
 //   COMMON_INTERCEPTOR_COPY_STRING
 //   COMMON_INTERCEPTOR_STRNDUP_IMPL
+//   COMMON_INTERCEPTOR_STRERROR
 //===----------------------------------------------------------------------===//
 
 #include "interception/interception.h"
@@ -301,6 +302,10 @@ bool PlatformHasDifferentMemcpyAndMemmove();
   return new_mem;
 #endif
 
+#ifndef COMMON_INTERCEPTOR_STRERROR
+#define COMMON_INTERCEPTOR_STRERROR() {}
+#endif
+
 struct FileMetadata {
   // For open_memstream().
   char **addr;
@@ -1267,9 +1272,8 @@ INTERCEPTOR(int, puts, char *s) {
 #endif
 
 #if SANITIZER_INTERCEPT_PRCTL
-INTERCEPTOR(int, prctl, int option, unsigned long arg2,
-            unsigned long arg3,                        // NOLINT
-            unsigned long arg4, unsigned long arg5) {  // NOLINT
+INTERCEPTOR(int, prctl, int option, unsigned long arg2, unsigned long arg3,
+            unsigned long arg4, unsigned long arg5) {
   void *ctx;
   COMMON_INTERCEPTOR_ENTER(ctx, prctl, option, arg2, arg3, arg4, arg5);
   static const int PR_SET_NAME = 15;
@@ -1701,13 +1705,13 @@ INTERCEPTOR(int, __fprintf_chk, __sanitizer_FILE *stream, SIZE_T size,
 FORMAT_INTERCEPTOR_IMPL(__fprintf_chk, vfprintf, stream, format)
 #endif
 
-INTERCEPTOR(int, sprintf, char *str, const char *format, ...) // NOLINT
-FORMAT_INTERCEPTOR_IMPL(sprintf, vsprintf, str, format) // NOLINT
+INTERCEPTOR(int, sprintf, char *str, const char *format, ...)
+FORMAT_INTERCEPTOR_IMPL(sprintf, vsprintf, str, format)
 
 #if SANITIZER_INTERCEPT___PRINTF_CHK
 INTERCEPTOR(int, __sprintf_chk, char *str, int flag, SIZE_T size_to,
-            const char *format, ...) // NOLINT
-FORMAT_INTERCEPTOR_IMPL(__sprintf_chk, vsprintf, str, format) // NOLINT
+            const char *format, ...)
+FORMAT_INTERCEPTOR_IMPL(__sprintf_chk, vsprintf, str, format)
 #endif
 
 INTERCEPTOR(int, snprintf, char *str, SIZE_T size, const char *format, ...)
@@ -1715,8 +1719,8 @@ FORMAT_INTERCEPTOR_IMPL(snprintf, vsnprintf, str, size, format)
 
 #if SANITIZER_INTERCEPT___PRINTF_CHK
 INTERCEPTOR(int, __snprintf_chk, char *str, SIZE_T size, int flag,
-            SIZE_T size_to, const char *format, ...) // NOLINT
-FORMAT_INTERCEPTOR_IMPL(__snprintf_chk, vsnprintf, str, size, format) // NOLINT
+            SIZE_T size_to, const char *format, ...)
+FORMAT_INTERCEPTOR_IMPL(__snprintf_chk, vsnprintf, str, size, format)
 #endif
 
 INTERCEPTOR(int, asprintf, char **strp, const char *format, ...)
@@ -3071,13 +3075,14 @@ INTERCEPTOR(int, sendmmsg, int fd, struct __sanitizer_mmsghdr *msgvec,
     COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
   }
   int res = REAL(sendmmsg)(fd, msgvec, vlen, flags);
-  if (res >= 0 && msgvec)
+  if (res >= 0 && msgvec) {
     for (int i = 0; i < res; ++i) {
       COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &msgvec[i].msg_len,
                                      sizeof(msgvec[i].msg_len));
       if (common_flags()->intercept_send)
         read_msghdr(ctx, &msgvec[i].msg_hdr, msgvec[i].msg_len);
     }
+  }
   return res;
 }
 #define INIT_SENDMMSG COMMON_INTERCEPT_FUNCTION(sendmmsg);
@@ -3208,20 +3213,21 @@ INTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) {
   __sanitizer_iovec local_iovec;
 
   if (data) {
-    if (request == ptrace_setregs)
+    if (request == ptrace_setregs) {
       COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_regs_struct_sz);
-    else if (request == ptrace_setfpregs)
+    } else if (request == ptrace_setfpregs) {
       COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpregs_struct_sz);
-    else if (request == ptrace_setfpxregs)
+    } else if (request == ptrace_setfpxregs) {
       COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpxregs_struct_sz);
-    else if (request == ptrace_setvfpregs)
+    } else if (request == ptrace_setvfpregs) {
       COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_vfpregs_struct_sz);
-    else if (request == ptrace_setsiginfo)
+    } else if (request == ptrace_setsiginfo) {
       COMMON_INTERCEPTOR_READ_RANGE(ctx, data, siginfo_t_sz);
+
     // Some kernel might zero the iovec::iov_base in case of invalid
     // write access.  In this case copy the invalid address for further
     // inspection.
-    else if (request == ptrace_setregset || request == ptrace_getregset) {
+    else if (request == ptrace_setregset || request == ptrace_getregset) {
       __sanitizer_iovec *iovec = (__sanitizer_iovec*)data;
       COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec, sizeof(*iovec));
       local_iovec = *iovec;
@@ -3238,19 +3244,19 @@ INTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) {
   if (!res && data) {
     // Note that PEEK* requests assign different meaning to the return value.
     // This function does not handle them (nor does it need to).
-    if (request == ptrace_getregs)
+    if (request == ptrace_getregs) {
       COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_regs_struct_sz);
-    else if (request == ptrace_getfpregs)
+    } else if (request == ptrace_getfpregs) {
       COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpregs_struct_sz);
-    else if (request == ptrace_getfpxregs)
+    } else if (request == ptrace_getfpxregs) {
       COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpxregs_struct_sz);
-    else if (request == ptrace_getvfpregs)
+    } else if (request == ptrace_getvfpregs) {
       COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_vfpregs_struct_sz);
-    else if (request == ptrace_getsiginfo)
+    } else if (request == ptrace_getsiginfo) {
       COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, siginfo_t_sz);
-    else if (request == ptrace_geteventmsg)
+    } else if (request == ptrace_geteventmsg) {
       COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, sizeof(unsigned long));
-    else if (request == ptrace_getregset) {
+    else if (request == ptrace_getregset) {
       __sanitizer_iovec *iovec = (__sanitizer_iovec*)data;
       COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iovec, sizeof(*iovec));
       COMMON_INTERCEPTOR_WRITE_RANGE(ctx, local_iovec.iov_base,
@@ -3676,6 +3682,7 @@ INTERCEPTOR(int, sched_getparam, int pid, void *param) {
 INTERCEPTOR(char *, strerror, int errnum) {
   void *ctx;
   COMMON_INTERCEPTOR_ENTER(ctx, strerror, errnum);
+  COMMON_INTERCEPTOR_STRERROR();
   char *res = REAL(strerror)(errnum);
   if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
   return res;
@@ -6716,7 +6723,7 @@ INTERCEPTOR(wchar_t *, wcscat, wchar_t *dst, const wchar_t *src) {
   COMMON_INTERCEPTOR_READ_RANGE(ctx, dst, (dst_size + 1) * sizeof(wchar_t));
   COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst + dst_size,
                                  (src_size + 1) * sizeof(wchar_t));
-  return REAL(wcscat)(dst, src);  // NOLINT
+  return REAL(wcscat)(dst, src);
 }
 
 INTERCEPTOR(wchar_t *, wcsncat, wchar_t *dst, const wchar_t *src, SIZE_T n) {
@@ -6729,7 +6736,7 @@ INTERCEPTOR(wchar_t *, wcsncat, wchar_t *dst, const wchar_t *src, SIZE_T n) {
   COMMON_INTERCEPTOR_READ_RANGE(ctx, dst, (dst_size + 1) * sizeof(wchar_t));
   COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst + dst_size,
                                  (src_size + 1) * sizeof(wchar_t));
-  return REAL(wcsncat)(dst, src, n);  // NOLINT
+  return REAL(wcsncat)(dst, src, n);
 }
 #define INIT_WCSCAT                  \
   COMMON_INTERCEPT_FUNCTION(wcscat); \
@@ -7843,10 +7850,11 @@ INTERCEPTOR(int, modctl, int operation, void *argp) {
     if (iov)
       COMMON_INTERCEPTOR_WRITE_RANGE(
           ctx, iov->iov_base, Min(iov_len,  iov->iov_len));
-  } else if (operation == modctl_exists)
+  } else if (operation == modctl_exists) {
     ret = REAL(modctl)(operation, argp);
-  else
+  } else {
     ret = REAL(modctl)(operation, argp);
+  }
 
   return ret;
 }
@@ -9565,11 +9573,60 @@ INTERCEPTOR(SSIZE_T, getrandom, void *buf, SIZE_T buflen, unsigned int flags) {
 #define INIT_GETRANDOM
 #endif
 
+#if SANITIZER_INTERCEPT_CRYPT
+INTERCEPTOR(char *, crypt, char *key, char *salt) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, crypt, key, salt);
+  COMMON_INTERCEPTOR_READ_RANGE(ctx, key, internal_strlen(key) + 1);
+  COMMON_INTERCEPTOR_READ_RANGE(ctx, salt, internal_strlen(salt) + 1);
+  char *res = REAL(crypt)(key, salt);
+  if (res != nullptr)
+    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
+  return res;
+}
+#define INIT_CRYPT COMMON_INTERCEPT_FUNCTION(crypt);
+#else
+#define INIT_CRYPT
+#endif
+
+#if SANITIZER_INTERCEPT_CRYPT_R
+INTERCEPTOR(char *, crypt_r, char *key, char *salt, void *data) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, crypt_r, key, salt, data);
+  COMMON_INTERCEPTOR_READ_RANGE(ctx, key, internal_strlen(key) + 1);
+  COMMON_INTERCEPTOR_READ_RANGE(ctx, salt, internal_strlen(salt) + 1);
+  char *res = REAL(crypt_r)(key, salt, data);
+  if (res != nullptr) {
+    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data,
+                                   __sanitizer::struct_crypt_data_sz);
+    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
+  }
+  return res;
+}
+#define INIT_CRYPT_R COMMON_INTERCEPT_FUNCTION(crypt_r);
+#else
+#define INIT_CRYPT_R
+#endif
+
+#if SANITIZER_INTERCEPT_GETENTROPY
+INTERCEPTOR(int, getentropy, void *buf, SIZE_T buflen) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, getentropy, buf, buflen);
+  int r = REAL(getentropy)(buf, buflen);
+  if (r == 0) {
+    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
+  }
+  return r;
+}
+#define INIT_GETENTROPY COMMON_INTERCEPT_FUNCTION(getentropy)
+#else
+#define INIT_GETENTROPY
+#endif
+
 static void InitializeCommonInterceptors() {
 #if SI_POSIX
   static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1];
-  interceptor_metadata_map =
-      new ((void *)&metadata_mem) MetadataHashMap();  // NOLINT
+  interceptor_metadata_map = new ((void *)&metadata_mem) MetadataHashMap();
 #endif
 
   INIT_MMAP;
@@ -9864,6 +9921,9 @@ static void InitializeCommonInterceptors() {
   INIT_GETUSERSHELL;
   INIT_SL_INIT;
   INIT_GETRANDOM;
+  INIT_CRYPT;
+  INIT_CRYPT_R;
+  INIT_GETENTROPY;
 
   INIT___PRINTF_CHK;
 }
index c72554973b05eb04ef55bb3361667cb3356d64a8..c78b6e10b689597dd0fafaff957384da299d38da 100644 (file)
@@ -14,6 +14,7 @@ INTERFACE_FUNCTION(__sanitizer_set_death_callback)
 INTERFACE_FUNCTION(__sanitizer_set_report_path)
 INTERFACE_FUNCTION(__sanitizer_set_report_fd)
 INTERFACE_FUNCTION(__sanitizer_verify_contiguous_container)
+INTERFACE_WEAK_FUNCTION(__sanitizer_on_print)
 INTERFACE_WEAK_FUNCTION(__sanitizer_report_error_summary)
 INTERFACE_WEAK_FUNCTION(__sanitizer_sandbox_on_notify)
 // Sanitizer weak hooks
index 5451d1e758b7e2659eda5653515e100172e3062d..f18cee66b84318705f0fb87a7d460706926c50c0 100644 (file)
@@ -36,7 +36,7 @@
 #include <zircon/sanitizer.h>
 #include <zircon/syscalls.h>
 
-using namespace __sanitizer;  // NOLINT
+using namespace __sanitizer;
 
 namespace __sancov {
 namespace {
@@ -198,8 +198,8 @@ void InitializeCoverage(bool enabled, const char *dir) {
 }  // namespace __sanitizer
 
 extern "C" {
-SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_coverage(  // NOLINT
-    const uptr *pcs, uptr len) {
+SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_coverage(const uptr *pcs,
+                                                             uptr len) {
   UNIMPLEMENTED();
 }
 
index ad137f936ffa0871b785e314e46feb418ffe1098..6a75792f92624d29b16932c8c649c0c32c4fd0ee 100644 (file)
@@ -166,8 +166,8 @@ void InitializeCoverage(bool enabled, const char *dir) {
 } // namespace __sanitizer
 
 extern "C" {
-SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_coverage(  // NOLINT
-    const uptr* pcs, uptr len) {
+SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_coverage(const uptr* pcs,
+                                                             uptr len) {
   return __sancov::SanitizerDumpCoverage(pcs, len);
 }
 
index 40184bbb913349d0a008b5c49acb5a0deed1eca7..e7d6563393cfd596c9ed45a245cff0793203fa8c 100644 (file)
@@ -31,7 +31,7 @@ extern "C" {
 // Use uint64_t so the linker won't need to add any padding if it tries to word
 // align the start of the 8-bit counters array. The array will always start 8
 // bytes after __start_sancov_cntrs.
-#pragma section(".SCOV$CA", read, write)  // NOLINT
+#pragma section(".SCOV$CA", read, write)
 __declspec(allocate(".SCOV$CA")) uint64_t __start___sancov_cntrs = 0;
 
 // Even though we said not to align __stop__sancov_cntrs (using the "align"
@@ -41,13 +41,13 @@ __declspec(allocate(".SCOV$CA")) uint64_t __start___sancov_cntrs = 0;
 // padding would be added to align .SCOVP$Z, However, if .SCOV$CZ section is 1
 // byte, the linker won't try to align it on an 8-byte boundary, so use a
 // uint8_t for __stop_sancov_cntrs.
-#pragma section(".SCOV$CZ", read, write)  // NOLINT
+#pragma section(".SCOV$CZ", read, write)
 __declspec(allocate(".SCOV$CZ")) __declspec(align(1)) uint8_t
     __stop___sancov_cntrs = 0;
 
-#pragma section(".SCOV$GA", read, write)  // NOLINT
+#pragma section(".SCOV$GA", read, write)
 __declspec(allocate(".SCOV$GA")) uint64_t __start___sancov_guards = 0;
-#pragma section(".SCOV$GZ", read, write)  // NOLINT
+#pragma section(".SCOV$GZ", read, write)
 __declspec(allocate(".SCOV$GZ")) __declspec(align(1)) uint8_t
     __stop___sancov_guards = 0;
 
@@ -56,9 +56,9 @@ __declspec(allocate(".SCOV$GZ")) __declspec(align(1)) uint8_t
 // constant it should be merged with the .rdata section.
 #pragma comment(linker, "/MERGE:.SCOV=.data")
 
-#pragma section(".SCOVP$A", read)  // NOLINT
+#pragma section(".SCOVP$A", read)
 __declspec(allocate(".SCOVP$A")) uint64_t __start___sancov_pcs = 0;
-#pragma section(".SCOVP$Z", read)  // NOLINT
+#pragma section(".SCOVP$Z", read)
 __declspec(allocate(".SCOVP$Z")) __declspec(align(1)) uint8_t
     __stop___sancov_pcs = 0;
 
index c8c0b33cd6c19e59ebd5d4f40a0096286fabc70b..79930d79425016f1d3aefb53b826b2b1ff7a5ceb 100644 (file)
@@ -199,7 +199,7 @@ char *FindPathToBinary(const char *name) {
 
 } // namespace __sanitizer
 
-using namespace __sanitizer;  // NOLINT
+using namespace __sanitizer;
 
 extern "C" {
 void __sanitizer_set_report_path(const char *path) {
index 4831814b6dfb11c2b5dd013ee54850722c323060..1e2bc6652617965a6043fbf7a0cac4ae6753268a 100644 (file)
@@ -83,8 +83,9 @@ void FlagParser::parse_flag(const char *env_option_name) {
       Printf("%s: ERROR: expected '=' in %s\n", SanitizerToolName,
              env_option_name);
       Die();
-    } else
+    } else {
       fatal_error("expected '='");
+    }
   }
   char *name = ll_strndup(buf_ + name_start, pos_ - name_start);
 
index 8e12700bbe8c3c5870d3e74dfdff82d62906adff..c24ad25626badc4e84a3e74c7996f0457d41701b 100644 (file)
@@ -24,7 +24,7 @@ class FlagHandlerBase {
   virtual bool Parse(const char *value) { return false; }
 
  protected:
-  ~FlagHandlerBase() {};
+  ~FlagHandlerBase() {}
 };
 
 template <typename T>
@@ -144,7 +144,7 @@ class FlagParser {
 template <typename T>
 static void RegisterFlag(FlagParser *parser, const char *name, const char *desc,
                          T *var) {
-  FlagHandler<T> *fh = new (FlagParser::Alloc) FlagHandler<T>(var);  // NOLINT
+  FlagHandler<T> *fh = new (FlagParser::Alloc) FlagHandler<T>(var);
   parser->RegisterHandler(name, fh, desc);
 }
 
index acc7ed39cb0ab3a5920ab77c3ade8610763325ce..66a0a5579ed386bc8104c3162c74fbd22a6d5d25 100644 (file)
@@ -92,11 +92,11 @@ class FlagHandlerInclude : public FlagHandlerBase {
 };
 
 void RegisterIncludeFlags(FlagParser *parser, CommonFlags *cf) {
-  FlagHandlerInclude *fh_include = new (FlagParser::Alloc) // NOLINT
+  FlagHandlerInclude *fh_include = new (FlagParser::Alloc)
       FlagHandlerInclude(parser, /*ignore_missing*/ false);
   parser->RegisterHandler("include", fh_include,
                           "read more options from the given file");
-  FlagHandlerInclude *fh_include_if_exists = new (FlagParser::Alloc) // NOLINT
+  FlagHandlerInclude *fh_include_if_exists = new (FlagParser::Alloc)
       FlagHandlerInclude(parser, /*ignore_missing*/ true);
   parser->RegisterHandler(
       "include_if_exists", fh_include_if_exists,
index 3dc6863a03af65d5155c687817561b1203488899..6e2c6137f0ce7fa25d2b07fee67ce6bf46161248 100644 (file)
@@ -502,7 +502,7 @@ uptr GetRSS() { UNIMPLEMENTED(); }
 
 }  // namespace __sanitizer
 
-using namespace __sanitizer;  // NOLINT
+using namespace __sanitizer;
 
 extern "C" {
 void __sanitizer_startup_hook(int argc, char **argv, char **envp,
index cbd1af12c04f26a3aac2aa93fa98db040d581717..86ad3a5e2c2aa5ef498aa8ac3751e5b1873d0622 100644 (file)
@@ -9,6 +9,7 @@
 // Common getauxval() guards and definitions.
 // getauxval() is not defined until glibc version 2.16, or until API level 21
 // for Android.
+// Implement the getauxval() compat function for NetBSD.
 //
 //===----------------------------------------------------------------------===//
 
 #define SANITIZER_GETAUXVAL_H
 
 #include "sanitizer_platform.h"
+#include "sanitizer_glibc_version.h"
 
 #if SANITIZER_LINUX || SANITIZER_FUCHSIA
 
-# include <features.h>
-
-# ifndef __GLIBC_PREREQ
-#  define __GLIBC_PREREQ(x, y) 0
-# endif
-
 # if __GLIBC_PREREQ(2, 16) || (SANITIZER_ANDROID && __ANDROID_API__ >= 21) || \
      SANITIZER_FUCHSIA
 #  define SANITIZER_USE_GETAUXVAL 1
 // The weak getauxval definition allows to check for the function at runtime.
 // This is useful for Android, when compiled at a lower API level yet running
 // on a more recent platform that offers the function.
-extern "C" SANITIZER_WEAK_ATTRIBUTE
-unsigned long getauxval(unsigned long type);  // NOLINT
+extern "C" SANITIZER_WEAK_ATTRIBUTE unsigned long getauxval(unsigned long type);
 # endif
 
-#endif // SANITIZER_LINUX || SANITIZER_FUCHSIA
+#elif SANITIZER_NETBSD
+
+#define SANITIZER_USE_GETAUXVAL 1
+
+#include <dlfcn.h>
+#include <elf.h>
+
+static inline decltype(AuxInfo::a_v) getauxval(decltype(AuxInfo::a_type) type) {
+  for (const AuxInfo *aux = (const AuxInfo *)_dlauxinfo();
+       aux->a_type != AT_NULL; ++aux) {
+    if (type == aux->a_type)
+      return aux->a_v;
+  }
+
+  return 0;
+}
+
+#endif
 
 #endif // SANITIZER_GETAUXVAL_H
diff --git a/libsanitizer/sanitizer_common/sanitizer_glibc_version.h b/libsanitizer/sanitizer_common/sanitizer_glibc_version.h
new file mode 100644 (file)
index 0000000..47175f2
--- /dev/null
@@ -0,0 +1,26 @@
+//===-- sanitizer_glibc_version.h -----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of Sanitizer common code.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_GLIBC_VERSION_H
+#define SANITIZER_GLIBC_VERSION_H
+
+#include "sanitizer_platform.h"
+
+#if SANITIZER_LINUX || SANITIZER_FUCHSIA
+#include <features.h>
+#endif
+
+#ifndef __GLIBC_PREREQ
+#define __GLIBC_PREREQ(x, y) 0
+#endif
+
+#endif
index 1ec73827b8b1427c505dd5c815905ea670b1e5e0..03ef7c1788cdb1658adfb99be9c6fe1a59849d09 100644 (file)
@@ -1404,7 +1404,7 @@ static void ioctl_table_fill() {
   _(SNDCTL_DSP_SKIP, NONE, 0);
   _(SNDCTL_DSP_SILENCE, NONE, 0);
 #undef _
-}
+}  // NOLINT
 
 static bool ioctl_initialized = false;
 
index e0c6506bed51ec181a58fb408b4baaa5677e8290..00226305e07cef5be10e682c30d1e80ae75bc0a6 100644 (file)
@@ -133,27 +133,27 @@ namespace __sanitizer {
 
 #if defined(_WIN64)
 // 64-bit Windows uses LLP64 data model.
-typedef unsigned long long uptr;  // NOLINT
-typedef signed   long long sptr;  // NOLINT
+typedef unsigned long long uptr;
+typedef signed long long sptr;
 #else
-typedef unsigned long uptr;  // NOLINT
-typedef signed   long sptr;  // NOLINT
+typedef unsigned long uptr;
+typedef signed long sptr;
 #endif  // defined(_WIN64)
 #if defined(__x86_64__)
 // Since x32 uses ILP32 data model in 64-bit hardware mode, we must use
 // 64-bit pointer to unwind stack frame.
-typedef unsigned long long uhwptr;  // NOLINT
+typedef unsigned long long uhwptr;
 #else
-typedef uptr uhwptr;   // NOLINT
+typedef uptr uhwptr;
 #endif
 typedef unsigned char u8;
-typedef unsigned short u16;  // NOLINT
+typedef unsigned short u16;
 typedef unsigned int u32;
-typedef unsigned long long u64;  // NOLINT
-typedef signed   char s8;
-typedef signed   short s16;  // NOLINT
-typedef signed   int s32;
-typedef signed   long long s64;  // NOLINT
+typedef unsigned long long u64;
+typedef signed char s8;
+typedef signed short s16;
+typedef signed int s32;
+typedef signed long long s64;
 #if SANITIZER_WINDOWS
 // On Windows, files are HANDLE, which is a synonim of void*.
 // Use void* to avoid including <windows.h> everywhere.
@@ -264,7 +264,7 @@ typedef ALIGNED(1) s64 us64;
 
 #if SANITIZER_WINDOWS
 }  // namespace __sanitizer
-typedef unsigned long DWORD;  // NOLINT
+typedef unsigned long DWORD;
 namespace __sanitizer {
 typedef DWORD thread_return_t;
 # define THREAD_CALLING_CONV __stdcall
@@ -419,18 +419,41 @@ inline void Trap() {
 
 }  // namespace __sanitizer
 
-namespace __asan  { using namespace __sanitizer; }  // NOLINT
-namespace __dsan  { using namespace __sanitizer; }  // NOLINT
-namespace __dfsan { using namespace __sanitizer; }  // NOLINT
-namespace __lsan  { using namespace __sanitizer; }  // NOLINT
-namespace __msan  { using namespace __sanitizer; }  // NOLINT
-namespace __hwasan  { using namespace __sanitizer; }  // NOLINT
-namespace __tsan  { using namespace __sanitizer; }  // NOLINT
-namespace __scudo { using namespace __sanitizer; }  // NOLINT
-namespace __ubsan { using namespace __sanitizer; }  // NOLINT
-namespace __xray  { using namespace __sanitizer; }  // NOLINT
-namespace __interception  { using namespace __sanitizer; }  // NOLINT
-namespace __hwasan  { using namespace __sanitizer; }  // NOLINT
-
+namespace __asan {
+using namespace __sanitizer;
+}
+namespace __dsan {
+using namespace __sanitizer;
+}
+namespace __dfsan {
+using namespace __sanitizer;
+}
+namespace __lsan {
+using namespace __sanitizer;
+}
+namespace __msan {
+using namespace __sanitizer;
+}
+namespace __hwasan {
+using namespace __sanitizer;
+}
+namespace __tsan {
+using namespace __sanitizer;
+}
+namespace __scudo {
+using namespace __sanitizer;
+}
+namespace __ubsan {
+using namespace __sanitizer;
+}
+namespace __xray {
+using namespace __sanitizer;
+}
+namespace __interception {
+using namespace __sanitizer;
+}
+namespace __hwasan {
+using namespace __sanitizer;
+}
 
 #endif  // SANITIZER_DEFS_H
index 5c9d3a80c1331faa4644a7fa605131c6153ecc4f..4bc04b486870c6e459ef969e67bcec498c991b02 100644 (file)
@@ -63,10 +63,11 @@ void *internal_memmove(void *dest, const void *src, uptr n) {
     for (i = 0; i < signed_n; ++i)
       d[i] = s[i];
   } else {
-    if (d > s && signed_n > 0)
-      for (i = signed_n - 1; i >= 0 ; --i) {
+    if (d > s && signed_n > 0) {
+      for (i = signed_n - 1; i >= 0; --i) {
         d[i] = s[i];
       }
+    }
   }
   return dest;
 }
@@ -270,9 +271,9 @@ bool mem_is_zero(const char *beg, uptr size) {
   for (; aligned_beg < aligned_end; aligned_beg++)
     all |= *aligned_beg;
   // Epilogue.
-  if ((char*)aligned_end >= beg)
-    for (const char *mem = (char*)aligned_end; mem < end; mem++)
-      all |= *mem;
+  if ((char *)aligned_end >= beg) {
+    for (const char *mem = (char *)aligned_end; mem < end; mem++) all |= *mem;
+  }
   return all == 0;
 }
 
index 1ed6af33fb8af100830b374fbc3643ec315f1499..0b53da6c349f281b302c98977f6b619f83e4ab04 100644 (file)
@@ -1062,8 +1062,6 @@ uptr GetMaxUserVirtualAddress() {
 uptr GetPageSize() {
 #if SANITIZER_LINUX && (defined(__x86_64__) || defined(__i386__))
   return EXEC_PAGESIZE;
-#elif SANITIZER_USE_GETAUXVAL
-  return getauxval(AT_PAGESZ);
 #elif SANITIZER_FREEBSD || SANITIZER_NETBSD
 // Use sysctl as sysconf can trigger interceptors internally.
   int pz = 0;
@@ -1072,6 +1070,8 @@ uptr GetPageSize() {
   int rv = internal_sysctl(mib, 2, &pz, &pzl, nullptr, 0);
   CHECK_EQ(rv, 0);
   return (uptr)pz;
+#elif SANITIZER_USE_GETAUXVAL
+  return getauxval(AT_PAGESZ);
 #else
   return sysconf(_SC_PAGESIZE);  // EXEC_PAGESIZE may not be trustworthy.
 #endif
@@ -1849,6 +1849,12 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
 #endif
 }
 
+bool SignalContext::IsTrueFaultingAddress() const {
+  auto si = static_cast<const siginfo_t *>(siginfo);
+  // SIGSEGV signals without a true fault address have si_code set to 128.
+  return si->si_signo == SIGSEGV && si->si_code != 128;
+}
+
 void SignalContext::DumpAllRegisters(void *context) {
   // FIXME: Implement this.
 }
@@ -2011,6 +2017,35 @@ void CheckASLR() {
     CHECK_NE(personality(old_personality | ADDR_NO_RANDOMIZE), -1);
     ReExec();
   }
+#elif SANITIZER_FREEBSD
+  int aslr_pie;
+  uptr len = sizeof(aslr_pie);
+#if SANITIZER_WORDSIZE == 64
+  if (UNLIKELY(internal_sysctlbyname("kern.elf64.aslr.pie_enable",
+      &aslr_pie, &len, NULL, 0) == -1)) {
+    // We're making things less 'dramatic' here since
+    // the OID is not necessarily guaranteed to be here
+    // just yet regarding FreeBSD release
+    return;
+  }
+
+  if (aslr_pie > 0) {
+    Printf("This sanitizer is not compatible with enabled ASLR "
+           "and binaries compiled with PIE\n");
+    Die();
+  }
+#endif
+  // there might be 32 bits compat for 64 bits
+  if (UNLIKELY(internal_sysctlbyname("kern.elf32.aslr.pie_enable",
+      &aslr_pie, &len, NULL, 0) == -1)) {
+    return;
+  }
+
+  if (aslr_pie > 0) {
+    Printf("This sanitizer is not compatible with enabled ASLR "
+           "and binaries compiled with PIE\n");
+    Die();
+  }
 #else
   // Do nothing
 #endif
index 7dc38a0b703fab1555b88925b07bf50f20611eaf..cd503718205a18807445b65c126296005d3ecd77 100644 (file)
@@ -23,6 +23,7 @@
 #include "sanitizer_flags.h"
 #include "sanitizer_freebsd.h"
 #include "sanitizer_getauxval.h"
+#include "sanitizer_glibc_version.h"
 #include "sanitizer_linux.h"
 #include "sanitizer_placement_new.h"
 #include "sanitizer_procmaps.h"
@@ -188,11 +189,7 @@ __attribute__((unused)) static bool GetLibcVersion(int *major, int *minor,
 static uptr g_tls_size;
 
 #ifdef __i386__
-# ifndef __GLIBC_PREREQ
-#  define CHECK_GET_TLS_STATIC_INFO_VERSION 1
-# else
-#  define CHECK_GET_TLS_STATIC_INFO_VERSION (!__GLIBC_PREREQ(2, 27))
-# endif
+# define CHECK_GET_TLS_STATIC_INFO_VERSION (!__GLIBC_PREREQ(2, 27))
 #else
 # define CHECK_GET_TLS_STATIC_INFO_VERSION 0
 #endif
@@ -701,13 +698,9 @@ u32 GetNumberOfCPUs() {
 #elif SANITIZER_SOLARIS
   return sysconf(_SC_NPROCESSORS_ONLN);
 #else
-#if defined(CPU_COUNT)
   cpu_set_t CPUs;
   CHECK_EQ(sched_getaffinity(0, sizeof(cpu_set_t), &CPUs), 0);
   return CPU_COUNT(&CPUs);
-#else
-  return 1;
-#endif
 #endif
 }
 
index 7552b7aa9654cdeee22b717645e8728b8ed5c795..ea4bd02aa92e4580bcf4f1c49a540722d70af9b7 100644 (file)
@@ -13,6 +13,7 @@
 #include "sanitizer_platform.h"
 #if SANITIZER_MAC
 #include "sanitizer_mac.h"
+#include "interception/interception.h"
 
 // Use 64-bit inodes in file operations. ASan does not support OS X 10.5, so
 // the clients will most certainly use 64-bit ones as well.
@@ -36,7 +37,7 @@
 extern char **environ;
 #endif
 
-#if defined(__has_include) && __has_include(<os/trace.h>) && defined(__BLOCKS__)
+#if defined(__has_include) && __has_include(<os/trace.h>)
 #define SANITIZER_OS_TRACE 1
 #include <os/trace.h>
 #else
@@ -64,7 +65,9 @@ extern "C" {
 #include <pthread.h>
 #include <sched.h>
 #include <signal.h>
+#include <spawn.h>
 #include <stdlib.h>
+#include <sys/ioctl.h>
 #include <sys/mman.h>
 #include <sys/resource.h>
 #include <sys/stat.h>
@@ -239,27 +242,102 @@ int internal_sysctlbyname(const char *sname, void *oldp, uptr *oldlenp,
                       (size_t)newlen);
 }
 
-int internal_forkpty(int *aparent) {
-  int parent, worker;
-  if (openpty(&parent, &worker, nullptr, nullptr, nullptr) == -1) return -1;
-  int pid = internal_fork();
-  if (pid == -1) {
-    close(parent);
-    close(worker);
-    return -1;
+static fd_t internal_spawn_impl(const char *argv[], pid_t *pid) {
+  fd_t master_fd = kInvalidFd;
+  fd_t slave_fd = kInvalidFd;
+
+  auto fd_closer = at_scope_exit([&] {
+    internal_close(master_fd);
+    internal_close(slave_fd);
+  });
+
+  // We need a new pseudoterminal to avoid buffering problems. The 'atos' tool
+  // in particular detects when it's talking to a pipe and forgets to flush the
+  // output stream after sending a response.
+  master_fd = posix_openpt(O_RDWR);
+  if (master_fd == kInvalidFd) return kInvalidFd;
+
+  int res = grantpt(master_fd) || unlockpt(master_fd);
+  if (res != 0) return kInvalidFd;
+
+  // Use TIOCPTYGNAME instead of ptsname() to avoid threading problems.
+  char slave_pty_name[128];
+  res = ioctl(master_fd, TIOCPTYGNAME, slave_pty_name);
+  if (res == -1) return kInvalidFd;
+
+  slave_fd = internal_open(slave_pty_name, O_RDWR);
+  if (slave_fd == kInvalidFd) return kInvalidFd;
+
+  // File descriptor actions
+  posix_spawn_file_actions_t acts;
+  res = posix_spawn_file_actions_init(&acts);
+  if (res != 0) return kInvalidFd;
+
+  auto acts_cleanup = at_scope_exit([&] {
+    posix_spawn_file_actions_destroy(&acts);
+  });
+
+  res = posix_spawn_file_actions_adddup2(&acts, slave_fd, STDIN_FILENO) ||
+        posix_spawn_file_actions_adddup2(&acts, slave_fd, STDOUT_FILENO) ||
+        posix_spawn_file_actions_addclose(&acts, slave_fd);
+  if (res != 0) return kInvalidFd;
+
+  // Spawn attributes
+  posix_spawnattr_t attrs;
+  res = posix_spawnattr_init(&attrs);
+  if (res != 0) return kInvalidFd;
+
+  auto attrs_cleanup  = at_scope_exit([&] {
+    posix_spawnattr_destroy(&attrs);
+  });
+
+  // In the spawned process, close all file descriptors that are not explicitly
+  // described by the file actions object. This is Darwin-specific extension.
+  res = posix_spawnattr_setflags(&attrs, POSIX_SPAWN_CLOEXEC_DEFAULT);
+  if (res != 0) return kInvalidFd;
+
+  // posix_spawn
+  char **argv_casted = const_cast<char **>(argv);
+  char **env = GetEnviron();
+  res = posix_spawn(pid, argv[0], &acts, &attrs, argv_casted, env);
+  if (res != 0) return kInvalidFd;
+
+  // Disable echo in the new terminal, disable CR.
+  struct termios termflags;
+  tcgetattr(master_fd, &termflags);
+  termflags.c_oflag &= ~ONLCR;
+  termflags.c_lflag &= ~ECHO;
+  tcsetattr(master_fd, TCSANOW, &termflags);
+
+  // On success, do not close master_fd on scope exit.
+  fd_t fd = master_fd;
+  master_fd = kInvalidFd;
+
+  return fd;
+}
+
+fd_t internal_spawn(const char *argv[], pid_t *pid) {
+  // The client program may close its stdin and/or stdout and/or stderr thus
+  // allowing open/posix_openpt to reuse file descriptors 0, 1 or 2. In this
+  // case the communication is broken if either the parent or the child tries to
+  // close or duplicate these descriptors. We temporarily reserve these
+  // descriptors here to prevent this.
+  fd_t low_fds[3];
+  size_t count = 0;
+
+  for (; count < 3; count++) {
+    low_fds[count] = posix_openpt(O_RDWR);
+    if (low_fds[count] >= STDERR_FILENO)
+      break;
   }
-  if (pid == 0) {
-    close(parent);
-    if (login_tty(worker) != 0) {
-      // We already forked, there's not much we can do.  Let's quit.
-      Report("login_tty failed (errno %d)\n", errno);
-      internal__exit(1);
-    }
-  } else {
-    *aparent = parent;
-    close(worker);
+
+  fd_t fd = internal_spawn_impl(argv, pid);
+
+  for (; count > 0; count--) {
+    internal_close(low_fds[count]);
   }
-  return pid;
+
+  return fd;
 }
 
 uptr internal_rename(const char *oldpath, const char *newpath) {
@@ -676,6 +754,12 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
 #endif
 }
 
+bool SignalContext::IsTrueFaultingAddress() const {
+  auto si = static_cast<const siginfo_t *>(siginfo);
+  // "Real" SIGSEGV codes (e.g., SEGV_MAPERR, SEGV_MAPERR) are non-zero.
+  return si->si_signo == SIGSEGV && si->si_code != 0;
+}
+
 static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
   ucontext_t *ucontext = (ucontext_t*)context;
 # if defined(__aarch64__)
@@ -1122,7 +1206,7 @@ bool GetRandom(void *buffer, uptr length, bool blocking) {
   if (!buffer || !length || length > 256)
     return false;
   // arc4random never fails.
-  arc4random_buf(buffer, length);
+  REAL(arc4random_buf)(buffer, length);
   return true;
 }
 
index e7becbb0e206a901adf2d171bcda7e7cab52a43b..61a6b82ef8184b98833ca482b6040cc6a9d3f198 100644 (file)
@@ -13,6 +13,7 @@
 #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H
 #define SANITIZER_PLATFORM_INTERCEPTORS_H
 
+#include "sanitizer_glibc_version.h"
 #include "sanitizer_internal_defs.h"
 
 #if SANITIZER_POSIX
 #define SANITIZER_INTERCEPT_ETHER_HOST \
   (SI_FREEBSD || SI_MAC || SI_LINUX_NOT_ANDROID)
 #define SANITIZER_INTERCEPT_ETHER_R (SI_FREEBSD || SI_LINUX_NOT_ANDROID)
-#define SANITIZER_INTERCEPT_SHMCTL          \
-  (SI_NETBSD || SI_OPENBSD || SI_SOLARIS || \
-  ((SI_FREEBSD || SI_LINUX_NOT_ANDROID) && \
-    SANITIZER_WORDSIZE == 64))  // NOLINT
+#define SANITIZER_INTERCEPT_SHMCTL                                       \
+  (((SI_FREEBSD || SI_LINUX_NOT_ANDROID) && SANITIZER_WORDSIZE == 64) || \
+   SI_NETBSD || SI_OPENBSD || SI_SOLARIS)  // NOLINT
 #define SANITIZER_INTERCEPT_RANDOM_R SI_LINUX_NOT_ANDROID
 #define SANITIZER_INTERCEPT_PTHREAD_ATTR_GET SI_POSIX
 #define SANITIZER_INTERCEPT_PTHREAD_ATTR_GETINHERITSCHED \
   SI_NOT_RTEMS)
 #define SANITIZER_INTERCEPT_REALLOCARRAY SI_POSIX
 #define SANITIZER_INTERCEPT_ALIGNED_ALLOC (!SI_MAC && SI_NOT_RTEMS)
-#define SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE (!SI_MAC && !SI_OPENBSD)
+#define SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE \
+  (!SI_MAC && !SI_OPENBSD && !SI_NETBSD)
 #define SANITIZER_INTERCEPT_MCHECK_MPROBE SI_LINUX_NOT_ANDROID
 #define SANITIZER_INTERCEPT_WCSCAT SI_POSIX
 #define SANITIZER_INTERCEPT_WCSDUP SI_POSIX
 #define SANITIZER_INTERCEPT_FUNOPEN (SI_NETBSD || SI_FREEBSD)
 #define SANITIZER_INTERCEPT_FUNOPEN2 SI_NETBSD
 #define SANITIZER_INTERCEPT_GETFSENT (SI_FREEBSD || SI_NETBSD || SI_MAC)
-#define SANITIZER_INTERCEPT_ARC4RANDOM (SI_FREEBSD || SI_NETBSD)
+#define SANITIZER_INTERCEPT_ARC4RANDOM (SI_FREEBSD || SI_NETBSD || SI_MAC)
 #define SANITIZER_INTERCEPT_FDEVNAME SI_FREEBSD
 #define SANITIZER_INTERCEPT_GETUSERSHELL (SI_POSIX && !SI_ANDROID)
 #define SANITIZER_INTERCEPT_SL_INIT (SI_FREEBSD || SI_NETBSD)
-
-#define SANITIZER_INTERCEPT_GETRANDOM SI_LINUX
+#define SANITIZER_INTERCEPT_CRYPT (SI_POSIX && !SI_ANDROID)
+#define SANITIZER_INTERCEPT_CRYPT_R (SI_LINUX && !SI_ANDROID)
+
+#define SANITIZER_INTERCEPT_GETRANDOM \
+  ((SI_LINUX && __GLIBC_PREREQ(2, 25)) || SI_FREEBSD)
+#define SANITIZER_INTERCEPT___CXA_ATEXIT SI_NETBSD
+#define SANITIZER_INTERCEPT_ATEXIT SI_NETBSD
+#define SANITIZER_INTERCEPT_PTHREAD_ATFORK SI_NETBSD
+#define SANITIZER_INTERCEPT_GETENTROPY SI_FREEBSD
 
 #endif  // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H
index 46307c6c4340fc3b3e2dc64ea06c63adc81e83ef..71cf5b9c35715c85a26018d3824212a5689305db 100644 (file)
 #include <sys/_types.h>
 
 namespace __sanitizer {
-  extern unsigned struct_utsname_sz;
-  extern unsigned struct_stat_sz;
+extern unsigned struct_utsname_sz;
+extern unsigned struct_stat_sz;
 #if defined(__powerpc64__)
-  const unsigned struct___old_kernel_stat_sz = 0;
+const unsigned struct___old_kernel_stat_sz = 0;
 #else
-  const unsigned struct___old_kernel_stat_sz = 32;
+const unsigned struct___old_kernel_stat_sz = 32;
 #endif
-  extern unsigned struct_rusage_sz;
-  extern unsigned siginfo_t_sz;
-  extern unsigned struct_itimerval_sz;
-  extern unsigned pthread_t_sz;
-  extern unsigned pthread_mutex_t_sz;
-  extern unsigned pthread_cond_t_sz;
-  extern unsigned pid_t_sz;
-  extern unsigned timeval_sz;
-  extern unsigned uid_t_sz;
-  extern unsigned gid_t_sz;
-  extern unsigned fpos_t_sz;
-  extern unsigned mbstate_t_sz;
-  extern unsigned struct_timezone_sz;
-  extern unsigned struct_tms_sz;
-  extern unsigned struct_itimerspec_sz;
-  extern unsigned struct_sigevent_sz;
-  extern unsigned struct_sched_param_sz;
-  extern unsigned struct_statfs64_sz;
-  extern unsigned struct_statfs_sz;
-  extern unsigned struct_sockaddr_sz;
-  extern unsigned ucontext_t_sz;
-  extern unsigned struct_rlimit_sz;
-  extern unsigned struct_utimbuf_sz;
-  extern unsigned struct_timespec_sz;
-  extern unsigned struct_regmatch_sz;
-  extern unsigned struct_regex_sz;
-  extern unsigned struct_FTS_sz;
-  extern unsigned struct_FTSENT_sz;
-  extern const int unvis_valid;
-  extern const int unvis_validpush;
-
-  struct __sanitizer_iocb {
-    u64   aio_data;
-    u32   aio_key_or_aio_reserved1; // Simply crazy.
-    u32   aio_reserved1_or_aio_key; // Luckily, we don't need these.
-    u16   aio_lio_opcode;
-    s16   aio_reqprio;
-    u32   aio_fildes;
-    u64   aio_buf;
-    u64   aio_nbytes;
-    s64   aio_offset;
-    u64   aio_reserved2;
-    u64   aio_reserved3;
-  };
-
-  struct __sanitizer_io_event {
-    u64 data;
-    u64 obj;
-    u64 res;
-    u64 res2;
-  };
-
-  const unsigned iocb_cmd_pread = 0;
-  const unsigned iocb_cmd_pwrite = 1;
-  const unsigned iocb_cmd_preadv = 7;
-  const unsigned iocb_cmd_pwritev = 8;
-
-  struct __sanitizer___sysctl_args {
-    int *name;
-    int nlen;
-    void *oldval;
-    uptr *oldlenp;
-    void *newval;
-    uptr newlen;
-    unsigned long ___unused[4];
-  };
-
-  struct __sanitizer_ipc_perm {
-    unsigned int cuid;
-    unsigned int cgid;
-    unsigned int uid;
-    unsigned int gid;
-    unsigned short mode;
-    unsigned short seq;
-    long key;
-  };
-
-  struct __sanitizer_shmid_ds {
-    __sanitizer_ipc_perm shm_perm;
-    unsigned long shm_segsz;
-    unsigned int shm_lpid;
-    unsigned int shm_cpid;
-    int shm_nattch;
-    unsigned long shm_atime;
-    unsigned long shm_dtime;
-    unsigned long shm_ctime;
-  };
-
-  extern unsigned struct_msqid_ds_sz;
-  extern unsigned struct_mq_attr_sz;
-  extern unsigned struct_timeb_sz;
-  extern unsigned struct_statvfs_sz;
-
-  struct __sanitizer_iovec {
-    void *iov_base;
-    uptr iov_len;
-  };
-
-  struct __sanitizer_ifaddrs {
-    struct __sanitizer_ifaddrs *ifa_next;
-    char *ifa_name;
-    unsigned int ifa_flags;
-    void *ifa_addr;    // (struct sockaddr *)
-    void *ifa_netmask; // (struct sockaddr *)
-# undef ifa_dstaddr
-    void *ifa_dstaddr; // (struct sockaddr *)
-    void *ifa_data;
-  };
-
-  typedef unsigned __sanitizer_pthread_key_t;
-
-  struct __sanitizer_passwd {
-    char *pw_name;
-    char *pw_passwd;
-    int pw_uid;
-    int pw_gid;
-    long pw_change;
-    char *pw_class;
-    char *pw_gecos;
-    char *pw_dir;
-    char *pw_shell;
-    long pw_expire;
-    int pw_fields;
-  };
-
-  struct __sanitizer_group {
-    char *gr_name;
-    char *gr_passwd;
-    int gr_gid;
-    char **gr_mem;
-  };
-
-#if defined(__LP64___)
-  typedef long long __sanitizer_time_t;
+extern unsigned struct_rusage_sz;
+extern unsigned siginfo_t_sz;
+extern unsigned struct_itimerval_sz;
+extern unsigned pthread_t_sz;
+extern unsigned pthread_mutex_t_sz;
+extern unsigned pthread_cond_t_sz;
+extern unsigned pid_t_sz;
+extern unsigned timeval_sz;
+extern unsigned uid_t_sz;
+extern unsigned gid_t_sz;
+extern unsigned fpos_t_sz;
+extern unsigned mbstate_t_sz;
+extern unsigned struct_timezone_sz;
+extern unsigned struct_tms_sz;
+extern unsigned struct_itimerspec_sz;
+extern unsigned struct_sigevent_sz;
+extern unsigned struct_sched_param_sz;
+extern unsigned struct_statfs64_sz;
+extern unsigned struct_statfs_sz;
+extern unsigned struct_sockaddr_sz;
+extern unsigned ucontext_t_sz;
+extern unsigned struct_rlimit_sz;
+extern unsigned struct_utimbuf_sz;
+extern unsigned struct_timespec_sz;
+extern unsigned struct_regmatch_sz;
+extern unsigned struct_regex_sz;
+extern unsigned struct_FTS_sz;
+extern unsigned struct_FTSENT_sz;
+extern const int unvis_valid;
+extern const int unvis_validpush;
+
+struct __sanitizer_iocb {
+  u64 aio_data;
+  u32 aio_key_or_aio_reserved1;  // Simply crazy.
+  u32 aio_reserved1_or_aio_key;  // Luckily, we don't need these.
+  u16 aio_lio_opcode;
+  s16 aio_reqprio;
+  u32 aio_fildes;
+  u64 aio_buf;
+  u64 aio_nbytes;
+  s64 aio_offset;
+  u64 aio_reserved2;
+  u64 aio_reserved3;
+};
+
+struct __sanitizer_io_event {
+  u64 data;
+  u64 obj;
+  u64 res;
+  u64 res2;
+};
+
+const unsigned iocb_cmd_pread = 0;
+const unsigned iocb_cmd_pwrite = 1;
+const unsigned iocb_cmd_preadv = 7;
+const unsigned iocb_cmd_pwritev = 8;
+
+struct __sanitizer___sysctl_args {
+  int *name;
+  int nlen;
+  void *oldval;
+  uptr *oldlenp;
+  void *newval;
+  uptr newlen;
+  unsigned long ___unused[4];
+};
+
+struct __sanitizer_ipc_perm {
+  unsigned int cuid;
+  unsigned int cgid;
+  unsigned int uid;
+  unsigned int gid;
+  unsigned short mode;
+  unsigned short seq;
+  long key;
+};
+
+#if !defined(__i386__)
+typedef long long __sanitizer_time_t;
 #else
-  typedef long __sanitizer_time_t;
+typedef long __sanitizer_time_t;
 #endif
 
-  typedef long __sanitizer_suseconds_t;
-
-  struct __sanitizer_timeval {
-    __sanitizer_time_t tv_sec;
-    __sanitizer_suseconds_t tv_usec;
-  };
-
-  struct __sanitizer_itimerval {
-    struct __sanitizer_timeval it_interval;
-    struct __sanitizer_timeval it_value;
-  };
-
-  struct __sanitizer_timeb {
-    __sanitizer_time_t time;
-    unsigned short millitm;
-    short timezone;
-    short dstflag;
-  };
-
-  struct __sanitizer_ether_addr {
-    u8 octet[6];
-  };
-
-  struct __sanitizer_tm {
-    int tm_sec;
-    int tm_min;
-    int tm_hour;
-    int tm_mday;
-    int tm_mon;
-    int tm_year;
-    int tm_wday;
-    int tm_yday;
-    int tm_isdst;
-    long int tm_gmtoff;
-    const char *tm_zone;
-  };
-
-  struct __sanitizer_msghdr {
-    void *msg_name;
-    unsigned msg_namelen;
-    struct __sanitizer_iovec *msg_iov;
-    unsigned msg_iovlen;
-    void *msg_control;
-    unsigned msg_controllen;
-    int msg_flags;
-  };
-
-  struct __sanitizer_cmsghdr {
-    unsigned cmsg_len;
-    int cmsg_level;
-    int cmsg_type;
-  };
-
-  struct __sanitizer_dirent {
+struct __sanitizer_shmid_ds {
+  __sanitizer_ipc_perm shm_perm;
+  unsigned long shm_segsz;
+  unsigned int shm_lpid;
+  unsigned int shm_cpid;
+  int shm_nattch;
+  __sanitizer_time_t shm_atime;
+  __sanitizer_time_t shm_dtime;
+  __sanitizer_time_t shm_ctime;
+};
+
+extern unsigned struct_msqid_ds_sz;
+extern unsigned struct_mq_attr_sz;
+extern unsigned struct_timeb_sz;
+extern unsigned struct_statvfs_sz;
+
+struct __sanitizer_iovec {
+  void *iov_base;
+  uptr iov_len;
+};
+
+struct __sanitizer_ifaddrs {
+  struct __sanitizer_ifaddrs *ifa_next;
+  char *ifa_name;
+  unsigned int ifa_flags;
+  void *ifa_addr;     // (struct sockaddr *)
+  void *ifa_netmask;  // (struct sockaddr *)
+# undef ifa_dstaddr
+  void *ifa_dstaddr;  // (struct sockaddr *)
+  void *ifa_data;
+};
+
+typedef unsigned __sanitizer_pthread_key_t;
+
+struct __sanitizer_passwd {
+  char *pw_name;
+  char *pw_passwd;
+  int pw_uid;
+  int pw_gid;
+  __sanitizer_time_t pw_change;
+  char *pw_class;
+  char *pw_gecos;
+  char *pw_dir;
+  char *pw_shell;
+  __sanitizer_time_t pw_expire;
+  int pw_fields;
+};
+
+struct __sanitizer_group {
+  char *gr_name;
+  char *gr_passwd;
+  int gr_gid;
+  char **gr_mem;
+};
+
+typedef long __sanitizer_suseconds_t;
+
+struct __sanitizer_timeval {
+  __sanitizer_time_t tv_sec;
+  __sanitizer_suseconds_t tv_usec;
+};
+
+struct __sanitizer_itimerval {
+  struct __sanitizer_timeval it_interval;
+  struct __sanitizer_timeval it_value;
+};
+
+struct __sanitizer_timeb {
+  __sanitizer_time_t time;
+  unsigned short millitm;
+  short timezone;
+  short dstflag;
+};
+
+struct __sanitizer_ether_addr {
+  u8 octet[6];
+};
+
+struct __sanitizer_tm {
+  int tm_sec;
+  int tm_min;
+  int tm_hour;
+  int tm_mday;
+  int tm_mon;
+  int tm_year;
+  int tm_wday;
+  int tm_yday;
+  int tm_isdst;
+  long int tm_gmtoff;
+  const char *tm_zone;
+};
+
+struct __sanitizer_msghdr {
+  void *msg_name;
+  unsigned msg_namelen;
+  struct __sanitizer_iovec *msg_iov;
+  unsigned msg_iovlen;
+  void *msg_control;
+  unsigned msg_controllen;
+  int msg_flags;
+};
+
+struct __sanitizer_cmsghdr {
+  unsigned cmsg_len;
+  int cmsg_level;
+  int cmsg_type;
+};
+
+struct __sanitizer_dirent {
 #if defined(__INO64)
-    unsigned long long d_fileno;
-    unsigned long long d_off;
+  unsigned long long d_fileno;
+  unsigned long long d_off;
 #else
-    unsigned int d_fileno;
+  unsigned int d_fileno;
 #endif
-    unsigned short d_reclen;
-    // more fields that we don't care about
-  };
+  unsigned short d_reclen;
+  // more fields that we don't care about
+};
 
 // 'clock_t' is 32 bits wide on x64 FreeBSD
-  typedef int __sanitizer_clock_t;
-  typedef int __sanitizer_clockid_t;
+typedef int __sanitizer_clock_t;
+typedef int __sanitizer_clockid_t;
 
-#if defined(_LP64) || defined(__x86_64__) || defined(__powerpc__)\
-                   || defined(__mips__)
-  typedef unsigned __sanitizer___kernel_uid_t;
-  typedef unsigned __sanitizer___kernel_gid_t;
+#if defined(_LP64) || defined(__x86_64__) || defined(__powerpc__) || \
+    defined(__mips__)
+typedef unsigned __sanitizer___kernel_uid_t;
+typedef unsigned __sanitizer___kernel_gid_t;
 #else
-  typedef unsigned short __sanitizer___kernel_uid_t;
-  typedef unsigned short __sanitizer___kernel_gid_t;
+typedef unsigned short __sanitizer___kernel_uid_t;
+typedef unsigned short __sanitizer___kernel_gid_t;
 #endif
-  typedef long long __sanitizer___kernel_off_t;
+typedef long long __sanitizer___kernel_off_t;
 
 #if defined(__powerpc__) || defined(__mips__)
-  typedef unsigned int __sanitizer___kernel_old_uid_t;
-  typedef unsigned int __sanitizer___kernel_old_gid_t;
+typedef unsigned int __sanitizer___kernel_old_uid_t;
+typedef unsigned int __sanitizer___kernel_old_gid_t;
 #else
-  typedef unsigned short __sanitizer___kernel_old_uid_t;
-  typedef unsigned short __sanitizer___kernel_old_gid_t;
+typedef unsigned short __sanitizer___kernel_old_uid_t;
+typedef unsigned short __sanitizer___kernel_old_gid_t;
 #endif
 
-  typedef long long __sanitizer___kernel_loff_t;
-  typedef struct {
-    unsigned long fds_bits[1024 / (8 * sizeof(long))];
-  } __sanitizer___kernel_fd_set;
-
-  // This thing depends on the platform. We are only interested in the upper
-  // limit. Verified with a compiler assert in .cpp.
-  const int pthread_attr_t_max_sz = 128;
-  union __sanitizer_pthread_attr_t {
-    char size[pthread_attr_t_max_sz]; // NOLINT
-    void *align;
-  };
-
-  const unsigned old_sigset_t_sz = sizeof(unsigned long);
-
-  struct __sanitizer_sigset_t {
-     // uint32_t * 4
-     unsigned int __bits[4];
-  };
-
-  typedef __sanitizer_sigset_t __sanitizer_kernel_sigset_t;
-
-  struct __sanitizer_siginfo {
-    // The size is determined by looking at sizeof of real siginfo_t on linux.
-    u64 opaque[128 / sizeof(u64)];
-  };
-
-  using __sanitizer_sighandler_ptr = void (*)(int sig);
-  using __sanitizer_sigactionhandler_ptr =
-      void (*)(int sig, __sanitizer_siginfo *siginfo, void *uctx);
-
-  struct __sanitizer_sigaction {
-    union {
-      __sanitizer_sigactionhandler_ptr sigaction;
-      __sanitizer_sighandler_ptr handler;
-    };
-    int sa_flags;
-    __sanitizer_sigset_t sa_mask;
-  };
-
-  struct __sanitizer_sem_t {
-    u32 data[4];
-  };
-
-  extern const uptr sig_ign;
-  extern const uptr sig_dfl;
-  extern const uptr sig_err;
-  extern const uptr sa_siginfo;
-
-  extern int af_inet;
-  extern int af_inet6;
-  uptr __sanitizer_in_addr_sz(int af);
-
-  struct __sanitizer_dl_phdr_info {
-    uptr dlpi_addr;
-    const char *dlpi_name;
-    const void *dlpi_phdr;
-    short dlpi_phnum;
-  };
-
-  extern unsigned struct_ElfW_Phdr_sz;
-
-  struct __sanitizer_addrinfo {
-    int ai_flags;
-    int ai_family;
-    int ai_socktype;
-    int ai_protocol;
-    unsigned ai_addrlen;
-    char *ai_canonname;
-    void *ai_addr;
-    struct __sanitizer_addrinfo *ai_next;
-  };
-
-  struct __sanitizer_hostent {
-    char *h_name;
-    char **h_aliases;
-    int h_addrtype;
-    int h_length;
-    char **h_addr_list;
-  };
-
-  struct __sanitizer_pollfd {
-    int fd;
-    short events;
-    short revents;
-  };
-
-  typedef unsigned __sanitizer_nfds_t;
-
-  struct __sanitizer_glob_t {
-    uptr gl_pathc;
-    uptr gl_matchc;
-    uptr gl_offs;
-    int gl_flags;
-    char **gl_pathv;
-    int (*gl_errfunc)(const char*, int);
-    void (*gl_closedir)(void *dirp);
-    struct dirent *(*gl_readdir)(void *dirp);
-    void *(*gl_opendir)(const char*);
-    int (*gl_lstat)(const char*, void* /* struct stat* */);
-    int (*gl_stat)(const char*, void* /* struct stat* */);
-  };
-
-  extern int glob_nomatch;
-  extern int glob_altdirfunc;
-
-  extern unsigned path_max;
-
-  struct __sanitizer_wordexp_t {
-    uptr we_wordc;
-    char **we_wordv;
-    uptr we_offs;
-    char *we_strings;
-    uptr we_nbytes;
-  };
-
-  typedef void __sanitizer_FILE;
-
-  extern unsigned struct_shminfo_sz;
-  extern unsigned struct_shm_info_sz;
-  extern int shmctl_ipc_stat;
-  extern int shmctl_ipc_info;
-  extern int shmctl_shm_info;
-  extern int shmctl_shm_stat;
-
-  extern unsigned struct_utmpx_sz;
-
-  extern int map_fixed;
-
-  // ioctl arguments
-  struct __sanitizer_ifconf {
-    int ifc_len;
-    union {
-      void *ifcu_req;
-    } ifc_ifcu;
+typedef long long __sanitizer___kernel_loff_t;
+typedef struct {
+  unsigned long fds_bits[1024 / (8 * sizeof(long))];
+} __sanitizer___kernel_fd_set;
+
+// This thing depends on the platform. We are only interested in the upper
+// limit. Verified with a compiler assert in .cpp.
+union __sanitizer_pthread_attr_t {
+  char size[128];
+  void *align;
+};
+
+const unsigned old_sigset_t_sz = sizeof(unsigned long);
+
+struct __sanitizer_sigset_t {
+  // uint32_t * 4
+  unsigned int __bits[4];
+};
+
+typedef __sanitizer_sigset_t __sanitizer_kernel_sigset_t;
+
+struct __sanitizer_siginfo {
+  // The size is determined by looking at sizeof of real siginfo_t on linux.
+  u64 opaque[128 / sizeof(u64)];
+};
+
+using __sanitizer_sighandler_ptr = void (*)(int sig);
+using __sanitizer_sigactionhandler_ptr = void (*)(int sig,
+                                                  __sanitizer_siginfo *siginfo,
+                                                  void *uctx);
+
+struct __sanitizer_sigaction {
+  union {
+    __sanitizer_sigactionhandler_ptr sigaction;
+    __sanitizer_sighandler_ptr handler;
   };
+  int sa_flags;
+  __sanitizer_sigset_t sa_mask;
+};
+
+struct __sanitizer_sem_t {
+  u32 data[4];
+};
+
+extern const uptr sig_ign;
+extern const uptr sig_dfl;
+extern const uptr sig_err;
+extern const uptr sa_siginfo;
+
+extern int af_inet;
+extern int af_inet6;
+uptr __sanitizer_in_addr_sz(int af);
+
+struct __sanitizer_dl_phdr_info {
+  uptr dlpi_addr;
+  const char *dlpi_name;
+  const void *dlpi_phdr;
+  short dlpi_phnum;
+};
+
+extern unsigned struct_ElfW_Phdr_sz;
+
+struct __sanitizer_addrinfo {
+  int ai_flags;
+  int ai_family;
+  int ai_socktype;
+  int ai_protocol;
+  unsigned ai_addrlen;
+  char *ai_canonname;
+  void *ai_addr;
+  struct __sanitizer_addrinfo *ai_next;
+};
+
+struct __sanitizer_hostent {
+  char *h_name;
+  char **h_aliases;
+  int h_addrtype;
+  int h_length;
+  char **h_addr_list;
+};
+
+struct __sanitizer_pollfd {
+  int fd;
+  short events;
+  short revents;
+};
+
+typedef unsigned __sanitizer_nfds_t;
+
+struct __sanitizer_glob_t {
+  uptr gl_pathc;
+  uptr gl_matchc;
+  uptr gl_offs;
+  int gl_flags;
+  char **gl_pathv;
+  int (*gl_errfunc)(const char *, int);
+  void (*gl_closedir)(void *dirp);
+  struct dirent *(*gl_readdir)(void *dirp);
+  void *(*gl_opendir)(const char *);
+  int (*gl_lstat)(const char *, void * /* struct stat* */);
+  int (*gl_stat)(const char *, void * /* struct stat* */);
+};
+
+extern int glob_nomatch;
+extern int glob_altdirfunc;
+
+extern unsigned path_max;
+
+struct __sanitizer_wordexp_t {
+  uptr we_wordc;
+  char **we_wordv;
+  uptr we_offs;
+  char *we_strings;
+  uptr we_nbytes;
+};
+
+typedef void __sanitizer_FILE;
+
+extern unsigned struct_shminfo_sz;
+extern unsigned struct_shm_info_sz;
+extern int shmctl_ipc_stat;
+extern int shmctl_ipc_info;
+extern int shmctl_shm_info;
+extern int shmctl_shm_stat;
+
+extern unsigned struct_utmpx_sz;
+
+extern int map_fixed;
+
+// ioctl arguments
+struct __sanitizer_ifconf {
+  int ifc_len;
+  union {
+    void *ifcu_req;
+  } ifc_ifcu;
+};
 
 #define IOC_NRBITS 8
 #define IOC_TYPEBITS 8
@@ -432,204 +432,204 @@ namespace __sanitizer {
 #define IOC_NR(nr) (((nr) >> IOC_NRSHIFT) & IOC_NRMASK)
 #define IOC_SIZE(nr) (((nr) >> IOC_SIZESHIFT) & IOC_SIZEMASK)
 
-  extern unsigned struct_ifreq_sz;
-  extern unsigned struct_termios_sz;
-  extern unsigned struct_winsize_sz;
-
-  extern unsigned struct_copr_buffer_sz;
-  extern unsigned struct_copr_debug_buf_sz;
-  extern unsigned struct_copr_msg_sz;
-  extern unsigned struct_midi_info_sz;
-  extern unsigned struct_mtget_sz;
-  extern unsigned struct_mtop_sz;
-  extern unsigned struct_rtentry_sz;
-  extern unsigned struct_sbi_instrument_sz;
-  extern unsigned struct_seq_event_rec_sz;
-  extern unsigned struct_synth_info_sz;
-  extern unsigned struct_vt_mode_sz;
-
-  extern const unsigned long __sanitizer_bufsiz;
-  extern unsigned struct_audio_buf_info_sz;
-  extern unsigned struct_ppp_stats_sz;
-  extern unsigned struct_sioc_sg_req_sz;
-  extern unsigned struct_sioc_vif_req_sz;
-
-  // ioctl request identifiers
-
-  // A special value to mark ioctls that are not present on the target platform,
-  // when it can not be determined without including any system headers.
-  extern const unsigned IOCTL_NOT_PRESENT;
-
-  extern unsigned IOCTL_FIOASYNC;
-  extern unsigned IOCTL_FIOCLEX;
-  extern unsigned IOCTL_FIOGETOWN;
-  extern unsigned IOCTL_FIONBIO;
-  extern unsigned IOCTL_FIONCLEX;
-  extern unsigned IOCTL_FIOSETOWN;
-  extern unsigned IOCTL_SIOCADDMULTI;
-  extern unsigned IOCTL_SIOCATMARK;
-  extern unsigned IOCTL_SIOCDELMULTI;
-  extern unsigned IOCTL_SIOCGIFADDR;
-  extern unsigned IOCTL_SIOCGIFBRDADDR;
-  extern unsigned IOCTL_SIOCGIFCONF;
-  extern unsigned IOCTL_SIOCGIFDSTADDR;
-  extern unsigned IOCTL_SIOCGIFFLAGS;
-  extern unsigned IOCTL_SIOCGIFMETRIC;
-  extern unsigned IOCTL_SIOCGIFMTU;
-  extern unsigned IOCTL_SIOCGIFNETMASK;
-  extern unsigned IOCTL_SIOCGPGRP;
-  extern unsigned IOCTL_SIOCSIFADDR;
-  extern unsigned IOCTL_SIOCSIFBRDADDR;
-  extern unsigned IOCTL_SIOCSIFDSTADDR;
-  extern unsigned IOCTL_SIOCSIFFLAGS;
-  extern unsigned IOCTL_SIOCSIFMETRIC;
-  extern unsigned IOCTL_SIOCSIFMTU;
-  extern unsigned IOCTL_SIOCSIFNETMASK;
-  extern unsigned IOCTL_SIOCSPGRP;
-  extern unsigned IOCTL_TIOCCONS;
-  extern unsigned IOCTL_TIOCEXCL;
-  extern unsigned IOCTL_TIOCGETD;
-  extern unsigned IOCTL_TIOCGPGRP;
-  extern unsigned IOCTL_TIOCGWINSZ;
-  extern unsigned IOCTL_TIOCMBIC;
-  extern unsigned IOCTL_TIOCMBIS;
-  extern unsigned IOCTL_TIOCMGET;
-  extern unsigned IOCTL_TIOCMSET;
-  extern unsigned IOCTL_TIOCNOTTY;
-  extern unsigned IOCTL_TIOCNXCL;
-  extern unsigned IOCTL_TIOCOUTQ;
-  extern unsigned IOCTL_TIOCPKT;
-  extern unsigned IOCTL_TIOCSCTTY;
-  extern unsigned IOCTL_TIOCSETD;
-  extern unsigned IOCTL_TIOCSPGRP;
-  extern unsigned IOCTL_TIOCSTI;
-  extern unsigned IOCTL_TIOCSWINSZ;
-  extern unsigned IOCTL_SIOCGETSGCNT;
-  extern unsigned IOCTL_SIOCGETVIFCNT;
-  extern unsigned IOCTL_MTIOCGET;
-  extern unsigned IOCTL_MTIOCTOP;
-  extern unsigned IOCTL_SIOCADDRT;
-  extern unsigned IOCTL_SIOCDELRT;
-  extern unsigned IOCTL_SNDCTL_DSP_GETBLKSIZE;
-  extern unsigned IOCTL_SNDCTL_DSP_GETFMTS;
-  extern unsigned IOCTL_SNDCTL_DSP_NONBLOCK;
-  extern unsigned IOCTL_SNDCTL_DSP_POST;
-  extern unsigned IOCTL_SNDCTL_DSP_RESET;
-  extern unsigned IOCTL_SNDCTL_DSP_SETFMT;
-  extern unsigned IOCTL_SNDCTL_DSP_SETFRAGMENT;
-  extern unsigned IOCTL_SNDCTL_DSP_SPEED;
-  extern unsigned IOCTL_SNDCTL_DSP_STEREO;
-  extern unsigned IOCTL_SNDCTL_DSP_SUBDIVIDE;
-  extern unsigned IOCTL_SNDCTL_DSP_SYNC;
-  extern unsigned IOCTL_SNDCTL_FM_4OP_ENABLE;
-  extern unsigned IOCTL_SNDCTL_FM_LOAD_INSTR;
-  extern unsigned IOCTL_SNDCTL_MIDI_INFO;
-  extern unsigned IOCTL_SNDCTL_MIDI_PRETIME;
-  extern unsigned IOCTL_SNDCTL_SEQ_CTRLRATE;
-  extern unsigned IOCTL_SNDCTL_SEQ_GETINCOUNT;
-  extern unsigned IOCTL_SNDCTL_SEQ_GETOUTCOUNT;
-  extern unsigned IOCTL_SNDCTL_SEQ_NRMIDIS;
-  extern unsigned IOCTL_SNDCTL_SEQ_NRSYNTHS;
-  extern unsigned IOCTL_SNDCTL_SEQ_OUTOFBAND;
-  extern unsigned IOCTL_SNDCTL_SEQ_PANIC;
-  extern unsigned IOCTL_SNDCTL_SEQ_PERCMODE;
-  extern unsigned IOCTL_SNDCTL_SEQ_RESET;
-  extern unsigned IOCTL_SNDCTL_SEQ_RESETSAMPLES;
-  extern unsigned IOCTL_SNDCTL_SEQ_SYNC;
-  extern unsigned IOCTL_SNDCTL_SEQ_TESTMIDI;
-  extern unsigned IOCTL_SNDCTL_SEQ_THRESHOLD;
-  extern unsigned IOCTL_SNDCTL_SYNTH_INFO;
-  extern unsigned IOCTL_SNDCTL_SYNTH_MEMAVL;
-  extern unsigned IOCTL_SNDCTL_TMR_CONTINUE;
-  extern unsigned IOCTL_SNDCTL_TMR_METRONOME;
-  extern unsigned IOCTL_SNDCTL_TMR_SELECT;
-  extern unsigned IOCTL_SNDCTL_TMR_SOURCE;
-  extern unsigned IOCTL_SNDCTL_TMR_START;
-  extern unsigned IOCTL_SNDCTL_TMR_STOP;
-  extern unsigned IOCTL_SNDCTL_TMR_TEMPO;
-  extern unsigned IOCTL_SNDCTL_TMR_TIMEBASE;
-  extern unsigned IOCTL_SOUND_MIXER_READ_ALTPCM;
-  extern unsigned IOCTL_SOUND_MIXER_READ_BASS;
-  extern unsigned IOCTL_SOUND_MIXER_READ_CAPS;
-  extern unsigned IOCTL_SOUND_MIXER_READ_CD;
-  extern unsigned IOCTL_SOUND_MIXER_READ_DEVMASK;
-  extern unsigned IOCTL_SOUND_MIXER_READ_ENHANCE;
-  extern unsigned IOCTL_SOUND_MIXER_READ_IGAIN;
-  extern unsigned IOCTL_SOUND_MIXER_READ_IMIX;
-  extern unsigned IOCTL_SOUND_MIXER_READ_LINE1;
-  extern unsigned IOCTL_SOUND_MIXER_READ_LINE2;
-  extern unsigned IOCTL_SOUND_MIXER_READ_LINE3;
-  extern unsigned IOCTL_SOUND_MIXER_READ_LINE;
-  extern unsigned IOCTL_SOUND_MIXER_READ_LOUD;
-  extern unsigned IOCTL_SOUND_MIXER_READ_MIC;
-  extern unsigned IOCTL_SOUND_MIXER_READ_MUTE;
-  extern unsigned IOCTL_SOUND_MIXER_READ_OGAIN;
-  extern unsigned IOCTL_SOUND_MIXER_READ_PCM;
-  extern unsigned IOCTL_SOUND_MIXER_READ_RECLEV;
-  extern unsigned IOCTL_SOUND_MIXER_READ_RECMASK;
-  extern unsigned IOCTL_SOUND_MIXER_READ_RECSRC;
-  extern unsigned IOCTL_SOUND_MIXER_READ_SPEAKER;
-  extern unsigned IOCTL_SOUND_MIXER_READ_STEREODEVS;
-  extern unsigned IOCTL_SOUND_MIXER_READ_SYNTH;
-  extern unsigned IOCTL_SOUND_MIXER_READ_TREBLE;
-  extern unsigned IOCTL_SOUND_MIXER_READ_VOLUME;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_ALTPCM;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_BASS;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_CD;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_ENHANCE;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_IGAIN;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_IMIX;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_LINE1;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_LINE2;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_LINE3;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_LINE;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_LOUD;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_MIC;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_MUTE;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_OGAIN;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_PCM;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_RECLEV;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_RECSRC;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_SPEAKER;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_SYNTH;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_TREBLE;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_VOLUME;
-  extern unsigned IOCTL_SOUND_PCM_READ_BITS;
-  extern unsigned IOCTL_SOUND_PCM_READ_CHANNELS;
-  extern unsigned IOCTL_SOUND_PCM_READ_FILTER;
-  extern unsigned IOCTL_SOUND_PCM_READ_RATE;
-  extern unsigned IOCTL_SOUND_PCM_WRITE_CHANNELS;
-  extern unsigned IOCTL_SOUND_PCM_WRITE_FILTER;
-  extern unsigned IOCTL_VT_ACTIVATE;
-  extern unsigned IOCTL_VT_GETMODE;
-  extern unsigned IOCTL_VT_OPENQRY;
-  extern unsigned IOCTL_VT_RELDISP;
-  extern unsigned IOCTL_VT_SETMODE;
-  extern unsigned IOCTL_VT_WAITACTIVE;
-  extern unsigned IOCTL_GIO_SCRNMAP;
-  extern unsigned IOCTL_KDDISABIO;
-  extern unsigned IOCTL_KDENABIO;
-  extern unsigned IOCTL_KDGETLED;
-  extern unsigned IOCTL_KDGETMODE;
-  extern unsigned IOCTL_KDGKBMODE;
-  extern unsigned IOCTL_KDGKBTYPE;
-  extern unsigned IOCTL_KDMKTONE;
-  extern unsigned IOCTL_KDSETLED;
-  extern unsigned IOCTL_KDSETMODE;
-  extern unsigned IOCTL_KDSKBMODE;
-
-  extern const int si_SEGV_MAPERR;
-  extern const int si_SEGV_ACCERR;
-
-  struct __sanitizer_cap_rights {
-    u64 cr_rights[2];
-  };
-
-  typedef struct __sanitizer_cap_rights __sanitizer_cap_rights_t;
-  extern unsigned struct_cap_rights_sz;
-
-  extern unsigned struct_fstab_sz;
-  extern unsigned struct_StringList_sz;
+extern unsigned struct_ifreq_sz;
+extern unsigned struct_termios_sz;
+extern unsigned struct_winsize_sz;
+
+extern unsigned struct_copr_buffer_sz;
+extern unsigned struct_copr_debug_buf_sz;
+extern unsigned struct_copr_msg_sz;
+extern unsigned struct_midi_info_sz;
+extern unsigned struct_mtget_sz;
+extern unsigned struct_mtop_sz;
+extern unsigned struct_rtentry_sz;
+extern unsigned struct_sbi_instrument_sz;
+extern unsigned struct_seq_event_rec_sz;
+extern unsigned struct_synth_info_sz;
+extern unsigned struct_vt_mode_sz;
+
+extern const unsigned long __sanitizer_bufsiz;
+extern unsigned struct_audio_buf_info_sz;
+extern unsigned struct_ppp_stats_sz;
+extern unsigned struct_sioc_sg_req_sz;
+extern unsigned struct_sioc_vif_req_sz;
+
+// ioctl request identifiers
+
+// A special value to mark ioctls that are not present on the target platform,
+// when it can not be determined without including any system headers.
+extern const unsigned IOCTL_NOT_PRESENT;
+
+extern unsigned IOCTL_FIOASYNC;
+extern unsigned IOCTL_FIOCLEX;
+extern unsigned IOCTL_FIOGETOWN;
+extern unsigned IOCTL_FIONBIO;
+extern unsigned IOCTL_FIONCLEX;
+extern unsigned IOCTL_FIOSETOWN;
+extern unsigned IOCTL_SIOCADDMULTI;
+extern unsigned IOCTL_SIOCATMARK;
+extern unsigned IOCTL_SIOCDELMULTI;
+extern unsigned IOCTL_SIOCGIFADDR;
+extern unsigned IOCTL_SIOCGIFBRDADDR;
+extern unsigned IOCTL_SIOCGIFCONF;
+extern unsigned IOCTL_SIOCGIFDSTADDR;
+extern unsigned IOCTL_SIOCGIFFLAGS;
+extern unsigned IOCTL_SIOCGIFMETRIC;
+extern unsigned IOCTL_SIOCGIFMTU;
+extern unsigned IOCTL_SIOCGIFNETMASK;
+extern unsigned IOCTL_SIOCGPGRP;
+extern unsigned IOCTL_SIOCSIFADDR;
+extern unsigned IOCTL_SIOCSIFBRDADDR;
+extern unsigned IOCTL_SIOCSIFDSTADDR;
+extern unsigned IOCTL_SIOCSIFFLAGS;
+extern unsigned IOCTL_SIOCSIFMETRIC;
+extern unsigned IOCTL_SIOCSIFMTU;
+extern unsigned IOCTL_SIOCSIFNETMASK;
+extern unsigned IOCTL_SIOCSPGRP;
+extern unsigned IOCTL_TIOCCONS;
+extern unsigned IOCTL_TIOCEXCL;
+extern unsigned IOCTL_TIOCGETD;
+extern unsigned IOCTL_TIOCGPGRP;
+extern unsigned IOCTL_TIOCGWINSZ;
+extern unsigned IOCTL_TIOCMBIC;
+extern unsigned IOCTL_TIOCMBIS;
+extern unsigned IOCTL_TIOCMGET;
+extern unsigned IOCTL_TIOCMSET;
+extern unsigned IOCTL_TIOCNOTTY;
+extern unsigned IOCTL_TIOCNXCL;
+extern unsigned IOCTL_TIOCOUTQ;
+extern unsigned IOCTL_TIOCPKT;
+extern unsigned IOCTL_TIOCSCTTY;
+extern unsigned IOCTL_TIOCSETD;
+extern unsigned IOCTL_TIOCSPGRP;
+extern unsigned IOCTL_TIOCSTI;
+extern unsigned IOCTL_TIOCSWINSZ;
+extern unsigned IOCTL_SIOCGETSGCNT;
+extern unsigned IOCTL_SIOCGETVIFCNT;
+extern unsigned IOCTL_MTIOCGET;
+extern unsigned IOCTL_MTIOCTOP;
+extern unsigned IOCTL_SIOCADDRT;
+extern unsigned IOCTL_SIOCDELRT;
+extern unsigned IOCTL_SNDCTL_DSP_GETBLKSIZE;
+extern unsigned IOCTL_SNDCTL_DSP_GETFMTS;
+extern unsigned IOCTL_SNDCTL_DSP_NONBLOCK;
+extern unsigned IOCTL_SNDCTL_DSP_POST;
+extern unsigned IOCTL_SNDCTL_DSP_RESET;
+extern unsigned IOCTL_SNDCTL_DSP_SETFMT;
+extern unsigned IOCTL_SNDCTL_DSP_SETFRAGMENT;
+extern unsigned IOCTL_SNDCTL_DSP_SPEED;
+extern unsigned IOCTL_SNDCTL_DSP_STEREO;
+extern unsigned IOCTL_SNDCTL_DSP_SUBDIVIDE;
+extern unsigned IOCTL_SNDCTL_DSP_SYNC;
+extern unsigned IOCTL_SNDCTL_FM_4OP_ENABLE;
+extern unsigned IOCTL_SNDCTL_FM_LOAD_INSTR;
+extern unsigned IOCTL_SNDCTL_MIDI_INFO;
+extern unsigned IOCTL_SNDCTL_MIDI_PRETIME;
+extern unsigned IOCTL_SNDCTL_SEQ_CTRLRATE;
+extern unsigned IOCTL_SNDCTL_SEQ_GETINCOUNT;
+extern unsigned IOCTL_SNDCTL_SEQ_GETOUTCOUNT;
+extern unsigned IOCTL_SNDCTL_SEQ_NRMIDIS;
+extern unsigned IOCTL_SNDCTL_SEQ_NRSYNTHS;
+extern unsigned IOCTL_SNDCTL_SEQ_OUTOFBAND;
+extern unsigned IOCTL_SNDCTL_SEQ_PANIC;
+extern unsigned IOCTL_SNDCTL_SEQ_PERCMODE;
+extern unsigned IOCTL_SNDCTL_SEQ_RESET;
+extern unsigned IOCTL_SNDCTL_SEQ_RESETSAMPLES;
+extern unsigned IOCTL_SNDCTL_SEQ_SYNC;
+extern unsigned IOCTL_SNDCTL_SEQ_TESTMIDI;
+extern unsigned IOCTL_SNDCTL_SEQ_THRESHOLD;
+extern unsigned IOCTL_SNDCTL_SYNTH_INFO;
+extern unsigned IOCTL_SNDCTL_SYNTH_MEMAVL;
+extern unsigned IOCTL_SNDCTL_TMR_CONTINUE;
+extern unsigned IOCTL_SNDCTL_TMR_METRONOME;
+extern unsigned IOCTL_SNDCTL_TMR_SELECT;
+extern unsigned IOCTL_SNDCTL_TMR_SOURCE;
+extern unsigned IOCTL_SNDCTL_TMR_START;
+extern unsigned IOCTL_SNDCTL_TMR_STOP;
+extern unsigned IOCTL_SNDCTL_TMR_TEMPO;
+extern unsigned IOCTL_SNDCTL_TMR_TIMEBASE;
+extern unsigned IOCTL_SOUND_MIXER_READ_ALTPCM;
+extern unsigned IOCTL_SOUND_MIXER_READ_BASS;
+extern unsigned IOCTL_SOUND_MIXER_READ_CAPS;
+extern unsigned IOCTL_SOUND_MIXER_READ_CD;
+extern unsigned IOCTL_SOUND_MIXER_READ_DEVMASK;
+extern unsigned IOCTL_SOUND_MIXER_READ_ENHANCE;
+extern unsigned IOCTL_SOUND_MIXER_READ_IGAIN;
+extern unsigned IOCTL_SOUND_MIXER_READ_IMIX;
+extern unsigned IOCTL_SOUND_MIXER_READ_LINE1;
+extern unsigned IOCTL_SOUND_MIXER_READ_LINE2;
+extern unsigned IOCTL_SOUND_MIXER_READ_LINE3;
+extern unsigned IOCTL_SOUND_MIXER_READ_LINE;
+extern unsigned IOCTL_SOUND_MIXER_READ_LOUD;
+extern unsigned IOCTL_SOUND_MIXER_READ_MIC;
+extern unsigned IOCTL_SOUND_MIXER_READ_MUTE;
+extern unsigned IOCTL_SOUND_MIXER_READ_OGAIN;
+extern unsigned IOCTL_SOUND_MIXER_READ_PCM;
+extern unsigned IOCTL_SOUND_MIXER_READ_RECLEV;
+extern unsigned IOCTL_SOUND_MIXER_READ_RECMASK;
+extern unsigned IOCTL_SOUND_MIXER_READ_RECSRC;
+extern unsigned IOCTL_SOUND_MIXER_READ_SPEAKER;
+extern unsigned IOCTL_SOUND_MIXER_READ_STEREODEVS;
+extern unsigned IOCTL_SOUND_MIXER_READ_SYNTH;
+extern unsigned IOCTL_SOUND_MIXER_READ_TREBLE;
+extern unsigned IOCTL_SOUND_MIXER_READ_VOLUME;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_ALTPCM;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_BASS;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_CD;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_ENHANCE;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_IGAIN;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_IMIX;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_LINE1;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_LINE2;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_LINE3;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_LINE;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_LOUD;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_MIC;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_MUTE;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_OGAIN;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_PCM;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_RECLEV;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_RECSRC;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_SPEAKER;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_SYNTH;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_TREBLE;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_VOLUME;
+extern unsigned IOCTL_SOUND_PCM_READ_BITS;
+extern unsigned IOCTL_SOUND_PCM_READ_CHANNELS;
+extern unsigned IOCTL_SOUND_PCM_READ_FILTER;
+extern unsigned IOCTL_SOUND_PCM_READ_RATE;
+extern unsigned IOCTL_SOUND_PCM_WRITE_CHANNELS;
+extern unsigned IOCTL_SOUND_PCM_WRITE_FILTER;
+extern unsigned IOCTL_VT_ACTIVATE;
+extern unsigned IOCTL_VT_GETMODE;
+extern unsigned IOCTL_VT_OPENQRY;
+extern unsigned IOCTL_VT_RELDISP;
+extern unsigned IOCTL_VT_SETMODE;
+extern unsigned IOCTL_VT_WAITACTIVE;
+extern unsigned IOCTL_GIO_SCRNMAP;
+extern unsigned IOCTL_KDDISABIO;
+extern unsigned IOCTL_KDENABIO;
+extern unsigned IOCTL_KDGETLED;
+extern unsigned IOCTL_KDGETMODE;
+extern unsigned IOCTL_KDGKBMODE;
+extern unsigned IOCTL_KDGKBTYPE;
+extern unsigned IOCTL_KDMKTONE;
+extern unsigned IOCTL_KDSETLED;
+extern unsigned IOCTL_KDSETMODE;
+extern unsigned IOCTL_KDSKBMODE;
+
+extern const int si_SEGV_MAPERR;
+extern const int si_SEGV_ACCERR;
+
+struct __sanitizer_cap_rights {
+  u64 cr_rights[2];
+};
+
+typedef struct __sanitizer_cap_rights __sanitizer_cap_rights_t;
+extern unsigned struct_cap_rights_sz;
+
+extern unsigned struct_fstab_sz;
+extern unsigned struct_StringList_sz;
 } // namespace __sanitizer
 
 #define CHECK_TYPE_SIZE(TYPE) \
index 7c1a21d6ccb322a9e4016ea5decc6b4b68937865..842bc789f4793117134a82a7fe18a8cc60dbf5ce 100644 (file)
 
 // With old kernels (and even new kernels on powerpc) asm/stat.h uses types that
 // are not defined anywhere in userspace headers. Fake them. This seems to work
-// fine with newer headers, too.  Beware that with <sys/stat.h>, struct stat
-// takes the form of struct stat64 on 32-bit platforms if _FILE_OFFSET_BITS=64.
-// Also, for some platforms (e.g. mips) there are additional members in the
-// <sys/stat.h> struct stat:s.
+// fine with newer headers, too.
 #include <linux/posix_types.h>
-#if defined(__x86_64__)
+#if defined(__x86_64__) ||  defined(__mips__)
 #include <sys/stat.h>
 #else
 #define ino_t __kernel_ino_t
index 1e3c7feff8bad2b3ffc7a93490b15a33124ba77e..9852e6ba78794ea81958bbdfad8625e3dd67f477 100644 (file)
 #ifdef _FILE_OFFSET_BITS
 #undef _FILE_OFFSET_BITS
 #endif
+
+// Must go after undef _FILE_OFFSET_BITS.
+#include "sanitizer_glibc_version.h"
+
 #include <arpa/inet.h>
 #include <dirent.h>
 #include <grp.h>
@@ -136,6 +140,7 @@ typedef struct user_fpregs elf_fpregset_t;
 #include <linux/serial.h>
 #include <sys/msg.h>
 #include <sys/ipc.h>
+#include <crypt.h>
 #endif // SANITIZER_LINUX && !SANITIZER_ANDROID
 
 #if SANITIZER_ANDROID
@@ -236,6 +241,7 @@ namespace __sanitizer {
   unsigned struct_ustat_sz = SIZEOF_STRUCT_USTAT;
   unsigned struct_rlimit64_sz = sizeof(struct rlimit64);
   unsigned struct_statvfs64_sz = sizeof(struct statvfs64);
+  unsigned struct_crypt_data_sz = sizeof(struct crypt_data);
 #endif // SANITIZER_LINUX && !SANITIZER_ANDROID
 
 #if SANITIZER_LINUX && !SANITIZER_ANDROID
@@ -1005,10 +1011,6 @@ CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_len);
 CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_level);
 CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_type);
 
-#ifndef __GLIBC_PREREQ
-#define __GLIBC_PREREQ(x, y) 0
-#endif
-
 #if SANITIZER_LINUX && (__ANDROID_API__ >= 21 || __GLIBC_PREREQ (2, 14))
 CHECK_TYPE_SIZE(mmsghdr);
 CHECK_SIZE_AND_OFFSET(mmsghdr, msg_hdr);
@@ -1129,9 +1131,8 @@ CHECK_SIZE_AND_OFFSET(ipc_perm, cgid);
 #if (!defined(__aarch64__) || !SANITIZER_LINUX || __GLIBC_PREREQ (2, 21)) && \
     !defined(__arm__)
 /* On aarch64 glibc 2.20 and earlier provided incorrect mode field.  */
-/* On Arm glibc 2.31 and later provide a different mode field, this field is
-   never used by libsanitizer so we can simply ignore this assert for all glibc
-   versions.  */
+/* On Arm newer glibc provide a different mode field, it's hard to detect
+   so just disable the check.  */
 CHECK_SIZE_AND_OFFSET(ipc_perm, mode);
 #endif
 
index f2d4812059bcfb89ac4fa2e1570a4a4a9bc25589..db2c4f07b3ae4f91f3549f4e695a8304e89369d8 100644 (file)
 #include "sanitizer_internal_defs.h"
 #include "sanitizer_platform.h"
 
-# define GET_LINK_MAP_BY_DLOPEN_HANDLE(handle) ((link_map*)(handle))
-
-#ifndef __GLIBC_PREREQ
-#define __GLIBC_PREREQ(x, y) 0
+#if defined(__sparc__)
+// FIXME: This can't be included from tsan which does not support sparc yet.
+#include "sanitizer_glibc_version.h"
 #endif
 
+# define GET_LINK_MAP_BY_DLOPEN_HANDLE(handle) ((link_map*)(handle))
+
 namespace __sanitizer {
-  extern unsigned struct_utsname_sz;
-  extern unsigned struct_stat_sz;
+extern unsigned struct_utsname_sz;
+extern unsigned struct_stat_sz;
 #if !SANITIZER_IOS
-  extern unsigned struct_stat64_sz;
-#endif
-  extern unsigned struct_rusage_sz;
-  extern unsigned siginfo_t_sz;
-  extern unsigned struct_itimerval_sz;
-  extern unsigned pthread_t_sz;
-  extern unsigned pthread_mutex_t_sz;
-  extern unsigned pthread_cond_t_sz;
-  extern unsigned pid_t_sz;
-  extern unsigned timeval_sz;
-  extern unsigned uid_t_sz;
-  extern unsigned gid_t_sz;
-  extern unsigned mbstate_t_sz;
-  extern unsigned struct_timezone_sz;
-  extern unsigned struct_tms_sz;
-  extern unsigned struct_itimerspec_sz;
-  extern unsigned struct_sigevent_sz;
-  extern unsigned struct_sched_param_sz;
-  extern unsigned struct_statfs64_sz;
-  extern unsigned struct_regex_sz;
-  extern unsigned struct_regmatch_sz;
+extern unsigned struct_stat64_sz;
+#endif
+extern unsigned struct_rusage_sz;
+extern unsigned siginfo_t_sz;
+extern unsigned struct_itimerval_sz;
+extern unsigned pthread_t_sz;
+extern unsigned pthread_mutex_t_sz;
+extern unsigned pthread_cond_t_sz;
+extern unsigned pid_t_sz;
+extern unsigned timeval_sz;
+extern unsigned uid_t_sz;
+extern unsigned gid_t_sz;
+extern unsigned mbstate_t_sz;
+extern unsigned struct_timezone_sz;
+extern unsigned struct_tms_sz;
+extern unsigned struct_itimerspec_sz;
+extern unsigned struct_sigevent_sz;
+extern unsigned struct_sched_param_sz;
+extern unsigned struct_statfs64_sz;
+extern unsigned struct_regex_sz;
+extern unsigned struct_regmatch_sz;
 
 #if !SANITIZER_ANDROID
-  extern unsigned struct_fstab_sz;
-  extern unsigned struct_statfs_sz;
-  extern unsigned struct_sockaddr_sz;
-  extern unsigned ucontext_t_sz;
+extern unsigned struct_fstab_sz;
+extern unsigned struct_statfs_sz;
+extern unsigned struct_sockaddr_sz;
+extern unsigned ucontext_t_sz;
 #endif // !SANITIZER_ANDROID
 
 #if SANITIZER_LINUX
 
 #if defined(__x86_64__)
-  const unsigned struct_kernel_stat_sz = 144;
-  const unsigned struct_kernel_stat64_sz = 0;
+const unsigned struct_kernel_stat_sz = 144;
+const unsigned struct_kernel_stat64_sz = 0;
 #elif defined(__i386__)
-  const unsigned struct_kernel_stat_sz = 64;
-  const unsigned struct_kernel_stat64_sz = 96;
+const unsigned struct_kernel_stat_sz = 64;
+const unsigned struct_kernel_stat64_sz = 96;
 #elif defined(__arm__)
-  const unsigned struct_kernel_stat_sz = 64;
-  const unsigned struct_kernel_stat64_sz = 104;
+const unsigned struct_kernel_stat_sz = 64;
+const unsigned struct_kernel_stat64_sz = 104;
 #elif defined(__aarch64__)
-  const unsigned struct_kernel_stat_sz = 128;
-  const unsigned struct_kernel_stat64_sz = 104;
+const unsigned struct_kernel_stat_sz = 128;
+const unsigned struct_kernel_stat64_sz = 104;
 #elif defined(__powerpc__) && !defined(__powerpc64__)
-  const unsigned struct_kernel_stat_sz = 72;
-  const unsigned struct_kernel_stat64_sz = 104;
+const unsigned struct_kernel_stat_sz = 72;
+const unsigned struct_kernel_stat64_sz = 104;
 #elif defined(__powerpc64__)
-  const unsigned struct_kernel_stat_sz = 144;
-  const unsigned struct_kernel_stat64_sz = 104;
+const unsigned struct_kernel_stat_sz = 144;
+const unsigned struct_kernel_stat64_sz = 104;
 #elif defined(__mips__)
-  const unsigned struct_kernel_stat_sz =
-                 SANITIZER_ANDROID ? FIRST_32_SECOND_64(104, 128) :
-                                     FIRST_32_SECOND_64(144, 216);
-  const unsigned struct_kernel_stat64_sz = 104;
+const unsigned struct_kernel_stat_sz = SANITIZER_ANDROID
+                                           ? FIRST_32_SECOND_64(104, 128)
+                                           : FIRST_32_SECOND_64(160, 216);
+const unsigned struct_kernel_stat64_sz = 104;
 #elif defined(__s390__) && !defined(__s390x__)
-  const unsigned struct_kernel_stat_sz = 64;
-  const unsigned struct_kernel_stat64_sz = 104;
+const unsigned struct_kernel_stat_sz = 64;
+const unsigned struct_kernel_stat64_sz = 104;
 #elif defined(__s390x__)
-  const unsigned struct_kernel_stat_sz = 144;
-  const unsigned struct_kernel_stat64_sz = 0;
+const unsigned struct_kernel_stat_sz = 144;
+const unsigned struct_kernel_stat64_sz = 0;
 #elif defined(__sparc__) && defined(__arch64__)
-  const unsigned struct___old_kernel_stat_sz = 0;
-  const unsigned struct_kernel_stat_sz = 104;
-  const unsigned struct_kernel_stat64_sz = 144;
+const unsigned struct___old_kernel_stat_sz = 0;
+const unsigned struct_kernel_stat_sz = 104;
+const unsigned struct_kernel_stat64_sz = 144;
 #elif defined(__sparc__) && !defined(__arch64__)
-  const unsigned struct___old_kernel_stat_sz = 0;
-  const unsigned struct_kernel_stat_sz = 64;
-  const unsigned struct_kernel_stat64_sz = 104;
-#endif
-  struct __sanitizer_perf_event_attr {
-    unsigned type;
-    unsigned size;
-    // More fields that vary with the kernel version.
-  };
+const unsigned struct___old_kernel_stat_sz = 0;
+const unsigned struct_kernel_stat_sz = 64;
+const unsigned struct_kernel_stat64_sz = 104;
+#endif
+struct __sanitizer_perf_event_attr {
+  unsigned type;
+  unsigned size;
+  // More fields that vary with the kernel version.
+};
 
-  extern unsigned struct_epoll_event_sz;
-  extern unsigned struct_sysinfo_sz;
-  extern unsigned __user_cap_header_struct_sz;
-  extern unsigned __user_cap_data_struct_sz;
-  extern unsigned struct_new_utsname_sz;
-  extern unsigned struct_old_utsname_sz;
-  extern unsigned struct_oldold_utsname_sz;
+extern unsigned struct_epoll_event_sz;
+extern unsigned struct_sysinfo_sz;
+extern unsigned __user_cap_header_struct_sz;
+extern unsigned __user_cap_data_struct_sz;
+extern unsigned struct_new_utsname_sz;
+extern unsigned struct_old_utsname_sz;
+extern unsigned struct_oldold_utsname_sz;
 
-  const unsigned struct_kexec_segment_sz = 4 * sizeof(unsigned long);
+const unsigned struct_kexec_segment_sz = 4 * sizeof(unsigned long);
 #endif  // SANITIZER_LINUX
 
 #if SANITIZER_LINUX
 
 #if defined(__powerpc64__) || defined(__s390__)
-  const unsigned struct___old_kernel_stat_sz = 0;
+const unsigned struct___old_kernel_stat_sz = 0;
 #elif !defined(__sparc__)
-  const unsigned struct___old_kernel_stat_sz = 32;
-#endif
-
-  extern unsigned struct_rlimit_sz;
-  extern unsigned struct_utimbuf_sz;
-  extern unsigned struct_timespec_sz;
-
-  struct __sanitizer_iocb {
-    u64   aio_data;
-    u32   aio_key_or_aio_reserved1; // Simply crazy.
-    u32   aio_reserved1_or_aio_key; // Luckily, we don't need these.
-    u16   aio_lio_opcode;
-    s16   aio_reqprio;
-    u32   aio_fildes;
-    u64   aio_buf;
-    u64   aio_nbytes;
-    s64   aio_offset;
-    u64   aio_reserved2;
-    u64   aio_reserved3;
-  };
+const unsigned struct___old_kernel_stat_sz = 32;
+#endif
 
-  struct __sanitizer_io_event {
-    u64 data;
-    u64 obj;
-    u64 res;
-    u64 res2;
-  };
+extern unsigned struct_rlimit_sz;
+extern unsigned struct_utimbuf_sz;
+extern unsigned struct_timespec_sz;
+
+struct __sanitizer_iocb {
+  u64 aio_data;
+  u32 aio_key_or_aio_reserved1;  // Simply crazy.
+  u32 aio_reserved1_or_aio_key;  // Luckily, we don't need these.
+  u16 aio_lio_opcode;
+  s16 aio_reqprio;
+  u32 aio_fildes;
+  u64 aio_buf;
+  u64 aio_nbytes;
+  s64 aio_offset;
+  u64 aio_reserved2;
+  u64 aio_reserved3;
+};
 
-  const unsigned iocb_cmd_pread = 0;
-  const unsigned iocb_cmd_pwrite = 1;
-  const unsigned iocb_cmd_preadv = 7;
-  const unsigned iocb_cmd_pwritev = 8;
-
-  struct __sanitizer___sysctl_args {
-    int *name;
-    int nlen;
-    void *oldval;
-    uptr *oldlenp;
-    void *newval;
-    uptr newlen;
-    unsigned long ___unused[4];
-  };
+struct __sanitizer_io_event {
+  u64 data;
+  u64 obj;
+  u64 res;
+  u64 res2;
+};
 
-  const unsigned old_sigset_t_sz = sizeof(unsigned long);
+const unsigned iocb_cmd_pread = 0;
+const unsigned iocb_cmd_pwrite = 1;
+const unsigned iocb_cmd_preadv = 7;
+const unsigned iocb_cmd_pwritev = 8;
+
+struct __sanitizer___sysctl_args {
+  int *name;
+  int nlen;
+  void *oldval;
+  uptr *oldlenp;
+  void *newval;
+  uptr newlen;
+  unsigned long ___unused[4];
+};
 
-  struct __sanitizer_sem_t {
+const unsigned old_sigset_t_sz = sizeof(unsigned long);
+
+struct __sanitizer_sem_t {
 #if SANITIZER_ANDROID && defined(_LP64)
-    int data[4];
+  int data[4];
 #elif SANITIZER_ANDROID && !defined(_LP64)
-    int data;
+  int data;
 #elif SANITIZER_LINUX
-    uptr data[4];
+  uptr data[4];
 #endif
-  };
+};
 #endif // SANITIZER_LINUX
 
 #if SANITIZER_ANDROID
-  struct __sanitizer_struct_mallinfo {
-    uptr v[10];
-  };
+struct __sanitizer_struct_mallinfo {
+  uptr v[10];
+};
 #endif
 
 #if SANITIZER_LINUX && !SANITIZER_ANDROID
-  struct __sanitizer_struct_mallinfo {
-    int v[10];
-  };
+struct __sanitizer_struct_mallinfo {
+  int v[10];
+};
 
-  extern unsigned struct_ustat_sz;
-  extern unsigned struct_rlimit64_sz;
-  extern unsigned struct_statvfs64_sz;
+extern unsigned struct_ustat_sz;
+extern unsigned struct_rlimit64_sz;
+extern unsigned struct_statvfs64_sz;
 
-  struct __sanitizer_ipc_perm {
-    int __key;
-    int uid;
-    int gid;
-    int cuid;
-    int cgid;
+struct __sanitizer_ipc_perm {
+  int __key;
+  int uid;
+  int gid;
+  int cuid;
+  int cgid;
 #ifdef __powerpc__
-    unsigned mode;
-    unsigned __seq;
-    u64 __unused1;
-    u64 __unused2;
+  unsigned mode;
+  unsigned __seq;
+  u64 __unused1;
+  u64 __unused2;
 #elif defined(__sparc__)
 #if defined(__arch64__)
-    unsigned mode;
-    unsigned short __pad1;
+  unsigned mode;
+  unsigned short __pad1;
 #else
-    unsigned short __pad1;
-    unsigned short mode;
-    unsigned short __pad2;
+  unsigned short __pad1;
+  unsigned short mode;
+  unsigned short __pad2;
 #endif
-    unsigned short __seq;
-    unsigned long long __unused1;
-    unsigned long long __unused2;
+  unsigned short __seq;
+  unsigned long long __unused1;
+  unsigned long long __unused2;
 #elif defined(__mips__) || defined(__aarch64__) || defined(__s390x__)
-    unsigned int mode;
-    unsigned short __seq;
-    unsigned short __pad1;
-    unsigned long __unused1;
-    unsigned long __unused2;
+  unsigned int mode;
+  unsigned short __seq;
+  unsigned short __pad1;
+  unsigned long __unused1;
+  unsigned long __unused2;
 #else
-    unsigned short mode;
-    unsigned short __pad1;
-    unsigned short __seq;
-    unsigned short __pad2;
+  unsigned short mode;
+  unsigned short __pad1;
+  unsigned short __seq;
+  unsigned short __pad2;
 #if defined(__x86_64__) && !defined(_LP64)
-    u64 __unused1;
-    u64 __unused2;
+  u64 __unused1;
+  u64 __unused2;
 #else
-    unsigned long __unused1;
-    unsigned long __unused2;
+  unsigned long __unused1;
+  unsigned long __unused2;
 #endif
 #endif
-  };
+};
 
-  struct __sanitizer_shmid_ds {
-    __sanitizer_ipc_perm shm_perm;
-  #if defined(__sparc__)
-  #if !defined(__arch64__)
-    u32 __pad1;
-  #endif
-    long shm_atime;
-  #if !defined(__arch64__)
-    u32 __pad2;
-  #endif
-    long shm_dtime;
-  #if !defined(__arch64__)
-    u32 __pad3;
-  #endif
-    long shm_ctime;
-    uptr shm_segsz;
-    int shm_cpid;
-    int shm_lpid;
-    unsigned long shm_nattch;
-    unsigned long __glibc_reserved1;
-    unsigned long __glibc_reserved2;
-  #else
-  #ifndef __powerpc__
-    uptr shm_segsz;
-  #elif !defined(__powerpc64__)
-    uptr __unused0;
-  #endif
-  #if defined(__x86_64__) && !defined(_LP64)
-    u64 shm_atime;
-    u64 shm_dtime;
-    u64 shm_ctime;
-  #else
-    uptr shm_atime;
-  #if !defined(_LP64) && !defined(__mips__)
-    uptr __unused1;
-  #endif
-    uptr shm_dtime;
-  #if !defined(_LP64) && !defined(__mips__)
-    uptr __unused2;
-  #endif
-    uptr shm_ctime;
-  #if !defined(_LP64) && !defined(__mips__)
-    uptr __unused3;
-  #endif
-  #endif
-  #ifdef __powerpc__
-    uptr shm_segsz;
-  #endif
-    int shm_cpid;
-    int shm_lpid;
-  #if defined(__x86_64__) && !defined(_LP64)
-    u64 shm_nattch;
-    u64 __unused4;
-    u64 __unused5;
-  #else
-    uptr shm_nattch;
-    uptr __unused4;
-    uptr __unused5;
-  #endif
+struct __sanitizer_shmid_ds {
+  __sanitizer_ipc_perm shm_perm;
+#if defined(__sparc__)
+#if !defined(__arch64__)
+  u32 __pad1;
 #endif
-  };
+  long shm_atime;
+#if !defined(__arch64__)
+  u32 __pad2;
+#endif
+  long shm_dtime;
+#if !defined(__arch64__)
+  u32 __pad3;
+#endif
+  long shm_ctime;
+  uptr shm_segsz;
+  int shm_cpid;
+  int shm_lpid;
+  unsigned long shm_nattch;
+  unsigned long __glibc_reserved1;
+  unsigned long __glibc_reserved2;
+#else
+#ifndef __powerpc__
+  uptr shm_segsz;
+#elif !defined(__powerpc64__)
+  uptr __unused0;
+#endif
+#if defined(__x86_64__) && !defined(_LP64)
+  u64 shm_atime;
+  u64 shm_dtime;
+  u64 shm_ctime;
+#else
+  uptr shm_atime;
+#if !defined(_LP64) && !defined(__mips__)
+  uptr __unused1;
+#endif
+  uptr shm_dtime;
+#if !defined(_LP64) && !defined(__mips__)
+  uptr __unused2;
+#endif
+  uptr shm_ctime;
+#if !defined(_LP64) && !defined(__mips__)
+  uptr __unused3;
+#endif
+#endif
+#ifdef __powerpc__
+  uptr shm_segsz;
+#endif
+  int shm_cpid;
+  int shm_lpid;
+#if defined(__x86_64__) && !defined(_LP64)
+  u64 shm_nattch;
+  u64 __unused4;
+  u64 __unused5;
+#else
+  uptr shm_nattch;
+  uptr __unused4;
+  uptr __unused5;
+#endif
+#endif
+};
 #endif
 
 #if SANITIZER_LINUX && !SANITIZER_ANDROID
-  extern unsigned struct_msqid_ds_sz;
-  extern unsigned struct_mq_attr_sz;
-  extern unsigned struct_timex_sz;
-  extern unsigned struct_statvfs_sz;
+extern unsigned struct_msqid_ds_sz;
+extern unsigned struct_mq_attr_sz;
+extern unsigned struct_timex_sz;
+extern unsigned struct_statvfs_sz;
+extern unsigned struct_crypt_data_sz;
 #endif  // SANITIZER_LINUX && !SANITIZER_ANDROID
 
-  struct __sanitizer_iovec {
-    void *iov_base;
-    uptr iov_len;
-  };
+struct __sanitizer_iovec {
+  void *iov_base;
+  uptr iov_len;
+};
 
 #if !SANITIZER_ANDROID
-  struct __sanitizer_ifaddrs {
-    struct __sanitizer_ifaddrs *ifa_next;
-    char *ifa_name;
-    unsigned int ifa_flags;
-    void *ifa_addr;    // (struct sockaddr *)
-    void *ifa_netmask; // (struct sockaddr *)
-    // This is a union on Linux.
+struct __sanitizer_ifaddrs {
+  struct __sanitizer_ifaddrs *ifa_next;
+  char *ifa_name;
+  unsigned int ifa_flags;
+  void *ifa_addr;     // (struct sockaddr *)
+  void *ifa_netmask;  // (struct sockaddr *)
+  // This is a union on Linux.
 # ifdef ifa_dstaddr
 # undef ifa_dstaddr
 # endif
-    void *ifa_dstaddr; // (struct sockaddr *)
-    void *ifa_data;
-  };
+  void *ifa_dstaddr;  // (struct sockaddr *)
+  void *ifa_data;
+};
 #endif  // !SANITIZER_ANDROID
 
 #if SANITIZER_MAC
-  typedef unsigned long __sanitizer_pthread_key_t;
+typedef unsigned long __sanitizer_pthread_key_t;
 #else
-  typedef unsigned __sanitizer_pthread_key_t;
+typedef unsigned __sanitizer_pthread_key_t;
 #endif
 
 #if SANITIZER_LINUX && !SANITIZER_ANDROID
 
-  struct __sanitizer_XDR {
-    int x_op;
-    void *x_ops;
-    uptr x_public;
-    uptr x_private;
-    uptr x_base;
-    unsigned x_handy;
-  };
+struct __sanitizer_XDR {
+  int x_op;
+  void *x_ops;
+  uptr x_public;
+  uptr x_private;
+  uptr x_base;
+  unsigned x_handy;
+};
 
-  const int __sanitizer_XDR_ENCODE = 0;
-  const int __sanitizer_XDR_DECODE = 1;
-  const int __sanitizer_XDR_FREE = 2;
+const int __sanitizer_XDR_ENCODE = 0;
+const int __sanitizer_XDR_DECODE = 1;
+const int __sanitizer_XDR_FREE = 2;
 #endif
 
-  struct __sanitizer_passwd {
-    char *pw_name;
-    char *pw_passwd;
-    int pw_uid;
-    int pw_gid;
+struct __sanitizer_passwd {
+  char *pw_name;
+  char *pw_passwd;
+  int pw_uid;
+  int pw_gid;
 #if SANITIZER_MAC
-    long pw_change;
-    char *pw_class;
+  long pw_change;
+  char *pw_class;
 #endif
 #if !(SANITIZER_ANDROID && (SANITIZER_WORDSIZE == 32))
-    char *pw_gecos;
+  char *pw_gecos;
 #endif
-    char *pw_dir;
-    char *pw_shell;
+  char *pw_dir;
+  char *pw_shell;
 #if SANITIZER_MAC
-    long pw_expire;
+  long pw_expire;
 #endif
-  };
+};
 
-  struct __sanitizer_group {
-    char *gr_name;
-    char *gr_passwd;
-    int gr_gid;
-    char **gr_mem;
-  };
+struct __sanitizer_group {
+  char *gr_name;
+  char *gr_passwd;
+  int gr_gid;
+  char **gr_mem;
+};
 
 #if defined(__x86_64__) && !defined(_LP64)
-  typedef long long __sanitizer_time_t;
+typedef long long __sanitizer_time_t;
 #else
-  typedef long __sanitizer_time_t;
+typedef long __sanitizer_time_t;
 #endif
 
-  typedef long __sanitizer_suseconds_t;
+typedef long __sanitizer_suseconds_t;
 
-  struct __sanitizer_timeval {
-    __sanitizer_time_t tv_sec;
-    __sanitizer_suseconds_t tv_usec;
-  };
+struct __sanitizer_timeval {
+  __sanitizer_time_t tv_sec;
+  __sanitizer_suseconds_t tv_usec;
+};
 
-  struct __sanitizer_itimerval {
-    struct __sanitizer_timeval it_interval;
-    struct __sanitizer_timeval it_value;
-  };
+struct __sanitizer_itimerval {
+  struct __sanitizer_timeval it_interval;
+  struct __sanitizer_timeval it_value;
+};
 
-  struct __sanitizer_timeb {
-    __sanitizer_time_t time;
-    unsigned short millitm;
-    short timezone;
-    short dstflag;
-  };
+struct __sanitizer_timeb {
+  __sanitizer_time_t time;
+  unsigned short millitm;
+  short timezone;
+  short dstflag;
+};
 
-  struct __sanitizer_ether_addr {
-    u8 octet[6];
-  };
+struct __sanitizer_ether_addr {
+  u8 octet[6];
+};
 
-  struct __sanitizer_tm {
-    int tm_sec;
-    int tm_min;
-    int tm_hour;
-    int tm_mday;
-    int tm_mon;
-    int tm_year;
-    int tm_wday;
-    int tm_yday;
-    int tm_isdst;
-    long int tm_gmtoff;
-    const char *tm_zone;
-  };
+struct __sanitizer_tm {
+  int tm_sec;
+  int tm_min;
+  int tm_hour;
+  int tm_mday;
+  int tm_mon;
+  int tm_year;
+  int tm_wday;
+  int tm_yday;
+  int tm_isdst;
+  long int tm_gmtoff;
+  const char *tm_zone;
+};
 
 #if SANITIZER_LINUX
-  struct __sanitizer_mntent {
-    char *mnt_fsname;
-    char *mnt_dir;
-    char *mnt_type;
-    char *mnt_opts;
-    int mnt_freq;
-    int mnt_passno;
-  };
+struct __sanitizer_mntent {
+  char *mnt_fsname;
+  char *mnt_dir;
+  char *mnt_type;
+  char *mnt_opts;
+  int mnt_freq;
+  int mnt_passno;
+};
 
-  struct __sanitizer_file_handle {
-    unsigned int handle_bytes;
-    int handle_type;
-    unsigned char f_handle[1];  // variable sized
-  };
+struct __sanitizer_file_handle {
+  unsigned int handle_bytes;
+  int handle_type;
+  unsigned char f_handle[1];  // variable sized
+};
 #endif
 
 #if SANITIZER_MAC
-  struct __sanitizer_msghdr {
-    void *msg_name;
-    unsigned msg_namelen;
-    struct __sanitizer_iovec *msg_iov;
-    unsigned msg_iovlen;
-    void *msg_control;
-    unsigned msg_controllen;
-    int msg_flags;
-  };
-  struct __sanitizer_cmsghdr {
-    unsigned cmsg_len;
-    int cmsg_level;
-    int cmsg_type;
-  };
+struct __sanitizer_msghdr {
+  void *msg_name;
+  unsigned msg_namelen;
+  struct __sanitizer_iovec *msg_iov;
+  unsigned msg_iovlen;
+  void *msg_control;
+  unsigned msg_controllen;
+  int msg_flags;
+};
+struct __sanitizer_cmsghdr {
+  unsigned cmsg_len;
+  int cmsg_level;
+  int cmsg_type;
+};
 #else
-  struct __sanitizer_msghdr {
-    void *msg_name;
-    unsigned msg_namelen;
-    struct __sanitizer_iovec *msg_iov;
-    uptr msg_iovlen;
-    void *msg_control;
-    uptr msg_controllen;
-    int msg_flags;
-  };
-  struct __sanitizer_cmsghdr {
-    uptr cmsg_len;
-    int cmsg_level;
-    int cmsg_type;
-  };
+struct __sanitizer_msghdr {
+  void *msg_name;
+  unsigned msg_namelen;
+  struct __sanitizer_iovec *msg_iov;
+  uptr msg_iovlen;
+  void *msg_control;
+  uptr msg_controllen;
+  int msg_flags;
+};
+struct __sanitizer_cmsghdr {
+  uptr cmsg_len;
+  int cmsg_level;
+  int cmsg_type;
+};
 #endif
 
 #if SANITIZER_LINUX
-  struct __sanitizer_mmsghdr {
-    __sanitizer_msghdr msg_hdr;
-    unsigned int msg_len;
-  };
+struct __sanitizer_mmsghdr {
+  __sanitizer_msghdr msg_hdr;
+  unsigned int msg_len;
+};
 #endif
 
 #if SANITIZER_MAC
-  struct __sanitizer_dirent {
-    unsigned long long d_ino;
-    unsigned long long d_seekoff;
-    unsigned short d_reclen;
-    // more fields that we don't care about
-  };
+struct __sanitizer_dirent {
+  unsigned long long d_ino;
+  unsigned long long d_seekoff;
+  unsigned short d_reclen;
+  // more fields that we don't care about
+};
 #elif SANITIZER_ANDROID || defined(__x86_64__)
-  struct __sanitizer_dirent {
-    unsigned long long d_ino;
-    unsigned long long d_off;
-    unsigned short d_reclen;
-    // more fields that we don't care about
-  };
+struct __sanitizer_dirent {
+  unsigned long long d_ino;
+  unsigned long long d_off;
+  unsigned short d_reclen;
+  // more fields that we don't care about
+};
 #else
-  struct __sanitizer_dirent {
-    uptr d_ino;
-    uptr d_off;
-    unsigned short d_reclen;
-    // more fields that we don't care about
-  };
+struct __sanitizer_dirent {
+  uptr d_ino;
+  uptr d_off;
+  unsigned short d_reclen;
+  // more fields that we don't care about
+};
 #endif
 
 #if SANITIZER_LINUX && !SANITIZER_ANDROID
-  struct __sanitizer_dirent64 {
-    unsigned long long d_ino;
-    unsigned long long d_off;
-    unsigned short d_reclen;
-    // more fields that we don't care about
-  };
+struct __sanitizer_dirent64 {
+  unsigned long long d_ino;
+  unsigned long long d_off;
+  unsigned short d_reclen;
+  // more fields that we don't care about
+};
 #endif
 
 #if defined(__x86_64__) && !defined(_LP64)
-  typedef long long __sanitizer_clock_t;
+typedef long long __sanitizer_clock_t;
 #else
-  typedef long __sanitizer_clock_t;
+typedef long __sanitizer_clock_t;
 #endif
 
 #if SANITIZER_LINUX
-  typedef int __sanitizer_clockid_t;
+typedef int __sanitizer_clockid_t;
 #endif
 
 #if SANITIZER_LINUX
-#if defined(_LP64) || defined(__x86_64__) || defined(__powerpc__)\
-                   || defined(__mips__)
-  typedef unsigned __sanitizer___kernel_uid_t;
-  typedef unsigned __sanitizer___kernel_gid_t;
+#if defined(_LP64) || defined(__x86_64__) || defined(__powerpc__) || \
+    defined(__mips__)
+typedef unsigned __sanitizer___kernel_uid_t;
+typedef unsigned __sanitizer___kernel_gid_t;
 #else
-  typedef unsigned short __sanitizer___kernel_uid_t;
-  typedef unsigned short __sanitizer___kernel_gid_t;
+typedef unsigned short __sanitizer___kernel_uid_t;
+typedef unsigned short __sanitizer___kernel_gid_t;
 #endif
 #if defined(__x86_64__) && !defined(_LP64)
-  typedef long long __sanitizer___kernel_off_t;
+typedef long long __sanitizer___kernel_off_t;
 #else
-  typedef long __sanitizer___kernel_off_t;
+typedef long __sanitizer___kernel_off_t;
 #endif
 
 #if defined(__powerpc__) || defined(__mips__)
-  typedef unsigned int __sanitizer___kernel_old_uid_t;
-  typedef unsigned int __sanitizer___kernel_old_gid_t;
+typedef unsigned int __sanitizer___kernel_old_uid_t;
+typedef unsigned int __sanitizer___kernel_old_gid_t;
 #else
-  typedef unsigned short __sanitizer___kernel_old_uid_t;
-  typedef unsigned short __sanitizer___kernel_old_gid_t;
+typedef unsigned short __sanitizer___kernel_old_uid_t;
+typedef unsigned short __sanitizer___kernel_old_gid_t;
 #endif
 
-  typedef long long __sanitizer___kernel_loff_t;
-  typedef struct {
-    unsigned long fds_bits[1024 / (8 * sizeof(long))];
-  } __sanitizer___kernel_fd_set;
+typedef long long __sanitizer___kernel_loff_t;
+typedef struct {
+  unsigned long fds_bits[1024 / (8 * sizeof(long))];
+} __sanitizer___kernel_fd_set;
 #endif
 
-  // This thing depends on the platform. We are only interested in the upper
-  // limit. Verified with a compiler assert in .cpp.
-  const int pthread_attr_t_max_sz = 128;
-  union __sanitizer_pthread_attr_t {
-    char size[pthread_attr_t_max_sz]; // NOLINT
-    void *align;
-  };
+// This thing depends on the platform. We are only interested in the upper
+// limit. Verified with a compiler assert in .cpp.
+union __sanitizer_pthread_attr_t {
+  char size[128];
+  void *align;
+};
 
 #if SANITIZER_ANDROID
 # if SANITIZER_MIPS
-  typedef unsigned long __sanitizer_sigset_t[16/sizeof(unsigned long)];
+typedef unsigned long __sanitizer_sigset_t[16 / sizeof(unsigned long)];
 # else
-  typedef unsigned long __sanitizer_sigset_t;
+typedef unsigned long __sanitizer_sigset_t;
 # endif
 #elif SANITIZER_MAC
-  typedef unsigned __sanitizer_sigset_t;
+typedef unsigned __sanitizer_sigset_t;
 #elif SANITIZER_LINUX
-  struct __sanitizer_sigset_t {
-    // The size is determined by looking at sizeof of real sigset_t on linux.
-    uptr val[128 / sizeof(uptr)];
-  };
+struct __sanitizer_sigset_t {
+  // The size is determined by looking at sizeof of real sigset_t on linux.
+  uptr val[128 / sizeof(uptr)];
+};
 #endif
 
-  struct __sanitizer_siginfo {
-    // The size is determined by looking at sizeof of real siginfo_t on linux.
-    u64 opaque[128 / sizeof(u64)];
-  };
+struct __sanitizer_siginfo {
+  // The size is determined by looking at sizeof of real siginfo_t on linux.
+  u64 opaque[128 / sizeof(u64)];
+};
 
-  using __sanitizer_sighandler_ptr = void (*)(int sig);
-  using __sanitizer_sigactionhandler_ptr =
-      void (*)(int sig, __sanitizer_siginfo *siginfo, void *uctx);
+using __sanitizer_sighandler_ptr = void (*)(int sig);
+using __sanitizer_sigactionhandler_ptr = void (*)(int sig,
+                                                  __sanitizer_siginfo *siginfo,
+                                                  void *uctx);
 
-  // Linux system headers define the 'sa_handler' and 'sa_sigaction' macros.
+// Linux system headers define the 'sa_handler' and 'sa_sigaction' macros.
 #if SANITIZER_ANDROID && (SANITIZER_WORDSIZE == 64)
-  struct __sanitizer_sigaction {
-    unsigned sa_flags;
-    union {
-      __sanitizer_sigactionhandler_ptr sigaction;
-      __sanitizer_sighandler_ptr handler;
-    };
-    __sanitizer_sigset_t sa_mask;
-    void (*sa_restorer)();
+struct __sanitizer_sigaction {
+  unsigned sa_flags;
+  union {
+    __sanitizer_sigactionhandler_ptr sigaction;
+    __sanitizer_sighandler_ptr handler;
   };
+  __sanitizer_sigset_t sa_mask;
+  void (*sa_restorer)();
+};
 #elif SANITIZER_ANDROID && SANITIZER_MIPS32  // check this before WORDSIZE == 32
-  struct __sanitizer_sigaction {
-    unsigned sa_flags;
-    union {
-      __sanitizer_sigactionhandler_ptr sigaction;
-      __sanitizer_sighandler_ptr handler;
-    };
-    __sanitizer_sigset_t sa_mask;
+struct __sanitizer_sigaction {
+  unsigned sa_flags;
+  union {
+    __sanitizer_sigactionhandler_ptr sigaction;
+    __sanitizer_sighandler_ptr handler;
   };
+  __sanitizer_sigset_t sa_mask;
+};
 #elif SANITIZER_ANDROID && (SANITIZER_WORDSIZE == 32)
-  struct __sanitizer_sigaction {
-    union {
-      __sanitizer_sigactionhandler_ptr sigaction;
-      __sanitizer_sighandler_ptr handler;
-    };
-    __sanitizer_sigset_t sa_mask;
-    uptr sa_flags;
-    void (*sa_restorer)();
+struct __sanitizer_sigaction {
+  union {
+    __sanitizer_sigactionhandler_ptr sigaction;
+    __sanitizer_sighandler_ptr handler;
   };
+  __sanitizer_sigset_t sa_mask;
+  uptr sa_flags;
+  void (*sa_restorer)();
+};
 #else // !SANITIZER_ANDROID
-  struct __sanitizer_sigaction {
+struct __sanitizer_sigaction {
 #if defined(__mips__) && !SANITIZER_FREEBSD
-    unsigned int sa_flags;
+  unsigned int sa_flags;
 #endif
-    union {
-      __sanitizer_sigactionhandler_ptr sigaction;
-      __sanitizer_sighandler_ptr handler;
-    };
+  union {
+    __sanitizer_sigactionhandler_ptr sigaction;
+    __sanitizer_sighandler_ptr handler;
+  };
 #if SANITIZER_FREEBSD
-    int sa_flags;
-    __sanitizer_sigset_t sa_mask;
+  int sa_flags;
+  __sanitizer_sigset_t sa_mask;
 #else
 #if defined(__s390x__)
-    int sa_resv;
+  int sa_resv;
 #else
-    __sanitizer_sigset_t sa_mask;
+  __sanitizer_sigset_t sa_mask;
 #endif
 #ifndef __mips__
 #if defined(__sparc__)
 #if __GLIBC_PREREQ (2, 20)
-    // On sparc glibc 2.19 and earlier sa_flags was unsigned long.
+  // On sparc glibc 2.19 and earlier sa_flags was unsigned long.
 #if defined(__arch64__)
-    // To maintain ABI compatibility on sparc64 when switching to an int,
-    // __glibc_reserved0 was added.
-    int __glibc_reserved0;
+  // To maintain ABI compatibility on sparc64 when switching to an int,
+  // __glibc_reserved0 was added.
+  int __glibc_reserved0;
 #endif
-    int sa_flags;
+  int sa_flags;
 #else
-    unsigned long sa_flags;
+  unsigned long sa_flags;
 #endif
 #else
-    int sa_flags;
+  int sa_flags;
 #endif
 #endif
 #endif
 #if SANITIZER_LINUX
-    void (*sa_restorer)();
+  void (*sa_restorer)();
 #endif
 #if defined(__mips__) && (SANITIZER_WORDSIZE == 32)
-    int sa_resv[1];
+  int sa_resv[1];
 #endif
 #if defined(__s390x__)
-    __sanitizer_sigset_t sa_mask;
+  __sanitizer_sigset_t sa_mask;
 #endif
-  };
+};
 #endif // !SANITIZER_ANDROID
 
 #if defined(__mips__)
-  struct __sanitizer_kernel_sigset_t {
-    uptr sig[2];
-  };
+struct __sanitizer_kernel_sigset_t {
+  uptr sig[2];
+};
 #else
-  struct __sanitizer_kernel_sigset_t {
-    u8 sig[8];
-  };
+struct __sanitizer_kernel_sigset_t {
+  u8 sig[8];
+};
 #endif
 
-  // Linux system headers define the 'sa_handler' and 'sa_sigaction' macros.
+// Linux system headers define the 'sa_handler' and 'sa_sigaction' macros.
 #if SANITIZER_MIPS
-  struct __sanitizer_kernel_sigaction_t {
-    unsigned int sa_flags;
-    union {
-      void (*handler)(int signo);
-      void (*sigaction)(int signo, __sanitizer_siginfo *info, void *ctx);
-    };
-    __sanitizer_kernel_sigset_t sa_mask;
-    void (*sa_restorer)(void);
+struct __sanitizer_kernel_sigaction_t {
+  unsigned int sa_flags;
+  union {
+    void (*handler)(int signo);
+    void (*sigaction)(int signo, __sanitizer_siginfo *info, void *ctx);
   };
+  __sanitizer_kernel_sigset_t sa_mask;
+  void (*sa_restorer)(void);
+};
 #else
-  struct __sanitizer_kernel_sigaction_t {
-    union {
-      void (*handler)(int signo);
-      void (*sigaction)(int signo, __sanitizer_siginfo *info, void *ctx);
-    };
-    unsigned long sa_flags;
-    void (*sa_restorer)(void);
-    __sanitizer_kernel_sigset_t sa_mask;
+struct __sanitizer_kernel_sigaction_t {
+  union {
+    void (*handler)(int signo);
+    void (*sigaction)(int signo, __sanitizer_siginfo *info, void *ctx);
   };
+  unsigned long sa_flags;
+  void (*sa_restorer)(void);
+  __sanitizer_kernel_sigset_t sa_mask;
+};
 #endif
 
-  extern const uptr sig_ign;
-  extern const uptr sig_dfl;
-  extern const uptr sig_err;
-  extern const uptr sa_siginfo;
+extern const uptr sig_ign;
+extern const uptr sig_dfl;
+extern const uptr sig_err;
+extern const uptr sa_siginfo;
 
 #if SANITIZER_LINUX
-  extern int e_tabsz;
+extern int e_tabsz;
 #endif
 
-  extern int af_inet;
-  extern int af_inet6;
-  uptr __sanitizer_in_addr_sz(int af);
+extern int af_inet;
+extern int af_inet6;
+uptr __sanitizer_in_addr_sz(int af);
 
 #if SANITIZER_LINUX
-  struct __sanitizer_dl_phdr_info {
-    uptr dlpi_addr;
-    const char *dlpi_name;
-    const void *dlpi_phdr;
-    short dlpi_phnum;
-  };
+struct __sanitizer_dl_phdr_info {
+  uptr dlpi_addr;
+  const char *dlpi_name;
+  const void *dlpi_phdr;
+  short dlpi_phnum;
+};
 
-  extern unsigned struct_ElfW_Phdr_sz;
+extern unsigned struct_ElfW_Phdr_sz;
 #endif
 
-  struct __sanitizer_addrinfo {
-    int ai_flags;
-    int ai_family;
-    int ai_socktype;
-    int ai_protocol;
+struct __sanitizer_addrinfo {
+  int ai_flags;
+  int ai_family;
+  int ai_socktype;
+  int ai_protocol;
 #if SANITIZER_ANDROID || SANITIZER_MAC
-    unsigned ai_addrlen;
-    char *ai_canonname;
-    void *ai_addr;
+  unsigned ai_addrlen;
+  char *ai_canonname;
+  void *ai_addr;
 #else // LINUX
-    unsigned ai_addrlen;
-    void *ai_addr;
-    char *ai_canonname;
+  unsigned ai_addrlen;
+  void *ai_addr;
+  char *ai_canonname;
 #endif
-    struct __sanitizer_addrinfo *ai_next;
-  };
+  struct __sanitizer_addrinfo *ai_next;
+};
 
-  struct __sanitizer_hostent {
-    char *h_name;
-    char **h_aliases;
-    int h_addrtype;
-    int h_length;
-    char **h_addr_list;
-  };
+struct __sanitizer_hostent {
+  char *h_name;
+  char **h_aliases;
+  int h_addrtype;
+  int h_length;
+  char **h_addr_list;
+};
 
-  struct __sanitizer_pollfd {
-    int fd;
-    short events;
-    short revents;
-  };
+struct __sanitizer_pollfd {
+  int fd;
+  short events;
+  short revents;
+};
 
 #if SANITIZER_ANDROID || SANITIZER_MAC
-  typedef unsigned __sanitizer_nfds_t;
+typedef unsigned __sanitizer_nfds_t;
 #else
-  typedef unsigned long __sanitizer_nfds_t;
+typedef unsigned long __sanitizer_nfds_t;
 #endif
 
 #if !SANITIZER_ANDROID
 # if SANITIZER_LINUX
-  struct __sanitizer_glob_t {
-    uptr gl_pathc;
-    char **gl_pathv;
-    uptr gl_offs;
-    int gl_flags;
-
-    void (*gl_closedir)(void *dirp);
-    void *(*gl_readdir)(void *dirp);
-    void *(*gl_opendir)(const char *);
-    int (*gl_lstat)(const char *, void *);
-    int (*gl_stat)(const char *, void *);
-  };
+struct __sanitizer_glob_t {
+  uptr gl_pathc;
+  char **gl_pathv;
+  uptr gl_offs;
+  int gl_flags;
+
+  void (*gl_closedir)(void *dirp);
+  void *(*gl_readdir)(void *dirp);
+  void *(*gl_opendir)(const char *);
+  int (*gl_lstat)(const char *, void *);
+  int (*gl_stat)(const char *, void *);
+};
 # endif  // SANITIZER_LINUX
 
 # if SANITIZER_LINUX
-  extern int glob_nomatch;
-  extern int glob_altdirfunc;
+extern int glob_nomatch;
+extern int glob_altdirfunc;
 # endif
 #endif  // !SANITIZER_ANDROID
 
-  extern unsigned path_max;
+extern unsigned path_max;
 
-  struct __sanitizer_wordexp_t {
-    uptr we_wordc;
-    char **we_wordv;
-    uptr we_offs;
-  };
+struct __sanitizer_wordexp_t {
+  uptr we_wordc;
+  char **we_wordv;
+  uptr we_offs;
+};
 
 #if SANITIZER_LINUX && !SANITIZER_ANDROID
-  struct __sanitizer_FILE {
-    int _flags;
-    char *_IO_read_ptr;
-    char *_IO_read_end;
-    char *_IO_read_base;
-    char *_IO_write_base;
-    char *_IO_write_ptr;
-    char *_IO_write_end;
-    char *_IO_buf_base;
-    char *_IO_buf_end;
-    char *_IO_save_base;
-    char *_IO_backup_base;
-    char *_IO_save_end;
-    void *_markers;
-    __sanitizer_FILE *_chain;
-    int _fileno;
-  };
+struct __sanitizer_FILE {
+  int _flags;
+  char *_IO_read_ptr;
+  char *_IO_read_end;
+  char *_IO_read_base;
+  char *_IO_write_base;
+  char *_IO_write_ptr;
+  char *_IO_write_end;
+  char *_IO_buf_base;
+  char *_IO_buf_end;
+  char *_IO_save_base;
+  char *_IO_backup_base;
+  char *_IO_save_end;
+  void *_markers;
+  __sanitizer_FILE *_chain;
+  int _fileno;
+};
 # define SANITIZER_HAS_STRUCT_FILE 1
 #else
-  typedef void __sanitizer_FILE;
+typedef void __sanitizer_FILE;
 # define SANITIZER_HAS_STRUCT_FILE 0
 #endif
 
-#if SANITIZER_LINUX && !SANITIZER_ANDROID && \
-  (defined(__i386) || defined(__x86_64) || defined(__mips64) || \
-    defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \
-    defined(__s390__))
-  extern unsigned struct_user_regs_struct_sz;
-  extern unsigned struct_user_fpregs_struct_sz;
-  extern unsigned struct_user_fpxregs_struct_sz;
-  extern unsigned struct_user_vfpregs_struct_sz;
-
-  extern int ptrace_peektext;
-  extern int ptrace_peekdata;
-  extern int ptrace_peekuser;
-  extern int ptrace_getregs;
-  extern int ptrace_setregs;
-  extern int ptrace_getfpregs;
-  extern int ptrace_setfpregs;
-  extern int ptrace_getfpxregs;
-  extern int ptrace_setfpxregs;
-  extern int ptrace_getvfpregs;
-  extern int ptrace_setvfpregs;
-  extern int ptrace_getsiginfo;
-  extern int ptrace_setsiginfo;
-  extern int ptrace_getregset;
-  extern int ptrace_setregset;
-  extern int ptrace_geteventmsg;
+#if SANITIZER_LINUX && !SANITIZER_ANDROID &&                               \
+    (defined(__i386) || defined(__x86_64) || defined(__mips64) ||          \
+     defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \
+     defined(__s390__))
+extern unsigned struct_user_regs_struct_sz;
+extern unsigned struct_user_fpregs_struct_sz;
+extern unsigned struct_user_fpxregs_struct_sz;
+extern unsigned struct_user_vfpregs_struct_sz;
+
+extern int ptrace_peektext;
+extern int ptrace_peekdata;
+extern int ptrace_peekuser;
+extern int ptrace_getregs;
+extern int ptrace_setregs;
+extern int ptrace_getfpregs;
+extern int ptrace_setfpregs;
+extern int ptrace_getfpxregs;
+extern int ptrace_setfpxregs;
+extern int ptrace_getvfpregs;
+extern int ptrace_setvfpregs;
+extern int ptrace_getsiginfo;
+extern int ptrace_setsiginfo;
+extern int ptrace_getregset;
+extern int ptrace_setregset;
+extern int ptrace_geteventmsg;
 #endif
 
 #if SANITIZER_LINUX  && !SANITIZER_ANDROID
-  extern unsigned struct_shminfo_sz;
-  extern unsigned struct_shm_info_sz;
-  extern int shmctl_ipc_stat;
-  extern int shmctl_ipc_info;
-  extern int shmctl_shm_info;
-  extern int shmctl_shm_stat;
+extern unsigned struct_shminfo_sz;
+extern unsigned struct_shm_info_sz;
+extern int shmctl_ipc_stat;
+extern int shmctl_ipc_info;
+extern int shmctl_shm_info;
+extern int shmctl_shm_stat;
 #endif
 
 #if !SANITIZER_MAC && !SANITIZER_FREEBSD
-  extern unsigned struct_utmp_sz;
+extern unsigned struct_utmp_sz;
 #endif
 #if !SANITIZER_ANDROID
-  extern unsigned struct_utmpx_sz;
+extern unsigned struct_utmpx_sz;
 #endif
 
-  extern int map_fixed;
+extern int map_fixed;
 
-  // ioctl arguments
-  struct __sanitizer_ifconf {
-    int ifc_len;
-    union {
-      void *ifcu_req;
-    } ifc_ifcu;
+// ioctl arguments
+struct __sanitizer_ifconf {
+  int ifc_len;
+  union {
+    void *ifcu_req;
+  } ifc_ifcu;
 #if SANITIZER_MAC
-  } __attribute__((packed));
+} __attribute__((packed));
 #else
-  };
+};
 #endif
 
 #if SANITIZER_LINUX && !SANITIZER_ANDROID
@@ -932,519 +934,519 @@ struct __sanitizer_cookie_io_functions_t {
 #define IOC_SIZE(nr) (((nr) >> IOC_SIZESHIFT) & IOC_SIZEMASK)
 #endif
 
-  extern unsigned struct_ifreq_sz;
-  extern unsigned struct_termios_sz;
-  extern unsigned struct_winsize_sz;
+extern unsigned struct_ifreq_sz;
+extern unsigned struct_termios_sz;
+extern unsigned struct_winsize_sz;
 
 #if SANITIZER_LINUX
-  extern unsigned struct_arpreq_sz;
-  extern unsigned struct_cdrom_msf_sz;
-  extern unsigned struct_cdrom_multisession_sz;
-  extern unsigned struct_cdrom_read_audio_sz;
-  extern unsigned struct_cdrom_subchnl_sz;
-  extern unsigned struct_cdrom_ti_sz;
-  extern unsigned struct_cdrom_tocentry_sz;
-  extern unsigned struct_cdrom_tochdr_sz;
-  extern unsigned struct_cdrom_volctrl_sz;
-  extern unsigned struct_ff_effect_sz;
-  extern unsigned struct_floppy_drive_params_sz;
-  extern unsigned struct_floppy_drive_struct_sz;
-  extern unsigned struct_floppy_fdc_state_sz;
-  extern unsigned struct_floppy_max_errors_sz;
-  extern unsigned struct_floppy_raw_cmd_sz;
-  extern unsigned struct_floppy_struct_sz;
-  extern unsigned struct_floppy_write_errors_sz;
-  extern unsigned struct_format_descr_sz;
-  extern unsigned struct_hd_driveid_sz;
-  extern unsigned struct_hd_geometry_sz;
-  extern unsigned struct_input_absinfo_sz;
-  extern unsigned struct_input_id_sz;
-  extern unsigned struct_mtpos_sz;
-  extern unsigned struct_termio_sz;
-  extern unsigned struct_vt_consize_sz;
-  extern unsigned struct_vt_sizes_sz;
-  extern unsigned struct_vt_stat_sz;
+extern unsigned struct_arpreq_sz;
+extern unsigned struct_cdrom_msf_sz;
+extern unsigned struct_cdrom_multisession_sz;
+extern unsigned struct_cdrom_read_audio_sz;
+extern unsigned struct_cdrom_subchnl_sz;
+extern unsigned struct_cdrom_ti_sz;
+extern unsigned struct_cdrom_tocentry_sz;
+extern unsigned struct_cdrom_tochdr_sz;
+extern unsigned struct_cdrom_volctrl_sz;
+extern unsigned struct_ff_effect_sz;
+extern unsigned struct_floppy_drive_params_sz;
+extern unsigned struct_floppy_drive_struct_sz;
+extern unsigned struct_floppy_fdc_state_sz;
+extern unsigned struct_floppy_max_errors_sz;
+extern unsigned struct_floppy_raw_cmd_sz;
+extern unsigned struct_floppy_struct_sz;
+extern unsigned struct_floppy_write_errors_sz;
+extern unsigned struct_format_descr_sz;
+extern unsigned struct_hd_driveid_sz;
+extern unsigned struct_hd_geometry_sz;
+extern unsigned struct_input_absinfo_sz;
+extern unsigned struct_input_id_sz;
+extern unsigned struct_mtpos_sz;
+extern unsigned struct_termio_sz;
+extern unsigned struct_vt_consize_sz;
+extern unsigned struct_vt_sizes_sz;
+extern unsigned struct_vt_stat_sz;
 #endif  // SANITIZER_LINUX
 
 #if SANITIZER_LINUX
-  extern unsigned struct_copr_buffer_sz;
-  extern unsigned struct_copr_debug_buf_sz;
-  extern unsigned struct_copr_msg_sz;
-  extern unsigned struct_midi_info_sz;
-  extern unsigned struct_mtget_sz;
-  extern unsigned struct_mtop_sz;
-  extern unsigned struct_rtentry_sz;
-  extern unsigned struct_sbi_instrument_sz;
-  extern unsigned struct_seq_event_rec_sz;
-  extern unsigned struct_synth_info_sz;
-  extern unsigned struct_vt_mode_sz;
+extern unsigned struct_copr_buffer_sz;
+extern unsigned struct_copr_debug_buf_sz;
+extern unsigned struct_copr_msg_sz;
+extern unsigned struct_midi_info_sz;
+extern unsigned struct_mtget_sz;
+extern unsigned struct_mtop_sz;
+extern unsigned struct_rtentry_sz;
+extern unsigned struct_sbi_instrument_sz;
+extern unsigned struct_seq_event_rec_sz;
+extern unsigned struct_synth_info_sz;
+extern unsigned struct_vt_mode_sz;
 #endif // SANITIZER_LINUX
 
 #if SANITIZER_LINUX && !SANITIZER_ANDROID
-  extern unsigned struct_ax25_parms_struct_sz;
-  extern unsigned struct_cyclades_monitor_sz;
-  extern unsigned struct_input_keymap_entry_sz;
-  extern unsigned struct_ipx_config_data_sz;
-  extern unsigned struct_kbdiacrs_sz;
-  extern unsigned struct_kbentry_sz;
-  extern unsigned struct_kbkeycode_sz;
-  extern unsigned struct_kbsentry_sz;
-  extern unsigned struct_mtconfiginfo_sz;
-  extern unsigned struct_nr_parms_struct_sz;
-  extern unsigned struct_scc_modem_sz;
-  extern unsigned struct_scc_stat_sz;
-  extern unsigned struct_serial_multiport_struct_sz;
-  extern unsigned struct_serial_struct_sz;
-  extern unsigned struct_sockaddr_ax25_sz;
-  extern unsigned struct_unimapdesc_sz;
-  extern unsigned struct_unimapinit_sz;
+extern unsigned struct_ax25_parms_struct_sz;
+extern unsigned struct_cyclades_monitor_sz;
+extern unsigned struct_input_keymap_entry_sz;
+extern unsigned struct_ipx_config_data_sz;
+extern unsigned struct_kbdiacrs_sz;
+extern unsigned struct_kbentry_sz;
+extern unsigned struct_kbkeycode_sz;
+extern unsigned struct_kbsentry_sz;
+extern unsigned struct_mtconfiginfo_sz;
+extern unsigned struct_nr_parms_struct_sz;
+extern unsigned struct_scc_modem_sz;
+extern unsigned struct_scc_stat_sz;
+extern unsigned struct_serial_multiport_struct_sz;
+extern unsigned struct_serial_struct_sz;
+extern unsigned struct_sockaddr_ax25_sz;
+extern unsigned struct_unimapdesc_sz;
+extern unsigned struct_unimapinit_sz;
 #endif  // SANITIZER_LINUX && !SANITIZER_ANDROID
 
-  extern const unsigned long __sanitizer_bufsiz;
+extern const unsigned long __sanitizer_bufsiz;
 
 #if SANITIZER_LINUX && !SANITIZER_ANDROID
-  extern unsigned struct_audio_buf_info_sz;
-  extern unsigned struct_ppp_stats_sz;
+extern unsigned struct_audio_buf_info_sz;
+extern unsigned struct_ppp_stats_sz;
 #endif  // (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID
 
 #if !SANITIZER_ANDROID && !SANITIZER_MAC
-  extern unsigned struct_sioc_sg_req_sz;
-  extern unsigned struct_sioc_vif_req_sz;
-#endif
-
-  // ioctl request identifiers
-
-  // A special value to mark ioctls that are not present on the target platform,
-  // when it can not be determined without including any system headers.
-  extern const unsigned IOCTL_NOT_PRESENT;
-
-  extern unsigned IOCTL_FIOASYNC;
-  extern unsigned IOCTL_FIOCLEX;
-  extern unsigned IOCTL_FIOGETOWN;
-  extern unsigned IOCTL_FIONBIO;
-  extern unsigned IOCTL_FIONCLEX;
-  extern unsigned IOCTL_FIOSETOWN;
-  extern unsigned IOCTL_SIOCADDMULTI;
-  extern unsigned IOCTL_SIOCATMARK;
-  extern unsigned IOCTL_SIOCDELMULTI;
-  extern unsigned IOCTL_SIOCGIFADDR;
-  extern unsigned IOCTL_SIOCGIFBRDADDR;
-  extern unsigned IOCTL_SIOCGIFCONF;
-  extern unsigned IOCTL_SIOCGIFDSTADDR;
-  extern unsigned IOCTL_SIOCGIFFLAGS;
-  extern unsigned IOCTL_SIOCGIFMETRIC;
-  extern unsigned IOCTL_SIOCGIFMTU;
-  extern unsigned IOCTL_SIOCGIFNETMASK;
-  extern unsigned IOCTL_SIOCGPGRP;
-  extern unsigned IOCTL_SIOCSIFADDR;
-  extern unsigned IOCTL_SIOCSIFBRDADDR;
-  extern unsigned IOCTL_SIOCSIFDSTADDR;
-  extern unsigned IOCTL_SIOCSIFFLAGS;
-  extern unsigned IOCTL_SIOCSIFMETRIC;
-  extern unsigned IOCTL_SIOCSIFMTU;
-  extern unsigned IOCTL_SIOCSIFNETMASK;
-  extern unsigned IOCTL_SIOCSPGRP;
-  extern unsigned IOCTL_TIOCCONS;
-  extern unsigned IOCTL_TIOCEXCL;
-  extern unsigned IOCTL_TIOCGETD;
-  extern unsigned IOCTL_TIOCGPGRP;
-  extern unsigned IOCTL_TIOCGWINSZ;
-  extern unsigned IOCTL_TIOCMBIC;
-  extern unsigned IOCTL_TIOCMBIS;
-  extern unsigned IOCTL_TIOCMGET;
-  extern unsigned IOCTL_TIOCMSET;
-  extern unsigned IOCTL_TIOCNOTTY;
-  extern unsigned IOCTL_TIOCNXCL;
-  extern unsigned IOCTL_TIOCOUTQ;
-  extern unsigned IOCTL_TIOCPKT;
-  extern unsigned IOCTL_TIOCSCTTY;
-  extern unsigned IOCTL_TIOCSETD;
-  extern unsigned IOCTL_TIOCSPGRP;
-  extern unsigned IOCTL_TIOCSTI;
-  extern unsigned IOCTL_TIOCSWINSZ;
+extern unsigned struct_sioc_sg_req_sz;
+extern unsigned struct_sioc_vif_req_sz;
+#endif
+
+// ioctl request identifiers
+
+// A special value to mark ioctls that are not present on the target platform,
+// when it can not be determined without including any system headers.
+extern const unsigned IOCTL_NOT_PRESENT;
+
+extern unsigned IOCTL_FIOASYNC;
+extern unsigned IOCTL_FIOCLEX;
+extern unsigned IOCTL_FIOGETOWN;
+extern unsigned IOCTL_FIONBIO;
+extern unsigned IOCTL_FIONCLEX;
+extern unsigned IOCTL_FIOSETOWN;
+extern unsigned IOCTL_SIOCADDMULTI;
+extern unsigned IOCTL_SIOCATMARK;
+extern unsigned IOCTL_SIOCDELMULTI;
+extern unsigned IOCTL_SIOCGIFADDR;
+extern unsigned IOCTL_SIOCGIFBRDADDR;
+extern unsigned IOCTL_SIOCGIFCONF;
+extern unsigned IOCTL_SIOCGIFDSTADDR;
+extern unsigned IOCTL_SIOCGIFFLAGS;
+extern unsigned IOCTL_SIOCGIFMETRIC;
+extern unsigned IOCTL_SIOCGIFMTU;
+extern unsigned IOCTL_SIOCGIFNETMASK;
+extern unsigned IOCTL_SIOCGPGRP;
+extern unsigned IOCTL_SIOCSIFADDR;
+extern unsigned IOCTL_SIOCSIFBRDADDR;
+extern unsigned IOCTL_SIOCSIFDSTADDR;
+extern unsigned IOCTL_SIOCSIFFLAGS;
+extern unsigned IOCTL_SIOCSIFMETRIC;
+extern unsigned IOCTL_SIOCSIFMTU;
+extern unsigned IOCTL_SIOCSIFNETMASK;
+extern unsigned IOCTL_SIOCSPGRP;
+extern unsigned IOCTL_TIOCCONS;
+extern unsigned IOCTL_TIOCEXCL;
+extern unsigned IOCTL_TIOCGETD;
+extern unsigned IOCTL_TIOCGPGRP;
+extern unsigned IOCTL_TIOCGWINSZ;
+extern unsigned IOCTL_TIOCMBIC;
+extern unsigned IOCTL_TIOCMBIS;
+extern unsigned IOCTL_TIOCMGET;
+extern unsigned IOCTL_TIOCMSET;
+extern unsigned IOCTL_TIOCNOTTY;
+extern unsigned IOCTL_TIOCNXCL;
+extern unsigned IOCTL_TIOCOUTQ;
+extern unsigned IOCTL_TIOCPKT;
+extern unsigned IOCTL_TIOCSCTTY;
+extern unsigned IOCTL_TIOCSETD;
+extern unsigned IOCTL_TIOCSPGRP;
+extern unsigned IOCTL_TIOCSTI;
+extern unsigned IOCTL_TIOCSWINSZ;
 #if SANITIZER_LINUX && !SANITIZER_ANDROID
-  extern unsigned IOCTL_SIOCGETSGCNT;
-  extern unsigned IOCTL_SIOCGETVIFCNT;
+extern unsigned IOCTL_SIOCGETSGCNT;
+extern unsigned IOCTL_SIOCGETVIFCNT;
 #endif
 #if SANITIZER_LINUX
-  extern unsigned IOCTL_EVIOCGABS;
-  extern unsigned IOCTL_EVIOCGBIT;
-  extern unsigned IOCTL_EVIOCGEFFECTS;
-  extern unsigned IOCTL_EVIOCGID;
-  extern unsigned IOCTL_EVIOCGKEY;
-  extern unsigned IOCTL_EVIOCGKEYCODE;
-  extern unsigned IOCTL_EVIOCGLED;
-  extern unsigned IOCTL_EVIOCGNAME;
-  extern unsigned IOCTL_EVIOCGPHYS;
-  extern unsigned IOCTL_EVIOCGRAB;
-  extern unsigned IOCTL_EVIOCGREP;
-  extern unsigned IOCTL_EVIOCGSND;
-  extern unsigned IOCTL_EVIOCGSW;
-  extern unsigned IOCTL_EVIOCGUNIQ;
-  extern unsigned IOCTL_EVIOCGVERSION;
-  extern unsigned IOCTL_EVIOCRMFF;
-  extern unsigned IOCTL_EVIOCSABS;
-  extern unsigned IOCTL_EVIOCSFF;
-  extern unsigned IOCTL_EVIOCSKEYCODE;
-  extern unsigned IOCTL_EVIOCSREP;
-  extern unsigned IOCTL_BLKFLSBUF;
-  extern unsigned IOCTL_BLKGETSIZE;
-  extern unsigned IOCTL_BLKRAGET;
-  extern unsigned IOCTL_BLKRASET;
-  extern unsigned IOCTL_BLKROGET;
-  extern unsigned IOCTL_BLKROSET;
-  extern unsigned IOCTL_BLKRRPART;
-  extern unsigned IOCTL_CDROMAUDIOBUFSIZ;
-  extern unsigned IOCTL_CDROMEJECT;
-  extern unsigned IOCTL_CDROMEJECT_SW;
-  extern unsigned IOCTL_CDROMMULTISESSION;
-  extern unsigned IOCTL_CDROMPAUSE;
-  extern unsigned IOCTL_CDROMPLAYMSF;
-  extern unsigned IOCTL_CDROMPLAYTRKIND;
-  extern unsigned IOCTL_CDROMREADAUDIO;
-  extern unsigned IOCTL_CDROMREADCOOKED;
-  extern unsigned IOCTL_CDROMREADMODE1;
-  extern unsigned IOCTL_CDROMREADMODE2;
-  extern unsigned IOCTL_CDROMREADRAW;
-  extern unsigned IOCTL_CDROMREADTOCENTRY;
-  extern unsigned IOCTL_CDROMREADTOCHDR;
-  extern unsigned IOCTL_CDROMRESET;
-  extern unsigned IOCTL_CDROMRESUME;
-  extern unsigned IOCTL_CDROMSEEK;
-  extern unsigned IOCTL_CDROMSTART;
-  extern unsigned IOCTL_CDROMSTOP;
-  extern unsigned IOCTL_CDROMSUBCHNL;
-  extern unsigned IOCTL_CDROMVOLCTRL;
-  extern unsigned IOCTL_CDROMVOLREAD;
-  extern unsigned IOCTL_CDROM_GET_UPC;
-  extern unsigned IOCTL_FDCLRPRM;
-  extern unsigned IOCTL_FDDEFPRM;
-  extern unsigned IOCTL_FDFLUSH;
-  extern unsigned IOCTL_FDFMTBEG;
-  extern unsigned IOCTL_FDFMTEND;
-  extern unsigned IOCTL_FDFMTTRK;
-  extern unsigned IOCTL_FDGETDRVPRM;
-  extern unsigned IOCTL_FDGETDRVSTAT;
-  extern unsigned IOCTL_FDGETDRVTYP;
-  extern unsigned IOCTL_FDGETFDCSTAT;
-  extern unsigned IOCTL_FDGETMAXERRS;
-  extern unsigned IOCTL_FDGETPRM;
-  extern unsigned IOCTL_FDMSGOFF;
-  extern unsigned IOCTL_FDMSGON;
-  extern unsigned IOCTL_FDPOLLDRVSTAT;
-  extern unsigned IOCTL_FDRAWCMD;
-  extern unsigned IOCTL_FDRESET;
-  extern unsigned IOCTL_FDSETDRVPRM;
-  extern unsigned IOCTL_FDSETEMSGTRESH;
-  extern unsigned IOCTL_FDSETMAXERRS;
-  extern unsigned IOCTL_FDSETPRM;
-  extern unsigned IOCTL_FDTWADDLE;
-  extern unsigned IOCTL_FDWERRORCLR;
-  extern unsigned IOCTL_FDWERRORGET;
-  extern unsigned IOCTL_HDIO_DRIVE_CMD;
-  extern unsigned IOCTL_HDIO_GETGEO;
-  extern unsigned IOCTL_HDIO_GET_32BIT;
-  extern unsigned IOCTL_HDIO_GET_DMA;
-  extern unsigned IOCTL_HDIO_GET_IDENTITY;
-  extern unsigned IOCTL_HDIO_GET_KEEPSETTINGS;
-  extern unsigned IOCTL_HDIO_GET_MULTCOUNT;
-  extern unsigned IOCTL_HDIO_GET_NOWERR;
-  extern unsigned IOCTL_HDIO_GET_UNMASKINTR;
-  extern unsigned IOCTL_HDIO_SET_32BIT;
-  extern unsigned IOCTL_HDIO_SET_DMA;
-  extern unsigned IOCTL_HDIO_SET_KEEPSETTINGS;
-  extern unsigned IOCTL_HDIO_SET_MULTCOUNT;
-  extern unsigned IOCTL_HDIO_SET_NOWERR;
-  extern unsigned IOCTL_HDIO_SET_UNMASKINTR;
-  extern unsigned IOCTL_MTIOCPOS;
-  extern unsigned IOCTL_PPPIOCGASYNCMAP;
-  extern unsigned IOCTL_PPPIOCGDEBUG;
-  extern unsigned IOCTL_PPPIOCGFLAGS;
-  extern unsigned IOCTL_PPPIOCGUNIT;
-  extern unsigned IOCTL_PPPIOCGXASYNCMAP;
-  extern unsigned IOCTL_PPPIOCSASYNCMAP;
-  extern unsigned IOCTL_PPPIOCSDEBUG;
-  extern unsigned IOCTL_PPPIOCSFLAGS;
-  extern unsigned IOCTL_PPPIOCSMAXCID;
-  extern unsigned IOCTL_PPPIOCSMRU;
-  extern unsigned IOCTL_PPPIOCSXASYNCMAP;
-  extern unsigned IOCTL_SIOCDARP;
-  extern unsigned IOCTL_SIOCDRARP;
-  extern unsigned IOCTL_SIOCGARP;
-  extern unsigned IOCTL_SIOCGIFENCAP;
-  extern unsigned IOCTL_SIOCGIFHWADDR;
-  extern unsigned IOCTL_SIOCGIFMAP;
-  extern unsigned IOCTL_SIOCGIFMEM;
-  extern unsigned IOCTL_SIOCGIFNAME;
-  extern unsigned IOCTL_SIOCGIFSLAVE;
-  extern unsigned IOCTL_SIOCGRARP;
-  extern unsigned IOCTL_SIOCGSTAMP;
-  extern unsigned IOCTL_SIOCSARP;
-  extern unsigned IOCTL_SIOCSIFENCAP;
-  extern unsigned IOCTL_SIOCSIFHWADDR;
-  extern unsigned IOCTL_SIOCSIFLINK;
-  extern unsigned IOCTL_SIOCSIFMAP;
-  extern unsigned IOCTL_SIOCSIFMEM;
-  extern unsigned IOCTL_SIOCSIFSLAVE;
-  extern unsigned IOCTL_SIOCSRARP;
-  extern unsigned IOCTL_SNDCTL_COPR_HALT;
-  extern unsigned IOCTL_SNDCTL_COPR_LOAD;
-  extern unsigned IOCTL_SNDCTL_COPR_RCODE;
-  extern unsigned IOCTL_SNDCTL_COPR_RCVMSG;
-  extern unsigned IOCTL_SNDCTL_COPR_RDATA;
-  extern unsigned IOCTL_SNDCTL_COPR_RESET;
-  extern unsigned IOCTL_SNDCTL_COPR_RUN;
-  extern unsigned IOCTL_SNDCTL_COPR_SENDMSG;
-  extern unsigned IOCTL_SNDCTL_COPR_WCODE;
-  extern unsigned IOCTL_SNDCTL_COPR_WDATA;
-  extern unsigned IOCTL_TCFLSH;
-  extern unsigned IOCTL_TCGETA;
-  extern unsigned IOCTL_TCGETS;
-  extern unsigned IOCTL_TCSBRK;
-  extern unsigned IOCTL_TCSBRKP;
-  extern unsigned IOCTL_TCSETA;
-  extern unsigned IOCTL_TCSETAF;
-  extern unsigned IOCTL_TCSETAW;
-  extern unsigned IOCTL_TCSETS;
-  extern unsigned IOCTL_TCSETSF;
-  extern unsigned IOCTL_TCSETSW;
-  extern unsigned IOCTL_TCXONC;
-  extern unsigned IOCTL_TIOCGLCKTRMIOS;
-  extern unsigned IOCTL_TIOCGSOFTCAR;
-  extern unsigned IOCTL_TIOCINQ;
-  extern unsigned IOCTL_TIOCLINUX;
-  extern unsigned IOCTL_TIOCSERCONFIG;
-  extern unsigned IOCTL_TIOCSERGETLSR;
-  extern unsigned IOCTL_TIOCSERGWILD;
-  extern unsigned IOCTL_TIOCSERSWILD;
-  extern unsigned IOCTL_TIOCSLCKTRMIOS;
-  extern unsigned IOCTL_TIOCSSOFTCAR;
-  extern unsigned IOCTL_VT_DISALLOCATE;
-  extern unsigned IOCTL_VT_GETSTATE;
-  extern unsigned IOCTL_VT_RESIZE;
-  extern unsigned IOCTL_VT_RESIZEX;
-  extern unsigned IOCTL_VT_SENDSIG;
-  extern unsigned IOCTL_MTIOCGET;
-  extern unsigned IOCTL_MTIOCTOP;
-  extern unsigned IOCTL_SIOCADDRT;
-  extern unsigned IOCTL_SIOCDELRT;
-  extern unsigned IOCTL_SNDCTL_DSP_GETBLKSIZE;
-  extern unsigned IOCTL_SNDCTL_DSP_GETFMTS;
-  extern unsigned IOCTL_SNDCTL_DSP_NONBLOCK;
-  extern unsigned IOCTL_SNDCTL_DSP_POST;
-  extern unsigned IOCTL_SNDCTL_DSP_RESET;
-  extern unsigned IOCTL_SNDCTL_DSP_SETFMT;
-  extern unsigned IOCTL_SNDCTL_DSP_SETFRAGMENT;
-  extern unsigned IOCTL_SNDCTL_DSP_SPEED;
-  extern unsigned IOCTL_SNDCTL_DSP_STEREO;
-  extern unsigned IOCTL_SNDCTL_DSP_SUBDIVIDE;
-  extern unsigned IOCTL_SNDCTL_DSP_SYNC;
-  extern unsigned IOCTL_SNDCTL_FM_4OP_ENABLE;
-  extern unsigned IOCTL_SNDCTL_FM_LOAD_INSTR;
-  extern unsigned IOCTL_SNDCTL_MIDI_INFO;
-  extern unsigned IOCTL_SNDCTL_MIDI_PRETIME;
-  extern unsigned IOCTL_SNDCTL_SEQ_CTRLRATE;
-  extern unsigned IOCTL_SNDCTL_SEQ_GETINCOUNT;
-  extern unsigned IOCTL_SNDCTL_SEQ_GETOUTCOUNT;
-  extern unsigned IOCTL_SNDCTL_SEQ_NRMIDIS;
-  extern unsigned IOCTL_SNDCTL_SEQ_NRSYNTHS;
-  extern unsigned IOCTL_SNDCTL_SEQ_OUTOFBAND;
-  extern unsigned IOCTL_SNDCTL_SEQ_PANIC;
-  extern unsigned IOCTL_SNDCTL_SEQ_PERCMODE;
-  extern unsigned IOCTL_SNDCTL_SEQ_RESET;
-  extern unsigned IOCTL_SNDCTL_SEQ_RESETSAMPLES;
-  extern unsigned IOCTL_SNDCTL_SEQ_SYNC;
-  extern unsigned IOCTL_SNDCTL_SEQ_TESTMIDI;
-  extern unsigned IOCTL_SNDCTL_SEQ_THRESHOLD;
-  extern unsigned IOCTL_SNDCTL_SYNTH_INFO;
-  extern unsigned IOCTL_SNDCTL_SYNTH_MEMAVL;
-  extern unsigned IOCTL_SNDCTL_TMR_CONTINUE;
-  extern unsigned IOCTL_SNDCTL_TMR_METRONOME;
-  extern unsigned IOCTL_SNDCTL_TMR_SELECT;
-  extern unsigned IOCTL_SNDCTL_TMR_SOURCE;
-  extern unsigned IOCTL_SNDCTL_TMR_START;
-  extern unsigned IOCTL_SNDCTL_TMR_STOP;
-  extern unsigned IOCTL_SNDCTL_TMR_TEMPO;
-  extern unsigned IOCTL_SNDCTL_TMR_TIMEBASE;
-  extern unsigned IOCTL_SOUND_MIXER_READ_ALTPCM;
-  extern unsigned IOCTL_SOUND_MIXER_READ_BASS;
-  extern unsigned IOCTL_SOUND_MIXER_READ_CAPS;
-  extern unsigned IOCTL_SOUND_MIXER_READ_CD;
-  extern unsigned IOCTL_SOUND_MIXER_READ_DEVMASK;
-  extern unsigned IOCTL_SOUND_MIXER_READ_ENHANCE;
-  extern unsigned IOCTL_SOUND_MIXER_READ_IGAIN;
-  extern unsigned IOCTL_SOUND_MIXER_READ_IMIX;
-  extern unsigned IOCTL_SOUND_MIXER_READ_LINE1;
-  extern unsigned IOCTL_SOUND_MIXER_READ_LINE2;
-  extern unsigned IOCTL_SOUND_MIXER_READ_LINE3;
-  extern unsigned IOCTL_SOUND_MIXER_READ_LINE;
-  extern unsigned IOCTL_SOUND_MIXER_READ_LOUD;
-  extern unsigned IOCTL_SOUND_MIXER_READ_MIC;
-  extern unsigned IOCTL_SOUND_MIXER_READ_MUTE;
-  extern unsigned IOCTL_SOUND_MIXER_READ_OGAIN;
-  extern unsigned IOCTL_SOUND_MIXER_READ_PCM;
-  extern unsigned IOCTL_SOUND_MIXER_READ_RECLEV;
-  extern unsigned IOCTL_SOUND_MIXER_READ_RECMASK;
-  extern unsigned IOCTL_SOUND_MIXER_READ_RECSRC;
-  extern unsigned IOCTL_SOUND_MIXER_READ_SPEAKER;
-  extern unsigned IOCTL_SOUND_MIXER_READ_STEREODEVS;
-  extern unsigned IOCTL_SOUND_MIXER_READ_SYNTH;
-  extern unsigned IOCTL_SOUND_MIXER_READ_TREBLE;
-  extern unsigned IOCTL_SOUND_MIXER_READ_VOLUME;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_ALTPCM;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_BASS;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_CD;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_ENHANCE;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_IGAIN;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_IMIX;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_LINE1;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_LINE2;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_LINE3;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_LINE;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_LOUD;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_MIC;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_MUTE;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_OGAIN;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_PCM;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_RECLEV;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_RECSRC;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_SPEAKER;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_SYNTH;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_TREBLE;
-  extern unsigned IOCTL_SOUND_MIXER_WRITE_VOLUME;
-  extern unsigned IOCTL_SOUND_PCM_READ_BITS;
-  extern unsigned IOCTL_SOUND_PCM_READ_CHANNELS;
-  extern unsigned IOCTL_SOUND_PCM_READ_FILTER;
-  extern unsigned IOCTL_SOUND_PCM_READ_RATE;
-  extern unsigned IOCTL_SOUND_PCM_WRITE_CHANNELS;
-  extern unsigned IOCTL_SOUND_PCM_WRITE_FILTER;
-  extern unsigned IOCTL_VT_ACTIVATE;
-  extern unsigned IOCTL_VT_GETMODE;
-  extern unsigned IOCTL_VT_OPENQRY;
-  extern unsigned IOCTL_VT_RELDISP;
-  extern unsigned IOCTL_VT_SETMODE;
-  extern unsigned IOCTL_VT_WAITACTIVE;
+extern unsigned IOCTL_EVIOCGABS;
+extern unsigned IOCTL_EVIOCGBIT;
+extern unsigned IOCTL_EVIOCGEFFECTS;
+extern unsigned IOCTL_EVIOCGID;
+extern unsigned IOCTL_EVIOCGKEY;
+extern unsigned IOCTL_EVIOCGKEYCODE;
+extern unsigned IOCTL_EVIOCGLED;
+extern unsigned IOCTL_EVIOCGNAME;
+extern unsigned IOCTL_EVIOCGPHYS;
+extern unsigned IOCTL_EVIOCGRAB;
+extern unsigned IOCTL_EVIOCGREP;
+extern unsigned IOCTL_EVIOCGSND;
+extern unsigned IOCTL_EVIOCGSW;
+extern unsigned IOCTL_EVIOCGUNIQ;
+extern unsigned IOCTL_EVIOCGVERSION;
+extern unsigned IOCTL_EVIOCRMFF;
+extern unsigned IOCTL_EVIOCSABS;
+extern unsigned IOCTL_EVIOCSFF;
+extern unsigned IOCTL_EVIOCSKEYCODE;
+extern unsigned IOCTL_EVIOCSREP;
+extern unsigned IOCTL_BLKFLSBUF;
+extern unsigned IOCTL_BLKGETSIZE;
+extern unsigned IOCTL_BLKRAGET;
+extern unsigned IOCTL_BLKRASET;
+extern unsigned IOCTL_BLKROGET;
+extern unsigned IOCTL_BLKROSET;
+extern unsigned IOCTL_BLKRRPART;
+extern unsigned IOCTL_CDROMAUDIOBUFSIZ;
+extern unsigned IOCTL_CDROMEJECT;
+extern unsigned IOCTL_CDROMEJECT_SW;
+extern unsigned IOCTL_CDROMMULTISESSION;
+extern unsigned IOCTL_CDROMPAUSE;
+extern unsigned IOCTL_CDROMPLAYMSF;
+extern unsigned IOCTL_CDROMPLAYTRKIND;
+extern unsigned IOCTL_CDROMREADAUDIO;
+extern unsigned IOCTL_CDROMREADCOOKED;
+extern unsigned IOCTL_CDROMREADMODE1;
+extern unsigned IOCTL_CDROMREADMODE2;
+extern unsigned IOCTL_CDROMREADRAW;
+extern unsigned IOCTL_CDROMREADTOCENTRY;
+extern unsigned IOCTL_CDROMREADTOCHDR;
+extern unsigned IOCTL_CDROMRESET;
+extern unsigned IOCTL_CDROMRESUME;
+extern unsigned IOCTL_CDROMSEEK;
+extern unsigned IOCTL_CDROMSTART;
+extern unsigned IOCTL_CDROMSTOP;
+extern unsigned IOCTL_CDROMSUBCHNL;
+extern unsigned IOCTL_CDROMVOLCTRL;
+extern unsigned IOCTL_CDROMVOLREAD;
+extern unsigned IOCTL_CDROM_GET_UPC;
+extern unsigned IOCTL_FDCLRPRM;
+extern unsigned IOCTL_FDDEFPRM;
+extern unsigned IOCTL_FDFLUSH;
+extern unsigned IOCTL_FDFMTBEG;
+extern unsigned IOCTL_FDFMTEND;
+extern unsigned IOCTL_FDFMTTRK;
+extern unsigned IOCTL_FDGETDRVPRM;
+extern unsigned IOCTL_FDGETDRVSTAT;
+extern unsigned IOCTL_FDGETDRVTYP;
+extern unsigned IOCTL_FDGETFDCSTAT;
+extern unsigned IOCTL_FDGETMAXERRS;
+extern unsigned IOCTL_FDGETPRM;
+extern unsigned IOCTL_FDMSGOFF;
+extern unsigned IOCTL_FDMSGON;
+extern unsigned IOCTL_FDPOLLDRVSTAT;
+extern unsigned IOCTL_FDRAWCMD;
+extern unsigned IOCTL_FDRESET;
+extern unsigned IOCTL_FDSETDRVPRM;
+extern unsigned IOCTL_FDSETEMSGTRESH;
+extern unsigned IOCTL_FDSETMAXERRS;
+extern unsigned IOCTL_FDSETPRM;
+extern unsigned IOCTL_FDTWADDLE;
+extern unsigned IOCTL_FDWERRORCLR;
+extern unsigned IOCTL_FDWERRORGET;
+extern unsigned IOCTL_HDIO_DRIVE_CMD;
+extern unsigned IOCTL_HDIO_GETGEO;
+extern unsigned IOCTL_HDIO_GET_32BIT;
+extern unsigned IOCTL_HDIO_GET_DMA;
+extern unsigned IOCTL_HDIO_GET_IDENTITY;
+extern unsigned IOCTL_HDIO_GET_KEEPSETTINGS;
+extern unsigned IOCTL_HDIO_GET_MULTCOUNT;
+extern unsigned IOCTL_HDIO_GET_NOWERR;
+extern unsigned IOCTL_HDIO_GET_UNMASKINTR;
+extern unsigned IOCTL_HDIO_SET_32BIT;
+extern unsigned IOCTL_HDIO_SET_DMA;
+extern unsigned IOCTL_HDIO_SET_KEEPSETTINGS;
+extern unsigned IOCTL_HDIO_SET_MULTCOUNT;
+extern unsigned IOCTL_HDIO_SET_NOWERR;
+extern unsigned IOCTL_HDIO_SET_UNMASKINTR;
+extern unsigned IOCTL_MTIOCPOS;
+extern unsigned IOCTL_PPPIOCGASYNCMAP;
+extern unsigned IOCTL_PPPIOCGDEBUG;
+extern unsigned IOCTL_PPPIOCGFLAGS;
+extern unsigned IOCTL_PPPIOCGUNIT;
+extern unsigned IOCTL_PPPIOCGXASYNCMAP;
+extern unsigned IOCTL_PPPIOCSASYNCMAP;
+extern unsigned IOCTL_PPPIOCSDEBUG;
+extern unsigned IOCTL_PPPIOCSFLAGS;
+extern unsigned IOCTL_PPPIOCSMAXCID;
+extern unsigned IOCTL_PPPIOCSMRU;
+extern unsigned IOCTL_PPPIOCSXASYNCMAP;
+extern unsigned IOCTL_SIOCDARP;
+extern unsigned IOCTL_SIOCDRARP;
+extern unsigned IOCTL_SIOCGARP;
+extern unsigned IOCTL_SIOCGIFENCAP;
+extern unsigned IOCTL_SIOCGIFHWADDR;
+extern unsigned IOCTL_SIOCGIFMAP;
+extern unsigned IOCTL_SIOCGIFMEM;
+extern unsigned IOCTL_SIOCGIFNAME;
+extern unsigned IOCTL_SIOCGIFSLAVE;
+extern unsigned IOCTL_SIOCGRARP;
+extern unsigned IOCTL_SIOCGSTAMP;
+extern unsigned IOCTL_SIOCSARP;
+extern unsigned IOCTL_SIOCSIFENCAP;
+extern unsigned IOCTL_SIOCSIFHWADDR;
+extern unsigned IOCTL_SIOCSIFLINK;
+extern unsigned IOCTL_SIOCSIFMAP;
+extern unsigned IOCTL_SIOCSIFMEM;
+extern unsigned IOCTL_SIOCSIFSLAVE;
+extern unsigned IOCTL_SIOCSRARP;
+extern unsigned IOCTL_SNDCTL_COPR_HALT;
+extern unsigned IOCTL_SNDCTL_COPR_LOAD;
+extern unsigned IOCTL_SNDCTL_COPR_RCODE;
+extern unsigned IOCTL_SNDCTL_COPR_RCVMSG;
+extern unsigned IOCTL_SNDCTL_COPR_RDATA;
+extern unsigned IOCTL_SNDCTL_COPR_RESET;
+extern unsigned IOCTL_SNDCTL_COPR_RUN;
+extern unsigned IOCTL_SNDCTL_COPR_SENDMSG;
+extern unsigned IOCTL_SNDCTL_COPR_WCODE;
+extern unsigned IOCTL_SNDCTL_COPR_WDATA;
+extern unsigned IOCTL_TCFLSH;
+extern unsigned IOCTL_TCGETA;
+extern unsigned IOCTL_TCGETS;
+extern unsigned IOCTL_TCSBRK;
+extern unsigned IOCTL_TCSBRKP;
+extern unsigned IOCTL_TCSETA;
+extern unsigned IOCTL_TCSETAF;
+extern unsigned IOCTL_TCSETAW;
+extern unsigned IOCTL_TCSETS;
+extern unsigned IOCTL_TCSETSF;
+extern unsigned IOCTL_TCSETSW;
+extern unsigned IOCTL_TCXONC;
+extern unsigned IOCTL_TIOCGLCKTRMIOS;
+extern unsigned IOCTL_TIOCGSOFTCAR;
+extern unsigned IOCTL_TIOCINQ;
+extern unsigned IOCTL_TIOCLINUX;
+extern unsigned IOCTL_TIOCSERCONFIG;
+extern unsigned IOCTL_TIOCSERGETLSR;
+extern unsigned IOCTL_TIOCSERGWILD;
+extern unsigned IOCTL_TIOCSERSWILD;
+extern unsigned IOCTL_TIOCSLCKTRMIOS;
+extern unsigned IOCTL_TIOCSSOFTCAR;
+extern unsigned IOCTL_VT_DISALLOCATE;
+extern unsigned IOCTL_VT_GETSTATE;
+extern unsigned IOCTL_VT_RESIZE;
+extern unsigned IOCTL_VT_RESIZEX;
+extern unsigned IOCTL_VT_SENDSIG;
+extern unsigned IOCTL_MTIOCGET;
+extern unsigned IOCTL_MTIOCTOP;
+extern unsigned IOCTL_SIOCADDRT;
+extern unsigned IOCTL_SIOCDELRT;
+extern unsigned IOCTL_SNDCTL_DSP_GETBLKSIZE;
+extern unsigned IOCTL_SNDCTL_DSP_GETFMTS;
+extern unsigned IOCTL_SNDCTL_DSP_NONBLOCK;
+extern unsigned IOCTL_SNDCTL_DSP_POST;
+extern unsigned IOCTL_SNDCTL_DSP_RESET;
+extern unsigned IOCTL_SNDCTL_DSP_SETFMT;
+extern unsigned IOCTL_SNDCTL_DSP_SETFRAGMENT;
+extern unsigned IOCTL_SNDCTL_DSP_SPEED;
+extern unsigned IOCTL_SNDCTL_DSP_STEREO;
+extern unsigned IOCTL_SNDCTL_DSP_SUBDIVIDE;
+extern unsigned IOCTL_SNDCTL_DSP_SYNC;
+extern unsigned IOCTL_SNDCTL_FM_4OP_ENABLE;
+extern unsigned IOCTL_SNDCTL_FM_LOAD_INSTR;
+extern unsigned IOCTL_SNDCTL_MIDI_INFO;
+extern unsigned IOCTL_SNDCTL_MIDI_PRETIME;
+extern unsigned IOCTL_SNDCTL_SEQ_CTRLRATE;
+extern unsigned IOCTL_SNDCTL_SEQ_GETINCOUNT;
+extern unsigned IOCTL_SNDCTL_SEQ_GETOUTCOUNT;
+extern unsigned IOCTL_SNDCTL_SEQ_NRMIDIS;
+extern unsigned IOCTL_SNDCTL_SEQ_NRSYNTHS;
+extern unsigned IOCTL_SNDCTL_SEQ_OUTOFBAND;
+extern unsigned IOCTL_SNDCTL_SEQ_PANIC;
+extern unsigned IOCTL_SNDCTL_SEQ_PERCMODE;
+extern unsigned IOCTL_SNDCTL_SEQ_RESET;
+extern unsigned IOCTL_SNDCTL_SEQ_RESETSAMPLES;
+extern unsigned IOCTL_SNDCTL_SEQ_SYNC;
+extern unsigned IOCTL_SNDCTL_SEQ_TESTMIDI;
+extern unsigned IOCTL_SNDCTL_SEQ_THRESHOLD;
+extern unsigned IOCTL_SNDCTL_SYNTH_INFO;
+extern unsigned IOCTL_SNDCTL_SYNTH_MEMAVL;
+extern unsigned IOCTL_SNDCTL_TMR_CONTINUE;
+extern unsigned IOCTL_SNDCTL_TMR_METRONOME;
+extern unsigned IOCTL_SNDCTL_TMR_SELECT;
+extern unsigned IOCTL_SNDCTL_TMR_SOURCE;
+extern unsigned IOCTL_SNDCTL_TMR_START;
+extern unsigned IOCTL_SNDCTL_TMR_STOP;
+extern unsigned IOCTL_SNDCTL_TMR_TEMPO;
+extern unsigned IOCTL_SNDCTL_TMR_TIMEBASE;
+extern unsigned IOCTL_SOUND_MIXER_READ_ALTPCM;
+extern unsigned IOCTL_SOUND_MIXER_READ_BASS;
+extern unsigned IOCTL_SOUND_MIXER_READ_CAPS;
+extern unsigned IOCTL_SOUND_MIXER_READ_CD;
+extern unsigned IOCTL_SOUND_MIXER_READ_DEVMASK;
+extern unsigned IOCTL_SOUND_MIXER_READ_ENHANCE;
+extern unsigned IOCTL_SOUND_MIXER_READ_IGAIN;
+extern unsigned IOCTL_SOUND_MIXER_READ_IMIX;
+extern unsigned IOCTL_SOUND_MIXER_READ_LINE1;
+extern unsigned IOCTL_SOUND_MIXER_READ_LINE2;
+extern unsigned IOCTL_SOUND_MIXER_READ_LINE3;
+extern unsigned IOCTL_SOUND_MIXER_READ_LINE;
+extern unsigned IOCTL_SOUND_MIXER_READ_LOUD;
+extern unsigned IOCTL_SOUND_MIXER_READ_MIC;
+extern unsigned IOCTL_SOUND_MIXER_READ_MUTE;
+extern unsigned IOCTL_SOUND_MIXER_READ_OGAIN;
+extern unsigned IOCTL_SOUND_MIXER_READ_PCM;
+extern unsigned IOCTL_SOUND_MIXER_READ_RECLEV;
+extern unsigned IOCTL_SOUND_MIXER_READ_RECMASK;
+extern unsigned IOCTL_SOUND_MIXER_READ_RECSRC;
+extern unsigned IOCTL_SOUND_MIXER_READ_SPEAKER;
+extern unsigned IOCTL_SOUND_MIXER_READ_STEREODEVS;
+extern unsigned IOCTL_SOUND_MIXER_READ_SYNTH;
+extern unsigned IOCTL_SOUND_MIXER_READ_TREBLE;
+extern unsigned IOCTL_SOUND_MIXER_READ_VOLUME;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_ALTPCM;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_BASS;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_CD;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_ENHANCE;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_IGAIN;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_IMIX;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_LINE1;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_LINE2;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_LINE3;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_LINE;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_LOUD;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_MIC;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_MUTE;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_OGAIN;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_PCM;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_RECLEV;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_RECSRC;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_SPEAKER;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_SYNTH;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_TREBLE;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_VOLUME;
+extern unsigned IOCTL_SOUND_PCM_READ_BITS;
+extern unsigned IOCTL_SOUND_PCM_READ_CHANNELS;
+extern unsigned IOCTL_SOUND_PCM_READ_FILTER;
+extern unsigned IOCTL_SOUND_PCM_READ_RATE;
+extern unsigned IOCTL_SOUND_PCM_WRITE_CHANNELS;
+extern unsigned IOCTL_SOUND_PCM_WRITE_FILTER;
+extern unsigned IOCTL_VT_ACTIVATE;
+extern unsigned IOCTL_VT_GETMODE;
+extern unsigned IOCTL_VT_OPENQRY;
+extern unsigned IOCTL_VT_RELDISP;
+extern unsigned IOCTL_VT_SETMODE;
+extern unsigned IOCTL_VT_WAITACTIVE;
 #endif  // SANITIZER_LINUX
 
 #if SANITIZER_LINUX && !SANITIZER_ANDROID
-  extern unsigned IOCTL_CYGETDEFTHRESH;
-  extern unsigned IOCTL_CYGETDEFTIMEOUT;
-  extern unsigned IOCTL_CYGETMON;
-  extern unsigned IOCTL_CYGETTHRESH;
-  extern unsigned IOCTL_CYGETTIMEOUT;
-  extern unsigned IOCTL_CYSETDEFTHRESH;
-  extern unsigned IOCTL_CYSETDEFTIMEOUT;
-  extern unsigned IOCTL_CYSETTHRESH;
-  extern unsigned IOCTL_CYSETTIMEOUT;
-  extern unsigned IOCTL_EQL_EMANCIPATE;
-  extern unsigned IOCTL_EQL_ENSLAVE;
-  extern unsigned IOCTL_EQL_GETMASTRCFG;
-  extern unsigned IOCTL_EQL_GETSLAVECFG;
-  extern unsigned IOCTL_EQL_SETMASTRCFG;
-  extern unsigned IOCTL_EQL_SETSLAVECFG;
-  extern unsigned IOCTL_EVIOCGKEYCODE_V2;
-  extern unsigned IOCTL_EVIOCGPROP;
-  extern unsigned IOCTL_EVIOCSKEYCODE_V2;
-  extern unsigned IOCTL_FS_IOC_GETFLAGS;
-  extern unsigned IOCTL_FS_IOC_GETVERSION;
-  extern unsigned IOCTL_FS_IOC_SETFLAGS;
-  extern unsigned IOCTL_FS_IOC_SETVERSION;
-  extern unsigned IOCTL_GIO_CMAP;
-  extern unsigned IOCTL_GIO_FONT;
-  extern unsigned IOCTL_GIO_UNIMAP;
-  extern unsigned IOCTL_GIO_UNISCRNMAP;
-  extern unsigned IOCTL_KDADDIO;
-  extern unsigned IOCTL_KDDELIO;
-  extern unsigned IOCTL_KDGETKEYCODE;
-  extern unsigned IOCTL_KDGKBDIACR;
-  extern unsigned IOCTL_KDGKBENT;
-  extern unsigned IOCTL_KDGKBLED;
-  extern unsigned IOCTL_KDGKBMETA;
-  extern unsigned IOCTL_KDGKBSENT;
-  extern unsigned IOCTL_KDMAPDISP;
-  extern unsigned IOCTL_KDSETKEYCODE;
-  extern unsigned IOCTL_KDSIGACCEPT;
-  extern unsigned IOCTL_KDSKBDIACR;
-  extern unsigned IOCTL_KDSKBENT;
-  extern unsigned IOCTL_KDSKBLED;
-  extern unsigned IOCTL_KDSKBMETA;
-  extern unsigned IOCTL_KDSKBSENT;
-  extern unsigned IOCTL_KDUNMAPDISP;
-  extern unsigned IOCTL_LPABORT;
-  extern unsigned IOCTL_LPABORTOPEN;
-  extern unsigned IOCTL_LPCAREFUL;
-  extern unsigned IOCTL_LPCHAR;
-  extern unsigned IOCTL_LPGETIRQ;
-  extern unsigned IOCTL_LPGETSTATUS;
-  extern unsigned IOCTL_LPRESET;
-  extern unsigned IOCTL_LPSETIRQ;
-  extern unsigned IOCTL_LPTIME;
-  extern unsigned IOCTL_LPWAIT;
-  extern unsigned IOCTL_MTIOCGETCONFIG;
-  extern unsigned IOCTL_MTIOCSETCONFIG;
-  extern unsigned IOCTL_PIO_CMAP;
-  extern unsigned IOCTL_PIO_FONT;
-  extern unsigned IOCTL_PIO_UNIMAP;
-  extern unsigned IOCTL_PIO_UNIMAPCLR;
-  extern unsigned IOCTL_PIO_UNISCRNMAP;
-  extern unsigned IOCTL_SCSI_IOCTL_GET_IDLUN;
-  extern unsigned IOCTL_SCSI_IOCTL_PROBE_HOST;
-  extern unsigned IOCTL_SCSI_IOCTL_TAGGED_DISABLE;
-  extern unsigned IOCTL_SCSI_IOCTL_TAGGED_ENABLE;
-  extern unsigned IOCTL_SIOCAIPXITFCRT;
-  extern unsigned IOCTL_SIOCAIPXPRISLT;
-  extern unsigned IOCTL_SIOCAX25ADDUID;
-  extern unsigned IOCTL_SIOCAX25DELUID;
-  extern unsigned IOCTL_SIOCAX25GETPARMS;
-  extern unsigned IOCTL_SIOCAX25GETUID;
-  extern unsigned IOCTL_SIOCAX25NOUID;
-  extern unsigned IOCTL_SIOCAX25SETPARMS;
-  extern unsigned IOCTL_SIOCDEVPLIP;
-  extern unsigned IOCTL_SIOCIPXCFGDATA;
-  extern unsigned IOCTL_SIOCNRDECOBS;
-  extern unsigned IOCTL_SIOCNRGETPARMS;
-  extern unsigned IOCTL_SIOCNRRTCTL;
-  extern unsigned IOCTL_SIOCNRSETPARMS;
-  extern unsigned IOCTL_SNDCTL_DSP_GETISPACE;
-  extern unsigned IOCTL_SNDCTL_DSP_GETOSPACE;
-  extern unsigned IOCTL_TIOCGSERIAL;
-  extern unsigned IOCTL_TIOCSERGETMULTI;
-  extern unsigned IOCTL_TIOCSERSETMULTI;
-  extern unsigned IOCTL_TIOCSSERIAL;
-  extern unsigned IOCTL_GIO_SCRNMAP;
-  extern unsigned IOCTL_KDDISABIO;
-  extern unsigned IOCTL_KDENABIO;
-  extern unsigned IOCTL_KDGETLED;
-  extern unsigned IOCTL_KDGETMODE;
-  extern unsigned IOCTL_KDGKBMODE;
-  extern unsigned IOCTL_KDGKBTYPE;
-  extern unsigned IOCTL_KDMKTONE;
-  extern unsigned IOCTL_KDSETLED;
-  extern unsigned IOCTL_KDSETMODE;
-  extern unsigned IOCTL_KDSKBMODE;
-  extern unsigned IOCTL_KIOCSOUND;
-  extern unsigned IOCTL_PIO_SCRNMAP;
-#endif
-
-  extern const int si_SEGV_MAPERR;
-  extern const int si_SEGV_ACCERR;
+extern unsigned IOCTL_CYGETDEFTHRESH;
+extern unsigned IOCTL_CYGETDEFTIMEOUT;
+extern unsigned IOCTL_CYGETMON;
+extern unsigned IOCTL_CYGETTHRESH;
+extern unsigned IOCTL_CYGETTIMEOUT;
+extern unsigned IOCTL_CYSETDEFTHRESH;
+extern unsigned IOCTL_CYSETDEFTIMEOUT;
+extern unsigned IOCTL_CYSETTHRESH;
+extern unsigned IOCTL_CYSETTIMEOUT;
+extern unsigned IOCTL_EQL_EMANCIPATE;
+extern unsigned IOCTL_EQL_ENSLAVE;
+extern unsigned IOCTL_EQL_GETMASTRCFG;
+extern unsigned IOCTL_EQL_GETSLAVECFG;
+extern unsigned IOCTL_EQL_SETMASTRCFG;
+extern unsigned IOCTL_EQL_SETSLAVECFG;
+extern unsigned IOCTL_EVIOCGKEYCODE_V2;
+extern unsigned IOCTL_EVIOCGPROP;
+extern unsigned IOCTL_EVIOCSKEYCODE_V2;
+extern unsigned IOCTL_FS_IOC_GETFLAGS;
+extern unsigned IOCTL_FS_IOC_GETVERSION;
+extern unsigned IOCTL_FS_IOC_SETFLAGS;
+extern unsigned IOCTL_FS_IOC_SETVERSION;
+extern unsigned IOCTL_GIO_CMAP;
+extern unsigned IOCTL_GIO_FONT;
+extern unsigned IOCTL_GIO_UNIMAP;
+extern unsigned IOCTL_GIO_UNISCRNMAP;
+extern unsigned IOCTL_KDADDIO;
+extern unsigned IOCTL_KDDELIO;
+extern unsigned IOCTL_KDGETKEYCODE;
+extern unsigned IOCTL_KDGKBDIACR;
+extern unsigned IOCTL_KDGKBENT;
+extern unsigned IOCTL_KDGKBLED;
+extern unsigned IOCTL_KDGKBMETA;
+extern unsigned IOCTL_KDGKBSENT;
+extern unsigned IOCTL_KDMAPDISP;
+extern unsigned IOCTL_KDSETKEYCODE;
+extern unsigned IOCTL_KDSIGACCEPT;
+extern unsigned IOCTL_KDSKBDIACR;
+extern unsigned IOCTL_KDSKBENT;
+extern unsigned IOCTL_KDSKBLED;
+extern unsigned IOCTL_KDSKBMETA;
+extern unsigned IOCTL_KDSKBSENT;
+extern unsigned IOCTL_KDUNMAPDISP;
+extern unsigned IOCTL_LPABORT;
+extern unsigned IOCTL_LPABORTOPEN;
+extern unsigned IOCTL_LPCAREFUL;
+extern unsigned IOCTL_LPCHAR;
+extern unsigned IOCTL_LPGETIRQ;
+extern unsigned IOCTL_LPGETSTATUS;
+extern unsigned IOCTL_LPRESET;
+extern unsigned IOCTL_LPSETIRQ;
+extern unsigned IOCTL_LPTIME;
+extern unsigned IOCTL_LPWAIT;
+extern unsigned IOCTL_MTIOCGETCONFIG;
+extern unsigned IOCTL_MTIOCSETCONFIG;
+extern unsigned IOCTL_PIO_CMAP;
+extern unsigned IOCTL_PIO_FONT;
+extern unsigned IOCTL_PIO_UNIMAP;
+extern unsigned IOCTL_PIO_UNIMAPCLR;
+extern unsigned IOCTL_PIO_UNISCRNMAP;
+extern unsigned IOCTL_SCSI_IOCTL_GET_IDLUN;
+extern unsigned IOCTL_SCSI_IOCTL_PROBE_HOST;
+extern unsigned IOCTL_SCSI_IOCTL_TAGGED_DISABLE;
+extern unsigned IOCTL_SCSI_IOCTL_TAGGED_ENABLE;
+extern unsigned IOCTL_SIOCAIPXITFCRT;
+extern unsigned IOCTL_SIOCAIPXPRISLT;
+extern unsigned IOCTL_SIOCAX25ADDUID;
+extern unsigned IOCTL_SIOCAX25DELUID;
+extern unsigned IOCTL_SIOCAX25GETPARMS;
+extern unsigned IOCTL_SIOCAX25GETUID;
+extern unsigned IOCTL_SIOCAX25NOUID;
+extern unsigned IOCTL_SIOCAX25SETPARMS;
+extern unsigned IOCTL_SIOCDEVPLIP;
+extern unsigned IOCTL_SIOCIPXCFGDATA;
+extern unsigned IOCTL_SIOCNRDECOBS;
+extern unsigned IOCTL_SIOCNRGETPARMS;
+extern unsigned IOCTL_SIOCNRRTCTL;
+extern unsigned IOCTL_SIOCNRSETPARMS;
+extern unsigned IOCTL_SNDCTL_DSP_GETISPACE;
+extern unsigned IOCTL_SNDCTL_DSP_GETOSPACE;
+extern unsigned IOCTL_TIOCGSERIAL;
+extern unsigned IOCTL_TIOCSERGETMULTI;
+extern unsigned IOCTL_TIOCSERSETMULTI;
+extern unsigned IOCTL_TIOCSSERIAL;
+extern unsigned IOCTL_GIO_SCRNMAP;
+extern unsigned IOCTL_KDDISABIO;
+extern unsigned IOCTL_KDENABIO;
+extern unsigned IOCTL_KDGETLED;
+extern unsigned IOCTL_KDGETMODE;
+extern unsigned IOCTL_KDGKBMODE;
+extern unsigned IOCTL_KDGKBTYPE;
+extern unsigned IOCTL_KDMKTONE;
+extern unsigned IOCTL_KDSETLED;
+extern unsigned IOCTL_KDSETMODE;
+extern unsigned IOCTL_KDSKBMODE;
+extern unsigned IOCTL_KIOCSOUND;
+extern unsigned IOCTL_PIO_SCRNMAP;
+#endif
+
+extern const int si_SEGV_MAPERR;
+extern const int si_SEGV_ACCERR;
 }  // namespace __sanitizer
 
 #define CHECK_TYPE_SIZE(TYPE) \
   COMPILER_CHECK(sizeof(__sanitizer_##TYPE) == sizeof(TYPE))
 
-#define CHECK_SIZE_AND_OFFSET(CLASS, MEMBER)                       \
-  COMPILER_CHECK(sizeof(((__sanitizer_##CLASS *) NULL)->MEMBER) == \
-                 sizeof(((CLASS *) NULL)->MEMBER));                \
-  COMPILER_CHECK(offsetof(__sanitizer_##CLASS, MEMBER) ==          \
+#define CHECK_SIZE_AND_OFFSET(CLASS, MEMBER)                      \
+  COMPILER_CHECK(sizeof(((__sanitizer_##CLASS *)NULL)->MEMBER) == \
+                 sizeof(((CLASS *)NULL)->MEMBER));                \
+  COMPILER_CHECK(offsetof(__sanitizer_##CLASS, MEMBER) ==         \
                  offsetof(CLASS, MEMBER))
 
 // For sigaction, which is a function and struct at the same time,
 // and thus requires explicit "struct" in sizeof() expression.
-#define CHECK_STRUCT_SIZE_AND_OFFSET(CLASS, MEMBER)                       \
-  COMPILER_CHECK(sizeof(((struct __sanitizer_##CLASS *) NULL)->MEMBER) == \
-                 sizeof(((struct CLASS *) NULL)->MEMBER));                \
-  COMPILER_CHECK(offsetof(struct __sanitizer_##CLASS, MEMBER) ==          \
+#define CHECK_STRUCT_SIZE_AND_OFFSET(CLASS, MEMBER)                      \
+  COMPILER_CHECK(sizeof(((struct __sanitizer_##CLASS *)NULL)->MEMBER) == \
+                 sizeof(((struct CLASS *)NULL)->MEMBER));                \
+  COMPILER_CHECK(offsetof(struct __sanitizer_##CLASS, MEMBER) ==         \
                  offsetof(struct CLASS, MEMBER))
 
 #define SIGACTION_SYMNAME sigaction
index ed3b7a04dff51379f17492346c9b3a5afb0cc9d0..77ae6e6a44dbd96dd00feaac6925ee1555579637 100644 (file)
@@ -68,7 +68,7 @@ struct __sanitizer_ipc_perm {
 #if !defined(_LP64)
   int pad[4];
 #endif
-  };
+};
 
 struct __sanitizer_shmid_ds {
   __sanitizer_ipc_perm shm_perm;
@@ -237,9 +237,8 @@ typedef int __sanitizer_clockid_t;
 
 // This thing depends on the platform. We are only interested in the upper
 // limit. Verified with a compiler assert in .cpp.
-const int pthread_attr_t_max_sz = 128;
 union __sanitizer_pthread_attr_t {
-  char size[pthread_attr_t_max_sz]; // NOLINT
+  char size[128];
   void *align;
 };
 
index 002bcb1eda4ab6f41fa3288bbe37912621dce1c3..d890a3a317737cdeddb31ddf35c429c53454e1d7 100644 (file)
@@ -312,6 +312,8 @@ const char *SignalContext::Describe() const {
       return "SEGV";
     case SIGBUS:
       return "BUS";
+    case SIGTRAP:
+      return "TRAP";
   }
   return "UNKNOWN SIGNAL";
 }
index 6cf5ce75b12e8c681c56326951ae30391bedf725..05fb0f630207c5951e8c8a7f18fa24c6752f3931 100644 (file)
@@ -63,7 +63,7 @@ uptr internal_ptrace(int request, int pid, void *addr, void *data);
 uptr internal_waitpid(int pid, int *status, int options);
 
 int internal_fork();
-int internal_forkpty(int *amaster);
+fd_t internal_spawn(const char *argv[], pid_t *pid);
 
 int internal_sysctl(const int *name, unsigned int namelen, void *oldp,
                     uptr *oldlenp, const void *newp, uptr newlen);
index 1bbbf8a675fdfff76009d947139be0782429ee43..304b3a01a08b6ac06e8dae266e5c4bc116cf8be6 100644 (file)
@@ -304,11 +304,13 @@ void PlatformPrepareForSandboxing(__sanitizer_sandbox_arguments *args) {
   MemoryMappingLayout::CacheMemoryMappings();
 }
 
-bool MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name) {
+static bool MmapFixed(uptr fixed_addr, uptr size, int additional_flags,
+                      const char *name) {
   size = RoundUpTo(size, GetPageSizeCached());
   fixed_addr = RoundDownTo(fixed_addr, GetPageSizeCached());
-  uptr p = MmapNamed((void *)fixed_addr, size, PROT_READ | PROT_WRITE,
-                     MAP_PRIVATE | MAP_FIXED | MAP_NORESERVE | MAP_ANON, name);
+  uptr p =
+      MmapNamed((void *)fixed_addr, size, PROT_READ | PROT_WRITE,
+                MAP_PRIVATE | MAP_FIXED | additional_flags | MAP_ANON, name);
   int reserrno;
   if (internal_iserror(p, &reserrno)) {
     Report("ERROR: %s failed to "
@@ -320,6 +322,24 @@ bool MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name) {
   return true;
 }
 
+bool MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name) {
+  return MmapFixed(fixed_addr, size, MAP_NORESERVE, name);
+}
+
+bool MmapFixedSuperNoReserve(uptr fixed_addr, uptr size, const char *name) {
+#if SANITIZER_FREEBSD
+  if (common_flags()->no_huge_pages_for_shadow)
+    return MmapFixedNoReserve(fixed_addr, size, name);
+  // MAP_NORESERVE is implicit with FreeBSD
+  return MmapFixed(fixed_addr, size, MAP_ALIGNED_SUPER, name);
+#else
+  bool r = MmapFixedNoReserve(fixed_addr, size, name);
+  if (r)
+    SetShadowRegionHugePageMode(fixed_addr, size);
+  return r;
+#endif
+}
+
 uptr ReservedAddressRange::Init(uptr size, const char *name, uptr fixed_addr) {
   base_ = fixed_addr ? MmapFixedNoAccess(fixed_addr, size, name)
                      : MmapNoAccess(size);
index 9d1c544786d34f621a3cfddba0c4c36769fe8f28..a032787114bb9824dbcb803406db59545df13a16 100644 (file)
@@ -229,15 +229,15 @@ void SetPrintfAndReportCallback(void (*callback)(const char *)) {
 // Can be overriden in frontend.
 #if SANITIZER_GO && defined(TSAN_EXTERNAL_HOOKS)
 // Implementation must be defined in frontend.
-extern "C" void OnPrint(const char *str);
+extern "C" void __sanitizer_on_print(const char *str);
 #else
-SANITIZER_INTERFACE_WEAK_DEF(void, OnPrint, const char *str) {
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_on_print, const char *str) {
   (void)str;
 }
 #endif
 
 static void CallPrintfAndReportCallback(const char *str) {
-  OnPrint(str);
+  __sanitizer_on_print(str);
   if (PrintfAndReportCallback)
     PrintfAndReportCallback(str);
 }
index 052027111ceb4b8546fae102f5c807a197cb3876..d0e5245f84dab815a6d1ee31f08a77a15df6cfe4 100644 (file)
@@ -37,7 +37,7 @@ struct MemoryMappedSegmentData;
 
 class MemoryMappedSegment {
  public:
-  MemoryMappedSegment(char *buff = nullptr, uptr size = 0)
+  explicit MemoryMappedSegment(char *buff = nullptr, uptr size = 0)
       : filename(buff), filename_size(size), data_(nullptr) {}
   ~MemoryMappedSegment() {}
 
index ea72a57bf3cb4a6b7f2c4a466a8fea0740dfcf82..d02afcfe87ae0879034d1f9a8446e3e7df52787b 100644 (file)
@@ -181,13 +181,14 @@ const mach_header *get_dyld_hdr() {
 // Note that the segment addresses are not necessarily sorted.
 template <u32 kLCSegment, typename SegmentCommand>
 static bool NextSegmentLoad(MemoryMappedSegment *segment,
-MemoryMappedSegmentData *seg_data, MemoryMappingLayoutData &layout_data) {
-  const char *lc = layout_data.current_load_cmd_addr;
-  layout_data.current_load_cmd_addr += ((const load_command *)lc)->cmdsize;
+                            MemoryMappedSegmentData *seg_data,
+                            MemoryMappingLayoutData *layout_data) {
+  const char *lc = layout_data->current_load_cmd_addr;
+  layout_data->current_load_cmd_addr += ((const load_command *)lc)->cmdsize;
   if (((const load_command *)lc)->cmd == kLCSegment) {
     const SegmentCommand* sc = (const SegmentCommand *)lc;
     uptr base_virt_addr, addr_mask;
-    if (layout_data.current_image == kDyldImageIdx) {
+    if (layout_data->current_image == kDyldImageIdx) {
       base_virt_addr = (uptr)get_dyld_hdr();
       // vmaddr is masked with 0xfffff because on macOS versions < 10.12,
       // it contains an absolute address rather than an offset for dyld.
@@ -198,7 +199,7 @@ MemoryMappedSegmentData *seg_data, MemoryMappingLayoutData &layout_data) {
       addr_mask = 0xfffff;
     } else {
       base_virt_addr =
-          (uptr)_dyld_get_image_vmaddr_slide(layout_data.current_image);
+          (uptr)_dyld_get_image_vmaddr_slide(layout_data->current_image);
       addr_mask = ~0;
     }
 
@@ -219,18 +220,18 @@ MemoryMappedSegmentData *seg_data, MemoryMappingLayoutData &layout_data) {
 
     // Return the initial protection.
     segment->protection = sc->initprot;
-    segment->offset = (layout_data.current_filetype ==
+    segment->offset = (layout_data->current_filetype ==
                        /*MH_EXECUTE*/ 0x2)
                           ? sc->vmaddr
                           : sc->fileoff;
     if (segment->filename) {
-      const char *src = (layout_data.current_image == kDyldImageIdx)
+      const char *src = (layout_data->current_image == kDyldImageIdx)
                             ? kDyldPath
-                            : _dyld_get_image_name(layout_data.current_image);
+                            : _dyld_get_image_name(layout_data->current_image);
       internal_strncpy(segment->filename, src, segment->filename_size);
     }
-    segment->arch = layout_data.current_arch;
-    internal_memcpy(segment->uuid, layout_data.current_uuid, kModuleUUIDSize);
+    segment->arch = layout_data->current_arch;
+    internal_memcpy(segment->uuid, layout_data->current_uuid, kModuleUUIDSize);
     return true;
   }
   return false;
@@ -331,14 +332,14 @@ bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) {
 #ifdef MH_MAGIC_64
         case MH_MAGIC_64: {
           if (NextSegmentLoad<LC_SEGMENT_64, struct segment_command_64>(
-          segment, segment->data_, data_))
+                  segment, segment->data_, &data_))
             return true;
           break;
         }
 #endif
         case MH_MAGIC: {
           if (NextSegmentLoad<LC_SEGMENT, struct segment_command>(
-          segment, segment->data_, data_))
+                  segment, segment->data_, &data_))
             return true;
           break;
         }
index ce75cbe5d265094329e3f770e5f0ed19b9a455f4..ef14fb704eed394acf0be36505eaae5f952fa6d2 100644 (file)
@@ -60,8 +60,8 @@ static inline uhwptr *GetCanonicFrame(uptr bp,
   // Nope, this does not look right either. This means the frame after next does
   // not have a valid frame pointer, but we can still extract the caller PC.
   // Unfortunately, there is no way to decide between GCC and LLVM frame
-  // layouts. Assume GCC.
-  return bp_prev - 1;
+  // layouts. Assume LLVM.
+  return bp_prev;
 #else
   return (uhwptr*)bp;
 #endif
@@ -84,21 +84,14 @@ void BufferedStackTrace::UnwindFast(uptr pc, uptr bp, uptr stack_top,
          IsAligned((uptr)frame, sizeof(*frame)) &&
          size < max_depth) {
 #ifdef __powerpc__
-    // PowerPC ABIs specify that the return address is saved on the
-    // *caller's* stack frame.  Thus we must dereference the back chain
-    // to find the caller frame before extracting it.
+    // PowerPC ABIs specify that the return address is saved at offset
+    // 16 of the *caller's* stack frame.  Thus we must dereference the
+    // back chain to find the caller frame before extracting it.
     uhwptr *caller_frame = (uhwptr*)frame[0];
     if (!IsValidFrame((uptr)caller_frame, stack_top, bottom) ||
         !IsAligned((uptr)caller_frame, sizeof(uhwptr)))
       break;
-    // For most ABIs the offset where the return address is saved is two
-    // register sizes.  The exception is the SVR4 ABI, which uses an
-    // offset of only one register size.
-#ifdef _CALL_SYSV
-    uhwptr pc1 = caller_frame[1];
-#else
     uhwptr pc1 = caller_frame[2];
-#endif
 #elif defined(__s390__)
     uhwptr pc1 = frame[14];
 #else
index 2c08274f35cdce65f7cbba6a067e24011f9b673f..4ef305cf17991b4c211f186fd3ca92284ef409f5 100644 (file)
@@ -150,8 +150,9 @@ void __sanitizer_symbolize_global(uptr data_addr, const char *fmt,
 }
 
 SANITIZER_INTERFACE_ATTRIBUTE
-int __sanitizer_get_module_and_offset_for_pc( // NOLINT
-    uptr pc, char *module_name, uptr module_name_len, uptr *pc_offset) {
+int __sanitizer_get_module_and_offset_for_pc(uptr pc, char *module_name,
+                                             uptr module_name_len,
+                                             uptr *pc_offset) {
   return __sanitizer::GetModuleAndOffsetForPc(pc, module_name, module_name_len,
                                               pc_offset);
 }
index b520dc8daca6a787162458115c35f4044b5430f6..651d5056dd9d5feb4a7ca2f8cd1fe52d2080fd77 100644 (file)
@@ -223,10 +223,11 @@ bool ThreadSuspender::SuspendAllThreads() {
       case ThreadLister::Ok:
         break;
     }
-    for (tid_t tid : threads)
+    for (tid_t tid : threads) {
       if (SuspendThread(tid))
         retry = true;
-  };
+    }
+  }
   return suspended_threads_list_.ThreadCount();
 }
 
index f9da7af7e6ab3ae6f2021dae9320d599d1a3a0c6..2d88b1f72fa6d8a2e56e753aa903bfa40321c1c5 100644 (file)
@@ -42,7 +42,7 @@ class SuppressionContext {
   void GetMatched(InternalMmapVector<Suppression *> *matched);
 
  private:
-  static const int kMaxSuppressionTypes = 32;
+  static const int kMaxSuppressionTypes = 64;
   const char **const suppression_types_;
   const int suppression_types_num_;
 
index 3031f28a20e19e71ece9af2a202a5c93361e9aab..c04797dd61b8b6d250046860125d41b66faba526 100644 (file)
@@ -76,7 +76,7 @@ class SymbolizerTool {
 // SymbolizerProcess may not be used from two threads simultaneously.
 class SymbolizerProcess {
  public:
-  explicit SymbolizerProcess(const char *path, bool use_forkpty = false);
+  explicit SymbolizerProcess(const char *path, bool use_posix_spawn = false);
   const char *SendCommand(const char *command);
 
  protected:
@@ -114,7 +114,7 @@ class SymbolizerProcess {
   uptr times_restarted_;
   bool failed_to_start_;
   bool reported_invalid_path_;
-  bool use_forkpty_;
+  bool use_posix_spawn_;
 };
 
 class LLVMSymbolizerProcess;
index 742b9748c98f6d6947ab41e564e15d03f5d63c31..3b19a6836ec53da3d2c4f71123e1e81cc6ffdecf 100644 (file)
@@ -238,7 +238,8 @@ const LoadedModule *Symbolizer::FindModuleForAddress(uptr address) {
 //   <empty line>
 class LLVMSymbolizerProcess : public SymbolizerProcess {
  public:
-  explicit LLVMSymbolizerProcess(const char *path) : SymbolizerProcess(path) {}
+  explicit LLVMSymbolizerProcess(const char *path)
+      : SymbolizerProcess(path, /*use_posix_spawn=*/SANITIZER_MAC) {}
 
  private:
   bool ReachedEndOfOutput(const char *buffer, uptr length) const override {
@@ -452,14 +453,14 @@ const char *LLVMSymbolizer::FormatAndSendCommand(const char *command_prefix,
   return symbolizer_process_->SendCommand(buffer_);
 }
 
-SymbolizerProcess::SymbolizerProcess(const char *path, bool use_forkpty)
+SymbolizerProcess::SymbolizerProcess(const char *path, bool use_posix_spawn)
     : path_(path),
       input_fd_(kInvalidFd),
       output_fd_(kInvalidFd),
       times_restarted_(0),
       failed_to_start_(false),
       reported_invalid_path_(false),
-      use_forkpty_(use_forkpty) {
+      use_posix_spawn_(use_posix_spawn) {
   CHECK(path_);
   CHECK_NE(path_[0], '\0');
 }
index 7bc4b0ce025ffb3c148c5c59344b6c0e88f9ee9f..a619ed092f0bce054c6b7d2c28724fb65d3f8eb3 100644 (file)
@@ -50,14 +50,14 @@ bool DlAddrSymbolizer::SymbolizeData(uptr addr, DataInfo *datainfo) {
 class AtosSymbolizerProcess : public SymbolizerProcess {
  public:
   explicit AtosSymbolizerProcess(const char *path, pid_t parent_pid)
-      : SymbolizerProcess(path, /*use_forkpty*/ true) {
+      : SymbolizerProcess(path, /*use_posix_spawn*/ true) {
     // Put the string command line argument in the object so that it outlives
     // the call to GetArgV.
     internal_snprintf(pid_str_, sizeof(pid_str_), "%d", parent_pid);
   }
 
  private:
-  virtual bool StartSymbolizerSubprocess() override {
+  bool StartSymbolizerSubprocess() override {
     // Configure sandbox before starting atos process.
     return SymbolizerProcess::StartSymbolizerSubprocess();
   }
index 43e6a6d2dbf77cdfb586b28958a2b6796c54d4da..c123ecb11206cca14d1b78683e40aa45edc8d201 100644 (file)
 #include <sys/wait.h>
 #include <unistd.h>
 
-#if SANITIZER_MAC
-#include <util.h>  // for forkpty()
-#endif  // SANITIZER_MAC
-
 // C++ demangling function, as required by Itanium C++ ABI. This is weak,
 // because we do not require a C++ ABI library to be linked to a program
 // using sanitizers; if it's not present, we'll just use the mangled name.
@@ -151,80 +147,32 @@ bool SymbolizerProcess::StartSymbolizerSubprocess() {
     return false;
   }
 
-  int pid = -1;
-
-  int infd[2];
-  internal_memset(&infd, 0, sizeof(infd));
-  int outfd[2];
-  internal_memset(&outfd, 0, sizeof(outfd));
-  if (!CreateTwoHighNumberedPipes(infd, outfd)) {
-    Report("WARNING: Can't create a socket pair to start "
-           "external symbolizer (errno: %d)\n", errno);
-    return false;
-  }
+  const char *argv[kArgVMax];
+  GetArgV(path_, argv);
+  pid_t pid;
 
-  if (use_forkpty_) {
+  if (use_posix_spawn_) {
 #if SANITIZER_MAC
-    fd_t fd = kInvalidFd;
-
-    // forkpty redirects stdout and stderr into a single stream, so we would
-    // receive error messages as standard replies. To avoid that, let's dup
-    // stderr and restore it in the child.
-    int saved_stderr = dup(STDERR_FILENO);
-    CHECK_GE(saved_stderr, 0);
-
-    // We only need one pipe, for stdin of the child.
-    close(outfd[0]);
-    close(outfd[1]);
-
-    // Use forkpty to disable buffering in the new terminal.
-    pid = internal_forkpty(&fd);
-    if (pid == -1) {
-      // forkpty() failed.
-      Report("WARNING: failed to fork external symbolizer (errno: %d)\n",
+    fd_t fd = internal_spawn(argv, &pid);
+    if (fd == kInvalidFd) {
+      Report("WARNING: failed to spawn external symbolizer (errno: %d)\n",
              errno);
       return false;
-    } else if (pid == 0) {
-      // Child subprocess.
-
-      // infd[0] is the child's reading end.
-      close(infd[1]);
-
-      // Set up stdin to read from the pipe.
-      CHECK_GE(dup2(infd[0], STDIN_FILENO), 0);
-      close(infd[0]);
-
-      // Restore stderr.
-      CHECK_GE(dup2(saved_stderr, STDERR_FILENO), 0);
-      close(saved_stderr);
-
-      const char *argv[kArgVMax];
-      GetArgV(path_, argv);
-      execv(path_, const_cast<char **>(&argv[0]));
-      internal__exit(1);
     }
 
-    // Input for the child, infd[1] is our writing end.
-    output_fd_ = infd[1];
-    close(infd[0]);
-
-    // Continue execution in parent process.
     input_fd_ = fd;
-
-    close(saved_stderr);
-
-    // Disable echo in the new terminal, disable CR.
-    struct termios termflags;
-    tcgetattr(fd, &termflags);
-    termflags.c_oflag &= ~ONLCR;
-    termflags.c_lflag &= ~ECHO;
-    tcsetattr(fd, TCSANOW, &termflags);
+    output_fd_ = fd;
 #else  // SANITIZER_MAC
     UNIMPLEMENTED();
 #endif  // SANITIZER_MAC
   } else {
-    const char *argv[kArgVMax];
-    GetArgV(path_, argv);
+    fd_t infd[2] = {}, outfd[2] = {};
+    if (!CreateTwoHighNumberedPipes(infd, outfd)) {
+      Report("WARNING: Can't create a socket pair to start "
+             "external symbolizer (errno: %d)\n", errno);
+      return false;
+    }
+
     pid = StartSubprocess(path_, argv, /* stdin */ outfd[0],
                           /* stdout */ infd[1]);
     if (pid < 0) {
index a8b449b030e75628e3ae122dd141da8e59300f11..c26724ceb7a7d3648d72fe617ea2d4f25f94ceb8 100644 (file)
@@ -106,8 +106,9 @@ void ReportMmapWriteExec(int prot) {
   if (StackTrace::WillUseFastUnwind(fast)) {
     GetThreadStackTopAndBottom(false, &top, &bottom);
     stack->Unwind(kStackTraceMax, pc, bp, nullptr, top, bottom, true);
-  } else
+  } else {
     stack->Unwind(kStackTraceMax, pc, 0, nullptr, 0, 0, false);
+  }
 
   Printf("%s", d.Warning());
   Report("WARNING: %s: writable-executable page usage\n", SanitizerToolName);
@@ -190,9 +191,14 @@ static void ReportDeadlySignalImpl(const SignalContext &sig, u32 tid,
   SanitizerCommonDecorator d;
   Printf("%s", d.Warning());
   const char *description = sig.Describe();
-  Report("ERROR: %s: %s on unknown address %p (pc %p bp %p sp %p T%d)\n",
-         SanitizerToolName, description, (void *)sig.addr, (void *)sig.pc,
-         (void *)sig.bp, (void *)sig.sp, tid);
+  if (sig.is_memory_access && !sig.is_true_faulting_addr)
+    Report("ERROR: %s: %s on unknown address (pc %p bp %p sp %p T%d)\n",
+           SanitizerToolName, description, (void *)sig.pc, (void *)sig.bp,
+           (void *)sig.sp, tid);
+  else
+    Report("ERROR: %s: %s on unknown address %p (pc %p bp %p sp %p T%d)\n",
+           SanitizerToolName, description, (void *)sig.addr, (void *)sig.pc,
+           (void *)sig.bp, (void *)sig.sp, tid);
   Printf("%s", d.Default());
   if (sig.pc < GetPageSizeCached())
     Report("Hint: pc points to the zero page.\n");
@@ -202,7 +208,11 @@ static void ReportDeadlySignalImpl(const SignalContext &sig, u32 tid,
             ? "WRITE"
             : (sig.write_flag == SignalContext::READ ? "READ" : "UNKNOWN");
     Report("The signal is caused by a %s memory access.\n", access_type);
-    if (sig.addr < GetPageSizeCached())
+    if (!sig.is_true_faulting_addr)
+      Report("Hint: this fault was caused by a dereference of a high value "
+             "address (see register values below).  Dissassemble the provided "
+             "pc to learn which register was used.\n");
+    else if (sig.addr < GetPageSizeCached())
       Report("Hint: address points to the zero page.\n");
   }
   MaybeReportNonExecRegion(sig.pc);
index e588c93b9943b1bd54e7562eeea4220cff8ef20b..84be6fc3234209fede5000c39145c4f722a86b26 100644 (file)
@@ -84,7 +84,7 @@ void NORETURN CheckFailed(const char *file, int line, const char *cond,
 
 } // namespace __sanitizer
 
-using namespace __sanitizer;  // NOLINT
+using namespace __sanitizer;
 
 extern "C" {
 SANITIZER_INTERFACE_ATTRIBUTE
index 1a43759e38ae12ac493327bab7f9289a7221dd0b..b2628dcc4dc1f68b1799f3a60021ae33aced9584 100644 (file)
@@ -27,6 +27,8 @@
 
 namespace __sanitizer {
 
+namespace {
+
 //---------------------------- UnwindSlow --------------------------------------
 
 typedef struct {
@@ -46,38 +48,6 @@ release_my_map_info_list_func release_my_map_info_list;
 unwind_backtrace_signal_arch_func unwind_backtrace_signal_arch;
 } // extern "C"
 
-#if SANITIZER_ANDROID
-void SanitizerInitializeUnwinder() {
-  if (AndroidGetApiLevel() >= ANDROID_LOLLIPOP_MR1) return;
-
-  // Pre-lollipop Android can not unwind through signal handler frames with
-  // libgcc unwinder, but it has a libcorkscrew.so library with the necessary
-  // workarounds.
-  void *p = dlopen("libcorkscrew.so", RTLD_LAZY);
-  if (!p) {
-    VReport(1,
-            "Failed to open libcorkscrew.so. You may see broken stack traces "
-            "in SEGV reports.");
-    return;
-  }
-  acquire_my_map_info_list =
-      (acquire_my_map_info_list_func)(uptr)dlsym(p, "acquire_my_map_info_list");
-  release_my_map_info_list =
-      (release_my_map_info_list_func)(uptr)dlsym(p, "release_my_map_info_list");
-  unwind_backtrace_signal_arch = (unwind_backtrace_signal_arch_func)(uptr)dlsym(
-      p, "unwind_backtrace_signal_arch");
-  if (!acquire_my_map_info_list || !release_my_map_info_list ||
-      !unwind_backtrace_signal_arch) {
-    VReport(1,
-            "Failed to find one of the required symbols in libcorkscrew.so. "
-            "You may see broken stack traces in SEGV reports.");
-    acquire_my_map_info_list = 0;
-    unwind_backtrace_signal_arch = 0;
-    release_my_map_info_list = 0;
-  }
-}
-#endif
-
 #if defined(__arm__) && !SANITIZER_NETBSD
 // NetBSD uses dwarf EH
 #define UNWIND_STOP _URC_END_OF_STACK
@@ -119,6 +89,40 @@ _Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, void *param) {
   return UNWIND_CONTINUE;
 }
 
+}  // namespace
+
+#if SANITIZER_ANDROID
+void SanitizerInitializeUnwinder() {
+  if (AndroidGetApiLevel() >= ANDROID_LOLLIPOP_MR1) return;
+
+  // Pre-lollipop Android can not unwind through signal handler frames with
+  // libgcc unwinder, but it has a libcorkscrew.so library with the necessary
+  // workarounds.
+  void *p = dlopen("libcorkscrew.so", RTLD_LAZY);
+  if (!p) {
+    VReport(1,
+            "Failed to open libcorkscrew.so. You may see broken stack traces "
+            "in SEGV reports.");
+    return;
+  }
+  acquire_my_map_info_list =
+      (acquire_my_map_info_list_func)(uptr)dlsym(p, "acquire_my_map_info_list");
+  release_my_map_info_list =
+      (release_my_map_info_list_func)(uptr)dlsym(p, "release_my_map_info_list");
+  unwind_backtrace_signal_arch = (unwind_backtrace_signal_arch_func)(uptr)dlsym(
+      p, "unwind_backtrace_signal_arch");
+  if (!acquire_my_map_info_list || !release_my_map_info_list ||
+      !unwind_backtrace_signal_arch) {
+    VReport(1,
+            "Failed to find one of the required symbols in libcorkscrew.so. "
+            "You may see broken stack traces in SEGV reports.");
+    acquire_my_map_info_list = 0;
+    unwind_backtrace_signal_arch = 0;
+    release_my_map_info_list = 0;
+  }
+}
+#endif
+
 void BufferedStackTrace::UnwindSlow(uptr pc, u32 max_depth) {
   CHECK_GE(max_depth, 2);
   size = 0;
index 4b9ae7db4c13414301a29928a8dec3884fdd41a1..31216f3ec3a6c6b2b211fea8898ee0498e2d952b 100644 (file)
@@ -23,11 +23,7 @@ namespace __sanitizer {
 template<typename T>
 class Vector {
  public:
-  explicit Vector()
-      : begin_()
-      , end_()
-      , last_() {
-  }
+  Vector() : begin_(), end_(), last_() {}
 
   ~Vector() {
     if (begin_)
index c98e3d42f43fe6fb5230ddf0249cb52e25f0d955..36dde49d8708343337fe5b965b5408cec8c50d19 100644 (file)
@@ -239,6 +239,11 @@ bool MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name) {
   return true;
 }
 
+bool MmapFixedSuperNoReserve(uptr fixed_addr, uptr size, const char *name) {
+  // FIXME: Windows support large pages too. Might be worth checking
+  return MmapFixedNoReserve(fixed_addr, size, name);
+}
+
 // Memory space mapped by 'MmapFixedOrDie' must have been reserved by
 // 'MmapFixedNoAccess'.
 void *MmapFixedOrDie(uptr fixed_addr, uptr size, const char *name) {
@@ -671,7 +676,7 @@ static int RunAtexit() {
   return ret;
 }
 
-#pragma section(".CRT$XID", long, read)  // NOLINT
+#pragma section(".CRT$XID", long, read)
 __declspec(allocate(".CRT$XID")) int (*__run_atexit)() = RunAtexit;
 #endif
 
@@ -940,6 +945,11 @@ bool SignalContext::IsMemoryAccess() const {
   return GetWriteFlag() != SignalContext::UNKNOWN;
 }
 
+bool SignalContext::IsTrueFaultingAddress() const {
+  // FIXME: Provide real implementation for this. See Linux and Mac variants.
+  return IsMemoryAccess();
+}
+
 SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
   EXCEPTION_RECORD *exception_record = (EXCEPTION_RECORD *)siginfo;
   // The contents of this array are documented at
index bcd94a08dc4412bb609fd9b877f4a2bdcc9fa089..bfe38a3323674626bb33e48657bf19b744320171 100644 (file)
@@ -43,6 +43,8 @@
 #define STRINGIFY_(A) #A
 #define STRINGIFY(A) STRINGIFY_(A)
 
+#if !SANITIZER_GO
+
 // ----------------- A workaround for the absence of weak symbols --------------
 // We don't have a direct equivalent of weak symbols when using MSVC, but we can
 // use the /alternatename directive to tell the linker to default a specific
 //     return a >= b;
 //   }
 //
+
+#else // SANITIZER_GO
+
+// Go neither needs nor wants weak references.
+// The shenanigans above don't work for gcc.
+# define WIN_WEAK_EXPORT_DEF(ReturnType, Name, ...)                            \
+  extern "C" ReturnType Name(__VA_ARGS__)
+
+#endif // SANITIZER_GO
+
 #endif // SANITIZER_WINDOWS
 #endif // SANITIZER_WIN_DEFS_H
index aa0eb4d43a4d065b2d79429f5dea73f95125fd97..1562c161a76260ab70aa84c1abbaec95149e9b00 100644 (file)
@@ -54,8 +54,8 @@ int dllThunkInterceptWhenPossible(const char* main_function,
 #define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name)
 #include "sanitizer_common_interface.inc"
 
-#pragma section(".DLLTH$A", read)  // NOLINT
-#pragma section(".DLLTH$Z", read)  // NOLINT
+#pragma section(".DLLTH$A", read)
+#pragma section(".DLLTH$Z", read)
 
 typedef void (*DllThunkCB)();
 extern "C" {
@@ -85,7 +85,7 @@ extern "C" int __dll_thunk_init() {
 
 // We want to call dll_thunk_init before C/C++ initializers / constructors are
 // executed, otherwise functions like memset might be invoked.
-#pragma section(".CRT$XIB", long, read)  // NOLINT
+#pragma section(".CRT$XIB", long, read)
 __declspec(allocate(".CRT$XIB")) int (*__dll_thunk_preinit)() =
     __dll_thunk_init;
 
@@ -94,7 +94,7 @@ static void WINAPI dll_thunk_thread_init(void *mod, unsigned long reason,
   if (reason == /*DLL_PROCESS_ATTACH=*/1) __dll_thunk_init();
 }
 
-#pragma section(".CRT$XLAB", long, read)  // NOLINT
+#pragma section(".CRT$XLAB", long, read)
 __declspec(allocate(".CRT$XLAB")) void (WINAPI *__dll_thunk_tls_init)(void *,
     unsigned long, void *) = dll_thunk_thread_init;
 
index a6f34c27788b9df818c5d5e0ea8f625e5c95adc9..b14bbf76d9a765bb88702743e7f659709d4f81a1 100644 (file)
@@ -38,6 +38,7 @@ int interceptWhenPossible(uptr dll_function, const char *real_function) {
 
 // Declare weak hooks.
 extern "C" {
+void __sanitizer_on_print(const char *str);
 void __sanitizer_weak_hook_memcmp(uptr called_pc, const void *s1,
                                   const void *s2, uptr n, int result);
 void __sanitizer_weak_hook_strcmp(uptr called_pc, const char *s1,
@@ -53,8 +54,8 @@ void __sanitizer_weak_hook_strstr(uptr called_pc, const char *s1,
 #define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name)
 #include "sanitizer_common_interface.inc"
 
-#pragma section(".WEAK$A", read)  // NOLINT
-#pragma section(".WEAK$Z", read)  // NOLINT
+#pragma section(".WEAK$A", read)
+#pragma section(".WEAK$Z", read)
 
 typedef void (*InterceptCB)();
 extern "C" {
@@ -77,7 +78,7 @@ static int weak_intercept_init() {
   return 0;
 }
 
-#pragma section(".CRT$XIB", long, read)  // NOLINT
+#pragma section(".CRT$XIB", long, read)
 __declspec(allocate(".CRT$XIB")) int (*__weak_intercept_preinit)() =
     weak_intercept_init;
 
@@ -86,7 +87,7 @@ static void WINAPI weak_intercept_thread_init(void *mod, unsigned long reason,
   if (reason == /*DLL_PROCESS_ATTACH=*/1) weak_intercept_init();
 }
 
-#pragma section(".CRT$XLAB", long, read)  // NOLINT
+#pragma section(".CRT$XLAB", long, read)
 __declspec(allocate(".CRT$XLAB")) void(WINAPI *__weak_intercept_tls_init)(
     void *, unsigned long, void *) = weak_intercept_thread_init;
 
index 6f1d1f75f600e4f0d95d6c7b42e48ca2ac976a5b..298297af31eb6b56f02b4d117bd47f4466d52bf2 100644 (file)
@@ -31,11 +31,11 @@ typedef void (^dispatch_block_t)(void);
 typedef void (^dispatch_io_handler_t)(bool done, dispatch_data_t data,
                                       int error);
 
-typedef long dispatch_once_t; // NOLINT
+typedef long dispatch_once_t;
 typedef __sanitizer::u64 dispatch_time_t;
-typedef int dispatch_fd_t; // NOLINT
-typedef unsigned long dispatch_io_type_t; // NOLINT
-typedef unsigned long dispatch_io_close_flags_t; // NOLINT
+typedef int dispatch_fd_t;
+typedef unsigned long dispatch_io_type_t;
+typedef unsigned long dispatch_io_close_flags_t;
 
 extern "C" {
 void *dispatch_get_context(dispatch_object_t object);
@@ -57,10 +57,10 @@ extern const dispatch_block_t _dispatch_data_destructor_munmap;
 #endif
 
 // Data types used in dispatch APIs
-typedef unsigned long size_t; // NOLINT
-typedef unsigned long uintptr_t; // NOLINT
+typedef unsigned long size_t;
+typedef unsigned long uintptr_t;
 typedef __sanitizer::s64 off_t;
 typedef __sanitizer::u16 mode_t;
-typedef long long_t; // NOLINT
+typedef long long_t;
 
 #endif  // TSAN_DISPATCH_DEFS_H
index efc1013087ca9f83ac14fe3839b9ba100a6137e9..0faa1ee93a139ea3600b269f9f0ff029270003e1 100644 (file)
@@ -25,7 +25,7 @@ static TagData registered_tags[kExternalTagMax] = {
   {},
   {"Swift variable", "Swift access race"},
 };
-static atomic_uint32_t used_tags{kExternalTagFirstUserAvailable};  // NOLINT.
+static atomic_uint32_t used_tags{kExternalTagFirstUserAvailable};
 static TagData *GetTagData(uptr tag) {
   // Invalid/corrupted tag?  Better return NULL and let the caller deal with it.
   if (tag >= atomic_load(&used_tags, memory_order_relaxed)) return nullptr;
index db01d809531ac8eb15aac4ac8a0c15b204f15886..50a6b56916aa7d4667c68907b5e8305871bdfef3 100644 (file)
@@ -86,7 +86,8 @@ static FdDesc *fddesc(ThreadState *thr, uptr pc, int fd) {
     else
       user_free(thr, pc, p, false);
   }
-  return &((FdDesc*)l1)[fd % kTableSizeL2];  // NOLINT
+  FdDesc *fds = reinterpret_cast<FdDesc *>(l1);
+  return &fds[fd % kTableSizeL2];
 }
 
 // pd must be already ref'ed.
diff --git a/libsanitizer/tsan/tsan_interceptors.cpp b/libsanitizer/tsan/tsan_interceptors.cpp
deleted file mode 100644 (file)
index 9e1b9ed..0000000
+++ /dev/null
@@ -1,2855 +0,0 @@
-//===-- tsan_interceptors.cpp ---------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is a part of ThreadSanitizer (TSan), a race detector.
-//
-// FIXME: move as many interceptors as possible into
-// sanitizer_common/sanitizer_common_interceptors.inc
-//===----------------------------------------------------------------------===//
-
-#include "sanitizer_common/sanitizer_atomic.h"
-#include "sanitizer_common/sanitizer_errno.h"
-#include "sanitizer_common/sanitizer_libc.h"
-#include "sanitizer_common/sanitizer_linux.h"
-#include "sanitizer_common/sanitizer_platform_limits_netbsd.h"
-#include "sanitizer_common/sanitizer_platform_limits_posix.h"
-#include "sanitizer_common/sanitizer_placement_new.h"
-#include "sanitizer_common/sanitizer_posix.h"
-#include "sanitizer_common/sanitizer_stacktrace.h"
-#include "sanitizer_common/sanitizer_tls_get_addr.h"
-#include "interception/interception.h"
-#include "tsan_interceptors.h"
-#include "tsan_interface.h"
-#include "tsan_platform.h"
-#include "tsan_suppressions.h"
-#include "tsan_rtl.h"
-#include "tsan_mman.h"
-#include "tsan_fd.h"
-
-
-using namespace __tsan;  // NOLINT
-
-#if SANITIZER_FREEBSD || SANITIZER_MAC
-#define stdout __stdoutp
-#define stderr __stderrp
-#endif
-
-#if SANITIZER_NETBSD
-#define dirfd(dirp) (*(int *)(dirp))
-#define fileno_unlocked(fp) \
-  (((__sanitizer_FILE*)fp)->_file == -1 ? -1 : \
-   (int)(unsigned short)(((__sanitizer_FILE*)fp)->_file))  // NOLINT
-
-#define stdout ((__sanitizer_FILE*)&__sF[1])
-#define stderr ((__sanitizer_FILE*)&__sF[2])
-
-#define nanosleep __nanosleep50
-#define vfork __vfork14
-#endif
-
-#if SANITIZER_ANDROID
-#define mallopt(a, b)
-#endif
-
-#ifdef __mips__
-const int kSigCount = 129;
-#else
-const int kSigCount = 65;
-#endif
-
-#ifdef __mips__
-struct ucontext_t {
-  u64 opaque[768 / sizeof(u64) + 1];
-};
-#else
-struct ucontext_t {
-  // The size is determined by looking at sizeof of real ucontext_t on linux.
-  u64 opaque[936 / sizeof(u64) + 1];
-};
-#endif
-
-#if defined(__x86_64__) || defined(__mips__) || SANITIZER_PPC64V1
-#define PTHREAD_ABI_BASE  "GLIBC_2.3.2"
-#elif defined(__aarch64__) || SANITIZER_PPC64V2
-#define PTHREAD_ABI_BASE  "GLIBC_2.17"
-#endif
-
-extern "C" int pthread_attr_init(void *attr);
-extern "C" int pthread_attr_destroy(void *attr);
-DECLARE_REAL(int, pthread_attr_getdetachstate, void *, void *)
-extern "C" int pthread_attr_setstacksize(void *attr, uptr stacksize);
-extern "C" int pthread_key_create(unsigned *key, void (*destructor)(void* v));
-extern "C" int pthread_setspecific(unsigned key, const void *v);
-DECLARE_REAL(int, pthread_mutexattr_gettype, void *, void *)
-DECLARE_REAL(int, fflush, __sanitizer_FILE *fp)
-DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr size)
-DECLARE_REAL_AND_INTERCEPTOR(void, free, void *ptr)
-extern "C" void *pthread_self();
-extern "C" void _exit(int status);
-#if !SANITIZER_NETBSD
-extern "C" int fileno_unlocked(void *stream);
-extern "C" int dirfd(void *dirp);
-#endif
-#if !SANITIZER_FREEBSD && !SANITIZER_ANDROID && !SANITIZER_NETBSD
-extern "C" int mallopt(int param, int value);
-#endif
-#if SANITIZER_NETBSD
-extern __sanitizer_FILE __sF[];
-#else
-extern __sanitizer_FILE *stdout, *stderr;
-#endif
-#if !SANITIZER_FREEBSD && !SANITIZER_MAC && !SANITIZER_NETBSD
-const int PTHREAD_MUTEX_RECURSIVE = 1;
-const int PTHREAD_MUTEX_RECURSIVE_NP = 1;
-#else
-const int PTHREAD_MUTEX_RECURSIVE = 2;
-const int PTHREAD_MUTEX_RECURSIVE_NP = 2;
-#endif
-#if !SANITIZER_FREEBSD && !SANITIZER_MAC && !SANITIZER_NETBSD
-const int EPOLL_CTL_ADD = 1;
-#endif
-const int SIGILL = 4;
-const int SIGABRT = 6;
-const int SIGFPE = 8;
-const int SIGSEGV = 11;
-const int SIGPIPE = 13;
-const int SIGTERM = 15;
-#if defined(__mips__) || SANITIZER_FREEBSD || SANITIZER_MAC || SANITIZER_NETBSD
-const int SIGBUS = 10;
-const int SIGSYS = 12;
-#else
-const int SIGBUS = 7;
-const int SIGSYS = 31;
-#endif
-void *const MAP_FAILED = (void*)-1;
-#if SANITIZER_NETBSD
-const int PTHREAD_BARRIER_SERIAL_THREAD = 1234567;
-#elif !SANITIZER_MAC
-const int PTHREAD_BARRIER_SERIAL_THREAD = -1;
-#endif
-const int MAP_FIXED = 0x10;
-typedef long long_t;  // NOLINT
-
-// From /usr/include/unistd.h
-# define F_ULOCK 0      /* Unlock a previously locked region.  */
-# define F_LOCK  1      /* Lock a region for exclusive use.  */
-# define F_TLOCK 2      /* Test and lock a region for exclusive use.  */
-# define F_TEST  3      /* Test a region for other processes locks.  */
-
-#if SANITIZER_FREEBSD || SANITIZER_MAC || SANITIZER_NETBSD
-const int SA_SIGINFO = 0x40;
-const int SIG_SETMASK = 3;
-#elif defined(__mips__)
-const int SA_SIGINFO = 8;
-const int SIG_SETMASK = 3;
-#else
-const int SA_SIGINFO = 4;
-const int SIG_SETMASK = 2;
-#endif
-
-#define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED \
-  (cur_thread_init(), !cur_thread()->is_inited)
-
-namespace __tsan {
-struct SignalDesc {
-  bool armed;
-  bool sigaction;
-  __sanitizer_siginfo siginfo;
-  ucontext_t ctx;
-};
-
-struct ThreadSignalContext {
-  int int_signal_send;
-  atomic_uintptr_t in_blocking_func;
-  atomic_uintptr_t have_pending_signals;
-  SignalDesc pending_signals[kSigCount];
-  // emptyset and oldset are too big for stack.
-  __sanitizer_sigset_t emptyset;
-  __sanitizer_sigset_t oldset;
-};
-
-// The sole reason tsan wraps atexit callbacks is to establish synchronization
-// between callback setup and callback execution.
-struct AtExitCtx {
-  void (*f)();
-  void *arg;
-};
-
-// InterceptorContext holds all global data required for interceptors.
-// It's explicitly constructed in InitializeInterceptors with placement new
-// and is never destroyed. This allows usage of members with non-trivial
-// constructors and destructors.
-struct InterceptorContext {
-  // The object is 64-byte aligned, because we want hot data to be located
-  // in a single cache line if possible (it's accessed in every interceptor).
-  ALIGNED(64) LibIgnore libignore;
-  __sanitizer_sigaction sigactions[kSigCount];
-#if !SANITIZER_MAC && !SANITIZER_NETBSD
-  unsigned finalize_key;
-#endif
-
-  BlockingMutex atexit_mu;
-  Vector<struct AtExitCtx *> AtExitStack;
-
-  InterceptorContext()
-      : libignore(LINKER_INITIALIZED), AtExitStack() {
-  }
-};
-
-static ALIGNED(64) char interceptor_placeholder[sizeof(InterceptorContext)];
-InterceptorContext *interceptor_ctx() {
-  return reinterpret_cast<InterceptorContext*>(&interceptor_placeholder[0]);
-}
-
-LibIgnore *libignore() {
-  return &interceptor_ctx()->libignore;
-}
-
-void InitializeLibIgnore() {
-  const SuppressionContext &supp = *Suppressions();
-  const uptr n = supp.SuppressionCount();
-  for (uptr i = 0; i < n; i++) {
-    const Suppression *s = supp.SuppressionAt(i);
-    if (0 == internal_strcmp(s->type, kSuppressionLib))
-      libignore()->AddIgnoredLibrary(s->templ);
-  }
-  if (flags()->ignore_noninstrumented_modules)
-    libignore()->IgnoreNoninstrumentedModules(true);
-  libignore()->OnLibraryLoaded(0);
-}
-
-// The following two hooks can be used by for cooperative scheduling when
-// locking.
-#ifdef TSAN_EXTERNAL_HOOKS
-void OnPotentiallyBlockingRegionBegin();
-void OnPotentiallyBlockingRegionEnd();
-#else
-SANITIZER_WEAK_CXX_DEFAULT_IMPL void OnPotentiallyBlockingRegionBegin() {}
-SANITIZER_WEAK_CXX_DEFAULT_IMPL void OnPotentiallyBlockingRegionEnd() {}
-#endif
-
-}  // namespace __tsan
-
-static ThreadSignalContext *SigCtx(ThreadState *thr) {
-  ThreadSignalContext *ctx = (ThreadSignalContext*)thr->signal_ctx;
-  if (ctx == 0 && !thr->is_dead) {
-    ctx = (ThreadSignalContext*)MmapOrDie(sizeof(*ctx), "ThreadSignalContext");
-    MemoryResetRange(thr, (uptr)&SigCtx, (uptr)ctx, sizeof(*ctx));
-    thr->signal_ctx = ctx;
-  }
-  return ctx;
-}
-
-ScopedInterceptor::ScopedInterceptor(ThreadState *thr, const char *fname,
-                                     uptr pc)
-    : thr_(thr), pc_(pc), in_ignored_lib_(false), ignoring_(false) {
-  Initialize(thr);
-  if (!thr_->is_inited) return;
-  if (!thr_->ignore_interceptors) FuncEntry(thr, pc);
-  DPrintf("#%d: intercept %s()\n", thr_->tid, fname);
-  ignoring_ =
-      !thr_->in_ignored_lib && libignore()->IsIgnored(pc, &in_ignored_lib_);
-  EnableIgnores();
-}
-
-ScopedInterceptor::~ScopedInterceptor() {
-  if (!thr_->is_inited) return;
-  DisableIgnores();
-  if (!thr_->ignore_interceptors) {
-    ProcessPendingSignals(thr_);
-    FuncExit(thr_);
-    CheckNoLocks(thr_);
-  }
-}
-
-void ScopedInterceptor::EnableIgnores() {
-  if (ignoring_) {
-    ThreadIgnoreBegin(thr_, pc_, /*save_stack=*/false);
-    if (flags()->ignore_noninstrumented_modules) thr_->suppress_reports++;
-    if (in_ignored_lib_) {
-      DCHECK(!thr_->in_ignored_lib);
-      thr_->in_ignored_lib = true;
-    }
-  }
-}
-
-void ScopedInterceptor::DisableIgnores() {
-  if (ignoring_) {
-    ThreadIgnoreEnd(thr_, pc_);
-    if (flags()->ignore_noninstrumented_modules) thr_->suppress_reports--;
-    if (in_ignored_lib_) {
-      DCHECK(thr_->in_ignored_lib);
-      thr_->in_ignored_lib = false;
-    }
-  }
-}
-
-#define TSAN_INTERCEPT(func) INTERCEPT_FUNCTION(func)
-#if SANITIZER_FREEBSD
-# define TSAN_INTERCEPT_VER(func, ver) INTERCEPT_FUNCTION(func)
-# define TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(func)
-# define TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS_THR(func)
-#elif SANITIZER_NETBSD
-# define TSAN_INTERCEPT_VER(func, ver) INTERCEPT_FUNCTION(func)
-# define TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(func) \
-         INTERCEPT_FUNCTION(__libc_##func)
-# define TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS_THR(func) \
-         INTERCEPT_FUNCTION(__libc_thr_##func)
-#else
-# define TSAN_INTERCEPT_VER(func, ver) INTERCEPT_FUNCTION_VER(func, ver)
-# define TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(func)
-# define TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS_THR(func)
-#endif
-
-#define READ_STRING_OF_LEN(thr, pc, s, len, n)                 \
-  MemoryAccessRange((thr), (pc), (uptr)(s),                         \
-    common_flags()->strict_string_checks ? (len) + 1 : (n), false)
-
-#define READ_STRING(thr, pc, s, n)                             \
-    READ_STRING_OF_LEN((thr), (pc), (s), internal_strlen(s), (n))
-
-#define BLOCK_REAL(name) (BlockingCall(thr), REAL(name))
-
-struct BlockingCall {
-  explicit BlockingCall(ThreadState *thr)
-      : thr(thr)
-      , ctx(SigCtx(thr)) {
-    for (;;) {
-      atomic_store(&ctx->in_blocking_func, 1, memory_order_relaxed);
-      if (atomic_load(&ctx->have_pending_signals, memory_order_relaxed) == 0)
-        break;
-      atomic_store(&ctx->in_blocking_func, 0, memory_order_relaxed);
-      ProcessPendingSignals(thr);
-    }
-    // When we are in a "blocking call", we process signals asynchronously
-    // (right when they arrive). In this context we do not expect to be
-    // executing any user/runtime code. The known interceptor sequence when
-    // this is not true is: pthread_join -> munmap(stack). It's fine
-    // to ignore munmap in this case -- we handle stack shadow separately.
-    thr->ignore_interceptors++;
-  }
-
-  ~BlockingCall() {
-    thr->ignore_interceptors--;
-    atomic_store(&ctx->in_blocking_func, 0, memory_order_relaxed);
-  }
-
-  ThreadState *thr;
-  ThreadSignalContext *ctx;
-};
-
-TSAN_INTERCEPTOR(unsigned, sleep, unsigned sec) {
-  SCOPED_TSAN_INTERCEPTOR(sleep, sec);
-  unsigned res = BLOCK_REAL(sleep)(sec);
-  AfterSleep(thr, pc);
-  return res;
-}
-
-TSAN_INTERCEPTOR(int, usleep, long_t usec) {
-  SCOPED_TSAN_INTERCEPTOR(usleep, usec);
-  int res = BLOCK_REAL(usleep)(usec);
-  AfterSleep(thr, pc);
-  return res;
-}
-
-TSAN_INTERCEPTOR(int, nanosleep, void *req, void *rem) {
-  SCOPED_TSAN_INTERCEPTOR(nanosleep, req, rem);
-  int res = BLOCK_REAL(nanosleep)(req, rem);
-  AfterSleep(thr, pc);
-  return res;
-}
-
-TSAN_INTERCEPTOR(int, pause, int fake) {
-  SCOPED_TSAN_INTERCEPTOR(pause, fake);
-  return BLOCK_REAL(pause)(fake);
-}
-
-static void at_exit_wrapper() {
-  AtExitCtx *ctx;
-  {
-    // Ensure thread-safety.
-    BlockingMutexLock l(&interceptor_ctx()->atexit_mu);
-
-    // Pop AtExitCtx from the top of the stack of callback functions
-    uptr element = interceptor_ctx()->AtExitStack.Size() - 1;
-    ctx = interceptor_ctx()->AtExitStack[element];
-    interceptor_ctx()->AtExitStack.PopBack();
-  }
-
-  Acquire(cur_thread(), (uptr)0, (uptr)ctx);
-  ((void(*)())ctx->f)();
-  InternalFree(ctx);
-}
-
-static void cxa_at_exit_wrapper(void *arg) {
-  Acquire(cur_thread(), 0, (uptr)arg);
-  AtExitCtx *ctx = (AtExitCtx*)arg;
-  ((void(*)(void *arg))ctx->f)(ctx->arg);
-  InternalFree(ctx);
-}
-
-static int setup_at_exit_wrapper(ThreadState *thr, uptr pc, void(*f)(),
-      void *arg, void *dso);
-
-#if !SANITIZER_ANDROID
-TSAN_INTERCEPTOR(int, atexit, void (*f)()) {
-  if (in_symbolizer())
-    return 0;
-  // We want to setup the atexit callback even if we are in ignored lib
-  // or after fork.
-  SCOPED_INTERCEPTOR_RAW(atexit, f);
-  return setup_at_exit_wrapper(thr, pc, (void(*)())f, 0, 0);
-}
-#endif
-
-TSAN_INTERCEPTOR(int, __cxa_atexit, void (*f)(void *a), void *arg, void *dso) {
-  if (in_symbolizer())
-    return 0;
-  SCOPED_TSAN_INTERCEPTOR(__cxa_atexit, f, arg, dso);
-  return setup_at_exit_wrapper(thr, pc, (void(*)())f, arg, dso);
-}
-
-static int setup_at_exit_wrapper(ThreadState *thr, uptr pc, void(*f)(),
-      void *arg, void *dso) {
-  AtExitCtx *ctx = (AtExitCtx*)InternalAlloc(sizeof(AtExitCtx));
-  ctx->f = f;
-  ctx->arg = arg;
-  Release(thr, pc, (uptr)ctx);
-  // Memory allocation in __cxa_atexit will race with free during exit,
-  // because we do not see synchronization around atexit callback list.
-  ThreadIgnoreBegin(thr, pc);
-  int res;
-  if (!dso) {
-    // NetBSD does not preserve the 2nd argument if dso is equal to 0
-    // Store ctx in a local stack-like structure
-
-    // Ensure thread-safety.
-    BlockingMutexLock l(&interceptor_ctx()->atexit_mu);
-
-    res = REAL(__cxa_atexit)((void (*)(void *a))at_exit_wrapper, 0, 0);
-    // Push AtExitCtx on the top of the stack of callback functions
-    if (!res) {
-      interceptor_ctx()->AtExitStack.PushBack(ctx);
-    }
-  } else {
-    res = REAL(__cxa_atexit)(cxa_at_exit_wrapper, ctx, dso);
-  }
-  ThreadIgnoreEnd(thr, pc);
-  return res;
-}
-
-#if !SANITIZER_MAC && !SANITIZER_NETBSD
-static void on_exit_wrapper(int status, void *arg) {
-  ThreadState *thr = cur_thread();
-  uptr pc = 0;
-  Acquire(thr, pc, (uptr)arg);
-  AtExitCtx *ctx = (AtExitCtx*)arg;
-  ((void(*)(int status, void *arg))ctx->f)(status, ctx->arg);
-  InternalFree(ctx);
-}
-
-TSAN_INTERCEPTOR(int, on_exit, void(*f)(int, void*), void *arg) {
-  if (in_symbolizer())
-    return 0;
-  SCOPED_TSAN_INTERCEPTOR(on_exit, f, arg);
-  AtExitCtx *ctx = (AtExitCtx*)InternalAlloc(sizeof(AtExitCtx));
-  ctx->f = (void(*)())f;
-  ctx->arg = arg;
-  Release(thr, pc, (uptr)ctx);
-  // Memory allocation in __cxa_atexit will race with free during exit,
-  // because we do not see synchronization around atexit callback list.
-  ThreadIgnoreBegin(thr, pc);
-  int res = REAL(on_exit)(on_exit_wrapper, ctx);
-  ThreadIgnoreEnd(thr, pc);
-  return res;
-}
-#define TSAN_MAYBE_INTERCEPT_ON_EXIT TSAN_INTERCEPT(on_exit)
-#else
-#define TSAN_MAYBE_INTERCEPT_ON_EXIT
-#endif
-
-// Cleanup old bufs.
-static void JmpBufGarbageCollect(ThreadState *thr, uptr sp) {
-  for (uptr i = 0; i < thr->jmp_bufs.Size(); i++) {
-    JmpBuf *buf = &thr->jmp_bufs[i];
-    if (buf->sp <= sp) {
-      uptr sz = thr->jmp_bufs.Size();
-      internal_memcpy(buf, &thr->jmp_bufs[sz - 1], sizeof(*buf));
-      thr->jmp_bufs.PopBack();
-      i--;
-    }
-  }
-}
-
-static void SetJmp(ThreadState *thr, uptr sp) {
-  if (!thr->is_inited)  // called from libc guts during bootstrap
-    return;
-  // Cleanup old bufs.
-  JmpBufGarbageCollect(thr, sp);
-  // Remember the buf.
-  JmpBuf *buf = thr->jmp_bufs.PushBack();
-  buf->sp = sp;
-  buf->shadow_stack_pos = thr->shadow_stack_pos;
-  ThreadSignalContext *sctx = SigCtx(thr);
-  buf->int_signal_send = sctx ? sctx->int_signal_send : 0;
-  buf->in_blocking_func = sctx ?
-      atomic_load(&sctx->in_blocking_func, memory_order_relaxed) :
-      false;
-  buf->in_signal_handler = atomic_load(&thr->in_signal_handler,
-      memory_order_relaxed);
-}
-
-static void LongJmp(ThreadState *thr, uptr *env) {
-  uptr sp = ExtractLongJmpSp(env);
-  // Find the saved buf with matching sp.
-  for (uptr i = 0; i < thr->jmp_bufs.Size(); i++) {
-    JmpBuf *buf = &thr->jmp_bufs[i];
-    if (buf->sp == sp) {
-      CHECK_GE(thr->shadow_stack_pos, buf->shadow_stack_pos);
-      // Unwind the stack.
-      while (thr->shadow_stack_pos > buf->shadow_stack_pos)
-        FuncExit(thr);
-      ThreadSignalContext *sctx = SigCtx(thr);
-      if (sctx) {
-        sctx->int_signal_send = buf->int_signal_send;
-        atomic_store(&sctx->in_blocking_func, buf->in_blocking_func,
-            memory_order_relaxed);
-      }
-      atomic_store(&thr->in_signal_handler, buf->in_signal_handler,
-          memory_order_relaxed);
-      JmpBufGarbageCollect(thr, buf->sp - 1);  // do not collect buf->sp
-      return;
-    }
-  }
-  Printf("ThreadSanitizer: can't find longjmp buf\n");
-  CHECK(0);
-}
-
-// FIXME: put everything below into a common extern "C" block?
-extern "C" void __tsan_setjmp(uptr sp) {
-  cur_thread_init();
-  SetJmp(cur_thread(), sp);
-}
-
-#if SANITIZER_MAC
-TSAN_INTERCEPTOR(int, setjmp, void *env);
-TSAN_INTERCEPTOR(int, _setjmp, void *env);
-TSAN_INTERCEPTOR(int, sigsetjmp, void *env);
-#else  // SANITIZER_MAC
-
-#if SANITIZER_NETBSD
-#define setjmp_symname __setjmp14
-#define sigsetjmp_symname __sigsetjmp14
-#else
-#define setjmp_symname setjmp
-#define sigsetjmp_symname sigsetjmp
-#endif
-
-#define TSAN_INTERCEPTOR_SETJMP_(x) __interceptor_ ## x
-#define TSAN_INTERCEPTOR_SETJMP__(x) TSAN_INTERCEPTOR_SETJMP_(x)
-#define TSAN_INTERCEPTOR_SETJMP TSAN_INTERCEPTOR_SETJMP__(setjmp_symname)
-#define TSAN_INTERCEPTOR_SIGSETJMP TSAN_INTERCEPTOR_SETJMP__(sigsetjmp_symname)
-
-#define TSAN_STRING_SETJMP SANITIZER_STRINGIFY(setjmp_symname)
-#define TSAN_STRING_SIGSETJMP SANITIZER_STRINGIFY(sigsetjmp_symname)
-
-// Not called.  Merely to satisfy TSAN_INTERCEPT().
-extern "C" SANITIZER_INTERFACE_ATTRIBUTE
-int TSAN_INTERCEPTOR_SETJMP(void *env);
-extern "C" int TSAN_INTERCEPTOR_SETJMP(void *env) {
-  CHECK(0);
-  return 0;
-}
-
-// FIXME: any reason to have a separate declaration?
-extern "C" SANITIZER_INTERFACE_ATTRIBUTE
-int __interceptor__setjmp(void *env);
-extern "C" int __interceptor__setjmp(void *env) {
-  CHECK(0);
-  return 0;
-}
-
-extern "C" SANITIZER_INTERFACE_ATTRIBUTE
-int TSAN_INTERCEPTOR_SIGSETJMP(void *env);
-extern "C" int TSAN_INTERCEPTOR_SIGSETJMP(void *env) {
-  CHECK(0);
-  return 0;
-}
-
-#if !SANITIZER_NETBSD
-extern "C" SANITIZER_INTERFACE_ATTRIBUTE
-int __interceptor___sigsetjmp(void *env);
-extern "C" int __interceptor___sigsetjmp(void *env) {
-  CHECK(0);
-  return 0;
-}
-#endif
-
-extern "C" int setjmp_symname(void *env);
-extern "C" int _setjmp(void *env);
-extern "C" int sigsetjmp_symname(void *env);
-#if !SANITIZER_NETBSD
-extern "C" int __sigsetjmp(void *env);
-#endif
-DEFINE_REAL(int, setjmp_symname, void *env)
-DEFINE_REAL(int, _setjmp, void *env)
-DEFINE_REAL(int, sigsetjmp_symname, void *env)
-#if !SANITIZER_NETBSD
-DEFINE_REAL(int, __sigsetjmp, void *env)
-#endif
-#endif  // SANITIZER_MAC
-
-#if SANITIZER_NETBSD
-#define longjmp_symname __longjmp14
-#define siglongjmp_symname __siglongjmp14
-#else
-#define longjmp_symname longjmp
-#define siglongjmp_symname siglongjmp
-#endif
-
-TSAN_INTERCEPTOR(void, longjmp_symname, uptr *env, int val) {
-  // Note: if we call REAL(longjmp) in the context of ScopedInterceptor,
-  // bad things will happen. We will jump over ScopedInterceptor dtor and can
-  // leave thr->in_ignored_lib set.
-  {
-    SCOPED_INTERCEPTOR_RAW(longjmp_symname, env, val);
-  }
-  LongJmp(cur_thread(), env);
-  REAL(longjmp_symname)(env, val);
-}
-
-TSAN_INTERCEPTOR(void, siglongjmp_symname, uptr *env, int val) {
-  {
-    SCOPED_INTERCEPTOR_RAW(siglongjmp_symname, env, val);
-  }
-  LongJmp(cur_thread(), env);
-  REAL(siglongjmp_symname)(env, val);
-}
-
-#if SANITIZER_NETBSD
-TSAN_INTERCEPTOR(void, _longjmp, uptr *env, int val) {
-  {
-    SCOPED_INTERCEPTOR_RAW(_longjmp, env, val);
-  }
-  LongJmp(cur_thread(), env);
-  REAL(_longjmp)(env, val);
-}
-#endif
-
-#if !SANITIZER_MAC
-TSAN_INTERCEPTOR(void*, malloc, uptr size) {
-  if (in_symbolizer())
-    return InternalAlloc(size);
-  void *p = 0;
-  {
-    SCOPED_INTERCEPTOR_RAW(malloc, size);
-    p = user_alloc(thr, pc, size);
-  }
-  invoke_malloc_hook(p, size);
-  return p;
-}
-
-TSAN_INTERCEPTOR(void*, __libc_memalign, uptr align, uptr sz) {
-  SCOPED_TSAN_INTERCEPTOR(__libc_memalign, align, sz);
-  return user_memalign(thr, pc, align, sz);
-}
-
-TSAN_INTERCEPTOR(void*, calloc, uptr size, uptr n) {
-  if (in_symbolizer())
-    return InternalCalloc(size, n);
-  void *p = 0;
-  {
-    SCOPED_INTERCEPTOR_RAW(calloc, size, n);
-    p = user_calloc(thr, pc, size, n);
-  }
-  invoke_malloc_hook(p, n * size);
-  return p;
-}
-
-TSAN_INTERCEPTOR(void*, realloc, void *p, uptr size) {
-  if (in_symbolizer())
-    return InternalRealloc(p, size);
-  if (p)
-    invoke_free_hook(p);
-  {
-    SCOPED_INTERCEPTOR_RAW(realloc, p, size);
-    p = user_realloc(thr, pc, p, size);
-  }
-  invoke_malloc_hook(p, size);
-  return p;
-}
-
-TSAN_INTERCEPTOR(void*, reallocarray, void *p, uptr size, uptr n) {
-  if (in_symbolizer())
-    return InternalReallocArray(p, size, n);
-  if (p)
-    invoke_free_hook(p);
-  {
-    SCOPED_INTERCEPTOR_RAW(reallocarray, p, size, n);
-    p = user_reallocarray(thr, pc, p, size, n);
-  }
-  invoke_malloc_hook(p, size);
-  return p;
-}
-
-TSAN_INTERCEPTOR(void, free, void *p) {
-  if (p == 0)
-    return;
-  if (in_symbolizer())
-    return InternalFree(p);
-  invoke_free_hook(p);
-  SCOPED_INTERCEPTOR_RAW(free, p);
-  user_free(thr, pc, p);
-}
-
-TSAN_INTERCEPTOR(void, cfree, void *p) {
-  if (p == 0)
-    return;
-  if (in_symbolizer())
-    return InternalFree(p);
-  invoke_free_hook(p);
-  SCOPED_INTERCEPTOR_RAW(cfree, p);
-  user_free(thr, pc, p);
-}
-
-TSAN_INTERCEPTOR(uptr, malloc_usable_size, void *p) {
-  SCOPED_INTERCEPTOR_RAW(malloc_usable_size, p);
-  return user_alloc_usable_size(p);
-}
-#endif
-
-TSAN_INTERCEPTOR(char*, strcpy, char *dst, const char *src) {  // NOLINT
-  SCOPED_TSAN_INTERCEPTOR(strcpy, dst, src);  // NOLINT
-  uptr srclen = internal_strlen(src);
-  MemoryAccessRange(thr, pc, (uptr)dst, srclen + 1, true);
-  MemoryAccessRange(thr, pc, (uptr)src, srclen + 1, false);
-  return REAL(strcpy)(dst, src);  // NOLINT
-}
-
-TSAN_INTERCEPTOR(char*, strncpy, char *dst, char *src, uptr n) {
-  SCOPED_TSAN_INTERCEPTOR(strncpy, dst, src, n);
-  uptr srclen = internal_strnlen(src, n);
-  MemoryAccessRange(thr, pc, (uptr)dst, n, true);
-  MemoryAccessRange(thr, pc, (uptr)src, min(srclen + 1, n), false);
-  return REAL(strncpy)(dst, src, n);
-}
-
-TSAN_INTERCEPTOR(char*, strdup, const char *str) {
-  SCOPED_TSAN_INTERCEPTOR(strdup, str);
-  // strdup will call malloc, so no instrumentation is required here.
-  return REAL(strdup)(str);
-}
-
-static bool fix_mmap_addr(void **addr, long_t sz, int flags) {
-  if (*addr) {
-    if (!IsAppMem((uptr)*addr) || !IsAppMem((uptr)*addr + sz - 1)) {
-      if (flags & MAP_FIXED) {
-        errno = errno_EINVAL;
-        return false;
-      } else {
-        *addr = 0;
-      }
-    }
-  }
-  return true;
-}
-
-template <class Mmap>
-static void *mmap_interceptor(ThreadState *thr, uptr pc, Mmap real_mmap,
-                              void *addr, SIZE_T sz, int prot, int flags,
-                              int fd, OFF64_T off) {
-  if (!fix_mmap_addr(&addr, sz, flags)) return MAP_FAILED;
-  void *res = real_mmap(addr, sz, prot, flags, fd, off);
-  if (res != MAP_FAILED) {
-    if (fd > 0) FdAccess(thr, pc, fd);
-    if (thr->ignore_reads_and_writes == 0)
-      MemoryRangeImitateWrite(thr, pc, (uptr)res, sz);
-    else
-      MemoryResetRange(thr, pc, (uptr)res, sz);
-  }
-  return res;
-}
-
-TSAN_INTERCEPTOR(int, munmap, void *addr, long_t sz) {
-  SCOPED_TSAN_INTERCEPTOR(munmap, addr, sz);
-  if (sz != 0) {
-    // If sz == 0, munmap will return EINVAL and don't unmap any memory.
-    DontNeedShadowFor((uptr)addr, sz);
-    ScopedGlobalProcessor sgp;
-    ctx->metamap.ResetRange(thr->proc(), (uptr)addr, (uptr)sz);
-  }
-  int res = REAL(munmap)(addr, sz);
-  return res;
-}
-
-#if SANITIZER_LINUX
-TSAN_INTERCEPTOR(void*, memalign, uptr align, uptr sz) {
-  SCOPED_INTERCEPTOR_RAW(memalign, align, sz);
-  return user_memalign(thr, pc, align, sz);
-}
-#define TSAN_MAYBE_INTERCEPT_MEMALIGN TSAN_INTERCEPT(memalign)
-#else
-#define TSAN_MAYBE_INTERCEPT_MEMALIGN
-#endif
-
-#if !SANITIZER_MAC
-TSAN_INTERCEPTOR(void*, aligned_alloc, uptr align, uptr sz) {
-  if (in_symbolizer())
-    return InternalAlloc(sz, nullptr, align);
-  SCOPED_INTERCEPTOR_RAW(aligned_alloc, align, sz);
-  return user_aligned_alloc(thr, pc, align, sz);
-}
-
-TSAN_INTERCEPTOR(void*, valloc, uptr sz) {
-  if (in_symbolizer())
-    return InternalAlloc(sz, nullptr, GetPageSizeCached());
-  SCOPED_INTERCEPTOR_RAW(valloc, sz);
-  return user_valloc(thr, pc, sz);
-}
-#endif
-
-#if SANITIZER_LINUX
-TSAN_INTERCEPTOR(void*, pvalloc, uptr sz) {
-  if (in_symbolizer()) {
-    uptr PageSize = GetPageSizeCached();
-    sz = sz ? RoundUpTo(sz, PageSize) : PageSize;
-    return InternalAlloc(sz, nullptr, PageSize);
-  }
-  SCOPED_INTERCEPTOR_RAW(pvalloc, sz);
-  return user_pvalloc(thr, pc, sz);
-}
-#define TSAN_MAYBE_INTERCEPT_PVALLOC TSAN_INTERCEPT(pvalloc)
-#else
-#define TSAN_MAYBE_INTERCEPT_PVALLOC
-#endif
-
-#if !SANITIZER_MAC
-TSAN_INTERCEPTOR(int, posix_memalign, void **memptr, uptr align, uptr sz) {
-  if (in_symbolizer()) {
-    void *p = InternalAlloc(sz, nullptr, align);
-    if (!p)
-      return errno_ENOMEM;
-    *memptr = p;
-    return 0;
-  }
-  SCOPED_INTERCEPTOR_RAW(posix_memalign, memptr, align, sz);
-  return user_posix_memalign(thr, pc, memptr, align, sz);
-}
-#endif
-
-// __cxa_guard_acquire and friends need to be intercepted in a special way -
-// regular interceptors will break statically-linked libstdc++. Linux
-// interceptors are especially defined as weak functions (so that they don't
-// cause link errors when user defines them as well). So they silently
-// auto-disable themselves when such symbol is already present in the binary. If
-// we link libstdc++ statically, it will bring own __cxa_guard_acquire which
-// will silently replace our interceptor.  That's why on Linux we simply export
-// these interceptors with INTERFACE_ATTRIBUTE.
-// On OS X, we don't support statically linking, so we just use a regular
-// interceptor.
-#if SANITIZER_MAC
-#define STDCXX_INTERCEPTOR TSAN_INTERCEPTOR
-#else
-#define STDCXX_INTERCEPTOR(rettype, name, ...) \
-  extern "C" rettype INTERFACE_ATTRIBUTE name(__VA_ARGS__)
-#endif
-
-// Used in thread-safe function static initialization.
-STDCXX_INTERCEPTOR(int, __cxa_guard_acquire, atomic_uint32_t *g) {
-  SCOPED_INTERCEPTOR_RAW(__cxa_guard_acquire, g);
-  OnPotentiallyBlockingRegionBegin();
-  auto on_exit = at_scope_exit(&OnPotentiallyBlockingRegionEnd);
-  for (;;) {
-    u32 cmp = atomic_load(g, memory_order_acquire);
-    if (cmp == 0) {
-      if (atomic_compare_exchange_strong(g, &cmp, 1<<16, memory_order_relaxed))
-        return 1;
-    } else if (cmp == 1) {
-      Acquire(thr, pc, (uptr)g);
-      return 0;
-    } else {
-      internal_sched_yield();
-    }
-  }
-}
-
-STDCXX_INTERCEPTOR(void, __cxa_guard_release, atomic_uint32_t *g) {
-  SCOPED_INTERCEPTOR_RAW(__cxa_guard_release, g);
-  Release(thr, pc, (uptr)g);
-  atomic_store(g, 1, memory_order_release);
-}
-
-STDCXX_INTERCEPTOR(void, __cxa_guard_abort, atomic_uint32_t *g) {
-  SCOPED_INTERCEPTOR_RAW(__cxa_guard_abort, g);
-  atomic_store(g, 0, memory_order_relaxed);
-}
-
-namespace __tsan {
-void DestroyThreadState() {
-  ThreadState *thr = cur_thread();
-  Processor *proc = thr->proc();
-  ThreadFinish(thr);
-  ProcUnwire(proc, thr);
-  ProcDestroy(proc);
-  ThreadSignalContext *sctx = thr->signal_ctx;
-  if (sctx) {
-    thr->signal_ctx = 0;
-    UnmapOrDie(sctx, sizeof(*sctx));
-  }
-  DTLS_Destroy();
-  cur_thread_finalize();
-}
-}  // namespace __tsan
-
-#if !SANITIZER_MAC && !SANITIZER_NETBSD && !SANITIZER_FREEBSD
-static void thread_finalize(void *v) {
-  uptr iter = (uptr)v;
-  if (iter > 1) {
-    if (pthread_setspecific(interceptor_ctx()->finalize_key,
-        (void*)(iter - 1))) {
-      Printf("ThreadSanitizer: failed to set thread key\n");
-      Die();
-    }
-    return;
-  }
-  DestroyThreadState();
-}
-#endif
-
-
-struct ThreadParam {
-  void* (*callback)(void *arg);
-  void *param;
-  atomic_uintptr_t tid;
-};
-
-extern "C" void *__tsan_thread_start_func(void *arg) {
-  ThreadParam *p = (ThreadParam*)arg;
-  void* (*callback)(void *arg) = p->callback;
-  void *param = p->param;
-  int tid = 0;
-  {
-    cur_thread_init();
-    ThreadState *thr = cur_thread();
-    // Thread-local state is not initialized yet.
-    ScopedIgnoreInterceptors ignore;
-#if !SANITIZER_MAC && !SANITIZER_NETBSD && !SANITIZER_FREEBSD
-    ThreadIgnoreBegin(thr, 0);
-    if (pthread_setspecific(interceptor_ctx()->finalize_key,
-                            (void *)GetPthreadDestructorIterations())) {
-      Printf("ThreadSanitizer: failed to set thread key\n");
-      Die();
-    }
-    ThreadIgnoreEnd(thr, 0);
-#endif
-    while ((tid = atomic_load(&p->tid, memory_order_acquire)) == 0)
-      internal_sched_yield();
-    Processor *proc = ProcCreate();
-    ProcWire(proc, thr);
-    ThreadStart(thr, tid, GetTid(), ThreadType::Regular);
-    atomic_store(&p->tid, 0, memory_order_release);
-  }
-  void *res = callback(param);
-  // Prevent the callback from being tail called,
-  // it mixes up stack traces.
-  volatile int foo = 42;
-  foo++;
-  return res;
-}
-
-TSAN_INTERCEPTOR(int, pthread_create,
-    void *th, void *attr, void *(*callback)(void*), void * param) {
-  SCOPED_INTERCEPTOR_RAW(pthread_create, th, attr, callback, param);
-
-  MaybeSpawnBackgroundThread();
-
-  if (ctx->after_multithreaded_fork) {
-    if (flags()->die_after_fork) {
-      Report("ThreadSanitizer: starting new threads after multi-threaded "
-          "fork is not supported. Dying (set die_after_fork=0 to override)\n");
-      Die();
-    } else {
-      VPrintf(1, "ThreadSanitizer: starting new threads after multi-threaded "
-          "fork is not supported (pid %d). Continuing because of "
-          "die_after_fork=0, but you are on your own\n", internal_getpid());
-    }
-  }
-  __sanitizer_pthread_attr_t myattr;
-  if (attr == 0) {
-    pthread_attr_init(&myattr);
-    attr = &myattr;
-  }
-  int detached = 0;
-  REAL(pthread_attr_getdetachstate)(attr, &detached);
-  AdjustStackSize(attr);
-
-  ThreadParam p;
-  p.callback = callback;
-  p.param = param;
-  atomic_store(&p.tid, 0, memory_order_relaxed);
-  int res = -1;
-  {
-    // Otherwise we see false positives in pthread stack manipulation.
-    ScopedIgnoreInterceptors ignore;
-    ThreadIgnoreBegin(thr, pc);
-    res = REAL(pthread_create)(th, attr, __tsan_thread_start_func, &p);
-    ThreadIgnoreEnd(thr, pc);
-  }
-  if (res == 0) {
-    int tid = ThreadCreate(thr, pc, *(uptr*)th, IsStateDetached(detached));
-    CHECK_NE(tid, 0);
-    // Synchronization on p.tid serves two purposes:
-    // 1. ThreadCreate must finish before the new thread starts.
-    //    Otherwise the new thread can call pthread_detach, but the pthread_t
-    //    identifier is not yet registered in ThreadRegistry by ThreadCreate.
-    // 2. ThreadStart must finish before this thread continues.
-    //    Otherwise, this thread can call pthread_detach and reset thr->sync
-    //    before the new thread got a chance to acquire from it in ThreadStart.
-    atomic_store(&p.tid, tid, memory_order_release);
-    while (atomic_load(&p.tid, memory_order_acquire) != 0)
-      internal_sched_yield();
-  }
-  if (attr == &myattr)
-    pthread_attr_destroy(&myattr);
-  return res;
-}
-
-TSAN_INTERCEPTOR(int, pthread_join, void *th, void **ret) {
-  SCOPED_INTERCEPTOR_RAW(pthread_join, th, ret);
-  int tid = ThreadTid(thr, pc, (uptr)th);
-  ThreadIgnoreBegin(thr, pc);
-  int res = BLOCK_REAL(pthread_join)(th, ret);
-  ThreadIgnoreEnd(thr, pc);
-  if (res == 0) {
-    ThreadJoin(thr, pc, tid);
-  }
-  return res;
-}
-
-DEFINE_REAL_PTHREAD_FUNCTIONS
-
-TSAN_INTERCEPTOR(int, pthread_detach, void *th) {
-  SCOPED_TSAN_INTERCEPTOR(pthread_detach, th);
-  int tid = ThreadTid(thr, pc, (uptr)th);
-  int res = REAL(pthread_detach)(th);
-  if (res == 0) {
-    ThreadDetach(thr, pc, tid);
-  }
-  return res;
-}
-
-TSAN_INTERCEPTOR(void, pthread_exit, void *retval) {
-  {
-    SCOPED_INTERCEPTOR_RAW(pthread_exit, retval);
-#if !SANITIZER_MAC && !SANITIZER_ANDROID
-    CHECK_EQ(thr, &cur_thread_placeholder);
-#endif
-  }
-  REAL(pthread_exit)(retval);
-}
-
-#if SANITIZER_LINUX
-TSAN_INTERCEPTOR(int, pthread_tryjoin_np, void *th, void **ret) {
-  SCOPED_TSAN_INTERCEPTOR(pthread_tryjoin_np, th, ret);
-  int tid = ThreadTid(thr, pc, (uptr)th);
-  ThreadIgnoreBegin(thr, pc);
-  int res = REAL(pthread_tryjoin_np)(th, ret);
-  ThreadIgnoreEnd(thr, pc);
-  if (res == 0)
-    ThreadJoin(thr, pc, tid);
-  else
-    ThreadNotJoined(thr, pc, tid, (uptr)th);
-  return res;
-}
-
-TSAN_INTERCEPTOR(int, pthread_timedjoin_np, void *th, void **ret,
-                 const struct timespec *abstime) {
-  SCOPED_TSAN_INTERCEPTOR(pthread_timedjoin_np, th, ret, abstime);
-  int tid = ThreadTid(thr, pc, (uptr)th);
-  ThreadIgnoreBegin(thr, pc);
-  int res = BLOCK_REAL(pthread_timedjoin_np)(th, ret, abstime);
-  ThreadIgnoreEnd(thr, pc);
-  if (res == 0)
-    ThreadJoin(thr, pc, tid);
-  else
-    ThreadNotJoined(thr, pc, tid, (uptr)th);
-  return res;
-}
-#endif
-
-// Problem:
-// NPTL implementation of pthread_cond has 2 versions (2.2.5 and 2.3.2).
-// pthread_cond_t has different size in the different versions.
-// If call new REAL functions for old pthread_cond_t, they will corrupt memory
-// after pthread_cond_t (old cond is smaller).
-// If we call old REAL functions for new pthread_cond_t, we will lose  some
-// functionality (e.g. old functions do not support waiting against
-// CLOCK_REALTIME).
-// Proper handling would require to have 2 versions of interceptors as well.
-// But this is messy, in particular requires linker scripts when sanitizer
-// runtime is linked into a shared library.
-// Instead we assume we don't have dynamic libraries built against old
-// pthread (2.2.5 is dated by 2002). And provide legacy_pthread_cond flag
-// that allows to work with old libraries (but this mode does not support
-// some features, e.g. pthread_condattr_getpshared).
-static void *init_cond(void *c, bool force = false) {
-  // sizeof(pthread_cond_t) >= sizeof(uptr) in both versions.
-  // So we allocate additional memory on the side large enough to hold
-  // any pthread_cond_t object. Always call new REAL functions, but pass
-  // the aux object to them.
-  // Note: the code assumes that PTHREAD_COND_INITIALIZER initializes
-  // first word of pthread_cond_t to zero.
-  // It's all relevant only for linux.
-  if (!common_flags()->legacy_pthread_cond)
-    return c;
-  atomic_uintptr_t *p = (atomic_uintptr_t*)c;
-  uptr cond = atomic_load(p, memory_order_acquire);
-  if (!force && cond != 0)
-    return (void*)cond;
-  void *newcond = WRAP(malloc)(pthread_cond_t_sz);
-  internal_memset(newcond, 0, pthread_cond_t_sz);
-  if (atomic_compare_exchange_strong(p, &cond, (uptr)newcond,
-      memory_order_acq_rel))
-    return newcond;
-  WRAP(free)(newcond);
-  return (void*)cond;
-}
-
-struct CondMutexUnlockCtx {
-  ScopedInterceptor *si;
-  ThreadState *thr;
-  uptr pc;
-  void *m;
-};
-
-static void cond_mutex_unlock(CondMutexUnlockCtx *arg) {
-  // pthread_cond_wait interceptor has enabled async signal delivery
-  // (see BlockingCall below). Disable async signals since we are running
-  // tsan code. Also ScopedInterceptor and BlockingCall destructors won't run
-  // since the thread is cancelled, so we have to manually execute them
-  // (the thread still can run some user code due to pthread_cleanup_push).
-  ThreadSignalContext *ctx = SigCtx(arg->thr);
-  CHECK_EQ(atomic_load(&ctx->in_blocking_func, memory_order_relaxed), 1);
-  atomic_store(&ctx->in_blocking_func, 0, memory_order_relaxed);
-  MutexPostLock(arg->thr, arg->pc, (uptr)arg->m, MutexFlagDoPreLockOnPostLock);
-  // Undo BlockingCall ctor effects.
-  arg->thr->ignore_interceptors--;
-  arg->si->~ScopedInterceptor();
-}
-
-INTERCEPTOR(int, pthread_cond_init, void *c, void *a) {
-  void *cond = init_cond(c, true);
-  SCOPED_TSAN_INTERCEPTOR(pthread_cond_init, cond, a);
-  MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), true);
-  return REAL(pthread_cond_init)(cond, a);
-}
-
-static int cond_wait(ThreadState *thr, uptr pc, ScopedInterceptor *si,
-                     int (*fn)(void *c, void *m, void *abstime), void *c,
-                     void *m, void *t) {
-  MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), false);
-  MutexUnlock(thr, pc, (uptr)m);
-  CondMutexUnlockCtx arg = {si, thr, pc, m};
-  int res = 0;
-  // This ensures that we handle mutex lock even in case of pthread_cancel.
-  // See test/tsan/cond_cancel.cpp.
-  {
-    // Enable signal delivery while the thread is blocked.
-    BlockingCall bc(thr);
-    res = call_pthread_cancel_with_cleanup(
-        fn, c, m, t, (void (*)(void *arg))cond_mutex_unlock, &arg);
-  }
-  if (res == errno_EOWNERDEAD) MutexRepair(thr, pc, (uptr)m);
-  MutexPostLock(thr, pc, (uptr)m, MutexFlagDoPreLockOnPostLock);
-  return res;
-}
-
-INTERCEPTOR(int, pthread_cond_wait, void *c, void *m) {
-  void *cond = init_cond(c);
-  SCOPED_TSAN_INTERCEPTOR(pthread_cond_wait, cond, m);
-  return cond_wait(thr, pc, &si, (int (*)(void *c, void *m, void *abstime))REAL(
-                                     pthread_cond_wait),
-                   cond, m, 0);
-}
-
-INTERCEPTOR(int, pthread_cond_timedwait, void *c, void *m, void *abstime) {
-  void *cond = init_cond(c);
-  SCOPED_TSAN_INTERCEPTOR(pthread_cond_timedwait, cond, m, abstime);
-  return cond_wait(thr, pc, &si, REAL(pthread_cond_timedwait), cond, m,
-                   abstime);
-}
-
-#if SANITIZER_MAC
-INTERCEPTOR(int, pthread_cond_timedwait_relative_np, void *c, void *m,
-            void *reltime) {
-  void *cond = init_cond(c);
-  SCOPED_TSAN_INTERCEPTOR(pthread_cond_timedwait_relative_np, cond, m, reltime);
-  return cond_wait(thr, pc, &si, REAL(pthread_cond_timedwait_relative_np), cond,
-                   m, reltime);
-}
-#endif
-
-INTERCEPTOR(int, pthread_cond_signal, void *c) {
-  void *cond = init_cond(c);
-  SCOPED_TSAN_INTERCEPTOR(pthread_cond_signal, cond);
-  MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), false);
-  return REAL(pthread_cond_signal)(cond);
-}
-
-INTERCEPTOR(int, pthread_cond_broadcast, void *c) {
-  void *cond = init_cond(c);
-  SCOPED_TSAN_INTERCEPTOR(pthread_cond_broadcast, cond);
-  MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), false);
-  return REAL(pthread_cond_broadcast)(cond);
-}
-
-INTERCEPTOR(int, pthread_cond_destroy, void *c) {
-  void *cond = init_cond(c);
-  SCOPED_TSAN_INTERCEPTOR(pthread_cond_destroy, cond);
-  MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), true);
-  int res = REAL(pthread_cond_destroy)(cond);
-  if (common_flags()->legacy_pthread_cond) {
-    // Free our aux cond and zero the pointer to not leave dangling pointers.
-    WRAP(free)(cond);
-    atomic_store((atomic_uintptr_t*)c, 0, memory_order_relaxed);
-  }
-  return res;
-}
-
-TSAN_INTERCEPTOR(int, pthread_mutex_init, void *m, void *a) {
-  SCOPED_TSAN_INTERCEPTOR(pthread_mutex_init, m, a);
-  int res = REAL(pthread_mutex_init)(m, a);
-  if (res == 0) {
-    u32 flagz = 0;
-    if (a) {
-      int type = 0;
-      if (REAL(pthread_mutexattr_gettype)(a, &type) == 0)
-        if (type == PTHREAD_MUTEX_RECURSIVE ||
-            type == PTHREAD_MUTEX_RECURSIVE_NP)
-          flagz |= MutexFlagWriteReentrant;
-    }
-    MutexCreate(thr, pc, (uptr)m, flagz);
-  }
-  return res;
-}
-
-TSAN_INTERCEPTOR(int, pthread_mutex_destroy, void *m) {
-  SCOPED_TSAN_INTERCEPTOR(pthread_mutex_destroy, m);
-  int res = REAL(pthread_mutex_destroy)(m);
-  if (res == 0 || res == errno_EBUSY) {
-    MutexDestroy(thr, pc, (uptr)m);
-  }
-  return res;
-}
-
-TSAN_INTERCEPTOR(int, pthread_mutex_trylock, void *m) {
-  SCOPED_TSAN_INTERCEPTOR(pthread_mutex_trylock, m);
-  int res = REAL(pthread_mutex_trylock)(m);
-  if (res == errno_EOWNERDEAD)
-    MutexRepair(thr, pc, (uptr)m);
-  if (res == 0 || res == errno_EOWNERDEAD)
-    MutexPostLock(thr, pc, (uptr)m, MutexFlagTryLock);
-  return res;
-}
-
-#if !SANITIZER_MAC
-TSAN_INTERCEPTOR(int, pthread_mutex_timedlock, void *m, void *abstime) {
-  SCOPED_TSAN_INTERCEPTOR(pthread_mutex_timedlock, m, abstime);
-  int res = REAL(pthread_mutex_timedlock)(m, abstime);
-  if (res == 0) {
-    MutexPostLock(thr, pc, (uptr)m, MutexFlagTryLock);
-  }
-  return res;
-}
-#endif
-
-#if !SANITIZER_MAC
-TSAN_INTERCEPTOR(int, pthread_spin_init, void *m, int pshared) {
-  SCOPED_TSAN_INTERCEPTOR(pthread_spin_init, m, pshared);
-  int res = REAL(pthread_spin_init)(m, pshared);
-  if (res == 0) {
-    MutexCreate(thr, pc, (uptr)m);
-  }
-  return res;
-}
-
-TSAN_INTERCEPTOR(int, pthread_spin_destroy, void *m) {
-  SCOPED_TSAN_INTERCEPTOR(pthread_spin_destroy, m);
-  int res = REAL(pthread_spin_destroy)(m);
-  if (res == 0) {
-    MutexDestroy(thr, pc, (uptr)m);
-  }
-  return res;
-}
-
-TSAN_INTERCEPTOR(int, pthread_spin_lock, void *m) {
-  SCOPED_TSAN_INTERCEPTOR(pthread_spin_lock, m);
-  MutexPreLock(thr, pc, (uptr)m);
-  int res = REAL(pthread_spin_lock)(m);
-  if (res == 0) {
-    MutexPostLock(thr, pc, (uptr)m);
-  }
-  return res;
-}
-
-TSAN_INTERCEPTOR(int, pthread_spin_trylock, void *m) {
-  SCOPED_TSAN_INTERCEPTOR(pthread_spin_trylock, m);
-  int res = REAL(pthread_spin_trylock)(m);
-  if (res == 0) {
-    MutexPostLock(thr, pc, (uptr)m, MutexFlagTryLock);
-  }
-  return res;
-}
-
-TSAN_INTERCEPTOR(int, pthread_spin_unlock, void *m) {
-  SCOPED_TSAN_INTERCEPTOR(pthread_spin_unlock, m);
-  MutexUnlock(thr, pc, (uptr)m);
-  int res = REAL(pthread_spin_unlock)(m);
-  return res;
-}
-#endif
-
-TSAN_INTERCEPTOR(int, pthread_rwlock_init, void *m, void *a) {
-  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_init, m, a);
-  int res = REAL(pthread_rwlock_init)(m, a);
-  if (res == 0) {
-    MutexCreate(thr, pc, (uptr)m);
-  }
-  return res;
-}
-
-TSAN_INTERCEPTOR(int, pthread_rwlock_destroy, void *m) {
-  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_destroy, m);
-  int res = REAL(pthread_rwlock_destroy)(m);
-  if (res == 0) {
-    MutexDestroy(thr, pc, (uptr)m);
-  }
-  return res;
-}
-
-TSAN_INTERCEPTOR(int, pthread_rwlock_rdlock, void *m) {
-  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_rdlock, m);
-  MutexPreReadLock(thr, pc, (uptr)m);
-  int res = REAL(pthread_rwlock_rdlock)(m);
-  if (res == 0) {
-    MutexPostReadLock(thr, pc, (uptr)m);
-  }
-  return res;
-}
-
-TSAN_INTERCEPTOR(int, pthread_rwlock_tryrdlock, void *m) {
-  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_tryrdlock, m);
-  int res = REAL(pthread_rwlock_tryrdlock)(m);
-  if (res == 0) {
-    MutexPostReadLock(thr, pc, (uptr)m, MutexFlagTryLock);
-  }
-  return res;
-}
-
-#if !SANITIZER_MAC
-TSAN_INTERCEPTOR(int, pthread_rwlock_timedrdlock, void *m, void *abstime) {
-  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_timedrdlock, m, abstime);
-  int res = REAL(pthread_rwlock_timedrdlock)(m, abstime);
-  if (res == 0) {
-    MutexPostReadLock(thr, pc, (uptr)m);
-  }
-  return res;
-}
-#endif
-
-TSAN_INTERCEPTOR(int, pthread_rwlock_wrlock, void *m) {
-  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_wrlock, m);
-  MutexPreLock(thr, pc, (uptr)m);
-  int res = REAL(pthread_rwlock_wrlock)(m);
-  if (res == 0) {
-    MutexPostLock(thr, pc, (uptr)m);
-  }
-  return res;
-}
-
-TSAN_INTERCEPTOR(int, pthread_rwlock_trywrlock, void *m) {
-  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_trywrlock, m);
-  int res = REAL(pthread_rwlock_trywrlock)(m);
-  if (res == 0) {
-    MutexPostLock(thr, pc, (uptr)m, MutexFlagTryLock);
-  }
-  return res;
-}
-
-#if !SANITIZER_MAC
-TSAN_INTERCEPTOR(int, pthread_rwlock_timedwrlock, void *m, void *abstime) {
-  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_timedwrlock, m, abstime);
-  int res = REAL(pthread_rwlock_timedwrlock)(m, abstime);
-  if (res == 0) {
-    MutexPostLock(thr, pc, (uptr)m, MutexFlagTryLock);
-  }
-  return res;
-}
-#endif
-
-TSAN_INTERCEPTOR(int, pthread_rwlock_unlock, void *m) {
-  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_unlock, m);
-  MutexReadOrWriteUnlock(thr, pc, (uptr)m);
-  int res = REAL(pthread_rwlock_unlock)(m);
-  return res;
-}
-
-#if !SANITIZER_MAC
-TSAN_INTERCEPTOR(int, pthread_barrier_init, void *b, void *a, unsigned count) {
-  SCOPED_TSAN_INTERCEPTOR(pthread_barrier_init, b, a, count);
-  MemoryWrite(thr, pc, (uptr)b, kSizeLog1);
-  int res = REAL(pthread_barrier_init)(b, a, count);
-  return res;
-}
-
-TSAN_INTERCEPTOR(int, pthread_barrier_destroy, void *b) {
-  SCOPED_TSAN_INTERCEPTOR(pthread_barrier_destroy, b);
-  MemoryWrite(thr, pc, (uptr)b, kSizeLog1);
-  int res = REAL(pthread_barrier_destroy)(b);
-  return res;
-}
-
-TSAN_INTERCEPTOR(int, pthread_barrier_wait, void *b) {
-  SCOPED_TSAN_INTERCEPTOR(pthread_barrier_wait, b);
-  Release(thr, pc, (uptr)b);
-  MemoryRead(thr, pc, (uptr)b, kSizeLog1);
-  int res = REAL(pthread_barrier_wait)(b);
-  MemoryRead(thr, pc, (uptr)b, kSizeLog1);
-  if (res == 0 || res == PTHREAD_BARRIER_SERIAL_THREAD) {
-    Acquire(thr, pc, (uptr)b);
-  }
-  return res;
-}
-#endif
-
-TSAN_INTERCEPTOR(int, pthread_once, void *o, void (*f)()) {
-  SCOPED_INTERCEPTOR_RAW(pthread_once, o, f);
-  if (o == 0 || f == 0)
-    return errno_EINVAL;
-  atomic_uint32_t *a;
-
-  if (SANITIZER_MAC)
-    a = static_cast<atomic_uint32_t*>((void *)((char *)o + sizeof(long_t)));
-  else if (SANITIZER_NETBSD)
-    a = static_cast<atomic_uint32_t*>
-          ((void *)((char *)o + __sanitizer::pthread_mutex_t_sz));
-  else
-    a = static_cast<atomic_uint32_t*>(o);
-
-  u32 v = atomic_load(a, memory_order_acquire);
-  if (v == 0 && atomic_compare_exchange_strong(a, &v, 1,
-                                               memory_order_relaxed)) {
-    (*f)();
-    if (!thr->in_ignored_lib)
-      Release(thr, pc, (uptr)o);
-    atomic_store(a, 2, memory_order_release);
-  } else {
-    while (v != 2) {
-      internal_sched_yield();
-      v = atomic_load(a, memory_order_acquire);
-    }
-    if (!thr->in_ignored_lib)
-      Acquire(thr, pc, (uptr)o);
-  }
-  return 0;
-}
-
-#if SANITIZER_LINUX && !SANITIZER_ANDROID
-TSAN_INTERCEPTOR(int, __fxstat, int version, int fd, void *buf) {
-  SCOPED_TSAN_INTERCEPTOR(__fxstat, version, fd, buf);
-  if (fd > 0)
-    FdAccess(thr, pc, fd);
-  return REAL(__fxstat)(version, fd, buf);
-}
-#define TSAN_MAYBE_INTERCEPT___FXSTAT TSAN_INTERCEPT(__fxstat)
-#else
-#define TSAN_MAYBE_INTERCEPT___FXSTAT
-#endif
-
-TSAN_INTERCEPTOR(int, fstat, int fd, void *buf) {
-#if SANITIZER_FREEBSD || SANITIZER_MAC || SANITIZER_ANDROID || SANITIZER_NETBSD
-  SCOPED_TSAN_INTERCEPTOR(fstat, fd, buf);
-  if (fd > 0)
-    FdAccess(thr, pc, fd);
-  return REAL(fstat)(fd, buf);
-#else
-  SCOPED_TSAN_INTERCEPTOR(__fxstat, 0, fd, buf);
-  if (fd > 0)
-    FdAccess(thr, pc, fd);
-  return REAL(__fxstat)(0, fd, buf);
-#endif
-}
-
-#if SANITIZER_LINUX && !SANITIZER_ANDROID
-TSAN_INTERCEPTOR(int, __fxstat64, int version, int fd, void *buf) {
-  SCOPED_TSAN_INTERCEPTOR(__fxstat64, version, fd, buf);
-  if (fd > 0)
-    FdAccess(thr, pc, fd);
-  return REAL(__fxstat64)(version, fd, buf);
-}
-#define TSAN_MAYBE_INTERCEPT___FXSTAT64 TSAN_INTERCEPT(__fxstat64)
-#else
-#define TSAN_MAYBE_INTERCEPT___FXSTAT64
-#endif
-
-#if SANITIZER_LINUX && !SANITIZER_ANDROID
-TSAN_INTERCEPTOR(int, fstat64, int fd, void *buf) {
-  SCOPED_TSAN_INTERCEPTOR(__fxstat64, 0, fd, buf);
-  if (fd > 0)
-    FdAccess(thr, pc, fd);
-  return REAL(__fxstat64)(0, fd, buf);
-}
-#define TSAN_MAYBE_INTERCEPT_FSTAT64 TSAN_INTERCEPT(fstat64)
-#else
-#define TSAN_MAYBE_INTERCEPT_FSTAT64
-#endif
-
-TSAN_INTERCEPTOR(int, open, const char *name, int flags, int mode) {
-  SCOPED_TSAN_INTERCEPTOR(open, name, flags, mode);
-  READ_STRING(thr, pc, name, 0);
-  int fd = REAL(open)(name, flags, mode);
-  if (fd >= 0)
-    FdFileCreate(thr, pc, fd);
-  return fd;
-}
-
-#if SANITIZER_LINUX
-TSAN_INTERCEPTOR(int, open64, const char *name, int flags, int mode) {
-  SCOPED_TSAN_INTERCEPTOR(open64, name, flags, mode);
-  READ_STRING(thr, pc, name, 0);
-  int fd = REAL(open64)(name, flags, mode);
-  if (fd >= 0)
-    FdFileCreate(thr, pc, fd);
-  return fd;
-}
-#define TSAN_MAYBE_INTERCEPT_OPEN64 TSAN_INTERCEPT(open64)
-#else
-#define TSAN_MAYBE_INTERCEPT_OPEN64
-#endif
-
-TSAN_INTERCEPTOR(int, creat, const char *name, int mode) {
-  SCOPED_TSAN_INTERCEPTOR(creat, name, mode);
-  READ_STRING(thr, pc, name, 0);
-  int fd = REAL(creat)(name, mode);
-  if (fd >= 0)
-    FdFileCreate(thr, pc, fd);
-  return fd;
-}
-
-#if SANITIZER_LINUX
-TSAN_INTERCEPTOR(int, creat64, const char *name, int mode) {
-  SCOPED_TSAN_INTERCEPTOR(creat64, name, mode);
-  READ_STRING(thr, pc, name, 0);
-  int fd = REAL(creat64)(name, mode);
-  if (fd >= 0)
-    FdFileCreate(thr, pc, fd);
-  return fd;
-}
-#define TSAN_MAYBE_INTERCEPT_CREAT64 TSAN_INTERCEPT(creat64)
-#else
-#define TSAN_MAYBE_INTERCEPT_CREAT64
-#endif
-
-TSAN_INTERCEPTOR(int, dup, int oldfd) {
-  SCOPED_TSAN_INTERCEPTOR(dup, oldfd);
-  int newfd = REAL(dup)(oldfd);
-  if (oldfd >= 0 && newfd >= 0 && newfd != oldfd)
-    FdDup(thr, pc, oldfd, newfd, true);
-  return newfd;
-}
-
-TSAN_INTERCEPTOR(int, dup2, int oldfd, int newfd) {
-  SCOPED_TSAN_INTERCEPTOR(dup2, oldfd, newfd);
-  int newfd2 = REAL(dup2)(oldfd, newfd);
-  if (oldfd >= 0 && newfd2 >= 0 && newfd2 != oldfd)
-    FdDup(thr, pc, oldfd, newfd2, false);
-  return newfd2;
-}
-
-#if !SANITIZER_MAC
-TSAN_INTERCEPTOR(int, dup3, int oldfd, int newfd, int flags) {
-  SCOPED_TSAN_INTERCEPTOR(dup3, oldfd, newfd, flags);
-  int newfd2 = REAL(dup3)(oldfd, newfd, flags);
-  if (oldfd >= 0 && newfd2 >= 0 && newfd2 != oldfd)
-    FdDup(thr, pc, oldfd, newfd2, false);
-  return newfd2;
-}
-#endif
-
-#if SANITIZER_LINUX
-TSAN_INTERCEPTOR(int, eventfd, unsigned initval, int flags) {
-  SCOPED_TSAN_INTERCEPTOR(eventfd, initval, flags);
-  int fd = REAL(eventfd)(initval, flags);
-  if (fd >= 0)
-    FdEventCreate(thr, pc, fd);
-  return fd;
-}
-#define TSAN_MAYBE_INTERCEPT_EVENTFD TSAN_INTERCEPT(eventfd)
-#else
-#define TSAN_MAYBE_INTERCEPT_EVENTFD
-#endif
-
-#if SANITIZER_LINUX
-TSAN_INTERCEPTOR(int, signalfd, int fd, void *mask, int flags) {
-  SCOPED_TSAN_INTERCEPTOR(signalfd, fd, mask, flags);
-  if (fd >= 0)
-    FdClose(thr, pc, fd);
-  fd = REAL(signalfd)(fd, mask, flags);
-  if (fd >= 0)
-    FdSignalCreate(thr, pc, fd);
-  return fd;
-}
-#define TSAN_MAYBE_INTERCEPT_SIGNALFD TSAN_INTERCEPT(signalfd)
-#else
-#define TSAN_MAYBE_INTERCEPT_SIGNALFD
-#endif
-
-#if SANITIZER_LINUX
-TSAN_INTERCEPTOR(int, inotify_init, int fake) {
-  SCOPED_TSAN_INTERCEPTOR(inotify_init, fake);
-  int fd = REAL(inotify_init)(fake);
-  if (fd >= 0)
-    FdInotifyCreate(thr, pc, fd);
-  return fd;
-}
-#define TSAN_MAYBE_INTERCEPT_INOTIFY_INIT TSAN_INTERCEPT(inotify_init)
-#else
-#define TSAN_MAYBE_INTERCEPT_INOTIFY_INIT
-#endif
-
-#if SANITIZER_LINUX
-TSAN_INTERCEPTOR(int, inotify_init1, int flags) {
-  SCOPED_TSAN_INTERCEPTOR(inotify_init1, flags);
-  int fd = REAL(inotify_init1)(flags);
-  if (fd >= 0)
-    FdInotifyCreate(thr, pc, fd);
-  return fd;
-}
-#define TSAN_MAYBE_INTERCEPT_INOTIFY_INIT1 TSAN_INTERCEPT(inotify_init1)
-#else
-#define TSAN_MAYBE_INTERCEPT_INOTIFY_INIT1
-#endif
-
-TSAN_INTERCEPTOR(int, socket, int domain, int type, int protocol) {
-  SCOPED_TSAN_INTERCEPTOR(socket, domain, type, protocol);
-  int fd = REAL(socket)(domain, type, protocol);
-  if (fd >= 0)
-    FdSocketCreate(thr, pc, fd);
-  return fd;
-}
-
-TSAN_INTERCEPTOR(int, socketpair, int domain, int type, int protocol, int *fd) {
-  SCOPED_TSAN_INTERCEPTOR(socketpair, domain, type, protocol, fd);
-  int res = REAL(socketpair)(domain, type, protocol, fd);
-  if (res == 0 && fd[0] >= 0 && fd[1] >= 0)
-    FdPipeCreate(thr, pc, fd[0], fd[1]);
-  return res;
-}
-
-TSAN_INTERCEPTOR(int, connect, int fd, void *addr, unsigned addrlen) {
-  SCOPED_TSAN_INTERCEPTOR(connect, fd, addr, addrlen);
-  FdSocketConnecting(thr, pc, fd);
-  int res = REAL(connect)(fd, addr, addrlen);
-  if (res == 0 && fd >= 0)
-    FdSocketConnect(thr, pc, fd);
-  return res;
-}
-
-TSAN_INTERCEPTOR(int, bind, int fd, void *addr, unsigned addrlen) {
-  SCOPED_TSAN_INTERCEPTOR(bind, fd, addr, addrlen);
-  int res = REAL(bind)(fd, addr, addrlen);
-  if (fd > 0 && res == 0)
-    FdAccess(thr, pc, fd);
-  return res;
-}
-
-TSAN_INTERCEPTOR(int, listen, int fd, int backlog) {
-  SCOPED_TSAN_INTERCEPTOR(listen, fd, backlog);
-  int res = REAL(listen)(fd, backlog);
-  if (fd > 0 && res == 0)
-    FdAccess(thr, pc, fd);
-  return res;
-}
-
-TSAN_INTERCEPTOR(int, close, int fd) {
-  SCOPED_TSAN_INTERCEPTOR(close, fd);
-  if (fd >= 0)
-    FdClose(thr, pc, fd);
-  return REAL(close)(fd);
-}
-
-#if SANITIZER_LINUX
-TSAN_INTERCEPTOR(int, __close, int fd) {
-  SCOPED_TSAN_INTERCEPTOR(__close, fd);
-  if (fd >= 0)
-    FdClose(thr, pc, fd);
-  return REAL(__close)(fd);
-}
-#define TSAN_MAYBE_INTERCEPT___CLOSE TSAN_INTERCEPT(__close)
-#else
-#define TSAN_MAYBE_INTERCEPT___CLOSE
-#endif
-
-// glibc guts
-#if SANITIZER_LINUX && !SANITIZER_ANDROID
-TSAN_INTERCEPTOR(void, __res_iclose, void *state, bool free_addr) {
-  SCOPED_TSAN_INTERCEPTOR(__res_iclose, state, free_addr);
-  int fds[64];
-  int cnt = ExtractResolvFDs(state, fds, ARRAY_SIZE(fds));
-  for (int i = 0; i < cnt; i++) {
-    if (fds[i] > 0)
-      FdClose(thr, pc, fds[i]);
-  }
-  REAL(__res_iclose)(state, free_addr);
-}
-#define TSAN_MAYBE_INTERCEPT___RES_ICLOSE TSAN_INTERCEPT(__res_iclose)
-#else
-#define TSAN_MAYBE_INTERCEPT___RES_ICLOSE
-#endif
-
-TSAN_INTERCEPTOR(int, pipe, int *pipefd) {
-  SCOPED_TSAN_INTERCEPTOR(pipe, pipefd);
-  int res = REAL(pipe)(pipefd);
-  if (res == 0 && pipefd[0] >= 0 && pipefd[1] >= 0)
-    FdPipeCreate(thr, pc, pipefd[0], pipefd[1]);
-  return res;
-}
-
-#if !SANITIZER_MAC
-TSAN_INTERCEPTOR(int, pipe2, int *pipefd, int flags) {
-  SCOPED_TSAN_INTERCEPTOR(pipe2, pipefd, flags);
-  int res = REAL(pipe2)(pipefd, flags);
-  if (res == 0 && pipefd[0] >= 0 && pipefd[1] >= 0)
-    FdPipeCreate(thr, pc, pipefd[0], pipefd[1]);
-  return res;
-}
-#endif
-
-TSAN_INTERCEPTOR(int, unlink, char *path) {
-  SCOPED_TSAN_INTERCEPTOR(unlink, path);
-  Release(thr, pc, File2addr(path));
-  int res = REAL(unlink)(path);
-  return res;
-}
-
-TSAN_INTERCEPTOR(void*, tmpfile, int fake) {
-  SCOPED_TSAN_INTERCEPTOR(tmpfile, fake);
-  void *res = REAL(tmpfile)(fake);
-  if (res) {
-    int fd = fileno_unlocked(res);
-    if (fd >= 0)
-      FdFileCreate(thr, pc, fd);
-  }
-  return res;
-}
-
-#if SANITIZER_LINUX
-TSAN_INTERCEPTOR(void*, tmpfile64, int fake) {
-  SCOPED_TSAN_INTERCEPTOR(tmpfile64, fake);
-  void *res = REAL(tmpfile64)(fake);
-  if (res) {
-    int fd = fileno_unlocked(res);
-    if (fd >= 0)
-      FdFileCreate(thr, pc, fd);
-  }
-  return res;
-}
-#define TSAN_MAYBE_INTERCEPT_TMPFILE64 TSAN_INTERCEPT(tmpfile64)
-#else
-#define TSAN_MAYBE_INTERCEPT_TMPFILE64
-#endif
-
-static void FlushStreams() {
-  // Flushing all the streams here may freeze the process if a child thread is
-  // performing file stream operations at the same time.
-  REAL(fflush)(stdout);
-  REAL(fflush)(stderr);
-}
-
-TSAN_INTERCEPTOR(void, abort, int fake) {
-  SCOPED_TSAN_INTERCEPTOR(abort, fake);
-  FlushStreams();
-  REAL(abort)(fake);
-}
-
-TSAN_INTERCEPTOR(int, rmdir, char *path) {
-  SCOPED_TSAN_INTERCEPTOR(rmdir, path);
-  Release(thr, pc, Dir2addr(path));
-  int res = REAL(rmdir)(path);
-  return res;
-}
-
-TSAN_INTERCEPTOR(int, closedir, void *dirp) {
-  SCOPED_TSAN_INTERCEPTOR(closedir, dirp);
-  if (dirp) {
-    int fd = dirfd(dirp);
-    FdClose(thr, pc, fd);
-  }
-  return REAL(closedir)(dirp);
-}
-
-#if SANITIZER_LINUX
-TSAN_INTERCEPTOR(int, epoll_create, int size) {
-  SCOPED_TSAN_INTERCEPTOR(epoll_create, size);
-  int fd = REAL(epoll_create)(size);
-  if (fd >= 0)
-    FdPollCreate(thr, pc, fd);
-  return fd;
-}
-
-TSAN_INTERCEPTOR(int, epoll_create1, int flags) {
-  SCOPED_TSAN_INTERCEPTOR(epoll_create1, flags);
-  int fd = REAL(epoll_create1)(flags);
-  if (fd >= 0)
-    FdPollCreate(thr, pc, fd);
-  return fd;
-}
-
-TSAN_INTERCEPTOR(int, epoll_ctl, int epfd, int op, int fd, void *ev) {
-  SCOPED_TSAN_INTERCEPTOR(epoll_ctl, epfd, op, fd, ev);
-  if (epfd >= 0)
-    FdAccess(thr, pc, epfd);
-  if (epfd >= 0 && fd >= 0)
-    FdAccess(thr, pc, fd);
-  if (op == EPOLL_CTL_ADD && epfd >= 0)
-    FdRelease(thr, pc, epfd);
-  int res = REAL(epoll_ctl)(epfd, op, fd, ev);
-  return res;
-}
-
-TSAN_INTERCEPTOR(int, epoll_wait, int epfd, void *ev, int cnt, int timeout) {
-  SCOPED_TSAN_INTERCEPTOR(epoll_wait, epfd, ev, cnt, timeout);
-  if (epfd >= 0)
-    FdAccess(thr, pc, epfd);
-  int res = BLOCK_REAL(epoll_wait)(epfd, ev, cnt, timeout);
-  if (res > 0 && epfd >= 0)
-    FdAcquire(thr, pc, epfd);
-  return res;
-}
-
-TSAN_INTERCEPTOR(int, epoll_pwait, int epfd, void *ev, int cnt, int timeout,
-                 void *sigmask) {
-  SCOPED_TSAN_INTERCEPTOR(epoll_pwait, epfd, ev, cnt, timeout, sigmask);
-  if (epfd >= 0)
-    FdAccess(thr, pc, epfd);
-  int res = BLOCK_REAL(epoll_pwait)(epfd, ev, cnt, timeout, sigmask);
-  if (res > 0 && epfd >= 0)
-    FdAcquire(thr, pc, epfd);
-  return res;
-}
-
-#define TSAN_MAYBE_INTERCEPT_EPOLL \
-    TSAN_INTERCEPT(epoll_create); \
-    TSAN_INTERCEPT(epoll_create1); \
-    TSAN_INTERCEPT(epoll_ctl); \
-    TSAN_INTERCEPT(epoll_wait); \
-    TSAN_INTERCEPT(epoll_pwait)
-#else
-#define TSAN_MAYBE_INTERCEPT_EPOLL
-#endif
-
-// The following functions are intercepted merely to process pending signals.
-// If program blocks signal X, we must deliver the signal before the function
-// returns. Similarly, if program unblocks a signal (or returns from sigsuspend)
-// it's better to deliver the signal straight away.
-TSAN_INTERCEPTOR(int, sigsuspend, const __sanitizer_sigset_t *mask) {
-  SCOPED_TSAN_INTERCEPTOR(sigsuspend, mask);
-  return REAL(sigsuspend)(mask);
-}
-
-TSAN_INTERCEPTOR(int, sigblock, int mask) {
-  SCOPED_TSAN_INTERCEPTOR(sigblock, mask);
-  return REAL(sigblock)(mask);
-}
-
-TSAN_INTERCEPTOR(int, sigsetmask, int mask) {
-  SCOPED_TSAN_INTERCEPTOR(sigsetmask, mask);
-  return REAL(sigsetmask)(mask);
-}
-
-TSAN_INTERCEPTOR(int, pthread_sigmask, int how, const __sanitizer_sigset_t *set,
-    __sanitizer_sigset_t *oldset) {
-  SCOPED_TSAN_INTERCEPTOR(pthread_sigmask, how, set, oldset);
-  return REAL(pthread_sigmask)(how, set, oldset);
-}
-
-namespace __tsan {
-
-static void CallUserSignalHandler(ThreadState *thr, bool sync, bool acquire,
-                                  bool sigact, int sig,
-                                  __sanitizer_siginfo *info, void *uctx) {
-  __sanitizer_sigaction *sigactions = interceptor_ctx()->sigactions;
-  if (acquire)
-    Acquire(thr, 0, (uptr)&sigactions[sig]);
-  // Signals are generally asynchronous, so if we receive a signals when
-  // ignores are enabled we should disable ignores. This is critical for sync
-  // and interceptors, because otherwise we can miss syncronization and report
-  // false races.
-  int ignore_reads_and_writes = thr->ignore_reads_and_writes;
-  int ignore_interceptors = thr->ignore_interceptors;
-  int ignore_sync = thr->ignore_sync;
-  if (!ctx->after_multithreaded_fork) {
-    thr->ignore_reads_and_writes = 0;
-    thr->fast_state.ClearIgnoreBit();
-    thr->ignore_interceptors = 0;
-    thr->ignore_sync = 0;
-  }
-  // Ensure that the handler does not spoil errno.
-  const int saved_errno = errno;
-  errno = 99;
-  // This code races with sigaction. Be careful to not read sa_sigaction twice.
-  // Also need to remember pc for reporting before the call,
-  // because the handler can reset it.
-  volatile uptr pc =
-      sigact ? (uptr)sigactions[sig].sigaction : (uptr)sigactions[sig].handler;
-  if (pc != sig_dfl && pc != sig_ign) {
-    if (sigact)
-      ((__sanitizer_sigactionhandler_ptr)pc)(sig, info, uctx);
-    else
-      ((__sanitizer_sighandler_ptr)pc)(sig);
-  }
-  if (!ctx->after_multithreaded_fork) {
-    thr->ignore_reads_and_writes = ignore_reads_and_writes;
-    if (ignore_reads_and_writes)
-      thr->fast_state.SetIgnoreBit();
-    thr->ignore_interceptors = ignore_interceptors;
-    thr->ignore_sync = ignore_sync;
-  }
-  // We do not detect errno spoiling for SIGTERM,
-  // because some SIGTERM handlers do spoil errno but reraise SIGTERM,
-  // tsan reports false positive in such case.
-  // It's difficult to properly detect this situation (reraise),
-  // because in async signal processing case (when handler is called directly
-  // from rtl_generic_sighandler) we have not yet received the reraised
-  // signal; and it looks too fragile to intercept all ways to reraise a signal.
-  if (flags()->report_bugs && !sync && sig != SIGTERM && errno != 99) {
-    VarSizeStackTrace stack;
-    // StackTrace::GetNestInstructionPc(pc) is used because return address is
-    // expected, OutputReport() will undo this.
-    ObtainCurrentStack(thr, StackTrace::GetNextInstructionPc(pc), &stack);
-    ThreadRegistryLock l(ctx->thread_registry);
-    ScopedReport rep(ReportTypeErrnoInSignal);
-    if (!IsFiredSuppression(ctx, ReportTypeErrnoInSignal, stack)) {
-      rep.AddStack(stack, true);
-      OutputReport(thr, rep);
-    }
-  }
-  errno = saved_errno;
-}
-
-void ProcessPendingSignals(ThreadState *thr) {
-  ThreadSignalContext *sctx = SigCtx(thr);
-  if (sctx == 0 ||
-      atomic_load(&sctx->have_pending_signals, memory_order_relaxed) == 0)
-    return;
-  atomic_store(&sctx->have_pending_signals, 0, memory_order_relaxed);
-  atomic_fetch_add(&thr->in_signal_handler, 1, memory_order_relaxed);
-  internal_sigfillset(&sctx->emptyset);
-  int res = REAL(pthread_sigmask)(SIG_SETMASK, &sctx->emptyset, &sctx->oldset);
-  CHECK_EQ(res, 0);
-  for (int sig = 0; sig < kSigCount; sig++) {
-    SignalDesc *signal = &sctx->pending_signals[sig];
-    if (signal->armed) {
-      signal->armed = false;
-      CallUserSignalHandler(thr, false, true, signal->sigaction, sig,
-          &signal->siginfo, &signal->ctx);
-    }
-  }
-  res = REAL(pthread_sigmask)(SIG_SETMASK, &sctx->oldset, 0);
-  CHECK_EQ(res, 0);
-  atomic_fetch_add(&thr->in_signal_handler, -1, memory_order_relaxed);
-}
-
-}  // namespace __tsan
-
-static bool is_sync_signal(ThreadSignalContext *sctx, int sig) {
-  return sig == SIGSEGV || sig == SIGBUS || sig == SIGILL ||
-      sig == SIGABRT || sig == SIGFPE || sig == SIGPIPE || sig == SIGSYS ||
-      // If we are sending signal to ourselves, we must process it now.
-      (sctx && sig == sctx->int_signal_send);
-}
-
-void ALWAYS_INLINE rtl_generic_sighandler(bool sigact, int sig,
-                                          __sanitizer_siginfo *info,
-                                          void *ctx) {
-  cur_thread_init();
-  ThreadState *thr = cur_thread();
-  ThreadSignalContext *sctx = SigCtx(thr);
-  if (sig < 0 || sig >= kSigCount) {
-    VPrintf(1, "ThreadSanitizer: ignoring signal %d\n", sig);
-    return;
-  }
-  // Don't mess with synchronous signals.
-  const bool sync = is_sync_signal(sctx, sig);
-  if (sync ||
-      // If we are in blocking function, we can safely process it now
-      // (but check if we are in a recursive interceptor,
-      // i.e. pthread_join()->munmap()).
-      (sctx && atomic_load(&sctx->in_blocking_func, memory_order_relaxed))) {
-    atomic_fetch_add(&thr->in_signal_handler, 1, memory_order_relaxed);
-    if (sctx && atomic_load(&sctx->in_blocking_func, memory_order_relaxed)) {
-      atomic_store(&sctx->in_blocking_func, 0, memory_order_relaxed);
-      CallUserSignalHandler(thr, sync, true, sigact, sig, info, ctx);
-      atomic_store(&sctx->in_blocking_func, 1, memory_order_relaxed);
-    } else {
-      // Be very conservative with when we do acquire in this case.
-      // It's unsafe to do acquire in async handlers, because ThreadState
-      // can be in inconsistent state.
-      // SIGSYS looks relatively safe -- it's synchronous and can actually
-      // need some global state.
-      bool acq = (sig == SIGSYS);
-      CallUserSignalHandler(thr, sync, acq, sigact, sig, info, ctx);
-    }
-    atomic_fetch_add(&thr->in_signal_handler, -1, memory_order_relaxed);
-    return;
-  }
-
-  if (sctx == 0)
-    return;
-  SignalDesc *signal = &sctx->pending_signals[sig];
-  if (signal->armed == false) {
-    signal->armed = true;
-    signal->sigaction = sigact;
-    if (info)
-      internal_memcpy(&signal->siginfo, info, sizeof(*info));
-    if (ctx)
-      internal_memcpy(&signal->ctx, ctx, sizeof(signal->ctx));
-    atomic_store(&sctx->have_pending_signals, 1, memory_order_relaxed);
-  }
-}
-
-static void rtl_sighandler(int sig) {
-  rtl_generic_sighandler(false, sig, 0, 0);
-}
-
-static void rtl_sigaction(int sig, __sanitizer_siginfo *info, void *ctx) {
-  rtl_generic_sighandler(true, sig, info, ctx);
-}
-
-TSAN_INTERCEPTOR(int, raise, int sig) {
-  SCOPED_TSAN_INTERCEPTOR(raise, sig);
-  ThreadSignalContext *sctx = SigCtx(thr);
-  CHECK_NE(sctx, 0);
-  int prev = sctx->int_signal_send;
-  sctx->int_signal_send = sig;
-  int res = REAL(raise)(sig);
-  CHECK_EQ(sctx->int_signal_send, sig);
-  sctx->int_signal_send = prev;
-  return res;
-}
-
-TSAN_INTERCEPTOR(int, kill, int pid, int sig) {
-  SCOPED_TSAN_INTERCEPTOR(kill, pid, sig);
-  ThreadSignalContext *sctx = SigCtx(thr);
-  CHECK_NE(sctx, 0);
-  int prev = sctx->int_signal_send;
-  if (pid == (int)internal_getpid()) {
-    sctx->int_signal_send = sig;
-  }
-  int res = REAL(kill)(pid, sig);
-  if (pid == (int)internal_getpid()) {
-    CHECK_EQ(sctx->int_signal_send, sig);
-    sctx->int_signal_send = prev;
-  }
-  return res;
-}
-
-TSAN_INTERCEPTOR(int, pthread_kill, void *tid, int sig) {
-  SCOPED_TSAN_INTERCEPTOR(pthread_kill, tid, sig);
-  ThreadSignalContext *sctx = SigCtx(thr);
-  CHECK_NE(sctx, 0);
-  int prev = sctx->int_signal_send;
-  if (tid == pthread_self()) {
-    sctx->int_signal_send = sig;
-  }
-  int res = REAL(pthread_kill)(tid, sig);
-  if (tid == pthread_self()) {
-    CHECK_EQ(sctx->int_signal_send, sig);
-    sctx->int_signal_send = prev;
-  }
-  return res;
-}
-
-TSAN_INTERCEPTOR(int, gettimeofday, void *tv, void *tz) {
-  SCOPED_TSAN_INTERCEPTOR(gettimeofday, tv, tz);
-  // It's intercepted merely to process pending signals.
-  return REAL(gettimeofday)(tv, tz);
-}
-
-TSAN_INTERCEPTOR(int, getaddrinfo, void *node, void *service,
-    void *hints, void *rv) {
-  SCOPED_TSAN_INTERCEPTOR(getaddrinfo, node, service, hints, rv);
-  // We miss atomic synchronization in getaddrinfo,
-  // and can report false race between malloc and free
-  // inside of getaddrinfo. So ignore memory accesses.
-  ThreadIgnoreBegin(thr, pc);
-  int res = REAL(getaddrinfo)(node, service, hints, rv);
-  ThreadIgnoreEnd(thr, pc);
-  return res;
-}
-
-TSAN_INTERCEPTOR(int, fork, int fake) {
-  if (in_symbolizer())
-    return REAL(fork)(fake);
-  SCOPED_INTERCEPTOR_RAW(fork, fake);
-  ForkBefore(thr, pc);
-  int pid;
-  {
-    // On OS X, REAL(fork) can call intercepted functions (OSSpinLockLock), and
-    // we'll assert in CheckNoLocks() unless we ignore interceptors.
-    ScopedIgnoreInterceptors ignore;
-    pid = REAL(fork)(fake);
-  }
-  if (pid == 0) {
-    // child
-    ForkChildAfter(thr, pc);
-    FdOnFork(thr, pc);
-  } else if (pid > 0) {
-    // parent
-    ForkParentAfter(thr, pc);
-  } else {
-    // error
-    ForkParentAfter(thr, pc);
-  }
-  return pid;
-}
-
-TSAN_INTERCEPTOR(int, vfork, int fake) {
-  // Some programs (e.g. openjdk) call close for all file descriptors
-  // in the child process. Under tsan it leads to false positives, because
-  // address space is shared, so the parent process also thinks that
-  // the descriptors are closed (while they are actually not).
-  // This leads to false positives due to missed synchronization.
-  // Strictly saying this is undefined behavior, because vfork child is not
-  // allowed to call any functions other than exec/exit. But this is what
-  // openjdk does, so we want to handle it.
-  // We could disable interceptors in the child process. But it's not possible
-  // to simply intercept and wrap vfork, because vfork child is not allowed
-  // to return from the function that calls vfork, and that's exactly what
-  // we would do. So this would require some assembly trickery as well.
-  // Instead we simply turn vfork into fork.
-  return WRAP(fork)(fake);
-}
-
-#if !SANITIZER_MAC && !SANITIZER_ANDROID
-typedef int (*dl_iterate_phdr_cb_t)(__sanitizer_dl_phdr_info *info, SIZE_T size,
-                                    void *data);
-struct dl_iterate_phdr_data {
-  ThreadState *thr;
-  uptr pc;
-  dl_iterate_phdr_cb_t cb;
-  void *data;
-};
-
-static bool IsAppNotRodata(uptr addr) {
-  return IsAppMem(addr) && *(u64*)MemToShadow(addr) != kShadowRodata;
-}
-
-static int dl_iterate_phdr_cb(__sanitizer_dl_phdr_info *info, SIZE_T size,
-                              void *data) {
-  dl_iterate_phdr_data *cbdata = (dl_iterate_phdr_data *)data;
-  // dlopen/dlclose allocate/free dynamic-linker-internal memory, which is later
-  // accessible in dl_iterate_phdr callback. But we don't see synchronization
-  // inside of dynamic linker, so we "unpoison" it here in order to not
-  // produce false reports. Ignoring malloc/free in dlopen/dlclose is not enough
-  // because some libc functions call __libc_dlopen.
-  if (info && IsAppNotRodata((uptr)info->dlpi_name))
-    MemoryResetRange(cbdata->thr, cbdata->pc, (uptr)info->dlpi_name,
-                     internal_strlen(info->dlpi_name));
-  int res = cbdata->cb(info, size, cbdata->data);
-  // Perform the check one more time in case info->dlpi_name was overwritten
-  // by user callback.
-  if (info && IsAppNotRodata((uptr)info->dlpi_name))
-    MemoryResetRange(cbdata->thr, cbdata->pc, (uptr)info->dlpi_name,
-                     internal_strlen(info->dlpi_name));
-  return res;
-}
-
-TSAN_INTERCEPTOR(int, dl_iterate_phdr, dl_iterate_phdr_cb_t cb, void *data) {
-  SCOPED_TSAN_INTERCEPTOR(dl_iterate_phdr, cb, data);
-  dl_iterate_phdr_data cbdata;
-  cbdata.thr = thr;
-  cbdata.pc = pc;
-  cbdata.cb = cb;
-  cbdata.data = data;
-  int res = REAL(dl_iterate_phdr)(dl_iterate_phdr_cb, &cbdata);
-  return res;
-}
-#endif
-
-static int OnExit(ThreadState *thr) {
-  int status = Finalize(thr);
-  FlushStreams();
-  return status;
-}
-
-struct TsanInterceptorContext {
-  ThreadState *thr;
-  const uptr caller_pc;
-  const uptr pc;
-};
-
-#if !SANITIZER_MAC
-static void HandleRecvmsg(ThreadState *thr, uptr pc,
-    __sanitizer_msghdr *msg) {
-  int fds[64];
-  int cnt = ExtractRecvmsgFDs(msg, fds, ARRAY_SIZE(fds));
-  for (int i = 0; i < cnt; i++)
-    FdEventCreate(thr, pc, fds[i]);
-}
-#endif
-
-#include "sanitizer_common/sanitizer_platform_interceptors.h"
-// Causes interceptor recursion (getaddrinfo() and fopen())
-#undef SANITIZER_INTERCEPT_GETADDRINFO
-// We define our own.
-#if SANITIZER_INTERCEPT_TLS_GET_ADDR
-#define NEED_TLS_GET_ADDR
-#endif
-#undef SANITIZER_INTERCEPT_TLS_GET_ADDR
-#undef SANITIZER_INTERCEPT_PTHREAD_SIGMASK
-
-#define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name)
-#define COMMON_INTERCEPT_FUNCTION_VER(name, ver)                          \
-  INTERCEPT_FUNCTION_VER(name, ver)
-
-#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size)                    \
-  MemoryAccessRange(((TsanInterceptorContext *)ctx)->thr,                 \
-                    ((TsanInterceptorContext *)ctx)->pc, (uptr)ptr, size, \
-                    true)
-
-#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size)                       \
-  MemoryAccessRange(((TsanInterceptorContext *) ctx)->thr,                  \
-                    ((TsanInterceptorContext *) ctx)->pc, (uptr) ptr, size, \
-                    false)
-
-#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...)      \
-  SCOPED_TSAN_INTERCEPTOR(func, __VA_ARGS__);         \
-  TsanInterceptorContext _ctx = {thr, caller_pc, pc}; \
-  ctx = (void *)&_ctx;                                \
-  (void) ctx;
-
-#define COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, func, ...) \
-  SCOPED_INTERCEPTOR_RAW(func, __VA_ARGS__);              \
-  TsanInterceptorContext _ctx = {thr, caller_pc, pc};     \
-  ctx = (void *)&_ctx;                                    \
-  (void) ctx;
-
-#define COMMON_INTERCEPTOR_FILE_OPEN(ctx, file, path) \
-  if (path)                                           \
-    Acquire(thr, pc, File2addr(path));                \
-  if (file) {                                         \
-    int fd = fileno_unlocked(file);                   \
-    if (fd >= 0) FdFileCreate(thr, pc, fd);           \
-  }
-
-#define COMMON_INTERCEPTOR_FILE_CLOSE(ctx, file) \
-  if (file) {                                    \
-    int fd = fileno_unlocked(file);              \
-    if (fd >= 0) FdClose(thr, pc, fd);           \
-  }
-
-#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) \
-  libignore()->OnLibraryLoaded(filename)
-
-#define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() \
-  libignore()->OnLibraryUnloaded()
-
-#define COMMON_INTERCEPTOR_ACQUIRE(ctx, u) \
-  Acquire(((TsanInterceptorContext *) ctx)->thr, pc, u)
-
-#define COMMON_INTERCEPTOR_RELEASE(ctx, u) \
-  Release(((TsanInterceptorContext *) ctx)->thr, pc, u)
-
-#define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \
-  Acquire(((TsanInterceptorContext *) ctx)->thr, pc, Dir2addr(path))
-
-#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
-  FdAcquire(((TsanInterceptorContext *) ctx)->thr, pc, fd)
-
-#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
-  FdRelease(((TsanInterceptorContext *) ctx)->thr, pc, fd)
-
-#define COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd) \
-  FdAccess(((TsanInterceptorContext *) ctx)->thr, pc, fd)
-
-#define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
-  FdSocketAccept(((TsanInterceptorContext *) ctx)->thr, pc, fd, newfd)
-
-#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \
-  ThreadSetName(((TsanInterceptorContext *) ctx)->thr, name)
-
-#define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
-  __tsan::ctx->thread_registry->SetThreadNameByUserId(thread, name)
-
-#define COMMON_INTERCEPTOR_BLOCK_REAL(name) BLOCK_REAL(name)
-
-#define COMMON_INTERCEPTOR_ON_EXIT(ctx) \
-  OnExit(((TsanInterceptorContext *) ctx)->thr)
-
-#define COMMON_INTERCEPTOR_MUTEX_PRE_LOCK(ctx, m) \
-  MutexPreLock(((TsanInterceptorContext *)ctx)->thr, \
-            ((TsanInterceptorContext *)ctx)->pc, (uptr)m)
-
-#define COMMON_INTERCEPTOR_MUTEX_POST_LOCK(ctx, m) \
-  MutexPostLock(((TsanInterceptorContext *)ctx)->thr, \
-            ((TsanInterceptorContext *)ctx)->pc, (uptr)m)
-
-#define COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m) \
-  MutexUnlock(((TsanInterceptorContext *)ctx)->thr, \
-            ((TsanInterceptorContext *)ctx)->pc, (uptr)m)
-
-#define COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m) \
-  MutexRepair(((TsanInterceptorContext *)ctx)->thr, \
-            ((TsanInterceptorContext *)ctx)->pc, (uptr)m)
-
-#define COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m) \
-  MutexInvalidAccess(((TsanInterceptorContext *)ctx)->thr, \
-                     ((TsanInterceptorContext *)ctx)->pc, (uptr)m)
-
-#define COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, sz, prot, flags, fd,  \
-                                     off)                                   \
-  do {                                                                      \
-    return mmap_interceptor(thr, pc, REAL(mmap), addr, sz, prot, flags, fd, \
-                            off);                                           \
-  } while (false)
-
-#if !SANITIZER_MAC
-#define COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, msg) \
-  HandleRecvmsg(((TsanInterceptorContext *)ctx)->thr, \
-      ((TsanInterceptorContext *)ctx)->pc, msg)
-#endif
-
-#define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end)                           \
-  if (TsanThread *t = GetCurrentThread()) {                                    \
-    *begin = t->tls_begin();                                                   \
-    *end = t->tls_end();                                                       \
-  } else {                                                                     \
-    *begin = *end = 0;                                                         \
-  }
-
-#define COMMON_INTERCEPTOR_USER_CALLBACK_START() \
-  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START()
-
-#define COMMON_INTERCEPTOR_USER_CALLBACK_END() \
-  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END()
-
-#include "sanitizer_common/sanitizer_common_interceptors.inc"
-
-static int sigaction_impl(int sig, const __sanitizer_sigaction *act,
-                          __sanitizer_sigaction *old);
-static __sanitizer_sighandler_ptr signal_impl(int sig,
-                                              __sanitizer_sighandler_ptr h);
-
-#define SIGNAL_INTERCEPTOR_SIGACTION_IMPL(signo, act, oldact) \
-  { return sigaction_impl(signo, act, oldact); }
-
-#define SIGNAL_INTERCEPTOR_SIGNAL_IMPL(func, signo, handler) \
-  { return (uptr)signal_impl(signo, (__sanitizer_sighandler_ptr)handler); }
-
-#include "sanitizer_common/sanitizer_signal_interceptors.inc"
-
-int sigaction_impl(int sig, const __sanitizer_sigaction *act,
-                   __sanitizer_sigaction *old) {
-  // Note: if we call REAL(sigaction) directly for any reason without proxying
-  // the signal handler through rtl_sigaction, very bad things will happen.
-  // The handler will run synchronously and corrupt tsan per-thread state.
-  SCOPED_INTERCEPTOR_RAW(sigaction, sig, act, old);
-  __sanitizer_sigaction *sigactions = interceptor_ctx()->sigactions;
-  __sanitizer_sigaction old_stored;
-  if (old) internal_memcpy(&old_stored, &sigactions[sig], sizeof(old_stored));
-  __sanitizer_sigaction newact;
-  if (act) {
-    // Copy act into sigactions[sig].
-    // Can't use struct copy, because compiler can emit call to memcpy.
-    // Can't use internal_memcpy, because it copies byte-by-byte,
-    // and signal handler reads the handler concurrently. It it can read
-    // some bytes from old value and some bytes from new value.
-    // Use volatile to prevent insertion of memcpy.
-    sigactions[sig].handler =
-        *(volatile __sanitizer_sighandler_ptr const *)&act->handler;
-    sigactions[sig].sa_flags = *(volatile int const *)&act->sa_flags;
-    internal_memcpy(&sigactions[sig].sa_mask, &act->sa_mask,
-                    sizeof(sigactions[sig].sa_mask));
-#if !SANITIZER_FREEBSD && !SANITIZER_MAC && !SANITIZER_NETBSD
-    sigactions[sig].sa_restorer = act->sa_restorer;
-#endif
-    internal_memcpy(&newact, act, sizeof(newact));
-    internal_sigfillset(&newact.sa_mask);
-    if ((uptr)act->handler != sig_ign && (uptr)act->handler != sig_dfl) {
-      if (newact.sa_flags & SA_SIGINFO)
-        newact.sigaction = rtl_sigaction;
-      else
-        newact.handler = rtl_sighandler;
-    }
-    ReleaseStore(thr, pc, (uptr)&sigactions[sig]);
-    act = &newact;
-  }
-  int res = REAL(sigaction)(sig, act, old);
-  if (res == 0 && old) {
-    uptr cb = (uptr)old->sigaction;
-    if (cb == (uptr)rtl_sigaction || cb == (uptr)rtl_sighandler) {
-      internal_memcpy(old, &old_stored, sizeof(*old));
-    }
-  }
-  return res;
-}
-
-static __sanitizer_sighandler_ptr signal_impl(int sig,
-                                              __sanitizer_sighandler_ptr h) {
-  __sanitizer_sigaction act;
-  act.handler = h;
-  internal_memset(&act.sa_mask, -1, sizeof(act.sa_mask));
-  act.sa_flags = 0;
-  __sanitizer_sigaction old;
-  int res = sigaction_symname(sig, &act, &old);
-  if (res) return (__sanitizer_sighandler_ptr)sig_err;
-  return old.handler;
-}
-
-#define TSAN_SYSCALL() \
-  ThreadState *thr = cur_thread(); \
-  if (thr->ignore_interceptors) \
-    return; \
-  ScopedSyscall scoped_syscall(thr) \
-/**/
-
-struct ScopedSyscall {
-  ThreadState *thr;
-
-  explicit ScopedSyscall(ThreadState *thr)
-      : thr(thr) {
-    Initialize(thr);
-  }
-
-  ~ScopedSyscall() {
-    ProcessPendingSignals(thr);
-  }
-};
-
-#if !SANITIZER_FREEBSD && !SANITIZER_MAC
-static void syscall_access_range(uptr pc, uptr p, uptr s, bool write) {
-  TSAN_SYSCALL();
-  MemoryAccessRange(thr, pc, p, s, write);
-}
-
-static void syscall_acquire(uptr pc, uptr addr) {
-  TSAN_SYSCALL();
-  Acquire(thr, pc, addr);
-  DPrintf("syscall_acquire(%p)\n", addr);
-}
-
-static void syscall_release(uptr pc, uptr addr) {
-  TSAN_SYSCALL();
-  DPrintf("syscall_release(%p)\n", addr);
-  Release(thr, pc, addr);
-}
-
-static void syscall_fd_close(uptr pc, int fd) {
-  TSAN_SYSCALL();
-  FdClose(thr, pc, fd);
-}
-
-static USED void syscall_fd_acquire(uptr pc, int fd) {
-  TSAN_SYSCALL();
-  FdAcquire(thr, pc, fd);
-  DPrintf("syscall_fd_acquire(%p)\n", fd);
-}
-
-static USED void syscall_fd_release(uptr pc, int fd) {
-  TSAN_SYSCALL();
-  DPrintf("syscall_fd_release(%p)\n", fd);
-  FdRelease(thr, pc, fd);
-}
-
-static void syscall_pre_fork(uptr pc) {
-  TSAN_SYSCALL();
-  ForkBefore(thr, pc);
-}
-
-static void syscall_post_fork(uptr pc, int pid) {
-  TSAN_SYSCALL();
-  if (pid == 0) {
-    // child
-    ForkChildAfter(thr, pc);
-    FdOnFork(thr, pc);
-  } else if (pid > 0) {
-    // parent
-    ForkParentAfter(thr, pc);
-  } else {
-    // error
-    ForkParentAfter(thr, pc);
-  }
-}
-#endif
-
-#define COMMON_SYSCALL_PRE_READ_RANGE(p, s) \
-  syscall_access_range(GET_CALLER_PC(), (uptr)(p), (uptr)(s), false)
-
-#define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) \
-  syscall_access_range(GET_CALLER_PC(), (uptr)(p), (uptr)(s), true)
-
-#define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
-  do {                                       \
-    (void)(p);                               \
-    (void)(s);                               \
-  } while (false)
-
-#define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \
-  do {                                        \
-    (void)(p);                                \
-    (void)(s);                                \
-  } while (false)
-
-#define COMMON_SYSCALL_ACQUIRE(addr) \
-    syscall_acquire(GET_CALLER_PC(), (uptr)(addr))
-
-#define COMMON_SYSCALL_RELEASE(addr) \
-    syscall_release(GET_CALLER_PC(), (uptr)(addr))
-
-#define COMMON_SYSCALL_FD_CLOSE(fd) syscall_fd_close(GET_CALLER_PC(), fd)
-
-#define COMMON_SYSCALL_FD_ACQUIRE(fd) syscall_fd_acquire(GET_CALLER_PC(), fd)
-
-#define COMMON_SYSCALL_FD_RELEASE(fd) syscall_fd_release(GET_CALLER_PC(), fd)
-
-#define COMMON_SYSCALL_PRE_FORK() \
-  syscall_pre_fork(GET_CALLER_PC())
-
-#define COMMON_SYSCALL_POST_FORK(res) \
-  syscall_post_fork(GET_CALLER_PC(), res)
-
-#include "sanitizer_common/sanitizer_common_syscalls.inc"
-#include "sanitizer_common/sanitizer_syscalls_netbsd.inc"
-
-#ifdef NEED_TLS_GET_ADDR
-// Define own interceptor instead of sanitizer_common's for three reasons:
-// 1. It must not process pending signals.
-//    Signal handlers may contain MOVDQA instruction (see below).
-// 2. It must be as simple as possible to not contain MOVDQA.
-// 3. Sanitizer_common version uses COMMON_INTERCEPTOR_INITIALIZE_RANGE which
-//    is empty for tsan (meant only for msan).
-// Note: __tls_get_addr can be called with mis-aligned stack due to:
-// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58066
-// So the interceptor must work with mis-aligned stack, in particular, does not
-// execute MOVDQA with stack addresses.
-TSAN_INTERCEPTOR(void *, __tls_get_addr, void *arg) {
-  void *res = REAL(__tls_get_addr)(arg);
-  ThreadState *thr = cur_thread();
-  if (!thr)
-    return res;
-  DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, res, thr->tls_addr,
-                                        thr->tls_addr + thr->tls_size);
-  if (!dtv)
-    return res;
-  // New DTLS block has been allocated.
-  MemoryResetRange(thr, 0, dtv->beg, dtv->size);
-  return res;
-}
-#endif
-
-#if SANITIZER_NETBSD
-TSAN_INTERCEPTOR(void, _lwp_exit) {
-  SCOPED_TSAN_INTERCEPTOR(_lwp_exit);
-  DestroyThreadState();
-  REAL(_lwp_exit)();
-}
-#define TSAN_MAYBE_INTERCEPT__LWP_EXIT TSAN_INTERCEPT(_lwp_exit)
-#else
-#define TSAN_MAYBE_INTERCEPT__LWP_EXIT
-#endif
-
-#if SANITIZER_FREEBSD
-TSAN_INTERCEPTOR(void, thr_exit, tid_t *state) {
-  SCOPED_TSAN_INTERCEPTOR(thr_exit, state);
-  DestroyThreadState();
-  REAL(thr_exit(state));
-}
-#define TSAN_MAYBE_INTERCEPT_THR_EXIT TSAN_INTERCEPT(thr_exit)
-#else
-#define TSAN_MAYBE_INTERCEPT_THR_EXIT
-#endif
-
-TSAN_INTERCEPTOR_NETBSD_ALIAS(int, cond_init, void *c, void *a)
-TSAN_INTERCEPTOR_NETBSD_ALIAS(int, cond_signal, void *c)
-TSAN_INTERCEPTOR_NETBSD_ALIAS(int, cond_broadcast, void *c)
-TSAN_INTERCEPTOR_NETBSD_ALIAS(int, cond_wait, void *c, void *m)
-TSAN_INTERCEPTOR_NETBSD_ALIAS(int, cond_destroy, void *c)
-TSAN_INTERCEPTOR_NETBSD_ALIAS(int, mutex_init, void *m, void *a)
-TSAN_INTERCEPTOR_NETBSD_ALIAS(int, mutex_destroy, void *m)
-TSAN_INTERCEPTOR_NETBSD_ALIAS(int, mutex_trylock, void *m)
-TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_init, void *m, void *a)
-TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_destroy, void *m)
-TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_rdlock, void *m)
-TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_tryrdlock, void *m)
-TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_wrlock, void *m)
-TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_trywrlock, void *m)
-TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_unlock, void *m)
-TSAN_INTERCEPTOR_NETBSD_ALIAS_THR(int, once, void *o, void (*f)())
-TSAN_INTERCEPTOR_NETBSD_ALIAS_THR2(int, sigsetmask, sigmask, int a, void *b,
-  void *c)
-
-namespace __tsan {
-
-static void finalize(void *arg) {
-  ThreadState *thr = cur_thread();
-  int status = Finalize(thr);
-  // Make sure the output is not lost.
-  FlushStreams();
-  if (status)
-    Die();
-}
-
-#if !SANITIZER_MAC && !SANITIZER_ANDROID
-static void unreachable() {
-  Report("FATAL: ThreadSanitizer: unreachable called\n");
-  Die();
-}
-#endif
-
-// Define default implementation since interception of libdispatch  is optional.
-SANITIZER_WEAK_ATTRIBUTE void InitializeLibdispatchInterceptors() {}
-
-void InitializeInterceptors() {
-#if !SANITIZER_MAC
-  // We need to setup it early, because functions like dlsym() can call it.
-  REAL(memset) = internal_memset;
-  REAL(memcpy) = internal_memcpy;
-#endif
-
-  // Instruct libc malloc to consume less memory.
-#if SANITIZER_LINUX
-  mallopt(1, 0);  // M_MXFAST
-  mallopt(-3, 32*1024);  // M_MMAP_THRESHOLD
-#endif
-
-  new(interceptor_ctx()) InterceptorContext();
-
-  InitializeCommonInterceptors();
-  InitializeSignalInterceptors();
-  InitializeLibdispatchInterceptors();
-
-#if !SANITIZER_MAC
-  // We can not use TSAN_INTERCEPT to get setjmp addr,
-  // because it does &setjmp and setjmp is not present in some versions of libc.
-  using __interception::InterceptFunction;
-  InterceptFunction(TSAN_STRING_SETJMP, (uptr*)&REAL(setjmp_symname), 0, 0);
-  InterceptFunction("_setjmp", (uptr*)&REAL(_setjmp), 0, 0);
-  InterceptFunction(TSAN_STRING_SIGSETJMP, (uptr*)&REAL(sigsetjmp_symname), 0,
-                    0);
-#if !SANITIZER_NETBSD
-  InterceptFunction("__sigsetjmp", (uptr*)&REAL(__sigsetjmp), 0, 0);
-#endif
-#endif
-
-  TSAN_INTERCEPT(longjmp_symname);
-  TSAN_INTERCEPT(siglongjmp_symname);
-#if SANITIZER_NETBSD
-  TSAN_INTERCEPT(_longjmp);
-#endif
-
-  TSAN_INTERCEPT(malloc);
-  TSAN_INTERCEPT(__libc_memalign);
-  TSAN_INTERCEPT(calloc);
-  TSAN_INTERCEPT(realloc);
-  TSAN_INTERCEPT(reallocarray);
-  TSAN_INTERCEPT(free);
-  TSAN_INTERCEPT(cfree);
-  TSAN_INTERCEPT(munmap);
-  TSAN_MAYBE_INTERCEPT_MEMALIGN;
-  TSAN_INTERCEPT(valloc);
-  TSAN_MAYBE_INTERCEPT_PVALLOC;
-  TSAN_INTERCEPT(posix_memalign);
-
-  TSAN_INTERCEPT(strcpy);  // NOLINT
-  TSAN_INTERCEPT(strncpy);
-  TSAN_INTERCEPT(strdup);
-
-  TSAN_INTERCEPT(pthread_create);
-  TSAN_INTERCEPT(pthread_join);
-  TSAN_INTERCEPT(pthread_detach);
-  TSAN_INTERCEPT(pthread_exit);
-  #if SANITIZER_LINUX
-  TSAN_INTERCEPT(pthread_tryjoin_np);
-  TSAN_INTERCEPT(pthread_timedjoin_np);
-  #endif
-
-  TSAN_INTERCEPT_VER(pthread_cond_init, PTHREAD_ABI_BASE);
-  TSAN_INTERCEPT_VER(pthread_cond_signal, PTHREAD_ABI_BASE);
-  TSAN_INTERCEPT_VER(pthread_cond_broadcast, PTHREAD_ABI_BASE);
-  TSAN_INTERCEPT_VER(pthread_cond_wait, PTHREAD_ABI_BASE);
-  TSAN_INTERCEPT_VER(pthread_cond_timedwait, PTHREAD_ABI_BASE);
-  TSAN_INTERCEPT_VER(pthread_cond_destroy, PTHREAD_ABI_BASE);
-
-  TSAN_INTERCEPT(pthread_mutex_init);
-  TSAN_INTERCEPT(pthread_mutex_destroy);
-  TSAN_INTERCEPT(pthread_mutex_trylock);
-  TSAN_INTERCEPT(pthread_mutex_timedlock);
-
-  TSAN_INTERCEPT(pthread_spin_init);
-  TSAN_INTERCEPT(pthread_spin_destroy);
-  TSAN_INTERCEPT(pthread_spin_lock);
-  TSAN_INTERCEPT(pthread_spin_trylock);
-  TSAN_INTERCEPT(pthread_spin_unlock);
-
-  TSAN_INTERCEPT(pthread_rwlock_init);
-  TSAN_INTERCEPT(pthread_rwlock_destroy);
-  TSAN_INTERCEPT(pthread_rwlock_rdlock);
-  TSAN_INTERCEPT(pthread_rwlock_tryrdlock);
-  TSAN_INTERCEPT(pthread_rwlock_timedrdlock);
-  TSAN_INTERCEPT(pthread_rwlock_wrlock);
-  TSAN_INTERCEPT(pthread_rwlock_trywrlock);
-  TSAN_INTERCEPT(pthread_rwlock_timedwrlock);
-  TSAN_INTERCEPT(pthread_rwlock_unlock);
-
-  TSAN_INTERCEPT(pthread_barrier_init);
-  TSAN_INTERCEPT(pthread_barrier_destroy);
-  TSAN_INTERCEPT(pthread_barrier_wait);
-
-  TSAN_INTERCEPT(pthread_once);
-
-  TSAN_INTERCEPT(fstat);
-  TSAN_MAYBE_INTERCEPT___FXSTAT;
-  TSAN_MAYBE_INTERCEPT_FSTAT64;
-  TSAN_MAYBE_INTERCEPT___FXSTAT64;
-  TSAN_INTERCEPT(open);
-  TSAN_MAYBE_INTERCEPT_OPEN64;
-  TSAN_INTERCEPT(creat);
-  TSAN_MAYBE_INTERCEPT_CREAT64;
-  TSAN_INTERCEPT(dup);
-  TSAN_INTERCEPT(dup2);
-  TSAN_INTERCEPT(dup3);
-  TSAN_MAYBE_INTERCEPT_EVENTFD;
-  TSAN_MAYBE_INTERCEPT_SIGNALFD;
-  TSAN_MAYBE_INTERCEPT_INOTIFY_INIT;
-  TSAN_MAYBE_INTERCEPT_INOTIFY_INIT1;
-  TSAN_INTERCEPT(socket);
-  TSAN_INTERCEPT(socketpair);
-  TSAN_INTERCEPT(connect);
-  TSAN_INTERCEPT(bind);
-  TSAN_INTERCEPT(listen);
-  TSAN_MAYBE_INTERCEPT_EPOLL;
-  TSAN_INTERCEPT(close);
-  TSAN_MAYBE_INTERCEPT___CLOSE;
-  TSAN_MAYBE_INTERCEPT___RES_ICLOSE;
-  TSAN_INTERCEPT(pipe);
-  TSAN_INTERCEPT(pipe2);
-
-  TSAN_INTERCEPT(unlink);
-  TSAN_INTERCEPT(tmpfile);
-  TSAN_MAYBE_INTERCEPT_TMPFILE64;
-  TSAN_INTERCEPT(abort);
-  TSAN_INTERCEPT(rmdir);
-  TSAN_INTERCEPT(closedir);
-
-  TSAN_INTERCEPT(sigsuspend);
-  TSAN_INTERCEPT(sigblock);
-  TSAN_INTERCEPT(sigsetmask);
-  TSAN_INTERCEPT(pthread_sigmask);
-  TSAN_INTERCEPT(raise);
-  TSAN_INTERCEPT(kill);
-  TSAN_INTERCEPT(pthread_kill);
-  TSAN_INTERCEPT(sleep);
-  TSAN_INTERCEPT(usleep);
-  TSAN_INTERCEPT(nanosleep);
-  TSAN_INTERCEPT(pause);
-  TSAN_INTERCEPT(gettimeofday);
-  TSAN_INTERCEPT(getaddrinfo);
-
-  TSAN_INTERCEPT(fork);
-  TSAN_INTERCEPT(vfork);
-#if !SANITIZER_ANDROID
-  TSAN_INTERCEPT(dl_iterate_phdr);
-#endif
-  TSAN_MAYBE_INTERCEPT_ON_EXIT;
-  TSAN_INTERCEPT(__cxa_atexit);
-  TSAN_INTERCEPT(_exit);
-
-#ifdef NEED_TLS_GET_ADDR
-  TSAN_INTERCEPT(__tls_get_addr);
-#endif
-
-  TSAN_MAYBE_INTERCEPT__LWP_EXIT;
-  TSAN_MAYBE_INTERCEPT_THR_EXIT;
-
-#if !SANITIZER_MAC && !SANITIZER_ANDROID
-  // Need to setup it, because interceptors check that the function is resolved.
-  // But atexit is emitted directly into the module, so can't be resolved.
-  REAL(atexit) = (int(*)(void(*)()))unreachable;
-#endif
-
-  if (REAL(__cxa_atexit)(&finalize, 0, 0)) {
-    Printf("ThreadSanitizer: failed to setup atexit callback\n");
-    Die();
-  }
-
-#if !SANITIZER_MAC && !SANITIZER_NETBSD && !SANITIZER_FREEBSD
-  if (pthread_key_create(&interceptor_ctx()->finalize_key, &thread_finalize)) {
-    Printf("ThreadSanitizer: failed to create thread key\n");
-    Die();
-  }
-#endif
-
-  TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(cond_init);
-  TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(cond_signal);
-  TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(cond_broadcast);
-  TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(cond_wait);
-  TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(cond_destroy);
-  TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(mutex_init);
-  TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(mutex_destroy);
-  TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(mutex_trylock);
-  TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_init);
-  TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_destroy);
-  TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_rdlock);
-  TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_tryrdlock);
-  TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_wrlock);
-  TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_trywrlock);
-  TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_unlock);
-  TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS_THR(once);
-  TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS_THR(sigsetmask);
-
-  FdInit();
-}
-
-}  // namespace __tsan
-
-// Invisible barrier for tests.
-// There were several unsuccessful iterations for this functionality:
-// 1. Initially it was implemented in user code using
-//    REAL(pthread_barrier_wait). But pthread_barrier_wait is not supported on
-//    MacOS. Futexes are linux-specific for this matter.
-// 2. Then we switched to atomics+usleep(10). But usleep produced parasitic
-//    "as-if synchronized via sleep" messages in reports which failed some
-//    output tests.
-// 3. Then we switched to atomics+sched_yield. But this produced tons of tsan-
-//    visible events, which lead to "failed to restore stack trace" failures.
-// Note that no_sanitize_thread attribute does not turn off atomic interception
-// so attaching it to the function defined in user code does not help.
-// That's why we now have what we have.
-extern "C" SANITIZER_INTERFACE_ATTRIBUTE
-void __tsan_testonly_barrier_init(u64 *barrier, u32 count) {
-  if (count >= (1 << 8)) {
-      Printf("barrier_init: count is too large (%d)\n", count);
-      Die();
-  }
-  // 8 lsb is thread count, the remaining are count of entered threads.
-  *barrier = count;
-}
-
-extern "C" SANITIZER_INTERFACE_ATTRIBUTE
-void __tsan_testonly_barrier_wait(u64 *barrier) {
-  unsigned old = __atomic_fetch_add(barrier, 1 << 8, __ATOMIC_RELAXED);
-  unsigned old_epoch = (old >> 8) / (old & 0xff);
-  for (;;) {
-    unsigned cur = __atomic_load_n(barrier, __ATOMIC_RELAXED);
-    unsigned cur_epoch = (cur >> 8) / (cur & 0xff);
-    if (cur_epoch != old_epoch)
-      return;
-    internal_sched_yield();
-  }
-}
diff --git a/libsanitizer/tsan/tsan_interceptors_libdispatch.cpp b/libsanitizer/tsan/tsan_interceptors_libdispatch.cpp
new file mode 100644 (file)
index 0000000..5dacd32
--- /dev/null
@@ -0,0 +1,782 @@
+//===-- tsan_interceptors_libdispatch.cpp ---------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+// Support for intercepting libdispatch (GCD).
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_common.h"
+#include "interception/interception.h"
+#include "tsan_interceptors.h"
+#include "tsan_rtl.h"
+
+#include "BlocksRuntime/Block.h"
+#include "tsan_dispatch_defs.h"
+
+namespace __tsan {
+  typedef u16 uint16_t;
+
+typedef struct {
+  dispatch_queue_t queue;
+  void *orig_context;
+  dispatch_function_t orig_work;
+  bool free_context_in_callback;
+  bool submitted_synchronously;
+  bool is_barrier_block;
+  uptr non_queue_sync_object;
+} block_context_t;
+
+// The offsets of different fields of the dispatch_queue_t structure, exported
+// by libdispatch.dylib.
+extern "C" struct dispatch_queue_offsets_s {
+  const uint16_t dqo_version;
+  const uint16_t dqo_label;
+  const uint16_t dqo_label_size;
+  const uint16_t dqo_flags;
+  const uint16_t dqo_flags_size;
+  const uint16_t dqo_serialnum;
+  const uint16_t dqo_serialnum_size;
+  const uint16_t dqo_width;
+  const uint16_t dqo_width_size;
+  const uint16_t dqo_running;
+  const uint16_t dqo_running_size;
+  const uint16_t dqo_suspend_cnt;
+  const uint16_t dqo_suspend_cnt_size;
+  const uint16_t dqo_target_queue;
+  const uint16_t dqo_target_queue_size;
+  const uint16_t dqo_priority;
+  const uint16_t dqo_priority_size;
+} dispatch_queue_offsets;
+
+static bool IsQueueSerial(dispatch_queue_t q) {
+  CHECK_EQ(dispatch_queue_offsets.dqo_width_size, 2);
+  uptr width = *(uint16_t *)(((uptr)q) + dispatch_queue_offsets.dqo_width);
+  CHECK_NE(width, 0);
+  return width == 1;
+}
+
+static dispatch_queue_t GetTargetQueueFromQueue(dispatch_queue_t q) {
+  CHECK_EQ(dispatch_queue_offsets.dqo_target_queue_size, 8);
+  dispatch_queue_t tq = *(
+      dispatch_queue_t *)(((uptr)q) + dispatch_queue_offsets.dqo_target_queue);
+  return tq;
+}
+
+static dispatch_queue_t GetTargetQueueFromSource(dispatch_source_t source) {
+  dispatch_queue_t tq = GetTargetQueueFromQueue((dispatch_queue_t)source);
+  CHECK_NE(tq, 0);
+  return tq;
+}
+
+static block_context_t *AllocContext(ThreadState *thr, uptr pc,
+                                     dispatch_queue_t queue, void *orig_context,
+                                     dispatch_function_t orig_work) {
+  block_context_t *new_context =
+      (block_context_t *)user_alloc_internal(thr, pc, sizeof(block_context_t));
+  new_context->queue = queue;
+  new_context->orig_context = orig_context;
+  new_context->orig_work = orig_work;
+  new_context->free_context_in_callback = true;
+  new_context->submitted_synchronously = false;
+  new_context->is_barrier_block = false;
+  new_context->non_queue_sync_object = 0;
+  return new_context;
+}
+
+#define GET_QUEUE_SYNC_VARS(context, q)                                  \
+  bool is_queue_serial = q && IsQueueSerial(q);                          \
+  uptr sync_ptr = (uptr)q ?: context->non_queue_sync_object;             \
+  uptr serial_sync = (uptr)sync_ptr;                                     \
+  uptr concurrent_sync = sync_ptr ? ((uptr)sync_ptr) + sizeof(uptr) : 0; \
+  bool serial_task = context->is_barrier_block || is_queue_serial
+
+static void dispatch_sync_pre_execute(ThreadState *thr, uptr pc,
+                                      block_context_t *context) {
+  uptr submit_sync = (uptr)context;
+  Acquire(thr, pc, submit_sync);
+
+  dispatch_queue_t q = context->queue;
+  do {
+    GET_QUEUE_SYNC_VARS(context, q);
+    if (serial_sync) Acquire(thr, pc, serial_sync);
+    if (serial_task && concurrent_sync) Acquire(thr, pc, concurrent_sync);
+
+    if (q) q = GetTargetQueueFromQueue(q);
+  } while (q);
+}
+
+static void dispatch_sync_post_execute(ThreadState *thr, uptr pc,
+                                       block_context_t *context) {
+  uptr submit_sync = (uptr)context;
+  if (context->submitted_synchronously) Release(thr, pc, submit_sync);
+
+  dispatch_queue_t q = context->queue;
+  do {
+    GET_QUEUE_SYNC_VARS(context, q);
+    if (serial_task && serial_sync) Release(thr, pc, serial_sync);
+    if (!serial_task && concurrent_sync) Release(thr, pc, concurrent_sync);
+
+    if (q) q = GetTargetQueueFromQueue(q);
+  } while (q);
+}
+
+static void dispatch_callback_wrap(void *param) {
+  SCOPED_INTERCEPTOR_RAW(dispatch_callback_wrap);
+  block_context_t *context = (block_context_t *)param;
+
+  dispatch_sync_pre_execute(thr, pc, context);
+
+  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
+  context->orig_work(context->orig_context);
+  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
+
+  dispatch_sync_post_execute(thr, pc, context);
+
+  if (context->free_context_in_callback) user_free(thr, pc, context);
+}
+
+static void invoke_block(void *param) {
+  dispatch_block_t block = (dispatch_block_t)param;
+  block();
+}
+
+static void invoke_and_release_block(void *param) {
+  dispatch_block_t block = (dispatch_block_t)param;
+  block();
+  Block_release(block);
+}
+
+#define DISPATCH_INTERCEPT_ASYNC_B(name, barrier)                            \
+  TSAN_INTERCEPTOR(void, name, dispatch_queue_t q, dispatch_block_t block) { \
+    SCOPED_TSAN_INTERCEPTOR(name, q, block);                                 \
+    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();                           \
+    dispatch_block_t heap_block = Block_copy(block);                         \
+    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();                             \
+    block_context_t *new_context =                                           \
+        AllocContext(thr, pc, q, heap_block, &invoke_and_release_block);     \
+    new_context->is_barrier_block = barrier;                                 \
+    Release(thr, pc, (uptr)new_context);                                     \
+    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();                           \
+    REAL(name##_f)(q, new_context, dispatch_callback_wrap);                  \
+    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();                             \
+  }
+
+#define DISPATCH_INTERCEPT_SYNC_B(name, barrier)                             \
+  TSAN_INTERCEPTOR(void, name, dispatch_queue_t q,                           \
+                   DISPATCH_NOESCAPE dispatch_block_t block) {               \
+    SCOPED_TSAN_INTERCEPTOR(name, q, block);                                 \
+    block_context_t new_context = {                                          \
+        q, block, &invoke_block, false, true, barrier, 0};                   \
+    Release(thr, pc, (uptr)&new_context);                                    \
+    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();                           \
+    REAL(name##_f)(q, &new_context, dispatch_callback_wrap);                 \
+    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();                             \
+    Acquire(thr, pc, (uptr)&new_context);                                    \
+  }
+
+#define DISPATCH_INTERCEPT_ASYNC_F(name, barrier)                 \
+  TSAN_INTERCEPTOR(void, name, dispatch_queue_t q, void *context, \
+                   dispatch_function_t work) {                    \
+    SCOPED_TSAN_INTERCEPTOR(name, q, context, work);              \
+    block_context_t *new_context =                                \
+        AllocContext(thr, pc, q, context, work);                  \
+    new_context->is_barrier_block = barrier;                      \
+    Release(thr, pc, (uptr)new_context);                          \
+    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();                \
+    REAL(name)(q, new_context, dispatch_callback_wrap);           \
+    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();                  \
+  }
+
+#define DISPATCH_INTERCEPT_SYNC_F(name, barrier)                              \
+  TSAN_INTERCEPTOR(void, name, dispatch_queue_t q, void *context,             \
+                   dispatch_function_t work) {                                \
+    SCOPED_TSAN_INTERCEPTOR(name, q, context, work);                          \
+    block_context_t new_context = {                                           \
+        q, context, work, false, true, barrier, 0};                           \
+    Release(thr, pc, (uptr)&new_context);                                     \
+    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();                            \
+    REAL(name)(q, &new_context, dispatch_callback_wrap);                      \
+    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();                              \
+    Acquire(thr, pc, (uptr)&new_context);                                     \
+  }
+
+#define DISPATCH_INTERCEPT(name, barrier)             \
+  DISPATCH_INTERCEPT_ASYNC_F(name##_async_f, barrier) \
+  DISPATCH_INTERCEPT_ASYNC_B(name##_async, barrier)   \
+  DISPATCH_INTERCEPT_SYNC_F(name##_sync_f, barrier)   \
+  DISPATCH_INTERCEPT_SYNC_B(name##_sync, barrier)
+
+// We wrap dispatch_async, dispatch_sync and friends where we allocate a new
+// context, which is used to synchronize (we release the context before
+// submitting, and the callback acquires it before executing the original
+// callback).
+DISPATCH_INTERCEPT(dispatch, false)
+DISPATCH_INTERCEPT(dispatch_barrier, true)
+
+DECLARE_REAL(void, dispatch_after_f, dispatch_time_t when,
+             dispatch_queue_t queue, void *context, dispatch_function_t work)
+
+TSAN_INTERCEPTOR(void, dispatch_after, dispatch_time_t when,
+                 dispatch_queue_t queue, dispatch_block_t block) {
+  SCOPED_TSAN_INTERCEPTOR(dispatch_after, when, queue, block);
+  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
+  dispatch_block_t heap_block = Block_copy(block);
+  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
+  block_context_t *new_context =
+      AllocContext(thr, pc, queue, heap_block, &invoke_and_release_block);
+  Release(thr, pc, (uptr)new_context);
+  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
+  REAL(dispatch_after_f)(when, queue, new_context, dispatch_callback_wrap);
+  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
+}
+
+TSAN_INTERCEPTOR(void, dispatch_after_f, dispatch_time_t when,
+                 dispatch_queue_t queue, void *context,
+                 dispatch_function_t work) {
+  SCOPED_TSAN_INTERCEPTOR(dispatch_after_f, when, queue, context, work);
+  WRAP(dispatch_after)(when, queue, ^(void) {
+    work(context);
+  });
+}
+
+// GCD's dispatch_once implementation has a fast path that contains a racy read
+// and it's inlined into user's code. Furthermore, this fast path doesn't
+// establish a proper happens-before relations between the initialization and
+// code following the call to dispatch_once. We could deal with this in
+// instrumented code, but there's not much we can do about it in system
+// libraries. Let's disable the fast path (by never storing the value ~0 to
+// predicate), so the interceptor is always called, and let's add proper release
+// and acquire semantics. Since TSan does not see its own atomic stores, the
+// race on predicate won't be reported - the only accesses to it that TSan sees
+// are the loads on the fast path. Loads don't race. Secondly, dispatch_once is
+// both a macro and a real function, we want to intercept the function, so we
+// need to undefine the macro.
+#undef dispatch_once
+TSAN_INTERCEPTOR(void, dispatch_once, dispatch_once_t *predicate,
+                 DISPATCH_NOESCAPE dispatch_block_t block) {
+  SCOPED_INTERCEPTOR_RAW(dispatch_once, predicate, block);
+  atomic_uint32_t *a = reinterpret_cast<atomic_uint32_t *>(predicate);
+  u32 v = atomic_load(a, memory_order_acquire);
+  if (v == 0 &&
+      atomic_compare_exchange_strong(a, &v, 1, memory_order_relaxed)) {
+    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
+    block();
+    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
+    Release(thr, pc, (uptr)a);
+    atomic_store(a, 2, memory_order_release);
+  } else {
+    while (v != 2) {
+      internal_sched_yield();
+      v = atomic_load(a, memory_order_acquire);
+    }
+    Acquire(thr, pc, (uptr)a);
+  }
+}
+
+#undef dispatch_once_f
+TSAN_INTERCEPTOR(void, dispatch_once_f, dispatch_once_t *predicate,
+                 void *context, dispatch_function_t function) {
+  SCOPED_INTERCEPTOR_RAW(dispatch_once_f, predicate, context, function);
+  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
+  WRAP(dispatch_once)(predicate, ^(void) {
+    function(context);
+  });
+  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
+}
+
+TSAN_INTERCEPTOR(long_t, dispatch_semaphore_signal,
+                 dispatch_semaphore_t dsema) {
+  SCOPED_TSAN_INTERCEPTOR(dispatch_semaphore_signal, dsema);
+  Release(thr, pc, (uptr)dsema);
+  return REAL(dispatch_semaphore_signal)(dsema);
+}
+
+TSAN_INTERCEPTOR(long_t, dispatch_semaphore_wait, dispatch_semaphore_t dsema,
+                 dispatch_time_t timeout) {
+  SCOPED_TSAN_INTERCEPTOR(dispatch_semaphore_wait, dsema, timeout);
+  long_t result = REAL(dispatch_semaphore_wait)(dsema, timeout);
+  if (result == 0) Acquire(thr, pc, (uptr)dsema);
+  return result;
+}
+
+TSAN_INTERCEPTOR(long_t, dispatch_group_wait, dispatch_group_t group,
+                 dispatch_time_t timeout) {
+  SCOPED_TSAN_INTERCEPTOR(dispatch_group_wait, group, timeout);
+  long_t result = REAL(dispatch_group_wait)(group, timeout);
+  if (result == 0) Acquire(thr, pc, (uptr)group);
+  return result;
+}
+
+// Used, but not intercepted.
+extern "C" void dispatch_group_enter(dispatch_group_t group);
+
+TSAN_INTERCEPTOR(void, dispatch_group_leave, dispatch_group_t group) {
+  SCOPED_TSAN_INTERCEPTOR(dispatch_group_leave, group);
+  // Acquired in the group notification callback in dispatch_group_notify[_f].
+  Release(thr, pc, (uptr)group);
+  REAL(dispatch_group_leave)(group);
+}
+
+TSAN_INTERCEPTOR(void, dispatch_group_async, dispatch_group_t group,
+                 dispatch_queue_t queue, dispatch_block_t block) {
+  SCOPED_TSAN_INTERCEPTOR(dispatch_group_async, group, queue, block);
+  dispatch_retain(group);
+  dispatch_group_enter(group);
+  __block dispatch_block_t block_copy = (dispatch_block_t)Block_copy(block);
+  WRAP(dispatch_async)(queue, ^(void) {
+    block_copy();
+    Block_release(block_copy);
+    WRAP(dispatch_group_leave)(group);
+    dispatch_release(group);
+  });
+}
+
+TSAN_INTERCEPTOR(void, dispatch_group_async_f, dispatch_group_t group,
+                 dispatch_queue_t queue, void *context,
+                 dispatch_function_t work) {
+  SCOPED_TSAN_INTERCEPTOR(dispatch_group_async_f, group, queue, context, work);
+  dispatch_retain(group);
+  dispatch_group_enter(group);
+  WRAP(dispatch_async)(queue, ^(void) {
+    work(context);
+    WRAP(dispatch_group_leave)(group);
+    dispatch_release(group);
+  });
+}
+
+DECLARE_REAL(void, dispatch_group_notify_f, dispatch_group_t group,
+             dispatch_queue_t q, void *context, dispatch_function_t work)
+
+TSAN_INTERCEPTOR(void, dispatch_group_notify, dispatch_group_t group,
+                 dispatch_queue_t q, dispatch_block_t block) {
+  SCOPED_TSAN_INTERCEPTOR(dispatch_group_notify, group, q, block);
+
+  // To make sure the group is still available in the callback (otherwise
+  // it can be already destroyed).  Will be released in the callback.
+  dispatch_retain(group);
+
+  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
+  dispatch_block_t heap_block = Block_copy(^(void) {
+    {
+      SCOPED_INTERCEPTOR_RAW(dispatch_read_callback);
+      // Released when leaving the group (dispatch_group_leave).
+      Acquire(thr, pc, (uptr)group);
+    }
+    dispatch_release(group);
+    block();
+  });
+  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
+  block_context_t *new_context =
+      AllocContext(thr, pc, q, heap_block, &invoke_and_release_block);
+  new_context->is_barrier_block = true;
+  Release(thr, pc, (uptr)new_context);
+  REAL(dispatch_group_notify_f)(group, q, new_context, dispatch_callback_wrap);
+}
+
+TSAN_INTERCEPTOR(void, dispatch_group_notify_f, dispatch_group_t group,
+                 dispatch_queue_t q, void *context, dispatch_function_t work) {
+  WRAP(dispatch_group_notify)(group, q, ^(void) { work(context); });
+}
+
+TSAN_INTERCEPTOR(void, dispatch_source_set_event_handler,
+                 dispatch_source_t source, dispatch_block_t handler) {
+  SCOPED_TSAN_INTERCEPTOR(dispatch_source_set_event_handler, source, handler);
+  if (handler == nullptr)
+    return REAL(dispatch_source_set_event_handler)(source, nullptr);
+  dispatch_queue_t q = GetTargetQueueFromSource(source);
+  __block block_context_t new_context = {
+      q, handler, &invoke_block, false, false, false, 0 };
+  dispatch_block_t new_handler = Block_copy(^(void) {
+    new_context.orig_context = handler;  // To explicitly capture "handler".
+    dispatch_callback_wrap(&new_context);
+  });
+  uptr submit_sync = (uptr)&new_context;
+  Release(thr, pc, submit_sync);
+  REAL(dispatch_source_set_event_handler)(source, new_handler);
+  Block_release(new_handler);
+}
+
+TSAN_INTERCEPTOR(void, dispatch_source_set_event_handler_f,
+                 dispatch_source_t source, dispatch_function_t handler) {
+  SCOPED_TSAN_INTERCEPTOR(dispatch_source_set_event_handler_f, source, handler);
+  if (handler == nullptr)
+    return REAL(dispatch_source_set_event_handler)(source, nullptr);
+  dispatch_block_t block = ^(void) {
+    handler(dispatch_get_context(source));
+  };
+  WRAP(dispatch_source_set_event_handler)(source, block);
+}
+
+TSAN_INTERCEPTOR(void, dispatch_source_set_cancel_handler,
+                 dispatch_source_t source, dispatch_block_t handler) {
+  SCOPED_TSAN_INTERCEPTOR(dispatch_source_set_cancel_handler, source, handler);
+  if (handler == nullptr)
+    return REAL(dispatch_source_set_cancel_handler)(source, nullptr);
+  dispatch_queue_t q = GetTargetQueueFromSource(source);
+  __block block_context_t new_context = {
+      q, handler, &invoke_block, false, false, false, 0};
+  dispatch_block_t new_handler = Block_copy(^(void) {
+    new_context.orig_context = handler;  // To explicitly capture "handler".
+    dispatch_callback_wrap(&new_context);
+  });
+  uptr submit_sync = (uptr)&new_context;
+  Release(thr, pc, submit_sync);
+  REAL(dispatch_source_set_cancel_handler)(source, new_handler);
+  Block_release(new_handler);
+}
+
+TSAN_INTERCEPTOR(void, dispatch_source_set_cancel_handler_f,
+                 dispatch_source_t source, dispatch_function_t handler) {
+  SCOPED_TSAN_INTERCEPTOR(dispatch_source_set_cancel_handler_f, source,
+                          handler);
+  if (handler == nullptr)
+    return REAL(dispatch_source_set_cancel_handler)(source, nullptr);
+  dispatch_block_t block = ^(void) {
+    handler(dispatch_get_context(source));
+  };
+  WRAP(dispatch_source_set_cancel_handler)(source, block);
+}
+
+TSAN_INTERCEPTOR(void, dispatch_source_set_registration_handler,
+                 dispatch_source_t source, dispatch_block_t handler) {
+  SCOPED_TSAN_INTERCEPTOR(dispatch_source_set_registration_handler, source,
+                          handler);
+  if (handler == nullptr)
+    return REAL(dispatch_source_set_registration_handler)(source, nullptr);
+  dispatch_queue_t q = GetTargetQueueFromSource(source);
+  __block block_context_t new_context = {
+      q, handler, &invoke_block, false, false, false, 0};
+  dispatch_block_t new_handler = Block_copy(^(void) {
+    new_context.orig_context = handler;  // To explicitly capture "handler".
+    dispatch_callback_wrap(&new_context);
+  });
+  uptr submit_sync = (uptr)&new_context;
+  Release(thr, pc, submit_sync);
+  REAL(dispatch_source_set_registration_handler)(source, new_handler);
+  Block_release(new_handler);
+}
+
+TSAN_INTERCEPTOR(void, dispatch_source_set_registration_handler_f,
+                 dispatch_source_t source, dispatch_function_t handler) {
+  SCOPED_TSAN_INTERCEPTOR(dispatch_source_set_registration_handler_f, source,
+                          handler);
+  if (handler == nullptr)
+    return REAL(dispatch_source_set_registration_handler)(source, nullptr);
+  dispatch_block_t block = ^(void) {
+    handler(dispatch_get_context(source));
+  };
+  WRAP(dispatch_source_set_registration_handler)(source, block);
+}
+
+TSAN_INTERCEPTOR(void, dispatch_apply, size_t iterations,
+                 dispatch_queue_t queue,
+                 DISPATCH_NOESCAPE void (^block)(size_t)) {
+  SCOPED_TSAN_INTERCEPTOR(dispatch_apply, iterations, queue, block);
+
+  u8 sync1, sync2;
+  uptr parent_to_child_sync = (uptr)&sync1;
+  uptr child_to_parent_sync = (uptr)&sync2;
+
+  Release(thr, pc, parent_to_child_sync);
+  void (^new_block)(size_t) = ^(size_t iteration) {
+    SCOPED_INTERCEPTOR_RAW(dispatch_apply);
+    Acquire(thr, pc, parent_to_child_sync);
+    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
+    block(iteration);
+    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
+    Release(thr, pc, child_to_parent_sync);
+  };
+  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
+  REAL(dispatch_apply)(iterations, queue, new_block);
+  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
+  Acquire(thr, pc, child_to_parent_sync);
+}
+
+static void invoke_block_iteration(void *param, size_t iteration) {
+  auto block = (void (^)(size_t)) param;
+  block(iteration);
+}
+
+TSAN_INTERCEPTOR(void, dispatch_apply_f, size_t iterations,
+                 dispatch_queue_t queue, void *context,
+                 void (*work)(void *, size_t)) {
+  SCOPED_TSAN_INTERCEPTOR(dispatch_apply_f, iterations, queue, context, work);
+
+  // Unfortunately, we cannot delegate to dispatch_apply, since libdispatch
+  // implements dispatch_apply in terms of dispatch_apply_f.
+  u8 sync1, sync2;
+  uptr parent_to_child_sync = (uptr)&sync1;
+  uptr child_to_parent_sync = (uptr)&sync2;
+
+  Release(thr, pc, parent_to_child_sync);
+  void (^new_block)(size_t) = ^(size_t iteration) {
+    SCOPED_INTERCEPTOR_RAW(dispatch_apply_f);
+    Acquire(thr, pc, parent_to_child_sync);
+    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
+    work(context, iteration);
+    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
+    Release(thr, pc, child_to_parent_sync);
+  };
+  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
+  REAL(dispatch_apply_f)(iterations, queue, new_block, invoke_block_iteration);
+  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
+  Acquire(thr, pc, child_to_parent_sync);
+}
+
+DECLARE_REAL_AND_INTERCEPTOR(void, free, void *ptr)
+DECLARE_REAL_AND_INTERCEPTOR(int, munmap, void *addr, long_t sz)
+
+TSAN_INTERCEPTOR(dispatch_data_t, dispatch_data_create, const void *buffer,
+                 size_t size, dispatch_queue_t q, dispatch_block_t destructor) {
+  SCOPED_TSAN_INTERCEPTOR(dispatch_data_create, buffer, size, q, destructor);
+  if ((q == nullptr) || (destructor == DISPATCH_DATA_DESTRUCTOR_DEFAULT))
+    return REAL(dispatch_data_create)(buffer, size, q, destructor);
+
+  if (destructor == DISPATCH_DATA_DESTRUCTOR_FREE)
+    destructor = ^(void) { WRAP(free)((void *)(uintptr_t)buffer); };
+  else if (destructor == DISPATCH_DATA_DESTRUCTOR_MUNMAP)
+    destructor = ^(void) { WRAP(munmap)((void *)(uintptr_t)buffer, size); };
+
+  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
+  dispatch_block_t heap_block = Block_copy(destructor);
+  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
+  block_context_t *new_context =
+      AllocContext(thr, pc, q, heap_block, &invoke_and_release_block);
+  uptr submit_sync = (uptr)new_context;
+  Release(thr, pc, submit_sync);
+  return REAL(dispatch_data_create)(buffer, size, q, ^(void) {
+    dispatch_callback_wrap(new_context);
+  });
+}
+
+typedef void (^fd_handler_t)(dispatch_data_t data, int error);
+typedef void (^cleanup_handler_t)(int error);
+
+TSAN_INTERCEPTOR(void, dispatch_read, dispatch_fd_t fd, size_t length,
+                 dispatch_queue_t q, fd_handler_t h) {
+  SCOPED_TSAN_INTERCEPTOR(dispatch_read, fd, length, q, h);
+  __block block_context_t new_context = {
+      q, nullptr, &invoke_block, false, false, false, 0};
+  fd_handler_t new_h = Block_copy(^(dispatch_data_t data, int error) {
+    new_context.orig_context = ^(void) {
+      h(data, error);
+    };
+    dispatch_callback_wrap(&new_context);
+  });
+  uptr submit_sync = (uptr)&new_context;
+  Release(thr, pc, submit_sync);
+  REAL(dispatch_read)(fd, length, q, new_h);
+  Block_release(new_h);
+}
+
+TSAN_INTERCEPTOR(void, dispatch_write, dispatch_fd_t fd, dispatch_data_t data,
+                 dispatch_queue_t q, fd_handler_t h) {
+  SCOPED_TSAN_INTERCEPTOR(dispatch_write, fd, data, q, h);
+  __block block_context_t new_context = {
+      q, nullptr, &invoke_block, false, false, false, 0};
+  fd_handler_t new_h = Block_copy(^(dispatch_data_t data, int error) {
+    new_context.orig_context = ^(void) {
+      h(data, error);
+    };
+    dispatch_callback_wrap(&new_context);
+  });
+  uptr submit_sync = (uptr)&new_context;
+  Release(thr, pc, submit_sync);
+  REAL(dispatch_write)(fd, data, q, new_h);
+  Block_release(new_h);
+}
+
+TSAN_INTERCEPTOR(void, dispatch_io_read, dispatch_io_t channel, off_t offset,
+                 size_t length, dispatch_queue_t q, dispatch_io_handler_t h) {
+  SCOPED_TSAN_INTERCEPTOR(dispatch_io_read, channel, offset, length, q, h);
+  __block block_context_t new_context = {
+      q, nullptr, &invoke_block, false, false, false, 0};
+  dispatch_io_handler_t new_h =
+      Block_copy(^(bool done, dispatch_data_t data, int error) {
+        new_context.orig_context = ^(void) {
+          h(done, data, error);
+        };
+        dispatch_callback_wrap(&new_context);
+      });
+  uptr submit_sync = (uptr)&new_context;
+  Release(thr, pc, submit_sync);
+  REAL(dispatch_io_read)(channel, offset, length, q, new_h);
+  Block_release(new_h);
+}
+
+TSAN_INTERCEPTOR(void, dispatch_io_write, dispatch_io_t channel, off_t offset,
+                 dispatch_data_t data, dispatch_queue_t q,
+                 dispatch_io_handler_t h) {
+  SCOPED_TSAN_INTERCEPTOR(dispatch_io_write, channel, offset, data, q, h);
+  __block block_context_t new_context = {
+      q, nullptr, &invoke_block, false, false, false, 0};
+  dispatch_io_handler_t new_h =
+      Block_copy(^(bool done, dispatch_data_t data, int error) {
+        new_context.orig_context = ^(void) {
+          h(done, data, error);
+        };
+        dispatch_callback_wrap(&new_context);
+      });
+  uptr submit_sync = (uptr)&new_context;
+  Release(thr, pc, submit_sync);
+  REAL(dispatch_io_write)(channel, offset, data, q, new_h);
+  Block_release(new_h);
+}
+
+TSAN_INTERCEPTOR(void, dispatch_io_barrier, dispatch_io_t channel,
+                 dispatch_block_t barrier) {
+  SCOPED_TSAN_INTERCEPTOR(dispatch_io_barrier, channel, barrier);
+  __block block_context_t new_context = {
+      nullptr, nullptr, &invoke_block, false, false, false, 0};
+  new_context.non_queue_sync_object = (uptr)channel;
+  new_context.is_barrier_block = true;
+  dispatch_block_t new_block = Block_copy(^(void) {
+    new_context.orig_context = ^(void) {
+      barrier();
+    };
+    dispatch_callback_wrap(&new_context);
+  });
+  uptr submit_sync = (uptr)&new_context;
+  Release(thr, pc, submit_sync);
+  REAL(dispatch_io_barrier)(channel, new_block);
+  Block_release(new_block);
+}
+
+TSAN_INTERCEPTOR(dispatch_io_t, dispatch_io_create, dispatch_io_type_t type,
+                 dispatch_fd_t fd, dispatch_queue_t q, cleanup_handler_t h) {
+  SCOPED_TSAN_INTERCEPTOR(dispatch_io_create, type, fd, q, h);
+  __block dispatch_io_t new_channel = nullptr;
+  __block block_context_t new_context = {
+      q, nullptr, &invoke_block, false, false, false, 0};
+  cleanup_handler_t new_h = Block_copy(^(int error) {
+    {
+      SCOPED_INTERCEPTOR_RAW(dispatch_io_create_callback);
+      Acquire(thr, pc, (uptr)new_channel);  // Release() in dispatch_io_close.
+    }
+    new_context.orig_context = ^(void) {
+      h(error);
+    };
+    dispatch_callback_wrap(&new_context);
+  });
+  uptr submit_sync = (uptr)&new_context;
+  Release(thr, pc, submit_sync);
+  new_channel = REAL(dispatch_io_create)(type, fd, q, new_h);
+  Block_release(new_h);
+  return new_channel;
+}
+
+TSAN_INTERCEPTOR(dispatch_io_t, dispatch_io_create_with_path,
+                 dispatch_io_type_t type, const char *path, int oflag,
+                 mode_t mode, dispatch_queue_t q, cleanup_handler_t h) {
+  SCOPED_TSAN_INTERCEPTOR(dispatch_io_create_with_path, type, path, oflag, mode,
+                          q, h);
+  __block dispatch_io_t new_channel = nullptr;
+  __block block_context_t new_context = {
+      q, nullptr, &invoke_block, false, false, false, 0};
+  cleanup_handler_t new_h = Block_copy(^(int error) {
+    {
+      SCOPED_INTERCEPTOR_RAW(dispatch_io_create_callback);
+      Acquire(thr, pc, (uptr)new_channel);  // Release() in dispatch_io_close.
+    }
+    new_context.orig_context = ^(void) {
+      h(error);
+    };
+    dispatch_callback_wrap(&new_context);
+  });
+  uptr submit_sync = (uptr)&new_context;
+  Release(thr, pc, submit_sync);
+  new_channel =
+      REAL(dispatch_io_create_with_path)(type, path, oflag, mode, q, new_h);
+  Block_release(new_h);
+  return new_channel;
+}
+
+TSAN_INTERCEPTOR(dispatch_io_t, dispatch_io_create_with_io,
+                 dispatch_io_type_t type, dispatch_io_t io, dispatch_queue_t q,
+                 cleanup_handler_t h) {
+  SCOPED_TSAN_INTERCEPTOR(dispatch_io_create_with_io, type, io, q, h);
+  __block dispatch_io_t new_channel = nullptr;
+  __block block_context_t new_context = {
+      q, nullptr, &invoke_block, false, false, false, 0};
+  cleanup_handler_t new_h = Block_copy(^(int error) {
+    {
+      SCOPED_INTERCEPTOR_RAW(dispatch_io_create_callback);
+      Acquire(thr, pc, (uptr)new_channel);  // Release() in dispatch_io_close.
+    }
+    new_context.orig_context = ^(void) {
+      h(error);
+    };
+    dispatch_callback_wrap(&new_context);
+  });
+  uptr submit_sync = (uptr)&new_context;
+  Release(thr, pc, submit_sync);
+  new_channel = REAL(dispatch_io_create_with_io)(type, io, q, new_h);
+  Block_release(new_h);
+  return new_channel;
+}
+
+TSAN_INTERCEPTOR(void, dispatch_io_close, dispatch_io_t channel,
+                 dispatch_io_close_flags_t flags) {
+  SCOPED_TSAN_INTERCEPTOR(dispatch_io_close, channel, flags);
+  Release(thr, pc, (uptr)channel);  // Acquire() in dispatch_io_create[_*].
+  return REAL(dispatch_io_close)(channel, flags);
+}
+
+// Resuming a suspended queue needs to synchronize with all subsequent
+// executions of blocks in that queue.
+TSAN_INTERCEPTOR(void, dispatch_resume, dispatch_object_t o) {
+  SCOPED_TSAN_INTERCEPTOR(dispatch_resume, o);
+  Release(thr, pc, (uptr)o);  // Synchronizes with the Acquire() on serial_sync
+                              // in dispatch_sync_pre_execute
+  return REAL(dispatch_resume)(o);
+}
+
+void InitializeLibdispatchInterceptors() {
+  INTERCEPT_FUNCTION(dispatch_async);
+  INTERCEPT_FUNCTION(dispatch_async_f);
+  INTERCEPT_FUNCTION(dispatch_sync);
+  INTERCEPT_FUNCTION(dispatch_sync_f);
+  INTERCEPT_FUNCTION(dispatch_barrier_async);
+  INTERCEPT_FUNCTION(dispatch_barrier_async_f);
+  INTERCEPT_FUNCTION(dispatch_barrier_sync);
+  INTERCEPT_FUNCTION(dispatch_barrier_sync_f);
+  INTERCEPT_FUNCTION(dispatch_after);
+  INTERCEPT_FUNCTION(dispatch_after_f);
+  INTERCEPT_FUNCTION(dispatch_once);
+  INTERCEPT_FUNCTION(dispatch_once_f);
+  INTERCEPT_FUNCTION(dispatch_semaphore_signal);
+  INTERCEPT_FUNCTION(dispatch_semaphore_wait);
+  INTERCEPT_FUNCTION(dispatch_group_wait);
+  INTERCEPT_FUNCTION(dispatch_group_leave);
+  INTERCEPT_FUNCTION(dispatch_group_async);
+  INTERCEPT_FUNCTION(dispatch_group_async_f);
+  INTERCEPT_FUNCTION(dispatch_group_notify);
+  INTERCEPT_FUNCTION(dispatch_group_notify_f);
+  INTERCEPT_FUNCTION(dispatch_source_set_event_handler);
+  INTERCEPT_FUNCTION(dispatch_source_set_event_handler_f);
+  INTERCEPT_FUNCTION(dispatch_source_set_cancel_handler);
+  INTERCEPT_FUNCTION(dispatch_source_set_cancel_handler_f);
+  INTERCEPT_FUNCTION(dispatch_source_set_registration_handler);
+  INTERCEPT_FUNCTION(dispatch_source_set_registration_handler_f);
+  INTERCEPT_FUNCTION(dispatch_apply);
+  INTERCEPT_FUNCTION(dispatch_apply_f);
+  INTERCEPT_FUNCTION(dispatch_data_create);
+  INTERCEPT_FUNCTION(dispatch_read);
+  INTERCEPT_FUNCTION(dispatch_write);
+  INTERCEPT_FUNCTION(dispatch_io_read);
+  INTERCEPT_FUNCTION(dispatch_io_write);
+  INTERCEPT_FUNCTION(dispatch_io_barrier);
+  INTERCEPT_FUNCTION(dispatch_io_create);
+  INTERCEPT_FUNCTION(dispatch_io_create_with_path);
+  INTERCEPT_FUNCTION(dispatch_io_create_with_io);
+  INTERCEPT_FUNCTION(dispatch_io_close);
+  INTERCEPT_FUNCTION(dispatch_resume);
+}
+
+}  // namespace __tsan
index c2083f8cde94029124c1923b73e3b975da230352..aa29536d8616ee8d54dcb51ad4662e5eee989a25 100644 (file)
 #include <errno.h>
 #include <libkern/OSAtomic.h>
 #include <objc/objc-sync.h>
+#include <os/lock.h>
 #include <sys/ucontext.h>
 
 #if defined(__has_include) && __has_include(<xpc/xpc.h>)
 #include <xpc/xpc.h>
 #endif  // #if defined(__has_include) && __has_include(<xpc/xpc.h>)
 
-typedef long long_t;  // NOLINT
+typedef long long_t;
 
 extern "C" {
 int getcontext(ucontext_t *ucp) __attribute__((returns_twice));
@@ -246,6 +247,45 @@ TSAN_INTERCEPTOR(void, os_lock_unlock, void *lock) {
   REAL(os_lock_unlock)(lock);
 }
 
+TSAN_INTERCEPTOR(void, os_unfair_lock_lock, os_unfair_lock_t lock) {
+  if (!cur_thread()->is_inited || cur_thread()->is_dead) {
+    return REAL(os_unfair_lock_lock)(lock);
+  }
+  SCOPED_TSAN_INTERCEPTOR(os_unfair_lock_lock, lock);
+  REAL(os_unfair_lock_lock)(lock);
+  Acquire(thr, pc, (uptr)lock);
+}
+
+TSAN_INTERCEPTOR(void, os_unfair_lock_lock_with_options, os_unfair_lock_t lock,
+                 u32 options) {
+  if (!cur_thread()->is_inited || cur_thread()->is_dead) {
+    return REAL(os_unfair_lock_lock_with_options)(lock, options);
+  }
+  SCOPED_TSAN_INTERCEPTOR(os_unfair_lock_lock_with_options, lock, options);
+  REAL(os_unfair_lock_lock_with_options)(lock, options);
+  Acquire(thr, pc, (uptr)lock);
+}
+
+TSAN_INTERCEPTOR(bool, os_unfair_lock_trylock, os_unfair_lock_t lock) {
+  if (!cur_thread()->is_inited || cur_thread()->is_dead) {
+    return REAL(os_unfair_lock_trylock)(lock);
+  }
+  SCOPED_TSAN_INTERCEPTOR(os_unfair_lock_trylock, lock);
+  bool result = REAL(os_unfair_lock_trylock)(lock);
+  if (result)
+    Acquire(thr, pc, (uptr)lock);
+  return result;
+}
+
+TSAN_INTERCEPTOR(void, os_unfair_lock_unlock, os_unfair_lock_t lock) {
+  if (!cur_thread()->is_inited || cur_thread()->is_dead) {
+    return REAL(os_unfair_lock_unlock)(lock);
+  }
+  SCOPED_TSAN_INTERCEPTOR(os_unfair_lock_unlock, lock);
+  Release(thr, pc, (uptr)lock);
+  REAL(os_unfair_lock_unlock)(lock);
+}
+
 #if defined(__has_include) && __has_include(<xpc/xpc.h>)
 
 TSAN_INTERCEPTOR(void, xpc_connection_set_event_handler,
diff --git a/libsanitizer/tsan/tsan_interceptors_mach_vm.cpp b/libsanitizer/tsan/tsan_interceptors_mach_vm.cpp
new file mode 100644 (file)
index 0000000..cd318f8
--- /dev/null
@@ -0,0 +1,52 @@
+//===-- tsan_interceptors_mach_vm.cpp -------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+// Interceptors for mach_vm_* user space memory routines on Darwin.
+//===----------------------------------------------------------------------===//
+
+#include "interception/interception.h"
+#include "tsan_interceptors.h"
+#include "tsan_platform.h"
+
+#include <mach/mach.h>
+
+namespace __tsan {
+
+static bool intersects_with_shadow(mach_vm_address_t *address,
+                                   mach_vm_size_t size, int flags) {
+  // VM_FLAGS_FIXED is 0x0, so we have to test for VM_FLAGS_ANYWHERE.
+  if (flags & VM_FLAGS_ANYWHERE) return false;
+  uptr ptr = *address;
+  return !IsAppMem(ptr) || !IsAppMem(ptr + size - 1);
+}
+
+TSAN_INTERCEPTOR(kern_return_t, mach_vm_allocate, vm_map_t target,
+                 mach_vm_address_t *address, mach_vm_size_t size, int flags) {
+  SCOPED_TSAN_INTERCEPTOR(mach_vm_allocate, target, address, size, flags);
+  if (target != mach_task_self())
+    return REAL(mach_vm_allocate)(target, address, size, flags);
+  if (intersects_with_shadow(address, size, flags))
+    return KERN_NO_SPACE;
+  kern_return_t res = REAL(mach_vm_allocate)(target, address, size, flags);
+  if (res == KERN_SUCCESS)
+    MemoryRangeImitateWriteOrResetRange(thr, pc, *address, size);
+  return res;
+}
+
+TSAN_INTERCEPTOR(kern_return_t, mach_vm_deallocate, vm_map_t target,
+                 mach_vm_address_t address, mach_vm_size_t size) {
+  SCOPED_TSAN_INTERCEPTOR(mach_vm_deallocate, target, address, size);
+  if (target != mach_task_self())
+    return REAL(mach_vm_deallocate)(target, address, size);
+  UnmapShadow(thr, address, size);
+  return REAL(mach_vm_deallocate)(target, address, size);
+}
+
+}  // namespace __tsan
diff --git a/libsanitizer/tsan/tsan_interceptors_posix.cpp b/libsanitizer/tsan/tsan_interceptors_posix.cpp
new file mode 100644 (file)
index 0000000..8aea1e4
--- /dev/null
@@ -0,0 +1,2850 @@
+//===-- tsan_interceptors_posix.cpp ---------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+// FIXME: move as many interceptors as possible into
+// sanitizer_common/sanitizer_common_interceptors.inc
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_atomic.h"
+#include "sanitizer_common/sanitizer_errno.h"
+#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_linux.h"
+#include "sanitizer_common/sanitizer_platform_limits_netbsd.h"
+#include "sanitizer_common/sanitizer_platform_limits_posix.h"
+#include "sanitizer_common/sanitizer_placement_new.h"
+#include "sanitizer_common/sanitizer_posix.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+#include "sanitizer_common/sanitizer_tls_get_addr.h"
+#include "interception/interception.h"
+#include "tsan_interceptors.h"
+#include "tsan_interface.h"
+#include "tsan_platform.h"
+#include "tsan_suppressions.h"
+#include "tsan_rtl.h"
+#include "tsan_mman.h"
+#include "tsan_fd.h"
+
+using namespace __tsan;
+
+#if SANITIZER_FREEBSD || SANITIZER_MAC
+#define stdout __stdoutp
+#define stderr __stderrp
+#endif
+
+#if SANITIZER_NETBSD
+#define dirfd(dirp) (*(int *)(dirp))
+#define fileno_unlocked(fp)              \
+  (((__sanitizer_FILE *)fp)->_file == -1 \
+       ? -1                              \
+       : (int)(unsigned short)(((__sanitizer_FILE *)fp)->_file))
+
+#define stdout ((__sanitizer_FILE*)&__sF[1])
+#define stderr ((__sanitizer_FILE*)&__sF[2])
+
+#define nanosleep __nanosleep50
+#define vfork __vfork14
+#endif
+
+#if SANITIZER_ANDROID
+#define mallopt(a, b)
+#endif
+
+#ifdef __mips__
+const int kSigCount = 129;
+#else
+const int kSigCount = 65;
+#endif
+
+#ifdef __mips__
+struct ucontext_t {
+  u64 opaque[768 / sizeof(u64) + 1];
+};
+#else
+struct ucontext_t {
+  // The size is determined by looking at sizeof of real ucontext_t on linux.
+  u64 opaque[936 / sizeof(u64) + 1];
+};
+#endif
+
+#if defined(__x86_64__) || defined(__mips__) || SANITIZER_PPC64V1
+#define PTHREAD_ABI_BASE  "GLIBC_2.3.2"
+#elif defined(__aarch64__) || SANITIZER_PPC64V2
+#define PTHREAD_ABI_BASE  "GLIBC_2.17"
+#endif
+
+extern "C" int pthread_attr_init(void *attr);
+extern "C" int pthread_attr_destroy(void *attr);
+DECLARE_REAL(int, pthread_attr_getdetachstate, void *, void *)
+extern "C" int pthread_attr_setstacksize(void *attr, uptr stacksize);
+extern "C" int pthread_key_create(unsigned *key, void (*destructor)(void* v));
+extern "C" int pthread_setspecific(unsigned key, const void *v);
+DECLARE_REAL(int, pthread_mutexattr_gettype, void *, void *)
+DECLARE_REAL(int, fflush, __sanitizer_FILE *fp)
+DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr size)
+DECLARE_REAL_AND_INTERCEPTOR(void, free, void *ptr)
+extern "C" void *pthread_self();
+extern "C" void _exit(int status);
+#if !SANITIZER_NETBSD
+extern "C" int fileno_unlocked(void *stream);
+extern "C" int dirfd(void *dirp);
+#endif
+#if !SANITIZER_FREEBSD && !SANITIZER_ANDROID && !SANITIZER_NETBSD
+extern "C" int mallopt(int param, int value);
+#endif
+#if SANITIZER_NETBSD
+extern __sanitizer_FILE __sF[];
+#else
+extern __sanitizer_FILE *stdout, *stderr;
+#endif
+#if !SANITIZER_FREEBSD && !SANITIZER_MAC && !SANITIZER_NETBSD
+const int PTHREAD_MUTEX_RECURSIVE = 1;
+const int PTHREAD_MUTEX_RECURSIVE_NP = 1;
+#else
+const int PTHREAD_MUTEX_RECURSIVE = 2;
+const int PTHREAD_MUTEX_RECURSIVE_NP = 2;
+#endif
+#if !SANITIZER_FREEBSD && !SANITIZER_MAC && !SANITIZER_NETBSD
+const int EPOLL_CTL_ADD = 1;
+#endif
+const int SIGILL = 4;
+const int SIGTRAP = 5;
+const int SIGABRT = 6;
+const int SIGFPE = 8;
+const int SIGSEGV = 11;
+const int SIGPIPE = 13;
+const int SIGTERM = 15;
+#if defined(__mips__) || SANITIZER_FREEBSD || SANITIZER_MAC || SANITIZER_NETBSD
+const int SIGBUS = 10;
+const int SIGSYS = 12;
+#else
+const int SIGBUS = 7;
+const int SIGSYS = 31;
+#endif
+void *const MAP_FAILED = (void*)-1;
+#if SANITIZER_NETBSD
+const int PTHREAD_BARRIER_SERIAL_THREAD = 1234567;
+#elif !SANITIZER_MAC
+const int PTHREAD_BARRIER_SERIAL_THREAD = -1;
+#endif
+const int MAP_FIXED = 0x10;
+typedef long long_t;
+
+// From /usr/include/unistd.h
+# define F_ULOCK 0      /* Unlock a previously locked region.  */
+# define F_LOCK  1      /* Lock a region for exclusive use.  */
+# define F_TLOCK 2      /* Test and lock a region for exclusive use.  */
+# define F_TEST  3      /* Test a region for other processes locks.  */
+
+#if SANITIZER_FREEBSD || SANITIZER_MAC || SANITIZER_NETBSD
+const int SA_SIGINFO = 0x40;
+const int SIG_SETMASK = 3;
+#elif defined(__mips__)
+const int SA_SIGINFO = 8;
+const int SIG_SETMASK = 3;
+#else
+const int SA_SIGINFO = 4;
+const int SIG_SETMASK = 2;
+#endif
+
+#define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED \
+  (cur_thread_init(), !cur_thread()->is_inited)
+
+namespace __tsan {
+struct SignalDesc {
+  bool armed;
+  bool sigaction;
+  __sanitizer_siginfo siginfo;
+  ucontext_t ctx;
+};
+
+struct ThreadSignalContext {
+  int int_signal_send;
+  atomic_uintptr_t in_blocking_func;
+  atomic_uintptr_t have_pending_signals;
+  SignalDesc pending_signals[kSigCount];
+  // emptyset and oldset are too big for stack.
+  __sanitizer_sigset_t emptyset;
+  __sanitizer_sigset_t oldset;
+};
+
+// The sole reason tsan wraps atexit callbacks is to establish synchronization
+// between callback setup and callback execution.
+struct AtExitCtx {
+  void (*f)();
+  void *arg;
+};
+
+// InterceptorContext holds all global data required for interceptors.
+// It's explicitly constructed in InitializeInterceptors with placement new
+// and is never destroyed. This allows usage of members with non-trivial
+// constructors and destructors.
+struct InterceptorContext {
+  // The object is 64-byte aligned, because we want hot data to be located
+  // in a single cache line if possible (it's accessed in every interceptor).
+  ALIGNED(64) LibIgnore libignore;
+  __sanitizer_sigaction sigactions[kSigCount];
+#if !SANITIZER_MAC && !SANITIZER_NETBSD
+  unsigned finalize_key;
+#endif
+
+  BlockingMutex atexit_mu;
+  Vector<struct AtExitCtx *> AtExitStack;
+
+  InterceptorContext()
+      : libignore(LINKER_INITIALIZED), AtExitStack() {
+  }
+};
+
+static ALIGNED(64) char interceptor_placeholder[sizeof(InterceptorContext)];
+InterceptorContext *interceptor_ctx() {
+  return reinterpret_cast<InterceptorContext*>(&interceptor_placeholder[0]);
+}
+
+LibIgnore *libignore() {
+  return &interceptor_ctx()->libignore;
+}
+
+void InitializeLibIgnore() {
+  const SuppressionContext &supp = *Suppressions();
+  const uptr n = supp.SuppressionCount();
+  for (uptr i = 0; i < n; i++) {
+    const Suppression *s = supp.SuppressionAt(i);
+    if (0 == internal_strcmp(s->type, kSuppressionLib))
+      libignore()->AddIgnoredLibrary(s->templ);
+  }
+  if (flags()->ignore_noninstrumented_modules)
+    libignore()->IgnoreNoninstrumentedModules(true);
+  libignore()->OnLibraryLoaded(0);
+}
+
+// The following two hooks can be used by for cooperative scheduling when
+// locking.
+#ifdef TSAN_EXTERNAL_HOOKS
+void OnPotentiallyBlockingRegionBegin();
+void OnPotentiallyBlockingRegionEnd();
+#else
+SANITIZER_WEAK_CXX_DEFAULT_IMPL void OnPotentiallyBlockingRegionBegin() {}
+SANITIZER_WEAK_CXX_DEFAULT_IMPL void OnPotentiallyBlockingRegionEnd() {}
+#endif
+
+}  // namespace __tsan
+
+static ThreadSignalContext *SigCtx(ThreadState *thr) {
+  ThreadSignalContext *ctx = (ThreadSignalContext*)thr->signal_ctx;
+  if (ctx == 0 && !thr->is_dead) {
+    ctx = (ThreadSignalContext*)MmapOrDie(sizeof(*ctx), "ThreadSignalContext");
+    MemoryResetRange(thr, (uptr)&SigCtx, (uptr)ctx, sizeof(*ctx));
+    thr->signal_ctx = ctx;
+  }
+  return ctx;
+}
+
+ScopedInterceptor::ScopedInterceptor(ThreadState *thr, const char *fname,
+                                     uptr pc)
+    : thr_(thr), pc_(pc), in_ignored_lib_(false), ignoring_(false) {
+  Initialize(thr);
+  if (!thr_->is_inited) return;
+  if (!thr_->ignore_interceptors) FuncEntry(thr, pc);
+  DPrintf("#%d: intercept %s()\n", thr_->tid, fname);
+  ignoring_ =
+      !thr_->in_ignored_lib && libignore()->IsIgnored(pc, &in_ignored_lib_);
+  EnableIgnores();
+}
+
+ScopedInterceptor::~ScopedInterceptor() {
+  if (!thr_->is_inited) return;
+  DisableIgnores();
+  if (!thr_->ignore_interceptors) {
+    ProcessPendingSignals(thr_);
+    FuncExit(thr_);
+    CheckNoLocks(thr_);
+  }
+}
+
+void ScopedInterceptor::EnableIgnores() {
+  if (ignoring_) {
+    ThreadIgnoreBegin(thr_, pc_, /*save_stack=*/false);
+    if (flags()->ignore_noninstrumented_modules) thr_->suppress_reports++;
+    if (in_ignored_lib_) {
+      DCHECK(!thr_->in_ignored_lib);
+      thr_->in_ignored_lib = true;
+    }
+  }
+}
+
+void ScopedInterceptor::DisableIgnores() {
+  if (ignoring_) {
+    ThreadIgnoreEnd(thr_, pc_);
+    if (flags()->ignore_noninstrumented_modules) thr_->suppress_reports--;
+    if (in_ignored_lib_) {
+      DCHECK(thr_->in_ignored_lib);
+      thr_->in_ignored_lib = false;
+    }
+  }
+}
+
+#define TSAN_INTERCEPT(func) INTERCEPT_FUNCTION(func)
+#if SANITIZER_FREEBSD
+# define TSAN_INTERCEPT_VER(func, ver) INTERCEPT_FUNCTION(func)
+# define TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(func)
+# define TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS_THR(func)
+#elif SANITIZER_NETBSD
+# define TSAN_INTERCEPT_VER(func, ver) INTERCEPT_FUNCTION(func)
+# define TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(func) \
+         INTERCEPT_FUNCTION(__libc_##func)
+# define TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS_THR(func) \
+         INTERCEPT_FUNCTION(__libc_thr_##func)
+#else
+# define TSAN_INTERCEPT_VER(func, ver) INTERCEPT_FUNCTION_VER(func, ver)
+# define TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(func)
+# define TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS_THR(func)
+#endif
+
+#define READ_STRING_OF_LEN(thr, pc, s, len, n)                 \
+  MemoryAccessRange((thr), (pc), (uptr)(s),                         \
+    common_flags()->strict_string_checks ? (len) + 1 : (n), false)
+
+#define READ_STRING(thr, pc, s, n)                             \
+    READ_STRING_OF_LEN((thr), (pc), (s), internal_strlen(s), (n))
+
+#define BLOCK_REAL(name) (BlockingCall(thr), REAL(name))
+
+struct BlockingCall {
+  explicit BlockingCall(ThreadState *thr)
+      : thr(thr)
+      , ctx(SigCtx(thr)) {
+    for (;;) {
+      atomic_store(&ctx->in_blocking_func, 1, memory_order_relaxed);
+      if (atomic_load(&ctx->have_pending_signals, memory_order_relaxed) == 0)
+        break;
+      atomic_store(&ctx->in_blocking_func, 0, memory_order_relaxed);
+      ProcessPendingSignals(thr);
+    }
+    // When we are in a "blocking call", we process signals asynchronously
+    // (right when they arrive). In this context we do not expect to be
+    // executing any user/runtime code. The known interceptor sequence when
+    // this is not true is: pthread_join -> munmap(stack). It's fine
+    // to ignore munmap in this case -- we handle stack shadow separately.
+    thr->ignore_interceptors++;
+  }
+
+  ~BlockingCall() {
+    thr->ignore_interceptors--;
+    atomic_store(&ctx->in_blocking_func, 0, memory_order_relaxed);
+  }
+
+  ThreadState *thr;
+  ThreadSignalContext *ctx;
+};
+
+TSAN_INTERCEPTOR(unsigned, sleep, unsigned sec) {
+  SCOPED_TSAN_INTERCEPTOR(sleep, sec);
+  unsigned res = BLOCK_REAL(sleep)(sec);
+  AfterSleep(thr, pc);
+  return res;
+}
+
+TSAN_INTERCEPTOR(int, usleep, long_t usec) {
+  SCOPED_TSAN_INTERCEPTOR(usleep, usec);
+  int res = BLOCK_REAL(usleep)(usec);
+  AfterSleep(thr, pc);
+  return res;
+}
+
+TSAN_INTERCEPTOR(int, nanosleep, void *req, void *rem) {
+  SCOPED_TSAN_INTERCEPTOR(nanosleep, req, rem);
+  int res = BLOCK_REAL(nanosleep)(req, rem);
+  AfterSleep(thr, pc);
+  return res;
+}
+
+TSAN_INTERCEPTOR(int, pause, int fake) {
+  SCOPED_TSAN_INTERCEPTOR(pause, fake);
+  return BLOCK_REAL(pause)(fake);
+}
+
+static void at_exit_wrapper() {
+  AtExitCtx *ctx;
+  {
+    // Ensure thread-safety.
+    BlockingMutexLock l(&interceptor_ctx()->atexit_mu);
+
+    // Pop AtExitCtx from the top of the stack of callback functions
+    uptr element = interceptor_ctx()->AtExitStack.Size() - 1;
+    ctx = interceptor_ctx()->AtExitStack[element];
+    interceptor_ctx()->AtExitStack.PopBack();
+  }
+
+  Acquire(cur_thread(), (uptr)0, (uptr)ctx);
+  ((void(*)())ctx->f)();
+  InternalFree(ctx);
+}
+
+static void cxa_at_exit_wrapper(void *arg) {
+  Acquire(cur_thread(), 0, (uptr)arg);
+  AtExitCtx *ctx = (AtExitCtx*)arg;
+  ((void(*)(void *arg))ctx->f)(ctx->arg);
+  InternalFree(ctx);
+}
+
+static int setup_at_exit_wrapper(ThreadState *thr, uptr pc, void(*f)(),
+      void *arg, void *dso);
+
+#if !SANITIZER_ANDROID
+TSAN_INTERCEPTOR(int, atexit, void (*f)()) {
+  if (in_symbolizer())
+    return 0;
+  // We want to setup the atexit callback even if we are in ignored lib
+  // or after fork.
+  SCOPED_INTERCEPTOR_RAW(atexit, f);
+  return setup_at_exit_wrapper(thr, pc, (void(*)())f, 0, 0);
+}
+#endif
+
+TSAN_INTERCEPTOR(int, __cxa_atexit, void (*f)(void *a), void *arg, void *dso) {
+  if (in_symbolizer())
+    return 0;
+  SCOPED_TSAN_INTERCEPTOR(__cxa_atexit, f, arg, dso);
+  return setup_at_exit_wrapper(thr, pc, (void(*)())f, arg, dso);
+}
+
+static int setup_at_exit_wrapper(ThreadState *thr, uptr pc, void(*f)(),
+      void *arg, void *dso) {
+  AtExitCtx *ctx = (AtExitCtx*)InternalAlloc(sizeof(AtExitCtx));
+  ctx->f = f;
+  ctx->arg = arg;
+  Release(thr, pc, (uptr)ctx);
+  // Memory allocation in __cxa_atexit will race with free during exit,
+  // because we do not see synchronization around atexit callback list.
+  ThreadIgnoreBegin(thr, pc);
+  int res;
+  if (!dso) {
+    // NetBSD does not preserve the 2nd argument if dso is equal to 0
+    // Store ctx in a local stack-like structure
+
+    // Ensure thread-safety.
+    BlockingMutexLock l(&interceptor_ctx()->atexit_mu);
+
+    res = REAL(__cxa_atexit)((void (*)(void *a))at_exit_wrapper, 0, 0);
+    // Push AtExitCtx on the top of the stack of callback functions
+    if (!res) {
+      interceptor_ctx()->AtExitStack.PushBack(ctx);
+    }
+  } else {
+    res = REAL(__cxa_atexit)(cxa_at_exit_wrapper, ctx, dso);
+  }
+  ThreadIgnoreEnd(thr, pc);
+  return res;
+}
+
+#if !SANITIZER_MAC && !SANITIZER_NETBSD
+static void on_exit_wrapper(int status, void *arg) {
+  ThreadState *thr = cur_thread();
+  uptr pc = 0;
+  Acquire(thr, pc, (uptr)arg);
+  AtExitCtx *ctx = (AtExitCtx*)arg;
+  ((void(*)(int status, void *arg))ctx->f)(status, ctx->arg);
+  InternalFree(ctx);
+}
+
+TSAN_INTERCEPTOR(int, on_exit, void(*f)(int, void*), void *arg) {
+  if (in_symbolizer())
+    return 0;
+  SCOPED_TSAN_INTERCEPTOR(on_exit, f, arg);
+  AtExitCtx *ctx = (AtExitCtx*)InternalAlloc(sizeof(AtExitCtx));
+  ctx->f = (void(*)())f;
+  ctx->arg = arg;
+  Release(thr, pc, (uptr)ctx);
+  // Memory allocation in __cxa_atexit will race with free during exit,
+  // because we do not see synchronization around atexit callback list.
+  ThreadIgnoreBegin(thr, pc);
+  int res = REAL(on_exit)(on_exit_wrapper, ctx);
+  ThreadIgnoreEnd(thr, pc);
+  return res;
+}
+#define TSAN_MAYBE_INTERCEPT_ON_EXIT TSAN_INTERCEPT(on_exit)
+#else
+#define TSAN_MAYBE_INTERCEPT_ON_EXIT
+#endif
+
+// Cleanup old bufs.
+static void JmpBufGarbageCollect(ThreadState *thr, uptr sp) {
+  for (uptr i = 0; i < thr->jmp_bufs.Size(); i++) {
+    JmpBuf *buf = &thr->jmp_bufs[i];
+    if (buf->sp <= sp) {
+      uptr sz = thr->jmp_bufs.Size();
+      internal_memcpy(buf, &thr->jmp_bufs[sz - 1], sizeof(*buf));
+      thr->jmp_bufs.PopBack();
+      i--;
+    }
+  }
+}
+
+static void SetJmp(ThreadState *thr, uptr sp) {
+  if (!thr->is_inited)  // called from libc guts during bootstrap
+    return;
+  // Cleanup old bufs.
+  JmpBufGarbageCollect(thr, sp);
+  // Remember the buf.
+  JmpBuf *buf = thr->jmp_bufs.PushBack();
+  buf->sp = sp;
+  buf->shadow_stack_pos = thr->shadow_stack_pos;
+  ThreadSignalContext *sctx = SigCtx(thr);
+  buf->int_signal_send = sctx ? sctx->int_signal_send : 0;
+  buf->in_blocking_func = sctx ?
+      atomic_load(&sctx->in_blocking_func, memory_order_relaxed) :
+      false;
+  buf->in_signal_handler = atomic_load(&thr->in_signal_handler,
+      memory_order_relaxed);
+}
+
+static void LongJmp(ThreadState *thr, uptr *env) {
+  uptr sp = ExtractLongJmpSp(env);
+  // Find the saved buf with matching sp.
+  for (uptr i = 0; i < thr->jmp_bufs.Size(); i++) {
+    JmpBuf *buf = &thr->jmp_bufs[i];
+    if (buf->sp == sp) {
+      CHECK_GE(thr->shadow_stack_pos, buf->shadow_stack_pos);
+      // Unwind the stack.
+      while (thr->shadow_stack_pos > buf->shadow_stack_pos)
+        FuncExit(thr);
+      ThreadSignalContext *sctx = SigCtx(thr);
+      if (sctx) {
+        sctx->int_signal_send = buf->int_signal_send;
+        atomic_store(&sctx->in_blocking_func, buf->in_blocking_func,
+            memory_order_relaxed);
+      }
+      atomic_store(&thr->in_signal_handler, buf->in_signal_handler,
+          memory_order_relaxed);
+      JmpBufGarbageCollect(thr, buf->sp - 1);  // do not collect buf->sp
+      return;
+    }
+  }
+  Printf("ThreadSanitizer: can't find longjmp buf\n");
+  CHECK(0);
+}
+
+// FIXME: put everything below into a common extern "C" block?
+extern "C" void __tsan_setjmp(uptr sp) {
+  cur_thread_init();
+  SetJmp(cur_thread(), sp);
+}
+
+#if SANITIZER_MAC
+TSAN_INTERCEPTOR(int, setjmp, void *env);
+TSAN_INTERCEPTOR(int, _setjmp, void *env);
+TSAN_INTERCEPTOR(int, sigsetjmp, void *env);
+#else  // SANITIZER_MAC
+
+#if SANITIZER_NETBSD
+#define setjmp_symname __setjmp14
+#define sigsetjmp_symname __sigsetjmp14
+#else
+#define setjmp_symname setjmp
+#define sigsetjmp_symname sigsetjmp
+#endif
+
+#define TSAN_INTERCEPTOR_SETJMP_(x) __interceptor_ ## x
+#define TSAN_INTERCEPTOR_SETJMP__(x) TSAN_INTERCEPTOR_SETJMP_(x)
+#define TSAN_INTERCEPTOR_SETJMP TSAN_INTERCEPTOR_SETJMP__(setjmp_symname)
+#define TSAN_INTERCEPTOR_SIGSETJMP TSAN_INTERCEPTOR_SETJMP__(sigsetjmp_symname)
+
+#define TSAN_STRING_SETJMP SANITIZER_STRINGIFY(setjmp_symname)
+#define TSAN_STRING_SIGSETJMP SANITIZER_STRINGIFY(sigsetjmp_symname)
+
+// Not called.  Merely to satisfy TSAN_INTERCEPT().
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+int TSAN_INTERCEPTOR_SETJMP(void *env);
+extern "C" int TSAN_INTERCEPTOR_SETJMP(void *env) {
+  CHECK(0);
+  return 0;
+}
+
+// FIXME: any reason to have a separate declaration?
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+int __interceptor__setjmp(void *env);
+extern "C" int __interceptor__setjmp(void *env) {
+  CHECK(0);
+  return 0;
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+int TSAN_INTERCEPTOR_SIGSETJMP(void *env);
+extern "C" int TSAN_INTERCEPTOR_SIGSETJMP(void *env) {
+  CHECK(0);
+  return 0;
+}
+
+#if !SANITIZER_NETBSD
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+int __interceptor___sigsetjmp(void *env);
+extern "C" int __interceptor___sigsetjmp(void *env) {
+  CHECK(0);
+  return 0;
+}
+#endif
+
+extern "C" int setjmp_symname(void *env);
+extern "C" int _setjmp(void *env);
+extern "C" int sigsetjmp_symname(void *env);
+#if !SANITIZER_NETBSD
+extern "C" int __sigsetjmp(void *env);
+#endif
+DEFINE_REAL(int, setjmp_symname, void *env)
+DEFINE_REAL(int, _setjmp, void *env)
+DEFINE_REAL(int, sigsetjmp_symname, void *env)
+#if !SANITIZER_NETBSD
+DEFINE_REAL(int, __sigsetjmp, void *env)
+#endif
+#endif  // SANITIZER_MAC
+
+#if SANITIZER_NETBSD
+#define longjmp_symname __longjmp14
+#define siglongjmp_symname __siglongjmp14
+#else
+#define longjmp_symname longjmp
+#define siglongjmp_symname siglongjmp
+#endif
+
+TSAN_INTERCEPTOR(void, longjmp_symname, uptr *env, int val) {
+  // Note: if we call REAL(longjmp) in the context of ScopedInterceptor,
+  // bad things will happen. We will jump over ScopedInterceptor dtor and can
+  // leave thr->in_ignored_lib set.
+  {
+    SCOPED_INTERCEPTOR_RAW(longjmp_symname, env, val);
+  }
+  LongJmp(cur_thread(), env);
+  REAL(longjmp_symname)(env, val);
+}
+
+TSAN_INTERCEPTOR(void, siglongjmp_symname, uptr *env, int val) {
+  {
+    SCOPED_INTERCEPTOR_RAW(siglongjmp_symname, env, val);
+  }
+  LongJmp(cur_thread(), env);
+  REAL(siglongjmp_symname)(env, val);
+}
+
+#if SANITIZER_NETBSD
+TSAN_INTERCEPTOR(void, _longjmp, uptr *env, int val) {
+  {
+    SCOPED_INTERCEPTOR_RAW(_longjmp, env, val);
+  }
+  LongJmp(cur_thread(), env);
+  REAL(_longjmp)(env, val);
+}
+#endif
+
+#if !SANITIZER_MAC
+TSAN_INTERCEPTOR(void*, malloc, uptr size) {
+  if (in_symbolizer())
+    return InternalAlloc(size);
+  void *p = 0;
+  {
+    SCOPED_INTERCEPTOR_RAW(malloc, size);
+    p = user_alloc(thr, pc, size);
+  }
+  invoke_malloc_hook(p, size);
+  return p;
+}
+
+TSAN_INTERCEPTOR(void*, __libc_memalign, uptr align, uptr sz) {
+  SCOPED_TSAN_INTERCEPTOR(__libc_memalign, align, sz);
+  return user_memalign(thr, pc, align, sz);
+}
+
+TSAN_INTERCEPTOR(void*, calloc, uptr size, uptr n) {
+  if (in_symbolizer())
+    return InternalCalloc(size, n);
+  void *p = 0;
+  {
+    SCOPED_INTERCEPTOR_RAW(calloc, size, n);
+    p = user_calloc(thr, pc, size, n);
+  }
+  invoke_malloc_hook(p, n * size);
+  return p;
+}
+
+TSAN_INTERCEPTOR(void*, realloc, void *p, uptr size) {
+  if (in_symbolizer())
+    return InternalRealloc(p, size);
+  if (p)
+    invoke_free_hook(p);
+  {
+    SCOPED_INTERCEPTOR_RAW(realloc, p, size);
+    p = user_realloc(thr, pc, p, size);
+  }
+  invoke_malloc_hook(p, size);
+  return p;
+}
+
+TSAN_INTERCEPTOR(void*, reallocarray, void *p, uptr size, uptr n) {
+  if (in_symbolizer())
+    return InternalReallocArray(p, size, n);
+  if (p)
+    invoke_free_hook(p);
+  {
+    SCOPED_INTERCEPTOR_RAW(reallocarray, p, size, n);
+    p = user_reallocarray(thr, pc, p, size, n);
+  }
+  invoke_malloc_hook(p, size);
+  return p;
+}
+
+TSAN_INTERCEPTOR(void, free, void *p) {
+  if (p == 0)
+    return;
+  if (in_symbolizer())
+    return InternalFree(p);
+  invoke_free_hook(p);
+  SCOPED_INTERCEPTOR_RAW(free, p);
+  user_free(thr, pc, p);
+}
+
+TSAN_INTERCEPTOR(void, cfree, void *p) {
+  if (p == 0)
+    return;
+  if (in_symbolizer())
+    return InternalFree(p);
+  invoke_free_hook(p);
+  SCOPED_INTERCEPTOR_RAW(cfree, p);
+  user_free(thr, pc, p);
+}
+
+TSAN_INTERCEPTOR(uptr, malloc_usable_size, void *p) {
+  SCOPED_INTERCEPTOR_RAW(malloc_usable_size, p);
+  return user_alloc_usable_size(p);
+}
+#endif
+
+TSAN_INTERCEPTOR(char *, strcpy, char *dst, const char *src) {
+  SCOPED_TSAN_INTERCEPTOR(strcpy, dst, src);
+  uptr srclen = internal_strlen(src);
+  MemoryAccessRange(thr, pc, (uptr)dst, srclen + 1, true);
+  MemoryAccessRange(thr, pc, (uptr)src, srclen + 1, false);
+  return REAL(strcpy)(dst, src);
+}
+
+TSAN_INTERCEPTOR(char*, strncpy, char *dst, char *src, uptr n) {
+  SCOPED_TSAN_INTERCEPTOR(strncpy, dst, src, n);
+  uptr srclen = internal_strnlen(src, n);
+  MemoryAccessRange(thr, pc, (uptr)dst, n, true);
+  MemoryAccessRange(thr, pc, (uptr)src, min(srclen + 1, n), false);
+  return REAL(strncpy)(dst, src, n);
+}
+
+TSAN_INTERCEPTOR(char*, strdup, const char *str) {
+  SCOPED_TSAN_INTERCEPTOR(strdup, str);
+  // strdup will call malloc, so no instrumentation is required here.
+  return REAL(strdup)(str);
+}
+
+// Zero out addr if it points into shadow memory and was provided as a hint
+// only, i.e., MAP_FIXED is not set.
+static bool fix_mmap_addr(void **addr, long_t sz, int flags) {
+  if (*addr) {
+    if (!IsAppMem((uptr)*addr) || !IsAppMem((uptr)*addr + sz - 1)) {
+      if (flags & MAP_FIXED) {
+        errno = errno_EINVAL;
+        return false;
+      } else {
+        *addr = 0;
+      }
+    }
+  }
+  return true;
+}
+
+template <class Mmap>
+static void *mmap_interceptor(ThreadState *thr, uptr pc, Mmap real_mmap,
+                              void *addr, SIZE_T sz, int prot, int flags,
+                              int fd, OFF64_T off) {
+  if (!fix_mmap_addr(&addr, sz, flags)) return MAP_FAILED;
+  void *res = real_mmap(addr, sz, prot, flags, fd, off);
+  if (res != MAP_FAILED) {
+    if (fd > 0) FdAccess(thr, pc, fd);
+    MemoryRangeImitateWriteOrResetRange(thr, pc, (uptr)res, sz);
+  }
+  return res;
+}
+
+TSAN_INTERCEPTOR(int, munmap, void *addr, long_t sz) {
+  SCOPED_TSAN_INTERCEPTOR(munmap, addr, sz);
+  UnmapShadow(thr, (uptr)addr, sz);
+  int res = REAL(munmap)(addr, sz);
+  return res;
+}
+
+#if SANITIZER_LINUX
+TSAN_INTERCEPTOR(void*, memalign, uptr align, uptr sz) {
+  SCOPED_INTERCEPTOR_RAW(memalign, align, sz);
+  return user_memalign(thr, pc, align, sz);
+}
+#define TSAN_MAYBE_INTERCEPT_MEMALIGN TSAN_INTERCEPT(memalign)
+#else
+#define TSAN_MAYBE_INTERCEPT_MEMALIGN
+#endif
+
+#if !SANITIZER_MAC
+TSAN_INTERCEPTOR(void*, aligned_alloc, uptr align, uptr sz) {
+  if (in_symbolizer())
+    return InternalAlloc(sz, nullptr, align);
+  SCOPED_INTERCEPTOR_RAW(aligned_alloc, align, sz);
+  return user_aligned_alloc(thr, pc, align, sz);
+}
+
+TSAN_INTERCEPTOR(void*, valloc, uptr sz) {
+  if (in_symbolizer())
+    return InternalAlloc(sz, nullptr, GetPageSizeCached());
+  SCOPED_INTERCEPTOR_RAW(valloc, sz);
+  return user_valloc(thr, pc, sz);
+}
+#endif
+
+#if SANITIZER_LINUX
+TSAN_INTERCEPTOR(void*, pvalloc, uptr sz) {
+  if (in_symbolizer()) {
+    uptr PageSize = GetPageSizeCached();
+    sz = sz ? RoundUpTo(sz, PageSize) : PageSize;
+    return InternalAlloc(sz, nullptr, PageSize);
+  }
+  SCOPED_INTERCEPTOR_RAW(pvalloc, sz);
+  return user_pvalloc(thr, pc, sz);
+}
+#define TSAN_MAYBE_INTERCEPT_PVALLOC TSAN_INTERCEPT(pvalloc)
+#else
+#define TSAN_MAYBE_INTERCEPT_PVALLOC
+#endif
+
+#if !SANITIZER_MAC
+TSAN_INTERCEPTOR(int, posix_memalign, void **memptr, uptr align, uptr sz) {
+  if (in_symbolizer()) {
+    void *p = InternalAlloc(sz, nullptr, align);
+    if (!p)
+      return errno_ENOMEM;
+    *memptr = p;
+    return 0;
+  }
+  SCOPED_INTERCEPTOR_RAW(posix_memalign, memptr, align, sz);
+  return user_posix_memalign(thr, pc, memptr, align, sz);
+}
+#endif
+
+// __cxa_guard_acquire and friends need to be intercepted in a special way -
+// regular interceptors will break statically-linked libstdc++. Linux
+// interceptors are especially defined as weak functions (so that they don't
+// cause link errors when user defines them as well). So they silently
+// auto-disable themselves when such symbol is already present in the binary. If
+// we link libstdc++ statically, it will bring own __cxa_guard_acquire which
+// will silently replace our interceptor.  That's why on Linux we simply export
+// these interceptors with INTERFACE_ATTRIBUTE.
+// On OS X, we don't support statically linking, so we just use a regular
+// interceptor.
+#if SANITIZER_MAC
+#define STDCXX_INTERCEPTOR TSAN_INTERCEPTOR
+#else
+#define STDCXX_INTERCEPTOR(rettype, name, ...) \
+  extern "C" rettype INTERFACE_ATTRIBUTE name(__VA_ARGS__)
+#endif
+
+// Used in thread-safe function static initialization.
+STDCXX_INTERCEPTOR(int, __cxa_guard_acquire, atomic_uint32_t *g) {
+  SCOPED_INTERCEPTOR_RAW(__cxa_guard_acquire, g);
+  OnPotentiallyBlockingRegionBegin();
+  auto on_exit = at_scope_exit(&OnPotentiallyBlockingRegionEnd);
+  for (;;) {
+    u32 cmp = atomic_load(g, memory_order_acquire);
+    if (cmp == 0) {
+      if (atomic_compare_exchange_strong(g, &cmp, 1<<16, memory_order_relaxed))
+        return 1;
+    } else if (cmp == 1) {
+      Acquire(thr, pc, (uptr)g);
+      return 0;
+    } else {
+      internal_sched_yield();
+    }
+  }
+}
+
+STDCXX_INTERCEPTOR(void, __cxa_guard_release, atomic_uint32_t *g) {
+  SCOPED_INTERCEPTOR_RAW(__cxa_guard_release, g);
+  Release(thr, pc, (uptr)g);
+  atomic_store(g, 1, memory_order_release);
+}
+
+STDCXX_INTERCEPTOR(void, __cxa_guard_abort, atomic_uint32_t *g) {
+  SCOPED_INTERCEPTOR_RAW(__cxa_guard_abort, g);
+  atomic_store(g, 0, memory_order_relaxed);
+}
+
+namespace __tsan {
+void DestroyThreadState() {
+  ThreadState *thr = cur_thread();
+  Processor *proc = thr->proc();
+  ThreadFinish(thr);
+  ProcUnwire(proc, thr);
+  ProcDestroy(proc);
+  ThreadSignalContext *sctx = thr->signal_ctx;
+  if (sctx) {
+    thr->signal_ctx = 0;
+    UnmapOrDie(sctx, sizeof(*sctx));
+  }
+  DTLS_Destroy();
+  cur_thread_finalize();
+}
+}  // namespace __tsan
+
+#if !SANITIZER_MAC && !SANITIZER_NETBSD && !SANITIZER_FREEBSD
+static void thread_finalize(void *v) {
+  uptr iter = (uptr)v;
+  if (iter > 1) {
+    if (pthread_setspecific(interceptor_ctx()->finalize_key,
+        (void*)(iter - 1))) {
+      Printf("ThreadSanitizer: failed to set thread key\n");
+      Die();
+    }
+    return;
+  }
+  DestroyThreadState();
+}
+#endif
+
+
+struct ThreadParam {
+  void* (*callback)(void *arg);
+  void *param;
+  atomic_uintptr_t tid;
+};
+
+extern "C" void *__tsan_thread_start_func(void *arg) {
+  ThreadParam *p = (ThreadParam*)arg;
+  void* (*callback)(void *arg) = p->callback;
+  void *param = p->param;
+  int tid = 0;
+  {
+    cur_thread_init();
+    ThreadState *thr = cur_thread();
+    // Thread-local state is not initialized yet.
+    ScopedIgnoreInterceptors ignore;
+#if !SANITIZER_MAC && !SANITIZER_NETBSD && !SANITIZER_FREEBSD
+    ThreadIgnoreBegin(thr, 0);
+    if (pthread_setspecific(interceptor_ctx()->finalize_key,
+                            (void *)GetPthreadDestructorIterations())) {
+      Printf("ThreadSanitizer: failed to set thread key\n");
+      Die();
+    }
+    ThreadIgnoreEnd(thr, 0);
+#endif
+    while ((tid = atomic_load(&p->tid, memory_order_acquire)) == 0)
+      internal_sched_yield();
+    Processor *proc = ProcCreate();
+    ProcWire(proc, thr);
+    ThreadStart(thr, tid, GetTid(), ThreadType::Regular);
+    atomic_store(&p->tid, 0, memory_order_release);
+  }
+  void *res = callback(param);
+  // Prevent the callback from being tail called,
+  // it mixes up stack traces.
+  volatile int foo = 42;
+  foo++;
+  return res;
+}
+
+TSAN_INTERCEPTOR(int, pthread_create,
+    void *th, void *attr, void *(*callback)(void*), void * param) {
+  SCOPED_INTERCEPTOR_RAW(pthread_create, th, attr, callback, param);
+
+  MaybeSpawnBackgroundThread();
+
+  if (ctx->after_multithreaded_fork) {
+    if (flags()->die_after_fork) {
+      Report("ThreadSanitizer: starting new threads after multi-threaded "
+          "fork is not supported. Dying (set die_after_fork=0 to override)\n");
+      Die();
+    } else {
+      VPrintf(1, "ThreadSanitizer: starting new threads after multi-threaded "
+          "fork is not supported (pid %d). Continuing because of "
+          "die_after_fork=0, but you are on your own\n", internal_getpid());
+    }
+  }
+  __sanitizer_pthread_attr_t myattr;
+  if (attr == 0) {
+    pthread_attr_init(&myattr);
+    attr = &myattr;
+  }
+  int detached = 0;
+  REAL(pthread_attr_getdetachstate)(attr, &detached);
+  AdjustStackSize(attr);
+
+  ThreadParam p;
+  p.callback = callback;
+  p.param = param;
+  atomic_store(&p.tid, 0, memory_order_relaxed);
+  int res = -1;
+  {
+    // Otherwise we see false positives in pthread stack manipulation.
+    ScopedIgnoreInterceptors ignore;
+    ThreadIgnoreBegin(thr, pc);
+    res = REAL(pthread_create)(th, attr, __tsan_thread_start_func, &p);
+    ThreadIgnoreEnd(thr, pc);
+  }
+  if (res == 0) {
+    int tid = ThreadCreate(thr, pc, *(uptr*)th, IsStateDetached(detached));
+    CHECK_NE(tid, 0);
+    // Synchronization on p.tid serves two purposes:
+    // 1. ThreadCreate must finish before the new thread starts.
+    //    Otherwise the new thread can call pthread_detach, but the pthread_t
+    //    identifier is not yet registered in ThreadRegistry by ThreadCreate.
+    // 2. ThreadStart must finish before this thread continues.
+    //    Otherwise, this thread can call pthread_detach and reset thr->sync
+    //    before the new thread got a chance to acquire from it in ThreadStart.
+    atomic_store(&p.tid, tid, memory_order_release);
+    while (atomic_load(&p.tid, memory_order_acquire) != 0)
+      internal_sched_yield();
+  }
+  if (attr == &myattr)
+    pthread_attr_destroy(&myattr);
+  return res;
+}
+
+TSAN_INTERCEPTOR(int, pthread_join, void *th, void **ret) {
+  SCOPED_INTERCEPTOR_RAW(pthread_join, th, ret);
+  int tid = ThreadTid(thr, pc, (uptr)th);
+  ThreadIgnoreBegin(thr, pc);
+  int res = BLOCK_REAL(pthread_join)(th, ret);
+  ThreadIgnoreEnd(thr, pc);
+  if (res == 0) {
+    ThreadJoin(thr, pc, tid);
+  }
+  return res;
+}
+
+DEFINE_REAL_PTHREAD_FUNCTIONS
+
+TSAN_INTERCEPTOR(int, pthread_detach, void *th) {
+  SCOPED_TSAN_INTERCEPTOR(pthread_detach, th);
+  int tid = ThreadTid(thr, pc, (uptr)th);
+  int res = REAL(pthread_detach)(th);
+  if (res == 0) {
+    ThreadDetach(thr, pc, tid);
+  }
+  return res;
+}
+
+TSAN_INTERCEPTOR(void, pthread_exit, void *retval) {
+  {
+    SCOPED_INTERCEPTOR_RAW(pthread_exit, retval);
+#if !SANITIZER_MAC && !SANITIZER_ANDROID
+    CHECK_EQ(thr, &cur_thread_placeholder);
+#endif
+  }
+  REAL(pthread_exit)(retval);
+}
+
+#if SANITIZER_LINUX
+TSAN_INTERCEPTOR(int, pthread_tryjoin_np, void *th, void **ret) {
+  SCOPED_TSAN_INTERCEPTOR(pthread_tryjoin_np, th, ret);
+  int tid = ThreadTid(thr, pc, (uptr)th);
+  ThreadIgnoreBegin(thr, pc);
+  int res = REAL(pthread_tryjoin_np)(th, ret);
+  ThreadIgnoreEnd(thr, pc);
+  if (res == 0)
+    ThreadJoin(thr, pc, tid);
+  else
+    ThreadNotJoined(thr, pc, tid, (uptr)th);
+  return res;
+}
+
+TSAN_INTERCEPTOR(int, pthread_timedjoin_np, void *th, void **ret,
+                 const struct timespec *abstime) {
+  SCOPED_TSAN_INTERCEPTOR(pthread_timedjoin_np, th, ret, abstime);
+  int tid = ThreadTid(thr, pc, (uptr)th);
+  ThreadIgnoreBegin(thr, pc);
+  int res = BLOCK_REAL(pthread_timedjoin_np)(th, ret, abstime);
+  ThreadIgnoreEnd(thr, pc);
+  if (res == 0)
+    ThreadJoin(thr, pc, tid);
+  else
+    ThreadNotJoined(thr, pc, tid, (uptr)th);
+  return res;
+}
+#endif
+
+// Problem:
+// NPTL implementation of pthread_cond has 2 versions (2.2.5 and 2.3.2).
+// pthread_cond_t has different size in the different versions.
+// If call new REAL functions for old pthread_cond_t, they will corrupt memory
+// after pthread_cond_t (old cond is smaller).
+// If we call old REAL functions for new pthread_cond_t, we will lose  some
+// functionality (e.g. old functions do not support waiting against
+// CLOCK_REALTIME).
+// Proper handling would require to have 2 versions of interceptors as well.
+// But this is messy, in particular requires linker scripts when sanitizer
+// runtime is linked into a shared library.
+// Instead we assume we don't have dynamic libraries built against old
+// pthread (2.2.5 is dated by 2002). And provide legacy_pthread_cond flag
+// that allows to work with old libraries (but this mode does not support
+// some features, e.g. pthread_condattr_getpshared).
+static void *init_cond(void *c, bool force = false) {
+  // sizeof(pthread_cond_t) >= sizeof(uptr) in both versions.
+  // So we allocate additional memory on the side large enough to hold
+  // any pthread_cond_t object. Always call new REAL functions, but pass
+  // the aux object to them.
+  // Note: the code assumes that PTHREAD_COND_INITIALIZER initializes
+  // first word of pthread_cond_t to zero.
+  // It's all relevant only for linux.
+  if (!common_flags()->legacy_pthread_cond)
+    return c;
+  atomic_uintptr_t *p = (atomic_uintptr_t*)c;
+  uptr cond = atomic_load(p, memory_order_acquire);
+  if (!force && cond != 0)
+    return (void*)cond;
+  void *newcond = WRAP(malloc)(pthread_cond_t_sz);
+  internal_memset(newcond, 0, pthread_cond_t_sz);
+  if (atomic_compare_exchange_strong(p, &cond, (uptr)newcond,
+      memory_order_acq_rel))
+    return newcond;
+  WRAP(free)(newcond);
+  return (void*)cond;
+}
+
+struct CondMutexUnlockCtx {
+  ScopedInterceptor *si;
+  ThreadState *thr;
+  uptr pc;
+  void *m;
+};
+
+static void cond_mutex_unlock(CondMutexUnlockCtx *arg) {
+  // pthread_cond_wait interceptor has enabled async signal delivery
+  // (see BlockingCall below). Disable async signals since we are running
+  // tsan code. Also ScopedInterceptor and BlockingCall destructors won't run
+  // since the thread is cancelled, so we have to manually execute them
+  // (the thread still can run some user code due to pthread_cleanup_push).
+  ThreadSignalContext *ctx = SigCtx(arg->thr);
+  CHECK_EQ(atomic_load(&ctx->in_blocking_func, memory_order_relaxed), 1);
+  atomic_store(&ctx->in_blocking_func, 0, memory_order_relaxed);
+  MutexPostLock(arg->thr, arg->pc, (uptr)arg->m, MutexFlagDoPreLockOnPostLock);
+  // Undo BlockingCall ctor effects.
+  arg->thr->ignore_interceptors--;
+  arg->si->~ScopedInterceptor();
+}
+
+INTERCEPTOR(int, pthread_cond_init, void *c, void *a) {
+  void *cond = init_cond(c, true);
+  SCOPED_TSAN_INTERCEPTOR(pthread_cond_init, cond, a);
+  MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), true);
+  return REAL(pthread_cond_init)(cond, a);
+}
+
+static int cond_wait(ThreadState *thr, uptr pc, ScopedInterceptor *si,
+                     int (*fn)(void *c, void *m, void *abstime), void *c,
+                     void *m, void *t) {
+  MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), false);
+  MutexUnlock(thr, pc, (uptr)m);
+  CondMutexUnlockCtx arg = {si, thr, pc, m};
+  int res = 0;
+  // This ensures that we handle mutex lock even in case of pthread_cancel.
+  // See test/tsan/cond_cancel.cpp.
+  {
+    // Enable signal delivery while the thread is blocked.
+    BlockingCall bc(thr);
+    res = call_pthread_cancel_with_cleanup(
+        fn, c, m, t, (void (*)(void *arg))cond_mutex_unlock, &arg);
+  }
+  if (res == errno_EOWNERDEAD) MutexRepair(thr, pc, (uptr)m);
+  MutexPostLock(thr, pc, (uptr)m, MutexFlagDoPreLockOnPostLock);
+  return res;
+}
+
+INTERCEPTOR(int, pthread_cond_wait, void *c, void *m) {
+  void *cond = init_cond(c);
+  SCOPED_TSAN_INTERCEPTOR(pthread_cond_wait, cond, m);
+  return cond_wait(thr, pc, &si, (int (*)(void *c, void *m, void *abstime))REAL(
+                                     pthread_cond_wait),
+                   cond, m, 0);
+}
+
+INTERCEPTOR(int, pthread_cond_timedwait, void *c, void *m, void *abstime) {
+  void *cond = init_cond(c);
+  SCOPED_TSAN_INTERCEPTOR(pthread_cond_timedwait, cond, m, abstime);
+  return cond_wait(thr, pc, &si, REAL(pthread_cond_timedwait), cond, m,
+                   abstime);
+}
+
+#if SANITIZER_MAC
+INTERCEPTOR(int, pthread_cond_timedwait_relative_np, void *c, void *m,
+            void *reltime) {
+  void *cond = init_cond(c);
+  SCOPED_TSAN_INTERCEPTOR(pthread_cond_timedwait_relative_np, cond, m, reltime);
+  return cond_wait(thr, pc, &si, REAL(pthread_cond_timedwait_relative_np), cond,
+                   m, reltime);
+}
+#endif
+
+INTERCEPTOR(int, pthread_cond_signal, void *c) {
+  void *cond = init_cond(c);
+  SCOPED_TSAN_INTERCEPTOR(pthread_cond_signal, cond);
+  MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), false);
+  return REAL(pthread_cond_signal)(cond);
+}
+
+INTERCEPTOR(int, pthread_cond_broadcast, void *c) {
+  void *cond = init_cond(c);
+  SCOPED_TSAN_INTERCEPTOR(pthread_cond_broadcast, cond);
+  MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), false);
+  return REAL(pthread_cond_broadcast)(cond);
+}
+
+INTERCEPTOR(int, pthread_cond_destroy, void *c) {
+  void *cond = init_cond(c);
+  SCOPED_TSAN_INTERCEPTOR(pthread_cond_destroy, cond);
+  MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), true);
+  int res = REAL(pthread_cond_destroy)(cond);
+  if (common_flags()->legacy_pthread_cond) {
+    // Free our aux cond and zero the pointer to not leave dangling pointers.
+    WRAP(free)(cond);
+    atomic_store((atomic_uintptr_t*)c, 0, memory_order_relaxed);
+  }
+  return res;
+}
+
+TSAN_INTERCEPTOR(int, pthread_mutex_init, void *m, void *a) {
+  SCOPED_TSAN_INTERCEPTOR(pthread_mutex_init, m, a);
+  int res = REAL(pthread_mutex_init)(m, a);
+  if (res == 0) {
+    u32 flagz = 0;
+    if (a) {
+      int type = 0;
+      if (REAL(pthread_mutexattr_gettype)(a, &type) == 0)
+        if (type == PTHREAD_MUTEX_RECURSIVE ||
+            type == PTHREAD_MUTEX_RECURSIVE_NP)
+          flagz |= MutexFlagWriteReentrant;
+    }
+    MutexCreate(thr, pc, (uptr)m, flagz);
+  }
+  return res;
+}
+
+TSAN_INTERCEPTOR(int, pthread_mutex_destroy, void *m) {
+  SCOPED_TSAN_INTERCEPTOR(pthread_mutex_destroy, m);
+  int res = REAL(pthread_mutex_destroy)(m);
+  if (res == 0 || res == errno_EBUSY) {
+    MutexDestroy(thr, pc, (uptr)m);
+  }
+  return res;
+}
+
+TSAN_INTERCEPTOR(int, pthread_mutex_trylock, void *m) {
+  SCOPED_TSAN_INTERCEPTOR(pthread_mutex_trylock, m);
+  int res = REAL(pthread_mutex_trylock)(m);
+  if (res == errno_EOWNERDEAD)
+    MutexRepair(thr, pc, (uptr)m);
+  if (res == 0 || res == errno_EOWNERDEAD)
+    MutexPostLock(thr, pc, (uptr)m, MutexFlagTryLock);
+  return res;
+}
+
+#if !SANITIZER_MAC
+TSAN_INTERCEPTOR(int, pthread_mutex_timedlock, void *m, void *abstime) {
+  SCOPED_TSAN_INTERCEPTOR(pthread_mutex_timedlock, m, abstime);
+  int res = REAL(pthread_mutex_timedlock)(m, abstime);
+  if (res == 0) {
+    MutexPostLock(thr, pc, (uptr)m, MutexFlagTryLock);
+  }
+  return res;
+}
+#endif
+
+#if !SANITIZER_MAC
+TSAN_INTERCEPTOR(int, pthread_spin_init, void *m, int pshared) {
+  SCOPED_TSAN_INTERCEPTOR(pthread_spin_init, m, pshared);
+  int res = REAL(pthread_spin_init)(m, pshared);
+  if (res == 0) {
+    MutexCreate(thr, pc, (uptr)m);
+  }
+  return res;
+}
+
+TSAN_INTERCEPTOR(int, pthread_spin_destroy, void *m) {
+  SCOPED_TSAN_INTERCEPTOR(pthread_spin_destroy, m);
+  int res = REAL(pthread_spin_destroy)(m);
+  if (res == 0) {
+    MutexDestroy(thr, pc, (uptr)m);
+  }
+  return res;
+}
+
+TSAN_INTERCEPTOR(int, pthread_spin_lock, void *m) {
+  SCOPED_TSAN_INTERCEPTOR(pthread_spin_lock, m);
+  MutexPreLock(thr, pc, (uptr)m);
+  int res = REAL(pthread_spin_lock)(m);
+  if (res == 0) {
+    MutexPostLock(thr, pc, (uptr)m);
+  }
+  return res;
+}
+
+TSAN_INTERCEPTOR(int, pthread_spin_trylock, void *m) {
+  SCOPED_TSAN_INTERCEPTOR(pthread_spin_trylock, m);
+  int res = REAL(pthread_spin_trylock)(m);
+  if (res == 0) {
+    MutexPostLock(thr, pc, (uptr)m, MutexFlagTryLock);
+  }
+  return res;
+}
+
+TSAN_INTERCEPTOR(int, pthread_spin_unlock, void *m) {
+  SCOPED_TSAN_INTERCEPTOR(pthread_spin_unlock, m);
+  MutexUnlock(thr, pc, (uptr)m);
+  int res = REAL(pthread_spin_unlock)(m);
+  return res;
+}
+#endif
+
+TSAN_INTERCEPTOR(int, pthread_rwlock_init, void *m, void *a) {
+  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_init, m, a);
+  int res = REAL(pthread_rwlock_init)(m, a);
+  if (res == 0) {
+    MutexCreate(thr, pc, (uptr)m);
+  }
+  return res;
+}
+
+TSAN_INTERCEPTOR(int, pthread_rwlock_destroy, void *m) {
+  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_destroy, m);
+  int res = REAL(pthread_rwlock_destroy)(m);
+  if (res == 0) {
+    MutexDestroy(thr, pc, (uptr)m);
+  }
+  return res;
+}
+
+TSAN_INTERCEPTOR(int, pthread_rwlock_rdlock, void *m) {
+  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_rdlock, m);
+  MutexPreReadLock(thr, pc, (uptr)m);
+  int res = REAL(pthread_rwlock_rdlock)(m);
+  if (res == 0) {
+    MutexPostReadLock(thr, pc, (uptr)m);
+  }
+  return res;
+}
+
+TSAN_INTERCEPTOR(int, pthread_rwlock_tryrdlock, void *m) {
+  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_tryrdlock, m);
+  int res = REAL(pthread_rwlock_tryrdlock)(m);
+  if (res == 0) {
+    MutexPostReadLock(thr, pc, (uptr)m, MutexFlagTryLock);
+  }
+  return res;
+}
+
+#if !SANITIZER_MAC
+TSAN_INTERCEPTOR(int, pthread_rwlock_timedrdlock, void *m, void *abstime) {
+  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_timedrdlock, m, abstime);
+  int res = REAL(pthread_rwlock_timedrdlock)(m, abstime);
+  if (res == 0) {
+    MutexPostReadLock(thr, pc, (uptr)m);
+  }
+  return res;
+}
+#endif
+
+TSAN_INTERCEPTOR(int, pthread_rwlock_wrlock, void *m) {
+  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_wrlock, m);
+  MutexPreLock(thr, pc, (uptr)m);
+  int res = REAL(pthread_rwlock_wrlock)(m);
+  if (res == 0) {
+    MutexPostLock(thr, pc, (uptr)m);
+  }
+  return res;
+}
+
+TSAN_INTERCEPTOR(int, pthread_rwlock_trywrlock, void *m) {
+  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_trywrlock, m);
+  int res = REAL(pthread_rwlock_trywrlock)(m);
+  if (res == 0) {
+    MutexPostLock(thr, pc, (uptr)m, MutexFlagTryLock);
+  }
+  return res;
+}
+
+#if !SANITIZER_MAC
+TSAN_INTERCEPTOR(int, pthread_rwlock_timedwrlock, void *m, void *abstime) {
+  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_timedwrlock, m, abstime);
+  int res = REAL(pthread_rwlock_timedwrlock)(m, abstime);
+  if (res == 0) {
+    MutexPostLock(thr, pc, (uptr)m, MutexFlagTryLock);
+  }
+  return res;
+}
+#endif
+
+TSAN_INTERCEPTOR(int, pthread_rwlock_unlock, void *m) {
+  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_unlock, m);
+  MutexReadOrWriteUnlock(thr, pc, (uptr)m);
+  int res = REAL(pthread_rwlock_unlock)(m);
+  return res;
+}
+
+#if !SANITIZER_MAC
+TSAN_INTERCEPTOR(int, pthread_barrier_init, void *b, void *a, unsigned count) {
+  SCOPED_TSAN_INTERCEPTOR(pthread_barrier_init, b, a, count);
+  MemoryWrite(thr, pc, (uptr)b, kSizeLog1);
+  int res = REAL(pthread_barrier_init)(b, a, count);
+  return res;
+}
+
+TSAN_INTERCEPTOR(int, pthread_barrier_destroy, void *b) {
+  SCOPED_TSAN_INTERCEPTOR(pthread_barrier_destroy, b);
+  MemoryWrite(thr, pc, (uptr)b, kSizeLog1);
+  int res = REAL(pthread_barrier_destroy)(b);
+  return res;
+}
+
+TSAN_INTERCEPTOR(int, pthread_barrier_wait, void *b) {
+  SCOPED_TSAN_INTERCEPTOR(pthread_barrier_wait, b);
+  Release(thr, pc, (uptr)b);
+  MemoryRead(thr, pc, (uptr)b, kSizeLog1);
+  int res = REAL(pthread_barrier_wait)(b);
+  MemoryRead(thr, pc, (uptr)b, kSizeLog1);
+  if (res == 0 || res == PTHREAD_BARRIER_SERIAL_THREAD) {
+    Acquire(thr, pc, (uptr)b);
+  }
+  return res;
+}
+#endif
+
+TSAN_INTERCEPTOR(int, pthread_once, void *o, void (*f)()) {
+  SCOPED_INTERCEPTOR_RAW(pthread_once, o, f);
+  if (o == 0 || f == 0)
+    return errno_EINVAL;
+  atomic_uint32_t *a;
+
+  if (SANITIZER_MAC)
+    a = static_cast<atomic_uint32_t*>((void *)((char *)o + sizeof(long_t)));
+  else if (SANITIZER_NETBSD)
+    a = static_cast<atomic_uint32_t*>
+          ((void *)((char *)o + __sanitizer::pthread_mutex_t_sz));
+  else
+    a = static_cast<atomic_uint32_t*>(o);
+
+  u32 v = atomic_load(a, memory_order_acquire);
+  if (v == 0 && atomic_compare_exchange_strong(a, &v, 1,
+                                               memory_order_relaxed)) {
+    (*f)();
+    if (!thr->in_ignored_lib)
+      Release(thr, pc, (uptr)o);
+    atomic_store(a, 2, memory_order_release);
+  } else {
+    while (v != 2) {
+      internal_sched_yield();
+      v = atomic_load(a, memory_order_acquire);
+    }
+    if (!thr->in_ignored_lib)
+      Acquire(thr, pc, (uptr)o);
+  }
+  return 0;
+}
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+TSAN_INTERCEPTOR(int, __fxstat, int version, int fd, void *buf) {
+  SCOPED_TSAN_INTERCEPTOR(__fxstat, version, fd, buf);
+  if (fd > 0)
+    FdAccess(thr, pc, fd);
+  return REAL(__fxstat)(version, fd, buf);
+}
+#define TSAN_MAYBE_INTERCEPT___FXSTAT TSAN_INTERCEPT(__fxstat)
+#else
+#define TSAN_MAYBE_INTERCEPT___FXSTAT
+#endif
+
+TSAN_INTERCEPTOR(int, fstat, int fd, void *buf) {
+#if SANITIZER_FREEBSD || SANITIZER_MAC || SANITIZER_ANDROID || SANITIZER_NETBSD
+  SCOPED_TSAN_INTERCEPTOR(fstat, fd, buf);
+  if (fd > 0)
+    FdAccess(thr, pc, fd);
+  return REAL(fstat)(fd, buf);
+#else
+  SCOPED_TSAN_INTERCEPTOR(__fxstat, 0, fd, buf);
+  if (fd > 0)
+    FdAccess(thr, pc, fd);
+  return REAL(__fxstat)(0, fd, buf);
+#endif
+}
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+TSAN_INTERCEPTOR(int, __fxstat64, int version, int fd, void *buf) {
+  SCOPED_TSAN_INTERCEPTOR(__fxstat64, version, fd, buf);
+  if (fd > 0)
+    FdAccess(thr, pc, fd);
+  return REAL(__fxstat64)(version, fd, buf);
+}
+#define TSAN_MAYBE_INTERCEPT___FXSTAT64 TSAN_INTERCEPT(__fxstat64)
+#else
+#define TSAN_MAYBE_INTERCEPT___FXSTAT64
+#endif
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+TSAN_INTERCEPTOR(int, fstat64, int fd, void *buf) {
+  SCOPED_TSAN_INTERCEPTOR(__fxstat64, 0, fd, buf);
+  if (fd > 0)
+    FdAccess(thr, pc, fd);
+  return REAL(__fxstat64)(0, fd, buf);
+}
+#define TSAN_MAYBE_INTERCEPT_FSTAT64 TSAN_INTERCEPT(fstat64)
+#else
+#define TSAN_MAYBE_INTERCEPT_FSTAT64
+#endif
+
+TSAN_INTERCEPTOR(int, open, const char *name, int flags, int mode) {
+  SCOPED_TSAN_INTERCEPTOR(open, name, flags, mode);
+  READ_STRING(thr, pc, name, 0);
+  int fd = REAL(open)(name, flags, mode);
+  if (fd >= 0)
+    FdFileCreate(thr, pc, fd);
+  return fd;
+}
+
+#if SANITIZER_LINUX
+TSAN_INTERCEPTOR(int, open64, const char *name, int flags, int mode) {
+  SCOPED_TSAN_INTERCEPTOR(open64, name, flags, mode);
+  READ_STRING(thr, pc, name, 0);
+  int fd = REAL(open64)(name, flags, mode);
+  if (fd >= 0)
+    FdFileCreate(thr, pc, fd);
+  return fd;
+}
+#define TSAN_MAYBE_INTERCEPT_OPEN64 TSAN_INTERCEPT(open64)
+#else
+#define TSAN_MAYBE_INTERCEPT_OPEN64
+#endif
+
+TSAN_INTERCEPTOR(int, creat, const char *name, int mode) {
+  SCOPED_TSAN_INTERCEPTOR(creat, name, mode);
+  READ_STRING(thr, pc, name, 0);
+  int fd = REAL(creat)(name, mode);
+  if (fd >= 0)
+    FdFileCreate(thr, pc, fd);
+  return fd;
+}
+
+#if SANITIZER_LINUX
+TSAN_INTERCEPTOR(int, creat64, const char *name, int mode) {
+  SCOPED_TSAN_INTERCEPTOR(creat64, name, mode);
+  READ_STRING(thr, pc, name, 0);
+  int fd = REAL(creat64)(name, mode);
+  if (fd >= 0)
+    FdFileCreate(thr, pc, fd);
+  return fd;
+}
+#define TSAN_MAYBE_INTERCEPT_CREAT64 TSAN_INTERCEPT(creat64)
+#else
+#define TSAN_MAYBE_INTERCEPT_CREAT64
+#endif
+
+TSAN_INTERCEPTOR(int, dup, int oldfd) {
+  SCOPED_TSAN_INTERCEPTOR(dup, oldfd);
+  int newfd = REAL(dup)(oldfd);
+  if (oldfd >= 0 && newfd >= 0 && newfd != oldfd)
+    FdDup(thr, pc, oldfd, newfd, true);
+  return newfd;
+}
+
+TSAN_INTERCEPTOR(int, dup2, int oldfd, int newfd) {
+  SCOPED_TSAN_INTERCEPTOR(dup2, oldfd, newfd);
+  int newfd2 = REAL(dup2)(oldfd, newfd);
+  if (oldfd >= 0 && newfd2 >= 0 && newfd2 != oldfd)
+    FdDup(thr, pc, oldfd, newfd2, false);
+  return newfd2;
+}
+
+#if !SANITIZER_MAC
+TSAN_INTERCEPTOR(int, dup3, int oldfd, int newfd, int flags) {
+  SCOPED_TSAN_INTERCEPTOR(dup3, oldfd, newfd, flags);
+  int newfd2 = REAL(dup3)(oldfd, newfd, flags);
+  if (oldfd >= 0 && newfd2 >= 0 && newfd2 != oldfd)
+    FdDup(thr, pc, oldfd, newfd2, false);
+  return newfd2;
+}
+#endif
+
+#if SANITIZER_LINUX
+TSAN_INTERCEPTOR(int, eventfd, unsigned initval, int flags) {
+  SCOPED_TSAN_INTERCEPTOR(eventfd, initval, flags);
+  int fd = REAL(eventfd)(initval, flags);
+  if (fd >= 0)
+    FdEventCreate(thr, pc, fd);
+  return fd;
+}
+#define TSAN_MAYBE_INTERCEPT_EVENTFD TSAN_INTERCEPT(eventfd)
+#else
+#define TSAN_MAYBE_INTERCEPT_EVENTFD
+#endif
+
+#if SANITIZER_LINUX
+TSAN_INTERCEPTOR(int, signalfd, int fd, void *mask, int flags) {
+  SCOPED_TSAN_INTERCEPTOR(signalfd, fd, mask, flags);
+  if (fd >= 0)
+    FdClose(thr, pc, fd);
+  fd = REAL(signalfd)(fd, mask, flags);
+  if (fd >= 0)
+    FdSignalCreate(thr, pc, fd);
+  return fd;
+}
+#define TSAN_MAYBE_INTERCEPT_SIGNALFD TSAN_INTERCEPT(signalfd)
+#else
+#define TSAN_MAYBE_INTERCEPT_SIGNALFD
+#endif
+
+#if SANITIZER_LINUX
+TSAN_INTERCEPTOR(int, inotify_init, int fake) {
+  SCOPED_TSAN_INTERCEPTOR(inotify_init, fake);
+  int fd = REAL(inotify_init)(fake);
+  if (fd >= 0)
+    FdInotifyCreate(thr, pc, fd);
+  return fd;
+}
+#define TSAN_MAYBE_INTERCEPT_INOTIFY_INIT TSAN_INTERCEPT(inotify_init)
+#else
+#define TSAN_MAYBE_INTERCEPT_INOTIFY_INIT
+#endif
+
+#if SANITIZER_LINUX
+TSAN_INTERCEPTOR(int, inotify_init1, int flags) {
+  SCOPED_TSAN_INTERCEPTOR(inotify_init1, flags);
+  int fd = REAL(inotify_init1)(flags);
+  if (fd >= 0)
+    FdInotifyCreate(thr, pc, fd);
+  return fd;
+}
+#define TSAN_MAYBE_INTERCEPT_INOTIFY_INIT1 TSAN_INTERCEPT(inotify_init1)
+#else
+#define TSAN_MAYBE_INTERCEPT_INOTIFY_INIT1
+#endif
+
+TSAN_INTERCEPTOR(int, socket, int domain, int type, int protocol) {
+  SCOPED_TSAN_INTERCEPTOR(socket, domain, type, protocol);
+  int fd = REAL(socket)(domain, type, protocol);
+  if (fd >= 0)
+    FdSocketCreate(thr, pc, fd);
+  return fd;
+}
+
+TSAN_INTERCEPTOR(int, socketpair, int domain, int type, int protocol, int *fd) {
+  SCOPED_TSAN_INTERCEPTOR(socketpair, domain, type, protocol, fd);
+  int res = REAL(socketpair)(domain, type, protocol, fd);
+  if (res == 0 && fd[0] >= 0 && fd[1] >= 0)
+    FdPipeCreate(thr, pc, fd[0], fd[1]);
+  return res;
+}
+
+TSAN_INTERCEPTOR(int, connect, int fd, void *addr, unsigned addrlen) {
+  SCOPED_TSAN_INTERCEPTOR(connect, fd, addr, addrlen);
+  FdSocketConnecting(thr, pc, fd);
+  int res = REAL(connect)(fd, addr, addrlen);
+  if (res == 0 && fd >= 0)
+    FdSocketConnect(thr, pc, fd);
+  return res;
+}
+
+TSAN_INTERCEPTOR(int, bind, int fd, void *addr, unsigned addrlen) {
+  SCOPED_TSAN_INTERCEPTOR(bind, fd, addr, addrlen);
+  int res = REAL(bind)(fd, addr, addrlen);
+  if (fd > 0 && res == 0)
+    FdAccess(thr, pc, fd);
+  return res;
+}
+
+TSAN_INTERCEPTOR(int, listen, int fd, int backlog) {
+  SCOPED_TSAN_INTERCEPTOR(listen, fd, backlog);
+  int res = REAL(listen)(fd, backlog);
+  if (fd > 0 && res == 0)
+    FdAccess(thr, pc, fd);
+  return res;
+}
+
+TSAN_INTERCEPTOR(int, close, int fd) {
+  SCOPED_TSAN_INTERCEPTOR(close, fd);
+  if (fd >= 0)
+    FdClose(thr, pc, fd);
+  return REAL(close)(fd);
+}
+
+#if SANITIZER_LINUX
+TSAN_INTERCEPTOR(int, __close, int fd) {
+  SCOPED_TSAN_INTERCEPTOR(__close, fd);
+  if (fd >= 0)
+    FdClose(thr, pc, fd);
+  return REAL(__close)(fd);
+}
+#define TSAN_MAYBE_INTERCEPT___CLOSE TSAN_INTERCEPT(__close)
+#else
+#define TSAN_MAYBE_INTERCEPT___CLOSE
+#endif
+
+// glibc guts
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+TSAN_INTERCEPTOR(void, __res_iclose, void *state, bool free_addr) {
+  SCOPED_TSAN_INTERCEPTOR(__res_iclose, state, free_addr);
+  int fds[64];
+  int cnt = ExtractResolvFDs(state, fds, ARRAY_SIZE(fds));
+  for (int i = 0; i < cnt; i++) {
+    if (fds[i] > 0)
+      FdClose(thr, pc, fds[i]);
+  }
+  REAL(__res_iclose)(state, free_addr);
+}
+#define TSAN_MAYBE_INTERCEPT___RES_ICLOSE TSAN_INTERCEPT(__res_iclose)
+#else
+#define TSAN_MAYBE_INTERCEPT___RES_ICLOSE
+#endif
+
+TSAN_INTERCEPTOR(int, pipe, int *pipefd) {
+  SCOPED_TSAN_INTERCEPTOR(pipe, pipefd);
+  int res = REAL(pipe)(pipefd);
+  if (res == 0 && pipefd[0] >= 0 && pipefd[1] >= 0)
+    FdPipeCreate(thr, pc, pipefd[0], pipefd[1]);
+  return res;
+}
+
+#if !SANITIZER_MAC
+TSAN_INTERCEPTOR(int, pipe2, int *pipefd, int flags) {
+  SCOPED_TSAN_INTERCEPTOR(pipe2, pipefd, flags);
+  int res = REAL(pipe2)(pipefd, flags);
+  if (res == 0 && pipefd[0] >= 0 && pipefd[1] >= 0)
+    FdPipeCreate(thr, pc, pipefd[0], pipefd[1]);
+  return res;
+}
+#endif
+
+TSAN_INTERCEPTOR(int, unlink, char *path) {
+  SCOPED_TSAN_INTERCEPTOR(unlink, path);
+  Release(thr, pc, File2addr(path));
+  int res = REAL(unlink)(path);
+  return res;
+}
+
+TSAN_INTERCEPTOR(void*, tmpfile, int fake) {
+  SCOPED_TSAN_INTERCEPTOR(tmpfile, fake);
+  void *res = REAL(tmpfile)(fake);
+  if (res) {
+    int fd = fileno_unlocked(res);
+    if (fd >= 0)
+      FdFileCreate(thr, pc, fd);
+  }
+  return res;
+}
+
+#if SANITIZER_LINUX
+TSAN_INTERCEPTOR(void*, tmpfile64, int fake) {
+  SCOPED_TSAN_INTERCEPTOR(tmpfile64, fake);
+  void *res = REAL(tmpfile64)(fake);
+  if (res) {
+    int fd = fileno_unlocked(res);
+    if (fd >= 0)
+      FdFileCreate(thr, pc, fd);
+  }
+  return res;
+}
+#define TSAN_MAYBE_INTERCEPT_TMPFILE64 TSAN_INTERCEPT(tmpfile64)
+#else
+#define TSAN_MAYBE_INTERCEPT_TMPFILE64
+#endif
+
+static void FlushStreams() {
+  // Flushing all the streams here may freeze the process if a child thread is
+  // performing file stream operations at the same time.
+  REAL(fflush)(stdout);
+  REAL(fflush)(stderr);
+}
+
+TSAN_INTERCEPTOR(void, abort, int fake) {
+  SCOPED_TSAN_INTERCEPTOR(abort, fake);
+  FlushStreams();
+  REAL(abort)(fake);
+}
+
+TSAN_INTERCEPTOR(int, rmdir, char *path) {
+  SCOPED_TSAN_INTERCEPTOR(rmdir, path);
+  Release(thr, pc, Dir2addr(path));
+  int res = REAL(rmdir)(path);
+  return res;
+}
+
+TSAN_INTERCEPTOR(int, closedir, void *dirp) {
+  SCOPED_TSAN_INTERCEPTOR(closedir, dirp);
+  if (dirp) {
+    int fd = dirfd(dirp);
+    FdClose(thr, pc, fd);
+  }
+  return REAL(closedir)(dirp);
+}
+
+#if SANITIZER_LINUX
+TSAN_INTERCEPTOR(int, epoll_create, int size) {
+  SCOPED_TSAN_INTERCEPTOR(epoll_create, size);
+  int fd = REAL(epoll_create)(size);
+  if (fd >= 0)
+    FdPollCreate(thr, pc, fd);
+  return fd;
+}
+
+TSAN_INTERCEPTOR(int, epoll_create1, int flags) {
+  SCOPED_TSAN_INTERCEPTOR(epoll_create1, flags);
+  int fd = REAL(epoll_create1)(flags);
+  if (fd >= 0)
+    FdPollCreate(thr, pc, fd);
+  return fd;
+}
+
+TSAN_INTERCEPTOR(int, epoll_ctl, int epfd, int op, int fd, void *ev) {
+  SCOPED_TSAN_INTERCEPTOR(epoll_ctl, epfd, op, fd, ev);
+  if (epfd >= 0)
+    FdAccess(thr, pc, epfd);
+  if (epfd >= 0 && fd >= 0)
+    FdAccess(thr, pc, fd);
+  if (op == EPOLL_CTL_ADD && epfd >= 0)
+    FdRelease(thr, pc, epfd);
+  int res = REAL(epoll_ctl)(epfd, op, fd, ev);
+  return res;
+}
+
+TSAN_INTERCEPTOR(int, epoll_wait, int epfd, void *ev, int cnt, int timeout) {
+  SCOPED_TSAN_INTERCEPTOR(epoll_wait, epfd, ev, cnt, timeout);
+  if (epfd >= 0)
+    FdAccess(thr, pc, epfd);
+  int res = BLOCK_REAL(epoll_wait)(epfd, ev, cnt, timeout);
+  if (res > 0 && epfd >= 0)
+    FdAcquire(thr, pc, epfd);
+  return res;
+}
+
+TSAN_INTERCEPTOR(int, epoll_pwait, int epfd, void *ev, int cnt, int timeout,
+                 void *sigmask) {
+  SCOPED_TSAN_INTERCEPTOR(epoll_pwait, epfd, ev, cnt, timeout, sigmask);
+  if (epfd >= 0)
+    FdAccess(thr, pc, epfd);
+  int res = BLOCK_REAL(epoll_pwait)(epfd, ev, cnt, timeout, sigmask);
+  if (res > 0 && epfd >= 0)
+    FdAcquire(thr, pc, epfd);
+  return res;
+}
+
+#define TSAN_MAYBE_INTERCEPT_EPOLL \
+    TSAN_INTERCEPT(epoll_create); \
+    TSAN_INTERCEPT(epoll_create1); \
+    TSAN_INTERCEPT(epoll_ctl); \
+    TSAN_INTERCEPT(epoll_wait); \
+    TSAN_INTERCEPT(epoll_pwait)
+#else
+#define TSAN_MAYBE_INTERCEPT_EPOLL
+#endif
+
+// The following functions are intercepted merely to process pending signals.
+// If program blocks signal X, we must deliver the signal before the function
+// returns. Similarly, if program unblocks a signal (or returns from sigsuspend)
+// it's better to deliver the signal straight away.
+TSAN_INTERCEPTOR(int, sigsuspend, const __sanitizer_sigset_t *mask) {
+  SCOPED_TSAN_INTERCEPTOR(sigsuspend, mask);
+  return REAL(sigsuspend)(mask);
+}
+
+TSAN_INTERCEPTOR(int, sigblock, int mask) {
+  SCOPED_TSAN_INTERCEPTOR(sigblock, mask);
+  return REAL(sigblock)(mask);
+}
+
+TSAN_INTERCEPTOR(int, sigsetmask, int mask) {
+  SCOPED_TSAN_INTERCEPTOR(sigsetmask, mask);
+  return REAL(sigsetmask)(mask);
+}
+
+TSAN_INTERCEPTOR(int, pthread_sigmask, int how, const __sanitizer_sigset_t *set,
+    __sanitizer_sigset_t *oldset) {
+  SCOPED_TSAN_INTERCEPTOR(pthread_sigmask, how, set, oldset);
+  return REAL(pthread_sigmask)(how, set, oldset);
+}
+
+namespace __tsan {
+
+static void CallUserSignalHandler(ThreadState *thr, bool sync, bool acquire,
+                                  bool sigact, int sig,
+                                  __sanitizer_siginfo *info, void *uctx) {
+  __sanitizer_sigaction *sigactions = interceptor_ctx()->sigactions;
+  if (acquire)
+    Acquire(thr, 0, (uptr)&sigactions[sig]);
+  // Signals are generally asynchronous, so if we receive a signals when
+  // ignores are enabled we should disable ignores. This is critical for sync
+  // and interceptors, because otherwise we can miss syncronization and report
+  // false races.
+  int ignore_reads_and_writes = thr->ignore_reads_and_writes;
+  int ignore_interceptors = thr->ignore_interceptors;
+  int ignore_sync = thr->ignore_sync;
+  if (!ctx->after_multithreaded_fork) {
+    thr->ignore_reads_and_writes = 0;
+    thr->fast_state.ClearIgnoreBit();
+    thr->ignore_interceptors = 0;
+    thr->ignore_sync = 0;
+  }
+  // Ensure that the handler does not spoil errno.
+  const int saved_errno = errno;
+  errno = 99;
+  // This code races with sigaction. Be careful to not read sa_sigaction twice.
+  // Also need to remember pc for reporting before the call,
+  // because the handler can reset it.
+  volatile uptr pc =
+      sigact ? (uptr)sigactions[sig].sigaction : (uptr)sigactions[sig].handler;
+  if (pc != sig_dfl && pc != sig_ign) {
+    if (sigact)
+      ((__sanitizer_sigactionhandler_ptr)pc)(sig, info, uctx);
+    else
+      ((__sanitizer_sighandler_ptr)pc)(sig);
+  }
+  if (!ctx->after_multithreaded_fork) {
+    thr->ignore_reads_and_writes = ignore_reads_and_writes;
+    if (ignore_reads_and_writes)
+      thr->fast_state.SetIgnoreBit();
+    thr->ignore_interceptors = ignore_interceptors;
+    thr->ignore_sync = ignore_sync;
+  }
+  // We do not detect errno spoiling for SIGTERM,
+  // because some SIGTERM handlers do spoil errno but reraise SIGTERM,
+  // tsan reports false positive in such case.
+  // It's difficult to properly detect this situation (reraise),
+  // because in async signal processing case (when handler is called directly
+  // from rtl_generic_sighandler) we have not yet received the reraised
+  // signal; and it looks too fragile to intercept all ways to reraise a signal.
+  if (flags()->report_bugs && !sync && sig != SIGTERM && errno != 99) {
+    VarSizeStackTrace stack;
+    // StackTrace::GetNestInstructionPc(pc) is used because return address is
+    // expected, OutputReport() will undo this.
+    ObtainCurrentStack(thr, StackTrace::GetNextInstructionPc(pc), &stack);
+    ThreadRegistryLock l(ctx->thread_registry);
+    ScopedReport rep(ReportTypeErrnoInSignal);
+    if (!IsFiredSuppression(ctx, ReportTypeErrnoInSignal, stack)) {
+      rep.AddStack(stack, true);
+      OutputReport(thr, rep);
+    }
+  }
+  errno = saved_errno;
+}
+
+void ProcessPendingSignals(ThreadState *thr) {
+  ThreadSignalContext *sctx = SigCtx(thr);
+  if (sctx == 0 ||
+      atomic_load(&sctx->have_pending_signals, memory_order_relaxed) == 0)
+    return;
+  atomic_store(&sctx->have_pending_signals, 0, memory_order_relaxed);
+  atomic_fetch_add(&thr->in_signal_handler, 1, memory_order_relaxed);
+  internal_sigfillset(&sctx->emptyset);
+  int res = REAL(pthread_sigmask)(SIG_SETMASK, &sctx->emptyset, &sctx->oldset);
+  CHECK_EQ(res, 0);
+  for (int sig = 0; sig < kSigCount; sig++) {
+    SignalDesc *signal = &sctx->pending_signals[sig];
+    if (signal->armed) {
+      signal->armed = false;
+      CallUserSignalHandler(thr, false, true, signal->sigaction, sig,
+          &signal->siginfo, &signal->ctx);
+    }
+  }
+  res = REAL(pthread_sigmask)(SIG_SETMASK, &sctx->oldset, 0);
+  CHECK_EQ(res, 0);
+  atomic_fetch_add(&thr->in_signal_handler, -1, memory_order_relaxed);
+}
+
+}  // namespace __tsan
+
+static bool is_sync_signal(ThreadSignalContext *sctx, int sig) {
+  return sig == SIGSEGV || sig == SIGBUS || sig == SIGILL || sig == SIGTRAP ||
+         sig == SIGABRT || sig == SIGFPE || sig == SIGPIPE || sig == SIGSYS ||
+         // If we are sending signal to ourselves, we must process it now.
+         (sctx && sig == sctx->int_signal_send);
+}
+
+void ALWAYS_INLINE rtl_generic_sighandler(bool sigact, int sig,
+                                          __sanitizer_siginfo *info,
+                                          void *ctx) {
+  cur_thread_init();
+  ThreadState *thr = cur_thread();
+  ThreadSignalContext *sctx = SigCtx(thr);
+  if (sig < 0 || sig >= kSigCount) {
+    VPrintf(1, "ThreadSanitizer: ignoring signal %d\n", sig);
+    return;
+  }
+  // Don't mess with synchronous signals.
+  const bool sync = is_sync_signal(sctx, sig);
+  if (sync ||
+      // If we are in blocking function, we can safely process it now
+      // (but check if we are in a recursive interceptor,
+      // i.e. pthread_join()->munmap()).
+      (sctx && atomic_load(&sctx->in_blocking_func, memory_order_relaxed))) {
+    atomic_fetch_add(&thr->in_signal_handler, 1, memory_order_relaxed);
+    if (sctx && atomic_load(&sctx->in_blocking_func, memory_order_relaxed)) {
+      atomic_store(&sctx->in_blocking_func, 0, memory_order_relaxed);
+      CallUserSignalHandler(thr, sync, true, sigact, sig, info, ctx);
+      atomic_store(&sctx->in_blocking_func, 1, memory_order_relaxed);
+    } else {
+      // Be very conservative with when we do acquire in this case.
+      // It's unsafe to do acquire in async handlers, because ThreadState
+      // can be in inconsistent state.
+      // SIGSYS looks relatively safe -- it's synchronous and can actually
+      // need some global state.
+      bool acq = (sig == SIGSYS);
+      CallUserSignalHandler(thr, sync, acq, sigact, sig, info, ctx);
+    }
+    atomic_fetch_add(&thr->in_signal_handler, -1, memory_order_relaxed);
+    return;
+  }
+
+  if (sctx == 0)
+    return;
+  SignalDesc *signal = &sctx->pending_signals[sig];
+  if (signal->armed == false) {
+    signal->armed = true;
+    signal->sigaction = sigact;
+    if (info)
+      internal_memcpy(&signal->siginfo, info, sizeof(*info));
+    if (ctx)
+      internal_memcpy(&signal->ctx, ctx, sizeof(signal->ctx));
+    atomic_store(&sctx->have_pending_signals, 1, memory_order_relaxed);
+  }
+}
+
+static void rtl_sighandler(int sig) {
+  rtl_generic_sighandler(false, sig, 0, 0);
+}
+
+static void rtl_sigaction(int sig, __sanitizer_siginfo *info, void *ctx) {
+  rtl_generic_sighandler(true, sig, info, ctx);
+}
+
+TSAN_INTERCEPTOR(int, raise, int sig) {
+  SCOPED_TSAN_INTERCEPTOR(raise, sig);
+  ThreadSignalContext *sctx = SigCtx(thr);
+  CHECK_NE(sctx, 0);
+  int prev = sctx->int_signal_send;
+  sctx->int_signal_send = sig;
+  int res = REAL(raise)(sig);
+  CHECK_EQ(sctx->int_signal_send, sig);
+  sctx->int_signal_send = prev;
+  return res;
+}
+
+TSAN_INTERCEPTOR(int, kill, int pid, int sig) {
+  SCOPED_TSAN_INTERCEPTOR(kill, pid, sig);
+  ThreadSignalContext *sctx = SigCtx(thr);
+  CHECK_NE(sctx, 0);
+  int prev = sctx->int_signal_send;
+  if (pid == (int)internal_getpid()) {
+    sctx->int_signal_send = sig;
+  }
+  int res = REAL(kill)(pid, sig);
+  if (pid == (int)internal_getpid()) {
+    CHECK_EQ(sctx->int_signal_send, sig);
+    sctx->int_signal_send = prev;
+  }
+  return res;
+}
+
+TSAN_INTERCEPTOR(int, pthread_kill, void *tid, int sig) {
+  SCOPED_TSAN_INTERCEPTOR(pthread_kill, tid, sig);
+  ThreadSignalContext *sctx = SigCtx(thr);
+  CHECK_NE(sctx, 0);
+  int prev = sctx->int_signal_send;
+  if (tid == pthread_self()) {
+    sctx->int_signal_send = sig;
+  }
+  int res = REAL(pthread_kill)(tid, sig);
+  if (tid == pthread_self()) {
+    CHECK_EQ(sctx->int_signal_send, sig);
+    sctx->int_signal_send = prev;
+  }
+  return res;
+}
+
+TSAN_INTERCEPTOR(int, gettimeofday, void *tv, void *tz) {
+  SCOPED_TSAN_INTERCEPTOR(gettimeofday, tv, tz);
+  // It's intercepted merely to process pending signals.
+  return REAL(gettimeofday)(tv, tz);
+}
+
+TSAN_INTERCEPTOR(int, getaddrinfo, void *node, void *service,
+    void *hints, void *rv) {
+  SCOPED_TSAN_INTERCEPTOR(getaddrinfo, node, service, hints, rv);
+  // We miss atomic synchronization in getaddrinfo,
+  // and can report false race between malloc and free
+  // inside of getaddrinfo. So ignore memory accesses.
+  ThreadIgnoreBegin(thr, pc);
+  int res = REAL(getaddrinfo)(node, service, hints, rv);
+  ThreadIgnoreEnd(thr, pc);
+  return res;
+}
+
+TSAN_INTERCEPTOR(int, fork, int fake) {
+  if (in_symbolizer())
+    return REAL(fork)(fake);
+  SCOPED_INTERCEPTOR_RAW(fork, fake);
+  ForkBefore(thr, pc);
+  int pid;
+  {
+    // On OS X, REAL(fork) can call intercepted functions (OSSpinLockLock), and
+    // we'll assert in CheckNoLocks() unless we ignore interceptors.
+    ScopedIgnoreInterceptors ignore;
+    pid = REAL(fork)(fake);
+  }
+  if (pid == 0) {
+    // child
+    ForkChildAfter(thr, pc);
+    FdOnFork(thr, pc);
+  } else if (pid > 0) {
+    // parent
+    ForkParentAfter(thr, pc);
+  } else {
+    // error
+    ForkParentAfter(thr, pc);
+  }
+  return pid;
+}
+
+TSAN_INTERCEPTOR(int, vfork, int fake) {
+  // Some programs (e.g. openjdk) call close for all file descriptors
+  // in the child process. Under tsan it leads to false positives, because
+  // address space is shared, so the parent process also thinks that
+  // the descriptors are closed (while they are actually not).
+  // This leads to false positives due to missed synchronization.
+  // Strictly saying this is undefined behavior, because vfork child is not
+  // allowed to call any functions other than exec/exit. But this is what
+  // openjdk does, so we want to handle it.
+  // We could disable interceptors in the child process. But it's not possible
+  // to simply intercept and wrap vfork, because vfork child is not allowed
+  // to return from the function that calls vfork, and that's exactly what
+  // we would do. So this would require some assembly trickery as well.
+  // Instead we simply turn vfork into fork.
+  return WRAP(fork)(fake);
+}
+
+#if !SANITIZER_MAC && !SANITIZER_ANDROID
+typedef int (*dl_iterate_phdr_cb_t)(__sanitizer_dl_phdr_info *info, SIZE_T size,
+                                    void *data);
+struct dl_iterate_phdr_data {
+  ThreadState *thr;
+  uptr pc;
+  dl_iterate_phdr_cb_t cb;
+  void *data;
+};
+
+static bool IsAppNotRodata(uptr addr) {
+  return IsAppMem(addr) && *(u64*)MemToShadow(addr) != kShadowRodata;
+}
+
+static int dl_iterate_phdr_cb(__sanitizer_dl_phdr_info *info, SIZE_T size,
+                              void *data) {
+  dl_iterate_phdr_data *cbdata = (dl_iterate_phdr_data *)data;
+  // dlopen/dlclose allocate/free dynamic-linker-internal memory, which is later
+  // accessible in dl_iterate_phdr callback. But we don't see synchronization
+  // inside of dynamic linker, so we "unpoison" it here in order to not
+  // produce false reports. Ignoring malloc/free in dlopen/dlclose is not enough
+  // because some libc functions call __libc_dlopen.
+  if (info && IsAppNotRodata((uptr)info->dlpi_name))
+    MemoryResetRange(cbdata->thr, cbdata->pc, (uptr)info->dlpi_name,
+                     internal_strlen(info->dlpi_name));
+  int res = cbdata->cb(info, size, cbdata->data);
+  // Perform the check one more time in case info->dlpi_name was overwritten
+  // by user callback.
+  if (info && IsAppNotRodata((uptr)info->dlpi_name))
+    MemoryResetRange(cbdata->thr, cbdata->pc, (uptr)info->dlpi_name,
+                     internal_strlen(info->dlpi_name));
+  return res;
+}
+
+TSAN_INTERCEPTOR(int, dl_iterate_phdr, dl_iterate_phdr_cb_t cb, void *data) {
+  SCOPED_TSAN_INTERCEPTOR(dl_iterate_phdr, cb, data);
+  dl_iterate_phdr_data cbdata;
+  cbdata.thr = thr;
+  cbdata.pc = pc;
+  cbdata.cb = cb;
+  cbdata.data = data;
+  int res = REAL(dl_iterate_phdr)(dl_iterate_phdr_cb, &cbdata);
+  return res;
+}
+#endif
+
+static int OnExit(ThreadState *thr) {
+  int status = Finalize(thr);
+  FlushStreams();
+  return status;
+}
+
+struct TsanInterceptorContext {
+  ThreadState *thr;
+  const uptr caller_pc;
+  const uptr pc;
+};
+
+#if !SANITIZER_MAC
+static void HandleRecvmsg(ThreadState *thr, uptr pc,
+    __sanitizer_msghdr *msg) {
+  int fds[64];
+  int cnt = ExtractRecvmsgFDs(msg, fds, ARRAY_SIZE(fds));
+  for (int i = 0; i < cnt; i++)
+    FdEventCreate(thr, pc, fds[i]);
+}
+#endif
+
+#include "sanitizer_common/sanitizer_platform_interceptors.h"
+// Causes interceptor recursion (getaddrinfo() and fopen())
+#undef SANITIZER_INTERCEPT_GETADDRINFO
+// We define our own.
+#if SANITIZER_INTERCEPT_TLS_GET_ADDR
+#define NEED_TLS_GET_ADDR
+#endif
+#undef SANITIZER_INTERCEPT_TLS_GET_ADDR
+#undef SANITIZER_INTERCEPT_PTHREAD_SIGMASK
+
+#define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name)
+#define COMMON_INTERCEPT_FUNCTION_VER(name, ver)                          \
+  INTERCEPT_FUNCTION_VER(name, ver)
+
+#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size)                    \
+  MemoryAccessRange(((TsanInterceptorContext *)ctx)->thr,                 \
+                    ((TsanInterceptorContext *)ctx)->pc, (uptr)ptr, size, \
+                    true)
+
+#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size)                       \
+  MemoryAccessRange(((TsanInterceptorContext *) ctx)->thr,                  \
+                    ((TsanInterceptorContext *) ctx)->pc, (uptr) ptr, size, \
+                    false)
+
+#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...)      \
+  SCOPED_TSAN_INTERCEPTOR(func, __VA_ARGS__);         \
+  TsanInterceptorContext _ctx = {thr, caller_pc, pc}; \
+  ctx = (void *)&_ctx;                                \
+  (void) ctx;
+
+#define COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, func, ...) \
+  SCOPED_INTERCEPTOR_RAW(func, __VA_ARGS__);              \
+  TsanInterceptorContext _ctx = {thr, caller_pc, pc};     \
+  ctx = (void *)&_ctx;                                    \
+  (void) ctx;
+
+#define COMMON_INTERCEPTOR_FILE_OPEN(ctx, file, path) \
+  if (path)                                           \
+    Acquire(thr, pc, File2addr(path));                \
+  if (file) {                                         \
+    int fd = fileno_unlocked(file);                   \
+    if (fd >= 0) FdFileCreate(thr, pc, fd);           \
+  }
+
+#define COMMON_INTERCEPTOR_FILE_CLOSE(ctx, file) \
+  if (file) {                                    \
+    int fd = fileno_unlocked(file);              \
+    if (fd >= 0) FdClose(thr, pc, fd);           \
+  }
+
+#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) \
+  libignore()->OnLibraryLoaded(filename)
+
+#define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() \
+  libignore()->OnLibraryUnloaded()
+
+#define COMMON_INTERCEPTOR_ACQUIRE(ctx, u) \
+  Acquire(((TsanInterceptorContext *) ctx)->thr, pc, u)
+
+#define COMMON_INTERCEPTOR_RELEASE(ctx, u) \
+  Release(((TsanInterceptorContext *) ctx)->thr, pc, u)
+
+#define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \
+  Acquire(((TsanInterceptorContext *) ctx)->thr, pc, Dir2addr(path))
+
+#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
+  FdAcquire(((TsanInterceptorContext *) ctx)->thr, pc, fd)
+
+#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
+  FdRelease(((TsanInterceptorContext *) ctx)->thr, pc, fd)
+
+#define COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd) \
+  FdAccess(((TsanInterceptorContext *) ctx)->thr, pc, fd)
+
+#define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
+  FdSocketAccept(((TsanInterceptorContext *) ctx)->thr, pc, fd, newfd)
+
+#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \
+  ThreadSetName(((TsanInterceptorContext *) ctx)->thr, name)
+
+#define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
+  __tsan::ctx->thread_registry->SetThreadNameByUserId(thread, name)
+
+#define COMMON_INTERCEPTOR_BLOCK_REAL(name) BLOCK_REAL(name)
+
+#define COMMON_INTERCEPTOR_ON_EXIT(ctx) \
+  OnExit(((TsanInterceptorContext *) ctx)->thr)
+
+#define COMMON_INTERCEPTOR_MUTEX_PRE_LOCK(ctx, m) \
+  MutexPreLock(((TsanInterceptorContext *)ctx)->thr, \
+            ((TsanInterceptorContext *)ctx)->pc, (uptr)m)
+
+#define COMMON_INTERCEPTOR_MUTEX_POST_LOCK(ctx, m) \
+  MutexPostLock(((TsanInterceptorContext *)ctx)->thr, \
+            ((TsanInterceptorContext *)ctx)->pc, (uptr)m)
+
+#define COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m) \
+  MutexUnlock(((TsanInterceptorContext *)ctx)->thr, \
+            ((TsanInterceptorContext *)ctx)->pc, (uptr)m)
+
+#define COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m) \
+  MutexRepair(((TsanInterceptorContext *)ctx)->thr, \
+            ((TsanInterceptorContext *)ctx)->pc, (uptr)m)
+
+#define COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m) \
+  MutexInvalidAccess(((TsanInterceptorContext *)ctx)->thr, \
+                     ((TsanInterceptorContext *)ctx)->pc, (uptr)m)
+
+#define COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, sz, prot, flags, fd,  \
+                                     off)                                   \
+  do {                                                                      \
+    return mmap_interceptor(thr, pc, REAL(mmap), addr, sz, prot, flags, fd, \
+                            off);                                           \
+  } while (false)
+
+#if !SANITIZER_MAC
+#define COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, msg) \
+  HandleRecvmsg(((TsanInterceptorContext *)ctx)->thr, \
+      ((TsanInterceptorContext *)ctx)->pc, msg)
+#endif
+
+#define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end)                           \
+  if (TsanThread *t = GetCurrentThread()) {                                    \
+    *begin = t->tls_begin();                                                   \
+    *end = t->tls_end();                                                       \
+  } else {                                                                     \
+    *begin = *end = 0;                                                         \
+  }
+
+#define COMMON_INTERCEPTOR_USER_CALLBACK_START() \
+  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START()
+
+#define COMMON_INTERCEPTOR_USER_CALLBACK_END() \
+  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END()
+
+#include "sanitizer_common/sanitizer_common_interceptors.inc"
+
+static int sigaction_impl(int sig, const __sanitizer_sigaction *act,
+                          __sanitizer_sigaction *old);
+static __sanitizer_sighandler_ptr signal_impl(int sig,
+                                              __sanitizer_sighandler_ptr h);
+
+#define SIGNAL_INTERCEPTOR_SIGACTION_IMPL(signo, act, oldact) \
+  { return sigaction_impl(signo, act, oldact); }
+
+#define SIGNAL_INTERCEPTOR_SIGNAL_IMPL(func, signo, handler) \
+  { return (uptr)signal_impl(signo, (__sanitizer_sighandler_ptr)handler); }
+
+#include "sanitizer_common/sanitizer_signal_interceptors.inc"
+
+int sigaction_impl(int sig, const __sanitizer_sigaction *act,
+                   __sanitizer_sigaction *old) {
+  // Note: if we call REAL(sigaction) directly for any reason without proxying
+  // the signal handler through rtl_sigaction, very bad things will happen.
+  // The handler will run synchronously and corrupt tsan per-thread state.
+  SCOPED_INTERCEPTOR_RAW(sigaction, sig, act, old);
+  __sanitizer_sigaction *sigactions = interceptor_ctx()->sigactions;
+  __sanitizer_sigaction old_stored;
+  if (old) internal_memcpy(&old_stored, &sigactions[sig], sizeof(old_stored));
+  __sanitizer_sigaction newact;
+  if (act) {
+    // Copy act into sigactions[sig].
+    // Can't use struct copy, because compiler can emit call to memcpy.
+    // Can't use internal_memcpy, because it copies byte-by-byte,
+    // and signal handler reads the handler concurrently. It it can read
+    // some bytes from old value and some bytes from new value.
+    // Use volatile to prevent insertion of memcpy.
+    sigactions[sig].handler =
+        *(volatile __sanitizer_sighandler_ptr const *)&act->handler;
+    sigactions[sig].sa_flags = *(volatile int const *)&act->sa_flags;
+    internal_memcpy(&sigactions[sig].sa_mask, &act->sa_mask,
+                    sizeof(sigactions[sig].sa_mask));
+#if !SANITIZER_FREEBSD && !SANITIZER_MAC && !SANITIZER_NETBSD
+    sigactions[sig].sa_restorer = act->sa_restorer;
+#endif
+    internal_memcpy(&newact, act, sizeof(newact));
+    internal_sigfillset(&newact.sa_mask);
+    if ((uptr)act->handler != sig_ign && (uptr)act->handler != sig_dfl) {
+      if (newact.sa_flags & SA_SIGINFO)
+        newact.sigaction = rtl_sigaction;
+      else
+        newact.handler = rtl_sighandler;
+    }
+    ReleaseStore(thr, pc, (uptr)&sigactions[sig]);
+    act = &newact;
+  }
+  int res = REAL(sigaction)(sig, act, old);
+  if (res == 0 && old) {
+    uptr cb = (uptr)old->sigaction;
+    if (cb == (uptr)rtl_sigaction || cb == (uptr)rtl_sighandler) {
+      internal_memcpy(old, &old_stored, sizeof(*old));
+    }
+  }
+  return res;
+}
+
+static __sanitizer_sighandler_ptr signal_impl(int sig,
+                                              __sanitizer_sighandler_ptr h) {
+  __sanitizer_sigaction act;
+  act.handler = h;
+  internal_memset(&act.sa_mask, -1, sizeof(act.sa_mask));
+  act.sa_flags = 0;
+  __sanitizer_sigaction old;
+  int res = sigaction_symname(sig, &act, &old);
+  if (res) return (__sanitizer_sighandler_ptr)sig_err;
+  return old.handler;
+}
+
+#define TSAN_SYSCALL() \
+  ThreadState *thr = cur_thread(); \
+  if (thr->ignore_interceptors) \
+    return; \
+  ScopedSyscall scoped_syscall(thr) \
+/**/
+
+struct ScopedSyscall {
+  ThreadState *thr;
+
+  explicit ScopedSyscall(ThreadState *thr)
+      : thr(thr) {
+    Initialize(thr);
+  }
+
+  ~ScopedSyscall() {
+    ProcessPendingSignals(thr);
+  }
+};
+
+#if !SANITIZER_FREEBSD && !SANITIZER_MAC
+static void syscall_access_range(uptr pc, uptr p, uptr s, bool write) {
+  TSAN_SYSCALL();
+  MemoryAccessRange(thr, pc, p, s, write);
+}
+
+static void syscall_acquire(uptr pc, uptr addr) {
+  TSAN_SYSCALL();
+  Acquire(thr, pc, addr);
+  DPrintf("syscall_acquire(%p)\n", addr);
+}
+
+static void syscall_release(uptr pc, uptr addr) {
+  TSAN_SYSCALL();
+  DPrintf("syscall_release(%p)\n", addr);
+  Release(thr, pc, addr);
+}
+
+static void syscall_fd_close(uptr pc, int fd) {
+  TSAN_SYSCALL();
+  FdClose(thr, pc, fd);
+}
+
+static USED void syscall_fd_acquire(uptr pc, int fd) {
+  TSAN_SYSCALL();
+  FdAcquire(thr, pc, fd);
+  DPrintf("syscall_fd_acquire(%p)\n", fd);
+}
+
+static USED void syscall_fd_release(uptr pc, int fd) {
+  TSAN_SYSCALL();
+  DPrintf("syscall_fd_release(%p)\n", fd);
+  FdRelease(thr, pc, fd);
+}
+
+static void syscall_pre_fork(uptr pc) {
+  TSAN_SYSCALL();
+  ForkBefore(thr, pc);
+}
+
+static void syscall_post_fork(uptr pc, int pid) {
+  TSAN_SYSCALL();
+  if (pid == 0) {
+    // child
+    ForkChildAfter(thr, pc);
+    FdOnFork(thr, pc);
+  } else if (pid > 0) {
+    // parent
+    ForkParentAfter(thr, pc);
+  } else {
+    // error
+    ForkParentAfter(thr, pc);
+  }
+}
+#endif
+
+#define COMMON_SYSCALL_PRE_READ_RANGE(p, s) \
+  syscall_access_range(GET_CALLER_PC(), (uptr)(p), (uptr)(s), false)
+
+#define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) \
+  syscall_access_range(GET_CALLER_PC(), (uptr)(p), (uptr)(s), true)
+
+#define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
+  do {                                       \
+    (void)(p);                               \
+    (void)(s);                               \
+  } while (false)
+
+#define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \
+  do {                                        \
+    (void)(p);                                \
+    (void)(s);                                \
+  } while (false)
+
+#define COMMON_SYSCALL_ACQUIRE(addr) \
+    syscall_acquire(GET_CALLER_PC(), (uptr)(addr))
+
+#define COMMON_SYSCALL_RELEASE(addr) \
+    syscall_release(GET_CALLER_PC(), (uptr)(addr))
+
+#define COMMON_SYSCALL_FD_CLOSE(fd) syscall_fd_close(GET_CALLER_PC(), fd)
+
+#define COMMON_SYSCALL_FD_ACQUIRE(fd) syscall_fd_acquire(GET_CALLER_PC(), fd)
+
+#define COMMON_SYSCALL_FD_RELEASE(fd) syscall_fd_release(GET_CALLER_PC(), fd)
+
+#define COMMON_SYSCALL_PRE_FORK() \
+  syscall_pre_fork(GET_CALLER_PC())
+
+#define COMMON_SYSCALL_POST_FORK(res) \
+  syscall_post_fork(GET_CALLER_PC(), res)
+
+#include "sanitizer_common/sanitizer_common_syscalls.inc"
+#include "sanitizer_common/sanitizer_syscalls_netbsd.inc"
+
+#ifdef NEED_TLS_GET_ADDR
+// Define own interceptor instead of sanitizer_common's for three reasons:
+// 1. It must not process pending signals.
+//    Signal handlers may contain MOVDQA instruction (see below).
+// 2. It must be as simple as possible to not contain MOVDQA.
+// 3. Sanitizer_common version uses COMMON_INTERCEPTOR_INITIALIZE_RANGE which
+//    is empty for tsan (meant only for msan).
+// Note: __tls_get_addr can be called with mis-aligned stack due to:
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58066
+// So the interceptor must work with mis-aligned stack, in particular, does not
+// execute MOVDQA with stack addresses.
+TSAN_INTERCEPTOR(void *, __tls_get_addr, void *arg) {
+  void *res = REAL(__tls_get_addr)(arg);
+  ThreadState *thr = cur_thread();
+  if (!thr)
+    return res;
+  DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, res, thr->tls_addr,
+                                        thr->tls_addr + thr->tls_size);
+  if (!dtv)
+    return res;
+  // New DTLS block has been allocated.
+  MemoryResetRange(thr, 0, dtv->beg, dtv->size);
+  return res;
+}
+#endif
+
+#if SANITIZER_NETBSD
+TSAN_INTERCEPTOR(void, _lwp_exit) {
+  SCOPED_TSAN_INTERCEPTOR(_lwp_exit);
+  DestroyThreadState();
+  REAL(_lwp_exit)();
+}
+#define TSAN_MAYBE_INTERCEPT__LWP_EXIT TSAN_INTERCEPT(_lwp_exit)
+#else
+#define TSAN_MAYBE_INTERCEPT__LWP_EXIT
+#endif
+
+#if SANITIZER_FREEBSD
+TSAN_INTERCEPTOR(void, thr_exit, tid_t *state) {
+  SCOPED_TSAN_INTERCEPTOR(thr_exit, state);
+  DestroyThreadState();
+  REAL(thr_exit(state));
+}
+#define TSAN_MAYBE_INTERCEPT_THR_EXIT TSAN_INTERCEPT(thr_exit)
+#else
+#define TSAN_MAYBE_INTERCEPT_THR_EXIT
+#endif
+
+TSAN_INTERCEPTOR_NETBSD_ALIAS(int, cond_init, void *c, void *a)
+TSAN_INTERCEPTOR_NETBSD_ALIAS(int, cond_signal, void *c)
+TSAN_INTERCEPTOR_NETBSD_ALIAS(int, cond_broadcast, void *c)
+TSAN_INTERCEPTOR_NETBSD_ALIAS(int, cond_wait, void *c, void *m)
+TSAN_INTERCEPTOR_NETBSD_ALIAS(int, cond_destroy, void *c)
+TSAN_INTERCEPTOR_NETBSD_ALIAS(int, mutex_init, void *m, void *a)
+TSAN_INTERCEPTOR_NETBSD_ALIAS(int, mutex_destroy, void *m)
+TSAN_INTERCEPTOR_NETBSD_ALIAS(int, mutex_trylock, void *m)
+TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_init, void *m, void *a)
+TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_destroy, void *m)
+TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_rdlock, void *m)
+TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_tryrdlock, void *m)
+TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_wrlock, void *m)
+TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_trywrlock, void *m)
+TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_unlock, void *m)
+TSAN_INTERCEPTOR_NETBSD_ALIAS_THR(int, once, void *o, void (*f)())
+TSAN_INTERCEPTOR_NETBSD_ALIAS_THR2(int, sigsetmask, sigmask, int a, void *b,
+  void *c)
+
+namespace __tsan {
+
+static void finalize(void *arg) {
+  ThreadState *thr = cur_thread();
+  int status = Finalize(thr);
+  // Make sure the output is not lost.
+  FlushStreams();
+  if (status)
+    Die();
+}
+
+#if !SANITIZER_MAC && !SANITIZER_ANDROID
+static void unreachable() {
+  Report("FATAL: ThreadSanitizer: unreachable called\n");
+  Die();
+}
+#endif
+
+// Define default implementation since interception of libdispatch  is optional.
+SANITIZER_WEAK_ATTRIBUTE void InitializeLibdispatchInterceptors() {}
+
+void InitializeInterceptors() {
+#if !SANITIZER_MAC
+  // We need to setup it early, because functions like dlsym() can call it.
+  REAL(memset) = internal_memset;
+  REAL(memcpy) = internal_memcpy;
+#endif
+
+  // Instruct libc malloc to consume less memory.
+#if SANITIZER_LINUX
+  mallopt(1, 0);  // M_MXFAST
+  mallopt(-3, 32*1024);  // M_MMAP_THRESHOLD
+#endif
+
+  new(interceptor_ctx()) InterceptorContext();
+
+  InitializeCommonInterceptors();
+  InitializeSignalInterceptors();
+  InitializeLibdispatchInterceptors();
+
+#if !SANITIZER_MAC
+  // We can not use TSAN_INTERCEPT to get setjmp addr,
+  // because it does &setjmp and setjmp is not present in some versions of libc.
+  using __interception::InterceptFunction;
+  InterceptFunction(TSAN_STRING_SETJMP, (uptr*)&REAL(setjmp_symname), 0, 0);
+  InterceptFunction("_setjmp", (uptr*)&REAL(_setjmp), 0, 0);
+  InterceptFunction(TSAN_STRING_SIGSETJMP, (uptr*)&REAL(sigsetjmp_symname), 0,
+                    0);
+#if !SANITIZER_NETBSD
+  InterceptFunction("__sigsetjmp", (uptr*)&REAL(__sigsetjmp), 0, 0);
+#endif
+#endif
+
+  TSAN_INTERCEPT(longjmp_symname);
+  TSAN_INTERCEPT(siglongjmp_symname);
+#if SANITIZER_NETBSD
+  TSAN_INTERCEPT(_longjmp);
+#endif
+
+  TSAN_INTERCEPT(malloc);
+  TSAN_INTERCEPT(__libc_memalign);
+  TSAN_INTERCEPT(calloc);
+  TSAN_INTERCEPT(realloc);
+  TSAN_INTERCEPT(reallocarray);
+  TSAN_INTERCEPT(free);
+  TSAN_INTERCEPT(cfree);
+  TSAN_INTERCEPT(munmap);
+  TSAN_MAYBE_INTERCEPT_MEMALIGN;
+  TSAN_INTERCEPT(valloc);
+  TSAN_MAYBE_INTERCEPT_PVALLOC;
+  TSAN_INTERCEPT(posix_memalign);
+
+  TSAN_INTERCEPT(strcpy);
+  TSAN_INTERCEPT(strncpy);
+  TSAN_INTERCEPT(strdup);
+
+  TSAN_INTERCEPT(pthread_create);
+  TSAN_INTERCEPT(pthread_join);
+  TSAN_INTERCEPT(pthread_detach);
+  TSAN_INTERCEPT(pthread_exit);
+  #if SANITIZER_LINUX
+  TSAN_INTERCEPT(pthread_tryjoin_np);
+  TSAN_INTERCEPT(pthread_timedjoin_np);
+  #endif
+
+  TSAN_INTERCEPT_VER(pthread_cond_init, PTHREAD_ABI_BASE);
+  TSAN_INTERCEPT_VER(pthread_cond_signal, PTHREAD_ABI_BASE);
+  TSAN_INTERCEPT_VER(pthread_cond_broadcast, PTHREAD_ABI_BASE);
+  TSAN_INTERCEPT_VER(pthread_cond_wait, PTHREAD_ABI_BASE);
+  TSAN_INTERCEPT_VER(pthread_cond_timedwait, PTHREAD_ABI_BASE);
+  TSAN_INTERCEPT_VER(pthread_cond_destroy, PTHREAD_ABI_BASE);
+
+  TSAN_INTERCEPT(pthread_mutex_init);
+  TSAN_INTERCEPT(pthread_mutex_destroy);
+  TSAN_INTERCEPT(pthread_mutex_trylock);
+  TSAN_INTERCEPT(pthread_mutex_timedlock);
+
+  TSAN_INTERCEPT(pthread_spin_init);
+  TSAN_INTERCEPT(pthread_spin_destroy);
+  TSAN_INTERCEPT(pthread_spin_lock);
+  TSAN_INTERCEPT(pthread_spin_trylock);
+  TSAN_INTERCEPT(pthread_spin_unlock);
+
+  TSAN_INTERCEPT(pthread_rwlock_init);
+  TSAN_INTERCEPT(pthread_rwlock_destroy);
+  TSAN_INTERCEPT(pthread_rwlock_rdlock);
+  TSAN_INTERCEPT(pthread_rwlock_tryrdlock);
+  TSAN_INTERCEPT(pthread_rwlock_timedrdlock);
+  TSAN_INTERCEPT(pthread_rwlock_wrlock);
+  TSAN_INTERCEPT(pthread_rwlock_trywrlock);
+  TSAN_INTERCEPT(pthread_rwlock_timedwrlock);
+  TSAN_INTERCEPT(pthread_rwlock_unlock);
+
+  TSAN_INTERCEPT(pthread_barrier_init);
+  TSAN_INTERCEPT(pthread_barrier_destroy);
+  TSAN_INTERCEPT(pthread_barrier_wait);
+
+  TSAN_INTERCEPT(pthread_once);
+
+  TSAN_INTERCEPT(fstat);
+  TSAN_MAYBE_INTERCEPT___FXSTAT;
+  TSAN_MAYBE_INTERCEPT_FSTAT64;
+  TSAN_MAYBE_INTERCEPT___FXSTAT64;
+  TSAN_INTERCEPT(open);
+  TSAN_MAYBE_INTERCEPT_OPEN64;
+  TSAN_INTERCEPT(creat);
+  TSAN_MAYBE_INTERCEPT_CREAT64;
+  TSAN_INTERCEPT(dup);
+  TSAN_INTERCEPT(dup2);
+  TSAN_INTERCEPT(dup3);
+  TSAN_MAYBE_INTERCEPT_EVENTFD;
+  TSAN_MAYBE_INTERCEPT_SIGNALFD;
+  TSAN_MAYBE_INTERCEPT_INOTIFY_INIT;
+  TSAN_MAYBE_INTERCEPT_INOTIFY_INIT1;
+  TSAN_INTERCEPT(socket);
+  TSAN_INTERCEPT(socketpair);
+  TSAN_INTERCEPT(connect);
+  TSAN_INTERCEPT(bind);
+  TSAN_INTERCEPT(listen);
+  TSAN_MAYBE_INTERCEPT_EPOLL;
+  TSAN_INTERCEPT(close);
+  TSAN_MAYBE_INTERCEPT___CLOSE;
+  TSAN_MAYBE_INTERCEPT___RES_ICLOSE;
+  TSAN_INTERCEPT(pipe);
+  TSAN_INTERCEPT(pipe2);
+
+  TSAN_INTERCEPT(unlink);
+  TSAN_INTERCEPT(tmpfile);
+  TSAN_MAYBE_INTERCEPT_TMPFILE64;
+  TSAN_INTERCEPT(abort);
+  TSAN_INTERCEPT(rmdir);
+  TSAN_INTERCEPT(closedir);
+
+  TSAN_INTERCEPT(sigsuspend);
+  TSAN_INTERCEPT(sigblock);
+  TSAN_INTERCEPT(sigsetmask);
+  TSAN_INTERCEPT(pthread_sigmask);
+  TSAN_INTERCEPT(raise);
+  TSAN_INTERCEPT(kill);
+  TSAN_INTERCEPT(pthread_kill);
+  TSAN_INTERCEPT(sleep);
+  TSAN_INTERCEPT(usleep);
+  TSAN_INTERCEPT(nanosleep);
+  TSAN_INTERCEPT(pause);
+  TSAN_INTERCEPT(gettimeofday);
+  TSAN_INTERCEPT(getaddrinfo);
+
+  TSAN_INTERCEPT(fork);
+  TSAN_INTERCEPT(vfork);
+#if !SANITIZER_ANDROID
+  TSAN_INTERCEPT(dl_iterate_phdr);
+#endif
+  TSAN_MAYBE_INTERCEPT_ON_EXIT;
+  TSAN_INTERCEPT(__cxa_atexit);
+  TSAN_INTERCEPT(_exit);
+
+#ifdef NEED_TLS_GET_ADDR
+  TSAN_INTERCEPT(__tls_get_addr);
+#endif
+
+  TSAN_MAYBE_INTERCEPT__LWP_EXIT;
+  TSAN_MAYBE_INTERCEPT_THR_EXIT;
+
+#if !SANITIZER_MAC && !SANITIZER_ANDROID
+  // Need to setup it, because interceptors check that the function is resolved.
+  // But atexit is emitted directly into the module, so can't be resolved.
+  REAL(atexit) = (int(*)(void(*)()))unreachable;
+#endif
+
+  if (REAL(__cxa_atexit)(&finalize, 0, 0)) {
+    Printf("ThreadSanitizer: failed to setup atexit callback\n");
+    Die();
+  }
+
+#if !SANITIZER_MAC && !SANITIZER_NETBSD && !SANITIZER_FREEBSD
+  if (pthread_key_create(&interceptor_ctx()->finalize_key, &thread_finalize)) {
+    Printf("ThreadSanitizer: failed to create thread key\n");
+    Die();
+  }
+#endif
+
+  TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(cond_init);
+  TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(cond_signal);
+  TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(cond_broadcast);
+  TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(cond_wait);
+  TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(cond_destroy);
+  TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(mutex_init);
+  TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(mutex_destroy);
+  TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(mutex_trylock);
+  TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_init);
+  TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_destroy);
+  TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_rdlock);
+  TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_tryrdlock);
+  TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_wrlock);
+  TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_trywrlock);
+  TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_unlock);
+  TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS_THR(once);
+  TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS_THR(sigsetmask);
+
+  FdInit();
+}
+
+}  // namespace __tsan
+
+// Invisible barrier for tests.
+// There were several unsuccessful iterations for this functionality:
+// 1. Initially it was implemented in user code using
+//    REAL(pthread_barrier_wait). But pthread_barrier_wait is not supported on
+//    MacOS. Futexes are linux-specific for this matter.
+// 2. Then we switched to atomics+usleep(10). But usleep produced parasitic
+//    "as-if synchronized via sleep" messages in reports which failed some
+//    output tests.
+// 3. Then we switched to atomics+sched_yield. But this produced tons of tsan-
+//    visible events, which lead to "failed to restore stack trace" failures.
+// Note that no_sanitize_thread attribute does not turn off atomic interception
+// so attaching it to the function defined in user code does not help.
+// That's why we now have what we have.
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_testonly_barrier_init(u64 *barrier, u32 count) {
+  if (count >= (1 << 8)) {
+      Printf("barrier_init: count is too large (%d)\n", count);
+      Die();
+  }
+  // 8 lsb is thread count, the remaining are count of entered threads.
+  *barrier = count;
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_testonly_barrier_wait(u64 *barrier) {
+  unsigned old = __atomic_fetch_add(barrier, 1 << 8, __ATOMIC_RELAXED);
+  unsigned old_epoch = (old >> 8) / (old & 0xff);
+  for (;;) {
+    unsigned cur = __atomic_load_n(barrier, __ATOMIC_RELAXED);
+    unsigned cur_epoch = (cur >> 8) / (cur & 0xff);
+    if (cur_epoch != old_epoch)
+      return;
+    internal_sched_yield();
+  }
+}
index 845d8c8520cecebe2b1f01f38cac51f7204d080b..2b3a0889b70a4ac636f4cc8c046e015a6a1efec5 100644 (file)
@@ -17,7 +17,7 @@
 
 #define CALLERPC ((uptr)__builtin_return_address(0))
 
-using namespace __tsan;  // NOLINT
+using namespace __tsan;
 
 typedef u16 uint16_t;
 typedef u32 uint32_t;
index fac57809aa245fbbb3db64f5b214fa8709d41514..6d7286ca5b8afbb22d82b1af0bc5bab3ca8a4084 100644 (file)
@@ -90,9 +90,14 @@ SANITIZER_INTERFACE_ATTRIBUTE
 void __tsan_external_write(void *addr, void *caller_pc, void *tag);
 
 SANITIZER_INTERFACE_ATTRIBUTE
-void __tsan_read_range(void *addr, unsigned long size);  // NOLINT
+void __tsan_read_range(void *addr, unsigned long size);
 SANITIZER_INTERFACE_ATTRIBUTE
-void __tsan_write_range(void *addr, unsigned long size);  // NOLINT
+void __tsan_write_range(void *addr, unsigned long size);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_read_range_pc(void *addr, unsigned long size, void *pc);  // NOLINT
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_write_range_pc(void *addr, unsigned long size, void *pc);  // NOLINT
 
 // User may provide function that would be called right when TSan detects
 // an error. The argument 'report' is an opaque pointer that can be used to
@@ -187,9 +192,9 @@ namespace __tsan {
 
 // These should match declarations from public tsan_interface_atomic.h header.
 typedef unsigned char      a8;
-typedef unsigned short     a16;  // NOLINT
+typedef unsigned short a16;
 typedef unsigned int       a32;
-typedef unsigned long long a64;  // NOLINT
+typedef unsigned long long a64;
 #if !SANITIZER_GO && (defined(__SIZEOF_INT128__) \
     || (__clang_major__ * 100 + __clang_minor__ >= 302)) && !defined(__mips64)
 __extension__ typedef __int128 a128;
index 288485c17fa8806c4184a58d5ca05abcddeafb01..99516d94bba3c2caec314ae0f15c886eb62fe14d 100644 (file)
@@ -24,7 +24,7 @@
 
 #define CALLERPC ((uptr)__builtin_return_address(0))
 
-using namespace __tsan;  // NOLINT
+using namespace __tsan;
 
 namespace __tsan {
 
@@ -220,7 +220,7 @@ static void ReportMissedExpectedRace(ExpectRace *race) {
 }
 }  // namespace __tsan
 
-using namespace __tsan;  // NOLINT
+using namespace __tsan;
 
 extern "C" {
 void INTERFACE_ATTRIBUTE AnnotateHappensBefore(char *f, int l, uptr addr) {
index 730a8e63f742087cd6e94fefc60c621defd423fd..3f459aff532cb6982a2054783ab8a2abd061c6d0 100644 (file)
@@ -25,7 +25,7 @@
 #include "tsan_interface.h"
 #include "tsan_rtl.h"
 
-using namespace __tsan;  // NOLINT
+using namespace __tsan;
 
 #if !SANITIZER_GO && __TSAN_HAS_INT128
 // Protects emulation of 128-bit atomic operations.
index bf4a1658625c051852820d758fe0cb35ba807a25..f955ddf99247c5f162de02992ae017a4df8465ad 100644 (file)
@@ -15,7 +15,7 @@
 
 #define CALLERPC ((uptr)__builtin_return_address(0))
 
-using namespace __tsan;  // NOLINT
+using namespace __tsan;
 
 void __tsan_read1(void *addr) {
   MemoryRead(cur_thread(), CALLERPC, (uptr)addr, kSizeLog1);
@@ -122,3 +122,11 @@ void __tsan_read_range(void *addr, uptr size) {
 void __tsan_write_range(void *addr, uptr size) {
   MemoryAccessRange(cur_thread(), CALLERPC, (uptr)addr, size, true);
 }
+
+void __tsan_read_range_pc(void *addr, uptr size, void *pc) {
+  MemoryAccessRange(cur_thread(), (uptr)pc, (uptr)addr, size, false);
+}
+
+void __tsan_write_range_pc(void *addr, uptr size, void *pc) {
+  MemoryAccessRange(cur_thread(), (uptr)pc, (uptr)addr, size, true);
+}
index 7d3d32fdbe0ff27cd550cc49964319a44feca476..081c6ff1022e876e115ba9032e893acdfe74033d 100644 (file)
@@ -19,7 +19,7 @@
 #include "sanitizer_common/sanitizer_stacktrace.h"
 #include "sanitizer_common/sanitizer_procmaps.h"
 
-using namespace __tsan;  // NOLINT
+using namespace __tsan;
 
 const jptr kHeapAlignment = 8;
 
index 93e67bd10b133584c3bc66eea602b4b4da5dbc64..51b445251e09b028788d1fcc564e096ce1e6c5b6 100644 (file)
@@ -31,7 +31,7 @@
 extern "C" {
 #endif
 
-typedef unsigned long jptr;  // NOLINT
+typedef unsigned long jptr;
 
 // Must be called before any other callback from Java.
 void __tsan_java_init(jptr heap_begin, jptr heap_size) INTERFACE_ATTRIBUTE;
diff --git a/libsanitizer/tsan/tsan_libdispatch.cpp b/libsanitizer/tsan/tsan_libdispatch.cpp
deleted file mode 100644 (file)
index 5e86ddc..0000000
+++ /dev/null
@@ -1,781 +0,0 @@
-//===-- tsan_libdispatch.cpp ----------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is a part of ThreadSanitizer (TSan), a race detector.
-//
-// Support for intercepting libdispatch (GCD).
-//===----------------------------------------------------------------------===//
-
-#include "sanitizer_common/sanitizer_common.h"
-#include "interception/interception.h"
-#include "tsan_interceptors.h"
-#include "tsan_rtl.h"
-
-#include "tsan_dispatch_defs.h"
-
-namespace __tsan {
-  typedef u16 uint16_t;
-
-typedef struct {
-  dispatch_queue_t queue;
-  void *orig_context;
-  dispatch_function_t orig_work;
-  bool free_context_in_callback;
-  bool submitted_synchronously;
-  bool is_barrier_block;
-  uptr non_queue_sync_object;
-} block_context_t;
-
-// The offsets of different fields of the dispatch_queue_t structure, exported
-// by libdispatch.dylib.
-extern "C" struct dispatch_queue_offsets_s {
-  const uint16_t dqo_version;
-  const uint16_t dqo_label;
-  const uint16_t dqo_label_size;
-  const uint16_t dqo_flags;
-  const uint16_t dqo_flags_size;
-  const uint16_t dqo_serialnum;
-  const uint16_t dqo_serialnum_size;
-  const uint16_t dqo_width;
-  const uint16_t dqo_width_size;
-  const uint16_t dqo_running;
-  const uint16_t dqo_running_size;
-  const uint16_t dqo_suspend_cnt;
-  const uint16_t dqo_suspend_cnt_size;
-  const uint16_t dqo_target_queue;
-  const uint16_t dqo_target_queue_size;
-  const uint16_t dqo_priority;
-  const uint16_t dqo_priority_size;
-} dispatch_queue_offsets;
-
-static bool IsQueueSerial(dispatch_queue_t q) {
-  CHECK_EQ(dispatch_queue_offsets.dqo_width_size, 2);
-  uptr width = *(uint16_t *)(((uptr)q) + dispatch_queue_offsets.dqo_width);
-  CHECK_NE(width, 0);
-  return width == 1;
-}
-
-static dispatch_queue_t GetTargetQueueFromQueue(dispatch_queue_t q) {
-  CHECK_EQ(dispatch_queue_offsets.dqo_target_queue_size, 8);
-  dispatch_queue_t tq = *(
-      dispatch_queue_t *)(((uptr)q) + dispatch_queue_offsets.dqo_target_queue);
-  return tq;
-}
-
-static dispatch_queue_t GetTargetQueueFromSource(dispatch_source_t source) {
-  dispatch_queue_t tq = GetTargetQueueFromQueue((dispatch_queue_t)source);
-  CHECK_NE(tq, 0);
-  return tq;
-}
-
-static block_context_t *AllocContext(ThreadState *thr, uptr pc,
-                                     dispatch_queue_t queue, void *orig_context,
-                                     dispatch_function_t orig_work) {
-  block_context_t *new_context =
-      (block_context_t *)user_alloc_internal(thr, pc, sizeof(block_context_t));
-  new_context->queue = queue;
-  new_context->orig_context = orig_context;
-  new_context->orig_work = orig_work;
-  new_context->free_context_in_callback = true;
-  new_context->submitted_synchronously = false;
-  new_context->is_barrier_block = false;
-  new_context->non_queue_sync_object = 0;
-  return new_context;
-}
-
-#define GET_QUEUE_SYNC_VARS(context, q)                                  \
-  bool is_queue_serial = q && IsQueueSerial(q);                          \
-  uptr sync_ptr = (uptr)q ?: context->non_queue_sync_object;             \
-  uptr serial_sync = (uptr)sync_ptr;                                     \
-  uptr concurrent_sync = sync_ptr ? ((uptr)sync_ptr) + sizeof(uptr) : 0; \
-  bool serial_task = context->is_barrier_block || is_queue_serial
-
-static void dispatch_sync_pre_execute(ThreadState *thr, uptr pc,
-                                      block_context_t *context) {
-  uptr submit_sync = (uptr)context;
-  Acquire(thr, pc, submit_sync);
-
-  dispatch_queue_t q = context->queue;
-  do {
-    GET_QUEUE_SYNC_VARS(context, q);
-    if (serial_sync) Acquire(thr, pc, serial_sync);
-    if (serial_task && concurrent_sync) Acquire(thr, pc, concurrent_sync);
-
-    if (q) q = GetTargetQueueFromQueue(q);
-  } while (q);
-}
-
-static void dispatch_sync_post_execute(ThreadState *thr, uptr pc,
-                                       block_context_t *context) {
-  uptr submit_sync = (uptr)context;
-  if (context->submitted_synchronously) Release(thr, pc, submit_sync);
-
-  dispatch_queue_t q = context->queue;
-  do {
-    GET_QUEUE_SYNC_VARS(context, q);
-    if (serial_task && serial_sync) Release(thr, pc, serial_sync);
-    if (!serial_task && concurrent_sync) Release(thr, pc, concurrent_sync);
-
-    if (q) q = GetTargetQueueFromQueue(q);
-  } while (q);
-}
-
-static void dispatch_callback_wrap(void *param) {
-  SCOPED_INTERCEPTOR_RAW(dispatch_callback_wrap);
-  block_context_t *context = (block_context_t *)param;
-
-  dispatch_sync_pre_execute(thr, pc, context);
-
-  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
-  context->orig_work(context->orig_context);
-  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
-
-  dispatch_sync_post_execute(thr, pc, context);
-
-  if (context->free_context_in_callback) user_free(thr, pc, context);
-}
-
-static void invoke_block(void *param) {
-  dispatch_block_t block = (dispatch_block_t)param;
-  block();
-}
-
-static void invoke_and_release_block(void *param) {
-  dispatch_block_t block = (dispatch_block_t)param;
-  block();
-  Block_release(block);
-}
-
-#define DISPATCH_INTERCEPT_ASYNC_B(name, barrier)                            \
-  TSAN_INTERCEPTOR(void, name, dispatch_queue_t q, dispatch_block_t block) { \
-    SCOPED_TSAN_INTERCEPTOR(name, q, block);                                 \
-    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();                           \
-    dispatch_block_t heap_block = Block_copy(block);                         \
-    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();                             \
-    block_context_t *new_context =                                           \
-        AllocContext(thr, pc, q, heap_block, &invoke_and_release_block);     \
-    new_context->is_barrier_block = barrier;                                 \
-    Release(thr, pc, (uptr)new_context);                                     \
-    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();                           \
-    REAL(name##_f)(q, new_context, dispatch_callback_wrap);                  \
-    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();                             \
-  }
-
-#define DISPATCH_INTERCEPT_SYNC_B(name, barrier)                             \
-  TSAN_INTERCEPTOR(void, name, dispatch_queue_t q,                           \
-                   DISPATCH_NOESCAPE dispatch_block_t block) {               \
-    SCOPED_TSAN_INTERCEPTOR(name, q, block);                                 \
-    block_context_t new_context = {                                          \
-        q, block, &invoke_block, false, true, barrier, 0};                   \
-    Release(thr, pc, (uptr)&new_context);                                    \
-    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();                           \
-    REAL(name##_f)(q, &new_context, dispatch_callback_wrap);                 \
-    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();                             \
-    Acquire(thr, pc, (uptr)&new_context);                                    \
-  }
-
-#define DISPATCH_INTERCEPT_ASYNC_F(name, barrier)                 \
-  TSAN_INTERCEPTOR(void, name, dispatch_queue_t q, void *context, \
-                   dispatch_function_t work) {                    \
-    SCOPED_TSAN_INTERCEPTOR(name, q, context, work);              \
-    block_context_t *new_context =                                \
-        AllocContext(thr, pc, q, context, work);                  \
-    new_context->is_barrier_block = barrier;                      \
-    Release(thr, pc, (uptr)new_context);                          \
-    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();                \
-    REAL(name)(q, new_context, dispatch_callback_wrap);           \
-    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();                  \
-  }
-
-#define DISPATCH_INTERCEPT_SYNC_F(name, barrier)                              \
-  TSAN_INTERCEPTOR(void, name, dispatch_queue_t q, void *context,             \
-                   dispatch_function_t work) {                                \
-    SCOPED_TSAN_INTERCEPTOR(name, q, context, work);                          \
-    block_context_t new_context = {                                           \
-        q, context, work, false, true, barrier, 0};                           \
-    Release(thr, pc, (uptr)&new_context);                                     \
-    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();                            \
-    REAL(name)(q, &new_context, dispatch_callback_wrap);                      \
-    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();                              \
-    Acquire(thr, pc, (uptr)&new_context);                                     \
-  }
-
-#define DISPATCH_INTERCEPT(name, barrier)             \
-  DISPATCH_INTERCEPT_ASYNC_F(name##_async_f, barrier) \
-  DISPATCH_INTERCEPT_ASYNC_B(name##_async, barrier)   \
-  DISPATCH_INTERCEPT_SYNC_F(name##_sync_f, barrier)   \
-  DISPATCH_INTERCEPT_SYNC_B(name##_sync, barrier)
-
-// We wrap dispatch_async, dispatch_sync and friends where we allocate a new
-// context, which is used to synchronize (we release the context before
-// submitting, and the callback acquires it before executing the original
-// callback).
-DISPATCH_INTERCEPT(dispatch, false)
-DISPATCH_INTERCEPT(dispatch_barrier, true)
-
-DECLARE_REAL(void, dispatch_after_f, dispatch_time_t when,
-             dispatch_queue_t queue, void *context, dispatch_function_t work)
-
-TSAN_INTERCEPTOR(void, dispatch_after, dispatch_time_t when,
-                 dispatch_queue_t queue, dispatch_block_t block) {
-  SCOPED_TSAN_INTERCEPTOR(dispatch_after, when, queue, block);
-  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
-  dispatch_block_t heap_block = Block_copy(block);
-  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
-  block_context_t *new_context =
-      AllocContext(thr, pc, queue, heap_block, &invoke_and_release_block);
-  Release(thr, pc, (uptr)new_context);
-  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
-  REAL(dispatch_after_f)(when, queue, new_context, dispatch_callback_wrap);
-  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
-}
-
-TSAN_INTERCEPTOR(void, dispatch_after_f, dispatch_time_t when,
-                 dispatch_queue_t queue, void *context,
-                 dispatch_function_t work) {
-  SCOPED_TSAN_INTERCEPTOR(dispatch_after_f, when, queue, context, work);
-  WRAP(dispatch_after)(when, queue, ^(void) {
-    work(context);
-  });
-}
-
-// GCD's dispatch_once implementation has a fast path that contains a racy read
-// and it's inlined into user's code. Furthermore, this fast path doesn't
-// establish a proper happens-before relations between the initialization and
-// code following the call to dispatch_once. We could deal with this in
-// instrumented code, but there's not much we can do about it in system
-// libraries. Let's disable the fast path (by never storing the value ~0 to
-// predicate), so the interceptor is always called, and let's add proper release
-// and acquire semantics. Since TSan does not see its own atomic stores, the
-// race on predicate won't be reported - the only accesses to it that TSan sees
-// are the loads on the fast path. Loads don't race. Secondly, dispatch_once is
-// both a macro and a real function, we want to intercept the function, so we
-// need to undefine the macro.
-#undef dispatch_once
-TSAN_INTERCEPTOR(void, dispatch_once, dispatch_once_t *predicate,
-                 DISPATCH_NOESCAPE dispatch_block_t block) {
-  SCOPED_INTERCEPTOR_RAW(dispatch_once, predicate, block);
-  atomic_uint32_t *a = reinterpret_cast<atomic_uint32_t *>(predicate);
-  u32 v = atomic_load(a, memory_order_acquire);
-  if (v == 0 &&
-      atomic_compare_exchange_strong(a, &v, 1, memory_order_relaxed)) {
-    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
-    block();
-    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
-    Release(thr, pc, (uptr)a);
-    atomic_store(a, 2, memory_order_release);
-  } else {
-    while (v != 2) {
-      internal_sched_yield();
-      v = atomic_load(a, memory_order_acquire);
-    }
-    Acquire(thr, pc, (uptr)a);
-  }
-}
-
-#undef dispatch_once_f
-TSAN_INTERCEPTOR(void, dispatch_once_f, dispatch_once_t *predicate,
-                 void *context, dispatch_function_t function) {
-  SCOPED_INTERCEPTOR_RAW(dispatch_once_f, predicate, context, function);
-  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
-  WRAP(dispatch_once)(predicate, ^(void) {
-    function(context);
-  });
-  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
-}
-
-TSAN_INTERCEPTOR(long_t, dispatch_semaphore_signal,
-                 dispatch_semaphore_t dsema) {
-  SCOPED_TSAN_INTERCEPTOR(dispatch_semaphore_signal, dsema);
-  Release(thr, pc, (uptr)dsema);
-  return REAL(dispatch_semaphore_signal)(dsema);
-}
-
-TSAN_INTERCEPTOR(long_t, dispatch_semaphore_wait, dispatch_semaphore_t dsema,
-                 dispatch_time_t timeout) {
-  SCOPED_TSAN_INTERCEPTOR(dispatch_semaphore_wait, dsema, timeout);
-  long_t result = REAL(dispatch_semaphore_wait)(dsema, timeout);
-  if (result == 0) Acquire(thr, pc, (uptr)dsema);
-  return result;
-}
-
-TSAN_INTERCEPTOR(long_t, dispatch_group_wait, dispatch_group_t group,
-                 dispatch_time_t timeout) {
-  SCOPED_TSAN_INTERCEPTOR(dispatch_group_wait, group, timeout);
-  long_t result = REAL(dispatch_group_wait)(group, timeout);
-  if (result == 0) Acquire(thr, pc, (uptr)group);
-  return result;
-}
-
-// Used, but not intercepted.
-extern "C" void dispatch_group_enter(dispatch_group_t group);
-
-TSAN_INTERCEPTOR(void, dispatch_group_leave, dispatch_group_t group) {
-  SCOPED_TSAN_INTERCEPTOR(dispatch_group_leave, group);
-  // Acquired in the group notification callback in dispatch_group_notify[_f].
-  Release(thr, pc, (uptr)group);
-  REAL(dispatch_group_leave)(group);
-}
-
-TSAN_INTERCEPTOR(void, dispatch_group_async, dispatch_group_t group,
-                 dispatch_queue_t queue, dispatch_block_t block) {
-  SCOPED_TSAN_INTERCEPTOR(dispatch_group_async, group, queue, block);
-  dispatch_retain(group);
-  dispatch_group_enter(group);
-  __block dispatch_block_t block_copy = (dispatch_block_t)Block_copy(block);
-  WRAP(dispatch_async)(queue, ^(void) {
-    block_copy();
-    Block_release(block_copy);
-    WRAP(dispatch_group_leave)(group);
-    dispatch_release(group);
-  });
-}
-
-TSAN_INTERCEPTOR(void, dispatch_group_async_f, dispatch_group_t group,
-                 dispatch_queue_t queue, void *context,
-                 dispatch_function_t work) {
-  SCOPED_TSAN_INTERCEPTOR(dispatch_group_async_f, group, queue, context, work);
-  dispatch_retain(group);
-  dispatch_group_enter(group);
-  WRAP(dispatch_async)(queue, ^(void) {
-    work(context);
-    WRAP(dispatch_group_leave)(group);
-    dispatch_release(group);
-  });
-}
-
-DECLARE_REAL(void, dispatch_group_notify_f, dispatch_group_t group,
-             dispatch_queue_t q, void *context, dispatch_function_t work)
-
-TSAN_INTERCEPTOR(void, dispatch_group_notify, dispatch_group_t group,
-                 dispatch_queue_t q, dispatch_block_t block) {
-  SCOPED_TSAN_INTERCEPTOR(dispatch_group_notify, group, q, block);
-
-  // To make sure the group is still available in the callback (otherwise
-  // it can be already destroyed).  Will be released in the callback.
-  dispatch_retain(group);
-
-  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
-  dispatch_block_t heap_block = Block_copy(^(void) {
-    {
-      SCOPED_INTERCEPTOR_RAW(dispatch_read_callback);
-      // Released when leaving the group (dispatch_group_leave).
-      Acquire(thr, pc, (uptr)group);
-    }
-    dispatch_release(group);
-    block();
-  });
-  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
-  block_context_t *new_context =
-      AllocContext(thr, pc, q, heap_block, &invoke_and_release_block);
-  new_context->is_barrier_block = true;
-  Release(thr, pc, (uptr)new_context);
-  REAL(dispatch_group_notify_f)(group, q, new_context, dispatch_callback_wrap);
-}
-
-TSAN_INTERCEPTOR(void, dispatch_group_notify_f, dispatch_group_t group,
-                 dispatch_queue_t q, void *context, dispatch_function_t work) {
-  WRAP(dispatch_group_notify)(group, q, ^(void) { work(context); });
-}
-
-TSAN_INTERCEPTOR(void, dispatch_source_set_event_handler,
-                 dispatch_source_t source, dispatch_block_t handler) {
-  SCOPED_TSAN_INTERCEPTOR(dispatch_source_set_event_handler, source, handler);
-  if (handler == nullptr)
-    return REAL(dispatch_source_set_event_handler)(source, nullptr);
-  dispatch_queue_t q = GetTargetQueueFromSource(source);
-  __block block_context_t new_context = {
-      q, handler, &invoke_block, false, false, false, 0 };
-  dispatch_block_t new_handler = Block_copy(^(void) {
-    new_context.orig_context = handler;  // To explicitly capture "handler".
-    dispatch_callback_wrap(&new_context);
-  });
-  uptr submit_sync = (uptr)&new_context;
-  Release(thr, pc, submit_sync);
-  REAL(dispatch_source_set_event_handler)(source, new_handler);
-  Block_release(new_handler);
-}
-
-TSAN_INTERCEPTOR(void, dispatch_source_set_event_handler_f,
-                 dispatch_source_t source, dispatch_function_t handler) {
-  SCOPED_TSAN_INTERCEPTOR(dispatch_source_set_event_handler_f, source, handler);
-  if (handler == nullptr)
-    return REAL(dispatch_source_set_event_handler)(source, nullptr);
-  dispatch_block_t block = ^(void) {
-    handler(dispatch_get_context(source));
-  };
-  WRAP(dispatch_source_set_event_handler)(source, block);
-}
-
-TSAN_INTERCEPTOR(void, dispatch_source_set_cancel_handler,
-                 dispatch_source_t source, dispatch_block_t handler) {
-  SCOPED_TSAN_INTERCEPTOR(dispatch_source_set_cancel_handler, source, handler);
-  if (handler == nullptr)
-    return REAL(dispatch_source_set_cancel_handler)(source, nullptr);
-  dispatch_queue_t q = GetTargetQueueFromSource(source);
-  __block block_context_t new_context = {
-      q, handler, &invoke_block, false, false, false, 0};
-  dispatch_block_t new_handler = Block_copy(^(void) {
-    new_context.orig_context = handler;  // To explicitly capture "handler".
-    dispatch_callback_wrap(&new_context);
-  });
-  uptr submit_sync = (uptr)&new_context;
-  Release(thr, pc, submit_sync);
-  REAL(dispatch_source_set_cancel_handler)(source, new_handler);
-  Block_release(new_handler);
-}
-
-TSAN_INTERCEPTOR(void, dispatch_source_set_cancel_handler_f,
-                 dispatch_source_t source, dispatch_function_t handler) {
-  SCOPED_TSAN_INTERCEPTOR(dispatch_source_set_cancel_handler_f, source,
-                          handler);
-  if (handler == nullptr)
-    return REAL(dispatch_source_set_cancel_handler)(source, nullptr);
-  dispatch_block_t block = ^(void) {
-    handler(dispatch_get_context(source));
-  };
-  WRAP(dispatch_source_set_cancel_handler)(source, block);
-}
-
-TSAN_INTERCEPTOR(void, dispatch_source_set_registration_handler,
-                 dispatch_source_t source, dispatch_block_t handler) {
-  SCOPED_TSAN_INTERCEPTOR(dispatch_source_set_registration_handler, source,
-                          handler);
-  if (handler == nullptr)
-    return REAL(dispatch_source_set_registration_handler)(source, nullptr);
-  dispatch_queue_t q = GetTargetQueueFromSource(source);
-  __block block_context_t new_context = {
-      q, handler, &invoke_block, false, false, false, 0};
-  dispatch_block_t new_handler = Block_copy(^(void) {
-    new_context.orig_context = handler;  // To explicitly capture "handler".
-    dispatch_callback_wrap(&new_context);
-  });
-  uptr submit_sync = (uptr)&new_context;
-  Release(thr, pc, submit_sync);
-  REAL(dispatch_source_set_registration_handler)(source, new_handler);
-  Block_release(new_handler);
-}
-
-TSAN_INTERCEPTOR(void, dispatch_source_set_registration_handler_f,
-                 dispatch_source_t source, dispatch_function_t handler) {
-  SCOPED_TSAN_INTERCEPTOR(dispatch_source_set_registration_handler_f, source,
-                          handler);
-  if (handler == nullptr)
-    return REAL(dispatch_source_set_registration_handler)(source, nullptr);
-  dispatch_block_t block = ^(void) {
-    handler(dispatch_get_context(source));
-  };
-  WRAP(dispatch_source_set_registration_handler)(source, block);
-}
-
-TSAN_INTERCEPTOR(void, dispatch_apply, size_t iterations,
-                 dispatch_queue_t queue,
-                 DISPATCH_NOESCAPE void (^block)(size_t)) {
-  SCOPED_TSAN_INTERCEPTOR(dispatch_apply, iterations, queue, block);
-
-  u8 sync1, sync2;
-  uptr parent_to_child_sync = (uptr)&sync1;
-  uptr child_to_parent_sync = (uptr)&sync2;
-
-  Release(thr, pc, parent_to_child_sync);
-  void (^new_block)(size_t) = ^(size_t iteration) {
-    SCOPED_INTERCEPTOR_RAW(dispatch_apply);
-    Acquire(thr, pc, parent_to_child_sync);
-    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
-    block(iteration);
-    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
-    Release(thr, pc, child_to_parent_sync);
-  };
-  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
-  REAL(dispatch_apply)(iterations, queue, new_block);
-  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
-  Acquire(thr, pc, child_to_parent_sync);
-}
-
-static void invoke_block_iteration(void *param, size_t iteration) {
-  auto block = (void (^)(size_t)) param;
-  block(iteration);
-}
-
-TSAN_INTERCEPTOR(void, dispatch_apply_f, size_t iterations,
-                 dispatch_queue_t queue, void *context,
-                 void (*work)(void *, size_t)) {
-  SCOPED_TSAN_INTERCEPTOR(dispatch_apply_f, iterations, queue, context, work);
-
-  // Unfortunately, we cannot delegate to dispatch_apply, since libdispatch
-  // implements dispatch_apply in terms of dispatch_apply_f.
-  u8 sync1, sync2;
-  uptr parent_to_child_sync = (uptr)&sync1;
-  uptr child_to_parent_sync = (uptr)&sync2;
-
-  Release(thr, pc, parent_to_child_sync);
-  void (^new_block)(size_t) = ^(size_t iteration) {
-    SCOPED_INTERCEPTOR_RAW(dispatch_apply_f);
-    Acquire(thr, pc, parent_to_child_sync);
-    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
-    work(context, iteration);
-    SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
-    Release(thr, pc, child_to_parent_sync);
-  };
-  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
-  REAL(dispatch_apply_f)(iterations, queue, new_block, invoke_block_iteration);
-  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
-  Acquire(thr, pc, child_to_parent_sync);
-}
-
-DECLARE_REAL_AND_INTERCEPTOR(void, free, void *ptr)
-DECLARE_REAL_AND_INTERCEPTOR(int, munmap, void *addr, long_t sz)
-
-TSAN_INTERCEPTOR(dispatch_data_t, dispatch_data_create, const void *buffer,
-                 size_t size, dispatch_queue_t q, dispatch_block_t destructor) {
-  SCOPED_TSAN_INTERCEPTOR(dispatch_data_create, buffer, size, q, destructor);
-  if ((q == nullptr) || (destructor == DISPATCH_DATA_DESTRUCTOR_DEFAULT))
-    return REAL(dispatch_data_create)(buffer, size, q, destructor);
-
-  if (destructor == DISPATCH_DATA_DESTRUCTOR_FREE)
-    destructor = ^(void) { WRAP(free)((void *)(uintptr_t)buffer); };
-  else if (destructor == DISPATCH_DATA_DESTRUCTOR_MUNMAP)
-    destructor = ^(void) { WRAP(munmap)((void *)(uintptr_t)buffer, size); };
-
-  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
-  dispatch_block_t heap_block = Block_copy(destructor);
-  SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
-  block_context_t *new_context =
-      AllocContext(thr, pc, q, heap_block, &invoke_and_release_block);
-  uptr submit_sync = (uptr)new_context;
-  Release(thr, pc, submit_sync);
-  return REAL(dispatch_data_create)(buffer, size, q, ^(void) {
-    dispatch_callback_wrap(new_context);
-  });
-}
-
-typedef void (^fd_handler_t)(dispatch_data_t data, int error);
-typedef void (^cleanup_handler_t)(int error);
-
-TSAN_INTERCEPTOR(void, dispatch_read, dispatch_fd_t fd, size_t length,
-                 dispatch_queue_t q, fd_handler_t h) {
-  SCOPED_TSAN_INTERCEPTOR(dispatch_read, fd, length, q, h);
-  __block block_context_t new_context = {
-      q, nullptr, &invoke_block, false, false, false, 0};
-  fd_handler_t new_h = Block_copy(^(dispatch_data_t data, int error) {
-    new_context.orig_context = ^(void) {
-      h(data, error);
-    };
-    dispatch_callback_wrap(&new_context);
-  });
-  uptr submit_sync = (uptr)&new_context;
-  Release(thr, pc, submit_sync);
-  REAL(dispatch_read)(fd, length, q, new_h);
-  Block_release(new_h);
-}
-
-TSAN_INTERCEPTOR(void, dispatch_write, dispatch_fd_t fd, dispatch_data_t data,
-                 dispatch_queue_t q, fd_handler_t h) {
-  SCOPED_TSAN_INTERCEPTOR(dispatch_write, fd, data, q, h);
-  __block block_context_t new_context = {
-      q, nullptr, &invoke_block, false, false, false, 0};
-  fd_handler_t new_h = Block_copy(^(dispatch_data_t data, int error) {
-    new_context.orig_context = ^(void) {
-      h(data, error);
-    };
-    dispatch_callback_wrap(&new_context);
-  });
-  uptr submit_sync = (uptr)&new_context;
-  Release(thr, pc, submit_sync);
-  REAL(dispatch_write)(fd, data, q, new_h);
-  Block_release(new_h);
-}
-
-TSAN_INTERCEPTOR(void, dispatch_io_read, dispatch_io_t channel, off_t offset,
-                 size_t length, dispatch_queue_t q, dispatch_io_handler_t h) {
-  SCOPED_TSAN_INTERCEPTOR(dispatch_io_read, channel, offset, length, q, h);
-  __block block_context_t new_context = {
-      q, nullptr, &invoke_block, false, false, false, 0};
-  dispatch_io_handler_t new_h =
-      Block_copy(^(bool done, dispatch_data_t data, int error) {
-        new_context.orig_context = ^(void) {
-          h(done, data, error);
-        };
-        dispatch_callback_wrap(&new_context);
-      });
-  uptr submit_sync = (uptr)&new_context;
-  Release(thr, pc, submit_sync);
-  REAL(dispatch_io_read)(channel, offset, length, q, new_h);
-  Block_release(new_h);
-}
-
-TSAN_INTERCEPTOR(void, dispatch_io_write, dispatch_io_t channel, off_t offset,
-                 dispatch_data_t data, dispatch_queue_t q,
-                 dispatch_io_handler_t h) {
-  SCOPED_TSAN_INTERCEPTOR(dispatch_io_write, channel, offset, data, q, h);
-  __block block_context_t new_context = {
-      q, nullptr, &invoke_block, false, false, false, 0};
-  dispatch_io_handler_t new_h =
-      Block_copy(^(bool done, dispatch_data_t data, int error) {
-        new_context.orig_context = ^(void) {
-          h(done, data, error);
-        };
-        dispatch_callback_wrap(&new_context);
-      });
-  uptr submit_sync = (uptr)&new_context;
-  Release(thr, pc, submit_sync);
-  REAL(dispatch_io_write)(channel, offset, data, q, new_h);
-  Block_release(new_h);
-}
-
-TSAN_INTERCEPTOR(void, dispatch_io_barrier, dispatch_io_t channel,
-                 dispatch_block_t barrier) {
-  SCOPED_TSAN_INTERCEPTOR(dispatch_io_barrier, channel, barrier);
-  __block block_context_t new_context = {
-      nullptr, nullptr, &invoke_block, false, false, false, 0};
-  new_context.non_queue_sync_object = (uptr)channel;
-  new_context.is_barrier_block = true;
-  dispatch_block_t new_block = Block_copy(^(void) {
-    new_context.orig_context = ^(void) {
-      barrier();
-    };
-    dispatch_callback_wrap(&new_context);
-  });
-  uptr submit_sync = (uptr)&new_context;
-  Release(thr, pc, submit_sync);
-  REAL(dispatch_io_barrier)(channel, new_block);
-  Block_release(new_block);
-}
-
-TSAN_INTERCEPTOR(dispatch_io_t, dispatch_io_create, dispatch_io_type_t type,
-                 dispatch_fd_t fd, dispatch_queue_t q, cleanup_handler_t h) {
-  SCOPED_TSAN_INTERCEPTOR(dispatch_io_create, type, fd, q, h);
-  __block dispatch_io_t new_channel = nullptr;
-  __block block_context_t new_context = {
-      q, nullptr, &invoke_block, false, false, false, 0};
-  cleanup_handler_t new_h = Block_copy(^(int error) {
-    {
-      SCOPED_INTERCEPTOR_RAW(dispatch_io_create_callback);
-      Acquire(thr, pc, (uptr)new_channel);  // Release() in dispatch_io_close.
-    }
-    new_context.orig_context = ^(void) {
-      h(error);
-    };
-    dispatch_callback_wrap(&new_context);
-  });
-  uptr submit_sync = (uptr)&new_context;
-  Release(thr, pc, submit_sync);
-  new_channel = REAL(dispatch_io_create)(type, fd, q, new_h);
-  Block_release(new_h);
-  return new_channel;
-}
-
-TSAN_INTERCEPTOR(dispatch_io_t, dispatch_io_create_with_path,
-                 dispatch_io_type_t type, const char *path, int oflag,
-                 mode_t mode, dispatch_queue_t q, cleanup_handler_t h) {
-  SCOPED_TSAN_INTERCEPTOR(dispatch_io_create_with_path, type, path, oflag, mode,
-                          q, h);
-  __block dispatch_io_t new_channel = nullptr;
-  __block block_context_t new_context = {
-      q, nullptr, &invoke_block, false, false, false, 0};
-  cleanup_handler_t new_h = Block_copy(^(int error) {
-    {
-      SCOPED_INTERCEPTOR_RAW(dispatch_io_create_callback);
-      Acquire(thr, pc, (uptr)new_channel);  // Release() in dispatch_io_close.
-    }
-    new_context.orig_context = ^(void) {
-      h(error);
-    };
-    dispatch_callback_wrap(&new_context);
-  });
-  uptr submit_sync = (uptr)&new_context;
-  Release(thr, pc, submit_sync);
-  new_channel =
-      REAL(dispatch_io_create_with_path)(type, path, oflag, mode, q, new_h);
-  Block_release(new_h);
-  return new_channel;
-}
-
-TSAN_INTERCEPTOR(dispatch_io_t, dispatch_io_create_with_io,
-                 dispatch_io_type_t type, dispatch_io_t io, dispatch_queue_t q,
-                 cleanup_handler_t h) {
-  SCOPED_TSAN_INTERCEPTOR(dispatch_io_create_with_io, type, io, q, h);
-  __block dispatch_io_t new_channel = nullptr;
-  __block block_context_t new_context = {
-      q, nullptr, &invoke_block, false, false, false, 0};
-  cleanup_handler_t new_h = Block_copy(^(int error) {
-    {
-      SCOPED_INTERCEPTOR_RAW(dispatch_io_create_callback);
-      Acquire(thr, pc, (uptr)new_channel);  // Release() in dispatch_io_close.
-    }
-    new_context.orig_context = ^(void) {
-      h(error);
-    };
-    dispatch_callback_wrap(&new_context);
-  });
-  uptr submit_sync = (uptr)&new_context;
-  Release(thr, pc, submit_sync);
-  new_channel = REAL(dispatch_io_create_with_io)(type, io, q, new_h);
-  Block_release(new_h);
-  return new_channel;
-}
-
-TSAN_INTERCEPTOR(void, dispatch_io_close, dispatch_io_t channel,
-                 dispatch_io_close_flags_t flags) {
-  SCOPED_TSAN_INTERCEPTOR(dispatch_io_close, channel, flags);
-  Release(thr, pc, (uptr)channel);  // Acquire() in dispatch_io_create[_*].
-  return REAL(dispatch_io_close)(channel, flags);
-}
-
-// Resuming a suspended queue needs to synchronize with all subsequent
-// executions of blocks in that queue.
-TSAN_INTERCEPTOR(void, dispatch_resume, dispatch_object_t o) {
-  SCOPED_TSAN_INTERCEPTOR(dispatch_resume, o);
-  Release(thr, pc, (uptr)o);  // Synchronizes with the Acquire() on serial_sync
-                              // in dispatch_sync_pre_execute
-  return REAL(dispatch_resume)(o);
-}
-
-void InitializeLibdispatchInterceptors() {
-  INTERCEPT_FUNCTION(dispatch_async);
-  INTERCEPT_FUNCTION(dispatch_async_f);
-  INTERCEPT_FUNCTION(dispatch_sync);
-  INTERCEPT_FUNCTION(dispatch_sync_f);
-  INTERCEPT_FUNCTION(dispatch_barrier_async);
-  INTERCEPT_FUNCTION(dispatch_barrier_async_f);
-  INTERCEPT_FUNCTION(dispatch_barrier_sync);
-  INTERCEPT_FUNCTION(dispatch_barrier_sync_f);
-  INTERCEPT_FUNCTION(dispatch_after);
-  INTERCEPT_FUNCTION(dispatch_after_f);
-  INTERCEPT_FUNCTION(dispatch_once);
-  INTERCEPT_FUNCTION(dispatch_once_f);
-  INTERCEPT_FUNCTION(dispatch_semaphore_signal);
-  INTERCEPT_FUNCTION(dispatch_semaphore_wait);
-  INTERCEPT_FUNCTION(dispatch_group_wait);
-  INTERCEPT_FUNCTION(dispatch_group_leave);
-  INTERCEPT_FUNCTION(dispatch_group_async);
-  INTERCEPT_FUNCTION(dispatch_group_async_f);
-  INTERCEPT_FUNCTION(dispatch_group_notify);
-  INTERCEPT_FUNCTION(dispatch_group_notify_f);
-  INTERCEPT_FUNCTION(dispatch_source_set_event_handler);
-  INTERCEPT_FUNCTION(dispatch_source_set_event_handler_f);
-  INTERCEPT_FUNCTION(dispatch_source_set_cancel_handler);
-  INTERCEPT_FUNCTION(dispatch_source_set_cancel_handler_f);
-  INTERCEPT_FUNCTION(dispatch_source_set_registration_handler);
-  INTERCEPT_FUNCTION(dispatch_source_set_registration_handler_f);
-  INTERCEPT_FUNCTION(dispatch_apply);
-  INTERCEPT_FUNCTION(dispatch_apply_f);
-  INTERCEPT_FUNCTION(dispatch_data_create);
-  INTERCEPT_FUNCTION(dispatch_read);
-  INTERCEPT_FUNCTION(dispatch_write);
-  INTERCEPT_FUNCTION(dispatch_io_read);
-  INTERCEPT_FUNCTION(dispatch_io_write);
-  INTERCEPT_FUNCTION(dispatch_io_barrier);
-  INTERCEPT_FUNCTION(dispatch_io_create);
-  INTERCEPT_FUNCTION(dispatch_io_create_with_path);
-  INTERCEPT_FUNCTION(dispatch_io_create_with_io);
-  INTERCEPT_FUNCTION(dispatch_io_close);
-  INTERCEPT_FUNCTION(dispatch_resume);
-}
-
-}  // namespace __tsan
index d146e1cc35f88dcb01b985fccbda236cab9a490c..72857b773fed62299dd270b60ddd9b3584643190 100644 (file)
@@ -29,7 +29,7 @@ namespace __tsan {
   SET(n)
 
 typedef unsigned int MD5_u32plus;
-typedef unsigned long ulong_t;  // NOLINT
+typedef unsigned long ulong_t;
 
 typedef struct {
   MD5_u32plus lo, hi;
index 467aabdf2b9d8e8ff6eda988d065498d4e0a2206..a5280d4472c9a8c742f6ee2d0d5ad4f9370e47f0 100644 (file)
@@ -79,11 +79,10 @@ enum MBlockType {
 void *internal_alloc(MBlockType typ, uptr sz);
 void internal_free(void *p);
 
-template<typename T>
-void DestroyAndFree(T *&p) {
+template <typename T>
+void DestroyAndFree(T *p) {
   p->~T();
   internal_free(p);
-  p = 0;
 }
 
 }  // namespace __tsan
index 3ed3c847a9a06573c6d709cae67661fe15a6b169..fc44a5221b5b0ff901988f9f5711bc2ae8ec9f85 100644 (file)
@@ -17,7 +17,7 @@
 #include "tsan_interceptors.h"
 #include "tsan_rtl.h"
 
-using namespace __tsan;  // NOLINT
+using namespace __tsan;
 
 namespace std {
 struct nothrow_t {};
index 0d106c4147c8895ff3728b1621827ef05c4bf11c..63eb14fcd3402abb8426ecfc30f2a62c4e32c9a7 100644 (file)
@@ -457,6 +457,8 @@ struct Mapping47 {
   static const uptr kAppMemEnd     = 0x00e000000000ull;
 };
 
+#define TSAN_RUNTIME_VMA 1
+
 #elif SANITIZER_GO && defined(__aarch64__)
 
 /* Go on linux/aarch64 (48-bit VMA)
index 655aa5f9123b287fc83a0b75d3991f783da9ae4d..368f1ca8adf2cb4b8eaa3dbbf8133b5f005f3848 100644 (file)
@@ -298,7 +298,7 @@ static bool FrameIsInternal(const SymbolizedStack *frame) {
   const char *file = frame->info.file;
   const char *module = frame->info.module;
   if (file != 0 &&
-      (internal_strstr(file, "tsan_interceptors.cpp") ||
+      (internal_strstr(file, "tsan_interceptors_posix.cpp") ||
        internal_strstr(file, "sanitizer_common_interceptors.inc") ||
        internal_strstr(file, "tsan_interface_")))
     return true;
index 1ac3907094b9ec2b954dffebd31e53b04545176a..3f3c0cce119c13ff665599eeff14d8b564ea9e22 100644 (file)
@@ -239,6 +239,15 @@ void DontNeedShadowFor(uptr addr, uptr size) {
   ReleaseMemoryPagesToOS(MemToShadow(addr), MemToShadow(addr + size));
 }
 
+#if !SANITIZER_GO
+void UnmapShadow(ThreadState *thr, uptr addr, uptr size) {
+  if (size == 0) return;
+  DontNeedShadowFor(addr, size);
+  ScopedGlobalProcessor sgp;
+  ctx->metamap.ResetRange(thr->proc(), addr, size);
+}
+#endif
+
 void MapShadow(uptr addr, uptr size) {
   // Global data is not 64K aligned, but there are no adjacent mappings,
   // so we can get away with unaligned mapping.
@@ -329,7 +338,7 @@ static void CheckShadowMapping() {
 #if !SANITIZER_GO
 static void OnStackUnwind(const SignalContext &sig, const void *,
                           BufferedStackTrace *stack) {
-  stack->Unwind(sig.pc, sig.bp, sig.context,
+  stack->Unwind(StackTrace::GetNextInstructionPc(sig.pc), sig.bp, sig.context,
                 common_flags()->fast_unwind_on_fatal);
 }
 
@@ -987,6 +996,14 @@ void MemoryRangeImitateWrite(ThreadState *thr, uptr pc, uptr addr, uptr size) {
   MemoryRangeSet(thr, pc, addr, size, s.raw());
 }
 
+void MemoryRangeImitateWriteOrResetRange(ThreadState *thr, uptr pc, uptr addr,
+                                         uptr size) {
+  if (thr->ignore_reads_and_writes == 0)
+    MemoryRangeImitateWrite(thr, pc, addr, size);
+  else
+    MemoryResetRange(thr, pc, addr, size);
+}
+
 ALWAYS_INLINE USED
 void FuncEntry(ThreadState *thr, uptr pc) {
   StatInc(thr, StatFuncEnter);
index 3a8231bda9a9cc7f5bfb16c27ca7ab6bcceba25b..c38fc43a9f848726ae40562b3de465d0a0a1d4bf 100644 (file)
@@ -238,7 +238,7 @@ class Shadow : public FastState {
       unsigned kS2AccessSize) {
     bool res = false;
     u64 diff = s1.addr0() - s2.addr0();
-    if ((s64)diff < 0) {  // s1.addr0 < s2.addr0  // NOLINT
+    if ((s64)diff < 0) {  // s1.addr0 < s2.addr0
       // if (s1.addr0() + size1) > s2.addr0()) return true;
       if (s1.size() > -diff)
         res = true;
@@ -680,6 +680,7 @@ void ALWAYS_INLINE StatSet(ThreadState *thr, StatType typ, u64 n) {
 void MapShadow(uptr addr, uptr size);
 void MapThreadTrace(uptr addr, uptr size, const char *name);
 void DontNeedShadowFor(uptr addr, uptr size);
+void UnmapShadow(ThreadState *thr, uptr addr, uptr size);
 void InitializeShadowMemory();
 void InitializeInterceptors();
 void InitializeLibIgnore();
@@ -759,6 +760,8 @@ void ALWAYS_INLINE MemoryWriteAtomic(ThreadState *thr, uptr pc,
 void MemoryResetRange(ThreadState *thr, uptr pc, uptr addr, uptr size);
 void MemoryRangeFreed(ThreadState *thr, uptr pc, uptr addr, uptr size);
 void MemoryRangeImitateWrite(ThreadState *thr, uptr pc, uptr addr, uptr size);
+void MemoryRangeImitateWriteOrResetRange(ThreadState *thr, uptr pc, uptr addr,
+                                         uptr size);
 
 void ThreadIgnoreBegin(ThreadState *thr, uptr pc, bool save_stack = true);
 void ThreadIgnoreEnd(ThreadState *thr, uptr pc);
index 9e533a71a9c477ecae59f09ab431b2664554d998..8285e21aa1ec7a797dfcf4840ee5a7851106b497 100644 (file)
@@ -1,6 +1,5 @@
 #include "tsan_ppc_regs.h"
 
-        .machine altivec
         .section .text
         .hidden __tsan_setjmp
         .globl _setjmp
index 47b8bf77dca0e2c517e941143a8927b06a4855f3..949beac1c5513f712a11094d9442ef240a96f3e3 100644 (file)
@@ -27,7 +27,7 @@
 
 namespace __tsan {
 
-using namespace __sanitizer;  // NOLINT
+using namespace __sanitizer;
 
 static ReportStack *SymbolizeStack(StackTrace trace);
 
@@ -154,6 +154,7 @@ ScopedReportBase::ScopedReportBase(ReportType typ, uptr tag) {
 ScopedReportBase::~ScopedReportBase() {
   ctx->report_mtx.Unlock();
   DestroyAndFree(rep_);
+  rep_ = nullptr;
 }
 
 void ScopedReportBase::AddStack(StackTrace stack, bool suppressable) {
@@ -700,7 +701,7 @@ void ReportRace(ThreadState *thr) {
   rep.AddLocation(addr_min, addr_max - addr_min);
 
 #if !SANITIZER_GO
-  {  // NOLINT
+  {
     Shadow s(thr->racy_state[1]);
     if (s.epoch() <= thr->last_sleep_clock.get(s.tid()))
       rep.AddSleep(thr->last_sleep_stack_id);
index 6bf6720210a1d25a5ce1766c283273ff379cf09a..a1c1bf81bf670af8a103214dba6b89e4c8076c42 100644 (file)
@@ -50,7 +50,7 @@ static const char *kSuppressionTypes[] = {
 
 void InitializeSuppressions() {
   CHECK_EQ(nullptr, suppression_ctx);
-  suppression_ctx = new (suppression_placeholder) // NOLINT
+  suppression_ctx = new (suppression_placeholder)
       SuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes));
   suppression_ctx->ParseFromFile(flags()->suppressions);
 #if !SANITIZER_GO
index 7e7216c5b4ab7bc6e3583978beaedb0a2344e408..33a8dfcde0269a013f57e2a6b25b47f5ade7fd5b 100644 (file)
 
 UBSAN_CHECK(GenericUB, "undefined-behavior", "undefined")
 UBSAN_CHECK(NullPointerUse, "null-pointer-use", "null")
+UBSAN_CHECK(NullptrWithOffset, "nullptr-with-offset", "pointer-overflow")
+UBSAN_CHECK(NullptrWithNonZeroOffset, "nullptr-with-nonzero-offset",
+            "pointer-overflow")
+UBSAN_CHECK(NullptrAfterNonZeroOffset, "nullptr-after-nonzero-offset",
+            "pointer-overflow")
 UBSAN_CHECK(PointerOverflow, "pointer-overflow", "pointer-overflow")
 UBSAN_CHECK(MisalignedPointerUse, "misaligned-pointer-use", "alignment")
 UBSAN_CHECK(AlignmentAssumption, "alignment-assumption", "alignment")
index c8f7960db42acd3466fc372c387f4fab94f839c8..1b2828d236d6e977a0aec0673da2c890876629c3 100644 (file)
@@ -404,7 +404,7 @@ static const char *kSuppressionTypes[] = {
 
 void __ubsan::InitializeSuppressions() {
   CHECK_EQ(nullptr, suppression_ctx);
-  suppression_ctx = new (suppression_placeholder) // NOLINT
+  suppression_ctx = new (suppression_placeholder)
       SuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes));
   suppression_ctx->ParseFromFile(flags()->suppressions);
 }
index 80de2a6d10169c2f58bc855ef11918bca3f58981..721c2273f133a3b4f7158b7e7297d7e9078eaffa 100644 (file)
@@ -54,7 +54,6 @@ void InitializeFlags() {
   {
     CommonFlags cf;
     cf.CopyFrom(*common_flags());
-    cf.print_summary = false;
     cf.external_symbolizer_path = GetFlag("UBSAN_SYMBOLIZER_PATH");
     OverrideCommonFlags(cf);
   }
index 6099e3631e7342e0547809b087a55a310b6d701a..3f9da75a12a8d34386977ba9e959eda2af27f298 100644 (file)
@@ -691,14 +691,33 @@ static void handlePointerOverflowImpl(PointerOverflowData *Data,
                                       ValueHandle Result,
                                       ReportOptions Opts) {
   SourceLocation Loc = Data->Loc.acquire();
-  ErrorType ET = ErrorType::PointerOverflow;
+  ErrorType ET;
+
+  if (Base == 0 && Result == 0)
+    ET = ErrorType::NullptrWithOffset;
+  else if (Base == 0 && Result != 0)
+    ET = ErrorType::NullptrWithNonZeroOffset;
+  else if (Base != 0 && Result == 0)
+    ET = ErrorType::NullptrAfterNonZeroOffset;
+  else
+    ET = ErrorType::PointerOverflow;
 
   if (ignoreReport(Loc, Opts, ET))
     return;
 
   ScopedReport R(Opts, Loc, ET);
 
-  if ((sptr(Base) >= 0) == (sptr(Result) >= 0)) {
+  if (ET == ErrorType::NullptrWithOffset) {
+    Diag(Loc, DL_Error, ET, "applying zero offset to null pointer");
+  } else if (ET == ErrorType::NullptrWithNonZeroOffset) {
+    Diag(Loc, DL_Error, ET, "applying non-zero offset %0 to null pointer")
+        << Result;
+  } else if (ET == ErrorType::NullptrAfterNonZeroOffset) {
+    Diag(
+        Loc, DL_Error, ET,
+        "applying non-zero offset to non-null pointer %0 produced null pointer")
+        << (void *)Base;
+  } else if ((sptr(Base) >= 0) == (sptr(Result) >= 0)) {
     if (Base > Result)
       Diag(Loc, DL_Error, ET,
            "addition of unsigned offset to %0 overflowed to %1")
@@ -800,21 +819,6 @@ void __ubsan_handle_cfi_bad_type(CFICheckFailData *Data, ValueHandle Vtable,
 
 }  // namespace __ubsan
 
-void __ubsan::__ubsan_handle_cfi_bad_icall(CFIBadIcallData *CallData,
-                                           ValueHandle Function) {
-  GET_REPORT_OPTIONS(false);
-  CFICheckFailData Data = {CFITCK_ICall, CallData->Loc, CallData->Type};
-  handleCFIBadIcall(&Data, Function, Opts);
-}
-
-void __ubsan::__ubsan_handle_cfi_bad_icall_abort(CFIBadIcallData *CallData,
-                                                 ValueHandle Function) {
-  GET_REPORT_OPTIONS(true);
-  CFICheckFailData Data = {CFITCK_ICall, CallData->Loc, CallData->Type};
-  handleCFIBadIcall(&Data, Function, Opts);
-  Die();
-}
-
 void __ubsan::__ubsan_handle_cfi_check_fail(CFICheckFailData *Data,
                                             ValueHandle Value,
                                             uptr ValidVtable) {
index eba1cf918fc34796fdaaf0d458984e197758e43c..22ca96422381c104798588f64c5ae370f3ef2f07 100644 (file)
@@ -207,20 +207,12 @@ enum CFITypeCheckKind : unsigned char {
   CFITCK_VMFCall,
 };
 
-struct CFIBadIcallData {
-  SourceLocation Loc;
-  const TypeDescriptor &Type;
-};
-
 struct CFICheckFailData {
   CFITypeCheckKind CheckKind;
   SourceLocation Loc;
   const TypeDescriptor &Type;
 };
 
-/// \brief Handle control flow integrity failure for indirect function calls.
-RECOVERABLE(cfi_bad_icall, CFIBadIcallData *Data, ValueHandle Function)
-
 /// \brief Handle control flow integrity failures.
 RECOVERABLE(cfi_check_fail, CFICheckFailData *Data, ValueHandle Function,
             uptr VtableIsValid)
index 58aabbe67b5c25e0b47b03a848182691de2252a7..71d7fb18c9b3a5e94039e3843113050f31fa1c9f 100644 (file)
@@ -12,7 +12,6 @@
 #ifndef UBSAN_PLATFORM_H
 #define UBSAN_PLATFORM_H
 
-#ifndef CAN_SANITIZE_UB
 // Other platforms should be easy to add, and probably work as-is.
 #if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) ||        \
     defined(__NetBSD__) || defined(__OpenBSD__) || \
@@ -22,6 +21,5 @@
 #else
 # define CAN_SANITIZE_UB 0
 #endif
-#endif //CAN_SANITIZE_UB
 
 #endif
index 627b3c4d89bb0ec02fbf20c017b652ad3882acc8..2c91db8ca3974841a2314b86a97b6d259c9e0d9c 100644 (file)
@@ -45,8 +45,9 @@ namespace __ubsan {
 
 static void OnStackUnwind(const SignalContext &sig, const void *,
                           BufferedStackTrace *stack) {
-  ubsan_GetStackTrace(stack, kStackTraceMax, sig.pc, sig.bp, sig.context,
-                common_flags()->fast_unwind_on_fatal);
+  ubsan_GetStackTrace(stack, kStackTraceMax,
+                      StackTrace::GetNextInstructionPc(sig.pc), sig.bp,
+                      sig.context, common_flags()->fast_unwind_on_fatal);
 }
 
 static void UBsanOnDeadlySignal(int signo, void *siginfo, void *context) {