Vendor import of compiler-rt trunk r304149:

https://llvm.org/svn/llvm-project/compiler-rt/trunk@304149
This commit is contained in:
Dimitry Andric 2017-05-29 16:25:57 +00:00
parent 99ea5e489f
commit 224c1c721b
62 changed files with 552 additions and 187 deletions

View File

@ -63,7 +63,9 @@ else()
set(COMPILER_RT_TEST_COMPILER_ID GNU)
endif()
string(TOLOWER ${CMAKE_SYSTEM_NAME} COMPILER_RT_OS_DIR)
if(NOT DEFINED COMPILER_RT_OS_DIR)
string(TOLOWER ${CMAKE_SYSTEM_NAME} COMPILER_RT_OS_DIR)
endif()
set(COMPILER_RT_LIBRARY_OUTPUT_DIR
${COMPILER_RT_OUTPUT_DIR}/lib/${COMPILER_RT_OS_DIR})
set(COMPILER_RT_LIBRARY_INSTALL_DIR

View File

@ -24,7 +24,7 @@ int foo(int x, int y) {
set(ARM64 aarch64)
set(ARM32 arm armhf armv6m)
set(ARM32 arm armhf armv6m armv7m armv7em armv7 armv7s armv7k)
set(X86 i386 i686)
set(X86_64 x86_64)
set(MIPS32 mips mipsel)

View File

@ -357,28 +357,22 @@ DEFINE_REAL_PTHREAD_FUNCTIONS
#if SANITIZER_ANDROID
INTERCEPTOR(void*, bsd_signal, int signum, void *handler) {
if (!IsHandledDeadlySignal(signum) ||
common_flags()->allow_user_segv_handler) {
if (GetHandleSignalMode(signum) != kHandleSignalExclusive)
return REAL(bsd_signal)(signum, handler);
}
return 0;
}
#endif
INTERCEPTOR(void*, signal, int signum, void *handler) {
if (!IsHandledDeadlySignal(signum) ||
common_flags()->allow_user_segv_handler) {
if (GetHandleSignalMode(signum) != kHandleSignalExclusive)
return REAL(signal)(signum, handler);
}
return nullptr;
}
INTERCEPTOR(int, sigaction, int signum, const struct sigaction *act,
struct sigaction *oldact) {
if (!IsHandledDeadlySignal(signum) ||
common_flags()->allow_user_segv_handler) {
if (GetHandleSignalMode(signum) != kHandleSignalExclusive)
return REAL(sigaction)(signum, act, oldact);
}
return 0;
}

View File

@ -80,7 +80,7 @@ static long WINAPI SEHHandler(EXCEPTION_POINTERS *info) {
INTERCEPTOR_WINAPI(LPTOP_LEVEL_EXCEPTION_FILTER, SetUnhandledExceptionFilter,
LPTOP_LEVEL_EXCEPTION_FILTER ExceptionFilter) {
CHECK(REAL(SetUnhandledExceptionFilter));
if (ExceptionFilter == &SEHHandler || common_flags()->allow_user_segv_handler)
if (ExceptionFilter == &SEHHandler)
return REAL(SetUnhandledExceptionFilter)(ExceptionFilter);
// We record the user provided exception handler to be called for all the
// exceptions unhandled by asan.

View File

@ -327,11 +327,6 @@ exec $_to \$@
EOF
}
# On Android-L not allowing user segv handler breaks some applications.
if [[ PRE_L -eq 0 ]]; then
ASAN_OPTIONS="$ASAN_OPTIONS,allow_user_segv_handler=1"
fi
if [[ x$extra_options != x ]] ; then
ASAN_OPTIONS="$ASAN_OPTIONS,$extra_options"
fi

View File

@ -102,9 +102,6 @@ TEST(AddressSanitizerInterface, GetHeapSizeTest) {
}
}
#ifndef __powerpc64__
// FIXME: This has not reliably worked on powerpc since r279664. Re-enable
// this once the problem is tracked down and fixed.
static const size_t kManyThreadsMallocSizes[] = {5, 1UL<<10, 1UL<<14, 357};
static const size_t kManyThreadsIterations = 250;
static const size_t kManyThreadsNumThreads =
@ -138,7 +135,6 @@ TEST(AddressSanitizerInterface, ManyThreadsWithStatsStressTest) {
// so we can't check for equality here.
EXPECT_LT(after_test, before_test + (1UL<<20));
}
#endif
static void DoDoubleFree() {
int *x = Ident(new int);

View File

@ -97,9 +97,6 @@ TEST(AddressSanitizer, NoInstMallocTest) {
MallocStress(ASAN_LOW_MEMORY ? 300000 : 1000000);
}
#ifndef __powerpc64__
// FIXME: This has not reliably worked on powerpc since r279664. Re-enable
// this once the problem is tracked down and fixed.
TEST(AddressSanitizer, ThreadedMallocStressTest) {
const int kNumThreads = 4;
const int kNumIterations = (ASAN_LOW_MEMORY) ? 10000 : 100000;
@ -112,7 +109,6 @@ TEST(AddressSanitizer, ThreadedMallocStressTest) {
PTHREAD_JOIN(t[i], 0);
}
}
#endif
static void PrintShadow(const char *tag, uptr ptr, size_t size) {
fprintf(stderr, "%s shadow: %lx size % 3ld: ", tag, (long)ptr, (long)size);
@ -210,10 +206,6 @@ void *ThreadedOneSizeMallocStress(void *unused) {
return NULL;
}
#ifndef __powerpc64__
// FIXME: This has not reliably worked on powerpc since r279664. Re-enable
// this once the problem is tracked down and fixed.
TEST(AddressSanitizer, ThreadedOneSizeMallocStressTest) {
const int kNumThreads = 4;
pthread_t t[kNumThreads];
@ -224,7 +216,6 @@ TEST(AddressSanitizer, ThreadedOneSizeMallocStressTest) {
PTHREAD_JOIN(t[i], 0);
}
}
#endif
TEST(AddressSanitizer, ShadowRegionIsPoisonedTest) {
using __asan::kHighMemEnd;

View File

@ -251,7 +251,8 @@ TEST(AddressSanitizer, BitFieldNegativeTest) {
namespace {
const char kSEGVCrash[] = "AddressSanitizer: SEGV on unknown address";
const char kOverriddenHandler[] = "ASan signal handler has been overridden\n";
const char kOverriddenSigactionHandler[] = "Test sigaction handler\n";
const char kOverriddenSignalHandler[] = "Test signal handler\n";
TEST(AddressSanitizer, WildAddressTest) {
char *c = (char*)0x123;
@ -259,12 +260,12 @@ TEST(AddressSanitizer, WildAddressTest) {
}
void my_sigaction_sighandler(int, siginfo_t*, void*) {
fprintf(stderr, kOverriddenHandler);
fprintf(stderr, kOverriddenSigactionHandler);
exit(1);
}
void my_signal_sighandler(int signum) {
fprintf(stderr, kOverriddenHandler);
fprintf(stderr, kOverriddenSignalHandler);
exit(1);
}
@ -273,16 +274,20 @@ TEST(AddressSanitizer, SignalTest) {
memset(&sigact, 0, sizeof(sigact));
sigact.sa_sigaction = my_sigaction_sighandler;
sigact.sa_flags = SA_SIGINFO;
// ASan should silently ignore sigaction()...
char *c = (char *)0x123;
EXPECT_DEATH(*c = 0, kSEGVCrash);
// ASan should allow to set sigaction()...
EXPECT_EQ(0, sigaction(SIGSEGV, &sigact, 0));
#ifdef __APPLE__
EXPECT_EQ(0, sigaction(SIGBUS, &sigact, 0));
#endif
char *c = (char*)0x123;
EXPECT_DEATH(*c = 0, kSEGVCrash);
EXPECT_DEATH(*c = 0, kOverriddenSigactionHandler);
// ... and signal().
EXPECT_EQ(0, signal(SIGSEGV, my_signal_sighandler));
EXPECT_DEATH(*c = 0, kSEGVCrash);
EXPECT_NE(SIG_ERR, signal(SIGSEGV, my_signal_sighandler));
EXPECT_DEATH(*c = 0, kOverriddenSignalHandler);
}
} // namespace
#endif

View File

@ -42,6 +42,8 @@ set(GENERIC_SOURCES
ashlti3.c
ashrdi3.c
ashrti3.c
bswapdi2.c
bswapsi2.c
clear_cache.c
clzdi2.c
clzsi2.c
@ -163,8 +165,7 @@ set(GENERIC_SOURCES
udivti3.c
umoddi3.c
umodsi3.c
umodti3.c
emutls.c)
umodti3.c)
set(GENERIC_TF_SOURCES
comparetf2.c
@ -193,6 +194,7 @@ option(COMPILER_RT_EXCLUDE_ATOMIC_BUILTIN
if(NOT COMPILER_RT_BAREMETAL_BUILD)
set(GENERIC_SOURCES
${GENERIC_SOURCES}
emutls.c
enable_execute_stack.c)
endif()

View File

@ -57,8 +57,8 @@ si_int __popcountsi2(si_int a); // bit population
si_int __popcountdi2(di_int a); // bit population
si_int __popcountti2(ti_int a); // bit population
uint32_t __bswapsi2(uint32_t a); // a byteswapped, arm only
uint64_t __bswapdi2(uint64_t a); // a byteswapped, arm only
uint32_t __bswapsi2(uint32_t a); // a byteswapped
uint64_t __bswapdi2(uint64_t a); // a byteswapped
// Integral arithmetic

View File

@ -48,7 +48,12 @@ DEFINE_COMPILERRT_FUNCTION(__aeabi_cdcmpeq)
// NaN has been ruled out, so __aeabi_cdcmple can't trap
bne __aeabi_cdcmple
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
mov ip, #APSR_C
msr APSR_nzcvq, ip
#else
msr CPSR_f, #APSR_C
#endif
JMP(lr)
#endif
END_COMPILERRT_FUNCTION(__aeabi_cdcmpeq)
@ -95,17 +100,23 @@ DEFINE_COMPILERRT_FUNCTION(__aeabi_cdcmple)
lsls r0, r0, #31
pop {r0-r3, pc}
#else
ITT(eq)
moveq ip, #0
beq 1f
ldm sp, {r0-r3}
bl __aeabi_dcmpeq
cmp r0, #1
ITE(eq)
moveq ip, #(APSR_C | APSR_Z)
movne ip, #(APSR_C)
1:
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
msr APSR_nzcvq, ip
#else
msr CPSR_f, ip
#endif
pop {r0-r3}
POP_PC()
#endif

View File

@ -48,7 +48,12 @@ DEFINE_COMPILERRT_FUNCTION(__aeabi_cfcmpeq)
// NaN has been ruled out, so __aeabi_cfcmple can't trap
bne __aeabi_cfcmple
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
mov ip, #APSR_C
msr APSR_nzcvq, ip
#else
msr CPSR_f, #APSR_C
#endif
JMP(lr)
#endif
END_COMPILERRT_FUNCTION(__aeabi_cfcmpeq)
@ -95,17 +100,23 @@ DEFINE_COMPILERRT_FUNCTION(__aeabi_cfcmple)
lsls r0, r0, #31
pop {r0-r3, pc}
#else
ITT(eq)
moveq ip, #0
beq 1f
ldm sp, {r0-r3}
bl __aeabi_fcmpeq
cmp r0, #1
ITE(eq)
moveq ip, #(APSR_C | APSR_Z)
movne ip, #(APSR_C)
1:
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
msr APSR_nzcvq, ip
#else
msr CPSR_f, ip
#endif
pop {r0-r3}
POP_PC()
#endif

View File

@ -27,6 +27,7 @@ DEFINE_COMPILERRT_FUNCTION(__eqdf2vfp)
vcmp.f64 d6, d7
#endif
vmrs apsr_nzcv, fpscr
ITE(eq)
moveq r0, #1 // set result register to 1 if equal
movne r0, #0
bx lr

View File

@ -27,6 +27,7 @@ DEFINE_COMPILERRT_FUNCTION(__eqsf2vfp)
vcmp.f32 s14, s15
#endif
vmrs apsr_nzcv, fpscr
ITE(eq)
moveq r0, #1 // set result register to 1 if equal
movne r0, #0
bx lr

View File

@ -27,6 +27,7 @@ DEFINE_COMPILERRT_FUNCTION(__gedf2vfp)
vcmp.f64 d6, d7
#endif
vmrs apsr_nzcv, fpscr
ITE(ge)
movge r0, #1 // set result register to 1 if greater than or equal
movlt r0, #0
bx lr

View File

@ -27,6 +27,7 @@ DEFINE_COMPILERRT_FUNCTION(__gesf2vfp)
vcmp.f32 s14, s15
#endif
vmrs apsr_nzcv, fpscr
ITE(ge)
movge r0, #1 // set result register to 1 if greater than or equal
movlt r0, #0
bx lr

View File

@ -27,6 +27,7 @@ DEFINE_COMPILERRT_FUNCTION(__gtdf2vfp)
vcmp.f64 d6, d7
#endif
vmrs apsr_nzcv, fpscr
ITE(gt)
movgt r0, #1 // set result register to 1 if equal
movle r0, #0
bx lr

View File

@ -27,6 +27,7 @@ DEFINE_COMPILERRT_FUNCTION(__gtsf2vfp)
vcmp.f32 s14, s15
#endif
vmrs apsr_nzcv, fpscr
ITE(gt)
movgt r0, #1 // set result register to 1 if equal
movle r0, #0
bx lr

View File

@ -27,6 +27,7 @@ DEFINE_COMPILERRT_FUNCTION(__ledf2vfp)
vcmp.f64 d6, d7
#endif
vmrs apsr_nzcv, fpscr
ITE(ls)
movls r0, #1 // set result register to 1 if equal
movhi r0, #0
bx lr

View File

@ -27,6 +27,7 @@ DEFINE_COMPILERRT_FUNCTION(__lesf2vfp)
vcmp.f32 s14, s15
#endif
vmrs apsr_nzcv, fpscr
ITE(ls)
movls r0, #1 // set result register to 1 if equal
movhi r0, #0
bx lr

View File

@ -27,6 +27,7 @@ DEFINE_COMPILERRT_FUNCTION(__ltdf2vfp)
vcmp.f64 d6, d7
#endif
vmrs apsr_nzcv, fpscr
ITE(mi)
movmi r0, #1 // set result register to 1 if equal
movpl r0, #0
bx lr

View File

@ -27,6 +27,7 @@ DEFINE_COMPILERRT_FUNCTION(__ltsf2vfp)
vcmp.f32 s14, s15
#endif
vmrs apsr_nzcv, fpscr
ITE(mi)
movmi r0, #1 // set result register to 1 if equal
movpl r0, #0
bx lr

View File

@ -27,6 +27,7 @@ DEFINE_COMPILERRT_FUNCTION(__nedf2vfp)
vcmp.f64 d6, d7
#endif
vmrs apsr_nzcv, fpscr
ITE(ne)
movne r0, #1 // set result register to 0 if unequal
moveq r0, #0
bx lr

View File

@ -27,6 +27,7 @@ DEFINE_COMPILERRT_FUNCTION(__nesf2vfp)
vcmp.f32 s14, s15
#endif
vmrs apsr_nzcv, fpscr
ITE(ne)
movne r0, #1 // set result register to 1 if unequal
moveq r0, #0
bx lr

View File

@ -27,6 +27,7 @@ DEFINE_COMPILERRT_FUNCTION(__unorddf2vfp)
vcmp.f64 d6, d7
#endif
vmrs apsr_nzcv, fpscr
ITE(vs)
movvs r0, #1 // set result register to 1 if "overflow" (any NaNs)
movvc r0, #0
bx lr

View File

@ -27,6 +27,7 @@ DEFINE_COMPILERRT_FUNCTION(__unordsf2vfp)
vcmp.f32 s14, s15
#endif
vmrs apsr_nzcv, fpscr
ITE(vs)
movvs r0, #1 // set result register to 1 if "overflow" (any NaNs)
movvc r0, #0
bx lr

View File

@ -96,9 +96,11 @@
#if __ARM_ARCH_ISA_THUMB == 2
#define IT(cond) it cond
#define ITT(cond) itt cond
#define ITE(cond) ite cond
#else
#define IT(cond)
#define ITT(cond)
#define ITE(cond)
#endif
#if __ARM_ARCH_ISA_THUMB == 2

27
lib/builtins/bswapdi2.c Normal file
View File

@ -0,0 +1,27 @@
/* ===-- bswapdi2.c - Implement __bswapdi2 ---------------------------------===
*
* The LLVM Compiler Infrastructure
*
* This file is dual licensed under the MIT and the University of Illinois Open
* Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
* This file implements __bswapdi2 for the compiler_rt library.
*
* ===----------------------------------------------------------------------===
*/
#include "int_lib.h"
COMPILER_RT_ABI uint64_t __bswapdi2(uint64_t u) {
return (
(((u)&0xff00000000000000ULL) >> 56) |
(((u)&0x00ff000000000000ULL) >> 40) |
(((u)&0x0000ff0000000000ULL) >> 24) |
(((u)&0x000000ff00000000ULL) >> 8) |
(((u)&0x00000000ff000000ULL) << 8) |
(((u)&0x0000000000ff0000ULL) << 24) |
(((u)&0x000000000000ff00ULL) << 40) |
(((u)&0x00000000000000ffULL) << 56));
}

23
lib/builtins/bswapsi2.c Normal file
View File

@ -0,0 +1,23 @@
/* ===-- bswapsi2.c - Implement __bswapsi2 ---------------------------------===
*
* The LLVM Compiler Infrastructure
*
* This file is dual licensed under the MIT and the University of Illinois Open
* Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
* This file implements __bswapsi2 for the compiler_rt library.
*
* ===----------------------------------------------------------------------===
*/
#include "int_lib.h"
COMPILER_RT_ABI uint32_t __bswapsi2(uint32_t u) {
return (
(((u)&0xff000000) >> 24) |
(((u)&0x00ff0000) >> 8) |
(((u)&0x0000ff00) << 8) |
(((u)&0x000000ff) << 24));
}

View File

@ -265,19 +265,21 @@ static void ProcessThreads(SuspendedThreadsList const &suspended_threads,
}
if (flags()->use_tls) {
LOG_THREADS("TLS at %p-%p.\n", tls_begin, tls_end);
if (cache_begin == cache_end) {
ScanRangeForPointers(tls_begin, tls_end, frontier, "TLS", kReachable);
} else {
// Because LSan should not be loaded with dlopen(), we can assume
// that allocator cache will be part of static TLS image.
CHECK_LE(tls_begin, cache_begin);
CHECK_GE(tls_end, cache_end);
if (tls_begin < cache_begin)
ScanRangeForPointers(tls_begin, cache_begin, frontier, "TLS",
kReachable);
if (tls_end > cache_end)
ScanRangeForPointers(cache_end, tls_end, frontier, "TLS", kReachable);
if (tls_begin) {
LOG_THREADS("TLS at %p-%p.\n", tls_begin, tls_end);
// If the tls and cache ranges don't overlap, scan full tls range,
// otherwise, only scan the non-overlapping portions
if (cache_begin == cache_end || tls_end < cache_begin ||
tls_begin > cache_end) {
ScanRangeForPointers(tls_begin, tls_end, frontier, "TLS", kReachable);
} else {
if (tls_begin < cache_begin)
ScanRangeForPointers(tls_begin, cache_begin, frontier, "TLS",
kReachable);
if (tls_end > cache_end)
ScanRangeForPointers(cache_end, tls_end, frontier, "TLS",
kReachable);
}
}
if (dtls && !DTLSInDestruction(dtls)) {
for (uptr j = 0; j < dtls->dtv_size; ++j) {

View File

@ -91,12 +91,7 @@ LoadedModule *GetLinker() { return nullptr; }
// Required on Linux for initialization of TLS behavior, but should not be
// required on Darwin.
void InitializePlatformSpecificModules() {
if (flags()->use_tls) {
Report("use_tls=1 is not supported on Darwin.\n");
Die();
}
}
void InitializePlatformSpecificModules() {}
// Scans global variables for heap pointers.
void ProcessGlobalRegions(Frontier *frontier) {

View File

@ -30,7 +30,7 @@ LSAN_FLAG(bool, use_globals, true,
"Root set: include global variables (.data and .bss)")
LSAN_FLAG(bool, use_stacks, true, "Root set: include thread stacks")
LSAN_FLAG(bool, use_registers, true, "Root set: include thread registers")
LSAN_FLAG(bool, use_tls, !SANITIZER_MAC,
LSAN_FLAG(bool, use_tls, true,
"Root set: include TLS and thread-specific storage")
LSAN_FLAG(bool, use_root_regions, true,
"Root set: include regions added via __lsan_register_root_region().")

View File

@ -319,5 +319,3 @@ class SizeClassAllocator32 {
ByteMap possible_regions;
SizeClassInfo size_class_info_array[kNumClasses];
};

View File

@ -380,7 +380,7 @@ void SetSoftRssLimitExceededCallback(void (*Callback)(bool exceeded));
// Functions related to signal handling.
typedef void (*SignalHandlerType)(int, void *, void *);
bool IsHandledDeadlySignal(int signum);
HandleSignalMode GetHandleSignalMode(int signum);
void InstallDeadlySignalHandlers(SignalHandlerType handler);
const char *DescribeSignalOrException(int signo);
// Alternative signal stack (POSIX-only).

View File

@ -64,6 +64,11 @@ inline bool FlagHandler<HandleSignalMode>::Parse(const char *value) {
*t_ = b ? kHandleSignalYes : kHandleSignalNo;
return true;
}
if (internal_strcmp(value, "2") == 0 ||
internal_strcmp(value, "exclusive") == 0) {
*t_ = kHandleSignalExclusive;
return true;
}
Printf("ERROR: Invalid value for signal handler option: '%s'\n", value);
return false;
}

View File

@ -21,6 +21,7 @@ namespace __sanitizer {
enum HandleSignalMode {
kHandleSignalNo,
kHandleSignalYes,
kHandleSignalExclusive,
};
struct CommonFlags {

View File

@ -75,12 +75,13 @@ COMMON_FLAG(bool, print_summary, true,
"If false, disable printing error summaries in addition to error "
"reports.")
COMMON_FLAG(int, print_module_map, 0,
"OS X only. 0 = don't print, 1 = print only once before process "
"exits, 2 = print after each report.")
"OS X only (0 - don't print, 1 - print only once before process "
"exits, 2 - print after each report).")
COMMON_FLAG(bool, check_printf, true, "Check printf arguments.")
#define COMMON_FLAG_HANDLE_SIGNAL_HELP(signal) \
"Controls custom tool's " #signal " handler (0 - do not registers the " \
"handler, 1 - register the handler). "
"handler, 1 - register the handler and allow user to set own, " \
"2 - registers the handler and block user from changing it). "
COMMON_FLAG(HandleSignalMode, handle_segv, kHandleSignalYes,
COMMON_FLAG_HANDLE_SIGNAL_HELP(SIGSEGV))
COMMON_FLAG(HandleSignalMode, handle_sigbus, kHandleSignalYes,
@ -92,9 +93,6 @@ COMMON_FLAG(HandleSignalMode, handle_sigill, kHandleSignalNo,
COMMON_FLAG(HandleSignalMode, handle_sigfpe, kHandleSignalYes,
COMMON_FLAG_HANDLE_SIGNAL_HELP(SIGFPE))
#undef COMMON_FLAG_HANDLE_SIGNAL_HELP
COMMON_FLAG(bool, allow_user_segv_handler, false,
"If set, allows user to register a SEGV handler even if the tool "
"registers one.")
COMMON_FLAG(bool, use_sigaltstack, true,
"If set, uses alternate stack for signal handling.")
COMMON_FLAG(bool, detect_deadlocks, false,

View File

@ -549,7 +549,7 @@ void BlockingMutex::Lock() {
void BlockingMutex::Unlock() {
atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
u32 v = atomic_exchange(m, MtxUnlocked, memory_order_relaxed);
u32 v = atomic_exchange(m, MtxUnlocked, memory_order_release);
CHECK_NE(v, MtxUnlocked);
if (v == MtxSleeping) {
#if SANITIZER_FREEBSD
@ -1394,7 +1394,7 @@ AndroidApiLevel AndroidGetApiLevel() {
#endif
bool IsHandledDeadlySignal(int signum) {
HandleSignalMode GetHandleSignalMode(int signum) {
switch (signum) {
case SIGABRT:
return common_flags()->handle_abort;
@ -1407,7 +1407,7 @@ bool IsHandledDeadlySignal(int signum) {
case SIGBUS:
return common_flags()->handle_sigbus;
}
return false;
return kHandleSignalNo;
}
#if !SANITIZER_GO

View File

@ -178,6 +178,13 @@ static bool FixedCVE_2016_2143() {
// 4.4.6+ is OK.
if (minor == 4 && patch >= 6)
return true;
if (minor == 4 && patch == 0 && ptr[0] == '-' &&
internal_strstr(buf.version, "Ubuntu")) {
// Check Ubuntu 16.04
int r1 = internal_simple_strtoll(ptr+1, &ptr, 10);
if (r1 >= 13) // 4.4.0-13 or later
return true;
}
// Otherwise, OK if 4.5+.
return minor >= 5;
} else {

View File

@ -370,6 +370,27 @@ uptr GetTlsSize() {
void InitTlsSize() {
}
uptr TlsBaseAddr() {
uptr segbase = 0;
#if defined(__x86_64__)
asm("movq %%gs:0,%0" : "=r"(segbase));
#elif defined(__i386__)
asm("movl %%gs:0,%0" : "=r"(segbase));
#endif
return segbase;
}
// The size of the tls on darwin does not appear to be well documented,
// however the vm memory map suggests that it is 1024 uptrs in size,
// with a size of 0x2000 bytes on x86_64 and 0x1000 bytes on i386.
uptr TlsSize() {
#if defined(__x86_64__) || defined(__i386__)
return 1024 * sizeof(uptr);
#else
return 0;
#endif
}
void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
uptr *tls_addr, uptr *tls_size) {
#if !SANITIZER_GO
@ -377,8 +398,8 @@ void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
*stk_addr = stack_bottom;
*stk_size = stack_top - stack_bottom;
*tls_addr = 0;
*tls_size = 0;
*tls_addr = TlsBaseAddr();
*tls_size = TlsSize();
#else
*stk_addr = 0;
*stk_size = 0;
@ -393,10 +414,10 @@ void ListOfModules::init() {
memory_mapping.DumpListOfModules(&modules_);
}
bool IsHandledDeadlySignal(int signum) {
HandleSignalMode GetHandleSignalMode(int signum) {
// Handling fatal signals on watchOS and tvOS devices is disallowed.
if ((SANITIZER_WATCHOS || SANITIZER_TVOS) && !(SANITIZER_IOSSIM))
return false;
return kHandleSignalNo;
switch (signum) {
case SIGABRT:
return common_flags()->handle_abort;
@ -409,7 +430,7 @@ bool IsHandledDeadlySignal(int signum) {
case SIGBUS:
return common_flags()->handle_sigbus;
}
return false;
return kHandleSignalNo;
}
MacosVersion cached_macos_version = MACOS_VERSION_UNINITIALIZED;

View File

@ -134,7 +134,8 @@ void SleepForMillis(int millis) {
void Abort() {
#if !SANITIZER_GO
// If we are handling SIGABRT, unhandle it first.
if (IsHandledDeadlySignal(SIGABRT)) {
// TODO(vitalybuka): Check if handler belongs to sanitizer.
if (GetHandleSignalMode(SIGABRT) != kHandleSignalNo) {
struct sigaction sigact;
internal_memset(&sigact, 0, sizeof(sigact));
sigact.sa_sigaction = (sa_sigaction_t)SIG_DFL;
@ -188,8 +189,26 @@ void UnsetAlternateSignalStack() {
static void MaybeInstallSigaction(int signum,
SignalHandlerType handler) {
if (!IsHandledDeadlySignal(signum))
return;
switch (GetHandleSignalMode(signum)) {
case kHandleSignalNo:
return;
case kHandleSignalYes: {
struct sigaction sigact;
internal_memset(&sigact, 0, sizeof(sigact));
CHECK_EQ(0, internal_sigaction(signum, nullptr, &sigact));
if (sigact.sa_flags & SA_SIGINFO) {
if (sigact.sa_sigaction) return;
} else {
if (sigact.sa_handler != SIG_DFL && sigact.sa_handler != SIG_IGN &&
sigact.sa_handler != SIG_ERR)
return;
}
break;
}
case kHandleSignalExclusive:
break;
}
struct sigaction sigact;
internal_memset(&sigact, 0, sizeof(sigact));
sigact.sa_sigaction = (sa_sigaction_t)handler;

View File

@ -832,9 +832,9 @@ void InstallDeadlySignalHandlers(SignalHandlerType handler) {
// FIXME: Decide what to do on Windows.
}
bool IsHandledDeadlySignal(int signum) {
HandleSignalMode GetHandleSignalMode(int signum) {
// FIXME: Decide what to do on Windows.
return false;
return kHandleSignalNo;
}
// Check based on flags if we should handle this exception.

View File

@ -78,13 +78,15 @@ TEST(SanitizerCommon, HandleSignalMode) {
TestFlag(kHandleSignalYes, "flag_name=0", kHandleSignalNo);
TestFlag(kHandleSignalYes, "flag_name=no", kHandleSignalNo);
TestFlag(kHandleSignalYes, "flag_name=false", kHandleSignalNo);
TestFlag(kHandleSignalNo, "flag_name=2", kHandleSignalExclusive);
TestFlag(kHandleSignalYes, "flag_name=exclusive", kHandleSignalExclusive);
EXPECT_DEATH(TestFlag(kHandleSignalNo, "flag_name", kHandleSignalNo),
"expected '='");
EXPECT_DEATH(TestFlag(kHandleSignalNo, "flag_name=", kHandleSignalNo),
"Invalid value for signal handler option: ''");
EXPECT_DEATH(TestFlag(kHandleSignalNo, "flag_name=2", kHandleSignalNo),
"Invalid value for signal handler option: '2'");
EXPECT_DEATH(TestFlag(kHandleSignalNo, "flag_name=3", kHandleSignalNo),
"Invalid value for signal handler option: '3'");
EXPECT_DEATH(TestFlag(kHandleSignalNo, "flag_name=-1", kHandleSignalNo),
"Invalid value for signal handler option: '-1'");
EXPECT_DEATH(TestFlag(kHandleSignalNo, "flag_name=on", kHandleSignalNo),

View File

@ -18,7 +18,6 @@
#include "scudo_tls.h"
#include <limits.h>
#include <pthread.h>
namespace __scudo {
@ -32,15 +31,17 @@ __attribute__((tls_model("initial-exec")))
THREADLOCAL ScudoThreadContext ThreadLocalContext;
static void teardownThread(void *Ptr) {
uptr Iteration = reinterpret_cast<uptr>(Ptr);
uptr I = reinterpret_cast<uptr>(Ptr);
// The glibc POSIX thread-local-storage deallocation routine calls user
// provided destructors in a loop of PTHREAD_DESTRUCTOR_ITERATIONS.
// We want to be called last since other destructors might call free and the
// like, so we wait until PTHREAD_DESTRUCTOR_ITERATIONS before draining the
// quarantine and swallowing the cache.
if (Iteration < PTHREAD_DESTRUCTOR_ITERATIONS) {
pthread_setspecific(PThreadKey, reinterpret_cast<void *>(Iteration + 1));
return;
if (I > 1) {
// If pthread_setspecific fails, we will go ahead with the teardown.
if (LIKELY(pthread_setspecific(PThreadKey,
reinterpret_cast<void *>(I - 1)) == 0))
return;
}
ThreadLocalContext.commitBack();
ScudoThreadState = ThreadTornDown;
@ -53,8 +54,9 @@ static void initOnce() {
}
void initThread() {
pthread_once(&GlobalInitialized, initOnce);
pthread_setspecific(PThreadKey, reinterpret_cast<void *>(1));
CHECK_EQ(pthread_once(&GlobalInitialized, initOnce), 0);
CHECK_EQ(pthread_setspecific(PThreadKey, reinterpret_cast<void *>(
GetPthreadDestructorIterations())), 0);
ThreadLocalContext.init();
ScudoThreadState = ThreadInitialized;
}

View File

@ -816,6 +816,7 @@ void FlushShadowMemory();
void WriteMemoryProfile(char *buf, uptr buf_size, uptr nthread, uptr nlive);
int ExtractResolvFDs(void *state, int *fds, int nfd);
int ExtractRecvmsgFDs(void *msg, int *fds, int nfd);
void ImitateTlsWrite(ThreadState *thr, uptr tls_addr, uptr tls_size);
int call_pthread_cancel_with_cleanup(int(*fn)(void *c, void *m,
void *abstime), void *c, void *m, void *abstime,

View File

@ -320,6 +320,20 @@ int ExtractRecvmsgFDs(void *msgp, int *fds, int nfd) {
return res;
}
void ImitateTlsWrite(ThreadState *thr, uptr tls_addr, uptr tls_size) {
// Check that the thr object is in tls;
const uptr thr_beg = (uptr)thr;
const uptr thr_end = (uptr)thr + sizeof(*thr);
CHECK_GE(thr_beg, tls_addr);
CHECK_LE(thr_beg, tls_addr + tls_size);
CHECK_GE(thr_end, tls_addr);
CHECK_LE(thr_end, tls_addr + tls_size);
// Since the thr object is huge, skip it.
MemoryRangeImitateWrite(thr, /*pc=*/2, tls_addr, thr_beg - tls_addr);
MemoryRangeImitateWrite(thr, /*pc=*/2, thr_end,
tls_addr + tls_size - thr_end);
}
// Note: this function runs with async signals enabled,
// so it must not touch any tsan state.
int call_pthread_cancel_with_cleanup(int(*fn)(void *c, void *m,

View File

@ -75,12 +75,18 @@ static void *SignalSafeGetOrAllocate(uptr *dst, uptr size) {
static uptr main_thread_identity = 0;
ALIGNED(64) static char main_thread_state[sizeof(ThreadState)];
ThreadState **cur_thread_location() {
ThreadState **thread_identity = (ThreadState **)pthread_self();
return ((uptr)thread_identity == main_thread_identity) ? nullptr
: thread_identity;
}
ThreadState *cur_thread() {
uptr thread_identity = (uptr)pthread_self();
if (thread_identity == main_thread_identity || main_thread_identity == 0) {
ThreadState **thr_state_loc = cur_thread_location();
if (thr_state_loc == nullptr || main_thread_identity == 0) {
return (ThreadState *)&main_thread_state;
}
ThreadState **fake_tls = (ThreadState **)MemToShadow(thread_identity);
ThreadState **fake_tls = (ThreadState **)MemToShadow((uptr)thr_state_loc);
ThreadState *thr = (ThreadState *)SignalSafeGetOrAllocate(
(uptr *)fake_tls, sizeof(ThreadState));
return thr;
@ -90,13 +96,13 @@ ThreadState *cur_thread() {
// munmap first and then clear `fake_tls`; if we receive a signal in between,
// handler will try to access the unmapped ThreadState.
void cur_thread_finalize() {
uptr thread_identity = (uptr)pthread_self();
if (thread_identity == main_thread_identity) {
ThreadState **thr_state_loc = cur_thread_location();
if (thr_state_loc == nullptr) {
// Calling dispatch_main() or xpc_main() actually invokes pthread_exit to
// exit the main thread. Let's keep the main thread's ThreadState.
return;
}
ThreadState **fake_tls = (ThreadState **)MemToShadow(thread_identity);
ThreadState **fake_tls = (ThreadState **)MemToShadow((uptr)thr_state_loc);
internal_munmap(*fake_tls, sizeof(ThreadState));
*fake_tls = nullptr;
}
@ -239,6 +245,29 @@ void InitializePlatform() {
#endif
}
#if !SANITIZER_GO
void ImitateTlsWrite(ThreadState *thr, uptr tls_addr, uptr tls_size) {
// The pointer to the ThreadState object is stored in the shadow memory
// of the tls.
uptr tls_end = tls_addr + tls_size;
ThreadState **thr_state_loc = cur_thread_location();
if (thr_state_loc == nullptr) {
MemoryRangeImitateWrite(thr, /*pc=*/2, tls_addr, tls_size);
} else {
uptr thr_state_start = (uptr)thr_state_loc;
uptr thr_state_end = thr_state_start + sizeof(uptr);
CHECK_GE(thr_state_start, tls_addr);
CHECK_LE(thr_state_start, tls_addr + tls_size);
CHECK_GE(thr_state_end, tls_addr);
CHECK_LE(thr_state_end, tls_addr + tls_size);
MemoryRangeImitateWrite(thr, /*pc=*/2, tls_addr,
thr_state_start - tls_addr);
MemoryRangeImitateWrite(thr, /*pc=*/2, thr_state_end,
tls_end - thr_state_end);
}
}
#endif
#if !SANITIZER_GO
// Note: this function runs with async signals enabled,
// so it must not touch any tsan state.

View File

@ -248,19 +248,7 @@ void ThreadStart(ThreadState *thr, int tid, tid_t os_id, bool workerthread) {
if (stk_addr && stk_size)
MemoryRangeImitateWrite(thr, /*pc=*/ 1, stk_addr, stk_size);
if (tls_addr && tls_size) {
// Check that the thr object is in tls;
const uptr thr_beg = (uptr)thr;
const uptr thr_end = (uptr)thr + sizeof(*thr);
CHECK_GE(thr_beg, tls_addr);
CHECK_LE(thr_beg, tls_addr + tls_size);
CHECK_GE(thr_end, tls_addr);
CHECK_LE(thr_end, tls_addr + tls_size);
// Since the thr object is huge, skip it.
MemoryRangeImitateWrite(thr, /*pc=*/ 2, tls_addr, thr_beg - tls_addr);
MemoryRangeImitateWrite(thr, /*pc=*/ 2,
thr_end, tls_addr + tls_size - thr_end);
}
if (tls_addr && tls_size) ImitateTlsWrite(thr, tls_addr, tls_size);
}
#endif

View File

@ -0,0 +1,105 @@
// clang-format off
// RUN: %clangxx -std=c++11 %s -o %t
// RUN: env LD_PRELOAD=%shared_libasan %env_asan_opts=handle_segv=1 not %run %t 2>&1 | FileCheck %s
// RUN: env LD_PRELOAD=%shared_libasan %env_asan_opts=handle_segv=2 not %run %t 2>&1 | FileCheck %s
// RUN: %clangxx -std=c++11 -DTEST_INSTALL_SIG_HANDLER %s -o %t
// RUN: env LD_PRELOAD=%shared_libasan %env_asan_opts=handle_segv=1 not %run %t 2>&1 | FileCheck --check-prefix=CHECK-HANDLER %s
// RUN: env LD_PRELOAD=%shared_libasan %env_asan_opts=handle_segv=2 not %run %t 2>&1 | FileCheck %s
// RUN: %clangxx -std=c++11 -DTEST_INSTALL_SIG_ACTION %s -o %t
// RUN: env LD_PRELOAD=%shared_libasan %env_asan_opts=handle_segv=1 not %run %t 2>&1 | FileCheck --check-prefix=CHECK-ACTION %s
// RUN: env LD_PRELOAD=%shared_libasan %env_asan_opts=handle_segv=2 not %run %t 2>&1 | FileCheck %s
// REQUIRES: asan-dynamic-runtime
// This way of setting LD_PRELOAD does not work with Android test runner.
// REQUIRES: not-android
// clang-format on
#include <assert.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/syscall.h>
#include <unistd.h>
const char *handler = nullptr;
void SigHandler(int signum) { handler = "TestSigHandler"; }
void SigAction(int, siginfo_t *, void *) { handler = "TestSigAction"; }
struct KernelSigaction {
__sighandler_t handler;
unsigned long flags;
void (*restorer)();
char unused[1024];
};
#if defined(__x86_64__)
extern "C" void restorer();
asm("restorer:mov $15,%rax\nsyscall");
#endif
int InternalSigaction(int sig, KernelSigaction *act, KernelSigaction *oact) {
if (act) {
#if defined(__x86_64__)
act->flags |= 0x04000000;
act->restorer = &restorer;
#endif
}
return syscall(__NR_rt_sigaction, sig, act, oact, NSIG / 8);
}
struct KernelSigaction sigact = {};
static void Init() {
int res = InternalSigaction(SIGSEGV, nullptr, &sigact);
assert(res >= 0);
assert(sigact.handler == SIG_DFL || sigact.handler == SIG_IGN);
#if defined(TEST_INSTALL_SIG_HANDLER)
sigact = {};
sigact.handler = &SigHandler;
res = InternalSigaction(SIGSEGV, &sigact, nullptr);
assert(res >= 0);
#elif defined(TEST_INSTALL_SIG_ACTION)
sigact = {};
sigact.flags = SA_SIGINFO | SA_NODEFER;
sigact.handler = (__sighandler_t)&SigAction;
res = InternalSigaction(SIGSEGV, &sigact, nullptr);
assert(res >= 0);
#endif
}
__attribute__((section(".preinit_array"), used))
void (*__local_test_preinit)(void) = Init;
bool ShouldAsanInstallHandlers() {
#if defined(TEST_INSTALL_SIG_HANDLER) || defined(TEST_INSTALL_SIG_ACTION)
return !strcmp(getenv("ASAN_OPTIONS"), "handle_segv=2");
#endif
return true;
}
int main(int argc, char *argv[]) {
KernelSigaction sigact_asan = {};
InternalSigaction(SIGSEGV, nullptr, &sigact_asan);
assert(sigact_asan.handler != SIG_DFL);
assert(sigact_asan.handler != SIG_IGN);
assert(ShouldAsanInstallHandlers() ==
(sigact_asan.handler != sigact.handler));
raise(SIGSEGV);
printf("%s\n", handler);
return 1;
}
// CHECK-NOT: TestSig
// CHECK: ASAN:DEADLYSIGNAL
// CHECK-HANDLER-NOT: ASAN:DEADLYSIGNAL
// CHECK-HANDLER: TestSigHandler
// CHECK-ACTION-NOT: ASAN:DEADLYSIGNAL
// CHECK-ACTION: TestSigAction

View File

@ -14,17 +14,15 @@ int main() {
if (unshare(CLONE_NEWUSER)) {
printf("unshare failed\n");
abort();
return 1;
}
// remove access to /proc/self/maps
if (chroot("/tmp")) {
printf("chroot failed\n");
abort();
return 2;
}
*(volatile int*)0x42 = 0;
// CHECK: AddressSanitizer: SEGV on unknown address 0x000000000042
// CHECK-NOT: AddressSanitizer CHECK failed
// CHECK: SUMMARY: AddressSanitizer: SEGV
// CHECK-NOT: CHECK failed
}

View File

@ -1,8 +1,14 @@
// Regression test for
// https://code.google.com/p/address-sanitizer/issues/detail?id=180
// RUN: %clangxx_asan -O0 %s -o %t && %env_asan_opts=allow_user_segv_handler=true not %run %t 2>&1 | FileCheck %s
// RUN: %clangxx_asan -O2 %s -o %t && %env_asan_opts=allow_user_segv_handler=true not %run %t 2>&1 | FileCheck %s
// RUN: %clangxx_asan -O0 %s -o %t && %env_asan_opts=handle_segv=0 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK0
// RUN: %clangxx_asan -O2 %s -o %t && %env_asan_opts=handle_segv=0 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK0
// RUN: %clangxx_asan -O0 %s -o %t && %env_asan_opts=handle_segv=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1
// RUN: %clangxx_asan -O2 %s -o %t && %env_asan_opts=handle_segv=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1
// RUN: %clangxx_asan -O0 %s -o %t && %env_asan_opts=handle_segv=2 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK2
// RUN: %clangxx_asan -O2 %s -o %t && %env_asan_opts=handle_segv=2 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK2
#include <signal.h>
#include <stdio.h>
@ -22,10 +28,14 @@ void User_OnSIGSEGV(int signum, siginfo_t *siginfo, void *context) {
printf("Invalid signum");
exit(1);
}
if (original_sigaction.sa_flags | SA_SIGINFO)
original_sigaction.sa_sigaction(signum, siginfo, context);
else
original_sigaction.sa_handler(signum);
if (original_sigaction.sa_flags | SA_SIGINFO) {
if (original_sigaction.sa_sigaction)
original_sigaction.sa_sigaction(signum, siginfo, context);
} else {
if (original_sigaction.sa_handler)
original_sigaction.sa_handler(signum);
}
exit(1);
}
int DoSEGV() {
@ -33,27 +43,38 @@ int DoSEGV() {
return *x;
}
int InstallHandler(int signum, struct sigaction *original_sigaction) {
bool InstallHandler(int signum, struct sigaction *original_sigaction) {
struct sigaction user_sigaction;
user_sigaction.sa_sigaction = User_OnSIGSEGV;
user_sigaction.sa_flags = SA_SIGINFO;
if (sigaction(signum, &user_sigaction, original_sigaction)) {
perror("sigaction");
return 1;
return false;
}
return 0;
return true;
}
int main() {
// Let's install handlers for both SIGSEGV and SIGBUS, since pre-Yosemite
// 32-bit Darwin triggers SIGBUS instead.
if (InstallHandler(SIGSEGV, &original_sigaction_sigsegv)) return 1;
if (InstallHandler(SIGBUS, &original_sigaction_sigbus)) return 1;
fprintf(stderr, "User sigaction installed\n");
if (InstallHandler(SIGSEGV, &original_sigaction_sigsegv) &&
InstallHandler(SIGBUS, &original_sigaction_sigbus)) {
fprintf(stderr, "User sigaction installed\n");
}
return DoSEGV();
}
// CHECK: User sigaction installed
// CHECK-NEXT: User sigaction called
// CHECK-NEXT: ASAN:DEADLYSIGNAL
// CHECK: AddressSanitizer: SEGV on unknown address
// CHECK0-NOT: ASAN:DEADLYSIGNAL
// CHECK0-NOT: AddressSanitizer: SEGV on unknown address
// CHECK0: User sigaction installed
// CHECK0-NEXT: User sigaction called
// CHECK1: User sigaction installed
// CHECK1-NEXT: User sigaction called
// CHECK1-NEXT: ASAN:DEADLYSIGNAL
// CHECK1: AddressSanitizer: SEGV on unknown address
// CHECK2-NOT: User sigaction called
// CHECK2: User sigaction installed
// CHECK2-NEXT: ASAN:DEADLYSIGNAL
// CHECK2: AddressSanitizer: SEGV on unknown address

View File

@ -1,9 +1,6 @@
// RUN: %clangxx_asan -O0 %s -pthread -o %t && %run %t
// RUN: %clangxx_asan -O2 %s -pthread -o %t && %run %t
// REQUIRES: stable-runtime
// UNSUPPORTED: powerpc64le
// FIXME: This test occasionally fails on powerpc64 LE possibly starting with
// r279664. Re-enable the test once the problem(s) have been fixed.
#include <assert.h>
#include <pthread.h>

View File

@ -4,6 +4,7 @@
// RUN: %clangxx_asan -DWAITPID -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
// RUN: %clangxx_asan -DWAITPID -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s
// UNSUPPORTED: darwin
#include <assert.h>
#include <sys/wait.h>

View File

@ -4,7 +4,7 @@
// RUN: %clangxx_asan -DWAIT3_RUSAGE -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
// RUN: %clangxx_asan -DWAIT3_RUSAGE -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s
// UNSUPPORTED: android
// UNSUPPORTED: android,darwin
#include <assert.h>
#include <sys/wait.h>

View File

@ -5,6 +5,7 @@
// RUN: %clangxx_asan -DWAIT4_RUSAGE -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s
// XFAIL: android
// UNSUPPORTED: darwin
#include <assert.h>
#include <sys/wait.h>

View File

@ -1,6 +1,8 @@
// RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
// RUN: %clangxx_asan -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s
// UNSUPPORTED: darwin
#include <assert.h>
#include <sys/wait.h>
#include <unistd.h>

View File

@ -13,34 +13,25 @@
//
//===----------------------------------------------------------------------===//
#include <stdlib.h>
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
extern uint64_t __bswapdi2(uint64_t);
#if __arm__
int test__bswapdi2(uint64_t a, uint64_t expected)
{
uint64_t actual = __bswapdi2(a);
if (actual != expected)
printf("error in test__bswapsi2(0x%0llX) = 0x%0llX, expected 0x%0llX\n",
a, actual, expected);
return actual != expected;
int test__bswapdi2(uint64_t a, uint64_t expected) {
uint64_t actual = __bswapdi2(a);
if (actual != expected)
printf("error in test__bswapsi2(0x%0llX) = 0x%0llX, expected 0x%0llX\n", a,
actual, expected);
return actual != expected;
}
#endif
int main()
{
#if __arm__
if (test__bswapdi2(0x123456789ABCDEF0LL, 0xF0DEBC9A78563412LL))
return 1;
if (test__bswapdi2(0x0000000100000002LL, 0x0200000001000000LL))
return 1;
#else
printf("skipped\n");
#endif
return 0;
int main() {
if (test__bswapdi2(0x123456789ABCDEF0LL, 0xF0DEBC9A78563412LL))
return 1;
if (test__bswapdi2(0x0000000100000002LL, 0x0200000001000000LL))
return 1;
return 0;
}

View File

@ -13,34 +13,25 @@
//
//===----------------------------------------------------------------------===//
#include <stdlib.h>
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
extern uint32_t __bswapsi2(uint32_t);
#if __arm__
int test__bswapsi2(uint32_t a, uint32_t expected)
{
uint32_t actual = __bswapsi2(a);
if (actual != expected)
printf("error in test__bswapsi2(0x%0X) = 0x%0X, expected 0x%0X\n",
a, actual, expected);
return actual != expected;
int test__bswapsi2(uint32_t a, uint32_t expected) {
uint32_t actual = __bswapsi2(a);
if (actual != expected)
printf("error in test__bswapsi2(0x%0X) = 0x%0X, expected 0x%0X\n", a,
actual, expected);
return actual != expected;
}
#endif
int main()
{
#if __arm__
if (test__bswapsi2(0x12345678, 0x78563412))
return 1;
if (test__bswapsi2(0x00000001, 0x01000000))
return 1;
#else
printf("skipped\n");
#endif
return 0;
int main() {
if (test__bswapsi2(0x12345678, 0x78563412))
return 1;
if (test__bswapsi2(0x00000001, 0x01000000))
return 1;
return 0;
}

View File

@ -0,0 +1,97 @@
// Test that lsan handles tls correctly for many threads
// RUN: LSAN_BASE="report_objects=1:use_stacks=0:use_registers=0"
// RUN: %clangxx_lsan %s -DUSE_THREAD -o %t-thread
// RUN: %clangxx_lsan %s -DUSE_PTHREAD -o %t-pthread
// RUN: %env_lsan_opts=$LSAN_BASE:"use_tls=0" not %run %t-thread 2>&1 | FileCheck %s
// RUN: %env_lsan_opts=$LSAN_BASE:"use_tls=1" %run %t-thread 2>&1
// RUN: %env_lsan_opts="" %run %t-thread 2>&1
// RUN: %env_lsan_opts=$LSAN_BASE:"use_tls=0" not %run %t-pthread 2>&1 | FileCheck %s
// RUN: %env_lsan_opts=$LSAN_BASE:"use_tls=1" %run %t-pthread 2>&1
// RUN: %env_lsan_opts="" %run %t-pthread 2>&1
// Patch r303906 did not fix all the problems.
// UNSUPPORTED: arm-linux,armhf-linux
#include <assert.h>
#include <limits.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
static const int NUM_THREADS = 10;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int finished = 0;
#if USE_THREAD
__thread void *ptr1;
__thread void *ptr2;
__thread void *ptr3;
__thread void *ptr4;
__thread void *ptr5;
void alloc() {
ptr1 = malloc(1111);
ptr2 = malloc(2222);
ptr3 = malloc(3333);
ptr4 = malloc(4444);
ptr5 = malloc(5555);
}
#elif USE_PTHREAD
// We won't be able to create the maximum number of keys, due to other users
// of the tls, but we'll use as many keys as we can before failing to create
// a new key.
pthread_key_t keys[PTHREAD_KEYS_MAX];
static const int PTHREAD_KEY_INVALID = 0xffffffff;
void alloc() {
for (int i = 0; i < PTHREAD_KEYS_MAX; ++i) {
void *ptr = malloc(123);
if ((keys[i] == PTHREAD_KEY_INVALID) || pthread_setspecific(keys[i], ptr)) {
free(ptr);
break;
}
}
}
void pthread_destructor(void *arg) {
assert(0 && "pthread destructors shouldn't be called");
}
#endif
void *thread_start(void *arg) {
alloc();
pthread_mutex_lock(&mutex);
finished++;
pthread_mutex_unlock(&mutex);
// don't exit, to intentionally leak tls data
while (1)
sleep(100);
}
int main() {
#if USE_PTHREAD
for (int i = 0; i < PTHREAD_KEYS_MAX; ++i) {
if (pthread_key_create(&keys[i], pthread_destructor)) {
keys[i] = PTHREAD_KEY_INVALID;
break;
}
}
#endif
pthread_t thread[NUM_THREADS];
for (int i = 0; i < NUM_THREADS; ++i) {
assert(0 == pthread_create(&thread[i], 0, thread_start, 0));
}
// spin until all threads have finished
while (finished < NUM_THREADS)
sleep(1);
exit(0);
}
// CHECK: LeakSanitizer: detected memory leaks
// CHECK: SUMMARY: {{(Leak|Address)}}Sanitizer:

View File

@ -8,8 +8,12 @@
#include <string.h>
#include <stdint.h>
// On powerpc64be semval_t must be 64 bits even with "old" versions of glibc.
#if __PPC64__ && __BIG_ENDIAN__
typedef uint64_t semval_t;
// This condition needs to correspond to __HAVE_64B_ATOMICS macro in glibc.
#if (defined(__x86_64__) || defined(__aarch64__) || defined(__powerpc64__) || \
#elif (defined(__x86_64__) || defined(__aarch64__) || defined(__powerpc64__) || \
defined(__s390x__) || defined(__sparc64__) || defined(__alpha__) || \
defined(__ia64__) || defined(__m68k__)) && __GLIBC_PREREQ(2, 21)
typedef uint64_t semval_t;

View File

@ -1,4 +1,4 @@
// RUN: %clangxx -O1 %s -o %t && TSAN_OPTIONS="flush_memory_ms=1 memory_limit_mb=1" ASAN_OPTIONS="handle_segv=0 allow_user_segv_handler=1" %run %t 2>&1 | FileCheck %s
// RUN: %clangxx -O1 %s -o %t && TSAN_OPTIONS="flush_memory_ms=1 memory_limit_mb=1" ASAN_OPTIONS="handle_segv=0" %run %t 2>&1 | FileCheck %s
// JVM uses SEGV to preempt threads. All threads do a load from a known address
// periodically. When runtime needs to preempt threads, it unmaps the page.

View File

@ -6,7 +6,9 @@ int main() {
// CHECKU: negate-overflow.cpp:[[@LINE+2]]:3: runtime error: negation of 2147483648 cannot be represented in type 'unsigned int'
// CHECKU-NOT: cast to an unsigned
-unsigned(-0x7fffffff - 1); // ok
// CHECKS: negate-overflow.cpp:[[@LINE+2]]:10: runtime error: negation of -2147483648 cannot be represented in type 'int'; cast to an unsigned type to negate this value to itself
// CHECKS: negate-overflow.cpp:[[@LINE+2]]:3: runtime error: negation of -2147483648 cannot be represented in type 'int'; cast to an unsigned type to negate this value to itself
// CHECKU-NOT: runtime error
return -(-0x7fffffff - 1);
-(-0x7fffffff - 1);
return 0;
}