[compiler-rt] [llvm] [compiler-rt][sanitizer] add Haiku support (PR #134772)

Brad Smith via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 7 19:58:39 PDT 2025


https://github.com/brad0 created https://github.com/llvm/llvm-project/pull/134772

None

>From a9431ad89f86ee926bb3b8360a7c0f5e872f84b5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= <jerome.duval at gmail.com>
Date: Fri, 21 Mar 2025 03:05:58 -0400
Subject: [PATCH] [compiler-rt][sanitizer] add Haiku support

---
 compiler-rt/CMakeLists.txt                    |   4 +
 compiler-rt/cmake/config-ix.cmake             |   4 +-
 compiler-rt/lib/asan/asan_linux.cpp           |  18 +-
 compiler-rt/lib/asan/asan_malloc_linux.cpp    |   2 +-
 compiler-rt/lib/asan/asan_posix.cpp           |   2 +-
 compiler-rt/lib/asan/tests/CMakeLists.txt     |   1 +
 compiler-rt/lib/asan/tests/asan_test.cpp      |   2 +-
 compiler-rt/lib/interception/interception.h   |   4 +-
 .../lib/interception/interception_linux.cpp   |   2 +-
 .../lib/interception/interception_linux.h     |   2 +-
 .../lib/sanitizer_common/CMakeLists.txt       |   5 +
 .../sanitizer_common_interceptors_ioctl.inc   |  18 +-
 .../lib/sanitizer_common/sanitizer_errno.h    |   2 +
 .../sanitizer_common/sanitizer_errno_codes.h  |   9 +
 .../lib/sanitizer_common/sanitizer_haiku.cpp  | 361 ++++++++++++++++++
 .../lib/sanitizer_common/sanitizer_linux.cpp  |  71 +++-
 .../lib/sanitizer_common/sanitizer_linux.h    |   8 +-
 .../sanitizer_linux_libcdep.cpp               |  21 +-
 .../lib/sanitizer_common/sanitizer_platform.h |  13 +-
 .../sanitizer_platform_limits_posix.cpp       |  51 ++-
 .../sanitizer_platform_limits_posix.h         |  46 ++-
 .../lib/sanitizer_common/sanitizer_procmaps.h |   2 +-
 .../sanitizer_procmaps_haiku.cpp              |  97 +++++
 .../sanitizer_unwind_linux_libcdep.cpp        |   4 +-
 .../lib/sanitizer_common/tests/CMakeLists.txt |   3 +
 compiler-rt/lib/ubsan/ubsan_platform.h        |   2 +-
 .../Instrumentation/AddressSanitizer.cpp      |   4 +
 27 files changed, 686 insertions(+), 72 deletions(-)
 create mode 100644 compiler-rt/lib/sanitizer_common/sanitizer_haiku.cpp
 create mode 100644 compiler-rt/lib/sanitizer_common/sanitizer_procmaps_haiku.cpp

diff --git a/compiler-rt/CMakeLists.txt b/compiler-rt/CMakeLists.txt
index f319113e5c16e..9f8e8334d75ba 100644
--- a/compiler-rt/CMakeLists.txt
+++ b/compiler-rt/CMakeLists.txt
@@ -569,6 +569,10 @@ append_list_if(COMPILER_RT_HAS_LIBC c SANITIZER_COMMON_LINK_LIBS)
 if("${CMAKE_SYSTEM_NAME}" STREQUAL "Fuchsia")
   list(APPEND SANITIZER_COMMON_LINK_LIBS zircon)
 endif()
+if("${CMAKE_SYSTEM_NAME}" STREQUAL "Haiku")
+  list(APPEND SANITIZER_COMMON_LINK_LIBS root)
+  list(APPEND SANITIZER_COMMON_LINK_LIBS bsd)
+endif()
 
 if("${CMAKE_SYSTEM_NAME}" STREQUAL "Fuchsia")
   set(SANITIZER_NO_UNDEFINED_SYMBOLS_DEFAULT ON)
diff --git a/compiler-rt/cmake/config-ix.cmake b/compiler-rt/cmake/config-ix.cmake
index cf729c3adb1f5..e3310b1ff0e2c 100644
--- a/compiler-rt/cmake/config-ix.cmake
+++ b/compiler-rt/cmake/config-ix.cmake
@@ -760,7 +760,7 @@ set(COMPILER_RT_SANITIZERS_TO_BUILD all CACHE STRING
 list_replace(COMPILER_RT_SANITIZERS_TO_BUILD all "${ALL_SANITIZERS}")
 
 if (SANITIZER_COMMON_SUPPORTED_ARCH AND NOT LLVM_USE_SANITIZER AND
-    (OS_NAME MATCHES "Android|Darwin|Linux|FreeBSD|NetBSD|Fuchsia|SunOS" OR
+    (OS_NAME MATCHES "Android|Darwin|Linux|FreeBSD|NetBSD|Fuchsia|SunOS|Haiku" OR
     (OS_NAME MATCHES "Windows" AND NOT CYGWIN AND
         (NOT MINGW OR CMAKE_CXX_COMPILER_ID MATCHES "Clang"))))
   set(COMPILER_RT_HAS_SANITIZER_COMMON TRUE)
@@ -875,7 +875,7 @@ else()
 endif()
 
 if (COMPILER_RT_HAS_SANITIZER_COMMON AND UBSAN_SUPPORTED_ARCH AND
-    OS_NAME MATCHES "Darwin|Linux|FreeBSD|NetBSD|Windows|Android|Fuchsia|SunOS")
+    OS_NAME MATCHES "Darwin|Linux|FreeBSD|NetBSD|Windows|Android|Fuchsia|SunOS|Haiku")
   set(COMPILER_RT_HAS_UBSAN TRUE)
 else()
   set(COMPILER_RT_HAS_UBSAN FALSE)
diff --git a/compiler-rt/lib/asan/asan_linux.cpp b/compiler-rt/lib/asan/asan_linux.cpp
index 3b40f76836efe..b3aa3ead187bc 100644
--- a/compiler-rt/lib/asan/asan_linux.cpp
+++ b/compiler-rt/lib/asan/asan_linux.cpp
@@ -13,7 +13,11 @@
 
 #include "sanitizer_common/sanitizer_platform.h"
 #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
-    SANITIZER_SOLARIS
+    SANITIZER_SOLARIS || SANITIZER_HAIKU
+
+#  if SANITIZER_HAIKU
+#    define _DEFAULT_SOURCE
+#  endif
 
 #  include <dlfcn.h>
 #  include <fcntl.h>
@@ -22,7 +26,9 @@
 #  include <stdio.h>
 #  include <sys/mman.h>
 #  include <sys/resource.h>
+#if !SANITIZER_HAIKU
 #  include <sys/syscall.h>
+#endif
 #  include <sys/time.h>
 #  include <sys/types.h>
 #  include <unistd.h>
@@ -37,7 +43,7 @@
 #  include "sanitizer_common/sanitizer_libc.h"
 #  include "sanitizer_common/sanitizer_procmaps.h"
 
-#  if SANITIZER_FREEBSD
+#  if SANITIZER_FREEBSD || SANITIZER_HAIKU
 #    include <sys/link_elf.h>
 #  endif
 
@@ -54,6 +60,8 @@
 #  elif SANITIZER_NETBSD
 #    include <link_elf.h>
 #    include <ucontext.h>
+#  elif SANITIZER_HAIKU
+extern "C" void* _DYNAMIC;
 #  else
 #    include <link.h>
 #    include <sys/ucontext.h>
@@ -162,6 +170,12 @@ static int FindFirstDSOCallback(struct dl_phdr_info *info, size_t size,
     return 0;
   }
 
+#    if SANITIZER_HAIKU
+  if (!info->dlpi_name[0] ||
+      internal_strncmp(info->dlpi_name, "/boot/system/runtime_loader",
+        sizeof("/boot/system/runtime_loader") - 1) == 0)
+    return 0;
+#    endif
 #    if SANITIZER_LINUX
   // Ignore vDSO. glibc versions earlier than 2.15 (and some patched
   // by distributors) return an empty name for the vDSO entry, so
diff --git a/compiler-rt/lib/asan/asan_malloc_linux.cpp b/compiler-rt/lib/asan/asan_malloc_linux.cpp
index 3d6b03fefab70..cbcdd9c1be29d 100644
--- a/compiler-rt/lib/asan/asan_malloc_linux.cpp
+++ b/compiler-rt/lib/asan/asan_malloc_linux.cpp
@@ -15,7 +15,7 @@
 
 #include "sanitizer_common/sanitizer_platform.h"
 #if SANITIZER_FREEBSD || SANITIZER_FUCHSIA || SANITIZER_LINUX || \
-    SANITIZER_NETBSD || SANITIZER_SOLARIS
+    SANITIZER_NETBSD || SANITIZER_SOLARIS || SANITIZER_HAIKU
 
 #  include "asan_allocator.h"
 #  include "asan_interceptors.h"
diff --git a/compiler-rt/lib/asan/asan_posix.cpp b/compiler-rt/lib/asan/asan_posix.cpp
index 39685696a0d0d..401df415096dd 100644
--- a/compiler-rt/lib/asan/asan_posix.cpp
+++ b/compiler-rt/lib/asan/asan_posix.cpp
@@ -174,7 +174,7 @@ static void AfterFork(bool fork_child) {
 
 void InstallAtForkHandler() {
 #  if SANITIZER_SOLARIS || SANITIZER_NETBSD || SANITIZER_APPLE || \
-      (SANITIZER_LINUX && SANITIZER_SPARC)
+      (SANITIZER_LINUX && SANITIZER_SPARC) || SANITIZER_HAIKU
   // While other Linux targets use clone in internal_fork which doesn't
   // trigger pthread_atfork handlers, Linux/sparc64 uses __fork, causing a
   // hang.
diff --git a/compiler-rt/lib/asan/tests/CMakeLists.txt b/compiler-rt/lib/asan/tests/CMakeLists.txt
index 00dcbf6534e28..9cd9c97bed813 100644
--- a/compiler-rt/lib/asan/tests/CMakeLists.txt
+++ b/compiler-rt/lib/asan/tests/CMakeLists.txt
@@ -109,6 +109,7 @@ if(NOT APPLE)
   append_list_if(COMPILER_RT_HAS_LIBM -lm ASAN_UNITTEST_NOINST_LINK_FLAGS)
   append_list_if(COMPILER_RT_HAS_LIBDL -ldl ASAN_UNITTEST_NOINST_LINK_FLAGS)
   append_list_if(COMPILER_RT_HAS_LIBRT -lrt ASAN_UNITTEST_NOINST_LINK_FLAGS)
+  append_list_if(HAIKU -lbsd ASAN_UNITTEST_NOINST_LINK_FLAGS)
   append_list_if(COMPILER_RT_HAS_LIBPTHREAD -pthread ASAN_UNITTEST_NOINST_LINK_FLAGS)
   append_list_if(COMPILER_RT_HAS_LIBPTHREAD -pthread ASAN_DYNAMIC_UNITTEST_INSTRUMENTED_LINK_FLAGS)
 endif()
diff --git a/compiler-rt/lib/asan/tests/asan_test.cpp b/compiler-rt/lib/asan/tests/asan_test.cpp
index 0d98b1498a821..2d054ee859ed4 100644
--- a/compiler-rt/lib/asan/tests/asan_test.cpp
+++ b/compiler-rt/lib/asan/tests/asan_test.cpp
@@ -1163,7 +1163,7 @@ TEST(AddressSanitizer, DISABLED_StressStackReuseAndExceptionsTest) {
 }
 #endif
 
-#if !defined(_WIN32)
+#if !defined(_WIN32) && !defined(__HAIKU__)
 TEST(AddressSanitizer, MlockTest) {
   EXPECT_EQ(0, mlockall(MCL_CURRENT));
   EXPECT_EQ(0, mlock((void *)0x12345, 0x5678));
diff --git a/compiler-rt/lib/interception/interception.h b/compiler-rt/lib/interception/interception.h
index 3cb6b446638e0..25480120e7ad6 100644
--- a/compiler-rt/lib/interception/interception.h
+++ b/compiler-rt/lib/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
 #  error "Interception doesn't work on this operating system."
 #endif
 
@@ -368,7 +368,7 @@ inline void DoesNotSupportStaticLinking() {}
 #define INCLUDED_FROM_INTERCEPTION_LIB
 
 #if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \
-    SANITIZER_SOLARIS
+    SANITIZER_SOLARIS || SANITIZER_HAIKU
 
 # include "interception_linux.h"
 # define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func)
diff --git a/compiler-rt/lib/interception/interception_linux.cpp b/compiler-rt/lib/interception/interception_linux.cpp
index ef8136eb4fc70..0a6659d38ae83 100644
--- a/compiler-rt/lib/interception/interception_linux.cpp
+++ b/compiler-rt/lib/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()
 
diff --git a/compiler-rt/lib/interception/interception_linux.h b/compiler-rt/lib/interception/interception_linux.h
index 2e01ff44578c3..52e34d535030e 100644
--- a/compiler-rt/lib/interception/interception_linux.h
+++ b/compiler-rt/lib/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
diff --git a/compiler-rt/lib/sanitizer_common/CMakeLists.txt b/compiler-rt/lib/sanitizer_common/CMakeLists.txt
index 09391e4f5f370..6e6dfd2f33ebf 100644
--- a/compiler-rt/lib/sanitizer_common/CMakeLists.txt
+++ b/compiler-rt/lib/sanitizer_common/CMakeLists.txt
@@ -11,6 +11,7 @@ set(SANITIZER_SOURCES_NOTERMINATION
   sanitizer_flags.cpp
   sanitizer_flag_parser.cpp
   sanitizer_fuchsia.cpp
+  sanitizer_haiku.cpp
   sanitizer_libc.cpp
   sanitizer_libignore.cpp
   sanitizer_linux.cpp
@@ -28,6 +29,7 @@ set(SANITIZER_SOURCES_NOTERMINATION
   sanitizer_procmaps_common.cpp
   sanitizer_procmaps_bsd.cpp
   sanitizer_procmaps_fuchsia.cpp
+  sanitizer_procmaps_haiku.cpp
   sanitizer_procmaps_linux.cpp
   sanitizer_procmaps_mac.cpp
   sanitizer_procmaps_solaris.cpp
@@ -227,6 +229,9 @@ set(SANITIZER_COMMON_DEFINITIONS
 
 # note: L not I, this is nodefaultlibs for msvc
 append_list_if(MSVC /Zl SANITIZER_COMMON_CFLAGS)
+if(HAIKU)
+   list(APPEND SANITIZER_COMMON_CFLAGS -I/system/develop/headers/private -I/system/develop/headers/private/system/arch/x86_64 -I/system/develop/headers/private/system)
+endif()
 set(SANITIZER_CFLAGS ${SANITIZER_COMMON_CFLAGS})
 
 # Too many existing bugs, needs cleanup.
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc
index 49ec4097c900b..f88f914b1d149 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc
@@ -48,35 +48,39 @@ 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));
   _(TIOCSCTTY, NONE, 0);
-  _(TIOCSETD, READ, sizeof(int));
   _(TIOCSPGRP, READ, pid_t_sz);
-  _(TIOCSTI, READ, sizeof(char));
   _(TIOCSWINSZ, READ, struct_winsize_sz);
 
 #if !SANITIZER_IOS
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_errno.h b/compiler-rt/lib/sanitizer_common/sanitizer_errno.h
index 46c85364cef56..76919da57d942 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_errno.h
+++ b/compiler-rt/lib/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();
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_errno_codes.h b/compiler-rt/lib/sanitizer_common/sanitizer_errno_codes.h
index 9e6e71ec80c15..c2ea52b84dfc3 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_errno_codes.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_errno_codes.h
@@ -21,12 +21,21 @@
 
 namespace __sanitizer {
 
+#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;
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_haiku.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_haiku.cpp
new file mode 100644
index 0000000000000..9b721775422ee
--- /dev/null
+++ b/compiler-rt/lib/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
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
index 1fa75214f4205..cadd79de9db87 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
+++ b/compiler-rt/lib/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
@@ -120,6 +122,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
@@ -248,7 +257,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) {
@@ -595,7 +604,7 @@ uptr internal_execve(const char *filename, char *const argv[],
 }
 #  endif  // !SANITIZER_SOLARIS && !SANITIZER_NETBSD
 
-#  if !SANITIZER_NETBSD
+#  if !SANITIZER_NETBSD && !SANITIZER_HAIKU
 void internal__exit(int exitcode) {
 #    if SANITIZER_FREEBSD || SANITIZER_SOLARIS
   internal_syscall(SYSCALL(exit), exitcode);
@@ -632,6 +641,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
@@ -647,6 +658,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
@@ -674,7 +687,7 @@ 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++) {
@@ -712,13 +725,13 @@ 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;
@@ -745,7 +758,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>.
@@ -804,7 +820,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);
@@ -814,7 +830,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);
@@ -846,7 +862,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,
@@ -1060,7 +1076,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);
@@ -1264,7 +1280,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);
@@ -1330,11 +1358,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
@@ -1993,11 +2021,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];
@@ -2610,6 +2642,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];
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.h b/compiler-rt/lib/sanitizer_common/sanitizer_linux.h
index 8b7874bb5a349..c1562506babf3 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.h
+++ b/compiler-rt/lib/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
 
 // Syscall wrappers.
 uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count);
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp
index e5e79d4e0521c..bf3b70365432e 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp
+++ b/compiler-rt/lib/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,6 +28,10 @@
 #  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()
 #  endif
@@ -74,6 +78,11 @@ extern "C" int __sys_sigaction(int signum, const struct sigaction *act,
 #    include <thread.h>
 #  endif
 
+#  if SANITIZER_HAIKU
+#    include <kernel/OS.h>
+#    include <sys/link_elf.h>
+#  endif
+
 #  if !SANITIZER_ANDROID
 #    include <elf.h>
 #    include <unistd.h>
@@ -636,6 +645,7 @@ static void GetTls(uptr *addr, uptr *size) {
       *addr = (uptr)tcb->tcb_dtv[1];
     }
   }
+#    elif SANITIZER_HAIKU
 #    else
 #      error "Unknown OS"
 #    endif
@@ -706,8 +716,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
@@ -843,6 +858,10 @@ u32 GetNumberOfCPUs() {
   req[1] = HW_NCPU;
   CHECK_EQ(internal_sysctl(req, 2, &ncpu, &len, NULL, 0), 0);
   return ncpu;
+#  elif SANITIZER_HAIKU
+  system_info info;
+  get_system_info(&info);
+  return info.cpu_count;
 #  elif SANITIZER_SOLARIS
   return sysconf(_SC_NPROCESSORS_ONLN);
 #  else
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform.h
index 57966403c92a9..af79e99165f97 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform.h
@@ -14,7 +14,7 @@
 
 #if !defined(__linux__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && \
     !defined(__APPLE__) && !defined(_WIN32) && !defined(__Fuchsia__) &&     \
-    !(defined(__sun__) && defined(__svr4__))
+    !(defined(__sun__) && defined(__svr4__)) && !defined(__HAIKU__)
 #  error "This operating system is not supported"
 #endif
 
@@ -55,6 +55,12 @@
 #  define SANITIZER_SOLARIS 0
 #endif
 
+#if defined(__HAIKU__)
+#  define SANITIZER_HAIKU 1
+#else
+#  define SANITIZER_HAIKU 0
+#endif
+
 // - SANITIZER_APPLE: all Apple code
 //   - TARGET_OS_OSX: macOS
 //   - SANITIZER_IOS: devices (iOS and iOS-like)
@@ -138,7 +144,7 @@
 
 #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
@@ -410,7 +416,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
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp
index a5311d266b0c4..28503ff487867 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp
+++ b/compiler-rt/lib/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,7 +365,7 @@ 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
 
@@ -540,7 +549,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
@@ -551,12 +560,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;
@@ -577,23 +588,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;
@@ -1103,7 +1118,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);
@@ -1119,7 +1134,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);
@@ -1174,7 +1191,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);
@@ -1204,7 +1221,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);
@@ -1242,7 +1261,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);
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
index 1f7e3d21b6a6f..26de940f931b5 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
@@ -14,7 +14,7 @@
 #ifndef SANITIZER_PLATFORM_LIMITS_POSIX_H
 #define SANITIZER_PLATFORM_LIMITS_POSIX_H
 
