mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-25 06:56:06 +00:00
[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
This commit is contained in:
parent
d501b18990
commit
2523faf677
@ -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})
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -26,6 +26,8 @@
|
||||
#include "lsan_common.h"
|
||||
#include "lsan_thread.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
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; \
|
||||
|
@ -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 "
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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__)
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 <assert.h>
|
||||
|
@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "sanitizer_common/print_address.h"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 <sanitizer/common_interface_defs.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// RUN: %clangxx -O0 %s -o %t && %run %t
|
||||
// XFAIL: lsan
|
||||
// UNSUPPORTED: lsan
|
||||
|
||||
#include <assert.h>
|
||||
#include <sys/time.h>
|
||||
|
@ -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'.
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user