Commit ac20506090
Changed files (58)
lib
libtsan
builtins
interception
sanitizer_common
ubsan
src
libs
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",