Commit ac20506090

Alex Rønne Petersen <alex@alexrp.com>
2025-07-16 11:22:46
libtsan: update to LLVM 21
1 parent 85438e7
lib/libtsan/builtins/assembly.h
@@ -61,7 +61,7 @@
 #define LOCAL_LABEL(name) .L ## name
 #define FILE_LEVEL_DIRECTIVE
 #define SYMBOL_IS_FUNC(name)                                                   \
-  .def name SEPARATOR                                                          \
+  .def FUNC_SYMBOL(name) SEPARATOR                                             \
     .scl 2 SEPARATOR                                                           \
     .type 32 SEPARATOR                                                         \
   .endef
@@ -71,7 +71,7 @@
 
 #endif
 
-#if defined(__arm__) || defined(__aarch64__)
+#if defined(__arm__) || defined(__aarch64__) || defined(__arm64ec__)
 #define FUNC_ALIGN                                                             \
   .text SEPARATOR                                                              \
   .balign 16 SEPARATOR
@@ -194,6 +194,23 @@
 #else
 #define WIDE(op) op
 #endif
+
+#if defined(__ARM_FEATURE_PAC_DEFAULT) && defined(__ARM_FEATURE_BTI_DEFAULT)
+#define PACBTI_LANDING pacbti r12, lr, sp
+#elif defined(__ARM_FEATURE_PAC_DEFAULT)
+#define PACBTI_LANDING pac r12, lr, sp
+#elif defined(__ARM_FEATURE_BTI_DEFAULT)
+#define PACBTI_LANDING bti
+#else
+#define PACBTI_LANDING
+#endif
+
+#if defined(__ARM_FEATURE_PAUTH)
+#define PAC_RETURN bxaut r12, lr, sp
+#else
+#define PAC_RETURN aut r12, lr, sp SEPARATOR bx lr
+#endif
+
 #else // !defined(__arm)
 #define DECLARE_FUNC_ENCODING
 #define DEFINE_CODE_STATE
@@ -208,6 +225,16 @@
 #define GLUE4(a, b, c, d) GLUE4_(a, b, c, d)
 
 #define SYMBOL_NAME(name) GLUE(__USER_LABEL_PREFIX__, name)
+#ifndef __arm64ec__
+#define FUNC_SYMBOL(name) name
+#else
+// On ARM64EC, function names and calls (but not address-taking or data symbol
+// references) use symbols prefixed with "#".
+#define QUOTE(a) #a
+#define STR(a) QUOTE(a)
+#define HASH #
+#define FUNC_SYMBOL(name) STR(GLUE2(HASH, name))
+#endif
 
 #ifdef VISIBILITY_HIDDEN
 #define DECLARE_SYMBOL_VISIBILITY(name)                                        \
@@ -222,54 +249,54 @@
 #define DEFINE_COMPILERRT_FUNCTION(name)                                       \
   DEFINE_CODE_STATE                                                            \
   FILE_LEVEL_DIRECTIVE SEPARATOR                                               \
-  .globl SYMBOL_NAME(name) SEPARATOR                                           \
+  .globl FUNC_SYMBOL(SYMBOL_NAME(name)) SEPARATOR                              \
   SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR                                  \
   DECLARE_SYMBOL_VISIBILITY(name)                                              \
   DECLARE_FUNC_ENCODING                                                        \
-  SYMBOL_NAME(name):
+  FUNC_SYMBOL(SYMBOL_NAME(name)):
 
 #define DEFINE_COMPILERRT_THUMB_FUNCTION(name)                                 \
   DEFINE_CODE_STATE                                                            \
   FILE_LEVEL_DIRECTIVE SEPARATOR                                               \
-  .globl SYMBOL_NAME(name) SEPARATOR                                           \
+  .globl FUNC_SYMBOL(SYMBOL_NAME(name)) SEPARATOR                              \
   SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR                                  \
   DECLARE_SYMBOL_VISIBILITY(name) SEPARATOR                                    \
   .thumb_func SEPARATOR                                                        \
-  SYMBOL_NAME(name):
+  FUNC_SYMBOL(SYMBOL_NAME(name)):
 
 #define DEFINE_COMPILERRT_PRIVATE_FUNCTION(name)                               \
   DEFINE_CODE_STATE                                                            \
   FILE_LEVEL_DIRECTIVE SEPARATOR                                               \
-  .globl SYMBOL_NAME(name) SEPARATOR                                           \
+  .globl FUNC_SYMBOL(SYMBOL_NAME(name)) SEPARATOR                              \
   SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR                                  \
   HIDDEN(SYMBOL_NAME(name)) SEPARATOR                                          \
   DECLARE_FUNC_ENCODING                                                        \
-  SYMBOL_NAME(name):
+  FUNC_SYMBOL(SYMBOL_NAME(name)):
 
 #define DEFINE_COMPILERRT_PRIVATE_FUNCTION_UNMANGLED(name)                     \
   DEFINE_CODE_STATE                                                            \
-  .globl name SEPARATOR                                                        \
+  .globl FUNC_SYMBOL(name) SEPARATOR                                           \
   SYMBOL_IS_FUNC(name) SEPARATOR                                               \
   HIDDEN(name) SEPARATOR                                                       \
   DECLARE_FUNC_ENCODING                                                        \
-  name:
+  FUNC_SYMBOL(name):
 
 #define DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(name)                     \
   DEFINE_CODE_STATE                                                            \
   FUNC_ALIGN                                                                   \
-  .globl name SEPARATOR                                                        \
+  .globl FUNC_SYMBOL(name) SEPARATOR                                           \
   SYMBOL_IS_FUNC(name) SEPARATOR                                               \
-  DECLARE_SYMBOL_VISIBILITY_UNMANGLED(name) SEPARATOR                          \
+  DECLARE_SYMBOL_VISIBILITY_UNMANGLED(FUNC_SYMBOL(name)) SEPARATOR             \
   DECLARE_FUNC_ENCODING                                                        \
-  name:                                                                        \
+  FUNC_SYMBOL(name):                                                           \
   SEPARATOR CFI_START                                                          \
   SEPARATOR BTI_C
 
 #define DEFINE_COMPILERRT_FUNCTION_ALIAS(name, target)                         \
-  .globl SYMBOL_NAME(name) SEPARATOR                                           \
+  .globl FUNC_SYMBOL(SYMBOL_NAME(name)) SEPARATOR                              \
   SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR                                  \
   DECLARE_SYMBOL_VISIBILITY(name) SEPARATOR                                    \
-  .set SYMBOL_NAME(name), SYMBOL_NAME(target) SEPARATOR
+  .set FUNC_SYMBOL(SYMBOL_NAME(name)), FUNC_SYMBOL(target) SEPARATOR
 
 #if defined(__ARM_EABI__)
 #define DEFINE_AEABI_FUNCTION_ALIAS(aeabi_name, name)                          \
lib/libtsan/interception/interception.h
@@ -19,7 +19,7 @@
 
 #if !SANITIZER_LINUX && !SANITIZER_FREEBSD && !SANITIZER_APPLE &&    \
     !SANITIZER_NETBSD && !SANITIZER_WINDOWS && !SANITIZER_FUCHSIA && \
-    !SANITIZER_SOLARIS
+    !SANITIZER_SOLARIS && !SANITIZER_HAIKU && !SANITIZER_AIX
 #  error "Interception doesn't work on this operating system."
 #endif
 
@@ -168,6 +168,16 @@ const interpose_substitution substitution_##func_name[]             \
     extern "C" ret_type func(__VA_ARGS__);
 # define DECLARE_WRAPPER_WINAPI(ret_type, func, ...)  \
     extern "C" __declspec(dllimport) ret_type __stdcall func(__VA_ARGS__);
+#elif SANITIZER_AIX
+#  define WRAP(x) __interceptor_##x
+#  define TRAMPOLINE(x) WRAP(x)
+// # define WRAPPER_NAME(x) "__interceptor_" #x
+#  define INTERCEPTOR_ATTRIBUTE __attribute__((visibility("default")))
+// AIX's linker will not select the weak symbol, so don't use weak for the
+// interceptors.
+#  define DECLARE_WRAPPER(ret_type, func, ...) \
+    extern "C" ret_type func(__VA_ARGS__)      \
+        __attribute__((alias("__interceptor_" #func), visibility("default")));
 #elif !SANITIZER_FUCHSIA  // LINUX, FREEBSD, NETBSD, SOLARIS
 # define INTERCEPTOR_ATTRIBUTE __attribute__((visibility("default")))
 # if ASM_INTERCEPTOR_TRAMPOLINE_SUPPORT
@@ -367,12 +377,17 @@ inline void DoesNotSupportStaticLinking() {}
 
 #define INCLUDED_FROM_INTERCEPTION_LIB
 
-#if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \
-    SANITIZER_SOLARIS
+#if SANITIZER_AIX
+#  include "interception_aix.h"
+#  define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_AIX(func)
+#  define INTERCEPT_FUNCTION_VER(func, symver) INTERCEPT_FUNCTION_AIX(func)
 
-# include "interception_linux.h"
-# define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func)
-# define INTERCEPT_FUNCTION_VER(func, symver) \
+#elif SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \
+    SANITIZER_SOLARIS || SANITIZER_HAIKU
+
+#  include "interception_linux.h"
+#  define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func)
+#  define INTERCEPT_FUNCTION_VER(func, symver) \
     INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver)
 #elif SANITIZER_APPLE
 # include "interception_mac.h"
lib/libtsan/interception/interception_aix.cpp
@@ -0,0 +1,45 @@
+//===-- interception_aix.cpp ------------------------------------*- 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 AddressSanitizer, an address sanity checker.
+//
+// AIX-specific interception methods.
+//===----------------------------------------------------------------------===//
+
+#include "interception.h"
+#include "sanitizer_common/sanitizer_common.h"
+
+#if SANITIZER_AIX
+
+#  include <dlfcn.h>  // for dlsym()
+
+namespace __interception {
+
+static void *GetFuncAddr(const char *name, uptr wrapper_addr) {
+  // AIX dlsym can only defect the functions that are exported, so
+  // on AIX, we can not intercept some basic functions like memcpy.
+  // FIXME: if we are going to ship dynamic asan library, we may need to search
+  // all the loaded modules with RTLD_DEFAULT if RTLD_NEXT failed.
+  void *addr = dlsym(RTLD_NEXT, name);
+
+  // In case `name' is not loaded, dlsym ends up finding the actual wrapper.
+  // We don't want to intercept the wrapper and have it point to itself.
+  if ((uptr)addr == wrapper_addr)
+    addr = nullptr;
+  return addr;
+}
+
+bool InterceptFunction(const char *name, uptr *ptr_to_real, uptr func,
+                       uptr wrapper) {
+  void *addr = GetFuncAddr(name, wrapper);
+  *ptr_to_real = (uptr)addr;
+  return addr && (func == wrapper);
+}
+
+}  // namespace __interception
+#endif  // SANITIZER_AIX
lib/libtsan/interception/interception_aix.h
@@ -0,0 +1,36 @@
+//===-- interception_aix.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 AddressSanitizer, an address sanity checker.
+//
+// AIX-specific interception methods.
+//===----------------------------------------------------------------------===//
+
+#if SANITIZER_AIX
+
+#  if !defined(INCLUDED_FROM_INTERCEPTION_LIB)
+#    error \
+        "interception_aix.h should be included from interception library only"
+#  endif
+
+#  ifndef INTERCEPTION_AIX_H
+#    define INTERCEPTION_AIX_H
+
+namespace __interception {
+bool InterceptFunction(const char *name, uptr *ptr_to_real, uptr func,
+                       uptr wrapper);
+}  // namespace __interception
+
+#    define INTERCEPT_FUNCTION_AIX(func)                \
+      ::__interception::InterceptFunction(              \
+          #func, (::__interception::uptr *)&REAL(func), \
+          (::__interception::uptr) & (func),            \
+          (::__interception::uptr) & WRAP(func))
+
+#  endif  // INTERCEPTION_AIX_H
+#endif    // SANITIZER_AIX
lib/libtsan/interception/interception_linux.cpp
@@ -14,7 +14,7 @@
 #include "interception.h"
 
 #if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \
-    SANITIZER_SOLARIS
+    SANITIZER_SOLARIS || SANITIZER_HAIKU
 
 #include <dlfcn.h>   // for dlsym() and dlvsym()
 
@@ -80,4 +80,4 @@ bool InterceptFunction(const char *name, const char *ver, uptr *ptr_to_real,
 }  // namespace __interception
 
 #endif  // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD ||
-        // SANITIZER_SOLARIS
+        // SANITIZER_SOLARIS || SANITIZER_HAIKU
lib/libtsan/interception/interception_linux.h
@@ -12,7 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \
-    SANITIZER_SOLARIS
+    SANITIZER_SOLARIS || SANITIZER_HAIKU
 
 #if !defined(INCLUDED_FROM_INTERCEPTION_LIB)
 # error interception_linux.h should be included from interception library only
@@ -52,4 +52,4 @@ bool InterceptFunction(const char *name, const char *ver, uptr *ptr_to_real,
 
 #endif  // INTERCEPTION_LINUX_H
 #endif  // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD ||
-        // SANITIZER_SOLARIS
+        // SANITIZER_SOLARIS || SANITIZER_HAIKU
lib/libtsan/interception/interception_win.cpp
@@ -646,6 +646,7 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
     case 0xC033:  // 33 C0 : xor eax, eax
     case 0xC933:  // 33 C9 : xor ecx, ecx
     case 0xD233:  // 33 D2 : xor edx, edx
+    case 0x9066:  // 66 90 : xchg %ax,%ax (Two-byte NOP)
     case 0xDB84:  // 84 DB : test bl,bl
     case 0xC084:  // 84 C0 : test al,al
     case 0xC984:  // 84 C9 : test cl,cl
@@ -726,7 +727,6 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
     case 0x5541:  // push r13
     case 0x5641:  // push r14
     case 0x5741:  // push r15
-    case 0x9066:  // Two-byte NOP
     case 0xc084:  // test al, al
     case 0x018a:  // mov al, byte ptr [rcx]
       return 2;
@@ -743,6 +743,7 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
     case 0x058B:  // 8B 05 XX XX XX XX : mov eax, dword ptr [XX XX XX XX]
       if (rel_offset)
         *rel_offset = 2;
+      FALLTHROUGH;
     case 0xB841:  // 41 B8 XX XX XX XX : mov r8d, XX XX XX XX
       return 6;
 
@@ -753,6 +754,12 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
     case 0x7B81:  // 81 7B YY XX XX XX XX  cmp DWORD PTR [rbx+YY], XX XX XX XX
     case 0x7981:  // 81 79 YY XX XX XX XX  cmp dword ptr [rcx+YY], XX XX XX XX
       return 7;
+
+    case 0xb848:  // 48 b8 XX XX XX XX XX XX XX XX :
+                  //   movabsq XX XX XX XX XX XX XX XX, rax
+    case 0xba48:  // 48 ba XX XX XX XX XX XX XX XX :
+                  //   movabsq XX XX XX XX XX XX XX XX, rdx
+      return 10;
   }
 
   switch (0x00FFFFFF & *(u32 *)address) {
lib/libtsan/sanitizer_common/sanitizer_allocator_internal.h
@@ -23,7 +23,7 @@ namespace __sanitizer {
 typedef CompactSizeClassMap InternalSizeClassMap;
 
 struct AP32 {
-  static const uptr kSpaceBeg = 0;
+  static const uptr kSpaceBeg = SANITIZER_MMAP_BEGIN;
   static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE;
   static const uptr kMetadataSize = 0;
   typedef InternalSizeClassMap SizeClassMap;
lib/libtsan/sanitizer_common/sanitizer_allocator_local_cache.h
@@ -166,7 +166,7 @@ struct SizeClassAllocator32LocalCache {
       DCHECK_GT(c->count, 0);
     }
     void *res = c->batch[--c->count];
-    PREFETCH(c->batch[c->count - 1]);
+    PREFETCH(c->batch[c->count > 0 ? c->count - 1 : 0]);
     stats_.Add(AllocatorStatAllocated, c->class_size);
     return res;
   }
lib/libtsan/sanitizer_common/sanitizer_atomic_clang.h
@@ -14,6 +14,18 @@
 #ifndef SANITIZER_ATOMIC_CLANG_H
 #define SANITIZER_ATOMIC_CLANG_H
 
+// Helper to suppress warnings related to 8-byte atomic accesses when the target
+// is 32-bit AIX (where such accesses use libatomic).
+#if defined(_AIX) && !defined(__powerpc64__) && defined(__clang__)
+#  define SANITIZER_IGNORE_ATOMIC_ALIGNMENT_BEGIN \
+    _Pragma("clang diagnostic push")              \
+        _Pragma("clang diagnostic ignored \"-Watomic-alignment\"")
+#  define SANITIZER_IGNORE_ATOMIC_ALIGNMENT_END _Pragma("clang diagnostic pop")
+#else
+#  define SANITIZER_IGNORE_ATOMIC_ALIGNMENT_BEGIN
+#  define SANITIZER_IGNORE_ATOMIC_ALIGNMENT_END
+#endif
+
 namespace __sanitizer {
 
 // We use the compiler builtin atomic operations for loads and stores, which
@@ -35,6 +47,7 @@ inline void proc_yield(int cnt) {
 #endif
 }
 
+SANITIZER_IGNORE_ATOMIC_ALIGNMENT_BEGIN
 template <typename T>
 inline typename T::Type atomic_load(const volatile T *a, memory_order mo) {
   DCHECK(mo == memory_order_relaxed || mo == memory_order_consume ||
@@ -92,6 +105,8 @@ inline bool atomic_compare_exchange_weak(volatile T *a, typename T::Type *cmp,
   return atomic_compare_exchange_strong(a, cmp, xchg, mo);
 }
 
+SANITIZER_IGNORE_ATOMIC_ALIGNMENT_END
+
 }  // namespace __sanitizer
 
 #undef ATOMIC_ORDER
lib/libtsan/sanitizer_common/sanitizer_common.h
@@ -166,7 +166,7 @@ uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding,
 
 // Used to check if we can map shadow memory to a fixed location.
 bool MemoryRangeIsAvailable(uptr range_start, uptr range_end);
-// Releases memory pages entirely within the [beg, end] address range. Noop if
+// Releases memory pages entirely within the [beg, end) address range. Noop if
 // the provided range does not contain at least one entire page.
 void ReleaseMemoryPagesToOS(uptr beg, uptr end);
 void IncreaseTotalMmap(uptr size);
@@ -925,12 +925,6 @@ class ListOfModules {
 // Callback type for iterating over a set of memory ranges.
 typedef void (*RangeIteratorCallback)(uptr begin, uptr end, void *arg);
 
-enum AndroidApiLevel {
-  ANDROID_NOT_ANDROID = 0,
-  ANDROID_LOLLIPOP_MR1 = 22,
-  ANDROID_POST_LOLLIPOP = 23
-};
-
 void WriteToSyslog(const char *buffer);
 
 #if defined(SANITIZER_WINDOWS) && defined(_MSC_VER) && !defined(__clang__)
@@ -963,19 +957,8 @@ inline void AndroidLogInit() {}
 inline void SetAbortMessage(const char *) {}
 #endif
 
-#if SANITIZER_ANDROID
-void SanitizerInitializeUnwinder();
-AndroidApiLevel AndroidGetApiLevel();
-#else
-inline void AndroidLogWrite(const char *buffer_unused) {}
-inline void SanitizerInitializeUnwinder() {}
-inline AndroidApiLevel AndroidGetApiLevel() { return ANDROID_NOT_ANDROID; }
-#endif
-
 inline uptr GetPthreadDestructorIterations() {
-#if SANITIZER_ANDROID
-  return (AndroidGetApiLevel() == ANDROID_LOLLIPOP_MR1) ? 8 : 4;
-#elif SANITIZER_POSIX
+#if SANITIZER_POSIX
   return 4;
 #else
 // Unused on Windows.
lib/libtsan/sanitizer_common/sanitizer_common_interceptors.inc
@@ -481,7 +481,8 @@ INTERCEPTOR(char*, textdomain, const char *domainname) {
 #endif
 
 #if SANITIZER_INTERCEPT_STRCMP || SANITIZER_INTERCEPT_MEMCMP
-static inline int CharCmpX(unsigned char c1, unsigned char c2) {
+[[maybe_unused]] static inline int CharCmpX(unsigned char c1,
+                                            unsigned char c2) {
   return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
 }
 #endif
@@ -953,7 +954,7 @@ INTERCEPTOR(double, frexp, double x, int *exp) {
 #define INIT_FREXP
 #endif  // SANITIZER_INTERCEPT_FREXP
 
-#if SANITIZER_INTERCEPT_FREXPF_FREXPL
+#if SANITIZER_INTERCEPT_FREXPF
 INTERCEPTOR(float, frexpf, float x, int *exp) {
   void *ctx;
   COMMON_INTERCEPTOR_ENTER(ctx, frexpf, x, exp);
@@ -963,6 +964,12 @@ INTERCEPTOR(float, frexpf, float x, int *exp) {
   return res;
 }
 
+#  define INIT_FREXPF COMMON_INTERCEPT_FUNCTION(frexpf);
+#else
+#  define INIT_FREXPF
+#endif
+
+#if SANITIZER_INTERCEPT_FREXPL
 INTERCEPTOR(long double, frexpl, long double x, int *exp) {
   void *ctx;
   COMMON_INTERCEPTOR_ENTER(ctx, frexpl, x, exp);
@@ -972,12 +979,10 @@ INTERCEPTOR(long double, frexpl, long double x, int *exp) {
   return res;
 }
 
-#define INIT_FREXPF_FREXPL           \
-  COMMON_INTERCEPT_FUNCTION(frexpf); \
-  COMMON_INTERCEPT_FUNCTION_LDBL(frexpl)
+#  define INIT_FREXPL COMMON_INTERCEPT_FUNCTION_LDBL(frexpl)
 #else
-#define INIT_FREXPF_FREXPL
-#endif  // SANITIZER_INTERCEPT_FREXPF_FREXPL
+#  define INIT_FREXPL
+#endif
 
 #if SI_POSIX
 static void write_iovec(void *ctx, struct __sanitizer_iovec *iovec,
@@ -1346,7 +1351,8 @@ INTERCEPTOR(unsigned long, time, unsigned long *t) {
 #if SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS
 static void unpoison_tm(void *ctx, __sanitizer_tm *tm) {
   COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tm, sizeof(*tm));
-#if !SANITIZER_SOLARIS
+// AIX tm struct does not have tm_zone field.
+#  if !SANITIZER_SOLARIS && !SANITIZER_AIX
   if (tm->tm_zone) {
     // Can not use COMMON_INTERCEPTOR_WRITE_RANGE here, because tm->tm_zone
     // can point to shared memory and tsan would report a data race.
@@ -1731,10 +1737,12 @@ INTERCEPTOR(int, __vsprintf_chk, char *str, int flag, SIZE_T size_to,
 VSPRINTF_INTERCEPTOR_IMPL(vsprintf, str, format, ap)
 #endif
 
+#  if SANITIZER_INTERCEPT_VASPRINTF
 INTERCEPTOR(int, vasprintf, char **strp, const char *format, va_list ap)
 VASPRINTF_INTERCEPTOR_IMPL(vasprintf, strp, format, ap)
+#  endif
 
-#if SANITIZER_INTERCEPT_ISOC99_PRINTF
+#  if SANITIZER_INTERCEPT_ISOC99_PRINTF
 INTERCEPTOR(int, __isoc99_vprintf, const char *format, va_list ap)
 VPRINTF_INTERCEPTOR_IMPL(__isoc99_vprintf, format, ap)
 
@@ -1783,10 +1791,12 @@ INTERCEPTOR(int, __snprintf_chk, char *str, SIZE_T size, int flag,
 FORMAT_INTERCEPTOR_IMPL(__snprintf_chk, vsnprintf, str, size, format)
 #endif
 
+#  if SANITIZER_INTERCEPT_ASPRINTF
 INTERCEPTOR(int, asprintf, char **strp, const char *format, ...)
 FORMAT_INTERCEPTOR_IMPL(asprintf, vasprintf, strp, format)
+#  endif
 
-#if SANITIZER_INTERCEPT_ISOC99_PRINTF
+#  if SANITIZER_INTERCEPT_ISOC99_PRINTF
 INTERCEPTOR(int, __isoc99_printf, const char *format, ...)
 FORMAT_INTERCEPTOR_IMPL(__isoc99_printf, __isoc99_vprintf, format)
 
@@ -1807,17 +1817,24 @@ FORMAT_INTERCEPTOR_IMPL(__isoc99_snprintf, __isoc99_vsnprintf, str, size,
 #endif  // SANITIZER_INTERCEPT_PRINTF
 
 #if SANITIZER_INTERCEPT_PRINTF
-#define INIT_PRINTF                     \
-  COMMON_INTERCEPT_FUNCTION_LDBL(printf);    \
-  COMMON_INTERCEPT_FUNCTION_LDBL(sprintf);   \
-  COMMON_INTERCEPT_FUNCTION_LDBL(snprintf);  \
-  COMMON_INTERCEPT_FUNCTION_LDBL(asprintf);  \
-  COMMON_INTERCEPT_FUNCTION_LDBL(fprintf);   \
-  COMMON_INTERCEPT_FUNCTION_LDBL(vprintf);   \
-  COMMON_INTERCEPT_FUNCTION_LDBL(vsprintf);  \
-  COMMON_INTERCEPT_FUNCTION_LDBL(vsnprintf); \
-  COMMON_INTERCEPT_FUNCTION_LDBL(vasprintf); \
-  COMMON_INTERCEPT_FUNCTION_LDBL(vfprintf);
+#  define INIT_PRINTF_COMMON                   \
+    COMMON_INTERCEPT_FUNCTION_LDBL(printf);    \
+    COMMON_INTERCEPT_FUNCTION_LDBL(sprintf);   \
+    COMMON_INTERCEPT_FUNCTION_LDBL(snprintf);  \
+    COMMON_INTERCEPT_FUNCTION_LDBL(fprintf);   \
+    COMMON_INTERCEPT_FUNCTION_LDBL(vprintf);   \
+    COMMON_INTERCEPT_FUNCTION_LDBL(vsprintf);  \
+    COMMON_INTERCEPT_FUNCTION_LDBL(vsnprintf); \
+    COMMON_INTERCEPT_FUNCTION_LDBL(vfprintf);
+#  if !SANITIZER_AIX
+// AIX does not have [v]asprintf.
+#    define INIT_PRINTF_EXTRA                   \
+      COMMON_INTERCEPT_FUNCTION_LDBL(asprintf); \
+      COMMON_INTERCEPT_FUNCTION_LDBL(vasprintf);
+#  else
+#    define INIT_PRINTF_EXTRA
+#  endif
+#  define INIT_PRINTF INIT_PRINTF_COMMON INIT_PRINTF_EXTRA
 #else
 #define INIT_PRINTF
 #endif
@@ -1855,6 +1872,22 @@ FORMAT_INTERCEPTOR_IMPL(__isoc99_snprintf, __isoc99_vsnprintf, str, size,
 #define INIT_ISOC99_PRINTF
 #endif
 
+#if SANITIZER_INTERCEPT_SETPROCTITLE
+INTERCEPTOR(void, setproctitle, const char *fmt, ...) {
+  void *ctx;
+  va_list ap;
+  va_start(ap, fmt);
+  COMMON_INTERCEPTOR_ENTER(ctx, setproctitle, fmt, ap);
+  if (common_flags()->check_printf)
+    printf_common(ctx, fmt, ap);
+  REAL(setproctitle)(fmt, ap);
+  va_end(ap);
+}
+#  define INIT_SETPROCTITLE COMMON_INTERCEPT_FUNCTION(setproctitle);
+#else
+#  define INIT_SETPROCTITLE
+#endif
+
 #if SANITIZER_INTERCEPT_IOCTL
 #include "sanitizer_common_interceptors_ioctl.inc"
 #include "sanitizer_interceptors_ioctl_netbsd.inc"
@@ -3901,7 +3934,7 @@ INTERCEPTOR(SIZE_T, wcrtomb, char *dest, wchar_t src, void *ps) {
   if (res != ((SIZE_T)-1)) {
     CHECK_LE(res, sizeof(local_dest));
     COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, res);
-    REAL(memcpy)(dest, local_dest, res);
+    internal_memcpy(dest, local_dest, res);
   }
   return res;
 }
@@ -3923,7 +3956,7 @@ INTERCEPTOR(int, wctomb, char *dest, wchar_t src) {
   if (res != -1) {
     CHECK_LE(res, sizeof(local_dest));
     COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, res);
-    REAL(memcpy)(dest, local_dest, res);
+    internal_memcpy(dest, local_dest, res);
   }
   return res;
 }
@@ -10263,6 +10296,71 @@ INTERCEPTOR(SSIZE_T, freadlink, int fd, char *buf, SIZE_T bufsiz) {
 #  define INIT_FREADLINK
 #endif
 
+#if SANITIZER_INTERCEPT_GETSERVENT_R || SANITIZER_INTERCEPT_GETSERVBYNAME_R || \
+    SANITIZER_INTERCEPT_GETSERVBYPORT_R
+
+UNUSED static void HandleGetServentReentrantResult(
+    void *ctx, int res, struct __sanitizer_servent *result_buf, char *buf,
+    SIZE_T buflen, struct __sanitizer_servent **result) {
+  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (char *)result, sizeof(void *));
+  if (res)
+    return;
+  if (*result) {
+    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (char *)*result,
+                                   sizeof(__sanitizer_servent));
+    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
+  }
+}
+
+#endif
+
+#if SANITIZER_INTERCEPT_GETSERVENT_R
+INTERCEPTOR(int, getservent_r, struct __sanitizer_servent *result_buf,
+            char *buf, SIZE_T buflen, struct __sanitizer_servent **result) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, getservent_r, result_buf, buf, buflen, result);
+  int res = REAL(getservent_r)(result_buf, buf, buflen, result);
+  HandleGetServentReentrantResult(ctx, res, result_buf, buf, buflen, result);
+  return res;
+}
+#  define INIT_GETSERVENT_R COMMON_INTERCEPT_FUNCTION(getservent_r)
+#else
+#  define INIT_GETSERVENT_R
+#endif
+
+#if SANITIZER_INTERCEPT_GETSERVBYNAME_R
+INTERCEPTOR(int, getservbyname_r, const char *name, const char *proto,
+            struct __sanitizer_servent *result_buf, char *buf, SIZE_T buflen,
+            struct __sanitizer_servent **result) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, getservbyname_r, name, proto, result_buf, buf,
+                           buflen, result);
+  COMMON_INTERCEPTOR_READ_STRING(ctx, name, internal_strlen(name));
+  int res = REAL(getservbyname_r)(name, proto, result_buf, buf, buflen, result);
+  HandleGetServentReentrantResult(ctx, res, result_buf, buf, buflen, result);
+  return res;
+}
+#  define INIT_GETSERVBYNAME_R COMMON_INTERCEPT_FUNCTION(getservbyname_r)
+#else
+#  define INIT_GETSERVBYNAME_R
+#endif
+
+#if SANITIZER_INTERCEPT_GETSERVBYPORT_R
+INTERCEPTOR(int, getservbyport_r, int port, const char *proto,
+            struct __sanitizer_servent *result_buf, char *buf, SIZE_T buflen,
+            struct __sanitizer_servent **result) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, getservbyport_r, port, proto, result_buf, buf,
+                           buflen, result);
+  int res = REAL(getservbyport_r)(port, proto, result_buf, buf, buflen, result);
+  HandleGetServentReentrantResult(ctx, res, result_buf, buf, buflen, result);
+  return res;
+}
+#  define INIT_GETSERVBYPORT_R COMMON_INTERCEPT_FUNCTION(getservbyport_r)
+#else
+#  define INIT_GETSERVBYPORT_R
+#endif
+
 #include "sanitizer_common_interceptors_netbsd_compat.inc"
 
 namespace __sanitizer {
@@ -10328,8 +10426,10 @@ static void InitializeCommonInterceptors() {
   INIT_PRINTF;
   INIT_PRINTF_L;
   INIT_ISOC99_PRINTF;
+  INIT_SETPROCTITLE;
   INIT_FREXP;
-  INIT_FREXPF_FREXPL;
+  INIT_FREXPF;
+  INIT_FREXPL;
   INIT_GETPWNAM_AND_FRIENDS;
   INIT_GETPWNAM_R_AND_FRIENDS;
   INIT_GETPWENT;
@@ -10587,4 +10687,7 @@ static void InitializeCommonInterceptors() {
   INIT_FREADLINK;
 
   INIT___PRINTF_CHK;
+  INIT_GETSERVENT_R;
+  INIT_GETSERVBYNAME_R;
+  INIT_GETSERVBYPORT_R;
 }
lib/libtsan/sanitizer_common/sanitizer_common_interceptors_format.inc
@@ -67,6 +67,10 @@ static const char *maybe_parse_length_modifier(const char *p, char ll[2]) {
 
 // Returns true if the character is an integer conversion specifier.
 static bool format_is_integer_conv(char c) {
+#if SANITIZER_GLIBC
+  if (char_is_one_of(c, "bB"))
+    return true;
+#endif
   return char_is_one_of(c, "diouxXn");
 }
 
lib/libtsan/sanitizer_common/sanitizer_common_interceptors_ioctl.inc
@@ -48,35 +48,41 @@ static void ioctl_table_fill() {
     ++ioctl_table_size;                                  \
   }
 
+  _(FIONBIO, READ, sizeof(int));
+#if !SANITIZER_HAIKU
   _(FIOASYNC, READ, sizeof(int));
   _(FIOCLEX, NONE, 0);
   _(FIOGETOWN, WRITE, sizeof(int));
-  _(FIONBIO, READ, sizeof(int));
   _(FIONCLEX, NONE, 0);
   _(FIOSETOWN, READ, sizeof(int));
+#endif
   _(SIOCATMARK, WRITE, sizeof(int));
   _(SIOCGIFCONF, CUSTOM, 0);
   _(SIOCGPGRP, WRITE, sizeof(int));
   _(SIOCSPGRP, READ, sizeof(int));
-#if !SANITIZER_SOLARIS
+#if !SANITIZER_SOLARIS && !SANITIZER_HAIKU
   _(TIOCCONS, NONE, 0);
 #endif
-  _(TIOCEXCL, NONE, 0);
+#if !SANITIZER_HAIKU
   _(TIOCGETD, WRITE, sizeof(int));
+  _(TIOCNOTTY, NONE, 0);
+  _(TIOCPKT, READ, sizeof(int));
+  _(TIOCSETD, READ, sizeof(int));
+  _(TIOCSTI, READ, sizeof(char));
+#endif
+  _(TIOCEXCL, NONE, 0);
   _(TIOCGPGRP, WRITE, pid_t_sz);
   _(TIOCGWINSZ, WRITE, struct_winsize_sz);
   _(TIOCMBIC, READ, sizeof(int));
   _(TIOCMBIS, READ, sizeof(int));
   _(TIOCMGET, WRITE, sizeof(int));
   _(TIOCMSET, READ, sizeof(int));
-  _(TIOCNOTTY, NONE, 0);
   _(TIOCNXCL, NONE, 0);
   _(TIOCOUTQ, WRITE, sizeof(int));
-  _(TIOCPKT, READ, sizeof(int));
+#  if !SANITIZER_AIX
   _(TIOCSCTTY, NONE, 0);
-  _(TIOCSETD, READ, sizeof(int));
+#  endif
   _(TIOCSPGRP, READ, pid_t_sz);
-  _(TIOCSTI, READ, sizeof(char));
   _(TIOCSWINSZ, READ, struct_winsize_sz);
 
 #if !SANITIZER_IOS
lib/libtsan/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc
@@ -33,11 +33,13 @@
 
 // Platform-specific options.
 #if SANITIZER_APPLE
-#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 0
+#  define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 0
 #elif SANITIZER_WINDOWS64
-#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 0
+#  define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 0
+#elif SANITIZER_AIX
+#  define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 0
 #else
-#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 1
+#  define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 1
 #endif  // SANITIZER_APPLE
 
 #ifndef COMMON_INTERCEPTOR_MEMSET_IMPL
lib/libtsan/sanitizer_common/sanitizer_common_syscalls.inc
@@ -3205,6 +3205,28 @@ POST_SYSCALL(futex)
   COMMON_SYSCALL_BLOCKING_END();
 }
 
+PRE_SYSCALL(copy_file_range)
+(int fdin, __sanitizer___kernel_off_t *offin, int fdout,
+ __sanitizer___kernel_off_t *offout, SIZE_T size, unsigned int flags) {
+  if (offin != nullptr) {
+    PRE_READ(offin, sizeof(*offin));
+  }
+  if (offout != nullptr) {
+    PRE_READ(offout, sizeof(*offout));
+  }
+}
+
+POST_SYSCALL(copy_file_range)
+(SSIZE_T, int fdin, __sanitizer___kernel_off_t *offin, int fdout,
+ __sanitizer___kernel_off_t *offout, SIZE_T size, unsigned int flags) {
+  if (offin != nullptr) {
+    POST_WRITE(offin, sizeof(*offin));
+  }
+  if (offout != nullptr) {
+    POST_WRITE(offout, sizeof(*offout));
+  }
+}
+
 }  // extern "C"
 
 #  undef PRE_SYSCALL
lib/libtsan/sanitizer_common/sanitizer_errno.h
@@ -29,6 +29,8 @@
 #  define __errno_location ___errno
 #elif SANITIZER_WINDOWS
 #  define __errno_location _errno
+#elif SANITIZER_HAIKU
+#  define __errno_location _errnop
 #endif
 
 extern "C" int *__errno_location();
lib/libtsan/sanitizer_common/sanitizer_errno_codes.h
@@ -21,12 +21,21 @@
 
 namespace __sanitizer {
 
-#define errno_ENOMEM 12
-#define errno_EBUSY 16
-#define errno_EINVAL 22
-#define errno_ERANGE 34
-#define errno_ENAMETOOLONG 36
-#define errno_ENOSYS 38
+#ifdef __HAIKU__
+#  define errno_ENOMEM (0x80000000)
+#  define errno_EBUSY (0x80000000 + 14)
+#  define errno_EINVAL (0x80000000 + 5)
+#  define errno_ERANGE (0x80007000 + 17)
+#  define errno_ENAMETOOLONG (0x80000000 + 0x6004)
+#  define errno_ENOSYS (0x80007009)
+#else
+#  define errno_ENOMEM 12
+#  define errno_EBUSY 16
+#  define errno_EINVAL 22
+#  define errno_ERANGE 34
+#  define errno_ENAMETOOLONG 36
+#  define errno_ENOSYS 38
+#endif
 
 // Those might not present or their value differ on different platforms.
 extern const int errno_EOWNERDEAD;
lib/libtsan/sanitizer_common/sanitizer_file.cpp
@@ -96,12 +96,76 @@ static void RecursiveCreateParentDirs(char *path) {
   }
 }
 
+/// Parse the report path \p pattern and copy the parsed path to \p dest.
+///
+/// * `%%` becomes `%`
+/// * `%H` expands to the environment variable `HOME`
+/// * `%t` expands to the environment variable `TMPDIR`
+/// * `%p` expands to the process ID (PID)
+static void ParseAndSetPath(const char *pattern, char *dest,
+                            const uptr dest_size) {
+  CHECK(pattern);
+  CHECK(dest);
+  CHECK_GE(dest_size, 1);
+  dest[0] = '\0';
+  uptr next_substr_start_idx = 0;
+  for (uptr i = 0; i < internal_strlen(pattern) - 1; i++) {
+    if (pattern[i] != '%')
+      continue;
+    int bytes_to_copy = i - next_substr_start_idx;
+    // Copy over previous substring.
+    CHECK_LT(internal_strlcat(dest, pattern + next_substr_start_idx,
+                              internal_strlen(dest) + bytes_to_copy + 1),
+             dest_size);
+    const char *str_to_concat;
+    switch (pattern[++i]) {
+      case '%':
+        str_to_concat = "%";
+        break;
+      case 'H':
+        str_to_concat = GetEnv("HOME");
+        break;
+      case 't':
+        str_to_concat = GetEnv("TMPDIR");
+        break;
+      case 'p': {
+        // Use printf directly to write the PID since it's not a static string.
+        int remaining_capacity = dest_size - internal_strlen(dest);
+        int bytes_copied =
+            internal_snprintf(dest + internal_strlen(dest), remaining_capacity,
+                              "%ld", internal_getpid());
+        CHECK_GT(bytes_copied, 0);
+        CHECK_LT(bytes_copied, remaining_capacity);
+        str_to_concat = "";
+        break;
+      }
+      default: {
+        // Invalid pattern: fallback to original pattern.
+        const char *message = "ERROR: Unexpected pattern: ";
+        WriteToFile(kStderrFd, message, internal_strlen(message));
+        WriteToFile(kStderrFd, pattern, internal_strlen(pattern));
+        WriteToFile(kStderrFd, "\n", internal_strlen("\n"));
+        CHECK_LT(internal_strlcpy(dest, pattern, dest_size), dest_size);
+        return;
+      }
+    }
+    CHECK(str_to_concat);
+    CHECK_LT(internal_strlcat(dest, str_to_concat, dest_size), dest_size);
+    next_substr_start_idx = i + 1;
+  }
+  CHECK_LT(internal_strlcat(dest, pattern + next_substr_start_idx, dest_size),
+           dest_size);
+}
+
 void ReportFile::SetReportPath(const char *path) {
   if (path) {
     uptr len = internal_strlen(path);
     if (len > sizeof(path_prefix) - 100) {
-      Report("ERROR: Path is too long: %c%c%c%c%c%c%c%c...\n", path[0], path[1],
-             path[2], path[3], path[4], path[5], path[6], path[7]);
+      const char *message = "ERROR: Path is too long: ";
+      WriteToFile(kStderrFd, message, internal_strlen(message));
+      WriteToFile(kStderrFd, path, 8);
+      message = "...\n";
+      WriteToFile(kStderrFd, message, internal_strlen(message));
       Die();
     }
   }
@@ -115,7 +179,7 @@ void ReportFile::SetReportPath(const char *path) {
   } else if (internal_strcmp(path, "stdout") == 0) {
     fd = kStdoutFd;
   } else {
-    internal_snprintf(path_prefix, kMaxPathLength, "%s", path);
+    ParseAndSetPath(path, path_prefix, kMaxPathLength);
     RecursiveCreateParentDirs(path_prefix);
   }
 }
lib/libtsan/sanitizer_common/sanitizer_fuchsia.cpp
@@ -547,6 +547,8 @@ void __sanitizer_startup_hook(int argc, char **argv, char **envp,
   __sanitizer::StoredEnviron = envp;
   __sanitizer::MainThreadStackBase = reinterpret_cast<uintptr_t>(stack_base);
   __sanitizer::MainThreadStackSize = stack_size;
+
+  EarlySanitizerInit();
 }
 
 void __sanitizer_set_report_path(const char *path) {
lib/libtsan/sanitizer_common/sanitizer_fuchsia.h
@@ -32,6 +32,13 @@ struct MemoryMappingLayoutData {
 
 void InitShadowBounds();
 
+// Individual sanitizers can define this to explicitly run something at the end
+// of `__sanitizer_startup_hook`. This can be useful if a sanitizer needs to do
+// extra work after the common startup hook code is called and before module
+// ctors are invoked. For example, hwasan can explicitly call its initializing
+// function here so it can be set up before libc extensions are initialized.
+void EarlySanitizerInit();
+
 }  // namespace __sanitizer
 
 #endif  // SANITIZER_FUCHSIA
lib/libtsan/sanitizer_common/sanitizer_haiku.cpp
@@ -0,0 +1,361 @@
+//===-- sanitizer_haiku.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 shared between Sanitizer run-time libraries and implements
+// Haiku-specific functions from sanitizer_libc.h.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+
+#if SANITIZER_HAIKU
+
+#  include "sanitizer_common.h"
+#  include "sanitizer_flags.h"
+#  include "sanitizer_getauxval.h"
+#  include "sanitizer_internal_defs.h"
+#  include "sanitizer_libc.h"
+#  include "sanitizer_linux.h"
+#  include "sanitizer_mutex.h"
+#  include "sanitizer_placement_new.h"
+#  include "sanitizer_procmaps.h"
+
+#  include <sys/param.h>
+#  include <sys/types.h>
+
+#  include <sys/mman.h>
+#  include <sys/resource.h>
+#  include <sys/stat.h>
+#  include <sys/time.h>
+
+#  include <dlfcn.h>
+#  include <errno.h>
+#  include <fcntl.h>
+#  include <limits.h>
+#  include <link.h>
+#  include <pthread.h>
+#  include <sched.h>
+#  include <signal.h>
+#  include <unistd.h>
+
+#  include "system/vm_defs.h"
+#  include "system/syscalls.h"
+#  include "shared/syscall_utils.h"
+
+namespace __sanitizer {
+
+static void *GetRealLibcAddress(const char *symbol) {
+  void *real = dlsym(RTLD_NEXT, symbol);
+  if (!real)
+    real = dlsym(RTLD_DEFAULT, symbol);
+  if (!real) {
+    Printf("GetRealLibcAddress failed for symbol=%s", symbol);
+    Die();
+  }
+  return real;
+}
+
+#  define _REAL(func, ...) real##_##func(__VA_ARGS__)
+#  define DEFINE__REAL(ret_type, func, ...)                              \
+    static ret_type (*real_##func)(__VA_ARGS__) = NULL;                  \
+    if (!real_##func) {                                                  \
+      real_##func = (ret_type(*)(__VA_ARGS__))GetRealLibcAddress(#func); \
+    }                                                                    \
+    CHECK(real_##func);
+
+// --------------- sanitizer_libc.h
+uptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd,
+                   u64 offset) {
+  if ((flags & MAP_ANONYMOUS) != 0)
+    fd = -1;
+
+  int mapping =
+      (flags & MAP_SHARED) != 0 ? REGION_NO_PRIVATE_MAP : REGION_PRIVATE_MAP;
+
+  uint32 addressSpec;
+  if ((flags & MAP_FIXED) != 0)
+    addressSpec = B_EXACT_ADDRESS;
+  else if (addr != NULL)
+    addressSpec = B_BASE_ADDRESS;
+  else
+    addressSpec = B_RANDOMIZED_ANY_ADDRESS;
+
+  uint32 areaProtection = 0;
+  if ((prot & PROT_READ) != 0)
+    areaProtection |= B_READ_AREA;
+  if ((prot & PROT_WRITE) != 0)
+    areaProtection |= B_WRITE_AREA;
+  if ((prot & PROT_EXEC) != 0)
+    areaProtection |= B_EXECUTE_AREA;
+
+  if ((flags & MAP_NORESERVE) != 0)
+    areaProtection |= B_OVERCOMMITTING_AREA;
+
+  area_id area = _kern_map_file("sanitizer mmap", &addr, addressSpec, length,
+                                areaProtection, mapping, true, fd, offset);
+  if (area < 0)
+    RETURN_AND_SET_ERRNO(area);
+  return (uptr)addr;
+}
+
+uptr internal_munmap(void *addr, uptr length) {
+  DEFINE__REAL(int, munmap, void *a, uptr b);
+  return _REAL(munmap, addr, length);
+}
+
+uptr internal_mremap(void *old_address, uptr old_size, uptr new_size, int flags,
+                     void *new_address) {
+  CHECK(false && "internal_mremap is unimplemented on Haiku");
+  return 0;
+}
+
+int internal_mprotect(void *addr, uptr length, int prot) {
+  DEFINE__REAL(int, mprotect, void *a, uptr b, int c);
+  return _REAL(mprotect, addr, length, prot);
+}
+
+int internal_madvise(uptr addr, uptr length, int advice) {
+  DEFINE__REAL(int, madvise, void *a, uptr b, int c);
+  return _REAL(madvise, (void *)addr, length, advice);
+}
+
+uptr internal_close(fd_t fd) {
+  CHECK(&_kern_close);
+  RETURN_AND_SET_ERRNO(_kern_close(fd));
+}
+
+uptr internal_open(const char *filename, int flags) {
+  CHECK(&_kern_open);
+  RETURN_AND_SET_ERRNO(_kern_open(-1, filename, flags, 0));
+}
+
+uptr internal_open(const char *filename, int flags, u32 mode) {
+  CHECK(&_kern_open);
+  RETURN_AND_SET_ERRNO(_kern_open(-1, filename, flags, mode));
+}
+
+uptr internal_read(fd_t fd, void *buf, uptr count) {
+  sptr res;
+  CHECK(&_kern_read);
+  HANDLE_EINTR(res, (sptr)_kern_read(fd, -1, buf, (size_t)count));
+  RETURN_AND_SET_ERRNO(res);
+  return res;
+}
+
+uptr internal_write(fd_t fd, const void *buf, uptr count) {
+  sptr res;
+  CHECK(&_kern_write);
+  HANDLE_EINTR(res, (sptr)_kern_write(fd, -1, buf, count));
+  RETURN_AND_SET_ERRNO(res);
+  return res;
+}
+
+uptr internal_ftruncate(fd_t fd, uptr size) {
+  sptr res;
+  DEFINE__REAL(int, ftruncate, int, off_t);
+  return _REAL(ftruncate, fd, size);
+  return res;
+}
+
+uptr internal_stat(const char *path, void *buf) {
+  DEFINE__REAL(int, _stat_current, const char *a, void *b);
+  return _REAL(_stat_current, path, buf);
+}
+
+uptr internal_lstat(const char *path, void *buf) {
+  DEFINE__REAL(int, _lstat_current, const char *a, void *b);
+  return _REAL(_lstat_current, path, buf);
+}
+
+uptr internal_fstat(fd_t fd, void *buf) {
+  DEFINE__REAL(int, _fstat_current, int a, void *b);
+  return _REAL(_fstat_current, fd, buf);
+}
+
+uptr internal_filesize(fd_t fd) {
+  struct stat st;
+  if (internal_fstat(fd, &st))
+    return -1;
+  return (uptr)st.st_size;
+}
+
+uptr internal_dup(int oldfd) {
+  DEFINE__REAL(int, dup, int a);
+  return _REAL(dup, oldfd);
+}
+
+uptr internal_dup2(int oldfd, int newfd) {
+  DEFINE__REAL(int, dup2, int a, int b);
+  return _REAL(dup2, oldfd, newfd);
+}
+
+uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
+  CHECK(&_kern_read_link);
+  RETURN_AND_SET_ERRNO(_kern_read_link(-1, path, buf, &bufsize));
+}
+
+uptr internal_unlink(const char *path) {
+  DEFINE__REAL(int, unlink, const char *a);
+  return _REAL(unlink, path);
+}
+
+uptr internal_rename(const char *oldpath, const char *newpath) {
+  DEFINE__REAL(int, rename, const char *a, const char *b);
+  return _REAL(rename, oldpath, newpath);
+}
+
+uptr internal_sched_yield() {
+  CHECK(&_kern_thread_yield);
+  _kern_thread_yield();
+  return 0;
+}
+
+void internal__exit(int exitcode) {
+  DEFINE__REAL(void, _exit, int a);
+  _REAL(_exit, exitcode);
+  Die();  // Unreachable.
+}
+
+void internal_usleep(u64 useconds) {
+  _kern_snooze_etc(useconds, B_SYSTEM_TIMEBASE, B_RELATIVE_TIMEOUT, NULL);
+}
+
+uptr internal_execve(const char *filename, char *const argv[],
+                     char *const envp[]) {
+  DEFINE__REAL(int, execve, const char *, char *const[], char *const[]);
+  return _REAL(execve, filename, argv, envp);
+}
+
+#  if 0
+tid_t GetTid() {
+  DEFINE__REAL(int, _lwp_self);
+  return _REAL(_lwp_self);
+}
+
+int TgKill(pid_t pid, tid_t tid, int sig) {
+  DEFINE__REAL(int, _lwp_kill, int a, int b);
+  (void)pid;
+  return _REAL(_lwp_kill, tid, sig);
+}
+
+u64 NanoTime() {
+  timeval tv;
+  DEFINE__REAL(int, __gettimeofday50, void *a, void *b);
+  internal_memset(&tv, 0, sizeof(tv));
+  _REAL(__gettimeofday50, &tv, 0);
+  return (u64)tv.tv_sec * 1000 * 1000 * 1000 + tv.tv_usec * 1000;
+}
+#  endif
+
+uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp) {
+  DEFINE__REAL(int, __clock_gettime50, __sanitizer_clockid_t a, void *b);
+  return _REAL(__clock_gettime50, clk_id, tp);
+}
+
+uptr internal_ptrace(int request, int pid, void *addr, int data) {
+  DEFINE__REAL(int, ptrace, int a, int b, void *c, int d);
+  return _REAL(ptrace, request, pid, addr, data);
+}
+
+uptr internal_waitpid(int pid, int *status, int options) {
+  DEFINE__REAL(int, waitpid, pid_t, int *, int);
+  return _REAL(waitpid, pid, status, options);
+}
+
+uptr internal_getpid() {
+  DEFINE__REAL(int, getpid);
+  return _REAL(getpid);
+}
+
+uptr internal_getppid() {
+  DEFINE__REAL(int, getppid);
+  return _REAL(getppid);
+}
+
+int internal_dlinfo(void *handle, int request, void *p) {
+  DEFINE__REAL(int, dlinfo, void *a, int b, void *c);
+  return _REAL(dlinfo, handle, request, p);
+}
+
+uptr internal_getdents(fd_t fd, void *dirp, unsigned int count) {
+  DEFINE__REAL(int, __getdents30, int a, void *b, size_t c);
+  return _REAL(__getdents30, fd, dirp, count);
+}
+
+uptr internal_lseek(fd_t fd, OFF_T offset, int whence) {
+  CHECK(&_kern_seek);
+  off_t result = _kern_seek(fd, offset, whence);
+  if (result < 0) {
+    errno = result;
+    return -1;
+  }
+  return result;
+}
+
+uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) {
+  Printf("internal_prctl not implemented for Haiku");
+  Die();
+  return 0;
+}
+
+uptr internal_sigaltstack(const void *ss, void *oss) {
+  DEFINE__REAL(int, __sigaltstack14, const void *a, void *b);
+  return _REAL(__sigaltstack14, ss, oss);
+}
+
+int internal_fork() {
+  DEFINE__REAL(int, fork);
+  return _REAL(fork);
+}
+
+#  if 0
+int internal_sysctl(const int *name, unsigned int namelen, void *oldp,
+                    uptr *oldlenp, const void *newp, uptr newlen) {
+  CHECK(&__sysctl);
+  return __sysctl(name, namelen, oldp, (size_t *)oldlenp, newp, (size_t)newlen);
+}
+#  endif
+
+int internal_sysctlbyname(const char *sname, void *oldp, uptr *oldlenp,
+                          const void *newp, uptr newlen) {
+  DEFINE__REAL(int, sysctlbyname, const char *a, void *b, size_t *c,
+               const void *d, size_t e);
+  return _REAL(sysctlbyname, sname, oldp, (size_t *)oldlenp, newp,
+               (size_t)newlen);
+}
+
+uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set,
+                          __sanitizer_sigset_t *oldset) {
+  CHECK(&_kern_set_signal_mask);
+  return _kern_set_signal_mask(how, set, oldset);
+}
+
+void internal_sigfillset(__sanitizer_sigset_t *set) {
+  DEFINE__REAL(int, __sigfillset14, const void *a);
+  (void)_REAL(__sigfillset14, set);
+}
+
+void internal_sigemptyset(__sanitizer_sigset_t *set) {
+  DEFINE__REAL(int, __sigemptyset14, const void *a);
+  (void)_REAL(__sigemptyset14, set);
+}
+
+void internal_sigdelset(__sanitizer_sigset_t *set, int signo) {
+  DEFINE__REAL(int, __sigdelset14, const void *a, int b);
+  (void)_REAL(__sigdelset14, set, signo);
+}
+
+uptr internal_clone(int (*fn)(void *), void *child_stack, int flags,
+                    void *arg) {
+  DEFINE__REAL(int, clone, int (*a)(void *b), void *c, int d, void *e);
+
+  return _REAL(clone, fn, child_stack, flags, arg);
+}
+
+}  // namespace __sanitizer
+
+#endif
lib/libtsan/sanitizer_common/sanitizer_linux.cpp
@@ -14,7 +14,7 @@
 #include "sanitizer_platform.h"
 
 #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
-    SANITIZER_SOLARIS
+    SANITIZER_SOLARIS || SANITIZER_HAIKU
 
 #  include "sanitizer_common.h"
 #  include "sanitizer_flags.h"
@@ -63,15 +63,17 @@
 #  include <sched.h>
 #  include <signal.h>
 #  include <sys/mman.h>
-#  if !SANITIZER_SOLARIS
+#  if !SANITIZER_SOLARIS && !SANITIZER_HAIKU
 #    include <sys/ptrace.h>
 #  endif
 #  include <sys/resource.h>
 #  include <sys/stat.h>
-#  include <sys/syscall.h>
+#  if !SANITIZER_HAIKU
+#    include <sys/syscall.h>
+#    include <ucontext.h>
+#  endif
 #  include <sys/time.h>
 #  include <sys/types.h>
-#  include <ucontext.h>
 #  include <unistd.h>
 
 #  if SANITIZER_LINUX
@@ -82,6 +84,12 @@
 #    include <sys/personality.h>
 #  endif
 
+#  if SANITIZER_ANDROID && __ANDROID_API__ < 35
+// The weak `strerrorname_np` (introduced in API level 35) definition,
+// allows for checking the API level at runtime.
+extern "C" SANITIZER_WEAK_ATTRIBUTE const char *strerrorname_np(int);
+#  endif
+
 #  if SANITIZER_LINUX && defined(__loongarch__)
 #    include <sys/sysmacros.h>
 #  endif
@@ -118,6 +126,13 @@ extern struct ps_strings *__ps_strings;
 #    define environ _environ
 #  endif
 
+#  if SANITIZER_HAIKU
+#    include <OS.h>
+#    include <elf.h>
+#    include <image.h>
+extern "C" char **__libc_argv;
+#  endif
+
 extern char **environ;
 
 #  if SANITIZER_LINUX
@@ -246,7 +261,7 @@ ScopedBlockSignals::~ScopedBlockSignals() { SetSigProcMask(&saved_, nullptr); }
 #  endif
 
 // --------------- sanitizer_libc.h
-#  if !SANITIZER_SOLARIS && !SANITIZER_NETBSD
+#  if !SANITIZER_SOLARIS && !SANITIZER_NETBSD && !SANITIZER_HAIKU
 #    if !SANITIZER_S390
 uptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd,
                    u64 offset) {
@@ -591,9 +606,9 @@ uptr internal_execve(const char *filename, char *const argv[],
   return internal_syscall(SYSCALL(execve), (uptr)filename, (uptr)argv,
                           (uptr)envp);
 }
-#  endif  // !SANITIZER_SOLARIS && !SANITIZER_NETBSD
+#  endif  // !SANITIZER_SOLARIS && !SANITIZER_NETBSD && !SANITIZER_HAIKU
 
-#  if !SANITIZER_NETBSD
+#  if !SANITIZER_NETBSD && !SANITIZER_HAIKU
 void internal__exit(int exitcode) {
 #    if SANITIZER_FREEBSD || SANITIZER_SOLARIS
   internal_syscall(SYSCALL(exit), exitcode);
@@ -602,7 +617,7 @@ void internal__exit(int exitcode) {
 #    endif
   Die();  // Unreachable.
 }
-#  endif  // !SANITIZER_NETBSD
+#  endif  // !SANITIZER_NETBSD && !SANITIZER_HAIKU
 
 // ----------------- sanitizer_common.h
 bool FileExists(const char *filename) {
@@ -630,6 +645,8 @@ tid_t GetTid() {
   return Tid;
 #    elif SANITIZER_SOLARIS
   return thr_self();
+#    elif SANITIZER_HAIKU
+  return find_thread(NULL);
 #    else
   return internal_syscall(SYSCALL(gettid));
 #    endif
@@ -645,6 +662,8 @@ int TgKill(pid_t pid, tid_t tid, int sig) {
   errno = thr_kill(tid, sig);
   // TgKill is expected to return -1 on error, not an errno.
   return errno != 0 ? -1 : 0;
+#    elif SANITIZER_HAIKU
+  return kill_thread(tid);
 #    endif
 }
 #  endif
@@ -672,7 +691,8 @@ u64 NanoTime() {
 // 'environ' array (on some others) and does not use libc. This function
 // should be called first inside __asan_init.
 const char *GetEnv(const char *name) {
-#  if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_SOLARIS
+#  if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_SOLARIS || \
+      SANITIZER_HAIKU
   if (::environ != 0) {
     uptr NameLen = internal_strlen(name);
     for (char **Env = ::environ; *Env != 0; Env++) {
@@ -710,13 +730,14 @@ const char *GetEnv(const char *name) {
 #  endif
 }
 
-#  if !SANITIZER_FREEBSD && !SANITIZER_NETBSD && !SANITIZER_GO
+#  if !SANITIZER_HAIKU && !SANITIZER_FREEBSD && !SANITIZER_NETBSD && \
+      !SANITIZER_GO
 extern "C" {
 SANITIZER_WEAK_ATTRIBUTE extern void *__libc_stack_end;
 }
 #  endif
 
-#  if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
+#  if !SANITIZER_HAIKU && !SANITIZER_FREEBSD && !SANITIZER_NETBSD
 static void ReadNullSepFileToArray(const char *path, char ***arr,
                                    int arr_size) {
   char *buff;
@@ -743,7 +764,10 @@ static void ReadNullSepFileToArray(const char *path, char ***arr,
 #  endif
 
 static void GetArgsAndEnv(char ***argv, char ***envp) {
-#  if SANITIZER_FREEBSD
+#  if SANITIZER_HAIKU
+  *argv = __libc_argv;
+  *envp = environ;
+#  elif SANITIZER_FREEBSD
   // On FreeBSD, retrieving the argument and environment arrays is done via the
   // kern.ps_strings sysctl, which returns a pointer to a structure containing
   // this information. See also <sys/exec.h>.
@@ -783,7 +807,7 @@ static void GetArgsAndEnv(char ***argv, char ***envp) {
 #    if !SANITIZER_GO
   }
 #    endif  // !SANITIZER_GO
-#  endif    // SANITIZER_FREEBSD
+#  endif    // SANITIZER_HAIKU
 }
 
 char **GetArgv() {
@@ -802,7 +826,7 @@ char **GetEnviron() {
 void FutexWait(atomic_uint32_t *p, u32 cmp) {
 #    if SANITIZER_FREEBSD
   _umtx_op(p, UMTX_OP_WAIT_UINT, cmp, 0, 0);
-#    elif SANITIZER_NETBSD
+#    elif SANITIZER_NETBSD || SANITIZER_HAIKU
   sched_yield(); /* No userspace futex-like synchronization */
 #    else
   internal_syscall(SYSCALL(futex), (uptr)p, FUTEX_WAIT_PRIVATE, cmp, 0, 0, 0);
@@ -812,7 +836,7 @@ void FutexWait(atomic_uint32_t *p, u32 cmp) {
 void FutexWake(atomic_uint32_t *p, u32 count) {
 #    if SANITIZER_FREEBSD
   _umtx_op(p, UMTX_OP_WAKE, count, 0, 0);
-#    elif SANITIZER_NETBSD
+#    elif SANITIZER_NETBSD || SANITIZER_HAIKU
   /* No userspace futex-like synchronization */
 #    else
   internal_syscall(SYSCALL(futex), (uptr)p, FUTEX_WAKE_PRIVATE, count, 0, 0, 0);
@@ -844,7 +868,7 @@ struct linux_dirent {
 };
 #  endif
 
-#  if !SANITIZER_SOLARIS && !SANITIZER_NETBSD
+#  if !SANITIZER_SOLARIS && !SANITIZER_NETBSD && !SANITIZER_HAIKU
 // Syscall wrappers.
 uptr internal_ptrace(int request, int pid, void *addr, void *data) {
   return internal_syscall(SYSCALL(ptrace), request, pid, (uptr)addr,
@@ -1058,7 +1082,7 @@ bool internal_sigismember(__sanitizer_sigset_t *set, int signum) {
 #    endif
 #  endif  // !SANITIZER_SOLARIS
 
-#  if !SANITIZER_NETBSD
+#  if !SANITIZER_NETBSD && !SANITIZER_HAIKU
 // ThreadLister implementation.
 ThreadLister::ThreadLister(pid_t pid) : buffer_(4096) {
   task_path_.AppendF("/proc/%d/task", pid);
@@ -1244,6 +1268,16 @@ uptr GetPageSize() {
   CHECK_EQ(rv, 0);
   return (uptr)pz;
 #    elif SANITIZER_USE_GETAUXVAL
+#      if SANITIZER_ANDROID && __ANDROID_API__ < 35
+  // The 16 KB page size was introduced in Android 15 (API level 35), while
+  // earlier versions of Android always used a 4 KB page size.
+  // We are checking the weak definition of `strerrorname_np` (introduced in API
+  // level 35) because some earlier API levels crashed when
+  // `getauxval(AT_PAGESZ)` was called from the `.preinit_array`.
+  if (!strerrorname_np)
+    return 4096;
+#      endif
+
   return getauxval(AT_PAGESZ);
 #    else
   return sysconf(_SC_PAGESIZE);  // EXEC_PAGESIZE may not be trustworthy.
@@ -1252,7 +1286,19 @@ uptr GetPageSize() {
 #  endif
 
 uptr ReadBinaryName(/*out*/ char *buf, uptr buf_len) {
-#  if SANITIZER_SOLARIS
+#  if SANITIZER_HAIKU
+  int cookie = 0;
+  image_info info;
+  const char *argv0 = "<UNKNOWN>";
+  while (get_next_image_info(B_CURRENT_TEAM, &cookie, &info) == B_OK) {
+    if (info.type != B_APP_IMAGE)
+      continue;
+    argv0 = info.name;
+    break;
+  }
+  internal_strncpy(buf, argv0, buf_len);
+  return internal_strlen(buf);
+#  elif SANITIZER_SOLARIS
   const char *default_module_name = getexecname();
   CHECK_NE(default_module_name, NULL);
   return internal_snprintf(buf, buf_len, "%s", default_module_name);
@@ -1318,11 +1364,11 @@ bool LibraryNameIs(const char *full_name, const char *base_name) {
   return (name[base_name_length] == '-' || name[base_name_length] == '.');
 }
 
-#  if !SANITIZER_ANDROID
+#  if !SANITIZER_ANDROID && !SANITIZER_HAIKU
 // Call cb for each region mapped by map.
 void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)) {
   CHECK_NE(map, nullptr);
-#    if !SANITIZER_FREEBSD
+#    if !SANITIZER_FREEBSD && !SANITIZER_HAIKU
   typedef ElfW(Phdr) Elf_Phdr;
   typedef ElfW(Ehdr) Elf_Ehdr;
 #    endif  // !SANITIZER_FREEBSD
@@ -1855,54 +1901,6 @@ int internal_uname(struct utsname *buf) {
 }
 #  endif
 
-#  if SANITIZER_ANDROID
-static int dl_iterate_phdr_test_cb(struct dl_phdr_info *info, size_t size,
-                                   void *data) {
-  // Any name starting with "lib" indicates a bug in L where library base names
-  // are returned instead of paths.
-  if (info->dlpi_name && info->dlpi_name[0] == 'l' &&
-      info->dlpi_name[1] == 'i' && info->dlpi_name[2] == 'b') {
-    *(bool *)data = true;
-    return 1;
-  }
-  return 0;
-}
-
-static atomic_uint32_t android_api_level;
-
-static AndroidApiLevel AndroidDetectApiLevelStatic() {
-#    if __ANDROID_API__ <= 22
-  return ANDROID_LOLLIPOP_MR1;
-#    else
-  return ANDROID_POST_LOLLIPOP;
-#    endif
-}
-
-static AndroidApiLevel AndroidDetectApiLevel() {
-  bool base_name_seen = false;
-  dl_iterate_phdr(dl_iterate_phdr_test_cb, &base_name_seen);
-  if (base_name_seen)
-    return ANDROID_LOLLIPOP_MR1;  // L MR1
-  return ANDROID_POST_LOLLIPOP;   // post-L
-  // Plain L (API level 21) is completely broken wrt ASan and not very
-  // interesting to detect.
-}
-
-extern "C" __attribute__((weak)) void *_DYNAMIC;
-
-AndroidApiLevel AndroidGetApiLevel() {
-  AndroidApiLevel level =
-      (AndroidApiLevel)atomic_load(&android_api_level, memory_order_relaxed);
-  if (level)
-    return level;
-  level = &_DYNAMIC == nullptr ? AndroidDetectApiLevelStatic()
-                               : AndroidDetectApiLevel();
-  atomic_store(&android_api_level, level, memory_order_relaxed);
-  return level;
-}
-
-#  endif
-
 static HandleSignalMode GetHandleSignalModeImpl(int signum) {
   switch (signum) {
     case SIGABRT:
@@ -1981,11 +1979,15 @@ using Context = ucontext_t;
 SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
   Context *ucontext = (Context *)context;
 #  if defined(__x86_64__) || defined(__i386__)
+#    if !SANITIZER_HAIKU
   static const uptr PF_WRITE = 1U << 1;
+#    endif
 #    if SANITIZER_FREEBSD
   uptr err = ucontext->uc_mcontext.mc_err;
 #    elif SANITIZER_NETBSD
   uptr err = ucontext->uc_mcontext.__gregs[_REG_ERR];
+#    elif SANITIZER_HAIKU
+  uptr err = ucontext->uc_mcontext.r13;
 #    elif SANITIZER_SOLARIS && defined(__i386__)
   const int Err = 13;
   uptr err = ucontext->uc_mcontext.gregs[Err];
@@ -2598,6 +2600,11 @@ static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
   *pc = ucontext->uc_mcontext.mc_rip;
   *bp = ucontext->uc_mcontext.mc_rbp;
   *sp = ucontext->uc_mcontext.mc_rsp;
+#    elif SANITIZER_HAIKU
+  ucontext_t *ucontext = (ucontext_t *)context;
+  *pc = ucontext->uc_mcontext.rip;
+  *bp = ucontext->uc_mcontext.rbp;
+  *sp = ucontext->uc_mcontext.rsp;
 #    else
   ucontext_t *ucontext = (ucontext_t *)context;
   *pc = ucontext->uc_mcontext.gregs[REG_RIP];
lib/libtsan/sanitizer_common/sanitizer_linux.h
@@ -14,7 +14,7 @@
 
 #include "sanitizer_platform.h"
 #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
-    SANITIZER_SOLARIS
+    SANITIZER_SOLARIS || SANITIZER_HAIKU
 #  include "sanitizer_common.h"
 #  include "sanitizer_internal_defs.h"
 #  include "sanitizer_platform_limits_freebsd.h"
@@ -31,6 +31,11 @@ namespace __sanitizer {
 // the one in <dirent.h>, which is used by readdir().
 struct linux_dirent;
 
+#  if SANITIZER_HAIKU
+struct MemoryMappingLayoutData {
+  long signed int cookie;
+};
+#  else
 struct ProcSelfMapsBuff {
   char *data;
   uptr mmaped_size;
@@ -43,6 +48,7 @@ struct MemoryMappingLayoutData {
 };
 
 void ReadProcMaps(ProcSelfMapsBuff *proc_maps);
+#  endif  // SANITIZER_HAIKU
 
 // Syscall wrappers.
 uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count);
@@ -124,7 +130,7 @@ bool LibraryNameIs(const char *full_name, const char *base_name);
 // Call cb for each region mapped by map.
 void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr));
 
-// Releases memory pages entirely within the [beg, end] address range.
+// Releases memory pages entirely within the [beg, end) address range.
 // The pages no longer count toward RSS; reads are guaranteed to return 0.
 // Requires (but does not verify!) that pages are MAP_PRIVATE.
 inline void ReleaseMemoryPagesToOSAndZeroFill(uptr beg, uptr end) {
lib/libtsan/sanitizer_common/sanitizer_linux_libcdep.cpp
@@ -14,7 +14,7 @@
 #include "sanitizer_platform.h"
 
 #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
-    SANITIZER_SOLARIS
+    SANITIZER_SOLARIS || SANITIZER_HAIKU
 
 #  include "sanitizer_allocator_internal.h"
 #  include "sanitizer_atomic.h"
@@ -28,8 +28,19 @@
 #  include "sanitizer_procmaps.h"
 #  include "sanitizer_solaris.h"
 
+#  if SANITIZER_HAIKU
+#    define _DEFAULT_SOURCE
+#  endif
+
 #  if SANITIZER_NETBSD
-#    define _RTLD_SOURCE  // for __lwp_gettcb_fast() / __lwp_getprivate_fast()
+#    // for __lwp_gettcb_fast() / __lwp_getprivate_fast()
+#    define _RTLD_SOURCE
+#    include <machine/mcontext.h>
+#    undef _RTLD_SOURCE
+#    include <sys/param.h>
+#    if __NetBSD_Version__ >= 1099001200
+#      include <machine/lwp_private.h>
+#    endif
 #  endif
 
 #  include <dlfcn.h>  // for dlsym()
@@ -74,18 +85,9 @@ extern "C" int __sys_sigaction(int signum, const struct sigaction *act,
 #    include <thread.h>
 #  endif
 
-#  if SANITIZER_ANDROID
-#    include <android/api-level.h>
-#    if !defined(CPU_COUNT) && !defined(__aarch64__)
-#      include <dirent.h>
-#      include <fcntl.h>
-struct __sanitizer::linux_dirent {
-  long d_ino;
-  off_t d_off;
-  unsigned short d_reclen;
-  char d_name[];
-};
-#    endif
+#  if SANITIZER_HAIKU
+#    include <kernel/OS.h>
+#    include <sys/link_elf.h>
 #  endif
 
 #  if !SANITIZER_ANDROID
@@ -651,6 +653,7 @@ static void GetTls(uptr *addr, uptr *size) {
       *addr = (uptr)tcb->tcb_dtv[1];
     }
   }
+#    elif SANITIZER_HAIKU
 #    else
 #      error "Unknown OS"
 #    endif
@@ -721,8 +724,13 @@ static int AddModuleSegments(const char *module_name, dl_phdr_info *info,
     if (phdr->p_type == PT_LOAD) {
       uptr cur_beg = info->dlpi_addr + phdr->p_vaddr;
       uptr cur_end = cur_beg + phdr->p_memsz;
+#  if SANITIZER_HAIKU
+      bool executable = phdr->p_flags & PF_EXECUTE;
+      bool writable = phdr->p_flags & PF_WRITE;
+#  else
       bool executable = phdr->p_flags & PF_X;
       bool writable = phdr->p_flags & PF_W;
+#  endif
       cur_module.addAddressRange(cur_beg, cur_end, executable, writable);
     } else if (phdr->p_type == PT_NOTE) {
 #  ifdef NT_GNU_BUILD_ID
@@ -774,42 +782,13 @@ static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) {
   return 0;
 }
 
-static bool requiresProcmaps() {
-#  if SANITIZER_ANDROID && __ANDROID_API__ <= 22
-  // Fall back to /proc/maps if dl_iterate_phdr is unavailable or broken.
-  // The runtime check allows the same library to work with
-  // both K and L (and future) Android releases.
-  return AndroidGetApiLevel() <= ANDROID_LOLLIPOP_MR1;
-#  else
-  return false;
-#  endif
-}
-
-static void procmapsInit(InternalMmapVectorNoCtor<LoadedModule> *modules) {
-  MemoryMappingLayout memory_mapping(/*cache_enabled*/ true);
-  memory_mapping.DumpListOfModules(modules);
-}
-
 void ListOfModules::init() {
   clearOrInit();
-  if (requiresProcmaps()) {
-    procmapsInit(&modules_);
-  } else {
-    DlIteratePhdrData data = {&modules_, true};
-    dl_iterate_phdr(dl_iterate_phdr_cb, &data);
-  }
+  DlIteratePhdrData data = {&modules_, true};
+  dl_iterate_phdr(dl_iterate_phdr_cb, &data);
 }
 
-// When a custom loader is used, dl_iterate_phdr may not contain the full
-// list of modules. Allow callers to fall back to using procmaps.
-void ListOfModules::fallbackInit() {
-  if (!requiresProcmaps()) {
-    clearOrInit();
-    procmapsInit(&modules_);
-  } else {
-    clear();
-  }
-}
+void ListOfModules::fallbackInit() { clear(); }
 
 // getrusage does not give us the current RSS, only the max RSS.
 // Still, this is better than nothing if /proc/self/statm is not available
@@ -855,45 +834,17 @@ u32 GetNumberOfCPUs() {
   int req[2];
   uptr len = sizeof(ncpu);
   req[0] = CTL_HW;
+#    ifdef HW_NCPUONLINE
+  req[1] = HW_NCPUONLINE;
+#    else
   req[1] = HW_NCPU;
+#    endif
   CHECK_EQ(internal_sysctl(req, 2, &ncpu, &len, NULL, 0), 0);
   return ncpu;
-#  elif SANITIZER_ANDROID && !defined(CPU_COUNT) && !defined(__aarch64__)
-  // Fall back to /sys/devices/system/cpu on Android when cpu_set_t doesn't
-  // exist in sched.h. That is the case for toolchains generated with older
-  // NDKs.
-  // This code doesn't work on AArch64 because internal_getdents makes use of
-  // the 64bit getdents syscall, but cpu_set_t seems to always exist on AArch64.
-  uptr fd = internal_open("/sys/devices/system/cpu", O_RDONLY | O_DIRECTORY);
-  if (internal_iserror(fd))
-    return 0;
-  InternalMmapVector<u8> buffer(4096);
-  uptr bytes_read = buffer.size();
-  uptr n_cpus = 0;
-  u8 *d_type;
-  struct linux_dirent *entry = (struct linux_dirent *)&buffer[bytes_read];
-  while (true) {
-    if ((u8 *)entry >= &buffer[bytes_read]) {
-      bytes_read = internal_getdents(fd, (struct linux_dirent *)buffer.data(),
-                                     buffer.size());
-      if (internal_iserror(bytes_read) || !bytes_read)
-        break;
-      entry = (struct linux_dirent *)buffer.data();
-    }
-    d_type = (u8 *)entry + entry->d_reclen - 1;
-    if (d_type >= &buffer[bytes_read] ||
-        (u8 *)&entry->d_name[3] >= &buffer[bytes_read])
-      break;
-    if (entry->d_ino != 0 && *d_type == DT_DIR) {
-      if (entry->d_name[0] == 'c' && entry->d_name[1] == 'p' &&
-          entry->d_name[2] == 'u' && entry->d_name[3] >= '0' &&
-          entry->d_name[3] <= '9')
-        n_cpus++;
-    }
-    entry = (struct linux_dirent *)(((u8 *)entry) + entry->d_reclen);
-  }
-  internal_close(fd);
-  return n_cpus;
+#  elif SANITIZER_HAIKU
+  system_info info;
+  get_system_info(&info);
+  return info.cpu_count;
 #  elif SANITIZER_SOLARIS
   return sysconf(_SC_NPROCESSORS_ONLN);
 #  else
lib/libtsan/sanitizer_common/sanitizer_mac.cpp
@@ -38,13 +38,6 @@
 extern char **environ;
 #  endif
 
-#  if defined(__has_include) && __has_include(<os/trace.h>)
-#    define SANITIZER_OS_TRACE 1
-#    include <os/trace.h>
-#  else
-#    define SANITIZER_OS_TRACE 0
-#  endif
-
 // Integrate with CrashReporter library if available
 #  if defined(__has_include) && __has_include(<CrashReporterClient.h>)
 #    define HAVE_CRASHREPORTERCLIENT_H 1
@@ -843,31 +836,23 @@ void LogMessageOnPrintf(const char *str) {
 }
 
 void LogFullErrorReport(const char *buffer) {
-#if !SANITIZER_GO
-  // Log with os_trace. This will make it into the crash log.
-#if SANITIZER_OS_TRACE
-#pragma clang diagnostic push
-// os_trace is deprecated.
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-  if (GetMacosAlignedVersion() >= MacosVersion(10, 10)) {
-    // os_trace requires the message (format parameter) to be a string literal.
-    if (internal_strncmp(SanitizerToolName, "AddressSanitizer",
-                         sizeof("AddressSanitizer") - 1) == 0)
-      os_trace("Address Sanitizer reported a failure.");
-    else if (internal_strncmp(SanitizerToolName, "UndefinedBehaviorSanitizer",
-                              sizeof("UndefinedBehaviorSanitizer") - 1) == 0)
-      os_trace("Undefined Behavior Sanitizer reported a failure.");
-    else if (internal_strncmp(SanitizerToolName, "ThreadSanitizer",
-                              sizeof("ThreadSanitizer") - 1) == 0)
-      os_trace("Thread Sanitizer reported a failure.");
-    else
-      os_trace("Sanitizer tool reported a failure.");
-
-    if (common_flags()->log_to_syslog)
-      os_trace("Consult syslog for more information.");
-  }
-#pragma clang diagnostic pop
-#endif
+#  if !SANITIZER_GO
+  // Log with os_log_error. This will make it into the crash log.
+  if (internal_strncmp(SanitizerToolName, "AddressSanitizer",
+                       sizeof("AddressSanitizer") - 1) == 0)
+    os_log_error(OS_LOG_DEFAULT, "Address Sanitizer reported a failure.");
+  else if (internal_strncmp(SanitizerToolName, "UndefinedBehaviorSanitizer",
+                            sizeof("UndefinedBehaviorSanitizer") - 1) == 0)
+    os_log_error(OS_LOG_DEFAULT,
+                 "Undefined Behavior Sanitizer reported a failure.");
+  else if (internal_strncmp(SanitizerToolName, "ThreadSanitizer",
+                            sizeof("ThreadSanitizer") - 1) == 0)
+    os_log_error(OS_LOG_DEFAULT, "Thread Sanitizer reported a failure.");
+  else
+    os_log_error(OS_LOG_DEFAULT, "Sanitizer tool reported a failure.");
+
+  if (common_flags()->log_to_syslog)
+    os_log_error(OS_LOG_DEFAULT, "Consult syslog for more information.");
 
   // Log to syslog.
   // The logging on OS X may call pthread_create so we need the threading
@@ -881,7 +866,7 @@ void LogFullErrorReport(const char *buffer) {
     WriteToSyslog(buffer);
 
   // The report is added to CrashLog as part of logging all of Printf output.
-#endif
+#  endif  // !SANITIZER_GO
 }
 
 SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
@@ -1203,13 +1188,14 @@ uptr MapDynamicShadow(uptr shadow_size_bytes, uptr shadow_scale,
   const uptr left_padding =
       Max<uptr>(granularity, 1ULL << min_shadow_base_alignment);
 
-  uptr space_size = shadow_size_bytes + left_padding;
+  uptr space_size = shadow_size_bytes;
 
   uptr largest_gap_found = 0;
   uptr max_occupied_addr = 0;
+
   VReport(2, "FindDynamicShadowStart, space_size = %p\n", (void *)space_size);
   uptr shadow_start =
-      FindAvailableMemoryRange(space_size, alignment, granularity,
+      FindAvailableMemoryRange(space_size, alignment, left_padding,
                                &largest_gap_found, &max_occupied_addr);
   // If the shadow doesn't fit, restrict the address space to make it fit.
   if (shadow_start == 0) {
@@ -1229,9 +1215,9 @@ uptr MapDynamicShadow(uptr shadow_size_bytes, uptr shadow_scale,
     }
     RestrictMemoryToMaxAddress(new_max_vm);
     high_mem_end = new_max_vm - 1;
-    space_size = (high_mem_end >> shadow_scale) + left_padding;
+    space_size = (high_mem_end >> shadow_scale);
     VReport(2, "FindDynamicShadowStart, space_size = %p\n", (void *)space_size);
-    shadow_start = FindAvailableMemoryRange(space_size, alignment, granularity,
+    shadow_start = FindAvailableMemoryRange(space_size, alignment, left_padding,
                                             nullptr, nullptr);
     if (shadow_start == 0) {
       Report("Unable to find a memory range after restricting VM.\n");
@@ -1272,10 +1258,15 @@ uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding,
     mach_msg_type_number_t count = kRegionInfoSize;
     kr = mach_vm_region_recurse(mach_task_self(), &address, &vmsize, &depth,
                                 (vm_region_info_t)&vminfo, &count);
-    if (kr == KERN_INVALID_ADDRESS) {
+
+    // There are cases where going beyond the processes' max vm does
+    // not return KERN_INVALID_ADDRESS so we check for going beyond that
+    // max address as well.
+    if (kr == KERN_INVALID_ADDRESS || address > max_vm_address) {
       // No more regions beyond "address", consider the gap at the end of VM.
       address = max_vm_address;
       vmsize = 0;
+      kr = -1;  // break after this iteration.
     } else {
       if (max_occupied_addr) *max_occupied_addr = address + vmsize;
     }
lib/libtsan/sanitizer_common/sanitizer_mac.h
@@ -37,9 +37,6 @@ struct VersionBase {
 
   VersionBase(u16 major, u16 minor) : major(major), minor(minor) {}
 
-  bool operator==(const VersionType &other) const {
-    return major == other.major && minor == other.minor;
-  }
   bool operator>=(const VersionType &other) const {
     return major > other.major ||
            (major == other.major && minor >= other.minor);
@@ -47,6 +44,12 @@ struct VersionBase {
   bool operator<(const VersionType &other) const { return !(*this >= other); }
 };
 
+template <typename VersionType>
+bool operator==(const VersionBase<VersionType> &self,
+                const VersionBase<VersionType> &other) {
+  return self.major == other.major && self.minor == other.minor;
+}
+
 struct MacosVersion : VersionBase<MacosVersion> {
   MacosVersion(u16 major, u16 minor) : VersionBase(major, minor) {}
 };
lib/libtsan/sanitizer_common/sanitizer_malloc_mac.inc
@@ -144,6 +144,22 @@ INTERCEPTOR(void, free, void *ptr) {
   COMMON_MALLOC_FREE(ptr);
 }
 
+#if SANITIZER_INTERCEPT_FREE_SIZED && defined(COMMON_MALLOC_FREE_SIZED)
+INTERCEPTOR(void, free_sized, void *ptr, size_t size) {
+  COMMON_MALLOC_ENTER();
+  COMMON_MALLOC_FREE_SIZED(ptr, size);
+}
+#endif
+
+#if SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED && \
+    defined(COMMON_MALLOC_FREE_ALIGNED_SIZED)
+INTERCEPTOR(void, free_aligned_sized, void *ptr, size_t alignment,
+            size_t size) {
+  COMMON_MALLOC_ENTER();
+  COMMON_MALLOC_FREE_ALIGNED_SIZED(ptr, alignment, size);
+}
+#endif
+
 INTERCEPTOR(void *, realloc, void *ptr, size_t size) {
   COMMON_MALLOC_ENTER();
   COMMON_MALLOC_REALLOC(ptr, size);
lib/libtsan/sanitizer_common/sanitizer_platform.h
@@ -14,7 +14,8 @@
 
 #if !defined(__linux__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && \
     !defined(__APPLE__) && !defined(_WIN32) && !defined(__Fuchsia__) &&     \
-    !(defined(__sun__) && defined(__svr4__))
+    !(defined(__sun__) && defined(__svr4__)) && !defined(__HAIKU__) &&      \
+    !defined(__wasi__)
 #  error "This operating system is not supported"
 #endif
 
@@ -55,6 +56,18 @@
 #  define SANITIZER_SOLARIS 0
 #endif
 
+#if defined(__HAIKU__)
+#  define SANITIZER_HAIKU 1
+#else
+#  define SANITIZER_HAIKU 0
+#endif
+
+#if defined(__wasi__)
+#  define SANITIZER_WASI 1
+#else
+#  define SANITIZER_WASI 0
+#endif
+
 // - SANITIZER_APPLE: all Apple code
 //   - TARGET_OS_OSX: macOS
 //   - SANITIZER_IOS: devices (iOS and iOS-like)
@@ -136,9 +149,9 @@
 #  define SANITIZER_MUSL 0
 #endif
 
-#define SANITIZER_POSIX                                     \
+#define SANITIZER_POSIX                                       \
   (SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_APPLE || \
-   SANITIZER_NETBSD || SANITIZER_SOLARIS)
+   SANITIZER_NETBSD || SANITIZER_SOLARIS || SANITIZER_HAIKU)
 
 #if __LP64__ || defined(_WIN64)
 #  define SANITIZER_WORDSIZE 64
@@ -305,6 +318,9 @@
 #  endif
 #endif
 
+// The first address that can be returned by mmap.
+#define SANITIZER_MMAP_BEGIN 0
+
 // The range of addresses which can be returned my mmap.
 // FIXME: this value should be different on different platforms.  Larger values
 // will still work but will consume more memory for TwoLevelByteMap.
@@ -410,7 +426,8 @@
 #  define SANITIZER_SUPPRESS_LEAK_ON_PTHREAD_EXIT 0
 #endif
 
-#if SANITIZER_FREEBSD || SANITIZER_APPLE || SANITIZER_NETBSD || SANITIZER_SOLARIS
+#if SANITIZER_FREEBSD || SANITIZER_APPLE || SANITIZER_NETBSD || \
+    SANITIZER_SOLARIS || SANITIZER_HAIKU
 #  define SANITIZER_MADVISE_DONTNEED MADV_FREE
 #else
 #  define SANITIZER_MADVISE_DONTNEED MADV_DONTNEED
lib/libtsan/sanitizer_common/sanitizer_platform_interceptors.h
@@ -129,8 +129,10 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment,
 
 #if SANITIZER_FUCHSIA
 #define SI_NOT_FUCHSIA 0
+#define SI_FUCHSIA 1
 #else
 #define SI_NOT_FUCHSIA 1
+#define SI_FUCHSIA 0
 #endif
 
 #if SANITIZER_SOLARIS
@@ -139,6 +141,12 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment,
 #define SI_SOLARIS 0
 #endif
 
+#if SANITIZER_AIX
+#  define SI_NOT_AIX 0
+#else
+#  define SI_NOT_AIX 1
+#endif
+
 #if SANITIZER_SOLARIS32
 #define SI_SOLARIS32 1
 #else
@@ -159,20 +167,20 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment,
 
 #define SANITIZER_INTERCEPT_STRLEN SI_NOT_FUCHSIA
 #define SANITIZER_INTERCEPT_STRNLEN (SI_NOT_MAC && SI_NOT_FUCHSIA)
-#define SANITIZER_INTERCEPT_STRCMP SI_NOT_FUCHSIA
+#define SANITIZER_INTERCEPT_STRCMP (SI_NOT_FUCHSIA && SI_NOT_AIX)
 #define SANITIZER_INTERCEPT_STRSTR SI_NOT_FUCHSIA
-#define SANITIZER_INTERCEPT_STRCASESTR SI_POSIX
+#define SANITIZER_INTERCEPT_STRCASESTR (SI_POSIX && SI_NOT_AIX)
 #define SANITIZER_INTERCEPT_STRTOK SI_NOT_FUCHSIA
 #define SANITIZER_INTERCEPT_STRCHR SI_NOT_FUCHSIA
-#define SANITIZER_INTERCEPT_STRCHRNUL SI_POSIX_NOT_MAC
+#define SANITIZER_INTERCEPT_STRCHRNUL (SI_POSIX_NOT_MAC && SI_NOT_AIX)
 #define SANITIZER_INTERCEPT_STRRCHR SI_NOT_FUCHSIA
 #define SANITIZER_INTERCEPT_STRSPN SI_NOT_FUCHSIA
 #define SANITIZER_INTERCEPT_STRPBRK SI_NOT_FUCHSIA
 #define SANITIZER_INTERCEPT_TEXTDOMAIN SI_LINUX_NOT_ANDROID || SI_SOLARIS
 #define SANITIZER_INTERCEPT_STRCASECMP SI_POSIX
 #define SANITIZER_INTERCEPT_MEMSET 1
-#define SANITIZER_INTERCEPT_MEMMOVE 1
-#define SANITIZER_INTERCEPT_MEMCPY 1
+#define SANITIZER_INTERCEPT_MEMMOVE SI_NOT_AIX
+#define SANITIZER_INTERCEPT_MEMCPY SI_NOT_AIX
 #define SANITIZER_INTERCEPT_MEMCMP SI_NOT_FUCHSIA
 #define SANITIZER_INTERCEPT_BCMP \
   SANITIZER_INTERCEPT_MEMCMP &&  \
@@ -231,16 +239,22 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment,
 #define SANITIZER_INTERCEPT_ISOC99_SCANF SI_GLIBC
 
 #ifndef SANITIZER_INTERCEPT_PRINTF
-#define SANITIZER_INTERCEPT_PRINTF SI_POSIX
-#define SANITIZER_INTERCEPT_PRINTF_L (SI_FREEBSD || SI_NETBSD)
-#define SANITIZER_INTERCEPT_ISOC99_PRINTF SI_GLIBC
+#  define SANITIZER_INTERCEPT_ASPRINTF SI_NOT_AIX
+#  define SANITIZER_INTERCEPT_VASPRINTF SI_NOT_AIX
+#  define SANITIZER_INTERCEPT_PRINTF SI_POSIX
+#  define SANITIZER_INTERCEPT_PRINTF_L (SI_FREEBSD || SI_NETBSD)
+#  define SANITIZER_INTERCEPT_ISOC99_PRINTF SI_GLIBC
 #endif
 
+#define SANITIZER_INTERCEPT_SETPROCTITLE (SI_FREEBSD || SI_NETBSD)
+
 #define SANITIZER_INTERCEPT___PRINTF_CHK \
   (SANITIZER_INTERCEPT_PRINTF && SI_GLIBC)
 
-#define SANITIZER_INTERCEPT_FREXP SI_NOT_FUCHSIA
-#define SANITIZER_INTERCEPT_FREXPF_FREXPL SI_POSIX
+// AIX libc does not export FREXP and FREXPF.
+#define SANITIZER_INTERCEPT_FREXP (SI_NOT_FUCHSIA && SI_NOT_AIX)
+#define SANITIZER_INTERCEPT_FREXPF (SI_POSIX && SI_NOT_AIX)
+#define SANITIZER_INTERCEPT_FREXPL SI_POSIX
 
 #define SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS SI_POSIX
 #define SANITIZER_INTERCEPT_GETPWNAM_R_AND_FRIENDS \
@@ -289,7 +303,7 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment,
 #define SANITIZER_INTERCEPT_ACCEPT4 \
   (SI_LINUX_NOT_ANDROID || SI_NETBSD || SI_FREEBSD)
 #define SANITIZER_INTERCEPT_PACCEPT SI_NETBSD
-#define SANITIZER_INTERCEPT_MODF SI_POSIX
+#define SANITIZER_INTERCEPT_MODF (SI_POSIX && SI_NOT_AIX)
 #define SANITIZER_INTERCEPT_RECVMSG SI_POSIX
 #define SANITIZER_INTERCEPT_SENDMSG SI_POSIX
 #define SANITIZER_INTERCEPT_RECVMMSG SI_LINUX
@@ -324,8 +338,9 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment,
 #define SANITIZER_INTERCEPT___WCSXFRM_L SI_LINUX
 #define SANITIZER_INTERCEPT_WCSNRTOMBS \
   (SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
-#define SANITIZER_INTERCEPT_WCRTOMB \
-  (SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_WCRTOMB                                           \
+  (SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS || \
+   !SI_NOT_AIX)
 #define SANITIZER_INTERCEPT_WCTOMB \
   (SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
 #define SANITIZER_INTERCEPT_TCGETATTR SI_LINUX_NOT_ANDROID || SI_SOLARIS
@@ -365,7 +380,8 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment,
 #define SANITIZER_INTERCEPT_GETMNTENT_R SI_LINUX_NOT_ANDROID
 #define SANITIZER_INTERCEPT_STATFS \
   (SI_FREEBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
-#define SANITIZER_INTERCEPT_STATFS64 SI_GLIBC && SANITIZER_HAS_STATFS64
+#define SANITIZER_INTERCEPT_STATFS64 \
+  ((SI_GLIBC || !SI_NOT_AIX) && SANITIZER_HAS_STATFS64)
 #define SANITIZER_INTERCEPT_STATVFS \
   (SI_FREEBSD || SI_NETBSD || SI_LINUX_NOT_ANDROID)
 #define SANITIZER_INTERCEPT_STATVFS64 SI_GLIBC
@@ -414,10 +430,10 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment,
 #define SANITIZER_INTERCEPT_TTYNAME_R SI_POSIX
 #define SANITIZER_INTERCEPT_TEMPNAM SI_POSIX
 #define SANITIZER_INTERCEPT_SINCOS SI_LINUX || SI_SOLARIS
-#define SANITIZER_INTERCEPT_REMQUO SI_POSIX
-#define SANITIZER_INTERCEPT_REMQUOL (SI_POSIX && !SI_NETBSD)
-#define SANITIZER_INTERCEPT_LGAMMA SI_POSIX
-#define SANITIZER_INTERCEPT_LGAMMAL (SI_POSIX && !SI_NETBSD)
+#define SANITIZER_INTERCEPT_REMQUO (SI_POSIX && SI_NOT_AIX)
+#define SANITIZER_INTERCEPT_REMQUOL (SI_POSIX && !SI_NETBSD && SI_NOT_AIX)
+#define SANITIZER_INTERCEPT_LGAMMA (SI_POSIX && SI_NOT_AIX)
+#define SANITIZER_INTERCEPT_LGAMMAL (SI_POSIX && !SI_NETBSD && SI_NOT_AIX)
 #define SANITIZER_INTERCEPT_LGAMMA_R (SI_FREEBSD || SI_LINUX || SI_SOLARIS)
 #define SANITIZER_INTERCEPT_LGAMMAL_R SI_LINUX_NOT_ANDROID || SI_SOLARIS
 #define SANITIZER_INTERCEPT_DRAND48_R SI_GLIBC
@@ -500,11 +516,13 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment,
 #define SANITIZER_INTERCEPT_EVENTFD_READ_WRITE (SI_LINUX || SI_FREEBSD)
 
 #define SI_STAT_LINUX (SI_LINUX && __GLIBC_PREREQ(2, 33))
-#define SANITIZER_INTERCEPT_STAT                                        \
-  (SI_FREEBSD || SI_MAC || SI_ANDROID || SI_NETBSD || SI_SOLARIS ||     \
-   SI_STAT_LINUX)
-#define SANITIZER_INTERCEPT_STAT64 SI_STAT_LINUX && SANITIZER_HAS_STAT64
-#define SANITIZER_INTERCEPT_LSTAT (SI_NETBSD || SI_FREEBSD || SI_STAT_LINUX)
+#define SANITIZER_INTERCEPT_STAT                                    \
+  (SI_FREEBSD || SI_MAC || SI_ANDROID || SI_NETBSD || SI_SOLARIS || \
+   SI_STAT_LINUX || !SI_NOT_AIX)
+#define SANITIZER_INTERCEPT_STAT64 \
+  ((SI_STAT_LINUX || !SI_NOT_AIX) && SANITIZER_HAS_STAT64)
+#define SANITIZER_INTERCEPT_LSTAT \
+  (SI_NETBSD || SI_FREEBSD || SI_STAT_LINUX || !SI_NOT_AIX)
 #define SANITIZER_INTERCEPT___XSTAT \
   ((!SANITIZER_INTERCEPT_STAT && SI_POSIX) || SI_STAT_LINUX)
 #define SANITIZER_INTERCEPT___XSTAT64 SI_GLIBC
@@ -521,7 +539,8 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment,
 
 #define SANITIZER_INTERCEPT_MMAP SI_POSIX
 #define SANITIZER_INTERCEPT_MMAP64 SI_GLIBC || SI_SOLARIS
-#define SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO (SI_GLIBC || SI_ANDROID)
+#define SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO \
+  (SI_GLIBC || SI_ANDROID || SI_FUCHSIA)
 #define SANITIZER_INTERCEPT_MEMALIGN (!SI_FREEBSD && !SI_MAC && !SI_NETBSD)
 #define SANITIZER_INTERCEPT___LIBC_MEMALIGN SI_GLIBC
 #define SANITIZER_INTERCEPT_PVALLOC (SI_GLIBC || SI_ANDROID)
@@ -572,7 +591,7 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment,
 #define SANITIZER_INTERCEPT_PROTOENT_R SI_GLIBC
 #define SANITIZER_INTERCEPT_NETENT (SI_LINUX || SI_NETBSD || SI_FREEBSD)
 #define SANITIZER_INTERCEPT_SETVBUF \
-  (SI_NETBSD || SI_FREEBSD || SI_LINUX || SI_MAC)
+  (SI_NETBSD || SI_FREEBSD || SI_LINUX || SI_MAC || !SI_NOT_AIX)
 #define SANITIZER_INTERCEPT_GETMNTINFO (SI_NETBSD || SI_FREEBSD || SI_MAC)
 #define SANITIZER_INTERCEPT_MI_VECTOR_HASH SI_NETBSD
 #define SANITIZER_INTERCEPT_GETVFSSTAT SI_NETBSD
@@ -640,6 +659,21 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment,
 #  define SI_MAC_OS_DEPLOYMENT_MIN_13_00 0
 #endif
 #define SANITIZER_INTERCEPT_FREADLINK (SI_MAC && SI_MAC_OS_DEPLOYMENT_MIN_13_00)
+#define SANITIZER_INTERCEPT_GETSERVENT_R SI_GLIBC
+#define SANITIZER_INTERCEPT_GETSERVBYNAME_R SI_GLIBC
+#define SANITIZER_INTERCEPT_GETSERVBYPORT_R SI_GLIBC
+
+// Until free_sized and free_aligned_sized are more generally available,
+// we can only unconditionally intercept on ELF-based platforms where it
+// is okay to have undefined weak symbols.
+#ifdef __ELF__
+#  define SANITIZER_INTERCEPT_FREE_SIZED 1
+#  define SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED 1
+#else
+#  define SANITIZER_INTERCEPT_FREE_SIZED 0
+#  define SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED 0
+#endif
+
 // This macro gives a way for downstream users to override the above
 // interceptor macros irrespective of the platform they are on. They have
 // to do two things:
lib/libtsan/sanitizer_common/sanitizer_platform_limits_freebsd.cpp
@@ -29,6 +29,7 @@
 #include <sys/mtio.h>
 #include <sys/ptrace.h>
 #include <sys/resource.h>
+#include <sys/shm.h>
 #include <sys/signal.h>
 #include <sys/socket.h>
 #include <sys/sockio.h>
@@ -81,10 +82,6 @@
 #include <wchar.h>
 #include <wordexp.h>
 
-#define _KERNEL  // to declare 'shminfo' structure
-#include <sys/shm.h>
-#undef _KERNEL
-
 #undef IOC_DIRMASK
 
 // Include these after system headers to avoid name clashes and ambiguities.
@@ -135,8 +132,6 @@ unsigned struct_timeb_sz = sizeof(struct timeb);
 unsigned struct_msqid_ds_sz = sizeof(struct msqid_ds);
 unsigned struct_mq_attr_sz = sizeof(struct mq_attr);
 unsigned struct_statvfs_sz = sizeof(struct statvfs);
-unsigned struct_shminfo_sz = sizeof(struct shminfo);
-unsigned struct_shm_info_sz = sizeof(struct shm_info);
 unsigned struct_regmatch_sz = sizeof(regmatch_t);
 unsigned struct_regex_sz = sizeof(regex_t);
 unsigned struct_fstab_sz = sizeof(struct fstab);
@@ -150,9 +145,6 @@ const uptr sig_err = (uptr)SIG_ERR;
 const uptr sa_siginfo = (uptr)SA_SIGINFO;
 
 int shmctl_ipc_stat = (int)IPC_STAT;
-int shmctl_ipc_info = (int)IPC_INFO;
-int shmctl_shm_info = (int)SHM_INFO;
-int shmctl_shm_stat = (int)SHM_STAT;
 unsigned struct_utmpx_sz = sizeof(struct utmpx);
 
 int map_fixed = MAP_FIXED;
lib/libtsan/sanitizer_common/sanitizer_platform_limits_freebsd.h
@@ -419,12 +419,14 @@ struct __sanitizer_wordexp_t {
 
 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;
+
+// This simplifies generic code
+#define struct_shminfo_sz -1
+#define struct_shm_info_sz -1
+#define shmctl_shm_stat -1
+#define shmctl_ipc_info -1
+#define shmctl_shm_info -1
 
 extern unsigned struct_utmpx_sz;
 
lib/libtsan/sanitizer_common/sanitizer_platform_limits_posix.cpp
@@ -24,7 +24,7 @@
 // Must go after undef _FILE_OFFSET_BITS.
 #include "sanitizer_platform.h"
 
-#if SANITIZER_LINUX || SANITIZER_APPLE
+#if SANITIZER_LINUX || SANITIZER_APPLE || SANITIZER_HAIKU
 // Must go after undef _FILE_OFFSET_BITS.
 #include "sanitizer_glibc_version.h"
 
@@ -52,7 +52,7 @@
 #include <time.h>
 #include <wchar.h>
 #include <regex.h>
-#if !SANITIZER_APPLE
+#if !SANITIZER_APPLE && !SANITIZER_HAIKU
 #include <utmp.h>
 #endif
 
@@ -61,7 +61,9 @@
 #endif
 
 #if !SANITIZER_ANDROID
+#if !SANITIZER_HAIKU
 #include <sys/mount.h>
+#endif
 #include <sys/timeb.h>
 #include <utmpx.h>
 #endif
@@ -111,9 +113,11 @@ typedef struct user_fpregs elf_fpregset_t;
 
 #if !SANITIZER_ANDROID
 #include <ifaddrs.h>
+#if !SANITIZER_HAIKU
 #include <sys/ucontext.h>
 #include <wordexp.h>
 #endif
+#endif
 
 #if SANITIZER_LINUX
 #if SANITIZER_GLIBC
@@ -163,7 +167,7 @@ typedef struct user_fpregs elf_fpregset_t;
 #include <sys/vfs.h>
 #include <sys/epoll.h>
 #include <linux/capability.h>
-#else
+#elif !SANITIZER_HAIKU
 #include <fstab.h>
 #endif // SANITIZER_LINUX
 
@@ -173,6 +177,11 @@ typedef struct user_fpregs elf_fpregset_t;
 #include <sys/sockio.h>
 #endif
 
+#if SANITIZER_HAIKU
+#include <sys/sockio.h>
+#include <sys/ioctl.h>
+#endif
+
 // Include these after system headers to avoid name clashes and ambiguities.
 #  include "sanitizer_common.h"
 #  include "sanitizer_internal_defs.h"
@@ -217,7 +226,7 @@ namespace __sanitizer {
   unsigned struct_fstab_sz = sizeof(struct fstab);
 #endif  // SANITIZER_GLIBC || SANITIZER_FREEBSD || SANITIZER_NETBSD ||
         // SANITIZER_APPLE
-#if !SANITIZER_ANDROID
+#if !SANITIZER_ANDROID && !SANITIZER_HAIKU
   unsigned struct_statfs_sz = sizeof(struct statfs);
   unsigned struct_sockaddr_sz = sizeof(struct sockaddr);
 
@@ -324,7 +333,7 @@ namespace __sanitizer {
   int shmctl_shm_stat = (int)SHM_STAT;
 #endif
 
-#if !SANITIZER_APPLE && !SANITIZER_FREEBSD
+#if !SANITIZER_APPLE && !SANITIZER_FREEBSD && !SANITIZER_HAIKU
   unsigned struct_utmp_sz = sizeof(struct utmp);
 #endif
 #if !SANITIZER_ANDROID
@@ -356,9 +365,9 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);
   int glob_altdirfunc = GLOB_ALTDIRFUNC;
 #endif
 
-#  if !SANITIZER_ANDROID
+#  if !SANITIZER_ANDROID && !SANITIZER_HAIKU
   const int wordexp_wrde_dooffs = WRDE_DOOFFS;
-#  endif  // !SANITIZER_ANDROID
+#  endif  // !SANITIZER_ANDROID && !SANITIZER_HAIKU
 
 #  if SANITIZER_LINUX && !SANITIZER_ANDROID &&                               \
       (defined(__i386) || defined(__x86_64) || defined(__mips64) ||          \
@@ -537,7 +546,7 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);
   unsigned struct_sock_fprog_sz = sizeof(struct sock_fprog);
 #  endif  // SANITIZER_GLIBC
 
-#  if !SANITIZER_ANDROID && !SANITIZER_APPLE
+#  if !SANITIZER_ANDROID && !SANITIZER_APPLE && !SANITIZER_HAIKU
   unsigned struct_sioc_sg_req_sz = sizeof(struct sioc_sg_req);
   unsigned struct_sioc_vif_req_sz = sizeof(struct sioc_vif_req);
 #endif
@@ -548,12 +557,14 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);
 
   const unsigned IOCTL_NOT_PRESENT = 0;
 
+  unsigned IOCTL_FIONBIO = FIONBIO;
+#if !SANITIZER_HAIKU
   unsigned IOCTL_FIOASYNC = FIOASYNC;
   unsigned IOCTL_FIOCLEX = FIOCLEX;
   unsigned IOCTL_FIOGETOWN = FIOGETOWN;
-  unsigned IOCTL_FIONBIO = FIONBIO;
   unsigned IOCTL_FIONCLEX = FIONCLEX;
   unsigned IOCTL_FIOSETOWN = FIOSETOWN;
+#endif
   unsigned IOCTL_SIOCADDMULTI = SIOCADDMULTI;
   unsigned IOCTL_SIOCATMARK = SIOCATMARK;
   unsigned IOCTL_SIOCDELMULTI = SIOCDELMULTI;
@@ -574,23 +585,27 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);
   unsigned IOCTL_SIOCSIFMTU = SIOCSIFMTU;
   unsigned IOCTL_SIOCSIFNETMASK = SIOCSIFNETMASK;
   unsigned IOCTL_SIOCSPGRP = SIOCSPGRP;
+
+#if !SANITIZER_HAIKU
   unsigned IOCTL_TIOCCONS = TIOCCONS;
-  unsigned IOCTL_TIOCEXCL = TIOCEXCL;
   unsigned IOCTL_TIOCGETD = TIOCGETD;
+  unsigned IOCTL_TIOCNOTTY = TIOCNOTTY;
+  unsigned IOCTL_TIOCPKT = TIOCPKT;
+  unsigned IOCTL_TIOCSETD = TIOCSETD;
+  unsigned IOCTL_TIOCSTI = TIOCSTI;
+#endif
+
+  unsigned IOCTL_TIOCEXCL = TIOCEXCL;
   unsigned IOCTL_TIOCGPGRP = TIOCGPGRP;
   unsigned IOCTL_TIOCGWINSZ = TIOCGWINSZ;
   unsigned IOCTL_TIOCMBIC = TIOCMBIC;
   unsigned IOCTL_TIOCMBIS = TIOCMBIS;
   unsigned IOCTL_TIOCMGET = TIOCMGET;
   unsigned IOCTL_TIOCMSET = TIOCMSET;
-  unsigned IOCTL_TIOCNOTTY = TIOCNOTTY;
   unsigned IOCTL_TIOCNXCL = TIOCNXCL;
   unsigned IOCTL_TIOCOUTQ = TIOCOUTQ;
-  unsigned IOCTL_TIOCPKT = TIOCPKT;
   unsigned IOCTL_TIOCSCTTY = TIOCSCTTY;
-  unsigned IOCTL_TIOCSETD = TIOCSETD;
   unsigned IOCTL_TIOCSPGRP = TIOCSPGRP;
-  unsigned IOCTL_TIOCSTI = TIOCSTI;
   unsigned IOCTL_TIOCSWINSZ = TIOCSWINSZ;
 #if SANITIZER_LINUX && !SANITIZER_ANDROID
   unsigned IOCTL_SIOCGETSGCNT = SIOCGETSGCNT;
@@ -1100,7 +1115,7 @@ COMPILER_CHECK(sizeof(__sanitizer_dirent) <= sizeof(dirent));
 CHECK_SIZE_AND_OFFSET(dirent, d_ino);
 #if SANITIZER_APPLE
 CHECK_SIZE_AND_OFFSET(dirent, d_seekoff);
-#elif SANITIZER_FREEBSD
+#elif SANITIZER_FREEBSD || SANITIZER_HAIKU
 // There is no 'd_off' field on FreeBSD.
 #else
 CHECK_SIZE_AND_OFFSET(dirent, d_off);
@@ -1116,7 +1131,9 @@ CHECK_SIZE_AND_OFFSET(dirent64, d_reclen);
 
 CHECK_TYPE_SIZE(ifconf);
 CHECK_SIZE_AND_OFFSET(ifconf, ifc_len);
+#if !SANITIZER_HAIKU
 CHECK_SIZE_AND_OFFSET(ifconf, ifc_ifcu);
+#endif
 
 CHECK_TYPE_SIZE(pollfd);
 CHECK_SIZE_AND_OFFSET(pollfd, fd);
@@ -1171,7 +1188,7 @@ CHECK_TYPE_SIZE(__kernel_loff_t);
 CHECK_TYPE_SIZE(__kernel_fd_set);
 #endif
 
-#if !SANITIZER_ANDROID
+#if !SANITIZER_ANDROID && !SANITIZER_HAIKU
 CHECK_TYPE_SIZE(wordexp_t);
 CHECK_SIZE_AND_OFFSET(wordexp_t, we_wordc);
 CHECK_SIZE_AND_OFFSET(wordexp_t, we_wordv);
@@ -1201,7 +1218,9 @@ CHECK_SIZE_AND_OFFSET(mntent, mnt_freq);
 CHECK_SIZE_AND_OFFSET(mntent, mnt_passno);
 #endif
 
+#if !SANITIZER_HAIKU
 CHECK_TYPE_SIZE(ether_addr);
+#endif
 
 #if SANITIZER_GLIBC || SANITIZER_FREEBSD
 CHECK_TYPE_SIZE(ipc_perm);
@@ -1239,7 +1258,7 @@ CHECK_TYPE_SIZE(clock_t);
 CHECK_TYPE_SIZE(clockid_t);
 #endif
 
-#if !SANITIZER_ANDROID
+#if !SANITIZER_ANDROID && !SANITIZER_HAIKU
 CHECK_TYPE_SIZE(ifaddrs);
 CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_next);
 CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_name);
lib/libtsan/sanitizer_common/sanitizer_platform_limits_posix.h
@@ -14,39 +14,39 @@
 #ifndef SANITIZER_PLATFORM_LIMITS_POSIX_H
 #define SANITIZER_PLATFORM_LIMITS_POSIX_H
 
-#if SANITIZER_LINUX || SANITIZER_APPLE
-
-#include "sanitizer_internal_defs.h"
-#include "sanitizer_platform.h"
-#include "sanitizer_mallinfo.h"
-
-#if SANITIZER_APPLE
-#include <sys/cdefs.h>
-#if !__DARWIN_ONLY_64_BIT_INO_T
-#define SANITIZER_HAS_STAT64 1
-#define SANITIZER_HAS_STATFS64 1
-#else
-#define SANITIZER_HAS_STAT64 0
-#define SANITIZER_HAS_STATFS64 0
-#endif
-#elif SANITIZER_GLIBC || SANITIZER_ANDROID
-#define SANITIZER_HAS_STAT64 1
-#define SANITIZER_HAS_STATFS64 1
-#endif
+#if SANITIZER_LINUX || SANITIZER_APPLE || SANITIZER_HAIKU
+
+#  include "sanitizer_internal_defs.h"
+#  include "sanitizer_mallinfo.h"
+#  include "sanitizer_platform.h"
+
+#  if SANITIZER_APPLE
+#    include <sys/cdefs.h>
+#    if !__DARWIN_ONLY_64_BIT_INO_T
+#      define SANITIZER_HAS_STAT64 1
+#      define SANITIZER_HAS_STATFS64 1
+#    else
+#      define SANITIZER_HAS_STAT64 0
+#      define SANITIZER_HAS_STATFS64 0
+#    endif
+#  elif SANITIZER_GLIBC || SANITIZER_ANDROID
+#    define SANITIZER_HAS_STAT64 1
+#    define SANITIZER_HAS_STATFS64 1
+#  endif
 
-#if defined(__sparc__)
+#  if defined(__sparc__)
 // FIXME: This can't be included from tsan which does not support sparc yet.
-#include "sanitizer_glibc_version.h"
-#endif
+#    include "sanitizer_glibc_version.h"
+#  endif
 
-# define GET_LINK_MAP_BY_DLOPEN_HANDLE(handle) ((link_map*)(handle))
+#  define GET_LINK_MAP_BY_DLOPEN_HANDLE(handle) ((link_map *)(handle))
 
 namespace __sanitizer {
 extern unsigned struct_utsname_sz;
 extern unsigned struct_stat_sz;
-#if SANITIZER_HAS_STAT64
+#  if SANITIZER_HAS_STAT64
 extern unsigned struct_stat64_sz;
-#endif
+#  endif
 extern unsigned struct_rusage_sz;
 extern unsigned siginfo_t_sz;
 extern unsigned struct_itimerval_sz;
@@ -64,13 +64,13 @@ extern unsigned struct_itimerspec_sz;
 extern unsigned struct_sigevent_sz;
 extern unsigned struct_stack_t_sz;
 extern unsigned struct_sched_param_sz;
-#if SANITIZER_HAS_STATFS64
+#  if SANITIZER_HAS_STATFS64
 extern unsigned struct_statfs64_sz;
-#endif
+#  endif
 extern unsigned struct_regex_sz;
 extern unsigned struct_regmatch_sz;
 
-#if !SANITIZER_ANDROID
+#  if !SANITIZER_ANDROID
 extern unsigned struct_fstab_sz;
 extern unsigned struct_statfs_sz;
 extern unsigned struct_sockaddr_sz;
@@ -82,22 +82,22 @@ unsigned ucontext_t_sz(void *uctx);
 #    if defined(__x86_64__)
 const unsigned struct_kernel_stat_sz = 144;
 const unsigned struct_kernel_stat64_sz = 0;
-#elif defined(__i386__)
+#    elif defined(__i386__)
 const unsigned struct_kernel_stat_sz = 64;
 const unsigned struct_kernel_stat64_sz = 96;
-#elif defined(__arm__)
+#    elif defined(__arm__)
 const unsigned struct_kernel_stat_sz = 64;
 const unsigned struct_kernel_stat64_sz = 104;
-#elif defined(__aarch64__)
+#    elif defined(__aarch64__)
 const unsigned struct_kernel_stat_sz = 128;
 const unsigned struct_kernel_stat64_sz = 104;
-#elif defined(__powerpc__) && !defined(__powerpc64__)
+#    elif defined(__powerpc__) && !defined(__powerpc64__)
 const unsigned struct_kernel_stat_sz = 72;
 const unsigned struct_kernel_stat64_sz = 104;
-#elif defined(__powerpc64__)
+#    elif defined(__powerpc64__)
 const unsigned struct_kernel_stat_sz = 144;
 const unsigned struct_kernel_stat64_sz = 104;
-#elif defined(__mips__)
+#    elif defined(__mips__)
 const unsigned struct_kernel_stat_sz = SANITIZER_ANDROID
                                            ? FIRST_32_SECOND_64(104, 128)
 #      if defined(_ABIN32) && _MIPS_SIM == _ABIN32
@@ -106,21 +106,21 @@ const unsigned struct_kernel_stat_sz = SANITIZER_ANDROID
                                            : FIRST_32_SECOND_64(160, 216);
 #      endif
 const unsigned struct_kernel_stat64_sz = 104;
-#elif defined(__s390__) && !defined(__s390x__)
+#    elif defined(__s390__) && !defined(__s390x__)
 const unsigned struct_kernel_stat_sz = 64;
 const unsigned struct_kernel_stat64_sz = 104;
-#elif defined(__s390x__)
+#    elif defined(__s390x__)
 const unsigned struct_kernel_stat_sz = 144;
 const unsigned struct_kernel_stat64_sz = 0;
-#elif defined(__sparc__) && defined(__arch64__)
+#    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;
-#elif defined(__sparc__) && !defined(__arch64__)
+#    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;
-#elif SANITIZER_RISCV64
+#    elif SANITIZER_RISCV64
 const unsigned struct_kernel_stat_sz = 128;
 const unsigned struct_kernel_stat64_sz = 0;  // RISCV64 does not use stat64
 #    elif defined(__hexagon__)
@@ -145,15 +145,15 @@ extern unsigned struct_old_utsname_sz;
 extern unsigned struct_oldold_utsname_sz;
 
 const unsigned struct_kexec_segment_sz = 4 * sizeof(unsigned long);
-#endif  // SANITIZER_LINUX
+#  endif  // SANITIZER_LINUX
 
-#if SANITIZER_LINUX
+#  if SANITIZER_LINUX
 
-#if defined(__powerpc64__) || defined(__s390__) || defined(__loongarch__)
+#    if defined(__powerpc64__) || defined(__s390__) || defined(__loongarch__)
 const unsigned struct___old_kernel_stat_sz = 0;
-#elif !defined(__sparc__)
+#    elif !defined(__sparc__)
 const unsigned struct___old_kernel_stat_sz = 32;
-#endif
+#    endif
 
 extern unsigned struct_rlimit_sz;
 extern unsigned struct_utimbuf_sz;
@@ -198,17 +198,17 @@ struct __sanitizer___sysctl_args {
 const unsigned old_sigset_t_sz = sizeof(unsigned long);
 
 struct __sanitizer_sem_t {
-#if SANITIZER_ANDROID && defined(_LP64)
+#    if SANITIZER_ANDROID && defined(_LP64)
   int data[4];
-#elif SANITIZER_ANDROID && !defined(_LP64)
+#    elif SANITIZER_ANDROID && !defined(_LP64)
   int data;
-#elif SANITIZER_LINUX
+#    elif SANITIZER_LINUX
   uptr data[4];
-#endif
+#    endif
 };
-#endif // SANITIZER_LINUX
+#  endif  // SANITIZER_LINUX
 
-#if SANITIZER_LINUX && !SANITIZER_ANDROID
+#  if SANITIZER_LINUX && !SANITIZER_ANDROID
 extern unsigned struct_ustat_sz;
 extern unsigned struct_rlimit64_sz;
 extern unsigned struct_statvfs64_sz;
@@ -219,45 +219,45 @@ struct __sanitizer_ipc_perm {
   int gid;
   int cuid;
   int cgid;
-#ifdef __powerpc__
+#    ifdef __powerpc__
   unsigned mode;
   unsigned __seq;
   u64 __unused1;
   u64 __unused2;
-#elif defined(__sparc__)
+#    elif defined(__sparc__)
   unsigned mode;
   unsigned short __pad2;
   unsigned short __seq;
   unsigned long long __unused1;
   unsigned long long __unused2;
-#else
+#    else
   unsigned int mode;
   unsigned short __seq;
   unsigned short __pad2;
-#if defined(__x86_64__) && !defined(_LP64)
+#      if defined(__x86_64__) && !defined(_LP64)
   u64 __unused1;
   u64 __unused2;
-#else
+#      else
   unsigned long __unused1;
   unsigned long __unused2;
-#endif
-#endif
+#      endif
+#    endif
 };
 
 struct __sanitizer_shmid_ds {
   __sanitizer_ipc_perm shm_perm;
-#if defined(__sparc__)
-#if !defined(__arch64__)
+#    if defined(__sparc__)
+#      if !defined(__arch64__)
   u32 __pad1;
-#endif
+#      endif
   long shm_atime;
-#if !defined(__arch64__)
+#      if !defined(__arch64__)
   u32 __pad2;
-#endif
+#      endif
   long shm_dtime;
-#if !defined(__arch64__)
+#      if !defined(__arch64__)
   u32 __pad3;
-#endif
+#      endif
   long shm_ctime;
   uptr shm_segsz;
   int shm_cpid;
@@ -265,61 +265,61 @@ struct __sanitizer_shmid_ds {
   unsigned long shm_nattch;
   unsigned long __glibc_reserved1;
   unsigned long __glibc_reserved2;
-#else
-#ifndef __powerpc__
+#    else
+#      ifndef __powerpc__
   uptr shm_segsz;
-#elif !defined(__powerpc64__)
+#      elif !defined(__powerpc64__)
   uptr __unused0;
-#endif
-#if defined(__x86_64__) && !defined(_LP64)
+#      endif
+#      if defined(__x86_64__) && !defined(_LP64)
   u64 shm_atime;
   u64 shm_dtime;
   u64 shm_ctime;
-#else
+#      else
   uptr shm_atime;
-#if !defined(_LP64) && !defined(__mips__)
+#        if !defined(_LP64) && !defined(__mips__)
   uptr __unused1;
-#endif
+#        endif
   uptr shm_dtime;
-#if !defined(_LP64) && !defined(__mips__)
+#        if !defined(_LP64) && !defined(__mips__)
   uptr __unused2;
-#endif
+#        endif
   uptr shm_ctime;
-#if !defined(_LP64) && !defined(__mips__)
+#        if !defined(_LP64) && !defined(__mips__)
   uptr __unused3;
-#endif
-#endif
-#ifdef __powerpc__
+#        endif
+#      endif
+#      ifdef __powerpc__
   uptr shm_segsz;
-#endif
+#      endif
   int shm_cpid;
   int shm_lpid;
-#if defined(__x86_64__) && !defined(_LP64)
+#      if defined(__x86_64__) && !defined(_LP64)
   u64 shm_nattch;
   u64 __unused4;
   u64 __unused5;
-#else
+#      else
   uptr shm_nattch;
   uptr __unused4;
   uptr __unused5;
-#endif
-#endif
+#      endif
+#    endif
 };
-#endif
+#  endif
 
-#if SANITIZER_LINUX && !SANITIZER_ANDROID
+#  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;
-#endif  // SANITIZER_LINUX && !SANITIZER_ANDROID
+#  endif  // SANITIZER_LINUX && !SANITIZER_ANDROID
 
 struct __sanitizer_iovec {
   void *iov_base;
   usize iov_len;
 };
 
-#if !SANITIZER_ANDROID
+#  if !SANITIZER_ANDROID
 struct __sanitizer_ifaddrs {
   struct __sanitizer_ifaddrs *ifa_next;
   char *ifa_name;
@@ -327,21 +327,21 @@ struct __sanitizer_ifaddrs {
   void *ifa_addr;     // (struct sockaddr *)
   void *ifa_netmask;  // (struct sockaddr *)
   // This is a union on Linux.
-# ifdef ifa_dstaddr
-# undef ifa_dstaddr
-# endif
+#    ifdef ifa_dstaddr
+#      undef ifa_dstaddr
+#    endif
   void *ifa_dstaddr;  // (struct sockaddr *)
   void *ifa_data;
 };
-#endif  // !SANITIZER_ANDROID
+#  endif  // !SANITIZER_ANDROID
 
-#if SANITIZER_APPLE
+#  if SANITIZER_APPLE
 typedef unsigned long __sanitizer_pthread_key_t;
-#else
+#  else
 typedef unsigned __sanitizer_pthread_key_t;
-#endif
+#  endif
 
-#if SANITIZER_LINUX && !SANITIZER_ANDROID
+#  if SANITIZER_LINUX && !SANITIZER_ANDROID
 
 struct __sanitizer_XDR {
   int x_op;
@@ -355,25 +355,28 @@ struct __sanitizer_XDR {
 const int __sanitizer_XDR_ENCODE = 0;
 const int __sanitizer_XDR_DECODE = 1;
 const int __sanitizer_XDR_FREE = 2;
-#endif
+#  endif
 
 struct __sanitizer_passwd {
   char *pw_name;
   char *pw_passwd;
   int pw_uid;
   int pw_gid;
-#if SANITIZER_APPLE
+#  if SANITIZER_APPLE
   long pw_change;
   char *pw_class;
-#endif
-#if !(SANITIZER_ANDROID && (SANITIZER_WORDSIZE == 32))
+#  endif
+#  if !(SANITIZER_ANDROID && (SANITIZER_WORDSIZE == 32)) && !SANITIZER_HAIKU
   char *pw_gecos;
-#endif
+#  endif
   char *pw_dir;
   char *pw_shell;
-#if SANITIZER_APPLE
+#  if SANITIZER_APPLE
   long pw_expire;
-#endif
+#  endif
+#  if SANITIZER_HAIKU
+  char *pw_gecos;
+#  endif
 };
 
 struct __sanitizer_group {
@@ -386,9 +389,9 @@ struct __sanitizer_group {
 #  if (SANITIZER_LINUX && !SANITIZER_GLIBC && !SANITIZER_ANDROID) || \
       (defined(__x86_64__) && !defined(_LP64)) || defined(__hexagon__)
 typedef long long __sanitizer_time_t;
-#else
+#  else
 typedef long __sanitizer_time_t;
-#endif
+#  endif
 
 typedef long __sanitizer_suseconds_t;
 
@@ -433,11 +436,15 @@ struct __sanitizer_tm {
   int tm_wday;
   int tm_yday;
   int tm_isdst;
+#  if SANITIZER_HAIKU
+  int tm_gmtoff;
+#  else
   long int tm_gmtoff;
+#  endif
   const char *tm_zone;
 };
 
-#if SANITIZER_LINUX
+#  if SANITIZER_LINUX
 struct __sanitizer_mntent {
   char *mnt_fsname;
   char *mnt_dir;
@@ -452,9 +459,9 @@ struct __sanitizer_file_handle {
   int handle_type;
   unsigned char f_handle[1];  // variable sized
 };
-#endif
+#  endif
 
-#if SANITIZER_APPLE
+#  if SANITIZER_APPLE || SANITIZER_HAIKU
 struct __sanitizer_msghdr {
   void *msg_name;
   unsigned msg_namelen;
@@ -469,7 +476,7 @@ struct __sanitizer_cmsghdr {
   int cmsg_level;
   int cmsg_type;
 };
-#else
+#  else
 // In POSIX, int msg_iovlen; socklen_t msg_controllen; socklen_t cmsg_len; but
 // many implementations don't conform to the standard.
 struct __sanitizer_msghdr {
@@ -486,22 +493,31 @@ struct __sanitizer_cmsghdr {
   int cmsg_level;
   int cmsg_type;
 };
-#endif
+#  endif
 
-#if SANITIZER_LINUX
+#  if SANITIZER_LINUX
 struct __sanitizer_mmsghdr {
   __sanitizer_msghdr msg_hdr;
   unsigned int msg_len;
 };
-#endif
+#  endif
 
-#if SANITIZER_APPLE
+#  if SANITIZER_APPLE
 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_HAIKU
+struct __sanitizer_dirent {
+  int d_dev;
+  int d_pdev;
+  unsigned long long d_ino;
+  unsigned long long d_pino;
+  unsigned short d_reclen;
+  // more fields that we don't care about
+};
 #  elif (SANITIZER_LINUX && !SANITIZER_GLIBC) || defined(__x86_64__) || \
       defined(__hexagon__)
 struct __sanitizer_dirent {
@@ -527,47 +543,49 @@ struct __sanitizer_dirent64 {
   // more fields that we don't care about
 };
 extern unsigned struct_sock_fprog_sz;
-#endif
+#  endif
 
-#if defined(__x86_64__) && !defined(_LP64)
+#  if SANITIZER_HAIKU
+typedef int __sanitizer_clock_t;
+#  elif defined(__x86_64__) && !defined(_LP64)
 typedef long long __sanitizer_clock_t;
-#else
+#  else
 typedef long __sanitizer_clock_t;
-#endif
+#  endif
 
-#if SANITIZER_LINUX
+#  if SANITIZER_LINUX || SANITIZER_HAIKU
 typedef int __sanitizer_clockid_t;
 typedef unsigned long long __sanitizer_eventfd_t;
-#endif
+#  endif
 
-#if SANITIZER_LINUX
+#  if SANITIZER_LINUX
 #    if defined(_LP64) || defined(__x86_64__) || defined(__powerpc__) || \
         defined(__mips__) || defined(__hexagon__)
 typedef unsigned __sanitizer___kernel_uid_t;
 typedef unsigned __sanitizer___kernel_gid_t;
-#else
+#    else
 typedef unsigned short __sanitizer___kernel_uid_t;
 typedef unsigned short __sanitizer___kernel_gid_t;
-#endif
-#if defined(__x86_64__) && !defined(_LP64)
+#    endif
+#    if defined(__x86_64__) && !defined(_LP64)
 typedef long long __sanitizer___kernel_off_t;
-#else
+#    else
 typedef long __sanitizer___kernel_off_t;
-#endif
+#    endif
 
-#if defined(__powerpc__) || defined(__mips__)
+#    if defined(__powerpc__) || defined(__mips__)
 typedef unsigned int __sanitizer___kernel_old_uid_t;
 typedef unsigned int __sanitizer___kernel_old_gid_t;
-#else
+#    else
 typedef unsigned short __sanitizer___kernel_old_uid_t;
 typedef unsigned short __sanitizer___kernel_old_gid_t;
-#endif
+#    endif
 
 typedef long long __sanitizer___kernel_loff_t;
 typedef struct {
   unsigned long fds_bits[1024 / (8 * sizeof(long))];
 } __sanitizer___kernel_fd_set;
-#endif
+#  endif
 
 // This thing depends on the platform. We are only interested in the upper
 // limit. Verified with a compiler assert in .cpp.
@@ -576,50 +594,52 @@ union __sanitizer_pthread_attr_t {
   void *align;
 };
 
-#if SANITIZER_ANDROID
-# if SANITIZER_MIPS
+#  if SANITIZER_ANDROID
+#    if SANITIZER_MIPS
 typedef unsigned long __sanitizer_sigset_t[16 / sizeof(unsigned long)];
-# else
+#    else
 typedef unsigned long __sanitizer_sigset_t;
-# endif
-#elif SANITIZER_APPLE
+#    endif
+#  elif SANITIZER_APPLE
 typedef unsigned __sanitizer_sigset_t;
-#elif SANITIZER_LINUX
+#  elif SANITIZER_HAIKU
+typedef unsigned long __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)];
 };
-#endif
+#  endif
 
 struct __sanitizer_siginfo_pad {
-#if SANITIZER_X32
+#  if SANITIZER_X32
   // x32 siginfo_t is aligned to 8 bytes.
   u64 pad[128 / sizeof(u64)];
-#else
+#  else
   // Require uptr, because siginfo_t is always pointer-size aligned on Linux.
   uptr pad[128 / sizeof(uptr)];
-#endif
+#  endif
 };
 
-#if SANITIZER_LINUX
-# define SANITIZER_HAS_SIGINFO 1
+#  if SANITIZER_LINUX
+#    define SANITIZER_HAS_SIGINFO 1
 union __sanitizer_siginfo {
   __extension__ struct {
     int si_signo;
-# if SANITIZER_MIPS
+#    if SANITIZER_MIPS
     int si_code;
     int si_errno;
-# else
+#    else
     int si_errno;
     int si_code;
-# endif
+#    endif
   };
   __sanitizer_siginfo_pad pad;
 };
-#else
-# define SANITIZER_HAS_SIGINFO 0
+#  else
+#    define SANITIZER_HAS_SIGINFO 0
 typedef __sanitizer_siginfo_pad __sanitizer_siginfo;
-#endif
+#  endif
 
 using __sanitizer_sighandler_ptr = void (*)(int sig);
 using __sanitizer_sigactionhandler_ptr = void (*)(int sig,
@@ -627,7 +647,7 @@ using __sanitizer_sigactionhandler_ptr = void (*)(int sig,
                                                   void *uctx);
 
 // Linux system headers define the 'sa_handler' and 'sa_sigaction' macros.
-#if SANITIZER_ANDROID && (SANITIZER_WORDSIZE == 64)
+#  if SANITIZER_ANDROID && (SANITIZER_WORDSIZE == 64)
 struct __sanitizer_sigaction {
   unsigned sa_flags;
   union {
@@ -637,7 +657,8 @@ struct __sanitizer_sigaction {
   __sanitizer_sigset_t sa_mask;
   void (*sa_restorer)();
 };
-#elif SANITIZER_ANDROID && SANITIZER_MIPS32  // check this before WORDSIZE == 32
+#  elif SANITIZER_ANDROID && \
+      SANITIZER_MIPS32  // check this before WORDSIZE == 32
 struct __sanitizer_sigaction {
   unsigned sa_flags;
   union {
@@ -646,7 +667,7 @@ struct __sanitizer_sigaction {
   };
   __sanitizer_sigset_t sa_mask;
 };
-#elif SANITIZER_ANDROID && (SANITIZER_WORDSIZE == 32)
+#  elif SANITIZER_ANDROID && (SANITIZER_WORDSIZE == 32)
 struct __sanitizer_sigaction {
   union {
     __sanitizer_sigactionhandler_ptr sigaction;
@@ -656,66 +677,66 @@ struct __sanitizer_sigaction {
   uptr sa_flags;
   void (*sa_restorer)();
 };
-#else // !SANITIZER_ANDROID
+#  else  // !SANITIZER_ANDROID
 struct __sanitizer_sigaction {
-#if defined(__mips__) && !SANITIZER_FREEBSD
+#    if defined(__mips__) && !SANITIZER_FREEBSD && !SANITIZER_MUSL
   unsigned int sa_flags;
-#endif
+#    endif
   union {
     __sanitizer_sigactionhandler_ptr sigaction;
     __sanitizer_sighandler_ptr handler;
   };
-#if SANITIZER_FREEBSD
+#    if SANITIZER_FREEBSD
   int sa_flags;
   __sanitizer_sigset_t sa_mask;
-#else
-#if defined(__s390x__)
+#    else
+#      if defined(__s390x__)
   int sa_resv;
-#else
+#      else
   __sanitizer_sigset_t sa_mask;
-#endif
-#ifndef __mips__
-#if defined(__sparc__)
-#if __GLIBC_PREREQ (2, 20)
+#      endif
+#      if !defined(__mips__) || SANITIZER_MUSL
+#        if defined(__sparc__)
+#          if __GLIBC_PREREQ(2, 20)
   // On sparc glibc 2.19 and earlier sa_flags was unsigned long.
-#if defined(__arch64__)
+#            if defined(__arch64__)
   // To maintain ABI compatibility on sparc64 when switching to an int,
   // __glibc_reserved0 was added.
   int __glibc_reserved0;
-#endif
+#            endif
   int sa_flags;
-#else
+#          else
   unsigned long sa_flags;
-#endif
-#else
+#          endif
+#        else
   int sa_flags;
-#endif
-#endif
-#endif
-#if SANITIZER_LINUX
+#        endif
+#      endif
+#    endif
+#    if SANITIZER_LINUX || SANITIZER_HAIKU
   void (*sa_restorer)();
-#endif
-#if defined(__mips__) && (SANITIZER_WORDSIZE == 32)
+#    endif
+#    if defined(__mips__) && (SANITIZER_WORDSIZE == 32) && !SANITIZER_MUSL
   int sa_resv[1];
-#endif
-#if defined(__s390x__)
+#    endif
+#    if defined(__s390x__)
   __sanitizer_sigset_t sa_mask;
-#endif
+#    endif
 };
-#endif // !SANITIZER_ANDROID
+#  endif  // !SANITIZER_ANDROID
 
-#if defined(__mips__)
-#define __SANITIZER_KERNEL_NSIG 128
-#else
-#define __SANITIZER_KERNEL_NSIG 64
-#endif
+#  if defined(__mips__)
+#    define __SANITIZER_KERNEL_NSIG 128
+#  else
+#    define __SANITIZER_KERNEL_NSIG 64
+#  endif
 
 struct __sanitizer_kernel_sigset_t {
   uptr sig[__SANITIZER_KERNEL_NSIG / (sizeof(uptr) * 8)];
 };
 
 // Linux system headers define the 'sa_handler' and 'sa_sigaction' macros.
-#if SANITIZER_MIPS
+#  if SANITIZER_MIPS
 struct __sanitizer_kernel_sigaction_t {
   unsigned int sa_flags;
   union {
@@ -725,7 +746,7 @@ struct __sanitizer_kernel_sigaction_t {
   __sanitizer_kernel_sigset_t sa_mask;
   void (*sa_restorer)(void);
 };
-#else
+#  else
 struct __sanitizer_kernel_sigaction_t {
   union {
     void (*handler)(int signo);
@@ -735,22 +756,22 @@ struct __sanitizer_kernel_sigaction_t {
   void (*sa_restorer)(void);
   __sanitizer_kernel_sigset_t sa_mask;
 };
-#endif
+#  endif
 
 extern const uptr sig_ign;
 extern const uptr sig_dfl;
 extern const uptr sig_err;
 extern const uptr sa_siginfo;
 
-#if SANITIZER_LINUX
+#  if SANITIZER_LINUX
 extern int e_tabsz;
-#endif
+#  endif
 
 extern int af_inet;
 extern int af_inet6;
 uptr __sanitizer_in_addr_sz(int af);
 
-#if SANITIZER_LINUX
+#  if SANITIZER_LINUX
 struct __sanitizer_dl_phdr_info {
   uptr dlpi_addr;
   const char *dlpi_name;
@@ -759,7 +780,7 @@ struct __sanitizer_dl_phdr_info {
 };
 
 extern unsigned struct_ElfW_Phdr_sz;
-#endif
+#  endif
 
 struct __sanitizer_protoent {
   char *p_name;
@@ -779,15 +800,15 @@ struct __sanitizer_addrinfo {
   int ai_family;
   int ai_socktype;
   int ai_protocol;
-#if SANITIZER_ANDROID || SANITIZER_APPLE
+#  if SANITIZER_ANDROID || SANITIZER_APPLE || SANITIZER_HAIKU
   unsigned ai_addrlen;
   char *ai_canonname;
   void *ai_addr;
-#else // LINUX
+#  else  // LINUX
   unsigned ai_addrlen;
   void *ai_addr;
   char *ai_canonname;
-#endif
+#  endif
   struct __sanitizer_addrinfo *ai_next;
 };
 
@@ -805,14 +826,14 @@ struct __sanitizer_pollfd {
   short revents;
 };
 
-#if SANITIZER_ANDROID || SANITIZER_APPLE
+#  if SANITIZER_ANDROID || SANITIZER_APPLE
 typedef unsigned __sanitizer_nfds_t;
-#else
+#  else
 typedef unsigned long __sanitizer_nfds_t;
-#endif
+#  endif
 
-#if !SANITIZER_ANDROID
-# if SANITIZER_LINUX
+#  if !SANITIZER_ANDROID
+#    if SANITIZER_LINUX
 struct __sanitizer_glob_t {
   uptr gl_pathc;
   char **gl_pathv;
@@ -825,13 +846,13 @@ struct __sanitizer_glob_t {
   int (*gl_lstat)(const char *, void *);
   int (*gl_stat)(const char *, void *);
 };
-# endif  // SANITIZER_LINUX
+#    endif  // SANITIZER_LINUX
 
-# if SANITIZER_LINUX
+#    if SANITIZER_LINUX
 extern int glob_nomatch;
 extern int glob_altdirfunc;
-# endif
-#endif  // !SANITIZER_ANDROID
+#    endif
+#  endif  // !SANITIZER_ANDROID
 
 extern unsigned path_max;
 
@@ -845,7 +866,7 @@ struct __sanitizer_wordexp_t {
   uptr we_offs;
 };
 
-#if SANITIZER_LINUX && !SANITIZER_ANDROID
+#  if SANITIZER_LINUX && !SANITIZER_ANDROID
 struct __sanitizer_FILE {
   int _flags;
   char *_IO_read_ptr;
@@ -863,11 +884,11 @@ struct __sanitizer_FILE {
   __sanitizer_FILE *_chain;
   int _fileno;
 };
-# define SANITIZER_HAS_STRUCT_FILE 1
-#else
+#    define SANITIZER_HAS_STRUCT_FILE 1
+#  else
 typedef void __sanitizer_FILE;
-# define SANITIZER_HAS_STRUCT_FILE 0
-#endif
+#    define SANITIZER_HAS_STRUCT_FILE 0
+#  endif
 
 #  if SANITIZER_LINUX && !SANITIZER_ANDROID &&                               \
       (defined(__i386) || defined(__x86_64) || defined(__mips64) ||          \
@@ -919,14 +940,14 @@ extern int shmctl_ipc_stat;
 extern int shmctl_ipc_info;
 extern int shmctl_shm_info;
 extern int shmctl_shm_stat;
-#endif
+#  endif
 
-#if !SANITIZER_APPLE && !SANITIZER_FREEBSD
+#  if !SANITIZER_APPLE && !SANITIZER_FREEBSD
 extern unsigned struct_utmp_sz;
-#endif
-#if !SANITIZER_ANDROID
+#  endif
+#  if !SANITIZER_ANDROID
 extern unsigned struct_utmpx_sz;
-#endif
+#  endif
 
 extern int map_fixed;
 
@@ -936,13 +957,13 @@ struct __sanitizer_ifconf {
   union {
     void *ifcu_req;
   } ifc_ifcu;
-#if SANITIZER_APPLE
+#  if SANITIZER_APPLE
 } __attribute__((packed));
-#else
+#  else
 };
-#endif
+#  endif
 
-#if SANITIZER_LINUX && !SANITIZER_ANDROID
+#  if SANITIZER_LINUX && !SANITIZER_ANDROID
 struct __sanitizer__obstack_chunk {
   char *limit;
   struct __sanitizer__obstack_chunk *prev;
@@ -969,57 +990,57 @@ struct __sanitizer_cookie_io_functions_t {
   __sanitizer_cookie_io_seek seek;
   __sanitizer_cookie_io_close close;
 };
-#endif
+#  endif
 
-#define IOC_NRBITS 8
-#define IOC_TYPEBITS 8
-#if defined(__powerpc__) || defined(__powerpc64__) || defined(__mips__) || \
-    defined(__sparc__)
-#define IOC_SIZEBITS 13
-#define IOC_DIRBITS 3
-#define IOC_NONE 1U
-#define IOC_WRITE 4U
-#define IOC_READ 2U
-#else
-#define IOC_SIZEBITS 14
-#define IOC_DIRBITS 2
-#define IOC_NONE 0U
-#define IOC_WRITE 1U
-#define IOC_READ 2U
-#endif
-#define IOC_NRMASK ((1 << IOC_NRBITS) - 1)
-#define IOC_TYPEMASK ((1 << IOC_TYPEBITS) - 1)
-#define IOC_SIZEMASK ((1 << IOC_SIZEBITS) - 1)
-#if defined(IOC_DIRMASK)
-#undef IOC_DIRMASK
-#endif
-#define IOC_DIRMASK ((1 << IOC_DIRBITS) - 1)
-#define IOC_NRSHIFT 0
-#define IOC_TYPESHIFT (IOC_NRSHIFT + IOC_NRBITS)
-#define IOC_SIZESHIFT (IOC_TYPESHIFT + IOC_TYPEBITS)
-#define IOC_DIRSHIFT (IOC_SIZESHIFT + IOC_SIZEBITS)
-#define EVIOC_EV_MAX 0x1f
-#define EVIOC_ABS_MAX 0x3f
-
-#define IOC_DIR(nr) (((nr) >> IOC_DIRSHIFT) & IOC_DIRMASK)
-#define IOC_TYPE(nr) (((nr) >> IOC_TYPESHIFT) & IOC_TYPEMASK)
-#define IOC_NR(nr) (((nr) >> IOC_NRSHIFT) & IOC_NRMASK)
-
-#if defined(__sparc__)
+#  define IOC_NRBITS 8
+#  define IOC_TYPEBITS 8
+#  if defined(__powerpc__) || defined(__powerpc64__) || defined(__mips__) || \
+      defined(__sparc__)
+#    define IOC_SIZEBITS 13
+#    define IOC_DIRBITS 3
+#    define IOC_NONE 1U
+#    define IOC_WRITE 4U
+#    define IOC_READ 2U
+#  else
+#    define IOC_SIZEBITS 14
+#    define IOC_DIRBITS 2
+#    define IOC_NONE 0U
+#    define IOC_WRITE 1U
+#    define IOC_READ 2U
+#  endif
+#  define IOC_NRMASK ((1 << IOC_NRBITS) - 1)
+#  define IOC_TYPEMASK ((1 << IOC_TYPEBITS) - 1)
+#  define IOC_SIZEMASK ((1 << IOC_SIZEBITS) - 1)
+#  if defined(IOC_DIRMASK)
+#    undef IOC_DIRMASK
+#  endif
+#  define IOC_DIRMASK ((1 << IOC_DIRBITS) - 1)
+#  define IOC_NRSHIFT 0
+#  define IOC_TYPESHIFT (IOC_NRSHIFT + IOC_NRBITS)
+#  define IOC_SIZESHIFT (IOC_TYPESHIFT + IOC_TYPEBITS)
+#  define IOC_DIRSHIFT (IOC_SIZESHIFT + IOC_SIZEBITS)
+#  define EVIOC_EV_MAX 0x1f
+#  define EVIOC_ABS_MAX 0x3f
+
+#  define IOC_DIR(nr) (((nr) >> IOC_DIRSHIFT) & IOC_DIRMASK)
+#  define IOC_TYPE(nr) (((nr) >> IOC_TYPESHIFT) & IOC_TYPEMASK)
+#  define IOC_NR(nr) (((nr) >> IOC_NRSHIFT) & IOC_NRMASK)
+
+#  if defined(__sparc__)
 // In sparc the 14 bits SIZE field overlaps with the
 // least significant bit of DIR, so either IOC_READ or
 // IOC_WRITE shall be 1 in order to get a non-zero SIZE.
-#define IOC_SIZE(nr) \
-  ((((((nr) >> 29) & 0x7) & (4U | 2U)) == 0) ? 0 : (((nr) >> 16) & 0x3fff))
-#else
-#define IOC_SIZE(nr) (((nr) >> IOC_SIZESHIFT) & IOC_SIZEMASK)
-#endif
+#    define IOC_SIZE(nr) \
+      ((((((nr) >> 29) & 0x7) & (4U | 2U)) == 0) ? 0 : (((nr) >> 16) & 0x3fff))
+#  else
+#    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;
 
-#if SANITIZER_LINUX
+#  if SANITIZER_LINUX
 extern unsigned struct_arpreq_sz;
 extern unsigned struct_cdrom_msf_sz;
 extern unsigned struct_cdrom_multisession_sz;
@@ -1046,9 +1067,9 @@ extern unsigned struct_mtpos_sz;
 extern unsigned struct_vt_consize_sz;
 extern unsigned struct_vt_sizes_sz;
 extern unsigned struct_vt_stat_sz;
-#endif  // SANITIZER_LINUX
+#  endif  // SANITIZER_LINUX
 
-#if SANITIZER_LINUX
+#  if SANITIZER_LINUX
 extern unsigned struct_copr_buffer_sz;
 extern unsigned struct_copr_debug_buf_sz;
 extern unsigned struct_copr_msg_sz;
@@ -1060,9 +1081,9 @@ 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
+#  endif  // SANITIZER_LINUX
 
-#if SANITIZER_LINUX && !SANITIZER_ANDROID
+#  if SANITIZER_LINUX && !SANITIZER_ANDROID
 extern unsigned struct_ax25_parms_struct_sz;
 extern unsigned struct_input_keymap_entry_sz;
 extern unsigned struct_ipx_config_data_sz;
@@ -1083,15 +1104,15 @@ extern unsigned struct_unimapinit_sz;
 
 extern const unsigned long __sanitizer_bufsiz;
 
-#if SANITIZER_LINUX && !SANITIZER_ANDROID
+#  if SANITIZER_LINUX && !SANITIZER_ANDROID
 extern unsigned struct_audio_buf_info_sz;
 extern unsigned struct_ppp_stats_sz;
-#endif  // (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID
+#  endif  // (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID
 
-#if !SANITIZER_ANDROID && !SANITIZER_APPLE
+#  if !SANITIZER_ANDROID && !SANITIZER_APPLE
 extern unsigned struct_sioc_sg_req_sz;
 extern unsigned struct_sioc_vif_req_sz;
-#endif
+#  endif
 
 extern unsigned fpos_t_sz;
 
@@ -1127,29 +1148,31 @@ extern unsigned IOCTL_SIOCSIFMETRIC;
 extern unsigned IOCTL_SIOCSIFMTU;
 extern unsigned IOCTL_SIOCSIFNETMASK;
 extern unsigned IOCTL_SIOCSPGRP;
+#  if !SANITIZER_HAIKU
 extern unsigned IOCTL_TIOCCONS;
-extern unsigned IOCTL_TIOCEXCL;
 extern unsigned IOCTL_TIOCGETD;
+extern unsigned IOCTL_TIOCNOTTY;
+extern unsigned IOCTL_TIOCPKT;
+extern unsigned IOCTL_TIOCSETD;
+extern unsigned IOCTL_TIOCSTI;
+#  endif
+extern unsigned IOCTL_TIOCEXCL;
 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
+#  if SANITIZER_LINUX && !SANITIZER_ANDROID
 extern unsigned IOCTL_SIOCGETSGCNT;
 extern unsigned IOCTL_SIOCGETVIFCNT;
-#endif
-#if SANITIZER_LINUX
+#  endif
+#  if SANITIZER_LINUX
 extern unsigned IOCTL_EVIOCGABS;
 extern unsigned IOCTL_EVIOCGBIT;
 extern unsigned IOCTL_EVIOCGEFFECTS;
@@ -1415,9 +1438,9 @@ extern unsigned IOCTL_VT_OPENQRY;
 extern unsigned IOCTL_VT_RELDISP;
 extern unsigned IOCTL_VT_SETMODE;
 extern unsigned IOCTL_VT_WAITACTIVE;
-#endif  // SANITIZER_LINUX
+#  endif  // SANITIZER_LINUX
 
-#if SANITIZER_LINUX && !SANITIZER_ANDROID
+#  if SANITIZER_LINUX && !SANITIZER_ANDROID
 extern unsigned IOCTL_EQL_EMANCIPATE;
 extern unsigned IOCTL_EQL_ENSLAVE;
 extern unsigned IOCTL_EQL_GETMASTRCFG;
@@ -1506,35 +1529,44 @@ extern unsigned IOCTL_KDSETMODE;
 extern unsigned IOCTL_KDSKBMODE;
 extern unsigned IOCTL_KIOCSOUND;
 extern unsigned IOCTL_PIO_SCRNMAP;
-#endif
+#  endif
+
+#  if SANITIZER_GLIBC
+struct __sanitizer_servent {
+  char *s_name;
+  char **s_aliases;
+  int s_port;
+  char *s_proto;
+};
+#  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_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) ==         \
-                 offsetof(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) ==         \
-                 offsetof(struct 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
+#  define SIGACTION_SYMNAME sigaction
 
 #  if SANITIZER_LINUX
 typedef void *__sanitizer_timer_t;
 #  endif
 
-#endif  // SANITIZER_LINUX || SANITIZER_APPLE
+#endif  // SANITIZER_LINUX || SANITIZER_APPLE || SANITIZER_HAIKU
 
 #endif
lib/libtsan/sanitizer_common/sanitizer_procmaps.h
@@ -16,7 +16,7 @@
 #include "sanitizer_platform.h"
 
 #if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \
-    SANITIZER_APPLE || SANITIZER_SOLARIS ||  \
+    SANITIZER_APPLE || SANITIZER_SOLARIS || SANITIZER_HAIKU ||  \
     SANITIZER_FUCHSIA
 
 #include "sanitizer_common.h"
lib/libtsan/sanitizer_common/sanitizer_procmaps_haiku.cpp
@@ -0,0 +1,94 @@
+//===-- sanitizer_procmaps_haiku.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
+//
+//===----------------------------------------------------------------------===//
+//
+// Information about the process mappings
+// (Haiku-specific parts).
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+#if SANITIZER_HAIKU
+#  include "sanitizer_common.h"
+#  include "sanitizer_procmaps.h"
+
+#  include <kernel/OS.h>
+
+namespace __sanitizer {
+
+void MemoryMappedSegment::AddAddressRanges(LoadedModule *module) {
+  // data_ should be unused on this platform
+  CHECK(!data_);
+  module->addAddressRange(start, end, IsExecutable(), IsWritable());
+}
+
+MemoryMappingLayout::MemoryMappingLayout(bool) { Reset(); }
+
+void MemoryMappingLayout::Reset() { data_.cookie = 0; }
+
+MemoryMappingLayout::~MemoryMappingLayout() {}
+
+// static
+void MemoryMappingLayout::CacheMemoryMappings() {}
+
+bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) {
+  area_info info;
+  if (get_next_area_info(B_CURRENT_TEAM, &data_.cookie, &info) != B_OK)
+    return false;
+
+  segment->start = (uptr)info.address;
+  segment->end = (uptr)info.address + info.size;
+  segment->offset = 0;
+  segment->protection = 0;
+  if (info.protection & B_READ_AREA)
+    segment->protection |= kProtectionRead;
+  if (info.protection & B_WRITE_AREA)
+    segment->protection |= kProtectionWrite;
+  if (info.protection & B_EXECUTE_AREA)
+    segment->protection |= kProtectionExecute;
+  if (segment->filename) {
+    uptr len = Min((uptr)B_OS_NAME_LENGTH, segment->filename_size - 1);
+    internal_strncpy(segment->filename, info.name, len);
+    segment->filename[len] = 0;
+  }
+  return true;
+}
+
+bool MemoryMappingLayout::Error() const { return false; }
+
+void MemoryMappingLayout::DumpListOfModules(
+    InternalMmapVectorNoCtor<LoadedModule> *modules) {
+  Reset();
+  InternalMmapVector<char> module_name(kMaxPathLength);
+  MemoryMappedSegment segment(module_name.data(), module_name.size());
+  for (uptr i = 0; Next(&segment); i++) {
+    const char *cur_name = segment.filename;
+    if (cur_name[0] == '\0')
+      continue;
+    // Don't subtract 'cur_beg' from the first entry:
+    // * If a binary is compiled w/o -pie, then the first entry in
+    //   process maps is likely the binary itself (all dynamic libs
+    //   are mapped higher in address space). For such a binary,
+    //   instruction offset in binary coincides with the actual
+    //   instruction address in virtual memory (as code section
+    //   is mapped to a fixed memory range).
+    // * If a binary is compiled with -pie, all the modules are
+    //   mapped high at address space (in particular, higher than
+    //   shadow memory of the tool), so the module can't be the
+    //   first entry.
+    uptr base_address = (i ? segment.start : 0) - segment.offset;
+    LoadedModule cur_module;
+    cur_module.set(cur_name, base_address);
+    segment.AddAddressRanges(&cur_module);
+    modules->push_back(cur_module);
+  }
+}
+
+void GetMemoryProfile(fill_profile_f cb, uptr *stats) {}
+
+}  // namespace __sanitizer
+
+#endif
lib/libtsan/sanitizer_common/sanitizer_procmaps_mac.cpp
@@ -334,9 +334,22 @@ static const load_command *NextCommand(const load_command *lc) {
   return (const load_command *)((const char *)lc + lc->cmdsize);
 }
 
-static void FindUUID(const load_command *first_lc, u8 *uuid_output) {
-  for (const load_command *lc = first_lc; lc->cmd != 0; lc = NextCommand(lc)) {
-    if (lc->cmd != LC_UUID) continue;
+#  ifdef MH_MAGIC_64
+static constexpr size_t header_size = sizeof(mach_header_64);
+#  else
+static constexpr size_t header_size = sizeof(mach_header);
+#  endif
+
+static void FindUUID(const load_command *first_lc, const mach_header *hdr,
+                     u8 *uuid_output) {
+  uint32_t curcmd = 0;
+  for (const load_command *lc = first_lc; curcmd < hdr->ncmds;
+       curcmd++, lc = NextCommand(lc)) {
+    CHECK_LT((const char *)lc,
+             (const char *)hdr + header_size + hdr->sizeofcmds);
+
+    if (lc->cmd != LC_UUID)
+      continue;
 
     const uuid_command *uuid_lc = (const uuid_command *)lc;
     const uint8_t *uuid = &uuid_lc->uuid[0];
@@ -345,9 +358,16 @@ static void FindUUID(const load_command *first_lc, u8 *uuid_output) {
   }
 }
 
-static bool IsModuleInstrumented(const load_command *first_lc) {
-  for (const load_command *lc = first_lc; lc->cmd != 0; lc = NextCommand(lc)) {
-    if (lc->cmd != LC_LOAD_DYLIB) continue;
+static bool IsModuleInstrumented(const load_command *first_lc,
+                                 const mach_header *hdr) {
+  uint32_t curcmd = 0;
+  for (const load_command *lc = first_lc; curcmd < hdr->ncmds;
+       curcmd++, lc = NextCommand(lc)) {
+    CHECK_LT((const char *)lc,
+             (const char *)hdr + header_size + hdr->sizeofcmds);
+
+    if (lc->cmd != LC_LOAD_DYLIB)
+      continue;
 
     const dylib_command *dylib_lc = (const dylib_command *)lc;
     uint32_t dylib_name_offset = dylib_lc->dylib.name.offset;
@@ -393,10 +413,10 @@ bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) {
           continue;
         }
       }
-      FindUUID((const load_command *)data_.current_load_cmd_addr,
+      FindUUID((const load_command *)data_.current_load_cmd_addr, hdr,
                data_.current_uuid);
       data_.current_instrumented = IsModuleInstrumented(
-          (const load_command *)data_.current_load_cmd_addr);
+          (const load_command *)data_.current_load_cmd_addr, hdr);
     }
 
     while (data_.current_load_cmd_count > 0) {
lib/libtsan/sanitizer_common/sanitizer_procmaps_solaris.cpp
@@ -9,9 +9,6 @@
 // Information about the process mappings (Solaris-specific parts).
 //===----------------------------------------------------------------------===//
 
-// Before Solaris 11.4, <procfs.h> doesn't work in a largefile environment.
-#undef _FILE_OFFSET_BITS
-
 // Avoid conflict between `_TIME_BITS` defined vs. `_FILE_OFFSET_BITS`
 // undefined in some Linux configurations.
 #undef _TIME_BITS
lib/libtsan/sanitizer_common/sanitizer_redefine_builtins.h
@@ -15,7 +15,7 @@
 #    define SANITIZER_REDEFINE_BUILTINS_H
 
 // The asm hack only works with GCC and Clang.
-#    if !defined(_WIN32)
+#    if !defined(_WIN32) && !defined(_AIX)
 
 asm(R"(
     .set memcpy, __sanitizer_internal_memcpy
lib/libtsan/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp
@@ -38,25 +38,28 @@
 # include <asm/ptrace.h>
 #endif
 #include <sys/user.h>  // for user_regs_struct
-#if SANITIZER_ANDROID && SANITIZER_MIPS
-# include <asm/reg.h>  // for mips SP register in sys/user.h
-#endif
-#include <sys/wait.h> // for signal-related stuff
-
-#ifdef sa_handler
-# undef sa_handler
-#endif
-
-#ifdef sa_sigaction
-# undef sa_sigaction
-#endif
-
-#include "sanitizer_common.h"
-#include "sanitizer_flags.h"
-#include "sanitizer_libc.h"
-#include "sanitizer_linux.h"
-#include "sanitizer_mutex.h"
-#include "sanitizer_placement_new.h"
+#  if SANITIZER_MIPS
+// clang-format off
+# include <asm/sgidefs.h>  // <asm/sgidefs.h> must be included before <asm/reg.h>
+# include <asm/reg.h>      // for mips SP register
+// clang-format on
+#  endif
+#  include <sys/wait.h>  // for signal-related stuff
+
+#  ifdef sa_handler
+#    undef sa_handler
+#  endif
+
+#  ifdef sa_sigaction
+#    undef sa_sigaction
+#  endif
+
+#  include "sanitizer_common.h"
+#  include "sanitizer_flags.h"
+#  include "sanitizer_libc.h"
+#  include "sanitizer_linux.h"
+#  include "sanitizer_mutex.h"
+#  include "sanitizer_placement_new.h"
 
 // Sufficiently old kernel headers don't provide this value, but we can still
 // call prctl with it. If the runtime kernel is new enough, the prctl call will
@@ -511,11 +514,7 @@ typedef pt_regs regs_struct;
 
 #elif defined(__mips__)
 typedef struct user regs_struct;
-# if SANITIZER_ANDROID
-#  define REG_SP regs[EF_R29]
-# else
-#  define REG_SP regs[EF_REG29]
-# endif
+#    define REG_SP regs[EF_R29]
 
 #elif defined(__aarch64__)
 typedef struct user_pt_regs regs_struct;
lib/libtsan/sanitizer_common/sanitizer_stoptheworld_win.cpp
@@ -49,6 +49,8 @@ struct SuspendedThreadsListWindows final : public SuspendedThreadsList {
 #    define SP_REG Esp
 #  elif SANITIZER_ARM | SANITIZER_ARM64
 #    define SP_REG Sp
+#  elif SANITIZER_MIPS32
+#    define SP_REG IntSp
 #  else
 #    error Architecture not supported!
 #  endif
lib/libtsan/sanitizer_common/sanitizer_symbolizer_libcdep.cpp
@@ -31,11 +31,12 @@ Symbolizer *Symbolizer::GetOrInit() {
 
 const char *ExtractToken(const char *str, const char *delims, char **result) {
   uptr prefix_len = internal_strcspn(str, delims);
-  *result = (char*)InternalAlloc(prefix_len + 1);
+  *result = (char *)InternalAlloc(prefix_len + 1);
   internal_memcpy(*result, str, prefix_len);
   (*result)[prefix_len] = '\0';
   const char *prefix_end = str + prefix_len;
-  if (*prefix_end != '\0') prefix_end++;
+  if (*prefix_end != '\0')
+    prefix_end++;
   return prefix_end;
 }
 
@@ -78,7 +79,8 @@ const char *ExtractTokenUpToDelimiter(const char *str, const char *delimiter,
   internal_memcpy(*result, str, prefix_len);
   (*result)[prefix_len] = '\0';
   const char *prefix_end = str + prefix_len;
-  if (*prefix_end != '\0') prefix_end += internal_strlen(delimiter);
+  if (*prefix_end != '\0')
+    prefix_end += internal_strlen(delimiter);
   return prefix_end;
 }
 
@@ -215,18 +217,20 @@ const LoadedModule *Symbolizer::FindModuleForAddress(uptr address) {
     modules_were_reloaded = true;
   }
   const LoadedModule *module = SearchForModule(modules_, address);
-  if (module) return module;
+  if (module)
+    return module;
 
   // dlopen/dlclose interceptors invalidate the module list, but when
   // interception is disabled, we need to retry if the lookup fails in
   // case the module list changed.
-#if !SANITIZER_INTERCEPT_DLOPEN_DLCLOSE
+#  if !SANITIZER_INTERCEPT_DLOPEN_DLCLOSE
   if (!modules_were_reloaded) {
     RefreshModules();
     module = SearchForModule(modules_, address);
-    if (module) return module;
+    if (module)
+      return module;
   }
-#endif
+#  endif
 
   if (fallback_modules_.size()) {
     module = SearchForModule(fallback_modules_, address);
@@ -260,31 +264,31 @@ class LLVMSymbolizerProcess final : public SymbolizerProcess {
   // script/asan_symbolize.py and sanitizer_common.h.
   void GetArgV(const char *path_to_binary,
                const char *(&argv)[kArgVMax]) const override {
-#if defined(__x86_64h__)
-    const char* const kSymbolizerArch = "--default-arch=x86_64h";
-#elif defined(__x86_64__)
-    const char* const kSymbolizerArch = "--default-arch=x86_64";
-#elif defined(__i386__)
-    const char* const kSymbolizerArch = "--default-arch=i386";
-#elif SANITIZER_LOONGARCH64
+#  if defined(__x86_64h__)
+    const char *const kSymbolizerArch = "--default-arch=x86_64h";
+#  elif defined(__x86_64__)
+    const char *const kSymbolizerArch = "--default-arch=x86_64";
+#  elif defined(__i386__)
+    const char *const kSymbolizerArch = "--default-arch=i386";
+#  elif SANITIZER_LOONGARCH64
     const char *const kSymbolizerArch = "--default-arch=loongarch64";
-#elif SANITIZER_RISCV64
+#  elif SANITIZER_RISCV64
     const char *const kSymbolizerArch = "--default-arch=riscv64";
-#elif defined(__aarch64__)
-    const char* const kSymbolizerArch = "--default-arch=arm64";
-#elif defined(__arm__)
-    const char* const kSymbolizerArch = "--default-arch=arm";
-#elif defined(__powerpc64__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
-    const char* const kSymbolizerArch = "--default-arch=powerpc64";
-#elif defined(__powerpc64__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
-    const char* const kSymbolizerArch = "--default-arch=powerpc64le";
-#elif defined(__s390x__)
-    const char* const kSymbolizerArch = "--default-arch=s390x";
-#elif defined(__s390__)
-    const char* const kSymbolizerArch = "--default-arch=s390";
-#else
-    const char* const kSymbolizerArch = "--default-arch=unknown";
-#endif
+#  elif defined(__aarch64__)
+    const char *const kSymbolizerArch = "--default-arch=arm64";
+#  elif defined(__arm__)
+    const char *const kSymbolizerArch = "--default-arch=arm";
+#  elif defined(__powerpc64__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+    const char *const kSymbolizerArch = "--default-arch=powerpc64";
+#  elif defined(__powerpc64__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+    const char *const kSymbolizerArch = "--default-arch=powerpc64le";
+#  elif defined(__s390x__)
+    const char *const kSymbolizerArch = "--default-arch=s390x";
+#  elif defined(__s390__)
+    const char *const kSymbolizerArch = "--default-arch=s390";
+#  else
+    const char *const kSymbolizerArch = "--default-arch=unknown";
+#  endif
 
     const char *const demangle_flag =
         common_flags()->demangle ? "--demangle" : "--no-demangle";
@@ -315,7 +319,8 @@ static const char *ParseFileLineInfo(AddressInfo *info, const char *str) {
     char *back = file_line_info + size - 1;
     for (int i = 0; i < 2; ++i) {
       while (back > file_line_info && IsDigit(*back)) --back;
-      if (*back != ':' || !IsDigit(back[1])) break;
+      if (*back != ':' || !IsDigit(back[1]))
+        break;
       info->column = info->line;
       info->line = internal_atoll(back + 1);
       // Truncate the string at the colon to keep only filename.
@@ -436,7 +441,7 @@ bool LLVMSymbolizer::SymbolizeData(uptr addr, DataInfo *info) {
   if (!buf)
     return false;
   ParseSymbolizeDataOutput(buf, info);
-  info->start += (addr - info->module_offset); // Add the base address.
+  info->start += (addr - info->module_offset);  // Add the base address.
   return true;
 }
 
@@ -459,10 +464,9 @@ const char *LLVMSymbolizer::FormatAndSendCommand(const char *command_prefix,
     size_needed = internal_snprintf(buffer_, kBufferSize, "%s \"%s\" 0x%zx\n",
                                     command_prefix, module_name, module_offset);
   else
-    size_needed = internal_snprintf(buffer_, kBufferSize,
-                                    "%s \"%s:%s\" 0x%zx\n", command_prefix,
-                                    module_name, ModuleArchToString(arch),
-                                    module_offset);
+    size_needed = internal_snprintf(
+        buffer_, kBufferSize, "%s \"%s:%s\" 0x%zx\n", command_prefix,
+        module_name, ModuleArchToString(arch), module_offset);
 
   if (size_needed >= static_cast<int>(kBufferSize)) {
     Report("WARNING: Command buffer too small");
@@ -484,9 +488,9 @@ SymbolizerProcess::SymbolizerProcess(const char *path, bool use_posix_spawn)
   CHECK_NE(path_[0], '\0');
 }
 
-static bool IsSameModule(const char* path) {
-  if (const char* ProcessName = GetProcessName()) {
-    if (const char* SymbolizerName = StripModuleName(path)) {
+static bool IsSameModule(const char *path) {
+  if (const char *ProcessName = GetProcessName()) {
+    if (const char *SymbolizerName = StripModuleName(path)) {
       return !internal_strcmp(ProcessName, SymbolizerName);
     }
   }
@@ -516,9 +520,9 @@ const char *SymbolizerProcess::SendCommand(const char *command) {
 
 const char *SymbolizerProcess::SendCommandImpl(const char *command) {
   if (input_fd_ == kInvalidFd || output_fd_ == kInvalidFd)
-      return nullptr;
+    return nullptr;
   if (!WriteToSymbolizer(command, internal_strlen(command)))
-      return nullptr;
+    return nullptr;
   if (!ReadFromSymbolizer())
     return nullptr;
   return buffer_.data();
lib/libtsan/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp
@@ -38,9 +38,10 @@
 // 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.
 namespace __cxxabiv1 {
-  extern "C" SANITIZER_WEAK_ATTRIBUTE
-  char *__cxa_demangle(const char *mangled, char *buffer,
-                                  size_t *length, int *status);
+extern "C" SANITIZER_WEAK_ATTRIBUTE char *__cxa_demangle(const char *mangled,
+                                                         char *buffer,
+                                                         size_t *length,
+                                                         int *status);
 }
 
 namespace __sanitizer {
@@ -53,8 +54,7 @@ const char *DemangleCXXABI(const char *name) {
   // it does not allocate). For now, we just call it anyway, and we leak
   // the returned value.
   if (&__cxxabiv1::__cxa_demangle)
-    if (const char *demangled_name =
-          __cxxabiv1::__cxa_demangle(name, 0, 0, 0))
+    if (const char *demangled_name = __cxxabiv1::__cxa_demangle(name, 0, 0, 0))
       return demangled_name;
 
   return nullptr;
@@ -85,7 +85,8 @@ const char *DemangleSwift(const char *name) {
 }
 
 const char *DemangleSwiftAndCXX(const char *name) {
-  if (!name) return nullptr;
+  if (!name)
+    return nullptr;
   if (const char *swift_demangled_name = DemangleSwift(name))
     return swift_demangled_name;
   return DemangleCXXABI(name);
@@ -114,7 +115,8 @@ static bool CreateTwoHighNumberedPipes(int *infd_, int *outfd_) {
       } else {
         outfd = sock_pair[i];
         for (int j = 0; j < i; j++) {
-          if (sock_pair[j] == infd) continue;
+          if (sock_pair[j] == infd)
+            continue;
           internal_close(sock_pair[j][0]);
           internal_close(sock_pair[j][1]);
         }
@@ -155,7 +157,7 @@ bool SymbolizerProcess::StartSymbolizerSubprocess() {
   }
 
   if (use_posix_spawn_) {
-#if SANITIZER_APPLE
+#  if SANITIZER_APPLE
     fd_t fd = internal_spawn(argv, const_cast<const char **>(GetEnvP()), &pid);
     if (fd == kInvalidFd) {
       Report("WARNING: failed to spawn external symbolizer (errno: %d)\n",
@@ -165,14 +167,16 @@ bool SymbolizerProcess::StartSymbolizerSubprocess() {
 
     input_fd_ = fd;
     output_fd_ = fd;
-#else  // SANITIZER_APPLE
+#  else   // SANITIZER_APPLE
     UNIMPLEMENTED();
-#endif  // SANITIZER_APPLE
+#  endif  // SANITIZER_APPLE
   } else {
     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);
+      Report(
+          "WARNING: Can't create a socket pair to start "
+          "external symbolizer (errno: %d)\n",
+          errno);
       return false;
     }
 
@@ -260,10 +264,11 @@ bool Addr2LineProcess::ReachedEndOfOutput(const char *buffer,
   // 1. First one, corresponding to given offset to be symbolized
   // (may be equal to output_terminator_, if offset is not valid).
   // 2. Second one for output_terminator_, itself to mark the end of output.
-  if (length <= kTerminatorLen) return false;
+  if (length <= kTerminatorLen)
+    return false;
   // Addr2Line output should end up with output_terminator_.
-  return !internal_memcmp(buffer + length - kTerminatorLen,
-                          output_terminator_, kTerminatorLen);
+  return !internal_memcmp(buffer + length - kTerminatorLen, output_terminator_,
+                          kTerminatorLen);
 }
 
 class Addr2LinePool final : public SymbolizerTool {
@@ -283,9 +288,7 @@ class Addr2LinePool final : public SymbolizerTool {
     return false;
   }
 
-  bool SymbolizeData(uptr addr, DataInfo *info) override {
-    return false;
-  }
+  bool SymbolizeData(uptr addr, DataInfo *info) override { return false; }
 
  private:
   const char *SendCommand(const char *module_name, uptr module_offset) {
@@ -299,22 +302,21 @@ class Addr2LinePool final : public SymbolizerTool {
     }
     if (!addr2line) {
       addr2line =
-          new(*allocator_) Addr2LineProcess(addr2line_path_, module_name);
+          new (*allocator_) Addr2LineProcess(addr2line_path_, module_name);
       addr2line_pool_.push_back(addr2line);
     }
     CHECK_EQ(0, internal_strcmp(module_name, addr2line->module_name()));
     char buffer[kBufferSize];
-    internal_snprintf(buffer, kBufferSize, "0x%zx\n0x%zx\n",
-                      module_offset, dummy_address_);
+    internal_snprintf(buffer, kBufferSize, "0x%zx\n0x%zx\n", module_offset,
+                      dummy_address_);
     return addr2line->SendCommand(buffer);
   }
 
   static const uptr kBufferSize = 64;
   const char *addr2line_path_;
   LowLevelAllocator *allocator_;
-  InternalMmapVector<Addr2LineProcess*> addr2line_pool_;
-  static const uptr dummy_address_ =
-      FIRST_32_SECOND_64(UINT32_MAX, UINT64_MAX);
+  InternalMmapVector<Addr2LineProcess *> addr2line_pool_;
+  static const uptr dummy_address_ = FIRST_32_SECOND_64(UINT32_MAX, UINT64_MAX);
 };
 
 #  if SANITIZER_SUPPORTS_WEAK_HOOKS
@@ -352,8 +354,9 @@ class InternalSymbolizer final : public SymbolizerTool {
   }
 
   bool SymbolizePC(uptr addr, SymbolizedStack *stack) override {
-    bool result = __sanitizer_symbolize_code(
-        stack->info.module, stack->info.module_offset, buffer_, sizeof(buffer_));
+    bool result = __sanitizer_symbolize_code(stack->info.module,
+                                             stack->info.module_offset, buffer_,
+                                             sizeof(buffer_));
     if (result)
       ParseSymbolizePCOutput(buffer_, stack);
     return result;
@@ -423,44 +426,53 @@ static SymbolizerTool *ChooseExternalSymbolizer(LowLevelAllocator *allocator) {
   } else if (!internal_strncmp(binary_name, kLLVMSymbolizerPrefix,
                                internal_strlen(kLLVMSymbolizerPrefix))) {
     VReport(2, "Using llvm-symbolizer at user-specified path: %s\n", path);
-    return new(*allocator) LLVMSymbolizer(path, allocator);
+    return new (*allocator) LLVMSymbolizer(path, allocator);
   } else if (!internal_strcmp(binary_name, "atos")) {
-#if SANITIZER_APPLE
+#  if SANITIZER_APPLE
     VReport(2, "Using atos at user-specified path: %s\n", path);
-    return new(*allocator) AtosSymbolizer(path, allocator);
-#else  // SANITIZER_APPLE
+    return new (*allocator) AtosSymbolizer(path, allocator);
+#  else   // SANITIZER_APPLE
     Report("ERROR: Using `atos` is only supported on Darwin.\n");
     Die();
-#endif  // SANITIZER_APPLE
+#  endif  // SANITIZER_APPLE
   } else if (!internal_strcmp(binary_name, "addr2line")) {
     VReport(2, "Using addr2line at user-specified path: %s\n", path);
-    return new(*allocator) Addr2LinePool(path, allocator);
+    return new (*allocator) Addr2LinePool(path, allocator);
   } else if (path) {
-    Report("ERROR: External symbolizer path is set to '%s' which isn't "
-           "a known symbolizer. Please set the path to the llvm-symbolizer "
-           "binary or other known tool.\n", path);
+    Report(
+        "ERROR: External symbolizer path is set to '%s' which isn't "
+        "a known symbolizer. Please set the path to the llvm-symbolizer "
+        "binary or other known tool.\n",
+        path);
     Die();
   }
 
   // Otherwise symbolizer program is unknown, let's search $PATH
+#  ifdef SANITIZER_DISABLE_SYMBOLIZER_PATH_SEARCH
+  VReport(2,
+          "Symbolizer path search is disabled in the runtime "
+          "build configuration.\n");
+  return nullptr;
+#  else
   CHECK(path == nullptr);
-#if SANITIZER_APPLE
+#    if SANITIZER_APPLE
   if (const char *found_path = FindPathToBinary("atos")) {
     VReport(2, "Using atos found at: %s\n", found_path);
-    return new(*allocator) AtosSymbolizer(found_path, allocator);
+    return new (*allocator) AtosSymbolizer(found_path, allocator);
   }
-#endif  // SANITIZER_APPLE
+#    endif  // SANITIZER_APPLE
   if (const char *found_path = FindPathToBinary("llvm-symbolizer")) {
     VReport(2, "Using llvm-symbolizer found at: %s\n", found_path);
-    return new(*allocator) LLVMSymbolizer(found_path, allocator);
+    return new (*allocator) LLVMSymbolizer(found_path, allocator);
   }
   if (common_flags()->allow_addr2line) {
     if (const char *found_path = FindPathToBinary("addr2line")) {
       VReport(2, "Using addr2line found at: %s\n", found_path);
-      return new(*allocator) Addr2LinePool(found_path, allocator);
+      return new (*allocator) Addr2LinePool(found_path, allocator);
     }
   }
   return nullptr;
+#  endif    // SANITIZER_DISABLE_SYMBOLIZER_PATH_SEARCH
 }
 
 static void ChooseSymbolizerTools(IntrusiveList<SymbolizerTool> *list,
@@ -492,17 +504,17 @@ static void ChooseSymbolizerTools(IntrusiveList<SymbolizerTool> *list,
     list->push_back(tool);
   }
 
-#if SANITIZER_APPLE
+#  if SANITIZER_APPLE
   VReport(2, "Using dladdr symbolizer.\n");
-  list->push_back(new(*allocator) DlAddrSymbolizer());
-#endif  // SANITIZER_APPLE
+  list->push_back(new (*allocator) DlAddrSymbolizer());
+#  endif  // SANITIZER_APPLE
 }
 
 Symbolizer *Symbolizer::PlatformInit() {
   IntrusiveList<SymbolizerTool> list;
   list.clear();
   ChooseSymbolizerTools(&list, &symbolizer_allocator_);
-  return new(symbolizer_allocator_) Symbolizer(list);
+  return new (symbolizer_allocator_) Symbolizer(list);
 }
 
 void Symbolizer::LateInitialize() {
lib/libtsan/sanitizer_common/sanitizer_unwind_linux_libcdep.cpp
@@ -12,7 +12,7 @@
 
 #include "sanitizer_platform.h"
 #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
-    SANITIZER_SOLARIS
+    SANITIZER_SOLARIS || SANITIZER_HAIKU
 #include "sanitizer_common.h"
 #include "sanitizer_stacktrace.h"
 
@@ -91,38 +91,6 @@ _Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, void *param) {
 
 }  // 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;
@@ -171,4 +139,4 @@ void BufferedStackTrace::UnwindSlow(uptr pc, void *context, u32 max_depth) {
 }  // namespace __sanitizer
 
 #endif  // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD ||
-        // SANITIZER_SOLARIS
+        // SANITIZER_SOLARIS || SANITIZER_HAIKU
lib/libtsan/sanitizer_common/sanitizer_unwind_win.cpp
@@ -75,6 +75,11 @@ void BufferedStackTrace::UnwindSlow(uptr pc, void *context, u32 max_depth) {
   stack_frame.AddrPC.Offset = ctx.Pc;
   stack_frame.AddrFrame.Offset = ctx.R11;
   stack_frame.AddrStack.Offset = ctx.Sp;
+#      elif SANITIZER_MIPS32
+  int machine_type = IMAGE_FILE_MACHINE_R4000;
+  stack_frame.AddrPC.Offset = ctx.Fir;
+  stack_frame.AddrFrame.Offset = ctx.IntS8;
+  stack_frame.AddrStack.Offset = ctx.IntSp;
 #      else
   int machine_type = IMAGE_FILE_MACHINE_I386;
   stack_frame.AddrPC.Offset = ctx.Eip;
lib/libtsan/sanitizer_common/sanitizer_win.cpp
@@ -1011,6 +1011,9 @@ void SignalContext::InitPcSpBp() {
 #    if SANITIZER_ARM
   bp = (uptr)context_record->R11;
   sp = (uptr)context_record->Sp;
+#    elif SANITIZER_MIPS32
+  bp = (uptr)context_record->IntS8;
+  sp = (uptr)context_record->IntSp;
 #    else
   bp = (uptr)context_record->Ebp;
   sp = (uptr)context_record->Esp;
lib/libtsan/ubsan/ubsan_platform.h
@@ -16,7 +16,7 @@
 #if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) ||        \
     defined(__NetBSD__) || defined(__DragonFly__) ||                           \
     (defined(__sun__) && defined(__svr4__)) || defined(_WIN32) ||              \
-    defined(__Fuchsia__)
+    defined(__Fuchsia__) || defined(__HAIKU__)
 #define CAN_SANITIZE_UB 1
 #else
 # define CAN_SANITIZE_UB 0
lib/libtsan/tsan_interceptors_posix.cpp
@@ -12,6 +12,9 @@
 // sanitizer_common/sanitizer_common_interceptors.inc
 //===----------------------------------------------------------------------===//
 
+#include <stdarg.h>
+
+#include "interception/interception.h"
 #include "sanitizer_common/sanitizer_allocator_dlsym.h"
 #include "sanitizer_common/sanitizer_atomic.h"
 #include "sanitizer_common/sanitizer_errno.h"
@@ -19,21 +22,20 @@
 #include "sanitizer_common/sanitizer_internal_defs.h"
 #include "sanitizer_common/sanitizer_libc.h"
 #include "sanitizer_common/sanitizer_linux.h"
+#include "sanitizer_common/sanitizer_platform_interceptors.h"
 #include "sanitizer_common/sanitizer_platform_limits_netbsd.h"
 #include "sanitizer_common/sanitizer_platform_limits_posix.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 "sanitizer_common/sanitizer_vector.h"
+#include "tsan_fd.h"
 #include "tsan_interceptors.h"
 #include "tsan_interface.h"
+#include "tsan_mman.h"
 #include "tsan_platform.h"
-#include "tsan_suppressions.h"
 #include "tsan_rtl.h"
-#include "tsan_mman.h"
-#include "tsan_fd.h"
-
-#include <stdarg.h>
+#include "tsan_suppressions.h"
 
 using namespace __tsan;
 
@@ -177,7 +179,7 @@ struct ThreadSignalContext {
   SignalDesc pending_signals[kSigCount];
   // emptyset and oldset are too big for stack.
   __sanitizer_sigset_t emptyset;
-  __sanitizer_sigset_t oldset;
+  __sanitizer::Vector<__sanitizer_sigset_t> oldset;
 };
 
 void EnterBlockingFunc(ThreadState *thr) {
@@ -558,6 +560,7 @@ static void SetJmp(ThreadState *thr, uptr sp) {
   buf->shadow_stack_pos = thr->shadow_stack_pos;
   ThreadSignalContext *sctx = SigCtx(thr);
   buf->int_signal_send = sctx ? sctx->int_signal_send : 0;
+  buf->oldset_stack_size = sctx ? sctx->oldset.Size() : 0;
   buf->in_blocking_func = atomic_load(&thr->in_blocking_func, memory_order_relaxed);
   buf->in_signal_handler = atomic_load(&thr->in_signal_handler,
       memory_order_relaxed);
@@ -574,8 +577,11 @@ static void LongJmp(ThreadState *thr, uptr *env) {
       while (thr->shadow_stack_pos > buf->shadow_stack_pos)
         FuncExit(thr);
       ThreadSignalContext *sctx = SigCtx(thr);
-      if (sctx)
+      if (sctx) {
         sctx->int_signal_send = buf->int_signal_send;
+        while (sctx->oldset.Size() > buf->oldset_stack_size)
+          sctx->oldset.PopBack();
+      }
       atomic_store(&thr->in_blocking_func, buf->in_blocking_func,
           memory_order_relaxed);
       atomic_store(&thr->in_signal_handler, buf->in_signal_handler,
@@ -742,6 +748,41 @@ TSAN_INTERCEPTOR(void, free, void *p) {
   user_free(thr, pc, p);
 }
 
+#  if SANITIZER_INTERCEPT_FREE_SIZED
+TSAN_INTERCEPTOR(void, free_sized, void *p, uptr size) {
+  if (UNLIKELY(!p))
+    return;
+  if (in_symbolizer())
+    return InternalFree(p);
+  if (DlsymAlloc::PointerIsMine(p))
+    return DlsymAlloc::Free(p);
+  invoke_free_hook(p);
+  SCOPED_INTERCEPTOR_RAW(free_sized, p, size);
+  user_free(thr, pc, p);
+}
+#    define TSAN_MAYBE_INTERCEPT_FREE_SIZED INTERCEPT_FUNCTION(free_sized)
+#  else
+#    define TSAN_MAYBE_INTERCEPT_FREE_SIZED
+#  endif
+
+#  if SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED
+TSAN_INTERCEPTOR(void, free_aligned_sized, void *p, uptr alignment, uptr size) {
+  if (UNLIKELY(!p))
+    return;
+  if (in_symbolizer())
+    return InternalFree(p);
+  if (DlsymAlloc::PointerIsMine(p))
+    return DlsymAlloc::Free(p);
+  invoke_free_hook(p);
+  SCOPED_INTERCEPTOR_RAW(free_aligned_sized, p, alignment, size);
+  user_free(thr, pc, p);
+}
+#    define TSAN_MAYBE_INTERCEPT_FREE_ALIGNED_SIZED \
+      INTERCEPT_FUNCTION(free_aligned_sized)
+#  else
+#    define TSAN_MAYBE_INTERCEPT_FREE_ALIGNED_SIZED
+#  endif
+
 TSAN_INTERCEPTOR(void, cfree, void *p) {
   if (UNLIKELY(!p))
     return;
@@ -758,6 +799,9 @@ TSAN_INTERCEPTOR(uptr, malloc_usable_size, void *p) {
   SCOPED_INTERCEPTOR_RAW(malloc_usable_size, p);
   return user_alloc_usable_size(p);
 }
+#else
+#  define TSAN_MAYBE_INTERCEPT_FREE_SIZED
+#  define TSAN_MAYBE_INTERCEPT_FREE_ALIGNED_SIZED
 #endif
 
 TSAN_INTERCEPTOR(char *, strcpy, char *dst, const char *src) {
@@ -892,10 +936,9 @@ constexpr u32 kGuardWaiter = 1 << 17;
 
 static int guard_acquire(ThreadState *thr, uptr pc, atomic_uint32_t *g,
                          bool blocking_hooks = true) {
-  if (blocking_hooks)
-    OnPotentiallyBlockingRegionBegin();
-  auto on_exit = at_scope_exit([blocking_hooks] {
-    if (blocking_hooks)
+  bool in_potentially_blocking_region = false;
+  auto on_exit = at_scope_exit([&] {
+    if (in_potentially_blocking_region)
       OnPotentiallyBlockingRegionEnd();
   });
 
@@ -912,8 +955,13 @@ static int guard_acquire(ThreadState *thr, uptr pc, atomic_uint32_t *g,
     } else {
       if ((cmp & kGuardWaiter) ||
           atomic_compare_exchange_strong(g, &cmp, cmp | kGuardWaiter,
-                                         memory_order_relaxed))
+                                         memory_order_relaxed)) {
+        if (blocking_hooks && !in_potentially_blocking_region) {
+          in_potentially_blocking_region = true;
+          OnPotentiallyBlockingRegionBegin();
+        }
         FutexWait(g, cmp | kGuardWaiter);
+      }
     }
   }
 }
@@ -976,6 +1024,7 @@ void PlatformCleanUpThreadState(ThreadState *thr) {
       &thr->signal_ctx, memory_order_relaxed);
   if (sctx) {
     atomic_store(&thr->signal_ctx, 0, memory_order_relaxed);
+    sctx->oldset.Reset();
     UnmapOrDie(sctx, sizeof(*sctx));
   }
 }
@@ -2172,7 +2221,8 @@ void ProcessPendingSignalsImpl(ThreadState *thr) {
     return;
   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);
+  __sanitizer_sigset_t *oldset = sctx->oldset.PushBack();
+  int res = REAL(pthread_sigmask)(SIG_SETMASK, &sctx->emptyset, oldset);
   CHECK_EQ(res, 0);
   for (int sig = 0; sig < kSigCount; sig++) {
     SignalDesc *signal = &sctx->pending_signals[sig];
@@ -2182,8 +2232,9 @@ void ProcessPendingSignalsImpl(ThreadState *thr) {
                             &signal->ctx);
     }
   }
-  res = REAL(pthread_sigmask)(SIG_SETMASK, &sctx->oldset, 0);
+  res = REAL(pthread_sigmask)(SIG_SETMASK, oldset, 0);
   CHECK_EQ(res, 0);
+  sctx->oldset.PopBack();
   atomic_fetch_add(&thr->in_signal_handler, -1, memory_order_relaxed);
 }
 
@@ -2951,6 +3002,8 @@ void InitializeInterceptors() {
   TSAN_INTERCEPT(realloc);
   TSAN_INTERCEPT(reallocarray);
   TSAN_INTERCEPT(free);
+  TSAN_MAYBE_INTERCEPT_FREE_SIZED;
+  TSAN_MAYBE_INTERCEPT_FREE_ALIGNED_SIZED;
   TSAN_INTERCEPT(cfree);
   TSAN_INTERCEPT(munmap);
   TSAN_MAYBE_INTERCEPT_MEMALIGN;
@@ -3073,6 +3126,10 @@ void InitializeInterceptors() {
 #if !SANITIZER_ANDROID
   TSAN_INTERCEPT(dl_iterate_phdr);
 #endif
+
+  // Symbolization indirectly calls dl_iterate_phdr
+  ready_to_symbolize = true;
+
   TSAN_MAYBE_INTERCEPT_ON_EXIT;
   TSAN_INTERCEPT(__cxa_atexit);
   TSAN_INTERCEPT(_exit);
lib/libtsan/tsan_interface_java.cpp
@@ -122,7 +122,6 @@ void __tsan_java_move(jptr src, jptr dst, jptr size) {
   DCHECK_GE(dst, jctx->heap_begin);
   DCHECK_LE(dst + size, jctx->heap_begin + jctx->heap_size);
   DCHECK_NE(dst, src);
-  DCHECK_NE(size, 0);
 
   // Assuming it's not running concurrently with threads that do
   // memory accesses and mutex operations (stop-the-world phase).
lib/libtsan/tsan_malloc_mac.cpp
@@ -73,15 +73,19 @@ using namespace __tsan;
   invoke_free_hook(ptr);                                     \
   SCOPED_INTERCEPTOR_RAW(free, ptr);                         \
   user_free(thr, pc, ptr)
-#define COMMON_MALLOC_SIZE(ptr) uptr size = user_alloc_usable_size(ptr);
-#define COMMON_MALLOC_FILL_STATS(zone, stats)
-#define COMMON_MALLOC_REPORT_UNKNOWN_REALLOC(ptr, zone_ptr, zone_name) \
-  (void)zone_name; \
-  Report("mz_realloc(%p) -- attempting to realloc unallocated memory.\n", ptr);
-#define COMMON_MALLOC_NAMESPACE __tsan
-#define COMMON_MALLOC_HAS_ZONE_ENUMERATOR 0
-#define COMMON_MALLOC_HAS_EXTRA_INTROSPECTION_INIT 0
+#  define COMMON_MALLOC_FREE_SIZED(ptr, size) COMMON_MALLOC_FREE(ptr)
+#  define COMMON_MALLOC_FREE_ALIGNED_SIZED(ptr, alignment, size) \
+    COMMON_MALLOC_FREE(ptr)
+#  define COMMON_MALLOC_SIZE(ptr) uptr size = user_alloc_usable_size(ptr);
+#  define COMMON_MALLOC_FILL_STATS(zone, stats)
+#  define COMMON_MALLOC_REPORT_UNKNOWN_REALLOC(ptr, zone_ptr, zone_name)    \
+    (void)zone_name;                                                        \
+    Report("mz_realloc(%p) -- attempting to realloc unallocated memory.\n", \
+           ptr);
+#  define COMMON_MALLOC_NAMESPACE __tsan
+#  define COMMON_MALLOC_HAS_ZONE_ENUMERATOR 0
+#  define COMMON_MALLOC_HAS_EXTRA_INTROSPECTION_INIT 0
 
-#include "sanitizer_common/sanitizer_malloc_mac.inc"
+#  include "sanitizer_common/sanitizer_malloc_mac.inc"
 
 #endif
lib/libtsan/tsan_platform.h
@@ -681,6 +681,33 @@ struct MappingGoMips64_47 {
   static const uptr kShadowAdd = 0x200000000000ull;
 };
 
+/* Go on linux/riscv64 (48-bit VMA)
+0000 0001 0000 - 00e0 0000 0000: executable and heap (896 GiB)
+00e0 0000 0000 - 2000 0000 0000: -
+2000 0000 0000 - 2400 0000 0000: shadow - 4 TiB ( ~ 4 * app)
+2400 0000 0000 - 3000 0000 0000: -
+3000 0000 0000 - 3100 0000 0000: metainfo - 1 TiB ( ~ 1 * app)
+3100 0000 0000 - 8000 0000 0000: -
+*/
+struct MappingGoRiscv64 {
+  static const uptr kMetaShadowBeg = 0x300000000000ull;
+  static const uptr kMetaShadowEnd = 0x310000000000ull;
+  static const uptr kShadowBeg = 0x200000000000ull;
+  static const uptr kShadowEnd = 0x240000000000ull;
+  static const uptr kLoAppMemBeg = 0x000000010000ull;
+  static const uptr kLoAppMemEnd = 0x000e00000000ull;
+  static const uptr kMidAppMemBeg = 0;
+  static const uptr kMidAppMemEnd = 0;
+  static const uptr kHiAppMemBeg = 0;
+  static const uptr kHiAppMemEnd = 0;
+  static const uptr kHeapMemBeg = 0;
+  static const uptr kHeapMemEnd = 0;
+  static const uptr kVdsoBeg = 0;
+  static const uptr kShadowMsk = 0;
+  static const uptr kShadowXor = 0;
+  static const uptr kShadowAdd = 0x200000000000ull;
+};
+
 /*
 Go on linux/s390x
 0000 0000 1000 - 1000 0000 0000: executable and heap - 16 TiB
@@ -728,6 +755,8 @@ ALWAYS_INLINE auto SelectMapping(Arg arg) {
   return Func::template Apply<MappingGoAarch64>(arg);
 #  elif defined(__loongarch_lp64)
   return Func::template Apply<MappingGoLoongArch64_47>(arg);
+#  elif SANITIZER_RISCV64
+  return Func::template Apply<MappingGoRiscv64>(arg);
 #  elif SANITIZER_WINDOWS
   return Func::template Apply<MappingGoWindows>(arg);
 #  else
@@ -798,6 +827,7 @@ void ForEachMapping() {
   Func::template Apply<MappingGoAarch64>();
   Func::template Apply<MappingGoLoongArch64_47>();
   Func::template Apply<MappingGoMips64_47>();
+  Func::template Apply<MappingGoRiscv64>();
   Func::template Apply<MappingGoS390x>();
 }
 
@@ -901,7 +931,7 @@ bool IsAppMem(uptr mem) { return SelectMapping<IsAppMemImpl>(mem); }
 struct IsShadowMemImpl {
   template <typename Mapping>
   static bool Apply(uptr mem) {
-    return mem >= Mapping::kShadowBeg && mem <= Mapping::kShadowEnd;
+    return mem >= Mapping::kShadowBeg && mem < Mapping::kShadowEnd;
   }
 };
 
@@ -913,7 +943,7 @@ bool IsShadowMem(RawShadow *p) {
 struct IsMetaMemImpl {
   template <typename Mapping>
   static bool Apply(uptr mem) {
-    return mem >= Mapping::kMetaShadowBeg && mem <= Mapping::kMetaShadowEnd;
+    return mem >= Mapping::kMetaShadowBeg && mem < Mapping::kMetaShadowEnd;
   }
 };
 
lib/libtsan/tsan_platform_linux.cpp
@@ -259,7 +259,15 @@ static void ReExecIfNeeded(bool ignore_heap) {
             "WARNING: Program is run with randomized virtual address "
             "space, which wouldn't work with ThreadSanitizer on Android.\n"
             "Re-execing with fixed virtual address space.\n");
-    CHECK_NE(personality(old_personality | ADDR_NO_RANDOMIZE), -1);
+
+    if (personality(old_personality | ADDR_NO_RANDOMIZE) == -1) {
+      Printf(
+          "FATAL: ThreadSanitizer: unable to disable ASLR (perhaps "
+          "sandboxing is enabled?).\n");
+      Printf("FATAL: Please rerun without sandboxing and/or ASLR.\n");
+      Die();
+    }
+
     reexec = true;
   }
 #      endif
@@ -287,7 +295,18 @@ static void ReExecIfNeeded(bool ignore_heap) {
               "possibly due to high-entropy ASLR.\n"
               "Re-execing with fixed virtual address space.\n"
               "N.B. reducing ASLR entropy is preferable.\n");
-      CHECK_NE(personality(old_personality | ADDR_NO_RANDOMIZE), -1);
+
+      if (personality(old_personality | ADDR_NO_RANDOMIZE) == -1) {
+        Printf(
+            "FATAL: ThreadSanitizer: encountered an incompatible memory "
+            "layout but was unable to disable ASLR (perhaps sandboxing is "
+            "enabled?).\n");
+        Printf(
+            "FATAL: Please rerun with lower ASLR entropy, ASLR disabled, "
+            "and/or sandboxing disabled.\n");
+        Die();
+      }
+
       reexec = true;
     } else {
       Printf(
@@ -373,6 +392,12 @@ void InitializePlatformEarly() {
     Printf("FATAL: Found %zd - Supported 39 and 48\n", vmaSize);
     Die();
   }
+#    else
+  if (vmaSize != 48) {
+    Printf("FATAL: ThreadSanitizer: unsupported VMA range\n");
+    Printf("FATAL: Found %zd - Supported 48\n", vmaSize);
+    Die();
+  }
 #    endif
 #  endif
 
lib/libtsan/tsan_rtl.cpp
@@ -566,17 +566,32 @@ static bool IsValidMmapRange(uptr addr, uptr size) {
   return false;
 }
 
-void UnmapShadow(ThreadState *thr, uptr addr, uptr size) {
+void UnmapShadow(ThreadState* thr, uptr addr, uptr size) {
   if (size == 0 || !IsValidMmapRange(addr, size))
     return;
-  DontNeedShadowFor(addr, size);
+  // unmap shadow is related to semantic of mmap/munmap, so we
+  // should clear the whole shadow range, including the tail shadow
+  // while addr + size % kShadowCell != 0.
+  uptr rounded_size_shadow = RoundUp(addr + size, kShadowCell) - addr;
+  DontNeedShadowFor(addr, rounded_size_shadow);
   ScopedGlobalProcessor sgp;
   SlotLocker locker(thr, true);
-  ctx->metamap.ResetRange(thr->proc(), addr, size, true);
+  uptr rounded_size_meta = RoundUp(addr + size, kMetaShadowCell) - addr;
+  ctx->metamap.ResetRange(thr->proc(), addr, rounded_size_meta, true);
 }
 #endif
 
 void MapShadow(uptr addr, uptr size) {
+  // Although named MapShadow, this function's semantic is unrelated to
+  // UnmapShadow. This function currently only used for Go's lazy allocation
+  // of shadow, whose targets are program section (e.g., bss, data, etc.).
+  // Therefore, we can guarantee that the addr and size align to kShadowCell
+  // and kMetaShadowCell by the following assertions.
+  DCHECK_EQ(addr % kShadowCell, 0);
+  DCHECK_EQ(size % kShadowCell, 0);
+  DCHECK_EQ(addr % kMetaShadowCell, 0);
+  DCHECK_EQ(size % kMetaShadowCell, 0);
+
   // Ensure thead registry lock held, so as to synchronize
   // with DoReset, which also access the mapped_shadow_* ctxt fields.
   ThreadRegistryLock lock0(&ctx->thread_registry);
@@ -624,6 +639,7 @@ void MapShadow(uptr addr, uptr size) {
   static uptr mapped_meta_end = 0;
   uptr meta_begin = (uptr)MemToMeta(addr);
   uptr meta_end = (uptr)MemToMeta(addr + size);
+  // Windows wants 64K alignment.
   meta_begin = RoundDownTo(meta_begin, 64 << 10);
   meta_end = RoundUpTo(meta_end, 64 << 10);
   if (!data_mapped) {
@@ -634,9 +650,6 @@ void MapShadow(uptr addr, uptr size) {
       Die();
   } else {
     // Mapping continuous heap.
-    // Windows wants 64K alignment.
-    meta_begin = RoundDownTo(meta_begin, 64 << 10);
-    meta_end = RoundUpTo(meta_end, 64 << 10);
     CHECK_GT(meta_end, mapped_meta_end);
     if (meta_begin < mapped_meta_end)
       meta_begin = mapped_meta_end;
@@ -679,6 +692,12 @@ void CheckUnwind() {
 
 bool is_initialized;
 
+// Symbolization indirectly calls dl_iterate_phdr. If a CHECK() fails early on
+// (prior to the dl_iterate_phdr interceptor setup), resulting in an attempted
+// symbolization, it will segfault.
+// dl_iterate_phdr is not intercepted for Android.
+bool ready_to_symbolize = SANITIZER_ANDROID;
+
 void Initialize(ThreadState *thr) {
   // Thread safe because done before all threads exist.
   if (is_initialized)
lib/libtsan/tsan_rtl.h
@@ -54,13 +54,15 @@
 
 namespace __tsan {
 
+extern bool ready_to_symbolize;
+
 #if !SANITIZER_GO
 struct MapUnmapCallback;
 #  if defined(__mips64) || defined(__aarch64__) || defined(__loongarch__) || \
       defined(__powerpc__) || SANITIZER_RISCV64
 
 struct AP32 {
-  static const uptr kSpaceBeg = 0;
+  static const uptr kSpaceBeg = SANITIZER_MMAP_BEGIN;
   static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE;
   static const uptr kMetadataSize = 0;
   typedef __sanitizer::CompactSizeClassMap SizeClassMap;
@@ -98,6 +100,7 @@ struct JmpBuf {
   uptr sp;
   int int_signal_send;
   bool in_blocking_func;
+  uptr oldset_stack_size;
   uptr in_signal_handler;
   uptr *shadow_stack_pos;
 };
lib/libtsan/tsan_rtl_access.cpp
@@ -523,9 +523,9 @@ SECOND:
 }
 
 void ShadowSet(RawShadow* p, RawShadow* end, RawShadow v) {
-  DCHECK_LE(p, end);
+  DCHECK_LT(p, end);
   DCHECK(IsShadowMem(p));
-  DCHECK(IsShadowMem(end));
+  DCHECK(IsShadowMem(end - 1));
   UNUSED const uptr kAlign = kShadowCnt * kShadowSize;
   DCHECK_EQ(reinterpret_cast<uptr>(p) % kAlign, 0);
   DCHECK_EQ(reinterpret_cast<uptr>(end) % kAlign, 0);
@@ -569,6 +569,7 @@ static void MemoryRangeSet(uptr addr, uptr size, RawShadow val) {
   RawShadow* mid1 =
       Min(end, reinterpret_cast<RawShadow*>(RoundUp(
                    reinterpret_cast<uptr>(begin) + kPageSize / 2, kPageSize)));
+  // begin must < mid1
   ShadowSet(begin, mid1, val);
   // Reset middle part.
   RawShadow* mid2 = RoundDown(end, kPageSize);
@@ -577,7 +578,10 @@ static void MemoryRangeSet(uptr addr, uptr size, RawShadow val) {
       Die();
   }
   // Set the ending.
-  ShadowSet(mid2, end, val);
+  if (mid2 < end)
+    ShadowSet(mid2, end, val);
+  else
+    DCHECK_EQ(mid2, end);
 }
 
 void MemoryResetRange(ThreadState* thr, uptr pc, uptr addr, uptr size) {
@@ -669,7 +673,7 @@ void MemoryAccessRangeT(ThreadState* thr, uptr pc, uptr addr, uptr size) {
   RawShadow* shadow_mem = MemToShadow(addr);
   DPrintf2("#%d: MemoryAccessRange: @%p %p size=%d is_read=%d\n", thr->tid,
            (void*)pc, (void*)addr, (int)size, is_read);
-
+  DCHECK_NE(size, 0);
 #if SANITIZER_DEBUG
   if (!IsAppMem(addr)) {
     Printf("Access to non app mem start: %p\n", (void*)addr);
@@ -684,16 +688,18 @@ void MemoryAccessRangeT(ThreadState* thr, uptr pc, uptr addr, uptr size) {
     DCHECK(IsShadowMem(shadow_mem));
   }
 
-  RawShadow* shadow_mem_end = reinterpret_cast<RawShadow*>(
-      reinterpret_cast<uptr>(shadow_mem) + size * kShadowMultiplier - 1);
-  if (!IsShadowMem(shadow_mem_end)) {
-    Printf("Bad shadow end addr: %p (%p)\n", shadow_mem_end,
+  uptr rounded_size =
+      (RoundUpTo(addr + size, kShadowCell) - RoundDownTo(addr, kShadowCell));
+  RawShadow* shadow_mem_end =
+      shadow_mem + rounded_size / kShadowCell * kShadowCnt;
+  if (!IsShadowMem(shadow_mem_end - 1)) {
+    Printf("Bad shadow end addr: %p (%p)\n", shadow_mem_end - 1,
            (void*)(addr + size - 1));
     Printf(
-        "Shadow start addr (ok): %p (%p); size: 0x%zx; kShadowMultiplier: "
-        "%zx\n",
-        shadow_mem, (void*)addr, size, kShadowMultiplier);
-    DCHECK(IsShadowMem(shadow_mem_end));
+        "Shadow start addr (ok): %p (%p); size: 0x%zx; rounded_size: 0x%zx; "
+        "kShadowMultiplier: %zx\n",
+        shadow_mem, (void*)addr, size, rounded_size, kShadowMultiplier);
+    DCHECK(IsShadowMem(shadow_mem_end - 1));
   }
 #endif
 
lib/libtsan/tsan_rtl_report.cpp
@@ -846,7 +846,16 @@ ALWAYS_INLINE USED void PrintCurrentStack(uptr pc, bool fast) {
     ptrace->trace_buffer[i] = ptrace->trace_buffer[ptrace->size - i - 1];
     ptrace->trace_buffer[ptrace->size - i - 1] = tmp;
   }
-  PrintStack(SymbolizeStack(*ptrace));
+
+  if (ready_to_symbolize) {
+    PrintStack(SymbolizeStack(*ptrace));
+  } else {
+    Printf(
+        "WARNING: PrintCurrentStack() has been called too early, before "
+        "symbolization is possible. Printing unsymbolized stack trace:\n");
+    for (unsigned int i = 0; i < ptrace->size; i++)
+      Printf("    #%u: 0x%zx\n", i, ptrace->trace[i]);
+  }
 #endif
 }
 
lib/libtsan/tsan_sync.cpp
@@ -246,12 +246,29 @@ void MetaMap::MoveMemory(uptr src, uptr dst, uptr sz) {
   // there are no concurrent accesses to the regions (e.g. stop-the-world).
   CHECK_NE(src, dst);
   CHECK_NE(sz, 0);
+
+  // The current MoveMemory implementation behaves incorrectly when src, dst,
+  // and sz are not aligned to kMetaShadowCell.
+  // For example, with kMetaShadowCell == 8:
+  // - src = 4: unexpectedly clears the metadata for the range [0, 4).
+  // - src = 16, dst = 4, size = 8: A sync variable for addr = 20, which should
+  //   be moved to the metadata for address 8, is incorrectly moved to the
+  //   metadata for address 0 instead.
+  // - src = 0, sz = 4: fails to move the tail metadata.
+  // Therefore, the following assertions is needed.
+  DCHECK_EQ(src % kMetaShadowCell, 0);
+  DCHECK_EQ(dst % kMetaShadowCell, 0);
+  DCHECK_EQ(sz % kMetaShadowCell, 0);
+
   uptr diff = dst - src;
-  u32 *src_meta = MemToMeta(src);
-  u32 *dst_meta = MemToMeta(dst);
-  u32 *src_meta_end = MemToMeta(src + sz);
-  uptr inc = 1;
-  if (dst > src) {
+  u32 *src_meta, *dst_meta, *src_meta_end;
+  uptr inc;
+  if (dst < src) {
+    src_meta = MemToMeta(src);
+    dst_meta = MemToMeta(dst);
+    src_meta_end = MemToMeta(src + sz);
+    inc = 1;
+  } else {
     src_meta = MemToMeta(src + sz) - 1;
     dst_meta = MemToMeta(dst + sz) - 1;
     src_meta_end = MemToMeta(src) - 1;
src/libs/libtsan.zig
@@ -403,6 +403,7 @@ const sanitizer_common_sources = [_][]const u8{
     "sanitizer_flag_parser.cpp",
     "sanitizer_flags.cpp",
     "sanitizer_fuchsia.cpp",
+    "sanitizer_haiku.cpp",
     "sanitizer_libc.cpp",
     "sanitizer_libignore.cpp",
     "sanitizer_linux.cpp",
@@ -420,6 +421,7 @@ const sanitizer_common_sources = [_][]const u8{
     "sanitizer_procmaps_bsd.cpp",
     "sanitizer_procmaps_common.cpp",
     "sanitizer_procmaps_fuchsia.cpp",
+    "sanitizer_procmaps_haiku.cpp",
     "sanitizer_procmaps_linux.cpp",
     "sanitizer_procmaps_mac.cpp",
     "sanitizer_procmaps_solaris.cpp",
@@ -478,6 +480,7 @@ const sanitizer_symbolizer_sources = [_][]const u8{
 };
 
 const interception_sources = [_][]const u8{
+    "interception_aix.cpp",
     "interception_linux.cpp",
     "interception_mac.cpp",
     "interception_win.cpp",