-#if SANITIZER_LINUX || SANITIZER_APPLE
+#if SANITIZER_LINUX || SANITIZER_APPLE || SANITIZER_HAIKU
 
 #include "sanitizer_internal_defs.h"
 #include "sanitizer_platform.h"
@@ -366,7 +366,7 @@ struct __sanitizer_passwd {
   long pw_change;
   char *pw_class;
 #endif
-#if !(SANITIZER_ANDROID && (SANITIZER_WORDSIZE == 32))
+#if !(SANITIZER_ANDROID && (SANITIZER_WORDSIZE == 32)) && !SANITIZER_HAIKU
   char *pw_gecos;
 #endif
   char *pw_dir;
@@ -374,6 +374,9 @@ struct __sanitizer_passwd {
 #if SANITIZER_APPLE
   long pw_expire;
 #endif
+#if SANITIZER_HAIKU
+  char *pw_gecos;
+#endif
 };
 
 struct __sanitizer_group {
@@ -433,7 +436,11 @@ 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;
 };
 
@@ -454,7 +461,7 @@ struct __sanitizer_file_handle {
 };
 #endif
 
-#if SANITIZER_APPLE
+#if SANITIZER_APPLE || SANITIZER_HAIKU
 struct __sanitizer_msghdr {
   void *msg_name;
   unsigned msg_namelen;
@@ -502,6 +509,15 @@ struct __sanitizer_dirent {
   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 {
@@ -529,13 +545,15 @@ struct __sanitizer_dirent64 {
 extern unsigned struct_sock_fprog_sz;
 #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
 typedef long __sanitizer_clock_t;
 #endif
 
-#if SANITIZER_LINUX
+#if SANITIZER_LINUX || SANITIZER_HAIKU
 typedef int __sanitizer_clockid_t;
 typedef unsigned long long __sanitizer_eventfd_t;
 #endif
@@ -584,6 +602,8 @@ typedef unsigned long __sanitizer_sigset_t;
 # endif
 #elif SANITIZER_APPLE
 typedef unsigned __sanitizer_sigset_t;
+#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.
@@ -692,7 +712,7 @@ struct __sanitizer_sigaction {
 #        endif
 #      endif
 #    endif
-#    if SANITIZER_LINUX
+#    if SANITIZER_LINUX || SANITIZER_HAIKU
   void (*sa_restorer)();
 #    endif
 #    if defined(__mips__) && (SANITIZER_WORDSIZE == 32) && !SANITIZER_MUSL
@@ -779,7 +799,7 @@ 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;
@@ -1128,23 +1148,25 @@ 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
 extern unsigned IOCTL_SIOCGETSGCNT;
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_procmaps.h b/compiler-rt/lib/sanitizer_common/sanitizer_procmaps.h
index bf3c2c28e32e3..a9be974c12b19 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_procmaps.h
+++ b/compiler-rt/lib/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"
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_haiku.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_haiku.cpp
new file mode 100644
index 0000000000000..befb55720626a
--- /dev/null
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_haiku.cpp
@@ -0,0 +1,97 @@
+//===-- 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
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cpp
index 6a8e82e2e213c..3f6901a2e7f1b 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cpp
+++ b/compiler-rt/lib/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"
 
@@ -171,4 +171,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
diff --git a/compiler-rt/lib/sanitizer_common/tests/CMakeLists.txt b/compiler-rt/lib/sanitizer_common/tests/CMakeLists.txt
index fef8bb772e0e0..55c7d665e639f 100644
--- a/compiler-rt/lib/sanitizer_common/tests/CMakeLists.txt
+++ b/compiler-rt/lib/sanitizer_common/tests/CMakeLists.txt
@@ -134,6 +134,9 @@ append_list_if(COMPILER_RT_HAS_LIBPTHREAD -pthread SANITIZER_TEST_LINK_FLAGS_COM
 if(CMAKE_SYSTEM MATCHES "FreeBSD-9.2-RELEASE")
   list(APPEND SANITIZER_TEST_LINK_FLAGS_COMMON "-lc++ -lm")
 endif()
+if(CMAKE_SYSTEM MATCHES "Haiku")
+  list(APPEND SANITIZER_TEST_LINK_FLAGS_COMMON "-lbsd")
+endif()
 
 include_directories(..)
 include_directories(../..)
diff --git a/compiler-rt/lib/ubsan/ubsan_platform.h b/compiler-rt/lib/ubsan/ubsan_platform.h
index d2cc2e10bd2f0..c7eb1a967e53f 100644
--- a/compiler-rt/lib/ubsan/ubsan_platform.h
+++ b/compiler-rt/lib/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
diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
index a4c6c61e57998..c1dba77c3532b 100644
--- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -501,6 +501,7 @@ static ShadowMapping getShadowMapping(const Triple &TargetTriple, int LongSize,
   bool IsFuchsia = TargetTriple.isOSFuchsia();
   bool IsEmscripten = TargetTriple.isOSEmscripten();
   bool IsAMDGPU = TargetTriple.isAMDGPU();
+  bool IsHaiku = TargetTriple.isOSHaiku();
 
   ShadowMapping Mapping;
 
@@ -574,6 +575,9 @@ static ShadowMapping getShadowMapping(const Triple &TargetTriple, int LongSize,
     else if (IsAMDGPU)
       Mapping.Offset = (kSmallX86_64ShadowOffsetBase &
                         (kSmallX86_64ShadowOffsetAlignMask << Mapping.Scale));
+    else if (IsHaiku && IsX86_64)
+      Mapping.Offset = (kSmallX86_64ShadowOffsetBase &
+                        (kSmallX86_64ShadowOffsetAlignMask << Mapping.Scale));
     else
       Mapping.Offset = kDefaultShadowOffset64;
   }



More information about the llvm-commits mailing list