libtsan: update to LLVM 21

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