mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 05:44:20 +00:00
libtsan: update to LLVM 21
This commit is contained in:
parent
85438e75e0
commit
ac20506090
58 changed files with 1891 additions and 835 deletions
57
lib/libtsan/builtins/assembly.h
vendored
57
lib/libtsan/builtins/assembly.h
vendored
|
|
@ -61,7 +61,7 @@
|
||||||
#define LOCAL_LABEL(name) .L ## name
|
#define LOCAL_LABEL(name) .L ## name
|
||||||
#define FILE_LEVEL_DIRECTIVE
|
#define FILE_LEVEL_DIRECTIVE
|
||||||
#define SYMBOL_IS_FUNC(name) \
|
#define SYMBOL_IS_FUNC(name) \
|
||||||
.def name SEPARATOR \
|
.def FUNC_SYMBOL(name) SEPARATOR \
|
||||||
.scl 2 SEPARATOR \
|
.scl 2 SEPARATOR \
|
||||||
.type 32 SEPARATOR \
|
.type 32 SEPARATOR \
|
||||||
.endef
|
.endef
|
||||||
|
|
@ -71,7 +71,7 @@
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__arm__) || defined(__aarch64__)
|
#if defined(__arm__) || defined(__aarch64__) || defined(__arm64ec__)
|
||||||
#define FUNC_ALIGN \
|
#define FUNC_ALIGN \
|
||||||
.text SEPARATOR \
|
.text SEPARATOR \
|
||||||
.balign 16 SEPARATOR
|
.balign 16 SEPARATOR
|
||||||
|
|
@ -194,6 +194,23 @@
|
||||||
#else
|
#else
|
||||||
#define WIDE(op) op
|
#define WIDE(op) op
|
||||||
#endif
|
#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)
|
#else // !defined(__arm)
|
||||||
#define DECLARE_FUNC_ENCODING
|
#define DECLARE_FUNC_ENCODING
|
||||||
#define DEFINE_CODE_STATE
|
#define DEFINE_CODE_STATE
|
||||||
|
|
@ -208,6 +225,16 @@
|
||||||
#define GLUE4(a, b, c, d) GLUE4_(a, b, c, d)
|
#define GLUE4(a, b, c, d) GLUE4_(a, b, c, d)
|
||||||
|
|
||||||
#define SYMBOL_NAME(name) GLUE(__USER_LABEL_PREFIX__, name)
|
#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
|
#ifdef VISIBILITY_HIDDEN
|
||||||
#define DECLARE_SYMBOL_VISIBILITY(name) \
|
#define DECLARE_SYMBOL_VISIBILITY(name) \
|
||||||
|
|
@ -222,54 +249,54 @@
|
||||||
#define DEFINE_COMPILERRT_FUNCTION(name) \
|
#define DEFINE_COMPILERRT_FUNCTION(name) \
|
||||||
DEFINE_CODE_STATE \
|
DEFINE_CODE_STATE \
|
||||||
FILE_LEVEL_DIRECTIVE SEPARATOR \
|
FILE_LEVEL_DIRECTIVE SEPARATOR \
|
||||||
.globl SYMBOL_NAME(name) SEPARATOR \
|
.globl FUNC_SYMBOL(SYMBOL_NAME(name)) SEPARATOR \
|
||||||
SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
|
SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
|
||||||
DECLARE_SYMBOL_VISIBILITY(name) \
|
DECLARE_SYMBOL_VISIBILITY(name) \
|
||||||
DECLARE_FUNC_ENCODING \
|
DECLARE_FUNC_ENCODING \
|
||||||
SYMBOL_NAME(name):
|
FUNC_SYMBOL(SYMBOL_NAME(name)):
|
||||||
|
|
||||||
#define DEFINE_COMPILERRT_THUMB_FUNCTION(name) \
|
#define DEFINE_COMPILERRT_THUMB_FUNCTION(name) \
|
||||||
DEFINE_CODE_STATE \
|
DEFINE_CODE_STATE \
|
||||||
FILE_LEVEL_DIRECTIVE SEPARATOR \
|
FILE_LEVEL_DIRECTIVE SEPARATOR \
|
||||||
.globl SYMBOL_NAME(name) SEPARATOR \
|
.globl FUNC_SYMBOL(SYMBOL_NAME(name)) SEPARATOR \
|
||||||
SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
|
SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
|
||||||
DECLARE_SYMBOL_VISIBILITY(name) SEPARATOR \
|
DECLARE_SYMBOL_VISIBILITY(name) SEPARATOR \
|
||||||
.thumb_func SEPARATOR \
|
.thumb_func SEPARATOR \
|
||||||
SYMBOL_NAME(name):
|
FUNC_SYMBOL(SYMBOL_NAME(name)):
|
||||||
|
|
||||||
#define DEFINE_COMPILERRT_PRIVATE_FUNCTION(name) \
|
#define DEFINE_COMPILERRT_PRIVATE_FUNCTION(name) \
|
||||||
DEFINE_CODE_STATE \
|
DEFINE_CODE_STATE \
|
||||||
FILE_LEVEL_DIRECTIVE SEPARATOR \
|
FILE_LEVEL_DIRECTIVE SEPARATOR \
|
||||||
.globl SYMBOL_NAME(name) SEPARATOR \
|
.globl FUNC_SYMBOL(SYMBOL_NAME(name)) SEPARATOR \
|
||||||
SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
|
SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
|
||||||
HIDDEN(SYMBOL_NAME(name)) SEPARATOR \
|
HIDDEN(SYMBOL_NAME(name)) SEPARATOR \
|
||||||
DECLARE_FUNC_ENCODING \
|
DECLARE_FUNC_ENCODING \
|
||||||
SYMBOL_NAME(name):
|
FUNC_SYMBOL(SYMBOL_NAME(name)):
|
||||||
|
|
||||||
#define DEFINE_COMPILERRT_PRIVATE_FUNCTION_UNMANGLED(name) \
|
#define DEFINE_COMPILERRT_PRIVATE_FUNCTION_UNMANGLED(name) \
|
||||||
DEFINE_CODE_STATE \
|
DEFINE_CODE_STATE \
|
||||||
.globl name SEPARATOR \
|
.globl FUNC_SYMBOL(name) SEPARATOR \
|
||||||
SYMBOL_IS_FUNC(name) SEPARATOR \
|
SYMBOL_IS_FUNC(name) SEPARATOR \
|
||||||
HIDDEN(name) SEPARATOR \
|
HIDDEN(name) SEPARATOR \
|
||||||
DECLARE_FUNC_ENCODING \
|
DECLARE_FUNC_ENCODING \
|
||||||
name:
|
FUNC_SYMBOL(name):
|
||||||
|
|
||||||
#define DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(name) \
|
#define DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(name) \
|
||||||
DEFINE_CODE_STATE \
|
DEFINE_CODE_STATE \
|
||||||
FUNC_ALIGN \
|
FUNC_ALIGN \
|
||||||
.globl name SEPARATOR \
|
.globl FUNC_SYMBOL(name) SEPARATOR \
|
||||||
SYMBOL_IS_FUNC(name) SEPARATOR \
|
SYMBOL_IS_FUNC(name) SEPARATOR \
|
||||||
DECLARE_SYMBOL_VISIBILITY_UNMANGLED(name) SEPARATOR \
|
DECLARE_SYMBOL_VISIBILITY_UNMANGLED(FUNC_SYMBOL(name)) SEPARATOR \
|
||||||
DECLARE_FUNC_ENCODING \
|
DECLARE_FUNC_ENCODING \
|
||||||
name: \
|
FUNC_SYMBOL(name): \
|
||||||
SEPARATOR CFI_START \
|
SEPARATOR CFI_START \
|
||||||
SEPARATOR BTI_C
|
SEPARATOR BTI_C
|
||||||
|
|
||||||
#define DEFINE_COMPILERRT_FUNCTION_ALIAS(name, target) \
|
#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 \
|
SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
|
||||||
DECLARE_SYMBOL_VISIBILITY(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__)
|
#if defined(__ARM_EABI__)
|
||||||
#define DEFINE_AEABI_FUNCTION_ALIAS(aeabi_name, name) \
|
#define DEFINE_AEABI_FUNCTION_ALIAS(aeabi_name, name) \
|
||||||
|
|
|
||||||
27
lib/libtsan/interception/interception.h
vendored
27
lib/libtsan/interception/interception.h
vendored
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
#if !SANITIZER_LINUX && !SANITIZER_FREEBSD && !SANITIZER_APPLE && \
|
#if !SANITIZER_LINUX && !SANITIZER_FREEBSD && !SANITIZER_APPLE && \
|
||||||
!SANITIZER_NETBSD && !SANITIZER_WINDOWS && !SANITIZER_FUCHSIA && \
|
!SANITIZER_NETBSD && !SANITIZER_WINDOWS && !SANITIZER_FUCHSIA && \
|
||||||
!SANITIZER_SOLARIS
|
!SANITIZER_SOLARIS && !SANITIZER_HAIKU && !SANITIZER_AIX
|
||||||
# error "Interception doesn't work on this operating system."
|
# error "Interception doesn't work on this operating system."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -168,6 +168,16 @@ const interpose_substitution substitution_##func_name[] \
|
||||||
extern "C" ret_type func(__VA_ARGS__);
|
extern "C" ret_type func(__VA_ARGS__);
|
||||||
# define DECLARE_WRAPPER_WINAPI(ret_type, func, ...) \
|
# define DECLARE_WRAPPER_WINAPI(ret_type, func, ...) \
|
||||||
extern "C" __declspec(dllimport) ret_type __stdcall func(__VA_ARGS__);
|
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
|
#elif !SANITIZER_FUCHSIA // LINUX, FREEBSD, NETBSD, SOLARIS
|
||||||
# define INTERCEPTOR_ATTRIBUTE __attribute__((visibility("default")))
|
# define INTERCEPTOR_ATTRIBUTE __attribute__((visibility("default")))
|
||||||
# if ASM_INTERCEPTOR_TRAMPOLINE_SUPPORT
|
# if ASM_INTERCEPTOR_TRAMPOLINE_SUPPORT
|
||||||
|
|
@ -367,12 +377,17 @@ inline void DoesNotSupportStaticLinking() {}
|
||||||
|
|
||||||
#define INCLUDED_FROM_INTERCEPTION_LIB
|
#define INCLUDED_FROM_INTERCEPTION_LIB
|
||||||
|
|
||||||
#if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \
|
#if SANITIZER_AIX
|
||||||
SANITIZER_SOLARIS
|
# 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"
|
#elif SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \
|
||||||
# define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func)
|
SANITIZER_SOLARIS || SANITIZER_HAIKU
|
||||||
# define INTERCEPT_FUNCTION_VER(func, symver) \
|
|
||||||
|
# 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)
|
INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver)
|
||||||
#elif SANITIZER_APPLE
|
#elif SANITIZER_APPLE
|
||||||
# include "interception_mac.h"
|
# include "interception_mac.h"
|
||||||
|
|
|
||||||
45
lib/libtsan/interception/interception_aix.cpp
vendored
Normal file
45
lib/libtsan/interception/interception_aix.cpp
vendored
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
//===-- interception_aix.cpp ------------------------------------*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This file is a part of AddressSanitizer, an address sanity checker.
|
||||||
|
//
|
||||||
|
// AIX-specific interception methods.
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "interception.h"
|
||||||
|
#include "sanitizer_common/sanitizer_common.h"
|
||||||
|
|
||||||
|
#if SANITIZER_AIX
|
||||||
|
|
||||||
|
# include <dlfcn.h> // for dlsym()
|
||||||
|
|
||||||
|
namespace __interception {
|
||||||
|
|
||||||
|
static void *GetFuncAddr(const char *name, uptr wrapper_addr) {
|
||||||
|
// AIX dlsym can only defect the functions that are exported, so
|
||||||
|
// on AIX, we can not intercept some basic functions like memcpy.
|
||||||
|
// FIXME: if we are going to ship dynamic asan library, we may need to search
|
||||||
|
// all the loaded modules with RTLD_DEFAULT if RTLD_NEXT failed.
|
||||||
|
void *addr = dlsym(RTLD_NEXT, name);
|
||||||
|
|
||||||
|
// In case `name' is not loaded, dlsym ends up finding the actual wrapper.
|
||||||
|
// We don't want to intercept the wrapper and have it point to itself.
|
||||||
|
if ((uptr)addr == wrapper_addr)
|
||||||
|
addr = nullptr;
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InterceptFunction(const char *name, uptr *ptr_to_real, uptr func,
|
||||||
|
uptr wrapper) {
|
||||||
|
void *addr = GetFuncAddr(name, wrapper);
|
||||||
|
*ptr_to_real = (uptr)addr;
|
||||||
|
return addr && (func == wrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace __interception
|
||||||
|
#endif // SANITIZER_AIX
|
||||||
36
lib/libtsan/interception/interception_aix.h
vendored
Normal file
36
lib/libtsan/interception/interception_aix.h
vendored
Normal file
|
|
@ -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
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
#include "interception.h"
|
#include "interception.h"
|
||||||
|
|
||||||
#if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \
|
#if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \
|
||||||
SANITIZER_SOLARIS
|
SANITIZER_SOLARIS || SANITIZER_HAIKU
|
||||||
|
|
||||||
#include <dlfcn.h> // for dlsym() and dlvsym()
|
#include <dlfcn.h> // for dlsym() and dlvsym()
|
||||||
|
|
||||||
|
|
@ -80,4 +80,4 @@ bool InterceptFunction(const char *name, const char *ver, uptr *ptr_to_real,
|
||||||
} // namespace __interception
|
} // namespace __interception
|
||||||
|
|
||||||
#endif // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD ||
|
#endif // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD ||
|
||||||
// SANITIZER_SOLARIS
|
// SANITIZER_SOLARIS || SANITIZER_HAIKU
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \
|
#if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \
|
||||||
SANITIZER_SOLARIS
|
SANITIZER_SOLARIS || SANITIZER_HAIKU
|
||||||
|
|
||||||
#if !defined(INCLUDED_FROM_INTERCEPTION_LIB)
|
#if !defined(INCLUDED_FROM_INTERCEPTION_LIB)
|
||||||
# error interception_linux.h should be included from interception library only
|
# 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 // INTERCEPTION_LINUX_H
|
||||||
#endif // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD ||
|
#endif // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD ||
|
||||||
// SANITIZER_SOLARIS
|
// SANITIZER_SOLARIS || SANITIZER_HAIKU
|
||||||
|
|
|
||||||
|
|
@ -646,6 +646,7 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
|
||||||
case 0xC033: // 33 C0 : xor eax, eax
|
case 0xC033: // 33 C0 : xor eax, eax
|
||||||
case 0xC933: // 33 C9 : xor ecx, ecx
|
case 0xC933: // 33 C9 : xor ecx, ecx
|
||||||
case 0xD233: // 33 D2 : xor edx, edx
|
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 0xDB84: // 84 DB : test bl,bl
|
||||||
case 0xC084: // 84 C0 : test al,al
|
case 0xC084: // 84 C0 : test al,al
|
||||||
case 0xC984: // 84 C9 : test cl,cl
|
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 0x5541: // push r13
|
||||||
case 0x5641: // push r14
|
case 0x5641: // push r14
|
||||||
case 0x5741: // push r15
|
case 0x5741: // push r15
|
||||||
case 0x9066: // Two-byte NOP
|
|
||||||
case 0xc084: // test al, al
|
case 0xc084: // test al, al
|
||||||
case 0x018a: // mov al, byte ptr [rcx]
|
case 0x018a: // mov al, byte ptr [rcx]
|
||||||
return 2;
|
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]
|
case 0x058B: // 8B 05 XX XX XX XX : mov eax, dword ptr [XX XX XX XX]
|
||||||
if (rel_offset)
|
if (rel_offset)
|
||||||
*rel_offset = 2;
|
*rel_offset = 2;
|
||||||
|
FALLTHROUGH;
|
||||||
case 0xB841: // 41 B8 XX XX XX XX : mov r8d, XX XX XX XX
|
case 0xB841: // 41 B8 XX XX XX XX : mov r8d, XX XX XX XX
|
||||||
return 6;
|
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 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
|
case 0x7981: // 81 79 YY XX XX XX XX cmp dword ptr [rcx+YY], XX XX XX XX
|
||||||
return 7;
|
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) {
|
switch (0x00FFFFFF & *(u32 *)address) {
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ namespace __sanitizer {
|
||||||
typedef CompactSizeClassMap InternalSizeClassMap;
|
typedef CompactSizeClassMap InternalSizeClassMap;
|
||||||
|
|
||||||
struct AP32 {
|
struct AP32 {
|
||||||
static const uptr kSpaceBeg = 0;
|
static const uptr kSpaceBeg = SANITIZER_MMAP_BEGIN;
|
||||||
static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE;
|
static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE;
|
||||||
static const uptr kMetadataSize = 0;
|
static const uptr kMetadataSize = 0;
|
||||||
typedef InternalSizeClassMap SizeClassMap;
|
typedef InternalSizeClassMap SizeClassMap;
|
||||||
|
|
|
||||||
|
|
@ -166,7 +166,7 @@ struct SizeClassAllocator32LocalCache {
|
||||||
DCHECK_GT(c->count, 0);
|
DCHECK_GT(c->count, 0);
|
||||||
}
|
}
|
||||||
void *res = c->batch[--c->count];
|
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);
|
stats_.Add(AllocatorStatAllocated, c->class_size);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,18 @@
|
||||||
#ifndef SANITIZER_ATOMIC_CLANG_H
|
#ifndef SANITIZER_ATOMIC_CLANG_H
|
||||||
#define 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 {
|
namespace __sanitizer {
|
||||||
|
|
||||||
// We use the compiler builtin atomic operations for loads and stores, which
|
// We use the compiler builtin atomic operations for loads and stores, which
|
||||||
|
|
@ -35,6 +47,7 @@ inline void proc_yield(int cnt) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SANITIZER_IGNORE_ATOMIC_ALIGNMENT_BEGIN
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline typename T::Type atomic_load(const volatile T *a, memory_order mo) {
|
inline typename T::Type atomic_load(const volatile T *a, memory_order mo) {
|
||||||
DCHECK(mo == memory_order_relaxed || mo == memory_order_consume ||
|
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);
|
return atomic_compare_exchange_strong(a, cmp, xchg, mo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SANITIZER_IGNORE_ATOMIC_ALIGNMENT_END
|
||||||
|
|
||||||
} // namespace __sanitizer
|
} // namespace __sanitizer
|
||||||
|
|
||||||
#undef ATOMIC_ORDER
|
#undef ATOMIC_ORDER
|
||||||
|
|
|
||||||
21
lib/libtsan/sanitizer_common/sanitizer_common.h
vendored
21
lib/libtsan/sanitizer_common/sanitizer_common.h
vendored
|
|
@ -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.
|
// Used to check if we can map shadow memory to a fixed location.
|
||||||
bool MemoryRangeIsAvailable(uptr range_start, uptr range_end);
|
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.
|
// the provided range does not contain at least one entire page.
|
||||||
void ReleaseMemoryPagesToOS(uptr beg, uptr end);
|
void ReleaseMemoryPagesToOS(uptr beg, uptr end);
|
||||||
void IncreaseTotalMmap(uptr size);
|
void IncreaseTotalMmap(uptr size);
|
||||||
|
|
@ -925,12 +925,6 @@ class ListOfModules {
|
||||||
// Callback type for iterating over a set of memory ranges.
|
// Callback type for iterating over a set of memory ranges.
|
||||||
typedef void (*RangeIteratorCallback)(uptr begin, uptr end, void *arg);
|
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);
|
void WriteToSyslog(const char *buffer);
|
||||||
|
|
||||||
#if defined(SANITIZER_WINDOWS) && defined(_MSC_VER) && !defined(__clang__)
|
#if defined(SANITIZER_WINDOWS) && defined(_MSC_VER) && !defined(__clang__)
|
||||||
|
|
@ -963,19 +957,8 @@ inline void AndroidLogInit() {}
|
||||||
inline void SetAbortMessage(const char *) {}
|
inline void SetAbortMessage(const char *) {}
|
||||||
#endif
|
#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() {
|
inline uptr GetPthreadDestructorIterations() {
|
||||||
#if SANITIZER_ANDROID
|
#if SANITIZER_POSIX
|
||||||
return (AndroidGetApiLevel() == ANDROID_LOLLIPOP_MR1) ? 8 : 4;
|
|
||||||
#elif SANITIZER_POSIX
|
|
||||||
return 4;
|
return 4;
|
||||||
#else
|
#else
|
||||||
// Unused on Windows.
|
// Unused on Windows.
|
||||||
|
|
|
||||||
|
|
@ -481,7 +481,8 @@ INTERCEPTOR(char*, textdomain, const char *domainname) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SANITIZER_INTERCEPT_STRCMP || SANITIZER_INTERCEPT_MEMCMP
|
#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;
|
return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -953,7 +954,7 @@ INTERCEPTOR(double, frexp, double x, int *exp) {
|
||||||
#define INIT_FREXP
|
#define INIT_FREXP
|
||||||
#endif // SANITIZER_INTERCEPT_FREXP
|
#endif // SANITIZER_INTERCEPT_FREXP
|
||||||
|
|
||||||
#if SANITIZER_INTERCEPT_FREXPF_FREXPL
|
#if SANITIZER_INTERCEPT_FREXPF
|
||||||
INTERCEPTOR(float, frexpf, float x, int *exp) {
|
INTERCEPTOR(float, frexpf, float x, int *exp) {
|
||||||
void *ctx;
|
void *ctx;
|
||||||
COMMON_INTERCEPTOR_ENTER(ctx, frexpf, x, exp);
|
COMMON_INTERCEPTOR_ENTER(ctx, frexpf, x, exp);
|
||||||
|
|
@ -963,6 +964,12 @@ INTERCEPTOR(float, frexpf, float x, int *exp) {
|
||||||
return res;
|
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) {
|
INTERCEPTOR(long double, frexpl, long double x, int *exp) {
|
||||||
void *ctx;
|
void *ctx;
|
||||||
COMMON_INTERCEPTOR_ENTER(ctx, frexpl, x, exp);
|
COMMON_INTERCEPTOR_ENTER(ctx, frexpl, x, exp);
|
||||||
|
|
@ -972,12 +979,10 @@ INTERCEPTOR(long double, frexpl, long double x, int *exp) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define INIT_FREXPF_FREXPL \
|
# define INIT_FREXPL COMMON_INTERCEPT_FUNCTION_LDBL(frexpl)
|
||||||
COMMON_INTERCEPT_FUNCTION(frexpf); \
|
|
||||||
COMMON_INTERCEPT_FUNCTION_LDBL(frexpl)
|
|
||||||
#else
|
#else
|
||||||
#define INIT_FREXPF_FREXPL
|
# define INIT_FREXPL
|
||||||
#endif // SANITIZER_INTERCEPT_FREXPF_FREXPL
|
#endif
|
||||||
|
|
||||||
#if SI_POSIX
|
#if SI_POSIX
|
||||||
static void write_iovec(void *ctx, struct __sanitizer_iovec *iovec,
|
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
|
#if SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS
|
||||||
static void unpoison_tm(void *ctx, __sanitizer_tm *tm) {
|
static void unpoison_tm(void *ctx, __sanitizer_tm *tm) {
|
||||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tm, sizeof(*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) {
|
if (tm->tm_zone) {
|
||||||
// Can not use COMMON_INTERCEPTOR_WRITE_RANGE here, because 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.
|
// 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)
|
VSPRINTF_INTERCEPTOR_IMPL(vsprintf, str, format, ap)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
# if SANITIZER_INTERCEPT_VASPRINTF
|
||||||
INTERCEPTOR(int, vasprintf, char **strp, const char *format, va_list ap)
|
INTERCEPTOR(int, vasprintf, char **strp, const char *format, va_list ap)
|
||||||
VASPRINTF_INTERCEPTOR_IMPL(vasprintf, strp, format, 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)
|
INTERCEPTOR(int, __isoc99_vprintf, const char *format, va_list ap)
|
||||||
VPRINTF_INTERCEPTOR_IMPL(__isoc99_vprintf, format, 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)
|
FORMAT_INTERCEPTOR_IMPL(__snprintf_chk, vsnprintf, str, size, format)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
# if SANITIZER_INTERCEPT_ASPRINTF
|
||||||
INTERCEPTOR(int, asprintf, char **strp, const char *format, ...)
|
INTERCEPTOR(int, asprintf, char **strp, const char *format, ...)
|
||||||
FORMAT_INTERCEPTOR_IMPL(asprintf, vasprintf, strp, 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, ...)
|
INTERCEPTOR(int, __isoc99_printf, const char *format, ...)
|
||||||
FORMAT_INTERCEPTOR_IMPL(__isoc99_printf, __isoc99_vprintf, 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
|
#endif // SANITIZER_INTERCEPT_PRINTF
|
||||||
|
|
||||||
#if SANITIZER_INTERCEPT_PRINTF
|
#if SANITIZER_INTERCEPT_PRINTF
|
||||||
#define INIT_PRINTF \
|
# define INIT_PRINTF_COMMON \
|
||||||
COMMON_INTERCEPT_FUNCTION_LDBL(printf); \
|
COMMON_INTERCEPT_FUNCTION_LDBL(printf); \
|
||||||
COMMON_INTERCEPT_FUNCTION_LDBL(sprintf); \
|
COMMON_INTERCEPT_FUNCTION_LDBL(sprintf); \
|
||||||
COMMON_INTERCEPT_FUNCTION_LDBL(snprintf); \
|
COMMON_INTERCEPT_FUNCTION_LDBL(snprintf); \
|
||||||
COMMON_INTERCEPT_FUNCTION_LDBL(asprintf); \
|
COMMON_INTERCEPT_FUNCTION_LDBL(fprintf); \
|
||||||
COMMON_INTERCEPT_FUNCTION_LDBL(fprintf); \
|
COMMON_INTERCEPT_FUNCTION_LDBL(vprintf); \
|
||||||
COMMON_INTERCEPT_FUNCTION_LDBL(vprintf); \
|
COMMON_INTERCEPT_FUNCTION_LDBL(vsprintf); \
|
||||||
COMMON_INTERCEPT_FUNCTION_LDBL(vsprintf); \
|
COMMON_INTERCEPT_FUNCTION_LDBL(vsnprintf); \
|
||||||
COMMON_INTERCEPT_FUNCTION_LDBL(vsnprintf); \
|
COMMON_INTERCEPT_FUNCTION_LDBL(vfprintf);
|
||||||
COMMON_INTERCEPT_FUNCTION_LDBL(vasprintf); \
|
# if !SANITIZER_AIX
|
||||||
COMMON_INTERCEPT_FUNCTION_LDBL(vfprintf);
|
// 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
|
#else
|
||||||
#define INIT_PRINTF
|
#define INIT_PRINTF
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -1855,6 +1872,22 @@ FORMAT_INTERCEPTOR_IMPL(__isoc99_snprintf, __isoc99_vsnprintf, str, size,
|
||||||
#define INIT_ISOC99_PRINTF
|
#define INIT_ISOC99_PRINTF
|
||||||
#endif
|
#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
|
#if SANITIZER_INTERCEPT_IOCTL
|
||||||
#include "sanitizer_common_interceptors_ioctl.inc"
|
#include "sanitizer_common_interceptors_ioctl.inc"
|
||||||
#include "sanitizer_interceptors_ioctl_netbsd.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)) {
|
if (res != ((SIZE_T)-1)) {
|
||||||
CHECK_LE(res, sizeof(local_dest));
|
CHECK_LE(res, sizeof(local_dest));
|
||||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, res);
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, res);
|
||||||
REAL(memcpy)(dest, local_dest, res);
|
internal_memcpy(dest, local_dest, res);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
@ -3923,7 +3956,7 @@ INTERCEPTOR(int, wctomb, char *dest, wchar_t src) {
|
||||||
if (res != -1) {
|
if (res != -1) {
|
||||||
CHECK_LE(res, sizeof(local_dest));
|
CHECK_LE(res, sizeof(local_dest));
|
||||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, res);
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, res);
|
||||||
REAL(memcpy)(dest, local_dest, res);
|
internal_memcpy(dest, local_dest, res);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
@ -10263,6 +10296,71 @@ INTERCEPTOR(SSIZE_T, freadlink, int fd, char *buf, SIZE_T bufsiz) {
|
||||||
# define INIT_FREADLINK
|
# define INIT_FREADLINK
|
||||||
#endif
|
#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"
|
#include "sanitizer_common_interceptors_netbsd_compat.inc"
|
||||||
|
|
||||||
namespace __sanitizer {
|
namespace __sanitizer {
|
||||||
|
|
@ -10328,8 +10426,10 @@ static void InitializeCommonInterceptors() {
|
||||||
INIT_PRINTF;
|
INIT_PRINTF;
|
||||||
INIT_PRINTF_L;
|
INIT_PRINTF_L;
|
||||||
INIT_ISOC99_PRINTF;
|
INIT_ISOC99_PRINTF;
|
||||||
|
INIT_SETPROCTITLE;
|
||||||
INIT_FREXP;
|
INIT_FREXP;
|
||||||
INIT_FREXPF_FREXPL;
|
INIT_FREXPF;
|
||||||
|
INIT_FREXPL;
|
||||||
INIT_GETPWNAM_AND_FRIENDS;
|
INIT_GETPWNAM_AND_FRIENDS;
|
||||||
INIT_GETPWNAM_R_AND_FRIENDS;
|
INIT_GETPWNAM_R_AND_FRIENDS;
|
||||||
INIT_GETPWENT;
|
INIT_GETPWENT;
|
||||||
|
|
@ -10587,4 +10687,7 @@ static void InitializeCommonInterceptors() {
|
||||||
INIT_FREADLINK;
|
INIT_FREADLINK;
|
||||||
|
|
||||||
INIT___PRINTF_CHK;
|
INIT___PRINTF_CHK;
|
||||||
|
INIT_GETSERVENT_R;
|
||||||
|
INIT_GETSERVBYNAME_R;
|
||||||
|
INIT_GETSERVBYPORT_R;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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.
|
// Returns true if the character is an integer conversion specifier.
|
||||||
static bool format_is_integer_conv(char c) {
|
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");
|
return char_is_one_of(c, "diouxXn");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,35 +48,41 @@ static void ioctl_table_fill() {
|
||||||
++ioctl_table_size; \
|
++ioctl_table_size; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_(FIONBIO, READ, sizeof(int));
|
||||||
|
#if !SANITIZER_HAIKU
|
||||||
_(FIOASYNC, READ, sizeof(int));
|
_(FIOASYNC, READ, sizeof(int));
|
||||||
_(FIOCLEX, NONE, 0);
|
_(FIOCLEX, NONE, 0);
|
||||||
_(FIOGETOWN, WRITE, sizeof(int));
|
_(FIOGETOWN, WRITE, sizeof(int));
|
||||||
_(FIONBIO, READ, sizeof(int));
|
|
||||||
_(FIONCLEX, NONE, 0);
|
_(FIONCLEX, NONE, 0);
|
||||||
_(FIOSETOWN, READ, sizeof(int));
|
_(FIOSETOWN, READ, sizeof(int));
|
||||||
|
#endif
|
||||||
_(SIOCATMARK, WRITE, sizeof(int));
|
_(SIOCATMARK, WRITE, sizeof(int));
|
||||||
_(SIOCGIFCONF, CUSTOM, 0);
|
_(SIOCGIFCONF, CUSTOM, 0);
|
||||||
_(SIOCGPGRP, WRITE, sizeof(int));
|
_(SIOCGPGRP, WRITE, sizeof(int));
|
||||||
_(SIOCSPGRP, READ, sizeof(int));
|
_(SIOCSPGRP, READ, sizeof(int));
|
||||||
#if !SANITIZER_SOLARIS
|
#if !SANITIZER_SOLARIS && !SANITIZER_HAIKU
|
||||||
_(TIOCCONS, NONE, 0);
|
_(TIOCCONS, NONE, 0);
|
||||||
#endif
|
#endif
|
||||||
_(TIOCEXCL, NONE, 0);
|
#if !SANITIZER_HAIKU
|
||||||
_(TIOCGETD, WRITE, sizeof(int));
|
_(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);
|
_(TIOCGPGRP, WRITE, pid_t_sz);
|
||||||
_(TIOCGWINSZ, WRITE, struct_winsize_sz);
|
_(TIOCGWINSZ, WRITE, struct_winsize_sz);
|
||||||
_(TIOCMBIC, READ, sizeof(int));
|
_(TIOCMBIC, READ, sizeof(int));
|
||||||
_(TIOCMBIS, READ, sizeof(int));
|
_(TIOCMBIS, READ, sizeof(int));
|
||||||
_(TIOCMGET, WRITE, sizeof(int));
|
_(TIOCMGET, WRITE, sizeof(int));
|
||||||
_(TIOCMSET, READ, sizeof(int));
|
_(TIOCMSET, READ, sizeof(int));
|
||||||
_(TIOCNOTTY, NONE, 0);
|
|
||||||
_(TIOCNXCL, NONE, 0);
|
_(TIOCNXCL, NONE, 0);
|
||||||
_(TIOCOUTQ, WRITE, sizeof(int));
|
_(TIOCOUTQ, WRITE, sizeof(int));
|
||||||
_(TIOCPKT, READ, sizeof(int));
|
# if !SANITIZER_AIX
|
||||||
_(TIOCSCTTY, NONE, 0);
|
_(TIOCSCTTY, NONE, 0);
|
||||||
_(TIOCSETD, READ, sizeof(int));
|
# endif
|
||||||
_(TIOCSPGRP, READ, pid_t_sz);
|
_(TIOCSPGRP, READ, pid_t_sz);
|
||||||
_(TIOCSTI, READ, sizeof(char));
|
|
||||||
_(TIOCSWINSZ, READ, struct_winsize_sz);
|
_(TIOCSWINSZ, READ, struct_winsize_sz);
|
||||||
|
|
||||||
#if !SANITIZER_IOS
|
#if !SANITIZER_IOS
|
||||||
|
|
|
||||||
|
|
@ -33,11 +33,13 @@
|
||||||
|
|
||||||
// Platform-specific options.
|
// Platform-specific options.
|
||||||
#if SANITIZER_APPLE
|
#if SANITIZER_APPLE
|
||||||
#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 0
|
# define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 0
|
||||||
#elif SANITIZER_WINDOWS64
|
#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
|
#else
|
||||||
#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 1
|
# define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 1
|
||||||
#endif // SANITIZER_APPLE
|
#endif // SANITIZER_APPLE
|
||||||
|
|
||||||
#ifndef COMMON_INTERCEPTOR_MEMSET_IMPL
|
#ifndef COMMON_INTERCEPTOR_MEMSET_IMPL
|
||||||
|
|
|
||||||
|
|
@ -3205,6 +3205,28 @@ POST_SYSCALL(futex)
|
||||||
COMMON_SYSCALL_BLOCKING_END();
|
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"
|
} // extern "C"
|
||||||
|
|
||||||
# undef PRE_SYSCALL
|
# undef PRE_SYSCALL
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,8 @@
|
||||||
# define __errno_location ___errno
|
# define __errno_location ___errno
|
||||||
#elif SANITIZER_WINDOWS
|
#elif SANITIZER_WINDOWS
|
||||||
# define __errno_location _errno
|
# define __errno_location _errno
|
||||||
|
#elif SANITIZER_HAIKU
|
||||||
|
# define __errno_location _errnop
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern "C" int *__errno_location();
|
extern "C" int *__errno_location();
|
||||||
|
|
|
||||||
|
|
@ -21,12 +21,21 @@
|
||||||
|
|
||||||
namespace __sanitizer {
|
namespace __sanitizer {
|
||||||
|
|
||||||
#define errno_ENOMEM 12
|
#ifdef __HAIKU__
|
||||||
#define errno_EBUSY 16
|
# define errno_ENOMEM (0x80000000)
|
||||||
#define errno_EINVAL 22
|
# define errno_EBUSY (0x80000000 + 14)
|
||||||
#define errno_ERANGE 34
|
# define errno_EINVAL (0x80000000 + 5)
|
||||||
#define errno_ENAMETOOLONG 36
|
# define errno_ERANGE (0x80007000 + 17)
|
||||||
#define errno_ENOSYS 38
|
# 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.
|
// Those might not present or their value differ on different platforms.
|
||||||
extern const int errno_EOWNERDEAD;
|
extern const int errno_EOWNERDEAD;
|
||||||
|
|
|
||||||
70
lib/libtsan/sanitizer_common/sanitizer_file.cpp
vendored
70
lib/libtsan/sanitizer_common/sanitizer_file.cpp
vendored
|
|
@ -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) {
|
void ReportFile::SetReportPath(const char *path) {
|
||||||
if (path) {
|
if (path) {
|
||||||
uptr len = internal_strlen(path);
|
uptr len = internal_strlen(path);
|
||||||
if (len > sizeof(path_prefix) - 100) {
|
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],
|
const char *message = "ERROR: Path is too long: ";
|
||||||
path[2], path[3], path[4], path[5], path[6], path[7]);
|
WriteToFile(kStderrFd, message, internal_strlen(message));
|
||||||
|
WriteToFile(kStderrFd, path, 8);
|
||||||
|
message = "...\n";
|
||||||
|
WriteToFile(kStderrFd, message, internal_strlen(message));
|
||||||
Die();
|
Die();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -115,7 +179,7 @@ void ReportFile::SetReportPath(const char *path) {
|
||||||
} else if (internal_strcmp(path, "stdout") == 0) {
|
} else if (internal_strcmp(path, "stdout") == 0) {
|
||||||
fd = kStdoutFd;
|
fd = kStdoutFd;
|
||||||
} else {
|
} else {
|
||||||
internal_snprintf(path_prefix, kMaxPathLength, "%s", path);
|
ParseAndSetPath(path, path_prefix, kMaxPathLength);
|
||||||
RecursiveCreateParentDirs(path_prefix);
|
RecursiveCreateParentDirs(path_prefix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -547,6 +547,8 @@ void __sanitizer_startup_hook(int argc, char **argv, char **envp,
|
||||||
__sanitizer::StoredEnviron = envp;
|
__sanitizer::StoredEnviron = envp;
|
||||||
__sanitizer::MainThreadStackBase = reinterpret_cast<uintptr_t>(stack_base);
|
__sanitizer::MainThreadStackBase = reinterpret_cast<uintptr_t>(stack_base);
|
||||||
__sanitizer::MainThreadStackSize = stack_size;
|
__sanitizer::MainThreadStackSize = stack_size;
|
||||||
|
|
||||||
|
EarlySanitizerInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void __sanitizer_set_report_path(const char *path) {
|
void __sanitizer_set_report_path(const char *path) {
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,13 @@ struct MemoryMappingLayoutData {
|
||||||
|
|
||||||
void InitShadowBounds();
|
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
|
} // namespace __sanitizer
|
||||||
|
|
||||||
#endif // SANITIZER_FUCHSIA
|
#endif // SANITIZER_FUCHSIA
|
||||||
|
|
|
||||||
361
lib/libtsan/sanitizer_common/sanitizer_haiku.cpp
vendored
Normal file
361
lib/libtsan/sanitizer_common/sanitizer_haiku.cpp
vendored
Normal file
|
|
@ -0,0 +1,361 @@
|
||||||
|
//===-- sanitizer_haiku.cpp -----------------------------------------------===//
|
||||||
|
//
|
||||||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This file is shared between Sanitizer run-time libraries and implements
|
||||||
|
// Haiku-specific functions from sanitizer_libc.h.
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "sanitizer_platform.h"
|
||||||
|
|
||||||
|
#if SANITIZER_HAIKU
|
||||||
|
|
||||||
|
# include "sanitizer_common.h"
|
||||||
|
# include "sanitizer_flags.h"
|
||||||
|
# include "sanitizer_getauxval.h"
|
||||||
|
# include "sanitizer_internal_defs.h"
|
||||||
|
# include "sanitizer_libc.h"
|
||||||
|
# include "sanitizer_linux.h"
|
||||||
|
# include "sanitizer_mutex.h"
|
||||||
|
# include "sanitizer_placement_new.h"
|
||||||
|
# include "sanitizer_procmaps.h"
|
||||||
|
|
||||||
|
# include <sys/param.h>
|
||||||
|
# include <sys/types.h>
|
||||||
|
|
||||||
|
# include <sys/mman.h>
|
||||||
|
# include <sys/resource.h>
|
||||||
|
# include <sys/stat.h>
|
||||||
|
# include <sys/time.h>
|
||||||
|
|
||||||
|
# include <dlfcn.h>
|
||||||
|
# include <errno.h>
|
||||||
|
# include <fcntl.h>
|
||||||
|
# include <limits.h>
|
||||||
|
# include <link.h>
|
||||||
|
# include <pthread.h>
|
||||||
|
# include <sched.h>
|
||||||
|
# include <signal.h>
|
||||||
|
# include <unistd.h>
|
||||||
|
|
||||||
|
# include "system/vm_defs.h"
|
||||||
|
# include "system/syscalls.h"
|
||||||
|
# include "shared/syscall_utils.h"
|
||||||
|
|
||||||
|
namespace __sanitizer {
|
||||||
|
|
||||||
|
static void *GetRealLibcAddress(const char *symbol) {
|
||||||
|
void *real = dlsym(RTLD_NEXT, symbol);
|
||||||
|
if (!real)
|
||||||
|
real = dlsym(RTLD_DEFAULT, symbol);
|
||||||
|
if (!real) {
|
||||||
|
Printf("GetRealLibcAddress failed for symbol=%s", symbol);
|
||||||
|
Die();
|
||||||
|
}
|
||||||
|
return real;
|
||||||
|
}
|
||||||
|
|
||||||
|
# define _REAL(func, ...) real##_##func(__VA_ARGS__)
|
||||||
|
# define DEFINE__REAL(ret_type, func, ...) \
|
||||||
|
static ret_type (*real_##func)(__VA_ARGS__) = NULL; \
|
||||||
|
if (!real_##func) { \
|
||||||
|
real_##func = (ret_type(*)(__VA_ARGS__))GetRealLibcAddress(#func); \
|
||||||
|
} \
|
||||||
|
CHECK(real_##func);
|
||||||
|
|
||||||
|
// --------------- sanitizer_libc.h
|
||||||
|
uptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd,
|
||||||
|
u64 offset) {
|
||||||
|
if ((flags & MAP_ANONYMOUS) != 0)
|
||||||
|
fd = -1;
|
||||||
|
|
||||||
|
int mapping =
|
||||||
|
(flags & MAP_SHARED) != 0 ? REGION_NO_PRIVATE_MAP : REGION_PRIVATE_MAP;
|
||||||
|
|
||||||
|
uint32 addressSpec;
|
||||||
|
if ((flags & MAP_FIXED) != 0)
|
||||||
|
addressSpec = B_EXACT_ADDRESS;
|
||||||
|
else if (addr != NULL)
|
||||||
|
addressSpec = B_BASE_ADDRESS;
|
||||||
|
else
|
||||||
|
addressSpec = B_RANDOMIZED_ANY_ADDRESS;
|
||||||
|
|
||||||
|
uint32 areaProtection = 0;
|
||||||
|
if ((prot & PROT_READ) != 0)
|
||||||
|
areaProtection |= B_READ_AREA;
|
||||||
|
if ((prot & PROT_WRITE) != 0)
|
||||||
|
areaProtection |= B_WRITE_AREA;
|
||||||
|
if ((prot & PROT_EXEC) != 0)
|
||||||
|
areaProtection |= B_EXECUTE_AREA;
|
||||||
|
|
||||||
|
if ((flags & MAP_NORESERVE) != 0)
|
||||||
|
areaProtection |= B_OVERCOMMITTING_AREA;
|
||||||
|
|
||||||
|
area_id area = _kern_map_file("sanitizer mmap", &addr, addressSpec, length,
|
||||||
|
areaProtection, mapping, true, fd, offset);
|
||||||
|
if (area < 0)
|
||||||
|
RETURN_AND_SET_ERRNO(area);
|
||||||
|
return (uptr)addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
uptr internal_munmap(void *addr, uptr length) {
|
||||||
|
DEFINE__REAL(int, munmap, void *a, uptr b);
|
||||||
|
return _REAL(munmap, addr, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
uptr internal_mremap(void *old_address, uptr old_size, uptr new_size, int flags,
|
||||||
|
void *new_address) {
|
||||||
|
CHECK(false && "internal_mremap is unimplemented on Haiku");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int internal_mprotect(void *addr, uptr length, int prot) {
|
||||||
|
DEFINE__REAL(int, mprotect, void *a, uptr b, int c);
|
||||||
|
return _REAL(mprotect, addr, length, prot);
|
||||||
|
}
|
||||||
|
|
||||||
|
int internal_madvise(uptr addr, uptr length, int advice) {
|
||||||
|
DEFINE__REAL(int, madvise, void *a, uptr b, int c);
|
||||||
|
return _REAL(madvise, (void *)addr, length, advice);
|
||||||
|
}
|
||||||
|
|
||||||
|
uptr internal_close(fd_t fd) {
|
||||||
|
CHECK(&_kern_close);
|
||||||
|
RETURN_AND_SET_ERRNO(_kern_close(fd));
|
||||||
|
}
|
||||||
|
|
||||||
|
uptr internal_open(const char *filename, int flags) {
|
||||||
|
CHECK(&_kern_open);
|
||||||
|
RETURN_AND_SET_ERRNO(_kern_open(-1, filename, flags, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
uptr internal_open(const char *filename, int flags, u32 mode) {
|
||||||
|
CHECK(&_kern_open);
|
||||||
|
RETURN_AND_SET_ERRNO(_kern_open(-1, filename, flags, mode));
|
||||||
|
}
|
||||||
|
|
||||||
|
uptr internal_read(fd_t fd, void *buf, uptr count) {
|
||||||
|
sptr res;
|
||||||
|
CHECK(&_kern_read);
|
||||||
|
HANDLE_EINTR(res, (sptr)_kern_read(fd, -1, buf, (size_t)count));
|
||||||
|
RETURN_AND_SET_ERRNO(res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
uptr internal_write(fd_t fd, const void *buf, uptr count) {
|
||||||
|
sptr res;
|
||||||
|
CHECK(&_kern_write);
|
||||||
|
HANDLE_EINTR(res, (sptr)_kern_write(fd, -1, buf, count));
|
||||||
|
RETURN_AND_SET_ERRNO(res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
uptr internal_ftruncate(fd_t fd, uptr size) {
|
||||||
|
sptr res;
|
||||||
|
DEFINE__REAL(int, ftruncate, int, off_t);
|
||||||
|
return _REAL(ftruncate, fd, size);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
uptr internal_stat(const char *path, void *buf) {
|
||||||
|
DEFINE__REAL(int, _stat_current, const char *a, void *b);
|
||||||
|
return _REAL(_stat_current, path, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
uptr internal_lstat(const char *path, void *buf) {
|
||||||
|
DEFINE__REAL(int, _lstat_current, const char *a, void *b);
|
||||||
|
return _REAL(_lstat_current, path, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
uptr internal_fstat(fd_t fd, void *buf) {
|
||||||
|
DEFINE__REAL(int, _fstat_current, int a, void *b);
|
||||||
|
return _REAL(_fstat_current, fd, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
uptr internal_filesize(fd_t fd) {
|
||||||
|
struct stat st;
|
||||||
|
if (internal_fstat(fd, &st))
|
||||||
|
return -1;
|
||||||
|
return (uptr)st.st_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
uptr internal_dup(int oldfd) {
|
||||||
|
DEFINE__REAL(int, dup, int a);
|
||||||
|
return _REAL(dup, oldfd);
|
||||||
|
}
|
||||||
|
|
||||||
|
uptr internal_dup2(int oldfd, int newfd) {
|
||||||
|
DEFINE__REAL(int, dup2, int a, int b);
|
||||||
|
return _REAL(dup2, oldfd, newfd);
|
||||||
|
}
|
||||||
|
|
||||||
|
uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
|
||||||
|
CHECK(&_kern_read_link);
|
||||||
|
RETURN_AND_SET_ERRNO(_kern_read_link(-1, path, buf, &bufsize));
|
||||||
|
}
|
||||||
|
|
||||||
|
uptr internal_unlink(const char *path) {
|
||||||
|
DEFINE__REAL(int, unlink, const char *a);
|
||||||
|
return _REAL(unlink, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
uptr internal_rename(const char *oldpath, const char *newpath) {
|
||||||
|
DEFINE__REAL(int, rename, const char *a, const char *b);
|
||||||
|
return _REAL(rename, oldpath, newpath);
|
||||||
|
}
|
||||||
|
|
||||||
|
uptr internal_sched_yield() {
|
||||||
|
CHECK(&_kern_thread_yield);
|
||||||
|
_kern_thread_yield();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void internal__exit(int exitcode) {
|
||||||
|
DEFINE__REAL(void, _exit, int a);
|
||||||
|
_REAL(_exit, exitcode);
|
||||||
|
Die(); // Unreachable.
|
||||||
|
}
|
||||||
|
|
||||||
|
void internal_usleep(u64 useconds) {
|
||||||
|
_kern_snooze_etc(useconds, B_SYSTEM_TIMEBASE, B_RELATIVE_TIMEOUT, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
uptr internal_execve(const char *filename, char *const argv[],
|
||||||
|
char *const envp[]) {
|
||||||
|
DEFINE__REAL(int, execve, const char *, char *const[], char *const[]);
|
||||||
|
return _REAL(execve, filename, argv, envp);
|
||||||
|
}
|
||||||
|
|
||||||
|
# if 0
|
||||||
|
tid_t GetTid() {
|
||||||
|
DEFINE__REAL(int, _lwp_self);
|
||||||
|
return _REAL(_lwp_self);
|
||||||
|
}
|
||||||
|
|
||||||
|
int TgKill(pid_t pid, tid_t tid, int sig) {
|
||||||
|
DEFINE__REAL(int, _lwp_kill, int a, int b);
|
||||||
|
(void)pid;
|
||||||
|
return _REAL(_lwp_kill, tid, sig);
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 NanoTime() {
|
||||||
|
timeval tv;
|
||||||
|
DEFINE__REAL(int, __gettimeofday50, void *a, void *b);
|
||||||
|
internal_memset(&tv, 0, sizeof(tv));
|
||||||
|
_REAL(__gettimeofday50, &tv, 0);
|
||||||
|
return (u64)tv.tv_sec * 1000 * 1000 * 1000 + tv.tv_usec * 1000;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp) {
|
||||||
|
DEFINE__REAL(int, __clock_gettime50, __sanitizer_clockid_t a, void *b);
|
||||||
|
return _REAL(__clock_gettime50, clk_id, tp);
|
||||||
|
}
|
||||||
|
|
||||||
|
uptr internal_ptrace(int request, int pid, void *addr, int data) {
|
||||||
|
DEFINE__REAL(int, ptrace, int a, int b, void *c, int d);
|
||||||
|
return _REAL(ptrace, request, pid, addr, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
uptr internal_waitpid(int pid, int *status, int options) {
|
||||||
|
DEFINE__REAL(int, waitpid, pid_t, int *, int);
|
||||||
|
return _REAL(waitpid, pid, status, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
uptr internal_getpid() {
|
||||||
|
DEFINE__REAL(int, getpid);
|
||||||
|
return _REAL(getpid);
|
||||||
|
}
|
||||||
|
|
||||||
|
uptr internal_getppid() {
|
||||||
|
DEFINE__REAL(int, getppid);
|
||||||
|
return _REAL(getppid);
|
||||||
|
}
|
||||||
|
|
||||||
|
int internal_dlinfo(void *handle, int request, void *p) {
|
||||||
|
DEFINE__REAL(int, dlinfo, void *a, int b, void *c);
|
||||||
|
return _REAL(dlinfo, handle, request, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
uptr internal_getdents(fd_t fd, void *dirp, unsigned int count) {
|
||||||
|
DEFINE__REAL(int, __getdents30, int a, void *b, size_t c);
|
||||||
|
return _REAL(__getdents30, fd, dirp, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
uptr internal_lseek(fd_t fd, OFF_T offset, int whence) {
|
||||||
|
CHECK(&_kern_seek);
|
||||||
|
off_t result = _kern_seek(fd, offset, whence);
|
||||||
|
if (result < 0) {
|
||||||
|
errno = result;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) {
|
||||||
|
Printf("internal_prctl not implemented for Haiku");
|
||||||
|
Die();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uptr internal_sigaltstack(const void *ss, void *oss) {
|
||||||
|
DEFINE__REAL(int, __sigaltstack14, const void *a, void *b);
|
||||||
|
return _REAL(__sigaltstack14, ss, oss);
|
||||||
|
}
|
||||||
|
|
||||||
|
int internal_fork() {
|
||||||
|
DEFINE__REAL(int, fork);
|
||||||
|
return _REAL(fork);
|
||||||
|
}
|
||||||
|
|
||||||
|
# if 0
|
||||||
|
int internal_sysctl(const int *name, unsigned int namelen, void *oldp,
|
||||||
|
uptr *oldlenp, const void *newp, uptr newlen) {
|
||||||
|
CHECK(&__sysctl);
|
||||||
|
return __sysctl(name, namelen, oldp, (size_t *)oldlenp, newp, (size_t)newlen);
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
int internal_sysctlbyname(const char *sname, void *oldp, uptr *oldlenp,
|
||||||
|
const void *newp, uptr newlen) {
|
||||||
|
DEFINE__REAL(int, sysctlbyname, const char *a, void *b, size_t *c,
|
||||||
|
const void *d, size_t e);
|
||||||
|
return _REAL(sysctlbyname, sname, oldp, (size_t *)oldlenp, newp,
|
||||||
|
(size_t)newlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set,
|
||||||
|
__sanitizer_sigset_t *oldset) {
|
||||||
|
CHECK(&_kern_set_signal_mask);
|
||||||
|
return _kern_set_signal_mask(how, set, oldset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void internal_sigfillset(__sanitizer_sigset_t *set) {
|
||||||
|
DEFINE__REAL(int, __sigfillset14, const void *a);
|
||||||
|
(void)_REAL(__sigfillset14, set);
|
||||||
|
}
|
||||||
|
|
||||||
|
void internal_sigemptyset(__sanitizer_sigset_t *set) {
|
||||||
|
DEFINE__REAL(int, __sigemptyset14, const void *a);
|
||||||
|
(void)_REAL(__sigemptyset14, set);
|
||||||
|
}
|
||||||
|
|
||||||
|
void internal_sigdelset(__sanitizer_sigset_t *set, int signo) {
|
||||||
|
DEFINE__REAL(int, __sigdelset14, const void *a, int b);
|
||||||
|
(void)_REAL(__sigdelset14, set, signo);
|
||||||
|
}
|
||||||
|
|
||||||
|
uptr internal_clone(int (*fn)(void *), void *child_stack, int flags,
|
||||||
|
void *arg) {
|
||||||
|
DEFINE__REAL(int, clone, int (*a)(void *b), void *c, int d, void *e);
|
||||||
|
|
||||||
|
return _REAL(clone, fn, child_stack, flags, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace __sanitizer
|
||||||
|
|
||||||
|
#endif
|
||||||
143
lib/libtsan/sanitizer_common/sanitizer_linux.cpp
vendored
143
lib/libtsan/sanitizer_common/sanitizer_linux.cpp
vendored
|
|
@ -14,7 +14,7 @@
|
||||||
#include "sanitizer_platform.h"
|
#include "sanitizer_platform.h"
|
||||||
|
|
||||||
#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
|
#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
|
||||||
SANITIZER_SOLARIS
|
SANITIZER_SOLARIS || SANITIZER_HAIKU
|
||||||
|
|
||||||
# include "sanitizer_common.h"
|
# include "sanitizer_common.h"
|
||||||
# include "sanitizer_flags.h"
|
# include "sanitizer_flags.h"
|
||||||
|
|
@ -63,15 +63,17 @@
|
||||||
# include <sched.h>
|
# include <sched.h>
|
||||||
# include <signal.h>
|
# include <signal.h>
|
||||||
# include <sys/mman.h>
|
# include <sys/mman.h>
|
||||||
# if !SANITIZER_SOLARIS
|
# if !SANITIZER_SOLARIS && !SANITIZER_HAIKU
|
||||||
# include <sys/ptrace.h>
|
# include <sys/ptrace.h>
|
||||||
# endif
|
# endif
|
||||||
# include <sys/resource.h>
|
# include <sys/resource.h>
|
||||||
# include <sys/stat.h>
|
# include <sys/stat.h>
|
||||||
# include <sys/syscall.h>
|
# if !SANITIZER_HAIKU
|
||||||
|
# include <sys/syscall.h>
|
||||||
|
# include <ucontext.h>
|
||||||
|
# endif
|
||||||
# include <sys/time.h>
|
# include <sys/time.h>
|
||||||
# include <sys/types.h>
|
# include <sys/types.h>
|
||||||
# include <ucontext.h>
|
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
|
|
||||||
# if SANITIZER_LINUX
|
# if SANITIZER_LINUX
|
||||||
|
|
@ -82,6 +84,12 @@
|
||||||
# include <sys/personality.h>
|
# include <sys/personality.h>
|
||||||
# endif
|
# 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__)
|
# if SANITIZER_LINUX && defined(__loongarch__)
|
||||||
# include <sys/sysmacros.h>
|
# include <sys/sysmacros.h>
|
||||||
# endif
|
# endif
|
||||||
|
|
@ -118,6 +126,13 @@ extern struct ps_strings *__ps_strings;
|
||||||
# define environ _environ
|
# define environ _environ
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
# if SANITIZER_HAIKU
|
||||||
|
# include <OS.h>
|
||||||
|
# include <elf.h>
|
||||||
|
# include <image.h>
|
||||||
|
extern "C" char **__libc_argv;
|
||||||
|
# endif
|
||||||
|
|
||||||
extern char **environ;
|
extern char **environ;
|
||||||
|
|
||||||
# if SANITIZER_LINUX
|
# if SANITIZER_LINUX
|
||||||
|
|
@ -246,7 +261,7 @@ ScopedBlockSignals::~ScopedBlockSignals() { SetSigProcMask(&saved_, nullptr); }
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
// --------------- sanitizer_libc.h
|
// --------------- sanitizer_libc.h
|
||||||
# if !SANITIZER_SOLARIS && !SANITIZER_NETBSD
|
# if !SANITIZER_SOLARIS && !SANITIZER_NETBSD && !SANITIZER_HAIKU
|
||||||
# if !SANITIZER_S390
|
# if !SANITIZER_S390
|
||||||
uptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd,
|
uptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd,
|
||||||
u64 offset) {
|
u64 offset) {
|
||||||
|
|
@ -591,9 +606,9 @@ uptr internal_execve(const char *filename, char *const argv[],
|
||||||
return internal_syscall(SYSCALL(execve), (uptr)filename, (uptr)argv,
|
return internal_syscall(SYSCALL(execve), (uptr)filename, (uptr)argv,
|
||||||
(uptr)envp);
|
(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) {
|
void internal__exit(int exitcode) {
|
||||||
# if SANITIZER_FREEBSD || SANITIZER_SOLARIS
|
# if SANITIZER_FREEBSD || SANITIZER_SOLARIS
|
||||||
internal_syscall(SYSCALL(exit), exitcode);
|
internal_syscall(SYSCALL(exit), exitcode);
|
||||||
|
|
@ -602,7 +617,7 @@ void internal__exit(int exitcode) {
|
||||||
# endif
|
# endif
|
||||||
Die(); // Unreachable.
|
Die(); // Unreachable.
|
||||||
}
|
}
|
||||||
# endif // !SANITIZER_NETBSD
|
# endif // !SANITIZER_NETBSD && !SANITIZER_HAIKU
|
||||||
|
|
||||||
// ----------------- sanitizer_common.h
|
// ----------------- sanitizer_common.h
|
||||||
bool FileExists(const char *filename) {
|
bool FileExists(const char *filename) {
|
||||||
|
|
@ -630,6 +645,8 @@ tid_t GetTid() {
|
||||||
return Tid;
|
return Tid;
|
||||||
# elif SANITIZER_SOLARIS
|
# elif SANITIZER_SOLARIS
|
||||||
return thr_self();
|
return thr_self();
|
||||||
|
# elif SANITIZER_HAIKU
|
||||||
|
return find_thread(NULL);
|
||||||
# else
|
# else
|
||||||
return internal_syscall(SYSCALL(gettid));
|
return internal_syscall(SYSCALL(gettid));
|
||||||
# endif
|
# endif
|
||||||
|
|
@ -645,6 +662,8 @@ int TgKill(pid_t pid, tid_t tid, int sig) {
|
||||||
errno = thr_kill(tid, sig);
|
errno = thr_kill(tid, sig);
|
||||||
// TgKill is expected to return -1 on error, not an errno.
|
// TgKill is expected to return -1 on error, not an errno.
|
||||||
return errno != 0 ? -1 : 0;
|
return errno != 0 ? -1 : 0;
|
||||||
|
# elif SANITIZER_HAIKU
|
||||||
|
return kill_thread(tid);
|
||||||
# endif
|
# endif
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
@ -672,7 +691,8 @@ u64 NanoTime() {
|
||||||
// 'environ' array (on some others) and does not use libc. This function
|
// 'environ' array (on some others) and does not use libc. This function
|
||||||
// should be called first inside __asan_init.
|
// should be called first inside __asan_init.
|
||||||
const char *GetEnv(const char *name) {
|
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) {
|
if (::environ != 0) {
|
||||||
uptr NameLen = internal_strlen(name);
|
uptr NameLen = internal_strlen(name);
|
||||||
for (char **Env = ::environ; *Env != 0; Env++) {
|
for (char **Env = ::environ; *Env != 0; Env++) {
|
||||||
|
|
@ -710,13 +730,14 @@ const char *GetEnv(const char *name) {
|
||||||
# endif
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
# if !SANITIZER_FREEBSD && !SANITIZER_NETBSD && !SANITIZER_GO
|
# if !SANITIZER_HAIKU && !SANITIZER_FREEBSD && !SANITIZER_NETBSD && \
|
||||||
|
!SANITIZER_GO
|
||||||
extern "C" {
|
extern "C" {
|
||||||
SANITIZER_WEAK_ATTRIBUTE extern void *__libc_stack_end;
|
SANITIZER_WEAK_ATTRIBUTE extern void *__libc_stack_end;
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
|
# if !SANITIZER_HAIKU && !SANITIZER_FREEBSD && !SANITIZER_NETBSD
|
||||||
static void ReadNullSepFileToArray(const char *path, char ***arr,
|
static void ReadNullSepFileToArray(const char *path, char ***arr,
|
||||||
int arr_size) {
|
int arr_size) {
|
||||||
char *buff;
|
char *buff;
|
||||||
|
|
@ -743,7 +764,10 @@ static void ReadNullSepFileToArray(const char *path, char ***arr,
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
static void GetArgsAndEnv(char ***argv, char ***envp) {
|
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
|
// On FreeBSD, retrieving the argument and environment arrays is done via the
|
||||||
// kern.ps_strings sysctl, which returns a pointer to a structure containing
|
// kern.ps_strings sysctl, which returns a pointer to a structure containing
|
||||||
// this information. See also <sys/exec.h>.
|
// this information. See also <sys/exec.h>.
|
||||||
|
|
@ -783,7 +807,7 @@ static void GetArgsAndEnv(char ***argv, char ***envp) {
|
||||||
# if !SANITIZER_GO
|
# if !SANITIZER_GO
|
||||||
}
|
}
|
||||||
# endif // !SANITIZER_GO
|
# endif // !SANITIZER_GO
|
||||||
# endif // SANITIZER_FREEBSD
|
# endif // SANITIZER_HAIKU
|
||||||
}
|
}
|
||||||
|
|
||||||
char **GetArgv() {
|
char **GetArgv() {
|
||||||
|
|
@ -802,7 +826,7 @@ char **GetEnviron() {
|
||||||
void FutexWait(atomic_uint32_t *p, u32 cmp) {
|
void FutexWait(atomic_uint32_t *p, u32 cmp) {
|
||||||
# if SANITIZER_FREEBSD
|
# if SANITIZER_FREEBSD
|
||||||
_umtx_op(p, UMTX_OP_WAIT_UINT, cmp, 0, 0);
|
_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 */
|
sched_yield(); /* No userspace futex-like synchronization */
|
||||||
# else
|
# else
|
||||||
internal_syscall(SYSCALL(futex), (uptr)p, FUTEX_WAIT_PRIVATE, cmp, 0, 0, 0);
|
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) {
|
void FutexWake(atomic_uint32_t *p, u32 count) {
|
||||||
# if SANITIZER_FREEBSD
|
# if SANITIZER_FREEBSD
|
||||||
_umtx_op(p, UMTX_OP_WAKE, count, 0, 0);
|
_umtx_op(p, UMTX_OP_WAKE, count, 0, 0);
|
||||||
# elif SANITIZER_NETBSD
|
# elif SANITIZER_NETBSD || SANITIZER_HAIKU
|
||||||
/* No userspace futex-like synchronization */
|
/* No userspace futex-like synchronization */
|
||||||
# else
|
# else
|
||||||
internal_syscall(SYSCALL(futex), (uptr)p, FUTEX_WAKE_PRIVATE, count, 0, 0, 0);
|
internal_syscall(SYSCALL(futex), (uptr)p, FUTEX_WAKE_PRIVATE, count, 0, 0, 0);
|
||||||
|
|
@ -844,7 +868,7 @@ struct linux_dirent {
|
||||||
};
|
};
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# if !SANITIZER_SOLARIS && !SANITIZER_NETBSD
|
# if !SANITIZER_SOLARIS && !SANITIZER_NETBSD && !SANITIZER_HAIKU
|
||||||
// Syscall wrappers.
|
// Syscall wrappers.
|
||||||
uptr internal_ptrace(int request, int pid, void *addr, void *data) {
|
uptr internal_ptrace(int request, int pid, void *addr, void *data) {
|
||||||
return internal_syscall(SYSCALL(ptrace), request, pid, (uptr)addr,
|
return internal_syscall(SYSCALL(ptrace), request, pid, (uptr)addr,
|
||||||
|
|
@ -1058,7 +1082,7 @@ bool internal_sigismember(__sanitizer_sigset_t *set, int signum) {
|
||||||
# endif
|
# endif
|
||||||
# endif // !SANITIZER_SOLARIS
|
# endif // !SANITIZER_SOLARIS
|
||||||
|
|
||||||
# if !SANITIZER_NETBSD
|
# if !SANITIZER_NETBSD && !SANITIZER_HAIKU
|
||||||
// ThreadLister implementation.
|
// ThreadLister implementation.
|
||||||
ThreadLister::ThreadLister(pid_t pid) : buffer_(4096) {
|
ThreadLister::ThreadLister(pid_t pid) : buffer_(4096) {
|
||||||
task_path_.AppendF("/proc/%d/task", pid);
|
task_path_.AppendF("/proc/%d/task", pid);
|
||||||
|
|
@ -1244,6 +1268,16 @@ uptr GetPageSize() {
|
||||||
CHECK_EQ(rv, 0);
|
CHECK_EQ(rv, 0);
|
||||||
return (uptr)pz;
|
return (uptr)pz;
|
||||||
# elif SANITIZER_USE_GETAUXVAL
|
# 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);
|
return getauxval(AT_PAGESZ);
|
||||||
# else
|
# else
|
||||||
return sysconf(_SC_PAGESIZE); // EXEC_PAGESIZE may not be trustworthy.
|
return sysconf(_SC_PAGESIZE); // EXEC_PAGESIZE may not be trustworthy.
|
||||||
|
|
@ -1252,7 +1286,19 @@ uptr GetPageSize() {
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
uptr ReadBinaryName(/*out*/ char *buf, uptr buf_len) {
|
uptr ReadBinaryName(/*out*/ char *buf, uptr buf_len) {
|
||||||
# if SANITIZER_SOLARIS
|
# if SANITIZER_HAIKU
|
||||||
|
int cookie = 0;
|
||||||
|
image_info info;
|
||||||
|
const char *argv0 = "<UNKNOWN>";
|
||||||
|
while (get_next_image_info(B_CURRENT_TEAM, &cookie, &info) == B_OK) {
|
||||||
|
if (info.type != B_APP_IMAGE)
|
||||||
|
continue;
|
||||||
|
argv0 = info.name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
internal_strncpy(buf, argv0, buf_len);
|
||||||
|
return internal_strlen(buf);
|
||||||
|
# elif SANITIZER_SOLARIS
|
||||||
const char *default_module_name = getexecname();
|
const char *default_module_name = getexecname();
|
||||||
CHECK_NE(default_module_name, NULL);
|
CHECK_NE(default_module_name, NULL);
|
||||||
return internal_snprintf(buf, buf_len, "%s", default_module_name);
|
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] == '.');
|
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.
|
// Call cb for each region mapped by map.
|
||||||
void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)) {
|
void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)) {
|
||||||
CHECK_NE(map, nullptr);
|
CHECK_NE(map, nullptr);
|
||||||
# if !SANITIZER_FREEBSD
|
# if !SANITIZER_FREEBSD && !SANITIZER_HAIKU
|
||||||
typedef ElfW(Phdr) Elf_Phdr;
|
typedef ElfW(Phdr) Elf_Phdr;
|
||||||
typedef ElfW(Ehdr) Elf_Ehdr;
|
typedef ElfW(Ehdr) Elf_Ehdr;
|
||||||
# endif // !SANITIZER_FREEBSD
|
# endif // !SANITIZER_FREEBSD
|
||||||
|
|
@ -1855,54 +1901,6 @@ int internal_uname(struct utsname *buf) {
|
||||||
}
|
}
|
||||||
# endif
|
# 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) {
|
static HandleSignalMode GetHandleSignalModeImpl(int signum) {
|
||||||
switch (signum) {
|
switch (signum) {
|
||||||
case SIGABRT:
|
case SIGABRT:
|
||||||
|
|
@ -1981,11 +1979,15 @@ using Context = ucontext_t;
|
||||||
SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
|
SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
|
||||||
Context *ucontext = (Context *)context;
|
Context *ucontext = (Context *)context;
|
||||||
# if defined(__x86_64__) || defined(__i386__)
|
# if defined(__x86_64__) || defined(__i386__)
|
||||||
|
# if !SANITIZER_HAIKU
|
||||||
static const uptr PF_WRITE = 1U << 1;
|
static const uptr PF_WRITE = 1U << 1;
|
||||||
|
# endif
|
||||||
# if SANITIZER_FREEBSD
|
# if SANITIZER_FREEBSD
|
||||||
uptr err = ucontext->uc_mcontext.mc_err;
|
uptr err = ucontext->uc_mcontext.mc_err;
|
||||||
# elif SANITIZER_NETBSD
|
# elif SANITIZER_NETBSD
|
||||||
uptr err = ucontext->uc_mcontext.__gregs[_REG_ERR];
|
uptr err = ucontext->uc_mcontext.__gregs[_REG_ERR];
|
||||||
|
# elif SANITIZER_HAIKU
|
||||||
|
uptr err = ucontext->uc_mcontext.r13;
|
||||||
# elif SANITIZER_SOLARIS && defined(__i386__)
|
# elif SANITIZER_SOLARIS && defined(__i386__)
|
||||||
const int Err = 13;
|
const int Err = 13;
|
||||||
uptr err = ucontext->uc_mcontext.gregs[Err];
|
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;
|
*pc = ucontext->uc_mcontext.mc_rip;
|
||||||
*bp = ucontext->uc_mcontext.mc_rbp;
|
*bp = ucontext->uc_mcontext.mc_rbp;
|
||||||
*sp = ucontext->uc_mcontext.mc_rsp;
|
*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
|
# else
|
||||||
ucontext_t *ucontext = (ucontext_t *)context;
|
ucontext_t *ucontext = (ucontext_t *)context;
|
||||||
*pc = ucontext->uc_mcontext.gregs[REG_RIP];
|
*pc = ucontext->uc_mcontext.gregs[REG_RIP];
|
||||||
|
|
|
||||||
10
lib/libtsan/sanitizer_common/sanitizer_linux.h
vendored
10
lib/libtsan/sanitizer_common/sanitizer_linux.h
vendored
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
#include "sanitizer_platform.h"
|
#include "sanitizer_platform.h"
|
||||||
#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
|
#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
|
||||||
SANITIZER_SOLARIS
|
SANITIZER_SOLARIS || SANITIZER_HAIKU
|
||||||
# include "sanitizer_common.h"
|
# include "sanitizer_common.h"
|
||||||
# include "sanitizer_internal_defs.h"
|
# include "sanitizer_internal_defs.h"
|
||||||
# include "sanitizer_platform_limits_freebsd.h"
|
# include "sanitizer_platform_limits_freebsd.h"
|
||||||
|
|
@ -31,6 +31,11 @@ namespace __sanitizer {
|
||||||
// the one in <dirent.h>, which is used by readdir().
|
// the one in <dirent.h>, which is used by readdir().
|
||||||
struct linux_dirent;
|
struct linux_dirent;
|
||||||
|
|
||||||
|
# if SANITIZER_HAIKU
|
||||||
|
struct MemoryMappingLayoutData {
|
||||||
|
long signed int cookie;
|
||||||
|
};
|
||||||
|
# else
|
||||||
struct ProcSelfMapsBuff {
|
struct ProcSelfMapsBuff {
|
||||||
char *data;
|
char *data;
|
||||||
uptr mmaped_size;
|
uptr mmaped_size;
|
||||||
|
|
@ -43,6 +48,7 @@ struct MemoryMappingLayoutData {
|
||||||
};
|
};
|
||||||
|
|
||||||
void ReadProcMaps(ProcSelfMapsBuff *proc_maps);
|
void ReadProcMaps(ProcSelfMapsBuff *proc_maps);
|
||||||
|
# endif // SANITIZER_HAIKU
|
||||||
|
|
||||||
// Syscall wrappers.
|
// Syscall wrappers.
|
||||||
uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count);
|
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.
|
// Call cb for each region mapped by map.
|
||||||
void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr));
|
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.
|
// The pages no longer count toward RSS; reads are guaranteed to return 0.
|
||||||
// Requires (but does not verify!) that pages are MAP_PRIVATE.
|
// Requires (but does not verify!) that pages are MAP_PRIVATE.
|
||||||
inline void ReleaseMemoryPagesToOSAndZeroFill(uptr beg, uptr end) {
|
inline void ReleaseMemoryPagesToOSAndZeroFill(uptr beg, uptr end) {
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
#include "sanitizer_platform.h"
|
#include "sanitizer_platform.h"
|
||||||
|
|
||||||
#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
|
#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
|
||||||
SANITIZER_SOLARIS
|
SANITIZER_SOLARIS || SANITIZER_HAIKU
|
||||||
|
|
||||||
# include "sanitizer_allocator_internal.h"
|
# include "sanitizer_allocator_internal.h"
|
||||||
# include "sanitizer_atomic.h"
|
# include "sanitizer_atomic.h"
|
||||||
|
|
@ -28,8 +28,19 @@
|
||||||
# include "sanitizer_procmaps.h"
|
# include "sanitizer_procmaps.h"
|
||||||
# include "sanitizer_solaris.h"
|
# include "sanitizer_solaris.h"
|
||||||
|
|
||||||
|
# if SANITIZER_HAIKU
|
||||||
|
# define _DEFAULT_SOURCE
|
||||||
|
# endif
|
||||||
|
|
||||||
# if SANITIZER_NETBSD
|
# if SANITIZER_NETBSD
|
||||||
# define _RTLD_SOURCE // for __lwp_gettcb_fast() / __lwp_getprivate_fast()
|
# // for __lwp_gettcb_fast() / __lwp_getprivate_fast()
|
||||||
|
# define _RTLD_SOURCE
|
||||||
|
# include <machine/mcontext.h>
|
||||||
|
# undef _RTLD_SOURCE
|
||||||
|
# include <sys/param.h>
|
||||||
|
# if __NetBSD_Version__ >= 1099001200
|
||||||
|
# include <machine/lwp_private.h>
|
||||||
|
# endif
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# include <dlfcn.h> // for dlsym()
|
# include <dlfcn.h> // for dlsym()
|
||||||
|
|
@ -74,18 +85,9 @@ extern "C" int __sys_sigaction(int signum, const struct sigaction *act,
|
||||||
# include <thread.h>
|
# include <thread.h>
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# if SANITIZER_ANDROID
|
# if SANITIZER_HAIKU
|
||||||
# include <android/api-level.h>
|
# include <kernel/OS.h>
|
||||||
# if !defined(CPU_COUNT) && !defined(__aarch64__)
|
# include <sys/link_elf.h>
|
||||||
# include <dirent.h>
|
|
||||||
# include <fcntl.h>
|
|
||||||
struct __sanitizer::linux_dirent {
|
|
||||||
long d_ino;
|
|
||||||
off_t d_off;
|
|
||||||
unsigned short d_reclen;
|
|
||||||
char d_name[];
|
|
||||||
};
|
|
||||||
# endif
|
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# if !SANITIZER_ANDROID
|
# if !SANITIZER_ANDROID
|
||||||
|
|
@ -651,6 +653,7 @@ static void GetTls(uptr *addr, uptr *size) {
|
||||||
*addr = (uptr)tcb->tcb_dtv[1];
|
*addr = (uptr)tcb->tcb_dtv[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
# elif SANITIZER_HAIKU
|
||||||
# else
|
# else
|
||||||
# error "Unknown OS"
|
# error "Unknown OS"
|
||||||
# endif
|
# endif
|
||||||
|
|
@ -721,8 +724,13 @@ static int AddModuleSegments(const char *module_name, dl_phdr_info *info,
|
||||||
if (phdr->p_type == PT_LOAD) {
|
if (phdr->p_type == PT_LOAD) {
|
||||||
uptr cur_beg = info->dlpi_addr + phdr->p_vaddr;
|
uptr cur_beg = info->dlpi_addr + phdr->p_vaddr;
|
||||||
uptr cur_end = cur_beg + phdr->p_memsz;
|
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 executable = phdr->p_flags & PF_X;
|
||||||
bool writable = phdr->p_flags & PF_W;
|
bool writable = phdr->p_flags & PF_W;
|
||||||
|
# endif
|
||||||
cur_module.addAddressRange(cur_beg, cur_end, executable, writable);
|
cur_module.addAddressRange(cur_beg, cur_end, executable, writable);
|
||||||
} else if (phdr->p_type == PT_NOTE) {
|
} else if (phdr->p_type == PT_NOTE) {
|
||||||
# ifdef NT_GNU_BUILD_ID
|
# 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool requiresProcmaps() {
|
|
||||||
# if SANITIZER_ANDROID && __ANDROID_API__ <= 22
|
|
||||||
// Fall back to /proc/maps if dl_iterate_phdr is unavailable or broken.
|
|
||||||
// The runtime check allows the same library to work with
|
|
||||||
// both K and L (and future) Android releases.
|
|
||||||
return AndroidGetApiLevel() <= ANDROID_LOLLIPOP_MR1;
|
|
||||||
# else
|
|
||||||
return false;
|
|
||||||
# endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void procmapsInit(InternalMmapVectorNoCtor<LoadedModule> *modules) {
|
|
||||||
MemoryMappingLayout memory_mapping(/*cache_enabled*/ true);
|
|
||||||
memory_mapping.DumpListOfModules(modules);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ListOfModules::init() {
|
void ListOfModules::init() {
|
||||||
clearOrInit();
|
clearOrInit();
|
||||||
if (requiresProcmaps()) {
|
DlIteratePhdrData data = {&modules_, true};
|
||||||
procmapsInit(&modules_);
|
dl_iterate_phdr(dl_iterate_phdr_cb, &data);
|
||||||
} else {
|
|
||||||
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
|
void ListOfModules::fallbackInit() { clear(); }
|
||||||
// list of modules. Allow callers to fall back to using procmaps.
|
|
||||||
void ListOfModules::fallbackInit() {
|
|
||||||
if (!requiresProcmaps()) {
|
|
||||||
clearOrInit();
|
|
||||||
procmapsInit(&modules_);
|
|
||||||
} else {
|
|
||||||
clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// getrusage does not give us the current RSS, only the max RSS.
|
// 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
|
// Still, this is better than nothing if /proc/self/statm is not available
|
||||||
|
|
@ -855,45 +834,17 @@ u32 GetNumberOfCPUs() {
|
||||||
int req[2];
|
int req[2];
|
||||||
uptr len = sizeof(ncpu);
|
uptr len = sizeof(ncpu);
|
||||||
req[0] = CTL_HW;
|
req[0] = CTL_HW;
|
||||||
|
# ifdef HW_NCPUONLINE
|
||||||
|
req[1] = HW_NCPUONLINE;
|
||||||
|
# else
|
||||||
req[1] = HW_NCPU;
|
req[1] = HW_NCPU;
|
||||||
|
# endif
|
||||||
CHECK_EQ(internal_sysctl(req, 2, &ncpu, &len, NULL, 0), 0);
|
CHECK_EQ(internal_sysctl(req, 2, &ncpu, &len, NULL, 0), 0);
|
||||||
return ncpu;
|
return ncpu;
|
||||||
# elif SANITIZER_ANDROID && !defined(CPU_COUNT) && !defined(__aarch64__)
|
# elif SANITIZER_HAIKU
|
||||||
// Fall back to /sys/devices/system/cpu on Android when cpu_set_t doesn't
|
system_info info;
|
||||||
// exist in sched.h. That is the case for toolchains generated with older
|
get_system_info(&info);
|
||||||
// NDKs.
|
return info.cpu_count;
|
||||||
// This code doesn't work on AArch64 because internal_getdents makes use of
|
|
||||||
// the 64bit getdents syscall, but cpu_set_t seems to always exist on AArch64.
|
|
||||||
uptr fd = internal_open("/sys/devices/system/cpu", O_RDONLY | O_DIRECTORY);
|
|
||||||
if (internal_iserror(fd))
|
|
||||||
return 0;
|
|
||||||
InternalMmapVector<u8> buffer(4096);
|
|
||||||
uptr bytes_read = buffer.size();
|
|
||||||
uptr n_cpus = 0;
|
|
||||||
u8 *d_type;
|
|
||||||
struct linux_dirent *entry = (struct linux_dirent *)&buffer[bytes_read];
|
|
||||||
while (true) {
|
|
||||||
if ((u8 *)entry >= &buffer[bytes_read]) {
|
|
||||||
bytes_read = internal_getdents(fd, (struct linux_dirent *)buffer.data(),
|
|
||||||
buffer.size());
|
|
||||||
if (internal_iserror(bytes_read) || !bytes_read)
|
|
||||||
break;
|
|
||||||
entry = (struct linux_dirent *)buffer.data();
|
|
||||||
}
|
|
||||||
d_type = (u8 *)entry + entry->d_reclen - 1;
|
|
||||||
if (d_type >= &buffer[bytes_read] ||
|
|
||||||
(u8 *)&entry->d_name[3] >= &buffer[bytes_read])
|
|
||||||
break;
|
|
||||||
if (entry->d_ino != 0 && *d_type == DT_DIR) {
|
|
||||||
if (entry->d_name[0] == 'c' && entry->d_name[1] == 'p' &&
|
|
||||||
entry->d_name[2] == 'u' && entry->d_name[3] >= '0' &&
|
|
||||||
entry->d_name[3] <= '9')
|
|
||||||
n_cpus++;
|
|
||||||
}
|
|
||||||
entry = (struct linux_dirent *)(((u8 *)entry) + entry->d_reclen);
|
|
||||||
}
|
|
||||||
internal_close(fd);
|
|
||||||
return n_cpus;
|
|
||||||
# elif SANITIZER_SOLARIS
|
# elif SANITIZER_SOLARIS
|
||||||
return sysconf(_SC_NPROCESSORS_ONLN);
|
return sysconf(_SC_NPROCESSORS_ONLN);
|
||||||
# else
|
# else
|
||||||
|
|
|
||||||
65
lib/libtsan/sanitizer_common/sanitizer_mac.cpp
vendored
65
lib/libtsan/sanitizer_common/sanitizer_mac.cpp
vendored
|
|
@ -38,13 +38,6 @@
|
||||||
extern char **environ;
|
extern char **environ;
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# if defined(__has_include) && __has_include(<os/trace.h>)
|
|
||||||
# define SANITIZER_OS_TRACE 1
|
|
||||||
# include <os/trace.h>
|
|
||||||
# else
|
|
||||||
# define SANITIZER_OS_TRACE 0
|
|
||||||
# endif
|
|
||||||
|
|
||||||
// Integrate with CrashReporter library if available
|
// Integrate with CrashReporter library if available
|
||||||
# if defined(__has_include) && __has_include(<CrashReporterClient.h>)
|
# if defined(__has_include) && __has_include(<CrashReporterClient.h>)
|
||||||
# define HAVE_CRASHREPORTERCLIENT_H 1
|
# define HAVE_CRASHREPORTERCLIENT_H 1
|
||||||
|
|
@ -843,31 +836,23 @@ void LogMessageOnPrintf(const char *str) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogFullErrorReport(const char *buffer) {
|
void LogFullErrorReport(const char *buffer) {
|
||||||
#if !SANITIZER_GO
|
# if !SANITIZER_GO
|
||||||
// Log with os_trace. This will make it into the crash log.
|
// Log with os_log_error. This will make it into the crash log.
|
||||||
#if SANITIZER_OS_TRACE
|
if (internal_strncmp(SanitizerToolName, "AddressSanitizer",
|
||||||
#pragma clang diagnostic push
|
sizeof("AddressSanitizer") - 1) == 0)
|
||||||
// os_trace is deprecated.
|
os_log_error(OS_LOG_DEFAULT, "Address Sanitizer reported a failure.");
|
||||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
else if (internal_strncmp(SanitizerToolName, "UndefinedBehaviorSanitizer",
|
||||||
if (GetMacosAlignedVersion() >= MacosVersion(10, 10)) {
|
sizeof("UndefinedBehaviorSanitizer") - 1) == 0)
|
||||||
// os_trace requires the message (format parameter) to be a string literal.
|
os_log_error(OS_LOG_DEFAULT,
|
||||||
if (internal_strncmp(SanitizerToolName, "AddressSanitizer",
|
"Undefined Behavior Sanitizer reported a failure.");
|
||||||
sizeof("AddressSanitizer") - 1) == 0)
|
else if (internal_strncmp(SanitizerToolName, "ThreadSanitizer",
|
||||||
os_trace("Address Sanitizer reported a failure.");
|
sizeof("ThreadSanitizer") - 1) == 0)
|
||||||
else if (internal_strncmp(SanitizerToolName, "UndefinedBehaviorSanitizer",
|
os_log_error(OS_LOG_DEFAULT, "Thread Sanitizer reported a failure.");
|
||||||
sizeof("UndefinedBehaviorSanitizer") - 1) == 0)
|
else
|
||||||
os_trace("Undefined Behavior Sanitizer reported a failure.");
|
os_log_error(OS_LOG_DEFAULT, "Sanitizer tool reported a failure.");
|
||||||
else if (internal_strncmp(SanitizerToolName, "ThreadSanitizer",
|
|
||||||
sizeof("ThreadSanitizer") - 1) == 0)
|
|
||||||
os_trace("Thread Sanitizer reported a failure.");
|
|
||||||
else
|
|
||||||
os_trace("Sanitizer tool reported a failure.");
|
|
||||||
|
|
||||||
if (common_flags()->log_to_syslog)
|
if (common_flags()->log_to_syslog)
|
||||||
os_trace("Consult syslog for more information.");
|
os_log_error(OS_LOG_DEFAULT, "Consult syslog for more information.");
|
||||||
}
|
|
||||||
#pragma clang diagnostic pop
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Log to syslog.
|
// Log to syslog.
|
||||||
// The logging on OS X may call pthread_create so we need the threading
|
// 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);
|
WriteToSyslog(buffer);
|
||||||
|
|
||||||
// The report is added to CrashLog as part of logging all of Printf output.
|
// The report is added to CrashLog as part of logging all of Printf output.
|
||||||
#endif
|
# endif // !SANITIZER_GO
|
||||||
}
|
}
|
||||||
|
|
||||||
SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
|
SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
|
||||||
|
|
@ -1203,13 +1188,14 @@ uptr MapDynamicShadow(uptr shadow_size_bytes, uptr shadow_scale,
|
||||||
const uptr left_padding =
|
const uptr left_padding =
|
||||||
Max<uptr>(granularity, 1ULL << min_shadow_base_alignment);
|
Max<uptr>(granularity, 1ULL << min_shadow_base_alignment);
|
||||||
|
|
||||||
uptr space_size = shadow_size_bytes + left_padding;
|
uptr space_size = shadow_size_bytes;
|
||||||
|
|
||||||
uptr largest_gap_found = 0;
|
uptr largest_gap_found = 0;
|
||||||
uptr max_occupied_addr = 0;
|
uptr max_occupied_addr = 0;
|
||||||
|
|
||||||
VReport(2, "FindDynamicShadowStart, space_size = %p\n", (void *)space_size);
|
VReport(2, "FindDynamicShadowStart, space_size = %p\n", (void *)space_size);
|
||||||
uptr shadow_start =
|
uptr shadow_start =
|
||||||
FindAvailableMemoryRange(space_size, alignment, granularity,
|
FindAvailableMemoryRange(space_size, alignment, left_padding,
|
||||||
&largest_gap_found, &max_occupied_addr);
|
&largest_gap_found, &max_occupied_addr);
|
||||||
// If the shadow doesn't fit, restrict the address space to make it fit.
|
// If the shadow doesn't fit, restrict the address space to make it fit.
|
||||||
if (shadow_start == 0) {
|
if (shadow_start == 0) {
|
||||||
|
|
@ -1229,9 +1215,9 @@ uptr MapDynamicShadow(uptr shadow_size_bytes, uptr shadow_scale,
|
||||||
}
|
}
|
||||||
RestrictMemoryToMaxAddress(new_max_vm);
|
RestrictMemoryToMaxAddress(new_max_vm);
|
||||||
high_mem_end = new_max_vm - 1;
|
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);
|
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);
|
nullptr, nullptr);
|
||||||
if (shadow_start == 0) {
|
if (shadow_start == 0) {
|
||||||
Report("Unable to find a memory range after restricting VM.\n");
|
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;
|
mach_msg_type_number_t count = kRegionInfoSize;
|
||||||
kr = mach_vm_region_recurse(mach_task_self(), &address, &vmsize, &depth,
|
kr = mach_vm_region_recurse(mach_task_self(), &address, &vmsize, &depth,
|
||||||
(vm_region_info_t)&vminfo, &count);
|
(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.
|
// No more regions beyond "address", consider the gap at the end of VM.
|
||||||
address = max_vm_address;
|
address = max_vm_address;
|
||||||
vmsize = 0;
|
vmsize = 0;
|
||||||
|
kr = -1; // break after this iteration.
|
||||||
} else {
|
} else {
|
||||||
if (max_occupied_addr) *max_occupied_addr = address + vmsize;
|
if (max_occupied_addr) *max_occupied_addr = address + vmsize;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
9
lib/libtsan/sanitizer_common/sanitizer_mac.h
vendored
9
lib/libtsan/sanitizer_common/sanitizer_mac.h
vendored
|
|
@ -37,9 +37,6 @@ struct VersionBase {
|
||||||
|
|
||||||
VersionBase(u16 major, u16 minor) : major(major), minor(minor) {}
|
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 {
|
bool operator>=(const VersionType &other) const {
|
||||||
return major > other.major ||
|
return major > other.major ||
|
||||||
(major == other.major && minor >= other.minor);
|
(major == other.major && minor >= other.minor);
|
||||||
|
|
@ -47,6 +44,12 @@ struct VersionBase {
|
||||||
bool operator<(const VersionType &other) const { return !(*this >= other); }
|
bool operator<(const VersionType &other) const { return !(*this >= other); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename VersionType>
|
||||||
|
bool operator==(const VersionBase<VersionType> &self,
|
||||||
|
const VersionBase<VersionType> &other) {
|
||||||
|
return self.major == other.major && self.minor == other.minor;
|
||||||
|
}
|
||||||
|
|
||||||
struct MacosVersion : VersionBase<MacosVersion> {
|
struct MacosVersion : VersionBase<MacosVersion> {
|
||||||
MacosVersion(u16 major, u16 minor) : VersionBase(major, minor) {}
|
MacosVersion(u16 major, u16 minor) : VersionBase(major, minor) {}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -144,6 +144,22 @@ INTERCEPTOR(void, free, void *ptr) {
|
||||||
COMMON_MALLOC_FREE(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) {
|
INTERCEPTOR(void *, realloc, void *ptr, size_t size) {
|
||||||
COMMON_MALLOC_ENTER();
|
COMMON_MALLOC_ENTER();
|
||||||
COMMON_MALLOC_REALLOC(ptr, size);
|
COMMON_MALLOC_REALLOC(ptr, size);
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,8 @@
|
||||||
|
|
||||||
#if !defined(__linux__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && \
|
#if !defined(__linux__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && \
|
||||||
!defined(__APPLE__) && !defined(_WIN32) && !defined(__Fuchsia__) && \
|
!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"
|
# error "This operating system is not supported"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -55,6 +56,18 @@
|
||||||
# define SANITIZER_SOLARIS 0
|
# define SANITIZER_SOLARIS 0
|
||||||
#endif
|
#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
|
// - SANITIZER_APPLE: all Apple code
|
||||||
// - TARGET_OS_OSX: macOS
|
// - TARGET_OS_OSX: macOS
|
||||||
// - SANITIZER_IOS: devices (iOS and iOS-like)
|
// - SANITIZER_IOS: devices (iOS and iOS-like)
|
||||||
|
|
@ -136,9 +149,9 @@
|
||||||
# define SANITIZER_MUSL 0
|
# define SANITIZER_MUSL 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define SANITIZER_POSIX \
|
#define SANITIZER_POSIX \
|
||||||
(SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_APPLE || \
|
(SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_APPLE || \
|
||||||
SANITIZER_NETBSD || SANITIZER_SOLARIS)
|
SANITIZER_NETBSD || SANITIZER_SOLARIS || SANITIZER_HAIKU)
|
||||||
|
|
||||||
#if __LP64__ || defined(_WIN64)
|
#if __LP64__ || defined(_WIN64)
|
||||||
# define SANITIZER_WORDSIZE 64
|
# define SANITIZER_WORDSIZE 64
|
||||||
|
|
@ -305,6 +318,9 @@
|
||||||
# endif
|
# endif
|
||||||
#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.
|
// The range of addresses which can be returned my mmap.
|
||||||
// FIXME: this value should be different on different platforms. Larger values
|
// FIXME: this value should be different on different platforms. Larger values
|
||||||
// will still work but will consume more memory for TwoLevelByteMap.
|
// will still work but will consume more memory for TwoLevelByteMap.
|
||||||
|
|
@ -410,7 +426,8 @@
|
||||||
# define SANITIZER_SUPPRESS_LEAK_ON_PTHREAD_EXIT 0
|
# define SANITIZER_SUPPRESS_LEAK_ON_PTHREAD_EXIT 0
|
||||||
#endif
|
#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
|
# define SANITIZER_MADVISE_DONTNEED MADV_FREE
|
||||||
#else
|
#else
|
||||||
# define SANITIZER_MADVISE_DONTNEED MADV_DONTNEED
|
# define SANITIZER_MADVISE_DONTNEED MADV_DONTNEED
|
||||||
|
|
|
||||||
|
|
@ -129,8 +129,10 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment,
|
||||||
|
|
||||||
#if SANITIZER_FUCHSIA
|
#if SANITIZER_FUCHSIA
|
||||||
#define SI_NOT_FUCHSIA 0
|
#define SI_NOT_FUCHSIA 0
|
||||||
|
#define SI_FUCHSIA 1
|
||||||
#else
|
#else
|
||||||
#define SI_NOT_FUCHSIA 1
|
#define SI_NOT_FUCHSIA 1
|
||||||
|
#define SI_FUCHSIA 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SANITIZER_SOLARIS
|
#if SANITIZER_SOLARIS
|
||||||
|
|
@ -139,6 +141,12 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment,
|
||||||
#define SI_SOLARIS 0
|
#define SI_SOLARIS 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if SANITIZER_AIX
|
||||||
|
# define SI_NOT_AIX 0
|
||||||
|
#else
|
||||||
|
# define SI_NOT_AIX 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#if SANITIZER_SOLARIS32
|
#if SANITIZER_SOLARIS32
|
||||||
#define SI_SOLARIS32 1
|
#define SI_SOLARIS32 1
|
||||||
#else
|
#else
|
||||||
|
|
@ -159,20 +167,20 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment,
|
||||||
|
|
||||||
#define SANITIZER_INTERCEPT_STRLEN SI_NOT_FUCHSIA
|
#define SANITIZER_INTERCEPT_STRLEN SI_NOT_FUCHSIA
|
||||||
#define SANITIZER_INTERCEPT_STRNLEN (SI_NOT_MAC && 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_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_STRTOK SI_NOT_FUCHSIA
|
||||||
#define SANITIZER_INTERCEPT_STRCHR 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_STRRCHR SI_NOT_FUCHSIA
|
||||||
#define SANITIZER_INTERCEPT_STRSPN SI_NOT_FUCHSIA
|
#define SANITIZER_INTERCEPT_STRSPN SI_NOT_FUCHSIA
|
||||||
#define SANITIZER_INTERCEPT_STRPBRK SI_NOT_FUCHSIA
|
#define SANITIZER_INTERCEPT_STRPBRK SI_NOT_FUCHSIA
|
||||||
#define SANITIZER_INTERCEPT_TEXTDOMAIN SI_LINUX_NOT_ANDROID || SI_SOLARIS
|
#define SANITIZER_INTERCEPT_TEXTDOMAIN SI_LINUX_NOT_ANDROID || SI_SOLARIS
|
||||||
#define SANITIZER_INTERCEPT_STRCASECMP SI_POSIX
|
#define SANITIZER_INTERCEPT_STRCASECMP SI_POSIX
|
||||||
#define SANITIZER_INTERCEPT_MEMSET 1
|
#define SANITIZER_INTERCEPT_MEMSET 1
|
||||||
#define SANITIZER_INTERCEPT_MEMMOVE 1
|
#define SANITIZER_INTERCEPT_MEMMOVE SI_NOT_AIX
|
||||||
#define SANITIZER_INTERCEPT_MEMCPY 1
|
#define SANITIZER_INTERCEPT_MEMCPY SI_NOT_AIX
|
||||||
#define SANITIZER_INTERCEPT_MEMCMP SI_NOT_FUCHSIA
|
#define SANITIZER_INTERCEPT_MEMCMP SI_NOT_FUCHSIA
|
||||||
#define SANITIZER_INTERCEPT_BCMP \
|
#define SANITIZER_INTERCEPT_BCMP \
|
||||||
SANITIZER_INTERCEPT_MEMCMP && \
|
SANITIZER_INTERCEPT_MEMCMP && \
|
||||||
|
|
@ -231,16 +239,22 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment,
|
||||||
#define SANITIZER_INTERCEPT_ISOC99_SCANF SI_GLIBC
|
#define SANITIZER_INTERCEPT_ISOC99_SCANF SI_GLIBC
|
||||||
|
|
||||||
#ifndef SANITIZER_INTERCEPT_PRINTF
|
#ifndef SANITIZER_INTERCEPT_PRINTF
|
||||||
#define SANITIZER_INTERCEPT_PRINTF SI_POSIX
|
# define SANITIZER_INTERCEPT_ASPRINTF SI_NOT_AIX
|
||||||
#define SANITIZER_INTERCEPT_PRINTF_L (SI_FREEBSD || SI_NETBSD)
|
# define SANITIZER_INTERCEPT_VASPRINTF SI_NOT_AIX
|
||||||
#define SANITIZER_INTERCEPT_ISOC99_PRINTF SI_GLIBC
|
# define SANITIZER_INTERCEPT_PRINTF SI_POSIX
|
||||||
|
# define SANITIZER_INTERCEPT_PRINTF_L (SI_FREEBSD || SI_NETBSD)
|
||||||
|
# define SANITIZER_INTERCEPT_ISOC99_PRINTF SI_GLIBC
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define SANITIZER_INTERCEPT_SETPROCTITLE (SI_FREEBSD || SI_NETBSD)
|
||||||
|
|
||||||
#define SANITIZER_INTERCEPT___PRINTF_CHK \
|
#define SANITIZER_INTERCEPT___PRINTF_CHK \
|
||||||
(SANITIZER_INTERCEPT_PRINTF && SI_GLIBC)
|
(SANITIZER_INTERCEPT_PRINTF && SI_GLIBC)
|
||||||
|
|
||||||
#define SANITIZER_INTERCEPT_FREXP SI_NOT_FUCHSIA
|
// AIX libc does not export FREXP and FREXPF.
|
||||||
#define SANITIZER_INTERCEPT_FREXPF_FREXPL SI_POSIX
|
#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_AND_FRIENDS SI_POSIX
|
||||||
#define SANITIZER_INTERCEPT_GETPWNAM_R_AND_FRIENDS \
|
#define SANITIZER_INTERCEPT_GETPWNAM_R_AND_FRIENDS \
|
||||||
|
|
@ -289,7 +303,7 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment,
|
||||||
#define SANITIZER_INTERCEPT_ACCEPT4 \
|
#define SANITIZER_INTERCEPT_ACCEPT4 \
|
||||||
(SI_LINUX_NOT_ANDROID || SI_NETBSD || SI_FREEBSD)
|
(SI_LINUX_NOT_ANDROID || SI_NETBSD || SI_FREEBSD)
|
||||||
#define SANITIZER_INTERCEPT_PACCEPT SI_NETBSD
|
#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_RECVMSG SI_POSIX
|
||||||
#define SANITIZER_INTERCEPT_SENDMSG SI_POSIX
|
#define SANITIZER_INTERCEPT_SENDMSG SI_POSIX
|
||||||
#define SANITIZER_INTERCEPT_RECVMMSG SI_LINUX
|
#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___WCSXFRM_L SI_LINUX
|
||||||
#define SANITIZER_INTERCEPT_WCSNRTOMBS \
|
#define SANITIZER_INTERCEPT_WCSNRTOMBS \
|
||||||
(SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
|
(SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
|
||||||
#define SANITIZER_INTERCEPT_WCRTOMB \
|
#define SANITIZER_INTERCEPT_WCRTOMB \
|
||||||
(SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
|
(SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS || \
|
||||||
|
!SI_NOT_AIX)
|
||||||
#define SANITIZER_INTERCEPT_WCTOMB \
|
#define SANITIZER_INTERCEPT_WCTOMB \
|
||||||
(SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
|
(SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
|
||||||
#define SANITIZER_INTERCEPT_TCGETATTR 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_GETMNTENT_R SI_LINUX_NOT_ANDROID
|
||||||
#define SANITIZER_INTERCEPT_STATFS \
|
#define SANITIZER_INTERCEPT_STATFS \
|
||||||
(SI_FREEBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
|
(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 \
|
#define SANITIZER_INTERCEPT_STATVFS \
|
||||||
(SI_FREEBSD || SI_NETBSD || SI_LINUX_NOT_ANDROID)
|
(SI_FREEBSD || SI_NETBSD || SI_LINUX_NOT_ANDROID)
|
||||||
#define SANITIZER_INTERCEPT_STATVFS64 SI_GLIBC
|
#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_TTYNAME_R SI_POSIX
|
||||||
#define SANITIZER_INTERCEPT_TEMPNAM SI_POSIX
|
#define SANITIZER_INTERCEPT_TEMPNAM SI_POSIX
|
||||||
#define SANITIZER_INTERCEPT_SINCOS SI_LINUX || SI_SOLARIS
|
#define SANITIZER_INTERCEPT_SINCOS SI_LINUX || SI_SOLARIS
|
||||||
#define SANITIZER_INTERCEPT_REMQUO SI_POSIX
|
#define SANITIZER_INTERCEPT_REMQUO (SI_POSIX && SI_NOT_AIX)
|
||||||
#define SANITIZER_INTERCEPT_REMQUOL (SI_POSIX && !SI_NETBSD)
|
#define SANITIZER_INTERCEPT_REMQUOL (SI_POSIX && !SI_NETBSD && SI_NOT_AIX)
|
||||||
#define SANITIZER_INTERCEPT_LGAMMA SI_POSIX
|
#define SANITIZER_INTERCEPT_LGAMMA (SI_POSIX && SI_NOT_AIX)
|
||||||
#define SANITIZER_INTERCEPT_LGAMMAL (SI_POSIX && !SI_NETBSD)
|
#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_LGAMMA_R (SI_FREEBSD || SI_LINUX || SI_SOLARIS)
|
||||||
#define SANITIZER_INTERCEPT_LGAMMAL_R SI_LINUX_NOT_ANDROID || SI_SOLARIS
|
#define SANITIZER_INTERCEPT_LGAMMAL_R SI_LINUX_NOT_ANDROID || SI_SOLARIS
|
||||||
#define SANITIZER_INTERCEPT_DRAND48_R SI_GLIBC
|
#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 SANITIZER_INTERCEPT_EVENTFD_READ_WRITE (SI_LINUX || SI_FREEBSD)
|
||||||
|
|
||||||
#define SI_STAT_LINUX (SI_LINUX && __GLIBC_PREREQ(2, 33))
|
#define SI_STAT_LINUX (SI_LINUX && __GLIBC_PREREQ(2, 33))
|
||||||
#define SANITIZER_INTERCEPT_STAT \
|
#define SANITIZER_INTERCEPT_STAT \
|
||||||
(SI_FREEBSD || SI_MAC || SI_ANDROID || SI_NETBSD || SI_SOLARIS || \
|
(SI_FREEBSD || SI_MAC || SI_ANDROID || SI_NETBSD || SI_SOLARIS || \
|
||||||
SI_STAT_LINUX)
|
SI_STAT_LINUX || !SI_NOT_AIX)
|
||||||
#define SANITIZER_INTERCEPT_STAT64 SI_STAT_LINUX && SANITIZER_HAS_STAT64
|
#define SANITIZER_INTERCEPT_STAT64 \
|
||||||
#define SANITIZER_INTERCEPT_LSTAT (SI_NETBSD || SI_FREEBSD || SI_STAT_LINUX)
|
((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 \
|
#define SANITIZER_INTERCEPT___XSTAT \
|
||||||
((!SANITIZER_INTERCEPT_STAT && SI_POSIX) || SI_STAT_LINUX)
|
((!SANITIZER_INTERCEPT_STAT && SI_POSIX) || SI_STAT_LINUX)
|
||||||
#define SANITIZER_INTERCEPT___XSTAT64 SI_GLIBC
|
#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_MMAP SI_POSIX
|
||||||
#define SANITIZER_INTERCEPT_MMAP64 SI_GLIBC || SI_SOLARIS
|
#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_MEMALIGN (!SI_FREEBSD && !SI_MAC && !SI_NETBSD)
|
||||||
#define SANITIZER_INTERCEPT___LIBC_MEMALIGN SI_GLIBC
|
#define SANITIZER_INTERCEPT___LIBC_MEMALIGN SI_GLIBC
|
||||||
#define SANITIZER_INTERCEPT_PVALLOC (SI_GLIBC || SI_ANDROID)
|
#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_PROTOENT_R SI_GLIBC
|
||||||
#define SANITIZER_INTERCEPT_NETENT (SI_LINUX || SI_NETBSD || SI_FREEBSD)
|
#define SANITIZER_INTERCEPT_NETENT (SI_LINUX || SI_NETBSD || SI_FREEBSD)
|
||||||
#define SANITIZER_INTERCEPT_SETVBUF \
|
#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_GETMNTINFO (SI_NETBSD || SI_FREEBSD || SI_MAC)
|
||||||
#define SANITIZER_INTERCEPT_MI_VECTOR_HASH SI_NETBSD
|
#define SANITIZER_INTERCEPT_MI_VECTOR_HASH SI_NETBSD
|
||||||
#define SANITIZER_INTERCEPT_GETVFSSTAT 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
|
# define SI_MAC_OS_DEPLOYMENT_MIN_13_00 0
|
||||||
#endif
|
#endif
|
||||||
#define SANITIZER_INTERCEPT_FREADLINK (SI_MAC && SI_MAC_OS_DEPLOYMENT_MIN_13_00)
|
#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
|
// This macro gives a way for downstream users to override the above
|
||||||
// interceptor macros irrespective of the platform they are on. They have
|
// interceptor macros irrespective of the platform they are on. They have
|
||||||
// to do two things:
|
// to do two things:
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@
|
||||||
#include <sys/mtio.h>
|
#include <sys/mtio.h>
|
||||||
#include <sys/ptrace.h>
|
#include <sys/ptrace.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
|
#include <sys/shm.h>
|
||||||
#include <sys/signal.h>
|
#include <sys/signal.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/sockio.h>
|
#include <sys/sockio.h>
|
||||||
|
|
@ -81,10 +82,6 @@
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
#include <wordexp.h>
|
#include <wordexp.h>
|
||||||
|
|
||||||
#define _KERNEL // to declare 'shminfo' structure
|
|
||||||
#include <sys/shm.h>
|
|
||||||
#undef _KERNEL
|
|
||||||
|
|
||||||
#undef IOC_DIRMASK
|
#undef IOC_DIRMASK
|
||||||
|
|
||||||
// Include these after system headers to avoid name clashes and ambiguities.
|
// 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_msqid_ds_sz = sizeof(struct msqid_ds);
|
||||||
unsigned struct_mq_attr_sz = sizeof(struct mq_attr);
|
unsigned struct_mq_attr_sz = sizeof(struct mq_attr);
|
||||||
unsigned struct_statvfs_sz = sizeof(struct statvfs);
|
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_regmatch_sz = sizeof(regmatch_t);
|
||||||
unsigned struct_regex_sz = sizeof(regex_t);
|
unsigned struct_regex_sz = sizeof(regex_t);
|
||||||
unsigned struct_fstab_sz = sizeof(struct fstab);
|
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;
|
const uptr sa_siginfo = (uptr)SA_SIGINFO;
|
||||||
|
|
||||||
int shmctl_ipc_stat = (int)IPC_STAT;
|
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);
|
unsigned struct_utmpx_sz = sizeof(struct utmpx);
|
||||||
|
|
||||||
int map_fixed = MAP_FIXED;
|
int map_fixed = MAP_FIXED;
|
||||||
|
|
|
||||||
|
|
@ -419,12 +419,14 @@ struct __sanitizer_wordexp_t {
|
||||||
|
|
||||||
typedef void __sanitizer_FILE;
|
typedef void __sanitizer_FILE;
|
||||||
|
|
||||||
extern unsigned struct_shminfo_sz;
|
|
||||||
extern unsigned struct_shm_info_sz;
|
|
||||||
extern int shmctl_ipc_stat;
|
extern int shmctl_ipc_stat;
|
||||||
extern int shmctl_ipc_info;
|
|
||||||
extern int shmctl_shm_info;
|
// This simplifies generic code
|
||||||
extern int shmctl_shm_stat;
|
#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;
|
extern unsigned struct_utmpx_sz;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
// Must go after undef _FILE_OFFSET_BITS.
|
// Must go after undef _FILE_OFFSET_BITS.
|
||||||
#include "sanitizer_platform.h"
|
#include "sanitizer_platform.h"
|
||||||
|
|
||||||
#if SANITIZER_LINUX || SANITIZER_APPLE
|
#if SANITIZER_LINUX || SANITIZER_APPLE || SANITIZER_HAIKU
|
||||||
// Must go after undef _FILE_OFFSET_BITS.
|
// Must go after undef _FILE_OFFSET_BITS.
|
||||||
#include "sanitizer_glibc_version.h"
|
#include "sanitizer_glibc_version.h"
|
||||||
|
|
||||||
|
|
@ -52,7 +52,7 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
#include <regex.h>
|
#include <regex.h>
|
||||||
#if !SANITIZER_APPLE
|
#if !SANITIZER_APPLE && !SANITIZER_HAIKU
|
||||||
#include <utmp.h>
|
#include <utmp.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -61,7 +61,9 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !SANITIZER_ANDROID
|
#if !SANITIZER_ANDROID
|
||||||
|
#if !SANITIZER_HAIKU
|
||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
|
#endif
|
||||||
#include <sys/timeb.h>
|
#include <sys/timeb.h>
|
||||||
#include <utmpx.h>
|
#include <utmpx.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -111,9 +113,11 @@ typedef struct user_fpregs elf_fpregset_t;
|
||||||
|
|
||||||
#if !SANITIZER_ANDROID
|
#if !SANITIZER_ANDROID
|
||||||
#include <ifaddrs.h>
|
#include <ifaddrs.h>
|
||||||
|
#if !SANITIZER_HAIKU
|
||||||
#include <sys/ucontext.h>
|
#include <sys/ucontext.h>
|
||||||
#include <wordexp.h>
|
#include <wordexp.h>
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#if SANITIZER_LINUX
|
#if SANITIZER_LINUX
|
||||||
#if SANITIZER_GLIBC
|
#if SANITIZER_GLIBC
|
||||||
|
|
@ -163,7 +167,7 @@ typedef struct user_fpregs elf_fpregset_t;
|
||||||
#include <sys/vfs.h>
|
#include <sys/vfs.h>
|
||||||
#include <sys/epoll.h>
|
#include <sys/epoll.h>
|
||||||
#include <linux/capability.h>
|
#include <linux/capability.h>
|
||||||
#else
|
#elif !SANITIZER_HAIKU
|
||||||
#include <fstab.h>
|
#include <fstab.h>
|
||||||
#endif // SANITIZER_LINUX
|
#endif // SANITIZER_LINUX
|
||||||
|
|
||||||
|
|
@ -173,6 +177,11 @@ typedef struct user_fpregs elf_fpregset_t;
|
||||||
#include <sys/sockio.h>
|
#include <sys/sockio.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if SANITIZER_HAIKU
|
||||||
|
#include <sys/sockio.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
// Include these after system headers to avoid name clashes and ambiguities.
|
// Include these after system headers to avoid name clashes and ambiguities.
|
||||||
# include "sanitizer_common.h"
|
# include "sanitizer_common.h"
|
||||||
# include "sanitizer_internal_defs.h"
|
# include "sanitizer_internal_defs.h"
|
||||||
|
|
@ -217,7 +226,7 @@ namespace __sanitizer {
|
||||||
unsigned struct_fstab_sz = sizeof(struct fstab);
|
unsigned struct_fstab_sz = sizeof(struct fstab);
|
||||||
#endif // SANITIZER_GLIBC || SANITIZER_FREEBSD || SANITIZER_NETBSD ||
|
#endif // SANITIZER_GLIBC || SANITIZER_FREEBSD || SANITIZER_NETBSD ||
|
||||||
// SANITIZER_APPLE
|
// SANITIZER_APPLE
|
||||||
#if !SANITIZER_ANDROID
|
#if !SANITIZER_ANDROID && !SANITIZER_HAIKU
|
||||||
unsigned struct_statfs_sz = sizeof(struct statfs);
|
unsigned struct_statfs_sz = sizeof(struct statfs);
|
||||||
unsigned struct_sockaddr_sz = sizeof(struct sockaddr);
|
unsigned struct_sockaddr_sz = sizeof(struct sockaddr);
|
||||||
|
|
||||||
|
|
@ -324,7 +333,7 @@ namespace __sanitizer {
|
||||||
int shmctl_shm_stat = (int)SHM_STAT;
|
int shmctl_shm_stat = (int)SHM_STAT;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !SANITIZER_APPLE && !SANITIZER_FREEBSD
|
#if !SANITIZER_APPLE && !SANITIZER_FREEBSD && !SANITIZER_HAIKU
|
||||||
unsigned struct_utmp_sz = sizeof(struct utmp);
|
unsigned struct_utmp_sz = sizeof(struct utmp);
|
||||||
#endif
|
#endif
|
||||||
#if !SANITIZER_ANDROID
|
#if !SANITIZER_ANDROID
|
||||||
|
|
@ -356,9 +365,9 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);
|
||||||
int glob_altdirfunc = GLOB_ALTDIRFUNC;
|
int glob_altdirfunc = GLOB_ALTDIRFUNC;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# if !SANITIZER_ANDROID
|
# if !SANITIZER_ANDROID && !SANITIZER_HAIKU
|
||||||
const int wordexp_wrde_dooffs = WRDE_DOOFFS;
|
const int wordexp_wrde_dooffs = WRDE_DOOFFS;
|
||||||
# endif // !SANITIZER_ANDROID
|
# endif // !SANITIZER_ANDROID && !SANITIZER_HAIKU
|
||||||
|
|
||||||
# if SANITIZER_LINUX && !SANITIZER_ANDROID && \
|
# if SANITIZER_LINUX && !SANITIZER_ANDROID && \
|
||||||
(defined(__i386) || defined(__x86_64) || defined(__mips64) || \
|
(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);
|
unsigned struct_sock_fprog_sz = sizeof(struct sock_fprog);
|
||||||
# endif // SANITIZER_GLIBC
|
# 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_sg_req_sz = sizeof(struct sioc_sg_req);
|
||||||
unsigned struct_sioc_vif_req_sz = sizeof(struct sioc_vif_req);
|
unsigned struct_sioc_vif_req_sz = sizeof(struct sioc_vif_req);
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -548,12 +557,14 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);
|
||||||
|
|
||||||
const unsigned IOCTL_NOT_PRESENT = 0;
|
const unsigned IOCTL_NOT_PRESENT = 0;
|
||||||
|
|
||||||
|
unsigned IOCTL_FIONBIO = FIONBIO;
|
||||||
|
#if !SANITIZER_HAIKU
|
||||||
unsigned IOCTL_FIOASYNC = FIOASYNC;
|
unsigned IOCTL_FIOASYNC = FIOASYNC;
|
||||||
unsigned IOCTL_FIOCLEX = FIOCLEX;
|
unsigned IOCTL_FIOCLEX = FIOCLEX;
|
||||||
unsigned IOCTL_FIOGETOWN = FIOGETOWN;
|
unsigned IOCTL_FIOGETOWN = FIOGETOWN;
|
||||||
unsigned IOCTL_FIONBIO = FIONBIO;
|
|
||||||
unsigned IOCTL_FIONCLEX = FIONCLEX;
|
unsigned IOCTL_FIONCLEX = FIONCLEX;
|
||||||
unsigned IOCTL_FIOSETOWN = FIOSETOWN;
|
unsigned IOCTL_FIOSETOWN = FIOSETOWN;
|
||||||
|
#endif
|
||||||
unsigned IOCTL_SIOCADDMULTI = SIOCADDMULTI;
|
unsigned IOCTL_SIOCADDMULTI = SIOCADDMULTI;
|
||||||
unsigned IOCTL_SIOCATMARK = SIOCATMARK;
|
unsigned IOCTL_SIOCATMARK = SIOCATMARK;
|
||||||
unsigned IOCTL_SIOCDELMULTI = SIOCDELMULTI;
|
unsigned IOCTL_SIOCDELMULTI = SIOCDELMULTI;
|
||||||
|
|
@ -574,23 +585,27 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);
|
||||||
unsigned IOCTL_SIOCSIFMTU = SIOCSIFMTU;
|
unsigned IOCTL_SIOCSIFMTU = SIOCSIFMTU;
|
||||||
unsigned IOCTL_SIOCSIFNETMASK = SIOCSIFNETMASK;
|
unsigned IOCTL_SIOCSIFNETMASK = SIOCSIFNETMASK;
|
||||||
unsigned IOCTL_SIOCSPGRP = SIOCSPGRP;
|
unsigned IOCTL_SIOCSPGRP = SIOCSPGRP;
|
||||||
|
|
||||||
|
#if !SANITIZER_HAIKU
|
||||||
unsigned IOCTL_TIOCCONS = TIOCCONS;
|
unsigned IOCTL_TIOCCONS = TIOCCONS;
|
||||||
unsigned IOCTL_TIOCEXCL = TIOCEXCL;
|
|
||||||
unsigned IOCTL_TIOCGETD = TIOCGETD;
|
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_TIOCGPGRP = TIOCGPGRP;
|
||||||
unsigned IOCTL_TIOCGWINSZ = TIOCGWINSZ;
|
unsigned IOCTL_TIOCGWINSZ = TIOCGWINSZ;
|
||||||
unsigned IOCTL_TIOCMBIC = TIOCMBIC;
|
unsigned IOCTL_TIOCMBIC = TIOCMBIC;
|
||||||
unsigned IOCTL_TIOCMBIS = TIOCMBIS;
|
unsigned IOCTL_TIOCMBIS = TIOCMBIS;
|
||||||
unsigned IOCTL_TIOCMGET = TIOCMGET;
|
unsigned IOCTL_TIOCMGET = TIOCMGET;
|
||||||
unsigned IOCTL_TIOCMSET = TIOCMSET;
|
unsigned IOCTL_TIOCMSET = TIOCMSET;
|
||||||
unsigned IOCTL_TIOCNOTTY = TIOCNOTTY;
|
|
||||||
unsigned IOCTL_TIOCNXCL = TIOCNXCL;
|
unsigned IOCTL_TIOCNXCL = TIOCNXCL;
|
||||||
unsigned IOCTL_TIOCOUTQ = TIOCOUTQ;
|
unsigned IOCTL_TIOCOUTQ = TIOCOUTQ;
|
||||||
unsigned IOCTL_TIOCPKT = TIOCPKT;
|
|
||||||
unsigned IOCTL_TIOCSCTTY = TIOCSCTTY;
|
unsigned IOCTL_TIOCSCTTY = TIOCSCTTY;
|
||||||
unsigned IOCTL_TIOCSETD = TIOCSETD;
|
|
||||||
unsigned IOCTL_TIOCSPGRP = TIOCSPGRP;
|
unsigned IOCTL_TIOCSPGRP = TIOCSPGRP;
|
||||||
unsigned IOCTL_TIOCSTI = TIOCSTI;
|
|
||||||
unsigned IOCTL_TIOCSWINSZ = TIOCSWINSZ;
|
unsigned IOCTL_TIOCSWINSZ = TIOCSWINSZ;
|
||||||
#if SANITIZER_LINUX && !SANITIZER_ANDROID
|
#if SANITIZER_LINUX && !SANITIZER_ANDROID
|
||||||
unsigned IOCTL_SIOCGETSGCNT = SIOCGETSGCNT;
|
unsigned IOCTL_SIOCGETSGCNT = SIOCGETSGCNT;
|
||||||
|
|
@ -1100,7 +1115,7 @@ COMPILER_CHECK(sizeof(__sanitizer_dirent) <= sizeof(dirent));
|
||||||
CHECK_SIZE_AND_OFFSET(dirent, d_ino);
|
CHECK_SIZE_AND_OFFSET(dirent, d_ino);
|
||||||
#if SANITIZER_APPLE
|
#if SANITIZER_APPLE
|
||||||
CHECK_SIZE_AND_OFFSET(dirent, d_seekoff);
|
CHECK_SIZE_AND_OFFSET(dirent, d_seekoff);
|
||||||
#elif SANITIZER_FREEBSD
|
#elif SANITIZER_FREEBSD || SANITIZER_HAIKU
|
||||||
// There is no 'd_off' field on FreeBSD.
|
// There is no 'd_off' field on FreeBSD.
|
||||||
#else
|
#else
|
||||||
CHECK_SIZE_AND_OFFSET(dirent, d_off);
|
CHECK_SIZE_AND_OFFSET(dirent, d_off);
|
||||||
|
|
@ -1116,7 +1131,9 @@ CHECK_SIZE_AND_OFFSET(dirent64, d_reclen);
|
||||||
|
|
||||||
CHECK_TYPE_SIZE(ifconf);
|
CHECK_TYPE_SIZE(ifconf);
|
||||||
CHECK_SIZE_AND_OFFSET(ifconf, ifc_len);
|
CHECK_SIZE_AND_OFFSET(ifconf, ifc_len);
|
||||||
|
#if !SANITIZER_HAIKU
|
||||||
CHECK_SIZE_AND_OFFSET(ifconf, ifc_ifcu);
|
CHECK_SIZE_AND_OFFSET(ifconf, ifc_ifcu);
|
||||||
|
#endif
|
||||||
|
|
||||||
CHECK_TYPE_SIZE(pollfd);
|
CHECK_TYPE_SIZE(pollfd);
|
||||||
CHECK_SIZE_AND_OFFSET(pollfd, fd);
|
CHECK_SIZE_AND_OFFSET(pollfd, fd);
|
||||||
|
|
@ -1171,7 +1188,7 @@ CHECK_TYPE_SIZE(__kernel_loff_t);
|
||||||
CHECK_TYPE_SIZE(__kernel_fd_set);
|
CHECK_TYPE_SIZE(__kernel_fd_set);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !SANITIZER_ANDROID
|
#if !SANITIZER_ANDROID && !SANITIZER_HAIKU
|
||||||
CHECK_TYPE_SIZE(wordexp_t);
|
CHECK_TYPE_SIZE(wordexp_t);
|
||||||
CHECK_SIZE_AND_OFFSET(wordexp_t, we_wordc);
|
CHECK_SIZE_AND_OFFSET(wordexp_t, we_wordc);
|
||||||
CHECK_SIZE_AND_OFFSET(wordexp_t, we_wordv);
|
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);
|
CHECK_SIZE_AND_OFFSET(mntent, mnt_passno);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !SANITIZER_HAIKU
|
||||||
CHECK_TYPE_SIZE(ether_addr);
|
CHECK_TYPE_SIZE(ether_addr);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if SANITIZER_GLIBC || SANITIZER_FREEBSD
|
#if SANITIZER_GLIBC || SANITIZER_FREEBSD
|
||||||
CHECK_TYPE_SIZE(ipc_perm);
|
CHECK_TYPE_SIZE(ipc_perm);
|
||||||
|
|
@ -1239,7 +1258,7 @@ CHECK_TYPE_SIZE(clock_t);
|
||||||
CHECK_TYPE_SIZE(clockid_t);
|
CHECK_TYPE_SIZE(clockid_t);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !SANITIZER_ANDROID
|
#if !SANITIZER_ANDROID && !SANITIZER_HAIKU
|
||||||
CHECK_TYPE_SIZE(ifaddrs);
|
CHECK_TYPE_SIZE(ifaddrs);
|
||||||
CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_next);
|
CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_next);
|
||||||
CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_name);
|
CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_name);
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -16,7 +16,7 @@
|
||||||
#include "sanitizer_platform.h"
|
#include "sanitizer_platform.h"
|
||||||
|
|
||||||
#if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \
|
#if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \
|
||||||
SANITIZER_APPLE || SANITIZER_SOLARIS || \
|
SANITIZER_APPLE || SANITIZER_SOLARIS || SANITIZER_HAIKU || \
|
||||||
SANITIZER_FUCHSIA
|
SANITIZER_FUCHSIA
|
||||||
|
|
||||||
#include "sanitizer_common.h"
|
#include "sanitizer_common.h"
|
||||||
|
|
|
||||||
94
lib/libtsan/sanitizer_common/sanitizer_procmaps_haiku.cpp
vendored
Normal file
94
lib/libtsan/sanitizer_common/sanitizer_procmaps_haiku.cpp
vendored
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
//===-- sanitizer_procmaps_haiku.cpp --------------------------------------===//
|
||||||
|
//
|
||||||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// Information about the process mappings
|
||||||
|
// (Haiku-specific parts).
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "sanitizer_platform.h"
|
||||||
|
#if SANITIZER_HAIKU
|
||||||
|
# include "sanitizer_common.h"
|
||||||
|
# include "sanitizer_procmaps.h"
|
||||||
|
|
||||||
|
# include <kernel/OS.h>
|
||||||
|
|
||||||
|
namespace __sanitizer {
|
||||||
|
|
||||||
|
void MemoryMappedSegment::AddAddressRanges(LoadedModule *module) {
|
||||||
|
// data_ should be unused on this platform
|
||||||
|
CHECK(!data_);
|
||||||
|
module->addAddressRange(start, end, IsExecutable(), IsWritable());
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryMappingLayout::MemoryMappingLayout(bool) { Reset(); }
|
||||||
|
|
||||||
|
void MemoryMappingLayout::Reset() { data_.cookie = 0; }
|
||||||
|
|
||||||
|
MemoryMappingLayout::~MemoryMappingLayout() {}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void MemoryMappingLayout::CacheMemoryMappings() {}
|
||||||
|
|
||||||
|
bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) {
|
||||||
|
area_info info;
|
||||||
|
if (get_next_area_info(B_CURRENT_TEAM, &data_.cookie, &info) != B_OK)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
segment->start = (uptr)info.address;
|
||||||
|
segment->end = (uptr)info.address + info.size;
|
||||||
|
segment->offset = 0;
|
||||||
|
segment->protection = 0;
|
||||||
|
if (info.protection & B_READ_AREA)
|
||||||
|
segment->protection |= kProtectionRead;
|
||||||
|
if (info.protection & B_WRITE_AREA)
|
||||||
|
segment->protection |= kProtectionWrite;
|
||||||
|
if (info.protection & B_EXECUTE_AREA)
|
||||||
|
segment->protection |= kProtectionExecute;
|
||||||
|
if (segment->filename) {
|
||||||
|
uptr len = Min((uptr)B_OS_NAME_LENGTH, segment->filename_size - 1);
|
||||||
|
internal_strncpy(segment->filename, info.name, len);
|
||||||
|
segment->filename[len] = 0;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MemoryMappingLayout::Error() const { return false; }
|
||||||
|
|
||||||
|
void MemoryMappingLayout::DumpListOfModules(
|
||||||
|
InternalMmapVectorNoCtor<LoadedModule> *modules) {
|
||||||
|
Reset();
|
||||||
|
InternalMmapVector<char> module_name(kMaxPathLength);
|
||||||
|
MemoryMappedSegment segment(module_name.data(), module_name.size());
|
||||||
|
for (uptr i = 0; Next(&segment); i++) {
|
||||||
|
const char *cur_name = segment.filename;
|
||||||
|
if (cur_name[0] == '\0')
|
||||||
|
continue;
|
||||||
|
// Don't subtract 'cur_beg' from the first entry:
|
||||||
|
// * If a binary is compiled w/o -pie, then the first entry in
|
||||||
|
// process maps is likely the binary itself (all dynamic libs
|
||||||
|
// are mapped higher in address space). For such a binary,
|
||||||
|
// instruction offset in binary coincides with the actual
|
||||||
|
// instruction address in virtual memory (as code section
|
||||||
|
// is mapped to a fixed memory range).
|
||||||
|
// * If a binary is compiled with -pie, all the modules are
|
||||||
|
// mapped high at address space (in particular, higher than
|
||||||
|
// shadow memory of the tool), so the module can't be the
|
||||||
|
// first entry.
|
||||||
|
uptr base_address = (i ? segment.start : 0) - segment.offset;
|
||||||
|
LoadedModule cur_module;
|
||||||
|
cur_module.set(cur_name, base_address);
|
||||||
|
segment.AddAddressRanges(&cur_module);
|
||||||
|
modules->push_back(cur_module);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetMemoryProfile(fill_profile_f cb, uptr *stats) {}
|
||||||
|
|
||||||
|
} // namespace __sanitizer
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -334,9 +334,22 @@ static const load_command *NextCommand(const load_command *lc) {
|
||||||
return (const load_command *)((const char *)lc + lc->cmdsize);
|
return (const load_command *)((const char *)lc + lc->cmdsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void FindUUID(const load_command *first_lc, u8 *uuid_output) {
|
# ifdef MH_MAGIC_64
|
||||||
for (const load_command *lc = first_lc; lc->cmd != 0; lc = NextCommand(lc)) {
|
static constexpr size_t header_size = sizeof(mach_header_64);
|
||||||
if (lc->cmd != LC_UUID) continue;
|
# 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 uuid_command *uuid_lc = (const uuid_command *)lc;
|
||||||
const uint8_t *uuid = &uuid_lc->uuid[0];
|
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) {
|
static bool IsModuleInstrumented(const load_command *first_lc,
|
||||||
for (const load_command *lc = first_lc; lc->cmd != 0; lc = NextCommand(lc)) {
|
const mach_header *hdr) {
|
||||||
if (lc->cmd != LC_LOAD_DYLIB) continue;
|
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;
|
const dylib_command *dylib_lc = (const dylib_command *)lc;
|
||||||
uint32_t dylib_name_offset = dylib_lc->dylib.name.offset;
|
uint32_t dylib_name_offset = dylib_lc->dylib.name.offset;
|
||||||
|
|
@ -393,10 +413,10 @@ bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) {
|
||||||
continue;
|
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_uuid);
|
||||||
data_.current_instrumented = IsModuleInstrumented(
|
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) {
|
while (data_.current_load_cmd_count > 0) {
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,6 @@
|
||||||
// Information about the process mappings (Solaris-specific parts).
|
// Information about the process mappings (Solaris-specific parts).
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
// Before Solaris 11.4, <procfs.h> doesn't work in a largefile environment.
|
|
||||||
#undef _FILE_OFFSET_BITS
|
|
||||||
|
|
||||||
// Avoid conflict between `_TIME_BITS` defined vs. `_FILE_OFFSET_BITS`
|
// Avoid conflict between `_TIME_BITS` defined vs. `_FILE_OFFSET_BITS`
|
||||||
// undefined in some Linux configurations.
|
// undefined in some Linux configurations.
|
||||||
#undef _TIME_BITS
|
#undef _TIME_BITS
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
# define SANITIZER_REDEFINE_BUILTINS_H
|
# define SANITIZER_REDEFINE_BUILTINS_H
|
||||||
|
|
||||||
// The asm hack only works with GCC and Clang.
|
// The asm hack only works with GCC and Clang.
|
||||||
# if !defined(_WIN32)
|
# if !defined(_WIN32) && !defined(_AIX)
|
||||||
|
|
||||||
asm(R"(
|
asm(R"(
|
||||||
.set memcpy, __sanitizer_internal_memcpy
|
.set memcpy, __sanitizer_internal_memcpy
|
||||||
|
|
|
||||||
|
|
@ -38,25 +38,28 @@
|
||||||
# include <asm/ptrace.h>
|
# include <asm/ptrace.h>
|
||||||
#endif
|
#endif
|
||||||
#include <sys/user.h> // for user_regs_struct
|
#include <sys/user.h> // for user_regs_struct
|
||||||
#if SANITIZER_ANDROID && SANITIZER_MIPS
|
# if SANITIZER_MIPS
|
||||||
# include <asm/reg.h> // for mips SP register in sys/user.h
|
// clang-format off
|
||||||
#endif
|
# include <asm/sgidefs.h> // <asm/sgidefs.h> must be included before <asm/reg.h>
|
||||||
#include <sys/wait.h> // for signal-related stuff
|
# include <asm/reg.h> // for mips SP register
|
||||||
|
// clang-format on
|
||||||
|
# endif
|
||||||
|
# include <sys/wait.h> // for signal-related stuff
|
||||||
|
|
||||||
#ifdef sa_handler
|
# ifdef sa_handler
|
||||||
# undef sa_handler
|
# undef sa_handler
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
#ifdef sa_sigaction
|
# ifdef sa_sigaction
|
||||||
# undef sa_sigaction
|
# undef sa_sigaction
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
#include "sanitizer_common.h"
|
# include "sanitizer_common.h"
|
||||||
#include "sanitizer_flags.h"
|
# include "sanitizer_flags.h"
|
||||||
#include "sanitizer_libc.h"
|
# include "sanitizer_libc.h"
|
||||||
#include "sanitizer_linux.h"
|
# include "sanitizer_linux.h"
|
||||||
#include "sanitizer_mutex.h"
|
# include "sanitizer_mutex.h"
|
||||||
#include "sanitizer_placement_new.h"
|
# include "sanitizer_placement_new.h"
|
||||||
|
|
||||||
// Sufficiently old kernel headers don't provide this value, but we can still
|
// 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
|
// 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__)
|
#elif defined(__mips__)
|
||||||
typedef struct user regs_struct;
|
typedef struct user regs_struct;
|
||||||
# if SANITIZER_ANDROID
|
# define REG_SP regs[EF_R29]
|
||||||
# define REG_SP regs[EF_R29]
|
|
||||||
# else
|
|
||||||
# define REG_SP regs[EF_REG29]
|
|
||||||
# endif
|
|
||||||
|
|
||||||
#elif defined(__aarch64__)
|
#elif defined(__aarch64__)
|
||||||
typedef struct user_pt_regs regs_struct;
|
typedef struct user_pt_regs regs_struct;
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,8 @@ struct SuspendedThreadsListWindows final : public SuspendedThreadsList {
|
||||||
# define SP_REG Esp
|
# define SP_REG Esp
|
||||||
# elif SANITIZER_ARM | SANITIZER_ARM64
|
# elif SANITIZER_ARM | SANITIZER_ARM64
|
||||||
# define SP_REG Sp
|
# define SP_REG Sp
|
||||||
|
# elif SANITIZER_MIPS32
|
||||||
|
# define SP_REG IntSp
|
||||||
# else
|
# else
|
||||||
# error Architecture not supported!
|
# error Architecture not supported!
|
||||||
# endif
|
# endif
|
||||||
|
|
|
||||||
|
|
@ -31,11 +31,12 @@ Symbolizer *Symbolizer::GetOrInit() {
|
||||||
|
|
||||||
const char *ExtractToken(const char *str, const char *delims, char **result) {
|
const char *ExtractToken(const char *str, const char *delims, char **result) {
|
||||||
uptr prefix_len = internal_strcspn(str, delims);
|
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);
|
internal_memcpy(*result, str, prefix_len);
|
||||||
(*result)[prefix_len] = '\0';
|
(*result)[prefix_len] = '\0';
|
||||||
const char *prefix_end = str + prefix_len;
|
const char *prefix_end = str + prefix_len;
|
||||||
if (*prefix_end != '\0') prefix_end++;
|
if (*prefix_end != '\0')
|
||||||
|
prefix_end++;
|
||||||
return prefix_end;
|
return prefix_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -78,7 +79,8 @@ const char *ExtractTokenUpToDelimiter(const char *str, const char *delimiter,
|
||||||
internal_memcpy(*result, str, prefix_len);
|
internal_memcpy(*result, str, prefix_len);
|
||||||
(*result)[prefix_len] = '\0';
|
(*result)[prefix_len] = '\0';
|
||||||
const char *prefix_end = str + prefix_len;
|
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;
|
return prefix_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -215,18 +217,20 @@ const LoadedModule *Symbolizer::FindModuleForAddress(uptr address) {
|
||||||
modules_were_reloaded = true;
|
modules_were_reloaded = true;
|
||||||
}
|
}
|
||||||
const LoadedModule *module = SearchForModule(modules_, address);
|
const LoadedModule *module = SearchForModule(modules_, address);
|
||||||
if (module) return module;
|
if (module)
|
||||||
|
return module;
|
||||||
|
|
||||||
// dlopen/dlclose interceptors invalidate the module list, but when
|
// dlopen/dlclose interceptors invalidate the module list, but when
|
||||||
// interception is disabled, we need to retry if the lookup fails in
|
// interception is disabled, we need to retry if the lookup fails in
|
||||||
// case the module list changed.
|
// case the module list changed.
|
||||||
#if !SANITIZER_INTERCEPT_DLOPEN_DLCLOSE
|
# if !SANITIZER_INTERCEPT_DLOPEN_DLCLOSE
|
||||||
if (!modules_were_reloaded) {
|
if (!modules_were_reloaded) {
|
||||||
RefreshModules();
|
RefreshModules();
|
||||||
module = SearchForModule(modules_, address);
|
module = SearchForModule(modules_, address);
|
||||||
if (module) return module;
|
if (module)
|
||||||
|
return module;
|
||||||
}
|
}
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
if (fallback_modules_.size()) {
|
if (fallback_modules_.size()) {
|
||||||
module = SearchForModule(fallback_modules_, address);
|
module = SearchForModule(fallback_modules_, address);
|
||||||
|
|
@ -260,31 +264,31 @@ class LLVMSymbolizerProcess final : public SymbolizerProcess {
|
||||||
// script/asan_symbolize.py and sanitizer_common.h.
|
// script/asan_symbolize.py and sanitizer_common.h.
|
||||||
void GetArgV(const char *path_to_binary,
|
void GetArgV(const char *path_to_binary,
|
||||||
const char *(&argv)[kArgVMax]) const override {
|
const char *(&argv)[kArgVMax]) const override {
|
||||||
#if defined(__x86_64h__)
|
# if defined(__x86_64h__)
|
||||||
const char* const kSymbolizerArch = "--default-arch=x86_64h";
|
const char *const kSymbolizerArch = "--default-arch=x86_64h";
|
||||||
#elif defined(__x86_64__)
|
# elif defined(__x86_64__)
|
||||||
const char* const kSymbolizerArch = "--default-arch=x86_64";
|
const char *const kSymbolizerArch = "--default-arch=x86_64";
|
||||||
#elif defined(__i386__)
|
# elif defined(__i386__)
|
||||||
const char* const kSymbolizerArch = "--default-arch=i386";
|
const char *const kSymbolizerArch = "--default-arch=i386";
|
||||||
#elif SANITIZER_LOONGARCH64
|
# elif SANITIZER_LOONGARCH64
|
||||||
const char *const kSymbolizerArch = "--default-arch=loongarch64";
|
const char *const kSymbolizerArch = "--default-arch=loongarch64";
|
||||||
#elif SANITIZER_RISCV64
|
# elif SANITIZER_RISCV64
|
||||||
const char *const kSymbolizerArch = "--default-arch=riscv64";
|
const char *const kSymbolizerArch = "--default-arch=riscv64";
|
||||||
#elif defined(__aarch64__)
|
# elif defined(__aarch64__)
|
||||||
const char* const kSymbolizerArch = "--default-arch=arm64";
|
const char *const kSymbolizerArch = "--default-arch=arm64";
|
||||||
#elif defined(__arm__)
|
# elif defined(__arm__)
|
||||||
const char* const kSymbolizerArch = "--default-arch=arm";
|
const char *const kSymbolizerArch = "--default-arch=arm";
|
||||||
#elif defined(__powerpc64__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
# elif defined(__powerpc64__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||||
const char* const kSymbolizerArch = "--default-arch=powerpc64";
|
const char *const kSymbolizerArch = "--default-arch=powerpc64";
|
||||||
#elif defined(__powerpc64__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
# elif defined(__powerpc64__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||||
const char* const kSymbolizerArch = "--default-arch=powerpc64le";
|
const char *const kSymbolizerArch = "--default-arch=powerpc64le";
|
||||||
#elif defined(__s390x__)
|
# elif defined(__s390x__)
|
||||||
const char* const kSymbolizerArch = "--default-arch=s390x";
|
const char *const kSymbolizerArch = "--default-arch=s390x";
|
||||||
#elif defined(__s390__)
|
# elif defined(__s390__)
|
||||||
const char* const kSymbolizerArch = "--default-arch=s390";
|
const char *const kSymbolizerArch = "--default-arch=s390";
|
||||||
#else
|
# else
|
||||||
const char* const kSymbolizerArch = "--default-arch=unknown";
|
const char *const kSymbolizerArch = "--default-arch=unknown";
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
const char *const demangle_flag =
|
const char *const demangle_flag =
|
||||||
common_flags()->demangle ? "--demangle" : "--no-demangle";
|
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;
|
char *back = file_line_info + size - 1;
|
||||||
for (int i = 0; i < 2; ++i) {
|
for (int i = 0; i < 2; ++i) {
|
||||||
while (back > file_line_info && IsDigit(*back)) --back;
|
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->column = info->line;
|
||||||
info->line = internal_atoll(back + 1);
|
info->line = internal_atoll(back + 1);
|
||||||
// Truncate the string at the colon to keep only filename.
|
// Truncate the string at the colon to keep only filename.
|
||||||
|
|
@ -436,7 +441,7 @@ bool LLVMSymbolizer::SymbolizeData(uptr addr, DataInfo *info) {
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return false;
|
return false;
|
||||||
ParseSymbolizeDataOutput(buf, info);
|
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;
|
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",
|
size_needed = internal_snprintf(buffer_, kBufferSize, "%s \"%s\" 0x%zx\n",
|
||||||
command_prefix, module_name, module_offset);
|
command_prefix, module_name, module_offset);
|
||||||
else
|
else
|
||||||
size_needed = internal_snprintf(buffer_, kBufferSize,
|
size_needed = internal_snprintf(
|
||||||
"%s \"%s:%s\" 0x%zx\n", command_prefix,
|
buffer_, kBufferSize, "%s \"%s:%s\" 0x%zx\n", command_prefix,
|
||||||
module_name, ModuleArchToString(arch),
|
module_name, ModuleArchToString(arch), module_offset);
|
||||||
module_offset);
|
|
||||||
|
|
||||||
if (size_needed >= static_cast<int>(kBufferSize)) {
|
if (size_needed >= static_cast<int>(kBufferSize)) {
|
||||||
Report("WARNING: Command buffer too small");
|
Report("WARNING: Command buffer too small");
|
||||||
|
|
@ -484,9 +488,9 @@ SymbolizerProcess::SymbolizerProcess(const char *path, bool use_posix_spawn)
|
||||||
CHECK_NE(path_[0], '\0');
|
CHECK_NE(path_[0], '\0');
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsSameModule(const char* path) {
|
static bool IsSameModule(const char *path) {
|
||||||
if (const char* ProcessName = GetProcessName()) {
|
if (const char *ProcessName = GetProcessName()) {
|
||||||
if (const char* SymbolizerName = StripModuleName(path)) {
|
if (const char *SymbolizerName = StripModuleName(path)) {
|
||||||
return !internal_strcmp(ProcessName, SymbolizerName);
|
return !internal_strcmp(ProcessName, SymbolizerName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -516,9 +520,9 @@ const char *SymbolizerProcess::SendCommand(const char *command) {
|
||||||
|
|
||||||
const char *SymbolizerProcess::SendCommandImpl(const char *command) {
|
const char *SymbolizerProcess::SendCommandImpl(const char *command) {
|
||||||
if (input_fd_ == kInvalidFd || output_fd_ == kInvalidFd)
|
if (input_fd_ == kInvalidFd || output_fd_ == kInvalidFd)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
if (!WriteToSymbolizer(command, internal_strlen(command)))
|
if (!WriteToSymbolizer(command, internal_strlen(command)))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
if (!ReadFromSymbolizer())
|
if (!ReadFromSymbolizer())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return buffer_.data();
|
return buffer_.data();
|
||||||
|
|
|
||||||
|
|
@ -38,9 +38,10 @@
|
||||||
// because we do not require a C++ ABI library to be linked to a program
|
// 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.
|
// using sanitizers; if it's not present, we'll just use the mangled name.
|
||||||
namespace __cxxabiv1 {
|
namespace __cxxabiv1 {
|
||||||
extern "C" SANITIZER_WEAK_ATTRIBUTE
|
extern "C" SANITIZER_WEAK_ATTRIBUTE char *__cxa_demangle(const char *mangled,
|
||||||
char *__cxa_demangle(const char *mangled, char *buffer,
|
char *buffer,
|
||||||
size_t *length, int *status);
|
size_t *length,
|
||||||
|
int *status);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace __sanitizer {
|
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
|
// it does not allocate). For now, we just call it anyway, and we leak
|
||||||
// the returned value.
|
// the returned value.
|
||||||
if (&__cxxabiv1::__cxa_demangle)
|
if (&__cxxabiv1::__cxa_demangle)
|
||||||
if (const char *demangled_name =
|
if (const char *demangled_name = __cxxabiv1::__cxa_demangle(name, 0, 0, 0))
|
||||||
__cxxabiv1::__cxa_demangle(name, 0, 0, 0))
|
|
||||||
return demangled_name;
|
return demangled_name;
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
@ -85,7 +85,8 @@ const char *DemangleSwift(const char *name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *DemangleSwiftAndCXX(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))
|
if (const char *swift_demangled_name = DemangleSwift(name))
|
||||||
return swift_demangled_name;
|
return swift_demangled_name;
|
||||||
return DemangleCXXABI(name);
|
return DemangleCXXABI(name);
|
||||||
|
|
@ -114,7 +115,8 @@ static bool CreateTwoHighNumberedPipes(int *infd_, int *outfd_) {
|
||||||
} else {
|
} else {
|
||||||
outfd = sock_pair[i];
|
outfd = sock_pair[i];
|
||||||
for (int j = 0; j < i; j++) {
|
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][0]);
|
||||||
internal_close(sock_pair[j][1]);
|
internal_close(sock_pair[j][1]);
|
||||||
}
|
}
|
||||||
|
|
@ -155,7 +157,7 @@ bool SymbolizerProcess::StartSymbolizerSubprocess() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (use_posix_spawn_) {
|
if (use_posix_spawn_) {
|
||||||
#if SANITIZER_APPLE
|
# if SANITIZER_APPLE
|
||||||
fd_t fd = internal_spawn(argv, const_cast<const char **>(GetEnvP()), &pid);
|
fd_t fd = internal_spawn(argv, const_cast<const char **>(GetEnvP()), &pid);
|
||||||
if (fd == kInvalidFd) {
|
if (fd == kInvalidFd) {
|
||||||
Report("WARNING: failed to spawn external symbolizer (errno: %d)\n",
|
Report("WARNING: failed to spawn external symbolizer (errno: %d)\n",
|
||||||
|
|
@ -165,14 +167,16 @@ bool SymbolizerProcess::StartSymbolizerSubprocess() {
|
||||||
|
|
||||||
input_fd_ = fd;
|
input_fd_ = fd;
|
||||||
output_fd_ = fd;
|
output_fd_ = fd;
|
||||||
#else // SANITIZER_APPLE
|
# else // SANITIZER_APPLE
|
||||||
UNIMPLEMENTED();
|
UNIMPLEMENTED();
|
||||||
#endif // SANITIZER_APPLE
|
# endif // SANITIZER_APPLE
|
||||||
} else {
|
} else {
|
||||||
fd_t infd[2] = {}, outfd[2] = {};
|
fd_t infd[2] = {}, outfd[2] = {};
|
||||||
if (!CreateTwoHighNumberedPipes(infd, outfd)) {
|
if (!CreateTwoHighNumberedPipes(infd, outfd)) {
|
||||||
Report("WARNING: Can't create a socket pair to start "
|
Report(
|
||||||
"external symbolizer (errno: %d)\n", errno);
|
"WARNING: Can't create a socket pair to start "
|
||||||
|
"external symbolizer (errno: %d)\n",
|
||||||
|
errno);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -260,10 +264,11 @@ bool Addr2LineProcess::ReachedEndOfOutput(const char *buffer,
|
||||||
// 1. First one, corresponding to given offset to be symbolized
|
// 1. First one, corresponding to given offset to be symbolized
|
||||||
// (may be equal to output_terminator_, if offset is not valid).
|
// (may be equal to output_terminator_, if offset is not valid).
|
||||||
// 2. Second one for output_terminator_, itself to mark the end of output.
|
// 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_.
|
// Addr2Line output should end up with output_terminator_.
|
||||||
return !internal_memcmp(buffer + length - kTerminatorLen,
|
return !internal_memcmp(buffer + length - kTerminatorLen, output_terminator_,
|
||||||
output_terminator_, kTerminatorLen);
|
kTerminatorLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
class Addr2LinePool final : public SymbolizerTool {
|
class Addr2LinePool final : public SymbolizerTool {
|
||||||
|
|
@ -283,9 +288,7 @@ class Addr2LinePool final : public SymbolizerTool {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SymbolizeData(uptr addr, DataInfo *info) override {
|
bool SymbolizeData(uptr addr, DataInfo *info) override { return false; }
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const char *SendCommand(const char *module_name, uptr module_offset) {
|
const char *SendCommand(const char *module_name, uptr module_offset) {
|
||||||
|
|
@ -299,22 +302,21 @@ class Addr2LinePool final : public SymbolizerTool {
|
||||||
}
|
}
|
||||||
if (!addr2line) {
|
if (!addr2line) {
|
||||||
addr2line =
|
addr2line =
|
||||||
new(*allocator_) Addr2LineProcess(addr2line_path_, module_name);
|
new (*allocator_) Addr2LineProcess(addr2line_path_, module_name);
|
||||||
addr2line_pool_.push_back(addr2line);
|
addr2line_pool_.push_back(addr2line);
|
||||||
}
|
}
|
||||||
CHECK_EQ(0, internal_strcmp(module_name, addr2line->module_name()));
|
CHECK_EQ(0, internal_strcmp(module_name, addr2line->module_name()));
|
||||||
char buffer[kBufferSize];
|
char buffer[kBufferSize];
|
||||||
internal_snprintf(buffer, kBufferSize, "0x%zx\n0x%zx\n",
|
internal_snprintf(buffer, kBufferSize, "0x%zx\n0x%zx\n", module_offset,
|
||||||
module_offset, dummy_address_);
|
dummy_address_);
|
||||||
return addr2line->SendCommand(buffer);
|
return addr2line->SendCommand(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uptr kBufferSize = 64;
|
static const uptr kBufferSize = 64;
|
||||||
const char *addr2line_path_;
|
const char *addr2line_path_;
|
||||||
LowLevelAllocator *allocator_;
|
LowLevelAllocator *allocator_;
|
||||||
InternalMmapVector<Addr2LineProcess*> addr2line_pool_;
|
InternalMmapVector<Addr2LineProcess *> addr2line_pool_;
|
||||||
static const uptr dummy_address_ =
|
static const uptr dummy_address_ = FIRST_32_SECOND_64(UINT32_MAX, UINT64_MAX);
|
||||||
FIRST_32_SECOND_64(UINT32_MAX, UINT64_MAX);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
# if SANITIZER_SUPPORTS_WEAK_HOOKS
|
# if SANITIZER_SUPPORTS_WEAK_HOOKS
|
||||||
|
|
@ -352,8 +354,9 @@ class InternalSymbolizer final : public SymbolizerTool {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SymbolizePC(uptr addr, SymbolizedStack *stack) override {
|
bool SymbolizePC(uptr addr, SymbolizedStack *stack) override {
|
||||||
bool result = __sanitizer_symbolize_code(
|
bool result = __sanitizer_symbolize_code(stack->info.module,
|
||||||
stack->info.module, stack->info.module_offset, buffer_, sizeof(buffer_));
|
stack->info.module_offset, buffer_,
|
||||||
|
sizeof(buffer_));
|
||||||
if (result)
|
if (result)
|
||||||
ParseSymbolizePCOutput(buffer_, stack);
|
ParseSymbolizePCOutput(buffer_, stack);
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -423,44 +426,53 @@ static SymbolizerTool *ChooseExternalSymbolizer(LowLevelAllocator *allocator) {
|
||||||
} else if (!internal_strncmp(binary_name, kLLVMSymbolizerPrefix,
|
} else if (!internal_strncmp(binary_name, kLLVMSymbolizerPrefix,
|
||||||
internal_strlen(kLLVMSymbolizerPrefix))) {
|
internal_strlen(kLLVMSymbolizerPrefix))) {
|
||||||
VReport(2, "Using llvm-symbolizer at user-specified path: %s\n", path);
|
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")) {
|
} else if (!internal_strcmp(binary_name, "atos")) {
|
||||||
#if SANITIZER_APPLE
|
# if SANITIZER_APPLE
|
||||||
VReport(2, "Using atos at user-specified path: %s\n", path);
|
VReport(2, "Using atos at user-specified path: %s\n", path);
|
||||||
return new(*allocator) AtosSymbolizer(path, allocator);
|
return new (*allocator) AtosSymbolizer(path, allocator);
|
||||||
#else // SANITIZER_APPLE
|
# else // SANITIZER_APPLE
|
||||||
Report("ERROR: Using `atos` is only supported on Darwin.\n");
|
Report("ERROR: Using `atos` is only supported on Darwin.\n");
|
||||||
Die();
|
Die();
|
||||||
#endif // SANITIZER_APPLE
|
# endif // SANITIZER_APPLE
|
||||||
} else if (!internal_strcmp(binary_name, "addr2line")) {
|
} else if (!internal_strcmp(binary_name, "addr2line")) {
|
||||||
VReport(2, "Using addr2line at user-specified path: %s\n", path);
|
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) {
|
} else if (path) {
|
||||||
Report("ERROR: External symbolizer path is set to '%s' which isn't "
|
Report(
|
||||||
"a known symbolizer. Please set the path to the llvm-symbolizer "
|
"ERROR: External symbolizer path is set to '%s' which isn't "
|
||||||
"binary or other known tool.\n", path);
|
"a known symbolizer. Please set the path to the llvm-symbolizer "
|
||||||
|
"binary or other known tool.\n",
|
||||||
|
path);
|
||||||
Die();
|
Die();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise symbolizer program is unknown, let's search $PATH
|
// 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);
|
CHECK(path == nullptr);
|
||||||
#if SANITIZER_APPLE
|
# if SANITIZER_APPLE
|
||||||
if (const char *found_path = FindPathToBinary("atos")) {
|
if (const char *found_path = FindPathToBinary("atos")) {
|
||||||
VReport(2, "Using atos found at: %s\n", found_path);
|
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")) {
|
if (const char *found_path = FindPathToBinary("llvm-symbolizer")) {
|
||||||
VReport(2, "Using llvm-symbolizer found at: %s\n", found_path);
|
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 (common_flags()->allow_addr2line) {
|
||||||
if (const char *found_path = FindPathToBinary("addr2line")) {
|
if (const char *found_path = FindPathToBinary("addr2line")) {
|
||||||
VReport(2, "Using addr2line found at: %s\n", found_path);
|
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;
|
return nullptr;
|
||||||
|
# endif // SANITIZER_DISABLE_SYMBOLIZER_PATH_SEARCH
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ChooseSymbolizerTools(IntrusiveList<SymbolizerTool> *list,
|
static void ChooseSymbolizerTools(IntrusiveList<SymbolizerTool> *list,
|
||||||
|
|
@ -492,17 +504,17 @@ static void ChooseSymbolizerTools(IntrusiveList<SymbolizerTool> *list,
|
||||||
list->push_back(tool);
|
list->push_back(tool);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SANITIZER_APPLE
|
# if SANITIZER_APPLE
|
||||||
VReport(2, "Using dladdr symbolizer.\n");
|
VReport(2, "Using dladdr symbolizer.\n");
|
||||||
list->push_back(new(*allocator) DlAddrSymbolizer());
|
list->push_back(new (*allocator) DlAddrSymbolizer());
|
||||||
#endif // SANITIZER_APPLE
|
# endif // SANITIZER_APPLE
|
||||||
}
|
}
|
||||||
|
|
||||||
Symbolizer *Symbolizer::PlatformInit() {
|
Symbolizer *Symbolizer::PlatformInit() {
|
||||||
IntrusiveList<SymbolizerTool> list;
|
IntrusiveList<SymbolizerTool> list;
|
||||||
list.clear();
|
list.clear();
|
||||||
ChooseSymbolizerTools(&list, &symbolizer_allocator_);
|
ChooseSymbolizerTools(&list, &symbolizer_allocator_);
|
||||||
return new(symbolizer_allocator_) Symbolizer(list);
|
return new (symbolizer_allocator_) Symbolizer(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Symbolizer::LateInitialize() {
|
void Symbolizer::LateInitialize() {
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
#include "sanitizer_platform.h"
|
#include "sanitizer_platform.h"
|
||||||
#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
|
#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
|
||||||
SANITIZER_SOLARIS
|
SANITIZER_SOLARIS || SANITIZER_HAIKU
|
||||||
#include "sanitizer_common.h"
|
#include "sanitizer_common.h"
|
||||||
#include "sanitizer_stacktrace.h"
|
#include "sanitizer_stacktrace.h"
|
||||||
|
|
||||||
|
|
@ -91,38 +91,6 @@ _Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, void *param) {
|
||||||
|
|
||||||
} // namespace
|
} // 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) {
|
void BufferedStackTrace::UnwindSlow(uptr pc, u32 max_depth) {
|
||||||
CHECK_GE(max_depth, 2);
|
CHECK_GE(max_depth, 2);
|
||||||
size = 0;
|
size = 0;
|
||||||
|
|
@ -171,4 +139,4 @@ void BufferedStackTrace::UnwindSlow(uptr pc, void *context, u32 max_depth) {
|
||||||
} // namespace __sanitizer
|
} // namespace __sanitizer
|
||||||
|
|
||||||
#endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD ||
|
#endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD ||
|
||||||
// SANITIZER_SOLARIS
|
// SANITIZER_SOLARIS || SANITIZER_HAIKU
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,11 @@ void BufferedStackTrace::UnwindSlow(uptr pc, void *context, u32 max_depth) {
|
||||||
stack_frame.AddrPC.Offset = ctx.Pc;
|
stack_frame.AddrPC.Offset = ctx.Pc;
|
||||||
stack_frame.AddrFrame.Offset = ctx.R11;
|
stack_frame.AddrFrame.Offset = ctx.R11;
|
||||||
stack_frame.AddrStack.Offset = ctx.Sp;
|
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
|
# else
|
||||||
int machine_type = IMAGE_FILE_MACHINE_I386;
|
int machine_type = IMAGE_FILE_MACHINE_I386;
|
||||||
stack_frame.AddrPC.Offset = ctx.Eip;
|
stack_frame.AddrPC.Offset = ctx.Eip;
|
||||||
|
|
|
||||||
|
|
@ -1011,6 +1011,9 @@ void SignalContext::InitPcSpBp() {
|
||||||
# if SANITIZER_ARM
|
# if SANITIZER_ARM
|
||||||
bp = (uptr)context_record->R11;
|
bp = (uptr)context_record->R11;
|
||||||
sp = (uptr)context_record->Sp;
|
sp = (uptr)context_record->Sp;
|
||||||
|
# elif SANITIZER_MIPS32
|
||||||
|
bp = (uptr)context_record->IntS8;
|
||||||
|
sp = (uptr)context_record->IntSp;
|
||||||
# else
|
# else
|
||||||
bp = (uptr)context_record->Ebp;
|
bp = (uptr)context_record->Ebp;
|
||||||
sp = (uptr)context_record->Esp;
|
sp = (uptr)context_record->Esp;
|
||||||
|
|
|
||||||
89
lib/libtsan/tsan_interceptors_posix.cpp
vendored
89
lib/libtsan/tsan_interceptors_posix.cpp
vendored
|
|
@ -12,6 +12,9 @@
|
||||||
// sanitizer_common/sanitizer_common_interceptors.inc
|
// sanitizer_common/sanitizer_common_interceptors.inc
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "interception/interception.h"
|
||||||
#include "sanitizer_common/sanitizer_allocator_dlsym.h"
|
#include "sanitizer_common/sanitizer_allocator_dlsym.h"
|
||||||
#include "sanitizer_common/sanitizer_atomic.h"
|
#include "sanitizer_common/sanitizer_atomic.h"
|
||||||
#include "sanitizer_common/sanitizer_errno.h"
|
#include "sanitizer_common/sanitizer_errno.h"
|
||||||
|
|
@ -19,21 +22,20 @@
|
||||||
#include "sanitizer_common/sanitizer_internal_defs.h"
|
#include "sanitizer_common/sanitizer_internal_defs.h"
|
||||||
#include "sanitizer_common/sanitizer_libc.h"
|
#include "sanitizer_common/sanitizer_libc.h"
|
||||||
#include "sanitizer_common/sanitizer_linux.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_netbsd.h"
|
||||||
#include "sanitizer_common/sanitizer_platform_limits_posix.h"
|
#include "sanitizer_common/sanitizer_platform_limits_posix.h"
|
||||||
#include "sanitizer_common/sanitizer_posix.h"
|
#include "sanitizer_common/sanitizer_posix.h"
|
||||||
#include "sanitizer_common/sanitizer_stacktrace.h"
|
#include "sanitizer_common/sanitizer_stacktrace.h"
|
||||||
#include "sanitizer_common/sanitizer_tls_get_addr.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_interceptors.h"
|
||||||
#include "tsan_interface.h"
|
#include "tsan_interface.h"
|
||||||
#include "tsan_platform.h"
|
|
||||||
#include "tsan_suppressions.h"
|
|
||||||
#include "tsan_rtl.h"
|
|
||||||
#include "tsan_mman.h"
|
#include "tsan_mman.h"
|
||||||
#include "tsan_fd.h"
|
#include "tsan_platform.h"
|
||||||
|
#include "tsan_rtl.h"
|
||||||
#include <stdarg.h>
|
#include "tsan_suppressions.h"
|
||||||
|
|
||||||
using namespace __tsan;
|
using namespace __tsan;
|
||||||
|
|
||||||
|
|
@ -177,7 +179,7 @@ struct ThreadSignalContext {
|
||||||
SignalDesc pending_signals[kSigCount];
|
SignalDesc pending_signals[kSigCount];
|
||||||
// emptyset and oldset are too big for stack.
|
// emptyset and oldset are too big for stack.
|
||||||
__sanitizer_sigset_t emptyset;
|
__sanitizer_sigset_t emptyset;
|
||||||
__sanitizer_sigset_t oldset;
|
__sanitizer::Vector<__sanitizer_sigset_t> oldset;
|
||||||
};
|
};
|
||||||
|
|
||||||
void EnterBlockingFunc(ThreadState *thr) {
|
void EnterBlockingFunc(ThreadState *thr) {
|
||||||
|
|
@ -558,6 +560,7 @@ static void SetJmp(ThreadState *thr, uptr sp) {
|
||||||
buf->shadow_stack_pos = thr->shadow_stack_pos;
|
buf->shadow_stack_pos = thr->shadow_stack_pos;
|
||||||
ThreadSignalContext *sctx = SigCtx(thr);
|
ThreadSignalContext *sctx = SigCtx(thr);
|
||||||
buf->int_signal_send = sctx ? sctx->int_signal_send : 0;
|
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_blocking_func = atomic_load(&thr->in_blocking_func, memory_order_relaxed);
|
||||||
buf->in_signal_handler = atomic_load(&thr->in_signal_handler,
|
buf->in_signal_handler = atomic_load(&thr->in_signal_handler,
|
||||||
memory_order_relaxed);
|
memory_order_relaxed);
|
||||||
|
|
@ -574,8 +577,11 @@ static void LongJmp(ThreadState *thr, uptr *env) {
|
||||||
while (thr->shadow_stack_pos > buf->shadow_stack_pos)
|
while (thr->shadow_stack_pos > buf->shadow_stack_pos)
|
||||||
FuncExit(thr);
|
FuncExit(thr);
|
||||||
ThreadSignalContext *sctx = SigCtx(thr);
|
ThreadSignalContext *sctx = SigCtx(thr);
|
||||||
if (sctx)
|
if (sctx) {
|
||||||
sctx->int_signal_send = buf->int_signal_send;
|
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,
|
atomic_store(&thr->in_blocking_func, buf->in_blocking_func,
|
||||||
memory_order_relaxed);
|
memory_order_relaxed);
|
||||||
atomic_store(&thr->in_signal_handler, buf->in_signal_handler,
|
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);
|
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) {
|
TSAN_INTERCEPTOR(void, cfree, void *p) {
|
||||||
if (UNLIKELY(!p))
|
if (UNLIKELY(!p))
|
||||||
return;
|
return;
|
||||||
|
|
@ -758,6 +799,9 @@ TSAN_INTERCEPTOR(uptr, malloc_usable_size, void *p) {
|
||||||
SCOPED_INTERCEPTOR_RAW(malloc_usable_size, p);
|
SCOPED_INTERCEPTOR_RAW(malloc_usable_size, p);
|
||||||
return user_alloc_usable_size(p);
|
return user_alloc_usable_size(p);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
# define TSAN_MAYBE_INTERCEPT_FREE_SIZED
|
||||||
|
# define TSAN_MAYBE_INTERCEPT_FREE_ALIGNED_SIZED
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TSAN_INTERCEPTOR(char *, strcpy, char *dst, const char *src) {
|
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,
|
static int guard_acquire(ThreadState *thr, uptr pc, atomic_uint32_t *g,
|
||||||
bool blocking_hooks = true) {
|
bool blocking_hooks = true) {
|
||||||
if (blocking_hooks)
|
bool in_potentially_blocking_region = false;
|
||||||
OnPotentiallyBlockingRegionBegin();
|
auto on_exit = at_scope_exit([&] {
|
||||||
auto on_exit = at_scope_exit([blocking_hooks] {
|
if (in_potentially_blocking_region)
|
||||||
if (blocking_hooks)
|
|
||||||
OnPotentiallyBlockingRegionEnd();
|
OnPotentiallyBlockingRegionEnd();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -912,8 +955,13 @@ static int guard_acquire(ThreadState *thr, uptr pc, atomic_uint32_t *g,
|
||||||
} else {
|
} else {
|
||||||
if ((cmp & kGuardWaiter) ||
|
if ((cmp & kGuardWaiter) ||
|
||||||
atomic_compare_exchange_strong(g, &cmp, 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);
|
FutexWait(g, cmp | kGuardWaiter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -976,6 +1024,7 @@ void PlatformCleanUpThreadState(ThreadState *thr) {
|
||||||
&thr->signal_ctx, memory_order_relaxed);
|
&thr->signal_ctx, memory_order_relaxed);
|
||||||
if (sctx) {
|
if (sctx) {
|
||||||
atomic_store(&thr->signal_ctx, 0, memory_order_relaxed);
|
atomic_store(&thr->signal_ctx, 0, memory_order_relaxed);
|
||||||
|
sctx->oldset.Reset();
|
||||||
UnmapOrDie(sctx, sizeof(*sctx));
|
UnmapOrDie(sctx, sizeof(*sctx));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2172,7 +2221,8 @@ void ProcessPendingSignalsImpl(ThreadState *thr) {
|
||||||
return;
|
return;
|
||||||
atomic_fetch_add(&thr->in_signal_handler, 1, memory_order_relaxed);
|
atomic_fetch_add(&thr->in_signal_handler, 1, memory_order_relaxed);
|
||||||
internal_sigfillset(&sctx->emptyset);
|
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);
|
CHECK_EQ(res, 0);
|
||||||
for (int sig = 0; sig < kSigCount; sig++) {
|
for (int sig = 0; sig < kSigCount; sig++) {
|
||||||
SignalDesc *signal = &sctx->pending_signals[sig];
|
SignalDesc *signal = &sctx->pending_signals[sig];
|
||||||
|
|
@ -2182,8 +2232,9 @@ void ProcessPendingSignalsImpl(ThreadState *thr) {
|
||||||
&signal->ctx);
|
&signal->ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res = REAL(pthread_sigmask)(SIG_SETMASK, &sctx->oldset, 0);
|
res = REAL(pthread_sigmask)(SIG_SETMASK, oldset, 0);
|
||||||
CHECK_EQ(res, 0);
|
CHECK_EQ(res, 0);
|
||||||
|
sctx->oldset.PopBack();
|
||||||
atomic_fetch_add(&thr->in_signal_handler, -1, memory_order_relaxed);
|
atomic_fetch_add(&thr->in_signal_handler, -1, memory_order_relaxed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2951,6 +3002,8 @@ void InitializeInterceptors() {
|
||||||
TSAN_INTERCEPT(realloc);
|
TSAN_INTERCEPT(realloc);
|
||||||
TSAN_INTERCEPT(reallocarray);
|
TSAN_INTERCEPT(reallocarray);
|
||||||
TSAN_INTERCEPT(free);
|
TSAN_INTERCEPT(free);
|
||||||
|
TSAN_MAYBE_INTERCEPT_FREE_SIZED;
|
||||||
|
TSAN_MAYBE_INTERCEPT_FREE_ALIGNED_SIZED;
|
||||||
TSAN_INTERCEPT(cfree);
|
TSAN_INTERCEPT(cfree);
|
||||||
TSAN_INTERCEPT(munmap);
|
TSAN_INTERCEPT(munmap);
|
||||||
TSAN_MAYBE_INTERCEPT_MEMALIGN;
|
TSAN_MAYBE_INTERCEPT_MEMALIGN;
|
||||||
|
|
@ -3073,6 +3126,10 @@ void InitializeInterceptors() {
|
||||||
#if !SANITIZER_ANDROID
|
#if !SANITIZER_ANDROID
|
||||||
TSAN_INTERCEPT(dl_iterate_phdr);
|
TSAN_INTERCEPT(dl_iterate_phdr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Symbolization indirectly calls dl_iterate_phdr
|
||||||
|
ready_to_symbolize = true;
|
||||||
|
|
||||||
TSAN_MAYBE_INTERCEPT_ON_EXIT;
|
TSAN_MAYBE_INTERCEPT_ON_EXIT;
|
||||||
TSAN_INTERCEPT(__cxa_atexit);
|
TSAN_INTERCEPT(__cxa_atexit);
|
||||||
TSAN_INTERCEPT(_exit);
|
TSAN_INTERCEPT(_exit);
|
||||||
|
|
|
||||||
1
lib/libtsan/tsan_interface_java.cpp
vendored
1
lib/libtsan/tsan_interface_java.cpp
vendored
|
|
@ -122,7 +122,6 @@ void __tsan_java_move(jptr src, jptr dst, jptr size) {
|
||||||
DCHECK_GE(dst, jctx->heap_begin);
|
DCHECK_GE(dst, jctx->heap_begin);
|
||||||
DCHECK_LE(dst + size, jctx->heap_begin + jctx->heap_size);
|
DCHECK_LE(dst + size, jctx->heap_begin + jctx->heap_size);
|
||||||
DCHECK_NE(dst, src);
|
DCHECK_NE(dst, src);
|
||||||
DCHECK_NE(size, 0);
|
|
||||||
|
|
||||||
// Assuming it's not running concurrently with threads that do
|
// Assuming it's not running concurrently with threads that do
|
||||||
// memory accesses and mutex operations (stop-the-world phase).
|
// memory accesses and mutex operations (stop-the-world phase).
|
||||||
|
|
|
||||||
22
lib/libtsan/tsan_malloc_mac.cpp
vendored
22
lib/libtsan/tsan_malloc_mac.cpp
vendored
|
|
@ -73,15 +73,19 @@ using namespace __tsan;
|
||||||
invoke_free_hook(ptr); \
|
invoke_free_hook(ptr); \
|
||||||
SCOPED_INTERCEPTOR_RAW(free, ptr); \
|
SCOPED_INTERCEPTOR_RAW(free, ptr); \
|
||||||
user_free(thr, pc, ptr)
|
user_free(thr, pc, ptr)
|
||||||
#define COMMON_MALLOC_SIZE(ptr) uptr size = user_alloc_usable_size(ptr);
|
# define COMMON_MALLOC_FREE_SIZED(ptr, size) COMMON_MALLOC_FREE(ptr)
|
||||||
#define COMMON_MALLOC_FILL_STATS(zone, stats)
|
# define COMMON_MALLOC_FREE_ALIGNED_SIZED(ptr, alignment, size) \
|
||||||
#define COMMON_MALLOC_REPORT_UNKNOWN_REALLOC(ptr, zone_ptr, zone_name) \
|
COMMON_MALLOC_FREE(ptr)
|
||||||
(void)zone_name; \
|
# define COMMON_MALLOC_SIZE(ptr) uptr size = user_alloc_usable_size(ptr);
|
||||||
Report("mz_realloc(%p) -- attempting to realloc unallocated memory.\n", ptr);
|
# define COMMON_MALLOC_FILL_STATS(zone, stats)
|
||||||
#define COMMON_MALLOC_NAMESPACE __tsan
|
# define COMMON_MALLOC_REPORT_UNKNOWN_REALLOC(ptr, zone_ptr, zone_name) \
|
||||||
#define COMMON_MALLOC_HAS_ZONE_ENUMERATOR 0
|
(void)zone_name; \
|
||||||
#define COMMON_MALLOC_HAS_EXTRA_INTROSPECTION_INIT 0
|
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
|
#endif
|
||||||
|
|
|
||||||
34
lib/libtsan/tsan_platform.h
vendored
34
lib/libtsan/tsan_platform.h
vendored
|
|
@ -681,6 +681,33 @@ struct MappingGoMips64_47 {
|
||||||
static const uptr kShadowAdd = 0x200000000000ull;
|
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
|
Go on linux/s390x
|
||||||
0000 0000 1000 - 1000 0000 0000: executable and heap - 16 TiB
|
0000 0000 1000 - 1000 0000 0000: executable and heap - 16 TiB
|
||||||
|
|
@ -728,6 +755,8 @@ ALWAYS_INLINE auto SelectMapping(Arg arg) {
|
||||||
return Func::template Apply<MappingGoAarch64>(arg);
|
return Func::template Apply<MappingGoAarch64>(arg);
|
||||||
# elif defined(__loongarch_lp64)
|
# elif defined(__loongarch_lp64)
|
||||||
return Func::template Apply<MappingGoLoongArch64_47>(arg);
|
return Func::template Apply<MappingGoLoongArch64_47>(arg);
|
||||||
|
# elif SANITIZER_RISCV64
|
||||||
|
return Func::template Apply<MappingGoRiscv64>(arg);
|
||||||
# elif SANITIZER_WINDOWS
|
# elif SANITIZER_WINDOWS
|
||||||
return Func::template Apply<MappingGoWindows>(arg);
|
return Func::template Apply<MappingGoWindows>(arg);
|
||||||
# else
|
# else
|
||||||
|
|
@ -798,6 +827,7 @@ void ForEachMapping() {
|
||||||
Func::template Apply<MappingGoAarch64>();
|
Func::template Apply<MappingGoAarch64>();
|
||||||
Func::template Apply<MappingGoLoongArch64_47>();
|
Func::template Apply<MappingGoLoongArch64_47>();
|
||||||
Func::template Apply<MappingGoMips64_47>();
|
Func::template Apply<MappingGoMips64_47>();
|
||||||
|
Func::template Apply<MappingGoRiscv64>();
|
||||||
Func::template Apply<MappingGoS390x>();
|
Func::template Apply<MappingGoS390x>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -901,7 +931,7 @@ bool IsAppMem(uptr mem) { return SelectMapping<IsAppMemImpl>(mem); }
|
||||||
struct IsShadowMemImpl {
|
struct IsShadowMemImpl {
|
||||||
template <typename Mapping>
|
template <typename Mapping>
|
||||||
static bool Apply(uptr mem) {
|
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 {
|
struct IsMetaMemImpl {
|
||||||
template <typename Mapping>
|
template <typename Mapping>
|
||||||
static bool Apply(uptr mem) {
|
static bool Apply(uptr mem) {
|
||||||
return mem >= Mapping::kMetaShadowBeg && mem <= Mapping::kMetaShadowEnd;
|
return mem >= Mapping::kMetaShadowBeg && mem < Mapping::kMetaShadowEnd;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
29
lib/libtsan/tsan_platform_linux.cpp
vendored
29
lib/libtsan/tsan_platform_linux.cpp
vendored
|
|
@ -259,7 +259,15 @@ static void ReExecIfNeeded(bool ignore_heap) {
|
||||||
"WARNING: Program is run with randomized virtual address "
|
"WARNING: Program is run with randomized virtual address "
|
||||||
"space, which wouldn't work with ThreadSanitizer on Android.\n"
|
"space, which wouldn't work with ThreadSanitizer on Android.\n"
|
||||||
"Re-execing with fixed virtual address space.\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;
|
reexec = true;
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
@ -287,7 +295,18 @@ static void ReExecIfNeeded(bool ignore_heap) {
|
||||||
"possibly due to high-entropy ASLR.\n"
|
"possibly due to high-entropy ASLR.\n"
|
||||||
"Re-execing with fixed virtual address space.\n"
|
"Re-execing with fixed virtual address space.\n"
|
||||||
"N.B. reducing ASLR entropy is preferable.\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;
|
reexec = true;
|
||||||
} else {
|
} else {
|
||||||
Printf(
|
Printf(
|
||||||
|
|
@ -373,6 +392,12 @@ void InitializePlatformEarly() {
|
||||||
Printf("FATAL: Found %zd - Supported 39 and 48\n", vmaSize);
|
Printf("FATAL: Found %zd - Supported 39 and 48\n", vmaSize);
|
||||||
Die();
|
Die();
|
||||||
}
|
}
|
||||||
|
# else
|
||||||
|
if (vmaSize != 48) {
|
||||||
|
Printf("FATAL: ThreadSanitizer: unsupported VMA range\n");
|
||||||
|
Printf("FATAL: Found %zd - Supported 48\n", vmaSize);
|
||||||
|
Die();
|
||||||
|
}
|
||||||
# endif
|
# endif
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
|
|
||||||
31
lib/libtsan/tsan_rtl.cpp
vendored
31
lib/libtsan/tsan_rtl.cpp
vendored
|
|
@ -566,17 +566,32 @@ static bool IsValidMmapRange(uptr addr, uptr size) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnmapShadow(ThreadState *thr, uptr addr, uptr size) {
|
void UnmapShadow(ThreadState* thr, uptr addr, uptr size) {
|
||||||
if (size == 0 || !IsValidMmapRange(addr, size))
|
if (size == 0 || !IsValidMmapRange(addr, size))
|
||||||
return;
|
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;
|
ScopedGlobalProcessor sgp;
|
||||||
SlotLocker locker(thr, true);
|
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
|
#endif
|
||||||
|
|
||||||
void MapShadow(uptr addr, uptr size) {
|
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
|
// Ensure thead registry lock held, so as to synchronize
|
||||||
// with DoReset, which also access the mapped_shadow_* ctxt fields.
|
// with DoReset, which also access the mapped_shadow_* ctxt fields.
|
||||||
ThreadRegistryLock lock0(&ctx->thread_registry);
|
ThreadRegistryLock lock0(&ctx->thread_registry);
|
||||||
|
|
@ -624,6 +639,7 @@ void MapShadow(uptr addr, uptr size) {
|
||||||
static uptr mapped_meta_end = 0;
|
static uptr mapped_meta_end = 0;
|
||||||
uptr meta_begin = (uptr)MemToMeta(addr);
|
uptr meta_begin = (uptr)MemToMeta(addr);
|
||||||
uptr meta_end = (uptr)MemToMeta(addr + size);
|
uptr meta_end = (uptr)MemToMeta(addr + size);
|
||||||
|
// Windows wants 64K alignment.
|
||||||
meta_begin = RoundDownTo(meta_begin, 64 << 10);
|
meta_begin = RoundDownTo(meta_begin, 64 << 10);
|
||||||
meta_end = RoundUpTo(meta_end, 64 << 10);
|
meta_end = RoundUpTo(meta_end, 64 << 10);
|
||||||
if (!data_mapped) {
|
if (!data_mapped) {
|
||||||
|
|
@ -634,9 +650,6 @@ void MapShadow(uptr addr, uptr size) {
|
||||||
Die();
|
Die();
|
||||||
} else {
|
} else {
|
||||||
// Mapping continuous heap.
|
// 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);
|
CHECK_GT(meta_end, mapped_meta_end);
|
||||||
if (meta_begin < mapped_meta_end)
|
if (meta_begin < mapped_meta_end)
|
||||||
meta_begin = mapped_meta_end;
|
meta_begin = mapped_meta_end;
|
||||||
|
|
@ -679,6 +692,12 @@ void CheckUnwind() {
|
||||||
|
|
||||||
bool is_initialized;
|
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) {
|
void Initialize(ThreadState *thr) {
|
||||||
// Thread safe because done before all threads exist.
|
// Thread safe because done before all threads exist.
|
||||||
if (is_initialized)
|
if (is_initialized)
|
||||||
|
|
|
||||||
5
lib/libtsan/tsan_rtl.h
vendored
5
lib/libtsan/tsan_rtl.h
vendored
|
|
@ -54,13 +54,15 @@
|
||||||
|
|
||||||
namespace __tsan {
|
namespace __tsan {
|
||||||
|
|
||||||
|
extern bool ready_to_symbolize;
|
||||||
|
|
||||||
#if !SANITIZER_GO
|
#if !SANITIZER_GO
|
||||||
struct MapUnmapCallback;
|
struct MapUnmapCallback;
|
||||||
# if defined(__mips64) || defined(__aarch64__) || defined(__loongarch__) || \
|
# if defined(__mips64) || defined(__aarch64__) || defined(__loongarch__) || \
|
||||||
defined(__powerpc__) || SANITIZER_RISCV64
|
defined(__powerpc__) || SANITIZER_RISCV64
|
||||||
|
|
||||||
struct AP32 {
|
struct AP32 {
|
||||||
static const uptr kSpaceBeg = 0;
|
static const uptr kSpaceBeg = SANITIZER_MMAP_BEGIN;
|
||||||
static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE;
|
static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE;
|
||||||
static const uptr kMetadataSize = 0;
|
static const uptr kMetadataSize = 0;
|
||||||
typedef __sanitizer::CompactSizeClassMap SizeClassMap;
|
typedef __sanitizer::CompactSizeClassMap SizeClassMap;
|
||||||
|
|
@ -98,6 +100,7 @@ struct JmpBuf {
|
||||||
uptr sp;
|
uptr sp;
|
||||||
int int_signal_send;
|
int int_signal_send;
|
||||||
bool in_blocking_func;
|
bool in_blocking_func;
|
||||||
|
uptr oldset_stack_size;
|
||||||
uptr in_signal_handler;
|
uptr in_signal_handler;
|
||||||
uptr *shadow_stack_pos;
|
uptr *shadow_stack_pos;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
30
lib/libtsan/tsan_rtl_access.cpp
vendored
30
lib/libtsan/tsan_rtl_access.cpp
vendored
|
|
@ -523,9 +523,9 @@ SECOND:
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShadowSet(RawShadow* p, RawShadow* end, RawShadow v) {
|
void ShadowSet(RawShadow* p, RawShadow* end, RawShadow v) {
|
||||||
DCHECK_LE(p, end);
|
DCHECK_LT(p, end);
|
||||||
DCHECK(IsShadowMem(p));
|
DCHECK(IsShadowMem(p));
|
||||||
DCHECK(IsShadowMem(end));
|
DCHECK(IsShadowMem(end - 1));
|
||||||
UNUSED const uptr kAlign = kShadowCnt * kShadowSize;
|
UNUSED const uptr kAlign = kShadowCnt * kShadowSize;
|
||||||
DCHECK_EQ(reinterpret_cast<uptr>(p) % kAlign, 0);
|
DCHECK_EQ(reinterpret_cast<uptr>(p) % kAlign, 0);
|
||||||
DCHECK_EQ(reinterpret_cast<uptr>(end) % kAlign, 0);
|
DCHECK_EQ(reinterpret_cast<uptr>(end) % kAlign, 0);
|
||||||
|
|
@ -569,6 +569,7 @@ static void MemoryRangeSet(uptr addr, uptr size, RawShadow val) {
|
||||||
RawShadow* mid1 =
|
RawShadow* mid1 =
|
||||||
Min(end, reinterpret_cast<RawShadow*>(RoundUp(
|
Min(end, reinterpret_cast<RawShadow*>(RoundUp(
|
||||||
reinterpret_cast<uptr>(begin) + kPageSize / 2, kPageSize)));
|
reinterpret_cast<uptr>(begin) + kPageSize / 2, kPageSize)));
|
||||||
|
// begin must < mid1
|
||||||
ShadowSet(begin, mid1, val);
|
ShadowSet(begin, mid1, val);
|
||||||
// Reset middle part.
|
// Reset middle part.
|
||||||
RawShadow* mid2 = RoundDown(end, kPageSize);
|
RawShadow* mid2 = RoundDown(end, kPageSize);
|
||||||
|
|
@ -577,7 +578,10 @@ static void MemoryRangeSet(uptr addr, uptr size, RawShadow val) {
|
||||||
Die();
|
Die();
|
||||||
}
|
}
|
||||||
// Set the ending.
|
// 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) {
|
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);
|
RawShadow* shadow_mem = MemToShadow(addr);
|
||||||
DPrintf2("#%d: MemoryAccessRange: @%p %p size=%d is_read=%d\n", thr->tid,
|
DPrintf2("#%d: MemoryAccessRange: @%p %p size=%d is_read=%d\n", thr->tid,
|
||||||
(void*)pc, (void*)addr, (int)size, is_read);
|
(void*)pc, (void*)addr, (int)size, is_read);
|
||||||
|
DCHECK_NE(size, 0);
|
||||||
#if SANITIZER_DEBUG
|
#if SANITIZER_DEBUG
|
||||||
if (!IsAppMem(addr)) {
|
if (!IsAppMem(addr)) {
|
||||||
Printf("Access to non app mem start: %p\n", (void*)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));
|
DCHECK(IsShadowMem(shadow_mem));
|
||||||
}
|
}
|
||||||
|
|
||||||
RawShadow* shadow_mem_end = reinterpret_cast<RawShadow*>(
|
uptr rounded_size =
|
||||||
reinterpret_cast<uptr>(shadow_mem) + size * kShadowMultiplier - 1);
|
(RoundUpTo(addr + size, kShadowCell) - RoundDownTo(addr, kShadowCell));
|
||||||
if (!IsShadowMem(shadow_mem_end)) {
|
RawShadow* shadow_mem_end =
|
||||||
Printf("Bad shadow end addr: %p (%p)\n", 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));
|
(void*)(addr + size - 1));
|
||||||
Printf(
|
Printf(
|
||||||
"Shadow start addr (ok): %p (%p); size: 0x%zx; kShadowMultiplier: "
|
"Shadow start addr (ok): %p (%p); size: 0x%zx; rounded_size: 0x%zx; "
|
||||||
"%zx\n",
|
"kShadowMultiplier: %zx\n",
|
||||||
shadow_mem, (void*)addr, size, kShadowMultiplier);
|
shadow_mem, (void*)addr, size, rounded_size, kShadowMultiplier);
|
||||||
DCHECK(IsShadowMem(shadow_mem_end));
|
DCHECK(IsShadowMem(shadow_mem_end - 1));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
11
lib/libtsan/tsan_rtl_report.cpp
vendored
11
lib/libtsan/tsan_rtl_report.cpp
vendored
|
|
@ -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[i] = ptrace->trace_buffer[ptrace->size - i - 1];
|
||||||
ptrace->trace_buffer[ptrace->size - i - 1] = tmp;
|
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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
27
lib/libtsan/tsan_sync.cpp
vendored
27
lib/libtsan/tsan_sync.cpp
vendored
|
|
@ -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).
|
// there are no concurrent accesses to the regions (e.g. stop-the-world).
|
||||||
CHECK_NE(src, dst);
|
CHECK_NE(src, dst);
|
||||||
CHECK_NE(sz, 0);
|
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;
|
uptr diff = dst - src;
|
||||||
u32 *src_meta = MemToMeta(src);
|
u32 *src_meta, *dst_meta, *src_meta_end;
|
||||||
u32 *dst_meta = MemToMeta(dst);
|
uptr inc;
|
||||||
u32 *src_meta_end = MemToMeta(src + sz);
|
if (dst < src) {
|
||||||
uptr inc = 1;
|
src_meta = MemToMeta(src);
|
||||||
if (dst > src) {
|
dst_meta = MemToMeta(dst);
|
||||||
|
src_meta_end = MemToMeta(src + sz);
|
||||||
|
inc = 1;
|
||||||
|
} else {
|
||||||
src_meta = MemToMeta(src + sz) - 1;
|
src_meta = MemToMeta(src + sz) - 1;
|
||||||
dst_meta = MemToMeta(dst + sz) - 1;
|
dst_meta = MemToMeta(dst + sz) - 1;
|
||||||
src_meta_end = MemToMeta(src) - 1;
|
src_meta_end = MemToMeta(src) - 1;
|
||||||
|
|
|
||||||
2
lib/libtsan/ubsan/ubsan_platform.h
vendored
2
lib/libtsan/ubsan/ubsan_platform.h
vendored
|
|
@ -16,7 +16,7 @@
|
||||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || \
|
#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || \
|
||||||
defined(__NetBSD__) || defined(__DragonFly__) || \
|
defined(__NetBSD__) || defined(__DragonFly__) || \
|
||||||
(defined(__sun__) && defined(__svr4__)) || defined(_WIN32) || \
|
(defined(__sun__) && defined(__svr4__)) || defined(_WIN32) || \
|
||||||
defined(__Fuchsia__)
|
defined(__Fuchsia__) || defined(__HAIKU__)
|
||||||
#define CAN_SANITIZE_UB 1
|
#define CAN_SANITIZE_UB 1
|
||||||
#else
|
#else
|
||||||
# define CAN_SANITIZE_UB 0
|
# define CAN_SANITIZE_UB 0
|
||||||
|
|
|
||||||
|
|
@ -403,6 +403,7 @@ const sanitizer_common_sources = [_][]const u8{
|
||||||
"sanitizer_flag_parser.cpp",
|
"sanitizer_flag_parser.cpp",
|
||||||
"sanitizer_flags.cpp",
|
"sanitizer_flags.cpp",
|
||||||
"sanitizer_fuchsia.cpp",
|
"sanitizer_fuchsia.cpp",
|
||||||
|
"sanitizer_haiku.cpp",
|
||||||
"sanitizer_libc.cpp",
|
"sanitizer_libc.cpp",
|
||||||
"sanitizer_libignore.cpp",
|
"sanitizer_libignore.cpp",
|
||||||
"sanitizer_linux.cpp",
|
"sanitizer_linux.cpp",
|
||||||
|
|
@ -420,6 +421,7 @@ const sanitizer_common_sources = [_][]const u8{
|
||||||
"sanitizer_procmaps_bsd.cpp",
|
"sanitizer_procmaps_bsd.cpp",
|
||||||
"sanitizer_procmaps_common.cpp",
|
"sanitizer_procmaps_common.cpp",
|
||||||
"sanitizer_procmaps_fuchsia.cpp",
|
"sanitizer_procmaps_fuchsia.cpp",
|
||||||
|
"sanitizer_procmaps_haiku.cpp",
|
||||||
"sanitizer_procmaps_linux.cpp",
|
"sanitizer_procmaps_linux.cpp",
|
||||||
"sanitizer_procmaps_mac.cpp",
|
"sanitizer_procmaps_mac.cpp",
|
||||||
"sanitizer_procmaps_solaris.cpp",
|
"sanitizer_procmaps_solaris.cpp",
|
||||||
|
|
@ -478,6 +480,7 @@ const sanitizer_symbolizer_sources = [_][]const u8{
|
||||||
};
|
};
|
||||||
|
|
||||||
const interception_sources = [_][]const u8{
|
const interception_sources = [_][]const u8{
|
||||||
|
"interception_aix.cpp",
|
||||||
"interception_linux.cpp",
|
"interception_linux.cpp",
|
||||||
"interception_mac.cpp",
|
"interception_mac.cpp",
|
||||||
"interception_win.cpp",
|
"interception_win.cpp",
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue