diff --git a/lib/libtsan/builtins/assembly.h b/lib/libtsan/builtins/assembly.h index 34c7124152..89372f18c8 100644 --- a/lib/libtsan/builtins/assembly.h +++ b/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) \ diff --git a/lib/libtsan/interception/interception.h b/lib/libtsan/interception/interception.h index 3cb6b44663..9fe7d3db30 100644 --- a/lib/libtsan/interception/interception.h +++ b/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" diff --git a/lib/libtsan/interception/interception_aix.cpp b/lib/libtsan/interception/interception_aix.cpp new file mode 100644 index 0000000000..953bbad96e --- /dev/null +++ b/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 // 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 diff --git a/lib/libtsan/interception/interception_aix.h b/lib/libtsan/interception/interception_aix.h new file mode 100644 index 0000000000..b86ae89f50 --- /dev/null +++ b/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 diff --git a/lib/libtsan/interception/interception_linux.cpp b/lib/libtsan/interception/interception_linux.cpp index ef8136eb4f..f900ae6a59 100644 --- a/lib/libtsan/interception/interception_linux.cpp +++ b/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 // 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 diff --git a/lib/libtsan/interception/interception_linux.h b/lib/libtsan/interception/interception_linux.h index 2e01ff4457..0958ffe3fe 100644 --- a/lib/libtsan/interception/interception_linux.h +++ b/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 diff --git a/lib/libtsan/interception/interception_win.cpp b/lib/libtsan/interception/interception_win.cpp index 002b37468a..246a22c56c 100644 --- a/lib/libtsan/interception/interception_win.cpp +++ b/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) { diff --git a/lib/libtsan/sanitizer_common/sanitizer_allocator_internal.h b/lib/libtsan/sanitizer_common/sanitizer_allocator_internal.h index 62523c7ae1..6c2020e637 100644 --- a/lib/libtsan/sanitizer_common/sanitizer_allocator_internal.h +++ b/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; diff --git a/lib/libtsan/sanitizer_common/sanitizer_allocator_local_cache.h b/lib/libtsan/sanitizer_common/sanitizer_allocator_local_cache.h index e495c56f03..6e54c4852f 100644 --- a/lib/libtsan/sanitizer_common/sanitizer_allocator_local_cache.h +++ b/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; } diff --git a/lib/libtsan/sanitizer_common/sanitizer_atomic_clang.h b/lib/libtsan/sanitizer_common/sanitizer_atomic_clang.h index 1414092e38..fded66546f 100644 --- a/lib/libtsan/sanitizer_common/sanitizer_atomic_clang.h +++ b/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 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 diff --git a/lib/libtsan/sanitizer_common/sanitizer_common.h b/lib/libtsan/sanitizer_common/sanitizer_common.h index d9e7ded593..120c2861c1 100644 --- a/lib/libtsan/sanitizer_common/sanitizer_common.h +++ b/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. diff --git a/lib/libtsan/sanitizer_common/sanitizer_common_interceptors.inc b/lib/libtsan/sanitizer_common/sanitizer_common_interceptors.inc index 24a8a2d4dc..2d6cf7fc32 100644 --- a/lib/libtsan/sanitizer_common/sanitizer_common_interceptors.inc +++ b/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; } diff --git a/lib/libtsan/sanitizer_common/sanitizer_common_interceptors_format.inc b/lib/libtsan/sanitizer_common/sanitizer_common_interceptors_format.inc index 24e5dc0fb2..dd4dab07b3 100644 --- a/lib/libtsan/sanitizer_common/sanitizer_common_interceptors_format.inc +++ b/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"); } diff --git a/lib/libtsan/sanitizer_common/sanitizer_common_interceptors_ioctl.inc b/lib/libtsan/sanitizer_common/sanitizer_common_interceptors_ioctl.inc index dda11daa77..08c2be47f5 100644 --- a/lib/libtsan/sanitizer_common/sanitizer_common_interceptors_ioctl.inc +++ b/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 diff --git a/lib/libtsan/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc b/lib/libtsan/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc index 1565a49414..0b6731c899 100644 --- a/lib/libtsan/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc +++ b/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 diff --git a/lib/libtsan/sanitizer_common/sanitizer_common_syscalls.inc b/lib/libtsan/sanitizer_common/sanitizer_common_syscalls.inc index 29fe4721ba..521fc116f2 100644 --- a/lib/libtsan/sanitizer_common/sanitizer_common_syscalls.inc +++ b/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 diff --git a/lib/libtsan/sanitizer_common/sanitizer_errno.h b/lib/libtsan/sanitizer_common/sanitizer_errno.h index 46c85364ce..76919da57d 100644 --- a/lib/libtsan/sanitizer_common/sanitizer_errno.h +++ b/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(); diff --git a/lib/libtsan/sanitizer_common/sanitizer_errno_codes.h b/lib/libtsan/sanitizer_common/sanitizer_errno_codes.h index 9e6e71ec80..10a98a9b4e 100644 --- a/lib/libtsan/sanitizer_common/sanitizer_errno_codes.h +++ b/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; diff --git a/lib/libtsan/sanitizer_common/sanitizer_file.cpp b/lib/libtsan/sanitizer_common/sanitizer_file.cpp index 96af270f9d..9236a458cd 100644 --- a/lib/libtsan/sanitizer_common/sanitizer_file.cpp +++ b/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); } } diff --git a/lib/libtsan/sanitizer_common/sanitizer_fuchsia.cpp b/lib/libtsan/sanitizer_common/sanitizer_fuchsia.cpp index acbf3ebfc9..1ca50eb186 100644 --- a/lib/libtsan/sanitizer_common/sanitizer_fuchsia.cpp +++ b/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(stack_base); __sanitizer::MainThreadStackSize = stack_size; + + EarlySanitizerInit(); } void __sanitizer_set_report_path(const char *path) { diff --git a/lib/libtsan/sanitizer_common/sanitizer_fuchsia.h b/lib/libtsan/sanitizer_common/sanitizer_fuchsia.h index 26c1deab9e..47e7537c1b 100644 --- a/lib/libtsan/sanitizer_common/sanitizer_fuchsia.h +++ b/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 diff --git a/lib/libtsan/sanitizer_common/sanitizer_haiku.cpp b/lib/libtsan/sanitizer_common/sanitizer_haiku.cpp new file mode 100644 index 0000000000..7cf2437d5b --- /dev/null +++ b/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 +# include + +# include +# include +# include +# include + +# include +# include +# include +# include +# include +# include +# include +# include +# include + +# include "system/vm_defs.h" +# include "system/syscalls.h" +# include "shared/syscall_utils.h" + +namespace __sanitizer { + +static void *GetRealLibcAddress(const char *symbol) { + void *real = dlsym(RTLD_NEXT, symbol); + if (!real) + real = dlsym(RTLD_DEFAULT, symbol); + if (!real) { + Printf("GetRealLibcAddress failed for symbol=%s", symbol); + Die(); + } + return real; +} + +# define _REAL(func, ...) real##_##func(__VA_ARGS__) +# define DEFINE__REAL(ret_type, func, ...) \ + static ret_type (*real_##func)(__VA_ARGS__) = NULL; \ + if (!real_##func) { \ + real_##func = (ret_type(*)(__VA_ARGS__))GetRealLibcAddress(#func); \ + } \ + CHECK(real_##func); + +// --------------- sanitizer_libc.h +uptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd, + u64 offset) { + if ((flags & MAP_ANONYMOUS) != 0) + fd = -1; + + int mapping = + (flags & MAP_SHARED) != 0 ? REGION_NO_PRIVATE_MAP : REGION_PRIVATE_MAP; + + uint32 addressSpec; + if ((flags & MAP_FIXED) != 0) + addressSpec = B_EXACT_ADDRESS; + else if (addr != NULL) + addressSpec = B_BASE_ADDRESS; + else + addressSpec = B_RANDOMIZED_ANY_ADDRESS; + + uint32 areaProtection = 0; + if ((prot & PROT_READ) != 0) + areaProtection |= B_READ_AREA; + if ((prot & PROT_WRITE) != 0) + areaProtection |= B_WRITE_AREA; + if ((prot & PROT_EXEC) != 0) + areaProtection |= B_EXECUTE_AREA; + + if ((flags & MAP_NORESERVE) != 0) + areaProtection |= B_OVERCOMMITTING_AREA; + + area_id area = _kern_map_file("sanitizer mmap", &addr, addressSpec, length, + areaProtection, mapping, true, fd, offset); + if (area < 0) + RETURN_AND_SET_ERRNO(area); + return (uptr)addr; +} + +uptr internal_munmap(void *addr, uptr length) { + DEFINE__REAL(int, munmap, void *a, uptr b); + return _REAL(munmap, addr, length); +} + +uptr internal_mremap(void *old_address, uptr old_size, uptr new_size, int flags, + void *new_address) { + CHECK(false && "internal_mremap is unimplemented on Haiku"); + return 0; +} + +int internal_mprotect(void *addr, uptr length, int prot) { + DEFINE__REAL(int, mprotect, void *a, uptr b, int c); + return _REAL(mprotect, addr, length, prot); +} + +int internal_madvise(uptr addr, uptr length, int advice) { + DEFINE__REAL(int, madvise, void *a, uptr b, int c); + return _REAL(madvise, (void *)addr, length, advice); +} + +uptr internal_close(fd_t fd) { + CHECK(&_kern_close); + RETURN_AND_SET_ERRNO(_kern_close(fd)); +} + +uptr internal_open(const char *filename, int flags) { + CHECK(&_kern_open); + RETURN_AND_SET_ERRNO(_kern_open(-1, filename, flags, 0)); +} + +uptr internal_open(const char *filename, int flags, u32 mode) { + CHECK(&_kern_open); + RETURN_AND_SET_ERRNO(_kern_open(-1, filename, flags, mode)); +} + +uptr internal_read(fd_t fd, void *buf, uptr count) { + sptr res; + CHECK(&_kern_read); + HANDLE_EINTR(res, (sptr)_kern_read(fd, -1, buf, (size_t)count)); + RETURN_AND_SET_ERRNO(res); + return res; +} + +uptr internal_write(fd_t fd, const void *buf, uptr count) { + sptr res; + CHECK(&_kern_write); + HANDLE_EINTR(res, (sptr)_kern_write(fd, -1, buf, count)); + RETURN_AND_SET_ERRNO(res); + return res; +} + +uptr internal_ftruncate(fd_t fd, uptr size) { + sptr res; + DEFINE__REAL(int, ftruncate, int, off_t); + return _REAL(ftruncate, fd, size); + return res; +} + +uptr internal_stat(const char *path, void *buf) { + DEFINE__REAL(int, _stat_current, const char *a, void *b); + return _REAL(_stat_current, path, buf); +} + +uptr internal_lstat(const char *path, void *buf) { + DEFINE__REAL(int, _lstat_current, const char *a, void *b); + return _REAL(_lstat_current, path, buf); +} + +uptr internal_fstat(fd_t fd, void *buf) { + DEFINE__REAL(int, _fstat_current, int a, void *b); + return _REAL(_fstat_current, fd, buf); +} + +uptr internal_filesize(fd_t fd) { + struct stat st; + if (internal_fstat(fd, &st)) + return -1; + return (uptr)st.st_size; +} + +uptr internal_dup(int oldfd) { + DEFINE__REAL(int, dup, int a); + return _REAL(dup, oldfd); +} + +uptr internal_dup2(int oldfd, int newfd) { + DEFINE__REAL(int, dup2, int a, int b); + return _REAL(dup2, oldfd, newfd); +} + +uptr internal_readlink(const char *path, char *buf, uptr bufsize) { + CHECK(&_kern_read_link); + RETURN_AND_SET_ERRNO(_kern_read_link(-1, path, buf, &bufsize)); +} + +uptr internal_unlink(const char *path) { + DEFINE__REAL(int, unlink, const char *a); + return _REAL(unlink, path); +} + +uptr internal_rename(const char *oldpath, const char *newpath) { + DEFINE__REAL(int, rename, const char *a, const char *b); + return _REAL(rename, oldpath, newpath); +} + +uptr internal_sched_yield() { + CHECK(&_kern_thread_yield); + _kern_thread_yield(); + return 0; +} + +void internal__exit(int exitcode) { + DEFINE__REAL(void, _exit, int a); + _REAL(_exit, exitcode); + Die(); // Unreachable. +} + +void internal_usleep(u64 useconds) { + _kern_snooze_etc(useconds, B_SYSTEM_TIMEBASE, B_RELATIVE_TIMEOUT, NULL); +} + +uptr internal_execve(const char *filename, char *const argv[], + char *const envp[]) { + DEFINE__REAL(int, execve, const char *, char *const[], char *const[]); + return _REAL(execve, filename, argv, envp); +} + +# if 0 +tid_t GetTid() { + DEFINE__REAL(int, _lwp_self); + return _REAL(_lwp_self); +} + +int TgKill(pid_t pid, tid_t tid, int sig) { + DEFINE__REAL(int, _lwp_kill, int a, int b); + (void)pid; + return _REAL(_lwp_kill, tid, sig); +} + +u64 NanoTime() { + timeval tv; + DEFINE__REAL(int, __gettimeofday50, void *a, void *b); + internal_memset(&tv, 0, sizeof(tv)); + _REAL(__gettimeofday50, &tv, 0); + return (u64)tv.tv_sec * 1000 * 1000 * 1000 + tv.tv_usec * 1000; +} +# endif + +uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp) { + DEFINE__REAL(int, __clock_gettime50, __sanitizer_clockid_t a, void *b); + return _REAL(__clock_gettime50, clk_id, tp); +} + +uptr internal_ptrace(int request, int pid, void *addr, int data) { + DEFINE__REAL(int, ptrace, int a, int b, void *c, int d); + return _REAL(ptrace, request, pid, addr, data); +} + +uptr internal_waitpid(int pid, int *status, int options) { + DEFINE__REAL(int, waitpid, pid_t, int *, int); + return _REAL(waitpid, pid, status, options); +} + +uptr internal_getpid() { + DEFINE__REAL(int, getpid); + return _REAL(getpid); +} + +uptr internal_getppid() { + DEFINE__REAL(int, getppid); + return _REAL(getppid); +} + +int internal_dlinfo(void *handle, int request, void *p) { + DEFINE__REAL(int, dlinfo, void *a, int b, void *c); + return _REAL(dlinfo, handle, request, p); +} + +uptr internal_getdents(fd_t fd, void *dirp, unsigned int count) { + DEFINE__REAL(int, __getdents30, int a, void *b, size_t c); + return _REAL(__getdents30, fd, dirp, count); +} + +uptr internal_lseek(fd_t fd, OFF_T offset, int whence) { + CHECK(&_kern_seek); + off_t result = _kern_seek(fd, offset, whence); + if (result < 0) { + errno = result; + return -1; + } + return result; +} + +uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) { + Printf("internal_prctl not implemented for Haiku"); + Die(); + return 0; +} + +uptr internal_sigaltstack(const void *ss, void *oss) { + DEFINE__REAL(int, __sigaltstack14, const void *a, void *b); + return _REAL(__sigaltstack14, ss, oss); +} + +int internal_fork() { + DEFINE__REAL(int, fork); + return _REAL(fork); +} + +# if 0 +int internal_sysctl(const int *name, unsigned int namelen, void *oldp, + uptr *oldlenp, const void *newp, uptr newlen) { + CHECK(&__sysctl); + return __sysctl(name, namelen, oldp, (size_t *)oldlenp, newp, (size_t)newlen); +} +# endif + +int internal_sysctlbyname(const char *sname, void *oldp, uptr *oldlenp, + const void *newp, uptr newlen) { + DEFINE__REAL(int, sysctlbyname, const char *a, void *b, size_t *c, + const void *d, size_t e); + return _REAL(sysctlbyname, sname, oldp, (size_t *)oldlenp, newp, + (size_t)newlen); +} + +uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set, + __sanitizer_sigset_t *oldset) { + CHECK(&_kern_set_signal_mask); + return _kern_set_signal_mask(how, set, oldset); +} + +void internal_sigfillset(__sanitizer_sigset_t *set) { + DEFINE__REAL(int, __sigfillset14, const void *a); + (void)_REAL(__sigfillset14, set); +} + +void internal_sigemptyset(__sanitizer_sigset_t *set) { + DEFINE__REAL(int, __sigemptyset14, const void *a); + (void)_REAL(__sigemptyset14, set); +} + +void internal_sigdelset(__sanitizer_sigset_t *set, int signo) { + DEFINE__REAL(int, __sigdelset14, const void *a, int b); + (void)_REAL(__sigdelset14, set, signo); +} + +uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, + void *arg) { + DEFINE__REAL(int, clone, int (*a)(void *b), void *c, int d, void *e); + + return _REAL(clone, fn, child_stack, flags, arg); +} + +} // namespace __sanitizer + +#endif diff --git a/lib/libtsan/sanitizer_common/sanitizer_linux.cpp b/lib/libtsan/sanitizer_common/sanitizer_linux.cpp index a4d526b446..16caf699a4 100644 --- a/lib/libtsan/sanitizer_common/sanitizer_linux.cpp +++ b/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 # include # include -# if !SANITIZER_SOLARIS +# if !SANITIZER_SOLARIS && !SANITIZER_HAIKU # include # endif # include # include -# include +# if !SANITIZER_HAIKU +# include +# include +# endif # include # include -# include # include # if SANITIZER_LINUX @@ -82,6 +84,12 @@ # include # 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 # endif @@ -118,6 +126,13 @@ extern struct ps_strings *__ps_strings; # define environ _environ # endif +# if SANITIZER_HAIKU +# include +# include +# include +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 . @@ -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 = ""; + 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]; diff --git a/lib/libtsan/sanitizer_common/sanitizer_linux.h b/lib/libtsan/sanitizer_common/sanitizer_linux.h index 8b7874bb5a..05b7d2e28a 100644 --- a/lib/libtsan/sanitizer_common/sanitizer_linux.h +++ b/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 , 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) { diff --git a/lib/libtsan/sanitizer_common/sanitizer_linux_libcdep.cpp b/lib/libtsan/sanitizer_common/sanitizer_linux_libcdep.cpp index 331e1c7d8d..f5cb85bc1b 100644 --- a/lib/libtsan/sanitizer_common/sanitizer_linux_libcdep.cpp +++ b/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 +# undef _RTLD_SOURCE +# include +# if __NetBSD_Version__ >= 1099001200 +# include +# endif # endif # include // for dlsym() @@ -74,18 +85,9 @@ extern "C" int __sys_sigaction(int signum, const struct sigaction *act, # include # endif -# if SANITIZER_ANDROID -# include -# if !defined(CPU_COUNT) && !defined(__aarch64__) -# include -# include -struct __sanitizer::linux_dirent { - long d_ino; - off_t d_off; - unsigned short d_reclen; - char d_name[]; -}; -# endif +# if SANITIZER_HAIKU +# include +# include # 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 *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 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 diff --git a/lib/libtsan/sanitizer_common/sanitizer_mac.cpp b/lib/libtsan/sanitizer_common/sanitizer_mac.cpp index d15f30c61b..bb71af5ad8 100644 --- a/lib/libtsan/sanitizer_common/sanitizer_mac.cpp +++ b/lib/libtsan/sanitizer_common/sanitizer_mac.cpp @@ -38,13 +38,6 @@ extern char **environ; # endif -# if defined(__has_include) && __has_include() -# define SANITIZER_OS_TRACE 1 -# include -# else -# define SANITIZER_OS_TRACE 0 -# endif - // Integrate with CrashReporter library if available # if defined(__has_include) && __has_include() # 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 !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_trace("Consult syslog for more information."); - } -#pragma clang diagnostic pop -#endif + 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(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; } diff --git a/lib/libtsan/sanitizer_common/sanitizer_mac.h b/lib/libtsan/sanitizer_common/sanitizer_mac.h index f0a97d098e..b0e4ac7f40 100644 --- a/lib/libtsan/sanitizer_common/sanitizer_mac.h +++ b/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 +bool operator==(const VersionBase &self, + const VersionBase &other) { + return self.major == other.major && self.minor == other.minor; +} + struct MacosVersion : VersionBase { MacosVersion(u16 major, u16 minor) : VersionBase(major, minor) {} }; diff --git a/lib/libtsan/sanitizer_common/sanitizer_malloc_mac.inc b/lib/libtsan/sanitizer_common/sanitizer_malloc_mac.inc index 6343eb284a..be27584f20 100644 --- a/lib/libtsan/sanitizer_common/sanitizer_malloc_mac.inc +++ b/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); diff --git a/lib/libtsan/sanitizer_common/sanitizer_platform.h b/lib/libtsan/sanitizer_common/sanitizer_platform.h index 57966403c9..196c0a9884 100644 --- a/lib/libtsan/sanitizer_common/sanitizer_platform.h +++ b/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 diff --git a/lib/libtsan/sanitizer_common/sanitizer_platform_interceptors.h b/lib/libtsan/sanitizer_common/sanitizer_platform_interceptors.h index febd233bb1..29987decdf 100644 --- a/lib/libtsan/sanitizer_common/sanitizer_platform_interceptors.h +++ b/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: diff --git a/lib/libtsan/sanitizer_common/sanitizer_platform_limits_freebsd.cpp b/lib/libtsan/sanitizer_common/sanitizer_platform_limits_freebsd.cpp index dd8d40eac0..c4fa1e3c1f 100644 --- a/lib/libtsan/sanitizer_common/sanitizer_platform_limits_freebsd.cpp +++ b/lib/libtsan/sanitizer_common/sanitizer_platform_limits_freebsd.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -81,10 +82,6 @@ #include #include -#define _KERNEL // to declare 'shminfo' structure -#include -#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; diff --git a/lib/libtsan/sanitizer_common/sanitizer_platform_limits_freebsd.h b/lib/libtsan/sanitizer_common/sanitizer_platform_limits_freebsd.h index cc6558f724..1cbb40e0b2 100644 --- a/lib/libtsan/sanitizer_common/sanitizer_platform_limits_freebsd.h +++ b/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; diff --git a/lib/libtsan/sanitizer_common/sanitizer_platform_limits_posix.cpp b/lib/libtsan/sanitizer_common/sanitizer_platform_limits_posix.cpp index b3e717591d..7a89bf1c74 100644 --- a/lib/libtsan/sanitizer_common/sanitizer_platform_limits_posix.cpp +++ b/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 #include #include -#if !SANITIZER_APPLE +#if !SANITIZER_APPLE && !SANITIZER_HAIKU #include #endif @@ -61,7 +61,9 @@ #endif #if !SANITIZER_ANDROID +#if !SANITIZER_HAIKU #include +#endif #include #include #endif @@ -111,9 +113,11 @@ typedef struct user_fpregs elf_fpregset_t; #if !SANITIZER_ANDROID #include +#if !SANITIZER_HAIKU #include #include #endif +#endif #if SANITIZER_LINUX #if SANITIZER_GLIBC @@ -163,7 +167,7 @@ typedef struct user_fpregs elf_fpregset_t; #include #include #include -#else +#elif !SANITIZER_HAIKU #include #endif // SANITIZER_LINUX @@ -173,6 +177,11 @@ typedef struct user_fpregs elf_fpregset_t; #include #endif +#if SANITIZER_HAIKU +#include +#include +#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); diff --git a/lib/libtsan/sanitizer_common/sanitizer_platform_limits_posix.h b/lib/libtsan/sanitizer_common/sanitizer_platform_limits_posix.h index 005ff27624..a2b6c37d54 100644 --- a/lib/libtsan/sanitizer_common/sanitizer_platform_limits_posix.h +++ b/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 +#if SANITIZER_LINUX || SANITIZER_APPLE || SANITIZER_HAIKU -#include "sanitizer_internal_defs.h" -#include "sanitizer_platform.h" -#include "sanitizer_mallinfo.h" +# include "sanitizer_internal_defs.h" +# include "sanitizer_mallinfo.h" +# include "sanitizer_platform.h" -#if SANITIZER_APPLE -#include -#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_APPLE +# include +# 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_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) +# 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__) +# 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 diff --git a/lib/libtsan/sanitizer_common/sanitizer_procmaps.h b/lib/libtsan/sanitizer_common/sanitizer_procmaps.h index bf3c2c28e3..d713ddf847 100644 --- a/lib/libtsan/sanitizer_common/sanitizer_procmaps.h +++ b/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" diff --git a/lib/libtsan/sanitizer_common/sanitizer_procmaps_haiku.cpp b/lib/libtsan/sanitizer_common/sanitizer_procmaps_haiku.cpp new file mode 100644 index 0000000000..7a6062a571 --- /dev/null +++ b/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 + +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 *modules) { + Reset(); + InternalMmapVector module_name(kMaxPathLength); + MemoryMappedSegment segment(module_name.data(), module_name.size()); + for (uptr i = 0; Next(&segment); i++) { + const char *cur_name = segment.filename; + if (cur_name[0] == '\0') + continue; + // Don't subtract 'cur_beg' from the first entry: + // * If a binary is compiled w/o -pie, then the first entry in + // process maps is likely the binary itself (all dynamic libs + // are mapped higher in address space). For such a binary, + // instruction offset in binary coincides with the actual + // instruction address in virtual memory (as code section + // is mapped to a fixed memory range). + // * If a binary is compiled with -pie, all the modules are + // mapped high at address space (in particular, higher than + // shadow memory of the tool), so the module can't be the + // first entry. + uptr base_address = (i ? segment.start : 0) - segment.offset; + LoadedModule cur_module; + cur_module.set(cur_name, base_address); + segment.AddAddressRanges(&cur_module); + modules->push_back(cur_module); + } +} + +void GetMemoryProfile(fill_profile_f cb, uptr *stats) {} + +} // namespace __sanitizer + +#endif diff --git a/lib/libtsan/sanitizer_common/sanitizer_procmaps_mac.cpp b/lib/libtsan/sanitizer_common/sanitizer_procmaps_mac.cpp index 5ff8d18325..a9533d6fc0 100644 --- a/lib/libtsan/sanitizer_common/sanitizer_procmaps_mac.cpp +++ b/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) { diff --git a/lib/libtsan/sanitizer_common/sanitizer_procmaps_solaris.cpp b/lib/libtsan/sanitizer_common/sanitizer_procmaps_solaris.cpp index 80b8158f43..452b30308b 100644 --- a/lib/libtsan/sanitizer_common/sanitizer_procmaps_solaris.cpp +++ b/lib/libtsan/sanitizer_common/sanitizer_procmaps_solaris.cpp @@ -9,9 +9,6 @@ // Information about the process mappings (Solaris-specific parts). //===----------------------------------------------------------------------===// -// Before Solaris 11.4, 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 diff --git a/lib/libtsan/sanitizer_common/sanitizer_redefine_builtins.h b/lib/libtsan/sanitizer_common/sanitizer_redefine_builtins.h index 41e0613d6f..bda0f04687 100644 --- a/lib/libtsan/sanitizer_common/sanitizer_redefine_builtins.h +++ b/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 diff --git a/lib/libtsan/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp b/lib/libtsan/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp index 58d17d90c3..24929b8c4b 100644 --- a/lib/libtsan/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp +++ b/lib/libtsan/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp @@ -38,25 +38,28 @@ # include #endif #include // for user_regs_struct -#if SANITIZER_ANDROID && SANITIZER_MIPS -# include // for mips SP register in sys/user.h -#endif -#include // for signal-related stuff +# if SANITIZER_MIPS +// clang-format off +# include // must be included before +# include // for mips SP register +// clang-format on +# endif +# include // for signal-related stuff -#ifdef sa_handler -# undef sa_handler -#endif +# ifdef sa_handler +# undef sa_handler +# endif -#ifdef sa_sigaction -# undef sa_sigaction -#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" +# 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; diff --git a/lib/libtsan/sanitizer_common/sanitizer_stoptheworld_win.cpp b/lib/libtsan/sanitizer_common/sanitizer_stoptheworld_win.cpp index f114acea79..fa15f8a9f0 100644 --- a/lib/libtsan/sanitizer_common/sanitizer_stoptheworld_win.cpp +++ b/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 diff --git a/lib/libtsan/sanitizer_common/sanitizer_symbolizer_libcdep.cpp b/lib/libtsan/sanitizer_common/sanitizer_symbolizer_libcdep.cpp index 74458028ae..565701c85d 100644 --- a/lib/libtsan/sanitizer_common/sanitizer_symbolizer_libcdep.cpp +++ b/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(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(); diff --git a/lib/libtsan/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp b/lib/libtsan/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp index 0ddc24802d..f8d821e125 100644 --- a/lib/libtsan/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp +++ b/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(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 addr2line_pool_; - static const uptr dummy_address_ = - FIRST_32_SECOND_64(UINT32_MAX, UINT64_MAX); + InternalMmapVector 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 *list, @@ -492,17 +504,17 @@ static void ChooseSymbolizerTools(IntrusiveList *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 list; list.clear(); ChooseSymbolizerTools(&list, &symbolizer_allocator_); - return new(symbolizer_allocator_) Symbolizer(list); + return new (symbolizer_allocator_) Symbolizer(list); } void Symbolizer::LateInitialize() { diff --git a/lib/libtsan/sanitizer_common/sanitizer_unwind_linux_libcdep.cpp b/lib/libtsan/sanitizer_common/sanitizer_unwind_linux_libcdep.cpp index 6a8e82e2e2..4f1538eeb9 100644 --- a/lib/libtsan/sanitizer_common/sanitizer_unwind_linux_libcdep.cpp +++ b/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 diff --git a/lib/libtsan/sanitizer_common/sanitizer_unwind_win.cpp b/lib/libtsan/sanitizer_common/sanitizer_unwind_win.cpp index 6fc18396ca..30ba812afc 100644 --- a/lib/libtsan/sanitizer_common/sanitizer_unwind_win.cpp +++ b/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; diff --git a/lib/libtsan/sanitizer_common/sanitizer_win.cpp b/lib/libtsan/sanitizer_common/sanitizer_win.cpp index fd0f989ee3..48ebe78c40 100644 --- a/lib/libtsan/sanitizer_common/sanitizer_win.cpp +++ b/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; diff --git a/lib/libtsan/tsan_interceptors_posix.cpp b/lib/libtsan/tsan_interceptors_posix.cpp index f671c8167a..14b25a8995 100644 --- a/lib/libtsan/tsan_interceptors_posix.cpp +++ b/lib/libtsan/tsan_interceptors_posix.cpp @@ -12,6 +12,9 @@ // sanitizer_common/sanitizer_common_interceptors.inc //===----------------------------------------------------------------------===// +#include + +#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_platform.h" -#include "tsan_suppressions.h" -#include "tsan_rtl.h" #include "tsan_mman.h" -#include "tsan_fd.h" - -#include +#include "tsan_platform.h" +#include "tsan_rtl.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); diff --git a/lib/libtsan/tsan_interface_java.cpp b/lib/libtsan/tsan_interface_java.cpp index 7c15a16388..cb4d767d90 100644 --- a/lib/libtsan/tsan_interface_java.cpp +++ b/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). diff --git a/lib/libtsan/tsan_malloc_mac.cpp b/lib/libtsan/tsan_malloc_mac.cpp index e973be963e..9d097806fa 100644 --- a/lib/libtsan/tsan_malloc_mac.cpp +++ b/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 diff --git a/lib/libtsan/tsan_platform.h b/lib/libtsan/tsan_platform.h index 377f8aeb8d..ada594bc11 100644 --- a/lib/libtsan/tsan_platform.h +++ b/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(arg); # elif defined(__loongarch_lp64) return Func::template Apply(arg); +# elif SANITIZER_RISCV64 + return Func::template Apply(arg); # elif SANITIZER_WINDOWS return Func::template Apply(arg); # else @@ -798,6 +827,7 @@ void ForEachMapping() { Func::template Apply(); Func::template Apply(); Func::template Apply(); + Func::template Apply(); Func::template Apply(); } @@ -901,7 +931,7 @@ bool IsAppMem(uptr mem) { return SelectMapping(mem); } struct IsShadowMemImpl { template 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 static bool Apply(uptr mem) { - return mem >= Mapping::kMetaShadowBeg && mem <= Mapping::kMetaShadowEnd; + return mem >= Mapping::kMetaShadowBeg && mem < Mapping::kMetaShadowEnd; } }; diff --git a/lib/libtsan/tsan_platform_linux.cpp b/lib/libtsan/tsan_platform_linux.cpp index 3e08a1bece..2c55645a15 100644 --- a/lib/libtsan/tsan_platform_linux.cpp +++ b/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 diff --git a/lib/libtsan/tsan_rtl.cpp b/lib/libtsan/tsan_rtl.cpp index c83efec8ea..0d7247a56a 100644 --- a/lib/libtsan/tsan_rtl.cpp +++ b/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) diff --git a/lib/libtsan/tsan_rtl.h b/lib/libtsan/tsan_rtl.h index 49bee9c67d..dc32980e90 100644 --- a/lib/libtsan/tsan_rtl.h +++ b/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; }; diff --git a/lib/libtsan/tsan_rtl_access.cpp b/lib/libtsan/tsan_rtl_access.cpp index cf07686d96..487fa49063 100644 --- a/lib/libtsan/tsan_rtl_access.cpp +++ b/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(p) % kAlign, 0); DCHECK_EQ(reinterpret_cast(end) % kAlign, 0); @@ -569,6 +569,7 @@ static void MemoryRangeSet(uptr addr, uptr size, RawShadow val) { RawShadow* mid1 = Min(end, reinterpret_cast(RoundUp( reinterpret_cast(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( - reinterpret_cast(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 diff --git a/lib/libtsan/tsan_rtl_report.cpp b/lib/libtsan/tsan_rtl_report.cpp index 51a98e2f2d..0820bf1ade 100644 --- a/lib/libtsan/tsan_rtl_report.cpp +++ b/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 } diff --git a/lib/libtsan/tsan_sync.cpp b/lib/libtsan/tsan_sync.cpp index 09d41780d1..be5829bc82 100644 --- a/lib/libtsan/tsan_sync.cpp +++ b/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; diff --git a/lib/libtsan/ubsan/ubsan_platform.h b/lib/libtsan/ubsan/ubsan_platform.h index d2cc2e10bd..c7eb1a967e 100644 --- a/lib/libtsan/ubsan/ubsan_platform.h +++ b/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 diff --git a/src/libs/libtsan.zig b/src/libs/libtsan.zig index 41fc82617a..7a72ae2ac3 100644 --- a/src/libs/libtsan.zig +++ b/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",