From 2523faf677b28e0747e76288df533fd8fe1e6393 Mon Sep 17 00:00:00 2001 From: Maxim Ostapenko Date: Mon, 23 Jan 2017 08:45:17 +0000 Subject: [PATCH] [lsan] Enable LSan for x86 Linux. People keep asking LSan to be available on 32 bit targets (e.g. https://github.com/google/sanitizers/issues/403) despite the fact that false negative ratio might be huge (up to 85%). This happens for big real world applications that may contain random binary data (e.g. browser), but for smaller apps situation is not so terrible and LSan still might be useful. This patch adds initial support for x86 Linux (disabled by default), ARM32 is in TODO list. We used this patch (well, ported to GCC) on our 32 bit mobile emulators and it worked pretty fine thus I'm posting it here to initiate further discussion. Differential Revision: https://reviews.llvm.org/D28609 llvm-svn: 292775 --- compiler-rt/cmake/config-ix.cmake | 2 +- compiler-rt/lib/lsan/lsan_allocator.cc | 11 +++- compiler-rt/lib/lsan/lsan_common.h | 10 +++ compiler-rt/lib/lsan/lsan_interceptors.cc | 10 +-- .../lib/sanitizer_common/sanitizer_flags.inc | 3 +- .../lib/sanitizer_common/sanitizer_linux.cc | 65 +++++++++++++++++++ .../lib/sanitizer_common/sanitizer_linux.h | 2 +- .../sanitizer_stoptheworld_linux_libcdep.cc | 4 +- compiler-rt/test/asan/lit.cfg | 2 +- compiler-rt/test/lsan/TestCases/disabler.cc | 2 +- .../lsan/TestCases/do_leak_check_override.cc | 2 +- .../TestCases/high_allocator_contention.cc | 2 +- .../lsan/TestCases/large_allocation_leak.cc | 6 +- .../test/lsan/TestCases/leak_check_at_exit.cc | 2 +- .../test/lsan/TestCases/link_turned_off.cc | 2 +- .../test/lsan/TestCases/pointer_to_self.cc | 2 +- .../test/lsan/TestCases/print_suppressions.cc | 2 +- .../lsan/TestCases/recoverable_leak_check.cc | 2 +- .../lsan/TestCases/register_root_region.cc | 2 +- .../test/lsan/TestCases/stale_stack_leak.cc | 2 +- .../lsan/TestCases/suppressions_default.cc | 2 +- .../test/lsan/TestCases/suppressions_file.cc | 2 +- .../test/lsan/TestCases/use_after_return.cc | 2 +- .../lsan/TestCases/use_globals_initialized.cc | 2 +- .../TestCases/use_globals_uninitialized.cc | 2 +- .../test/lsan/TestCases/use_poisoned_asan.cc | 2 +- .../test/lsan/TestCases/use_registers.cc | 2 +- compiler-rt/test/lsan/TestCases/use_stacks.cc | 2 +- .../lsan/TestCases/use_stacks_threaded.cc | 2 +- .../test/lsan/TestCases/use_tls_dynamic.cc | 2 +- .../use_tls_pthread_specific_dynamic.cc | 2 +- .../use_tls_pthread_specific_static.cc | 2 +- .../test/lsan/TestCases/use_tls_static.cc | 2 +- .../test/lsan/TestCases/use_unaligned.cc | 2 +- .../sanitizer_set_death_callback_test.cc | 7 ++ .../sanitizer_common/TestCases/corelimit.cc | 2 +- .../test/sanitizer_common/lit.common.cfg | 3 + .../test/sanitizer_common/print_address.h | 2 + 38 files changed, 140 insertions(+), 37 deletions(-) diff --git a/compiler-rt/cmake/config-ix.cmake b/compiler-rt/cmake/config-ix.cmake index f0c96c25b03e..ce3b2de8b42c 100644 --- a/compiler-rt/cmake/config-ix.cmake +++ b/compiler-rt/cmake/config-ix.cmake @@ -164,7 +164,7 @@ set(ALL_SANITIZER_COMMON_SUPPORTED_ARCH ${X86} ${X86_64} ${PPC64} set(ALL_ASAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} ${PPC64} ${S390X}) set(ALL_DFSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64}) -set(ALL_LSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64}) +set(ALL_LSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${MIPS64} ${ARM64}) set(ALL_MSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64}) set(ALL_PROFILE_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${PPC64} ${MIPS32} ${MIPS64} ${S390X}) diff --git a/compiler-rt/lib/lsan/lsan_allocator.cc b/compiler-rt/lib/lsan/lsan_allocator.cc index c805a39e1cc5..4284857962fe 100644 --- a/compiler-rt/lib/lsan/lsan_allocator.cc +++ b/compiler-rt/lib/lsan/lsan_allocator.cc @@ -28,12 +28,21 @@ namespace __lsan { struct ChunkMetadata { u8 allocated : 8; // Must be first. ChunkTag tag : 2; +#if SANITIZER_WORDSIZE == 64 uptr requested_size : 54; +#else + uptr requested_size : 32; + uptr padding : 22; +#endif u32 stack_trace_id; }; -#if defined(__mips64) || defined(__aarch64__) +#if defined(__mips64) || defined(__aarch64__) || defined(__i386__) +#if defined(__i386__) +static const uptr kMaxAllowedMallocSize = 1UL << 30; +#else static const uptr kMaxAllowedMallocSize = 4UL << 30; +#endif static const uptr kRegionSizeLog = 20; static const uptr kNumRegions = SANITIZER_MMAP_RANGE_SIZE >> kRegionSizeLog; typedef TwoLevelByteMap<(kNumRegions >> 12), 1 << 12> ByteMap; diff --git a/compiler-rt/lib/lsan/lsan_common.h b/compiler-rt/lib/lsan/lsan_common.h index 890ce6562c82..43b8dff7849f 100644 --- a/compiler-rt/lib/lsan/lsan_common.h +++ b/compiler-rt/lib/lsan/lsan_common.h @@ -22,9 +22,19 @@ #include "sanitizer_common/sanitizer_stoptheworld.h" #include "sanitizer_common/sanitizer_symbolizer.h" +// LeakSanitizer relies on some Glibc's internals (e.g. TLS machinery) thus +// supported for Linux only. Also, LSan doesn't like 32 bit architectures +// because of "small" (4 bytes) pointer size that leads to high false negative +// ratio on large leaks. But we still want to have it for some 32 bit arches +// (e.g. x86), see https://github.com/google/sanitizers/issues/403. +// To enable LeakSanitizer on new architecture, one need to implement +// internal_clone function as well as (probably) adjust TLS machinery for +// new architecture inside sanitizer library. #if (SANITIZER_LINUX && !SANITIZER_ANDROID) && (SANITIZER_WORDSIZE == 64) \ && (defined(__x86_64__) || defined(__mips64) || defined(__aarch64__)) #define CAN_SANITIZE_LEAKS 1 +#elif SANITIZER_LINUX && !SANITIZER_ANDROID && defined(__i386__) +#define CAN_SANITIZE_LEAKS 1 #else #define CAN_SANITIZE_LEAKS 0 #endif diff --git a/compiler-rt/lib/lsan/lsan_interceptors.cc b/compiler-rt/lib/lsan/lsan_interceptors.cc index 28f1786edb64..0a04f8a70654 100644 --- a/compiler-rt/lib/lsan/lsan_interceptors.cc +++ b/compiler-rt/lib/lsan/lsan_interceptors.cc @@ -26,6 +26,8 @@ #include "lsan_common.h" #include "lsan_thread.h" +#include + using namespace __lsan; extern "C" { @@ -161,13 +163,13 @@ INTERCEPTOR(void, cfree, void *p) ALIAS(WRAPPER_NAME(free)); return Allocate(stack, size, 1, kAlwaysClearMemory); INTERCEPTOR_ATTRIBUTE -void *operator new(uptr size) { OPERATOR_NEW_BODY; } +void *operator new(size_t size) { OPERATOR_NEW_BODY; } INTERCEPTOR_ATTRIBUTE -void *operator new[](uptr size) { OPERATOR_NEW_BODY; } +void *operator new[](size_t size) { OPERATOR_NEW_BODY; } INTERCEPTOR_ATTRIBUTE -void *operator new(uptr size, std::nothrow_t const&) { OPERATOR_NEW_BODY; } +void *operator new(size_t size, std::nothrow_t const&) { OPERATOR_NEW_BODY; } INTERCEPTOR_ATTRIBUTE -void *operator new[](uptr size, std::nothrow_t const&) { OPERATOR_NEW_BODY; } +void *operator new[](size_t size, std::nothrow_t const&) { OPERATOR_NEW_BODY; } #define OPERATOR_DELETE_BODY \ ENSURE_LSAN_INITED; \ diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc b/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc index d7fa34a58081..d799f6ef7ea9 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc @@ -62,7 +62,8 @@ COMMON_FLAG( COMMON_FLAG( int, verbosity, 0, "Verbosity level (0 - silent, 1 - a bit of output, 2+ - more output).") -COMMON_FLAG(bool, detect_leaks, true, "Enable memory leak detection.") +COMMON_FLAG(bool, detect_leaks, SANITIZER_WORDSIZE == 64, + "Enable memory leak detection.") COMMON_FLAG( bool, leak_check_at_exit, true, "Invoke leak checking in an atexit handler. Has no effect if " diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc index 7328a5c0ac18..ba301a04b748 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc @@ -1175,6 +1175,71 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, "r0", "r29", "r27", "r28"); return res; } +#elif defined(__i386__) && SANITIZER_LINUX +uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, + int *parent_tidptr, void *newtls, int *child_tidptr) { + int res; + if (!fn || !child_stack) + return -EINVAL; + CHECK_EQ(0, (uptr)child_stack % 16); + child_stack = (char *)child_stack - 7 * sizeof(unsigned int); + ((unsigned int *)child_stack)[0] = (uptr)flags; + ((unsigned int *)child_stack)[1] = (uptr)0; + ((unsigned int *)child_stack)[2] = (uptr)fn; + ((unsigned int *)child_stack)[3] = (uptr)arg; + __asm__ __volatile__( + /* %eax = syscall(%eax = SYSCALL(clone), + * %ebx = flags, + * %ecx = child_stack, + * %edx = parent_tidptr, + * %esi = new_tls, + * %edi = child_tidptr) + */ + + /* Obtain flags */ + "movl (%%ecx), %%ebx\n" + /* Do the system call */ + "pushl %%ebx\n" + "pushl %%esi\n" + "pushl %%edi\n" + /* Remember the flag value. */ + "movl %%ebx, (%%ecx)\n" + "int $0x80\n" + "popl %%edi\n" + "popl %%esi\n" + "popl %%ebx\n" + + /* if (%eax != 0) + * return; + */ + + "test %%eax,%%eax\n" + "jnz 1f\n" + + /* terminate the stack frame */ + "xorl %%ebp,%%ebp\n" + /* Call FN. */ + "call *%%ebx\n" +#ifdef PIC + "call here\n" + "here:\n" + "popl %%ebx\n" + "addl $_GLOBAL_OFFSET_TABLE_+[.-here], %%ebx\n" +#endif + /* Call exit */ + "movl %%eax, %%ebx\n" + "movl %2, %%eax\n" + "int $0x80\n" + "1:\n" + : "=a" (res) + : "a"(SYSCALL(clone)), "i"(SYSCALL(exit)), + "c"(child_stack), + "d"(parent_tidptr), + "S"(newtls), + "D"(child_tidptr) + : "memory"); + return res; +} #endif // defined(__x86_64__) && SANITIZER_LINUX #if SANITIZER_ANDROID diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.h b/compiler-rt/lib/sanitizer_common/sanitizer_linux.h index d4d0f47eed02..bba8624a9b9b 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.h @@ -48,7 +48,7 @@ int internal_sigaction_syscall(int signum, const void *act, void *oldact); #endif void internal_sigdelset(__sanitizer_sigset_t *set, int signum); #if defined(__x86_64__) || defined(__mips__) || defined(__aarch64__) \ - || defined(__powerpc64__) || defined(__s390__) + || defined(__powerpc64__) || defined(__s390__) || defined(__i386__) uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, int *parent_tidptr, void *newtls, int *child_tidptr); #endif diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc b/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc index eb4c403d3de0..ce8873b9e8cb 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc @@ -16,7 +16,7 @@ #if SANITIZER_LINUX && (defined(__x86_64__) || defined(__mips__) || \ defined(__aarch64__) || defined(__powerpc64__) || \ - defined(__s390__)) + defined(__s390__) || defined(__i386__)) #include "sanitizer_stoptheworld.h" @@ -528,4 +528,4 @@ uptr SuspendedThreadsList::RegisterCount() { #endif // SANITIZER_LINUX && (defined(__x86_64__) || defined(__mips__) // || defined(__aarch64__) || defined(__powerpc64__) - // || defined(__s390__) + // || defined(__s390__) || defined(__i386__) diff --git a/compiler-rt/test/asan/lit.cfg b/compiler-rt/test/asan/lit.cfg index 5ebe414d427d..0a4856b11b8c 100644 --- a/compiler-rt/test/asan/lit.cfg +++ b/compiler-rt/test/asan/lit.cfg @@ -205,7 +205,7 @@ if config.target_arch != 'arm' and config.target_arch != 'armhf' and config.targ config.available_features.add('stable-runtime') # Turn on leak detection on 64-bit Linux. -if config.host_os == 'Linux' and config.target_arch == 'x86_64': +if config.host_os == 'Linux' and (config.target_arch == 'x86_64' or config.target_arch == 'i386'): config.available_features.add('leak-detection') # Set LD_LIBRARY_PATH to pick dynamic runtime up properly. diff --git a/compiler-rt/test/lsan/TestCases/disabler.cc b/compiler-rt/test/lsan/TestCases/disabler.cc index 12e5ffe4d44a..95e58f457cc4 100644 --- a/compiler-rt/test/lsan/TestCases/disabler.cc +++ b/compiler-rt/test/lsan/TestCases/disabler.cc @@ -1,5 +1,5 @@ // Test for ScopedDisabler. -// RUN: LSAN_BASE="report_objects=1:use_registers=0:use_stacks=0:use_globals=0:use_tls=0" +// RUN: LSAN_BASE="detect_leaks=1:report_objects=1:use_registers=0:use_stacks=0:use_globals=0:use_tls=0" // RUN: %clangxx_lsan %s -o %t // RUN: LSAN_OPTIONS=$LSAN_BASE not %run %t 2>&1 | FileCheck %s diff --git a/compiler-rt/test/lsan/TestCases/do_leak_check_override.cc b/compiler-rt/test/lsan/TestCases/do_leak_check_override.cc index bedb0cad6908..3d191f861d02 100644 --- a/compiler-rt/test/lsan/TestCases/do_leak_check_override.cc +++ b/compiler-rt/test/lsan/TestCases/do_leak_check_override.cc @@ -1,7 +1,7 @@ // Test for __lsan_do_leak_check(). We test it by making the leak check run // before global destructors, which also tests compatibility with HeapChecker's // "normal" mode (LSan runs in "strict" mode by default). -// RUN: LSAN_BASE="use_stacks=0:use_registers=0" +// RUN: LSAN_BASE="detect_leaks=1:use_stacks=0:use_registers=0" // RUN: %clangxx_lsan %s -o %t // RUN: LSAN_OPTIONS=$LSAN_BASE not %run %t 2>&1 | FileCheck --check-prefix=CHECK-strict %s // RUN: LSAN_OPTIONS=$LSAN_BASE not %run %t foo 2>&1 | FileCheck --check-prefix=CHECK-normal %s diff --git a/compiler-rt/test/lsan/TestCases/high_allocator_contention.cc b/compiler-rt/test/lsan/TestCases/high_allocator_contention.cc index f423fd48c79c..322e61bde8d9 100644 --- a/compiler-rt/test/lsan/TestCases/high_allocator_contention.cc +++ b/compiler-rt/test/lsan/TestCases/high_allocator_contention.cc @@ -1,6 +1,6 @@ // A benchmark that executes malloc/free pairs in parallel. // Usage: ./a.out number_of_threads total_number_of_allocations -// RUN: LSAN_BASE="use_ld_allocations=0" +// RUN: LSAN_BASE="detect_leaks=1:use_ld_allocations=0" // RUN: %clangxx_lsan %s -o %t // RUN: LSAN_OPTIONS=$LSAN_BASE %run %t 5 1000000 2>&1 #include diff --git a/compiler-rt/test/lsan/TestCases/large_allocation_leak.cc b/compiler-rt/test/lsan/TestCases/large_allocation_leak.cc index 9d5698c9f8a6..7254f9cbe744 100644 --- a/compiler-rt/test/lsan/TestCases/large_allocation_leak.cc +++ b/compiler-rt/test/lsan/TestCases/large_allocation_leak.cc @@ -1,8 +1,12 @@ // Test that LargeMmapAllocator's chunks aren't reachable via some internal data structure. -// RUN: LSAN_BASE="report_objects=1:use_stacks=0:use_registers=0" +// RUN: LSAN_BASE="detect_leaks=1:report_objects=1:use_stacks=0:use_registers=0" // RUN: %clangxx_lsan %s -o %t // RUN: LSAN_OPTIONS=$LSAN_BASE not %run %t 2>&1 | FileCheck %s +// For 32 bit LSan it's pretty likely that large chunks are "reachable" from some +// internal data structures (e.g. Glibc global data). +// UNSUPPORTED: x86 + #include #include #include "sanitizer_common/print_address.h" diff --git a/compiler-rt/test/lsan/TestCases/leak_check_at_exit.cc b/compiler-rt/test/lsan/TestCases/leak_check_at_exit.cc index 6f1cd22cf68d..5659b396894e 100644 --- a/compiler-rt/test/lsan/TestCases/leak_check_at_exit.cc +++ b/compiler-rt/test/lsan/TestCases/leak_check_at_exit.cc @@ -1,5 +1,5 @@ // Test for the leak_check_at_exit flag. -// RUN: LSAN_BASE="use_stacks=0:use_registers=0" +// RUN: LSAN_BASE="detect_leaks=1:use_stacks=0:use_registers=0" // RUN: %clangxx_lsan %s -o %t // RUN: LSAN_OPTIONS=$LSAN_BASE not %run %t foo 2>&1 | FileCheck %s --check-prefix=CHECK-do // RUN: LSAN_OPTIONS=$LSAN_BASE not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-do diff --git a/compiler-rt/test/lsan/TestCases/link_turned_off.cc b/compiler-rt/test/lsan/TestCases/link_turned_off.cc index 2482f6197d92..a425a6c2da3e 100644 --- a/compiler-rt/test/lsan/TestCases/link_turned_off.cc +++ b/compiler-rt/test/lsan/TestCases/link_turned_off.cc @@ -1,5 +1,5 @@ // Test for disabling LSan at link-time. -// RUN: LSAN_BASE="use_stacks=0:use_registers=0" +// RUN: LSAN_BASE="detect_leaks=1:use_stacks=0:use_registers=0" // RUN: %clangxx_lsan %s -o %t // RUN: LSAN_OPTIONS=$LSAN_BASE %run %t // RUN: LSAN_OPTIONS=$LSAN_BASE not %run %t foo 2>&1 | FileCheck %s diff --git a/compiler-rt/test/lsan/TestCases/pointer_to_self.cc b/compiler-rt/test/lsan/TestCases/pointer_to_self.cc index 40c122811f18..ea1208dcfa78 100644 --- a/compiler-rt/test/lsan/TestCases/pointer_to_self.cc +++ b/compiler-rt/test/lsan/TestCases/pointer_to_self.cc @@ -1,6 +1,6 @@ // Regression test: pointers to self should not confuse LSan into thinking the // object is indirectly leaked. Only external pointers count. -// RUN: LSAN_BASE="report_objects=1:use_registers=0" +// RUN: LSAN_BASE="detect_leaks=1:report_objects=1:use_registers=0" // RUN: %clangxx_lsan %s -o %t // RUN: LSAN_OPTIONS=$LSAN_BASE:"use_stacks=0" not %run %t 2>&1 | FileCheck %s diff --git a/compiler-rt/test/lsan/TestCases/print_suppressions.cc b/compiler-rt/test/lsan/TestCases/print_suppressions.cc index b292c0a7c3cf..1a252e442720 100644 --- a/compiler-rt/test/lsan/TestCases/print_suppressions.cc +++ b/compiler-rt/test/lsan/TestCases/print_suppressions.cc @@ -1,6 +1,6 @@ // Print matched suppressions only if print_suppressions=1 AND at least one is // matched. Default is print_suppressions=true. -// RUN: LSAN_BASE="use_registers=0:use_stacks=0" +// RUN: LSAN_BASE="detect_leaks=1:use_registers=0:use_stacks=0" // RUN: %clangxx_lsan %s -o %t // RUN: LSAN_OPTIONS=$LSAN_BASE:print_suppressions=0 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-dont-print // RUN: LSAN_OPTIONS=$LSAN_BASE %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-dont-print diff --git a/compiler-rt/test/lsan/TestCases/recoverable_leak_check.cc b/compiler-rt/test/lsan/TestCases/recoverable_leak_check.cc index 0fe377f65af1..04686a561d76 100644 --- a/compiler-rt/test/lsan/TestCases/recoverable_leak_check.cc +++ b/compiler-rt/test/lsan/TestCases/recoverable_leak_check.cc @@ -1,5 +1,5 @@ // Test for on-demand leak checking. -// RUN: LSAN_BASE="use_stacks=0:use_registers=0" +// RUN: LSAN_BASE="detect_leaks=1:use_stacks=0:use_registers=0" // RUN: %clangxx_lsan %s -o %t // RUN: LSAN_OPTIONS=$LSAN_BASE %run %t foo 2>&1 | FileCheck %s // RUN: LSAN_OPTIONS=$LSAN_BASE %run %t 2>&1 | FileCheck %s diff --git a/compiler-rt/test/lsan/TestCases/register_root_region.cc b/compiler-rt/test/lsan/TestCases/register_root_region.cc index 6fc84c2fb50f..a63b0cc62cd0 100644 --- a/compiler-rt/test/lsan/TestCases/register_root_region.cc +++ b/compiler-rt/test/lsan/TestCases/register_root_region.cc @@ -1,5 +1,5 @@ // Test for __lsan_(un)register_root_region(). -// RUN: LSAN_BASE="use_stacks=0:use_registers=0" +// RUN: LSAN_BASE="detect_leaks=1:use_stacks=0:use_registers=0" // RUN: %clangxx_lsan %s -o %t // RUN: LSAN_OPTIONS=$LSAN_BASE %run %t // RUN: LSAN_OPTIONS=$LSAN_BASE not %run %t foo 2>&1 | FileCheck %s diff --git a/compiler-rt/test/lsan/TestCases/stale_stack_leak.cc b/compiler-rt/test/lsan/TestCases/stale_stack_leak.cc index 770096b08888..43b0d26a4b67 100644 --- a/compiler-rt/test/lsan/TestCases/stale_stack_leak.cc +++ b/compiler-rt/test/lsan/TestCases/stale_stack_leak.cc @@ -1,5 +1,5 @@ // Test that out-of-scope local variables are ignored by LSan. -// RUN: LSAN_BASE="report_objects=1:use_registers=0:use_stacks=1" +// RUN: LSAN_BASE="detect_leaks=1:report_objects=1:use_registers=0:use_stacks=1" // RUN: %clangxx_lsan %s -o %t // RUN: LSAN_OPTIONS=$LSAN_BASE not %run %t 2>&1 | FileCheck %s // RUN: LSAN_OPTIONS=$LSAN_BASE":exitcode=0" %run %t 2>&1 | FileCheck --check-prefix=CHECK-sanity %s diff --git a/compiler-rt/test/lsan/TestCases/suppressions_default.cc b/compiler-rt/test/lsan/TestCases/suppressions_default.cc index b4c0de016cd1..6c0364e62c74 100644 --- a/compiler-rt/test/lsan/TestCases/suppressions_default.cc +++ b/compiler-rt/test/lsan/TestCases/suppressions_default.cc @@ -1,4 +1,4 @@ -// RUN: LSAN_BASE="use_registers=0:use_stacks=0" +// RUN: LSAN_BASE="detect_leaks=1:use_registers=0:use_stacks=0" // RUN: %clangxx_lsan %s -o %t // RUN: LSAN_OPTIONS=$LSAN_BASE not %run %t 2>&1 | FileCheck %s diff --git a/compiler-rt/test/lsan/TestCases/suppressions_file.cc b/compiler-rt/test/lsan/TestCases/suppressions_file.cc index 805091cba4c4..1d8a06474d64 100644 --- a/compiler-rt/test/lsan/TestCases/suppressions_file.cc +++ b/compiler-rt/test/lsan/TestCases/suppressions_file.cc @@ -1,4 +1,4 @@ -// RUN: LSAN_BASE="use_registers=0:use_stacks=0" +// RUN: LSAN_BASE="detect_leaks=1:use_registers=0:use_stacks=0" // RUN: %clangxx_lsan %s -o %t // RUN: rm -f %t.supp diff --git a/compiler-rt/test/lsan/TestCases/use_after_return.cc b/compiler-rt/test/lsan/TestCases/use_after_return.cc index ed9cc785f0f5..413775276b19 100644 --- a/compiler-rt/test/lsan/TestCases/use_after_return.cc +++ b/compiler-rt/test/lsan/TestCases/use_after_return.cc @@ -1,6 +1,6 @@ // Test that fake stack (introduced by ASan's use-after-return mode) is included // in the root set. -// RUN: LSAN_BASE="report_objects=1:use_registers=0" +// RUN: LSAN_BASE="detect_leaks=1:report_objects=1:use_registers=0" // RUN: %clangxx_lsan %s -O2 -o %t // RUN: ASAN_OPTIONS=$ASAN_OPTIONS:detect_stack_use_after_return=1 LSAN_OPTIONS=$LSAN_BASE:"use_stacks=0" not %run %t 2>&1 | FileCheck %s // RUN: ASAN_OPTIONS=$ASAN_OPTIONS:detect_stack_use_after_return=1 LSAN_OPTIONS=$LSAN_BASE:"use_stacks=1" %run %t 2>&1 diff --git a/compiler-rt/test/lsan/TestCases/use_globals_initialized.cc b/compiler-rt/test/lsan/TestCases/use_globals_initialized.cc index 45c12dc4e120..996052d6e832 100644 --- a/compiler-rt/test/lsan/TestCases/use_globals_initialized.cc +++ b/compiler-rt/test/lsan/TestCases/use_globals_initialized.cc @@ -1,5 +1,5 @@ // Test that initialized globals are included in the root set. -// RUN: LSAN_BASE="report_objects=1:use_stacks=0:use_registers=0" +// RUN: LSAN_BASE="detect_leaks=1:report_objects=1:use_stacks=0:use_registers=0" // RUN: %clangxx_lsan %s -o %t // RUN: LSAN_OPTIONS=$LSAN_BASE:"use_globals=0" not %run %t 2>&1 | FileCheck %s // RUN: LSAN_OPTIONS=$LSAN_BASE:"use_globals=1" %run %t 2>&1 diff --git a/compiler-rt/test/lsan/TestCases/use_globals_uninitialized.cc b/compiler-rt/test/lsan/TestCases/use_globals_uninitialized.cc index c198fcc7cbbb..25ccacc7eff8 100644 --- a/compiler-rt/test/lsan/TestCases/use_globals_uninitialized.cc +++ b/compiler-rt/test/lsan/TestCases/use_globals_uninitialized.cc @@ -1,5 +1,5 @@ // Test that uninitialized globals are included in the root set. -// RUN: LSAN_BASE="report_objects=1:use_stacks=0:use_registers=0" +// RUN: LSAN_BASE="detect_leaks=1:report_objects=1:use_stacks=0:use_registers=0" // RUN: %clangxx_lsan %s -o %t // RUN: LSAN_OPTIONS=$LSAN_BASE:"use_globals=0" not %run %t 2>&1 | FileCheck %s // RUN: LSAN_OPTIONS=$LSAN_BASE:"use_globals=1" %run %t 2>&1 diff --git a/compiler-rt/test/lsan/TestCases/use_poisoned_asan.cc b/compiler-rt/test/lsan/TestCases/use_poisoned_asan.cc index 5acceeb8ce0a..d9ef16a4e1dd 100644 --- a/compiler-rt/test/lsan/TestCases/use_poisoned_asan.cc +++ b/compiler-rt/test/lsan/TestCases/use_poisoned_asan.cc @@ -1,6 +1,6 @@ // ASan-poisoned memory should be ignored if use_poisoned is false. // REQUIRES: asan -// RUN: LSAN_BASE="report_objects=1:use_stacks=0:use_registers=0" +// RUN: LSAN_BASE="detect_leaks=1:report_objects=1:use_stacks=0:use_registers=0" // RUN: %clangxx_lsan %s -o %t // RUN: LSAN_OPTIONS=$LSAN_BASE:"use_poisoned=0" not %run %t 2>&1 | FileCheck %s // RUN: LSAN_OPTIONS=$LSAN_BASE:"use_poisoned=1" %run %t 2>&1 diff --git a/compiler-rt/test/lsan/TestCases/use_registers.cc b/compiler-rt/test/lsan/TestCases/use_registers.cc index 7647679f4796..7896874018f9 100644 --- a/compiler-rt/test/lsan/TestCases/use_registers.cc +++ b/compiler-rt/test/lsan/TestCases/use_registers.cc @@ -1,5 +1,5 @@ // Test that registers of running threads are included in the root set. -// RUN: LSAN_BASE="report_objects=1:use_stacks=0" +// RUN: LSAN_BASE="detect_leaks=1:report_objects=1:use_stacks=0" // RUN: %clangxx_lsan -pthread %s -o %t // RUN: LSAN_OPTIONS=$LSAN_BASE:"use_registers=0" not %run %t 2>&1 | FileCheck %s // RUN: LSAN_OPTIONS=$LSAN_BASE:"use_registers=1" %run %t 2>&1 diff --git a/compiler-rt/test/lsan/TestCases/use_stacks.cc b/compiler-rt/test/lsan/TestCases/use_stacks.cc index c32af6841260..95a01003b0c0 100644 --- a/compiler-rt/test/lsan/TestCases/use_stacks.cc +++ b/compiler-rt/test/lsan/TestCases/use_stacks.cc @@ -1,5 +1,5 @@ // Test that stack of main thread is included in the root set. -// RUN: LSAN_BASE="report_objects=1:use_registers=0" +// RUN: LSAN_BASE="detect_leaks=1:report_objects=1:use_registers=0" // RUN: %clangxx_lsan %s -o %t // RUN: LSAN_OPTIONS=$LSAN_BASE:"use_stacks=0" not %run %t 2>&1 | FileCheck %s // RUN: LSAN_OPTIONS=$LSAN_BASE:"use_stacks=1" %run %t 2>&1 diff --git a/compiler-rt/test/lsan/TestCases/use_stacks_threaded.cc b/compiler-rt/test/lsan/TestCases/use_stacks_threaded.cc index ac1fb466fa03..310171feb03b 100644 --- a/compiler-rt/test/lsan/TestCases/use_stacks_threaded.cc +++ b/compiler-rt/test/lsan/TestCases/use_stacks_threaded.cc @@ -1,5 +1,5 @@ // Test that stacks of non-main threads are included in the root set. -// RUN: LSAN_BASE="report_objects=1:use_registers=0" +// RUN: LSAN_BASE="detect_leaks=1:report_objects=1:use_registers=0" // RUN: %clangxx_lsan -pthread %s -o %t // RUN: LSAN_OPTIONS=$LSAN_BASE:"use_stacks=0" not %run %t 2>&1 | FileCheck %s // RUN: LSAN_OPTIONS=$LSAN_BASE:"use_stacks=1" %run %t 2>&1 diff --git a/compiler-rt/test/lsan/TestCases/use_tls_dynamic.cc b/compiler-rt/test/lsan/TestCases/use_tls_dynamic.cc index 927c5c4f768e..770ffafe226d 100644 --- a/compiler-rt/test/lsan/TestCases/use_tls_dynamic.cc +++ b/compiler-rt/test/lsan/TestCases/use_tls_dynamic.cc @@ -1,5 +1,5 @@ // Test that dynamically allocated TLS space is included in the root set. -// RUN: LSAN_BASE="report_objects=1:use_stacks=0:use_registers=0:use_ld_allocations=0" +// RUN: LSAN_BASE="detect_leaks=1:report_objects=1:use_stacks=0:use_registers=0:use_ld_allocations=0" // RUN: %clangxx %s -DBUILD_DSO -fPIC -shared -o %t-so.so // RUN: %clangxx_lsan %s -o %t // RUN: LSAN_OPTIONS=$LSAN_BASE:"use_tls=0" not %run %t 2>&1 | FileCheck %s diff --git a/compiler-rt/test/lsan/TestCases/use_tls_pthread_specific_dynamic.cc b/compiler-rt/test/lsan/TestCases/use_tls_pthread_specific_dynamic.cc index 9ab4e1cdbc0e..f075d035a3e3 100644 --- a/compiler-rt/test/lsan/TestCases/use_tls_pthread_specific_dynamic.cc +++ b/compiler-rt/test/lsan/TestCases/use_tls_pthread_specific_dynamic.cc @@ -1,5 +1,5 @@ // Test that dynamically allocated thread-specific storage is included in the root set. -// RUN: LSAN_BASE="report_objects=1:use_stacks=0:use_registers=0" +// RUN: LSAN_BASE="detect_leaks=1:report_objects=1:use_stacks=0:use_registers=0" // RUN: %clangxx_lsan %s -o %t // RUN: LSAN_OPTIONS=$LSAN_BASE:"use_tls=0" not %run %t 2>&1 | FileCheck %s // RUN: LSAN_OPTIONS=$LSAN_BASE:"use_tls=1" %run %t 2>&1 diff --git a/compiler-rt/test/lsan/TestCases/use_tls_pthread_specific_static.cc b/compiler-rt/test/lsan/TestCases/use_tls_pthread_specific_static.cc index be0bcf628754..d97abab41f09 100644 --- a/compiler-rt/test/lsan/TestCases/use_tls_pthread_specific_static.cc +++ b/compiler-rt/test/lsan/TestCases/use_tls_pthread_specific_static.cc @@ -1,5 +1,5 @@ // Test that statically allocated thread-specific storage is included in the root set. -// RUN: LSAN_BASE="report_objects=1:use_stacks=0:use_registers=0" +// RUN: LSAN_BASE="detect_leaks=1:report_objects=1:use_stacks=0:use_registers=0" // RUN: %clangxx_lsan %s -o %t // RUN: LSAN_OPTIONS=$LSAN_BASE:"use_tls=0" not %run %t 2>&1 | FileCheck %s // RUN: LSAN_OPTIONS=$LSAN_BASE:"use_tls=1" %run %t 2>&1 diff --git a/compiler-rt/test/lsan/TestCases/use_tls_static.cc b/compiler-rt/test/lsan/TestCases/use_tls_static.cc index 5ffaf166bcd5..be34a3abf301 100644 --- a/compiler-rt/test/lsan/TestCases/use_tls_static.cc +++ b/compiler-rt/test/lsan/TestCases/use_tls_static.cc @@ -1,5 +1,5 @@ // Test that statically allocated TLS space is included in the root set. -// RUN: LSAN_BASE="report_objects=1:use_stacks=0:use_registers=0" +// RUN: LSAN_BASE="detect_leaks=1:report_objects=1:use_stacks=0:use_registers=0" // RUN: %clangxx_lsan %s -o %t // RUN: LSAN_OPTIONS=$LSAN_BASE:"use_tls=0" not %run %t 2>&1 | FileCheck %s // RUN: LSAN_OPTIONS=$LSAN_BASE:"use_tls=1" %run %t 2>&1 diff --git a/compiler-rt/test/lsan/TestCases/use_unaligned.cc b/compiler-rt/test/lsan/TestCases/use_unaligned.cc index 86c3ed5200a3..1179c15b73bc 100644 --- a/compiler-rt/test/lsan/TestCases/use_unaligned.cc +++ b/compiler-rt/test/lsan/TestCases/use_unaligned.cc @@ -1,5 +1,5 @@ // Test that unaligned pointers are detected correctly. -// RUN: LSAN_BASE="report_objects=1:use_stacks=0:use_registers=0" +// RUN: LSAN_BASE="detect_leaks=1:report_objects=1:use_stacks=0:use_registers=0" // RUN: %clangxx_lsan %s -o %t // RUN: LSAN_OPTIONS=$LSAN_BASE:"use_unaligned=0" not %run %t 2>&1 | FileCheck %s // RUN: LSAN_OPTIONS=$LSAN_BASE:"use_unaligned=1" %run %t 2>&1 diff --git a/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_death_callback_test.cc b/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_death_callback_test.cc index fdb68c0cdea5..12a56c73e049 100644 --- a/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_death_callback_test.cc +++ b/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_death_callback_test.cc @@ -2,6 +2,13 @@ // REQUIRES: stable-runtime +// For standalone LSan on x86 we have a problem: compiler spills the address +// of allocated at line 42 memory thus memory block allocated in Leak() function +// ends up to be classified as reachable despite the fact we zero out 'sink' at +// the last line of main function. The problem doesn't reproduce with ASan because +// quarantine prohibits memory block reuse for different allocations. +// XFAIL: lsan-x86 + #include #include diff --git a/compiler-rt/test/sanitizer_common/TestCases/corelimit.cc b/compiler-rt/test/sanitizer_common/TestCases/corelimit.cc index 8f54940d04cc..0a86e5b7b7fe 100644 --- a/compiler-rt/test/sanitizer_common/TestCases/corelimit.cc +++ b/compiler-rt/test/sanitizer_common/TestCases/corelimit.cc @@ -1,5 +1,5 @@ // RUN: %clangxx -O0 %s -o %t && %run %t -// XFAIL: lsan +// UNSUPPORTED: lsan #include #include diff --git a/compiler-rt/test/sanitizer_common/lit.common.cfg b/compiler-rt/test/sanitizer_common/lit.common.cfg index b32fb1ba9685..2926edb127aa 100644 --- a/compiler-rt/test/sanitizer_common/lit.common.cfg +++ b/compiler-rt/test/sanitizer_common/lit.common.cfg @@ -26,6 +26,9 @@ config.available_features.add(config.tool_name) if config.target_arch not in ['arm', 'armhf', 'aarch64']: config.available_features.add('stable-runtime') +if config.host_os == 'Linux' and config.target_arch == 'i386' and config.tool_name == "lsan": + config.available_features.add("lsan-x86") + if config.host_os == 'Darwin': # On Darwin, we default to `abort_on_error=1`, which would make tests run # much slower. Let's override this and run lit tests with 'abort_on_error=0'. diff --git a/compiler-rt/test/sanitizer_common/print_address.h b/compiler-rt/test/sanitizer_common/print_address.h index 018db61800d3..99261b331245 100644 --- a/compiler-rt/test/sanitizer_common/print_address.h +++ b/compiler-rt/test/sanitizer_common/print_address.h @@ -11,6 +11,8 @@ void print_address(const char *str, int n, ...) { // On FreeBSD, the %p conversion specifier works as 0x%x and thus does not // match to the format used in the diagnotic message. fprintf(stderr, "0x%012lx ", (unsigned long) p); +#elif defined(__i386__) + fprintf(stderr, "0x%8lx ", (unsigned long) p); #elif defined(__mips64) fprintf(stderr, "0x%010lx ", (unsigned long) p); #endif