summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid L. Jones <dlj@google.com>2017-11-15 01:40:05 +0000
committerDavid L. Jones <dlj@google.com>2017-11-15 01:40:05 +0000
commit29961b5a9b00642c770ae522a336cf2cc6077398 (patch)
treed5d975f68cc9a5b4eaa8df4bca59c298988eaede
parent5cdb7458cb1d6fc8fc83dd5a177658f1284f5d29 (diff)
parent65964b0190520f92123c3b1adb7dce481179909b (diff)
downloadcompiler-rt-google/testing.tar.gz
Creating branches/google/testing and tags/google/testing/2017-11-14 from r317716google/testing
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/branches/google/testing@318248 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/asan/asan_fuchsia.cc2
-rw-r--r--lib/asan/asan_rtl.cc2
-rw-r--r--lib/builtins/CMakeLists.txt8
-rw-r--r--lib/cfi/cfi.cc2
-rw-r--r--lib/lsan/lsan_common.cc5
-rw-r--r--lib/lsan/lsan_common_linux.cc20
-rw-r--r--lib/msan/msan_linux.cc2
-rw-r--r--lib/profile/WindowsMMap.c58
-rw-r--r--lib/sanitizer_common/sanitizer_allocator_primary64.h21
-rw-r--r--lib/sanitizer_common/sanitizer_common.h5
-rw-r--r--lib/sanitizer_common/sanitizer_common_interceptors.inc4
-rw-r--r--lib/sanitizer_common/sanitizer_fuchsia.cc10
-rw-r--r--lib/sanitizer_common/sanitizer_getauxval.h40
-rw-r--r--lib/sanitizer_common/sanitizer_linux.cc19
-rw-r--r--lib/sanitizer_common/sanitizer_mac.cc2
-rw-r--r--lib/sanitizer_common/sanitizer_mac_libcdep.cc2
-rw-r--r--lib/sanitizer_common/sanitizer_posix_libcdep.cc17
-rw-r--r--lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc10
-rw-r--r--lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc3
-rw-r--r--lib/sanitizer_common/sanitizer_syscall_linux_arm.inc141
-rw-r--r--lib/sanitizer_common/sanitizer_win.cc12
-rw-r--r--lib/sanitizer_common/sanitizer_win_weak_interception.cc2
-rwxr-xr-xlib/sanitizer_common/scripts/check_lint.sh6
-rw-r--r--lib/scudo/scudo_allocator_secondary.h1
-rw-r--r--lib/scudo/scudo_crc32.h2
-rw-r--r--lib/scudo/scudo_utils.cpp6
-rw-r--r--lib/scudo/scudo_utils.h6
-rw-r--r--lib/tsan/CMakeLists.txt6
-rw-r--r--lib/tsan/rtl/tsan_interceptors.cc71
-rw-r--r--lib/tsan/rtl/tsan_platform_mac.cc2
-rw-r--r--test/asan/TestCases/contiguous_container_crash.cc6
31 files changed, 398 insertions, 95 deletions
diff --git a/lib/asan/asan_fuchsia.cc b/lib/asan/asan_fuchsia.cc
index 02fb8be4a..0b5bff4f5 100644
--- a/lib/asan/asan_fuchsia.cc
+++ b/lib/asan/asan_fuchsia.cc
@@ -28,7 +28,7 @@
namespace __asan {
// The system already set up the shadow memory for us.
-// __sanitizer::GetMaxVirtualAddress has already been called by
+// __sanitizer::GetMaxUserVirtualAddress has already been called by
// AsanInitInternal->InitializeHighMemEnd (asan_rtl.cc).
// Just do some additional sanity checks here.
void InitializeShadowMemory() {
diff --git a/lib/asan/asan_rtl.cc b/lib/asan/asan_rtl.cc
index 8608e4a60..27e4bd842 100644
--- a/lib/asan/asan_rtl.cc
+++ b/lib/asan/asan_rtl.cc
@@ -307,7 +307,7 @@ static void asan_atexit() {
static void InitializeHighMemEnd() {
#if !ASAN_FIXED_MAPPING
- kHighMemEnd = GetMaxVirtualAddress();
+ kHighMemEnd = GetMaxUserVirtualAddress();
// Increase kHighMemEnd to make sure it's properly
// aligned together with kHighMemBeg:
kHighMemEnd |= SHADOW_GRANULARITY * GetMmapGranularity() - 1;
diff --git a/lib/builtins/CMakeLists.txt b/lib/builtins/CMakeLists.txt
index 6128abcbf..3fc1d057f 100644
--- a/lib/builtins/CMakeLists.txt
+++ b/lib/builtins/CMakeLists.txt
@@ -454,8 +454,12 @@ set(mips64_SOURCES ${GENERIC_TF_SOURCES}
set(mips64el_SOURCES ${GENERIC_TF_SOURCES}
${mips_SOURCES})
-set(wasm32_SOURCES ${GENERIC_SOURCES})
-set(wasm64_SOURCES ${GENERIC_SOURCES})
+set(wasm32_SOURCES
+ ${GENERIC_TF_SOURCES}
+ ${GENERIC_SOURCES})
+set(wasm64_SOURCES
+ ${GENERIC_TF_SOURCES}
+ ${GENERIC_SOURCES})
add_custom_target(builtins)
set_target_properties(builtins PROPERTIES FOLDER "Compiler-RT Misc")
diff --git a/lib/cfi/cfi.cc b/lib/cfi/cfi.cc
index f720230a7..f7693b37d 100644
--- a/lib/cfi/cfi.cc
+++ b/lib/cfi/cfi.cc
@@ -280,7 +280,7 @@ void InitShadow() {
CHECK_EQ(0, GetShadow());
CHECK_EQ(0, GetShadowSize());
- uptr vma = GetMaxVirtualAddress();
+ uptr vma = GetMaxUserVirtualAddress();
// Shadow is 2 -> 2**kShadowGranularity.
SetShadowSize((vma >> (kShadowGranularity - 1)) + 1);
VReport(1, "CFI: VMA size %zx, shadow size %zx\n", vma, GetShadowSize());
diff --git a/lib/lsan/lsan_common.cc b/lib/lsan/lsan_common.cc
index 622aae734..651bbe1f3 100644
--- a/lib/lsan/lsan_common.cc
+++ b/lib/lsan/lsan_common.cc
@@ -411,8 +411,9 @@ static void MarkInvalidPCCb(uptr chunk, void *arg) {
}
}
-// On Linux, handles dynamically allocated TLS blocks by treating all chunks
-// allocated from ld-linux.so as reachable.
+// On Linux, treats all chunks allocated from ld-linux.so as reachable, which
+// covers dynamically allocated TLS blocks, internal dynamic loader's loaded
+// modules accounting etc.
// Dynamic TLS blocks contain the TLS variables of dynamically loaded modules.
// They are allocated with a __libc_memalign() call in allocate_and_init()
// (elf/dl-tls.c). Glibc won't tell us the address ranges occupied by those
diff --git a/lib/lsan/lsan_common_linux.cc b/lib/lsan/lsan_common_linux.cc
index 5042c7b3a..cdd7f032a 100644
--- a/lib/lsan/lsan_common_linux.cc
+++ b/lib/lsan/lsan_common_linux.cc
@@ -20,6 +20,7 @@
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_getauxval.h"
#include "sanitizer_common/sanitizer_linux.h"
#include "sanitizer_common/sanitizer_stackdepot.h"
@@ -30,8 +31,12 @@ static const char kLinkerName[] = "ld";
static char linker_placeholder[sizeof(LoadedModule)] ALIGNED(64);
static LoadedModule *linker = nullptr;
-static bool IsLinker(const char* full_name) {
- return LibraryNameIs(full_name, kLinkerName);
+static bool IsLinker(const LoadedModule& module) {
+#if SANITIZER_USE_GETAUXVAL
+ return module.base_address() == getauxval(AT_BASE);
+#else
+ return LibraryNameIs(module.full_name(), kLinkerName);
+#endif // SANITIZER_USE_GETAUXVAL
}
__attribute__((tls_model("initial-exec")))
@@ -49,22 +54,25 @@ void InitializePlatformSpecificModules() {
ListOfModules modules;
modules.init();
for (LoadedModule &module : modules) {
- if (!IsLinker(module.full_name())) continue;
+ if (!IsLinker(module))
+ continue;
if (linker == nullptr) {
linker = reinterpret_cast<LoadedModule *>(linker_placeholder);
*linker = module;
module = LoadedModule();
} else {
VReport(1, "LeakSanitizer: Multiple modules match \"%s\". "
- "TLS will not be handled correctly.\n", kLinkerName);
+ "TLS and other allocations originating from linker might be "
+ "falsely reported as leaks.\n", kLinkerName);
linker->clear();
linker = nullptr;
return;
}
}
if (linker == nullptr) {
- VReport(1, "LeakSanitizer: Dynamic linker not found. "
- "TLS will not be handled correctly.\n");
+ VReport(1, "LeakSanitizer: Dynamic linker not found. TLS and other "
+ "allocations originating from linker might be falsely reported "
+ "as leaks.\n");
}
}
diff --git a/lib/msan/msan_linux.cc b/lib/msan/msan_linux.cc
index a1191a100..4e6321fcb 100644
--- a/lib/msan/msan_linux.cc
+++ b/lib/msan/msan_linux.cc
@@ -120,7 +120,7 @@ bool InitShadow(bool init_origins) {
return false;
}
- const uptr maxVirtualAddress = GetMaxVirtualAddress();
+ const uptr maxVirtualAddress = GetMaxUserVirtualAddress();
for (unsigned i = 0; i < kMemoryLayoutSize; ++i) {
uptr start = kMemoryLayout[i].start;
diff --git a/lib/profile/WindowsMMap.c b/lib/profile/WindowsMMap.c
index f81d7da53..0c534710b 100644
--- a/lib/profile/WindowsMMap.c
+++ b/lib/profile/WindowsMMap.c
@@ -120,9 +120,61 @@ int msync(void *addr, size_t length, int flags)
}
COMPILER_RT_VISIBILITY
-int flock(int fd, int operation)
-{
- return -1; /* Not supported. */
+int lock(HANDLE handle, DWORD lockType, BOOL blocking) {
+ DWORD flags = lockType;
+ if (!blocking)
+ flags |= LOCKFILE_FAIL_IMMEDIATELY;
+
+ OVERLAPPED overlapped;
+ ZeroMemory(&overlapped, sizeof(OVERLAPPED));
+ overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ BOOL result = LockFileEx(handle, flags, 0, MAXDWORD, MAXDWORD, &overlapped);
+ if (!result) {
+ DWORD dw = GetLastError();
+
+ // In non-blocking mode, return an error if the file is locked.
+ if (!blocking && dw == ERROR_LOCK_VIOLATION)
+ return -1; // EWOULDBLOCK
+
+ // If the error is ERROR_IO_PENDING, we need to wait until the operation
+ // finishes. Otherwise, we return an error.
+ if (dw != ERROR_IO_PENDING)
+ return -1;
+
+ DWORD dwNumBytes;
+ if (!GetOverlappedResult(handle, &overlapped, &dwNumBytes, TRUE))
+ return -1;
+ }
+
+ return 0;
+}
+
+COMPILER_RT_VISIBILITY
+int flock(int fd, int operation) {
+ HANDLE handle = (HANDLE)_get_osfhandle(fd);
+ if (handle == INVALID_HANDLE_VALUE)
+ return -1;
+
+ BOOL blocking = (operation & LOCK_NB) == 0;
+ int op = operation & ~LOCK_NB;
+
+ switch (op) {
+ case LOCK_EX:
+ return lock(handle, LOCKFILE_EXCLUSIVE_LOCK, blocking);
+
+ case LOCK_SH:
+ return lock(handle, 0, blocking);
+
+ case LOCK_UN:
+ if (!UnlockFile(handle, 0, 0, MAXDWORD, MAXDWORD))
+ return -1;
+ break;
+
+ default:
+ return -1;
+ }
+
+ return 0;
}
#undef DWORD_HI
diff --git a/lib/sanitizer_common/sanitizer_allocator_primary64.h b/lib/sanitizer_common/sanitizer_allocator_primary64.h
index b22f3aba9..4fb2f929c 100644
--- a/lib/sanitizer_common/sanitizer_allocator_primary64.h
+++ b/lib/sanitizer_common/sanitizer_allocator_primary64.h
@@ -72,11 +72,10 @@ class SizeClassAllocator64 {
void Init(s32 release_to_os_interval_ms) {
uptr TotalSpaceSize = kSpaceSize + AdditionalSize();
if (kUsingConstantSpaceBeg) {
- CHECK_EQ(kSpaceBeg, reinterpret_cast<uptr>(
- MmapFixedNoAccess(kSpaceBeg, TotalSpaceSize)));
+ CHECK_EQ(kSpaceBeg, address_range.Init(TotalSpaceSize, AllocatorName(),
+ kSpaceBeg));
} else {
- NonConstSpaceBeg =
- reinterpret_cast<uptr>(MmapNoAccess(TotalSpaceSize));
+ NonConstSpaceBeg = address_range.Init(TotalSpaceSize, AllocatorName());
CHECK_NE(NonConstSpaceBeg, ~(uptr)0);
}
SetReleaseToOSIntervalMs(release_to_os_interval_ms);
@@ -544,6 +543,9 @@ class SizeClassAllocator64 {
private:
friend class MemoryMapper;
+ ReservedAddressRange address_range;
+ static const char *AllocatorName() { return "sanitizer_allocator"; }
+
static const uptr kRegionSize = kSpaceSize / kNumClassesRounded;
// FreeArray is the array of free-d chunks (stored as 4-byte offsets).
// In the worst case it may reguire kRegionSize/SizeClassMap::kMinSize
@@ -625,7 +627,7 @@ class SizeClassAllocator64 {
}
bool MapWithCallback(uptr beg, uptr size) {
- uptr mapped = reinterpret_cast<uptr>(MmapFixedOrDieOnFatalError(beg, size));
+ uptr mapped = address_range.Map(beg, size);
if (UNLIKELY(!mapped))
return false;
CHECK_EQ(beg, mapped);
@@ -634,13 +636,13 @@ class SizeClassAllocator64 {
}
void MapWithCallbackOrDie(uptr beg, uptr size) {
- CHECK_EQ(beg, reinterpret_cast<uptr>(MmapFixedOrDie(beg, size)));
+ CHECK_EQ(beg, address_range.MapOrDie(beg, size));
MapUnmapCallback().OnMap(beg, size);
}
void UnmapWithCallbackOrDie(uptr beg, uptr size) {
MapUnmapCallback().OnUnmap(beg, size);
- UnmapOrDie(reinterpret_cast<void *>(beg), size);
+ address_range.Unmap(beg, size);
}
bool EnsureFreeArraySpace(RegionInfo *region, uptr region_beg,
@@ -677,7 +679,10 @@ class SizeClassAllocator64 {
// preventing just allocated memory from being released sooner than
// necessary and also preventing extraneous ReleaseMemoryPagesToOS calls
// for short lived processes.
- region->rtoi.last_release_at_ns = NanoTime();
+ // Do it only when the feature is turned on, to avoid a potentially
+ // extraneous syscall.
+ if (ReleaseToOSIntervalMs() >= 0)
+ region->rtoi.last_release_at_ns = NanoTime();
}
// Do the mmap for the user memory.
uptr map_size = kUserMapSize;
diff --git a/lib/sanitizer_common/sanitizer_common.h b/lib/sanitizer_common/sanitizer_common.h
index 14b92d9c4..d64d3e153 100644
--- a/lib/sanitizer_common/sanitizer_common.h
+++ b/lib/sanitizer_common/sanitizer_common.h
@@ -73,7 +73,7 @@ INLINE uptr GetPageSizeCached() {
return PageSizeCached;
}
uptr GetMmapGranularity();
-uptr GetMaxVirtualAddress();
+uptr GetMaxUserVirtualAddress();
// Threads
tid_t GetTid();
uptr GetThreadSelf();
@@ -131,7 +131,8 @@ void RunFreeHooks(const void *ptr);
class ReservedAddressRange {
public:
uptr Init(uptr size, const char *name = nullptr, uptr fixed_addr = 0);
- uptr Map(uptr fixed_addr, uptr size, bool tolerate_enomem = false);
+ uptr Map(uptr fixed_addr, uptr size);
+ uptr MapOrDie(uptr fixed_addr, uptr size);
void Unmap(uptr addr, uptr size);
void *base() const { return base_; }
uptr size() const { return size_; }
diff --git a/lib/sanitizer_common/sanitizer_common_interceptors.inc b/lib/sanitizer_common/sanitizer_common_interceptors.inc
index 321126c10..16cc07020 100644
--- a/lib/sanitizer_common/sanitizer_common_interceptors.inc
+++ b/lib/sanitizer_common/sanitizer_common_interceptors.inc
@@ -5835,7 +5835,7 @@ INTERCEPTOR(int, pthread_setcancelstate, int state, int *oldstate) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, pthread_setcancelstate, state, oldstate);
int res = REAL(pthread_setcancelstate)(state, oldstate);
- if (res == 0)
+ if (res == 0 && oldstate != nullptr)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldstate, sizeof(*oldstate));
return res;
}
@@ -5844,7 +5844,7 @@ INTERCEPTOR(int, pthread_setcanceltype, int type, int *oldtype) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, pthread_setcanceltype, type, oldtype);
int res = REAL(pthread_setcanceltype)(type, oldtype);
- if (res == 0)
+ if (res == 0 && oldtype != nullptr)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldtype, sizeof(*oldtype));
return res;
}
diff --git a/lib/sanitizer_common/sanitizer_fuchsia.cc b/lib/sanitizer_common/sanitizer_fuchsia.cc
index a2a532110..97dff0d8b 100644
--- a/lib/sanitizer_common/sanitizer_fuchsia.cc
+++ b/lib/sanitizer_common/sanitizer_fuchsia.cc
@@ -186,7 +186,7 @@ uptr GetMmapGranularity() { return PAGE_SIZE; }
sanitizer_shadow_bounds_t ShadowBounds;
-uptr GetMaxVirtualAddress() {
+uptr GetMaxUserVirtualAddress() {
ShadowBounds = __sanitizer_shadow_bounds();
return ShadowBounds.memory_limit - 1;
}
@@ -246,8 +246,12 @@ uptr ReservedAddressRange::Init(uptr init_size, const char* name,
// Uses fixed_addr for now.
// Will use offset instead once we've implemented this function for real.
-uptr ReservedAddressRange::Map(uptr fixed_addr, uptr map_size,
- bool tolerate_enomem) {
+uptr ReservedAddressRange::Map(uptr fixed_addr, uptr map_size) {
+ return reinterpret_cast<uptr>(MmapFixedOrDieOnFatalError(fixed_addr,
+ map_size));
+}
+
+uptr ReservedAddressRange::MapOrDie(uptr fixed_addr, uptr map_size) {
return reinterpret_cast<uptr>(MmapFixedOrDie(fixed_addr, map_size));
}
diff --git a/lib/sanitizer_common/sanitizer_getauxval.h b/lib/sanitizer_common/sanitizer_getauxval.h
new file mode 100644
index 000000000..d0287f02c
--- /dev/null
+++ b/lib/sanitizer_common/sanitizer_getauxval.h
@@ -0,0 +1,40 @@
+//===-- sanitizer_getauxval.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Common getauxval() guards and definitions.
+// getauxval() is not defined until glbc version 2.16.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_GETAUXVAL_H
+#define SANITIZER_GETAUXVAL_H
+
+#include "sanitizer_platform.h"
+
+#if SANITIZER_LINUX
+
+#include <features.h>
+
+#ifndef __GLIBC_PREREQ
+#define __GLIBC_PREREQ(x, y) 0
+#endif
+
+#if __GLIBC_PREREQ(2, 16)
+# define SANITIZER_USE_GETAUXVAL 1
+#else
+# define SANITIZER_USE_GETAUXVAL 0
+#endif
+
+#if SANITIZER_USE_GETAUXVAL
+#include <sys/auxv.h>
+#endif
+
+#endif // SANITIZER_LINUX
+
+#endif // SANITIZER_GETAUXVAL_H
diff --git a/lib/sanitizer_common/sanitizer_linux.cc b/lib/sanitizer_common/sanitizer_linux.cc
index 6ea185817..ea1e79556 100644
--- a/lib/sanitizer_common/sanitizer_linux.cc
+++ b/lib/sanitizer_common/sanitizer_linux.cc
@@ -18,6 +18,7 @@
#include "sanitizer_common.h"
#include "sanitizer_flags.h"
+#include "sanitizer_getauxval.h"
#include "sanitizer_internal_defs.h"
#include "sanitizer_libc.h"
#include "sanitizer_linux.h"
@@ -95,20 +96,6 @@ extern struct ps_strings *__ps_strings;
#include <sys/signal.h>
#endif
-#ifndef __GLIBC_PREREQ
-#define __GLIBC_PREREQ(x, y) 0
-#endif
-
-#if SANITIZER_LINUX && __GLIBC_PREREQ(2, 16)
-# define SANITIZER_USE_GETAUXVAL 1
-#else
-# define SANITIZER_USE_GETAUXVAL 0
-#endif
-
-#if SANITIZER_USE_GETAUXVAL
-#include <sys/auxv.h>
-#endif
-
#if SANITIZER_LINUX
// <linux/time.h>
struct kernel_timeval {
@@ -152,6 +139,8 @@ namespace __sanitizer {
#include "sanitizer_syscall_linux_x86_64.inc"
#elif SANITIZER_LINUX && defined(__aarch64__)
#include "sanitizer_syscall_linux_aarch64.inc"
+#elif SANITIZER_LINUX && defined(__arm__)
+#include "sanitizer_syscall_linux_arm.inc"
#else
#include "sanitizer_syscall_generic.inc"
#endif
@@ -965,7 +954,7 @@ static uptr GetKernelAreaSize() {
}
#endif // SANITIZER_WORDSIZE == 32
-uptr GetMaxVirtualAddress() {
+uptr GetMaxUserVirtualAddress() {
#if SANITIZER_NETBSD && defined(__x86_64__)
return 0x7f7ffffff000ULL; // (0x00007f8000000000 - PAGE_SIZE)
#elif SANITIZER_WORDSIZE == 64
diff --git a/lib/sanitizer_common/sanitizer_mac.cc b/lib/sanitizer_common/sanitizer_mac.cc
index 9fead91b9..7a93c112b 100644
--- a/lib/sanitizer_common/sanitizer_mac.cc
+++ b/lib/sanitizer_common/sanitizer_mac.cc
@@ -849,7 +849,7 @@ uptr GetTaskInfoMaxAddress() {
}
#endif
-uptr GetMaxVirtualAddress() {
+uptr GetMaxUserVirtualAddress() {
#if SANITIZER_WORDSIZE == 64
# if defined(__aarch64__) && SANITIZER_IOS && !SANITIZER_IOSSIM
// Get the maximum VM address
diff --git a/lib/sanitizer_common/sanitizer_mac_libcdep.cc b/lib/sanitizer_common/sanitizer_mac_libcdep.cc
index c95daa937..090f17c88 100644
--- a/lib/sanitizer_common/sanitizer_mac_libcdep.cc
+++ b/lib/sanitizer_common/sanitizer_mac_libcdep.cc
@@ -20,7 +20,7 @@
namespace __sanitizer {
void RestrictMemoryToMaxAddress(uptr max_address) {
- uptr size_to_mmap = GetMaxVirtualAddress() + 1 - max_address;
+ uptr size_to_mmap = GetMaxUserVirtualAddress() + 1 - max_address;
void *res = MmapFixedNoAccess(max_address, size_to_mmap, "high gap");
CHECK(res != MAP_FAILED);
}
diff --git a/lib/sanitizer_common/sanitizer_posix_libcdep.cc b/lib/sanitizer_common/sanitizer_posix_libcdep.cc
index 0ba3ad46b..40b5f8a4e 100644
--- a/lib/sanitizer_common/sanitizer_posix_libcdep.cc
+++ b/lib/sanitizer_common/sanitizer_posix_libcdep.cc
@@ -338,8 +338,13 @@ void *MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name) {
}
uptr ReservedAddressRange::Init(uptr size, const char *name, uptr fixed_addr) {
+ // We don't pass `name` along because, when you enable `decorate_proc_maps`
+ // AND actually use a named mapping AND are using a sanitizer intercepting
+ // `open` (e.g. TSAN, ESAN), then you'll get a failure during initialization.
+ // TODO(flowerhack): Fix the implementation of GetNamedMappingFd to solve
+ // this problem.
if (fixed_addr) {
- base_ = MmapFixedNoAccess(fixed_addr, size, name);
+ base_ = MmapFixedNoAccess(fixed_addr, size);
} else {
base_ = MmapNoAccess(size);
}
@@ -350,11 +355,11 @@ uptr ReservedAddressRange::Init(uptr size, const char *name, uptr fixed_addr) {
// Uses fixed_addr for now.
// Will use offset instead once we've implemented this function for real.
-uptr ReservedAddressRange::Map(uptr fixed_addr, uptr size,
- bool tolerate_enomem) {
- if (tolerate_enomem) {
- return reinterpret_cast<uptr>(MmapFixedOrDieOnFatalError(fixed_addr, size));
- }
+uptr ReservedAddressRange::Map(uptr fixed_addr, uptr size) {
+ return reinterpret_cast<uptr>(MmapFixedOrDieOnFatalError(fixed_addr, size));
+}
+
+uptr ReservedAddressRange::MapOrDie(uptr fixed_addr, uptr size) {
return reinterpret_cast<uptr>(MmapFixedOrDie(fixed_addr, size));
}
diff --git a/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc b/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc
index e1cb6f76f..ea864e59e 100644
--- a/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc
+++ b/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc
@@ -57,6 +57,14 @@
#include "sanitizer_mutex.h"
#include "sanitizer_placement_new.h"
+// Sufficiently old kernel headers don't provide this value, but we can still
+// call prctl with it. If the runtime kernel is new enough, the prctl call will
+// have the desired effect; if the kernel is too old, the call will error and we
+// can ignore said error.
+#ifndef PR_SET_PTRACER
+#define PR_SET_PTRACER 0x59616d61
+#endif
+
// This module works by spawning a Linux task which then attaches to every
// thread in the caller process with ptrace. This suspends the threads, and
// PTRACE_GETREGS can then be used to obtain their register state. The callback
@@ -433,9 +441,7 @@ void StopTheWorld(StopTheWorldCallback callback, void *argument) {
ScopedSetTracerPID scoped_set_tracer_pid(tracer_pid);
// On some systems we have to explicitly declare that we want to be traced
// by the tracer thread.
-#ifdef PR_SET_PTRACER
internal_prctl(PR_SET_PTRACER, tracer_pid, 0, 0, 0);
-#endif
// Allow the tracer thread to start.
tracer_thread_argument.mutex.Unlock();
// NOTE: errno is shared between this thread and the tracer thread.
diff --git a/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc b/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc
index 57354668b..e98fab01d 100644
--- a/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc
+++ b/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc
@@ -95,7 +95,8 @@ struct SymbolizeCodeCallbackArg {
if (frames_symbolized > 0) {
SymbolizedStack *cur = SymbolizedStack::New(addr);
AddressInfo *info = &cur->info;
- info->FillModuleInfo(first->info.module, first->info.module_offset);
+ info->FillModuleInfo(first->info.module, first->info.module_offset,
+ first->info.module_arch);
last->next = cur;
last = cur;
}
diff --git a/lib/sanitizer_common/sanitizer_syscall_linux_arm.inc b/lib/sanitizer_common/sanitizer_syscall_linux_arm.inc
new file mode 100644
index 000000000..a3fdb9e60
--- /dev/null
+++ b/lib/sanitizer_common/sanitizer_syscall_linux_arm.inc
@@ -0,0 +1,141 @@
+//===-- sanitizer_syscall_linux_arm.inc -------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementations of internal_syscall and internal_iserror for Linux/arm.
+//
+//===----------------------------------------------------------------------===//
+
+#define SYSCALL(name) __NR_ ## name
+
+static uptr __internal_syscall(u32 nr) {
+ register u32 r8 asm("r7") = nr;
+ register u32 r0 asm("r0");
+ asm volatile("swi #0"
+ : "=r"(r0)
+ : "r"(r8)
+ : "memory", "cc");
+ return r0;
+}
+#define __internal_syscall0(n) \
+ (__internal_syscall)(n)
+
+static uptr __internal_syscall(u32 nr, u32 arg1) {
+ register u32 r8 asm("r7") = nr;
+ register u32 r0 asm("r0") = arg1;
+ asm volatile("swi #0"
+ : "=r"(r0)
+ : "r"(r8), "0"(r0)
+ : "memory", "cc");
+ return r0;
+}
+#define __internal_syscall1(n, a1) \
+ (__internal_syscall)(n, (u32)(a1))
+
+static uptr __internal_syscall(u32 nr, u32 arg1, long arg2) {
+ register u32 r8 asm("r7") = nr;
+ register u32 r0 asm("r0") = arg1;
+ register u32 r1 asm("r1") = arg2;
+ asm volatile("swi #0"
+ : "=r"(r0)
+ : "r"(r8), "0"(r0), "r"(r1)
+ : "memory", "cc");
+ return r0;
+}
+#define __internal_syscall2(n, a1, a2) \
+ (__internal_syscall)(n, (u32)(a1), (long)(a2))
+
+static uptr __internal_syscall(u32 nr, u32 arg1, long arg2, long arg3) {
+ register u32 r8 asm("r7") = nr;
+ register u32 r0 asm("r0") = arg1;
+ register u32 r1 asm("r1") = arg2;
+ register u32 r2 asm("r2") = arg3;
+ asm volatile("swi #0"
+ : "=r"(r0)
+ : "r"(r8), "0"(r0), "r"(r1), "r"(r2)
+ : "memory", "cc");
+ return r0;
+}
+#define __internal_syscall3(n, a1, a2, a3) \
+ (__internal_syscall)(n, (u32)(a1), (long)(a2), (long)(a3))
+
+static uptr __internal_syscall(u32 nr, u32 arg1, long arg2, long arg3,
+ u32 arg4) {
+ register u32 r8 asm("r7") = nr;
+ register u32 r0 asm("r0") = arg1;
+ register u32 r1 asm("r1") = arg2;
+ register u32 r2 asm("r2") = arg3;
+ register u32 r3 asm("r3") = arg4;
+ asm volatile("swi #0"
+ : "=r"(r0)
+ : "r"(r8), "0"(r0), "r"(r1), "r"(r2), "r"(r3)
+ : "memory", "cc");
+ return r0;
+}
+#define __internal_syscall4(n, a1, a2, a3, a4) \
+ (__internal_syscall)(n, (u32)(a1), (long)(a2), (long)(a3), (long)(a4))
+
+static uptr __internal_syscall(u32 nr, u32 arg1, long arg2, long arg3,
+ u32 arg4, long arg5) {
+ register u32 r8 asm("r7") = nr;
+ register u32 r0 asm("r0") = arg1;
+ register u32 r1 asm("r1") = arg2;
+ register u32 r2 asm("r2") = arg3;
+ register u32 r3 asm("r3") = arg4;
+ register u32 r4 asm("r4") = arg5;
+ asm volatile("swi #0"
+ : "=r"(r0)
+ : "r"(r8), "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4)
+ : "memory", "cc");
+ return r0;
+}
+#define __internal_syscall5(n, a1, a2, a3, a4, a5) \
+ (__internal_syscall)(n, (u32)(a1), (long)(a2), (long)(a3), (long)(a4), \
+ (u32)(a5))
+
+static uptr __internal_syscall(u32 nr, u32 arg1, long arg2, long arg3,
+ u32 arg4, long arg5, long arg6) {
+ register u32 r8 asm("r7") = nr;
+ register u32 r0 asm("r0") = arg1;
+ register u32 r1 asm("r1") = arg2;
+ register u32 r2 asm("r2") = arg3;
+ register u32 r3 asm("r3") = arg4;
+ register u32 r4 asm("r4") = arg5;
+ register u32 r5 asm("r5") = arg6;
+ asm volatile("swi #0"
+ : "=r"(r0)
+ : "r"(r8), "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5)
+ : "memory", "cc");
+ return r0;
+}
+#define __internal_syscall6(n, a1, a2, a3, a4, a5, a6) \
+ (__internal_syscall)(n, (u32)(a1), (long)(a2), (long)(a3), (long)(a4), \
+ (u32)(a5), (long)(a6))
+
+#define __SYSCALL_NARGS_X(a1, a2, a3, a4, a5, a6, a7, a8, n, ...) n
+#define __SYSCALL_NARGS(...) \
+ __SYSCALL_NARGS_X(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0, )
+#define __SYSCALL_CONCAT_X(a, b) a##b
+#define __SYSCALL_CONCAT(a, b) __SYSCALL_CONCAT_X(a, b)
+#define __SYSCALL_DISP(b, ...) \
+ __SYSCALL_CONCAT(b, __SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__)
+
+#define internal_syscall(...) __SYSCALL_DISP(__internal_syscall, __VA_ARGS__)
+
+#define internal_syscall_ptr internal_syscall
+#define internal_syscall64 internal_syscall
+
+// Helper function used to avoid cobbler errno.
+bool internal_iserror(uptr retval, int *rverrno) {
+ if (retval >= (uptr)-4095) {
+ if (rverrno)
+ *rverrno = -retval;
+ return true;
+ }
+ return false;
+}
diff --git a/lib/sanitizer_common/sanitizer_win.cc b/lib/sanitizer_common/sanitizer_win.cc
index b2fd8baca..1186971f7 100644
--- a/lib/sanitizer_common/sanitizer_win.cc
+++ b/lib/sanitizer_common/sanitizer_win.cc
@@ -64,7 +64,7 @@ uptr GetMmapGranularity() {
return si.dwAllocationGranularity;
}
-uptr GetMaxVirtualAddress() {
+uptr GetMaxUserVirtualAddress() {
SYSTEM_INFO si;
GetSystemInfo(&si);
return (uptr)si.lpMaximumApplicationAddress;
@@ -237,11 +237,11 @@ void *MmapFixedOrDie(uptr fixed_addr, uptr size) {
// Uses fixed_addr for now.
// Will use offset instead once we've implemented this function for real.
-uptr ReservedAddressRange::Map(uptr fixed_addr, uptr size,
- bool tolerate_enomem) {
- if (tolerate_enomem) {
- return reinterpret_cast<uptr>(MmapFixedOrDieOnFatalError(fixed_addr, size));
- }
+uptr ReservedAddressRange::Map(uptr fixed_addr, uptr size) {
+ return reinterpret_cast<uptr>(MmapFixedOrDieOnFatalError(fixed_addr, size));
+}
+
+uptr ReservedAddressRange::MapOrDie(uptr fixed_addr, uptr size) {
return reinterpret_cast<uptr>(MmapFixedOrDie(fixed_addr, size));
}
diff --git a/lib/sanitizer_common/sanitizer_win_weak_interception.cc b/lib/sanitizer_common/sanitizer_win_weak_interception.cc
index 364319398..5711f5dc8 100644
--- a/lib/sanitizer_common/sanitizer_win_weak_interception.cc
+++ b/lib/sanitizer_common/sanitizer_win_weak_interception.cc
@@ -12,7 +12,7 @@
// definition is provided.
//===----------------------------------------------------------------------===//
-#include "sanitizer_common/sanitizer_platform.h"
+#include "sanitizer_platform.h"
#if SANITIZER_WINDOWS && SANITIZER_DYNAMIC
#include "sanitizer_win_weak_interception.h"
#include "sanitizer_allocator_interface.h"
diff --git a/lib/sanitizer_common/scripts/check_lint.sh b/lib/sanitizer_common/scripts/check_lint.sh
index 82e4bc84d..ec07138ca 100755
--- a/lib/sanitizer_common/scripts/check_lint.sh
+++ b/lib/sanitizer_common/scripts/check_lint.sh
@@ -29,6 +29,7 @@ MSAN_RTL_LINT_FILTER=${COMMON_LINT_FILTER}
LSAN_RTL_LINT_FILTER=${COMMON_LINT_FILTER}
LSAN_LIT_TEST_LINT_FILTER=${LSAN_RTL_LINT_FILTER},-whitespace/line_length
DFSAN_RTL_LINT_FILTER=${COMMON_LINT_FILTER},-runtime/int,-runtime/printf,-runtime/references,-readability/function
+SCUDO_RTL_LINT_FILTER=${COMMON_LINT_FILTER}
COMMON_RTL_INC_LINT_FILTER=${COMMON_LINT_FILTER},-runtime/int,-runtime/sizeof,-runtime/printf,-readability/fn_size
SANITIZER_INCLUDES_LINT_FILTER=${COMMON_LINT_FILTER},-runtime/int
@@ -112,6 +113,11 @@ run_lint ${DFSAN_RTL_LINT_FILTER} ${DFSAN_RTL}/*.cc \
${DFSAN_RTL}/*.h &
${DFSAN_RTL}/scripts/check_custom_wrappers.sh >> $ERROR_LOG
+# Scudo
+SCUDO_RTL=${COMPILER_RT}/lib/scudo
+run_lint ${SCUDO_RTL_LINT_FILTER} ${SCUDO_RTL}/*.cpp \
+ ${SCUDO_RTL}/*.h &
+
# Misc files
FILES=${COMMON_RTL}/*.inc
TMPFILES=""
diff --git a/lib/scudo/scudo_allocator_secondary.h b/lib/scudo/scudo_allocator_secondary.h
index dbfb22565..5220b7c57 100644
--- a/lib/scudo/scudo_allocator_secondary.h
+++ b/lib/scudo/scudo_allocator_secondary.h
@@ -23,7 +23,6 @@
class ScudoLargeMmapAllocator {
public:
-
void Init() {
PageSize = GetPageSizeCached();
}
diff --git a/lib/scudo/scudo_crc32.h b/lib/scudo/scudo_crc32.h
index 5ffcc6265..e89e430f4 100644
--- a/lib/scudo/scudo_crc32.h
+++ b/lib/scudo/scudo_crc32.h
@@ -40,7 +40,7 @@ enum : u8 {
CRC32Hardware = 1,
};
-const static u32 CRC32Table[] = {
+static const u32 CRC32Table[] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
diff --git a/lib/scudo/scudo_utils.cpp b/lib/scudo/scudo_utils.cpp
index 093eafe8e..653b6c8fa 100644
--- a/lib/scudo/scudo_utils.cpp
+++ b/lib/scudo/scudo_utils.cpp
@@ -90,8 +90,7 @@ typedef struct {
u32 Edx;
} CPUIDRegs;
-static void getCPUID(CPUIDRegs *Regs, u32 Level)
-{
+static void getCPUID(CPUIDRegs *Regs, u32 Level) {
__get_cpuid(Level, &Regs->Eax, &Regs->Ebx, &Regs->Ecx, &Regs->Edx);
}
@@ -118,8 +117,7 @@ CPUIDRegs getCPUFeatures() {
# define bit_SSE4_2 bit_SSE42 // clang and gcc have different defines.
# endif
-bool testCPUFeature(CPUFeature Feature)
-{
+bool testCPUFeature(CPUFeature Feature) {
CPUIDRegs FeaturesRegs = getCPUFeatures();
switch (Feature) {
diff --git a/lib/scudo/scudo_utils.h b/lib/scudo/scudo_utils.h
index 13269195b..cb7300db9 100644
--- a/lib/scudo/scudo_utils.h
+++ b/lib/scudo/scudo_utils.h
@@ -14,10 +14,10 @@
#ifndef SCUDO_UTILS_H_
#define SCUDO_UTILS_H_
-#include <string.h>
-
#include "sanitizer_common/sanitizer_common.h"
+#include <string.h>
+
namespace __scudo {
template <class Dest, class Source>
@@ -34,7 +34,7 @@ enum CPUFeature {
CRC32CPUFeature = 0,
MaxCPUFeature,
};
-bool testCPUFeature(CPUFeature feature);
+bool testCPUFeature(CPUFeature Feature);
INLINE u64 rotl(const u64 X, int K) {
return (X << K) | (X >> (64 - K));
diff --git a/lib/tsan/CMakeLists.txt b/lib/tsan/CMakeLists.txt
index 08974a467..f7a5d70a3 100644
--- a/lib/tsan/CMakeLists.txt
+++ b/lib/tsan/CMakeLists.txt
@@ -184,13 +184,15 @@ else()
$<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
$<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>
$<TARGET_OBJECTS:RTUbsan.${arch}>
- CFLAGS ${TSAN_RTL_CFLAGS})
+ CFLAGS ${TSAN_RTL_CFLAGS}
+ PARENT_TARGET tsan)
add_compiler_rt_runtime(clang_rt.tsan_cxx
STATIC
ARCHS ${arch}
SOURCES ${TSAN_CXX_SOURCES}
$<TARGET_OBJECTS:RTUbsan_cxx.${arch}>
- CFLAGS ${TSAN_RTL_CFLAGS})
+ CFLAGS ${TSAN_RTL_CFLAGS}
+ PARENT_TARGET tsan)
list(APPEND TSAN_RUNTIME_LIBRARIES clang_rt.tsan-${arch}
clang_rt.tsan_cxx-${arch})
add_sanitizer_rt_symbols(clang_rt.tsan
diff --git a/lib/tsan/rtl/tsan_interceptors.cc b/lib/tsan/rtl/tsan_interceptors.cc
index 79e243aef..976fe2967 100644
--- a/lib/tsan/rtl/tsan_interceptors.cc
+++ b/lib/tsan/rtl/tsan_interceptors.cc
@@ -213,8 +213,6 @@ const int SIG_SETMASK = 2;
#define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED \
(!cur_thread()->is_inited)
-static sigaction_t sigactions[kSigCount];
-
namespace __tsan {
struct SignalDesc {
bool armed;
@@ -233,11 +231,31 @@ struct ThreadSignalContext {
__sanitizer_sigset_t oldset;
};
-// The object is 64-byte aligned, because we want hot data to be located in
-// a single cache line if possible (it's accessed in every interceptor).
-static ALIGNED(64) char libignore_placeholder[sizeof(LibIgnore)];
+// InterceptorContext holds all global data required for interceptors.
+// It's explicitly constructed in InitializeInterceptors with placement new
+// and is never destroyed. This allows usage of members with non-trivial
+// constructors and destructors.
+struct InterceptorContext {
+ // The object is 64-byte aligned, because we want hot data to be located
+ // in a single cache line if possible (it's accessed in every interceptor).
+ ALIGNED(64) LibIgnore libignore;
+ sigaction_t sigactions[kSigCount];
+#if !SANITIZER_MAC && !SANITIZER_NETBSD
+ unsigned finalize_key;
+#endif
+
+ InterceptorContext()
+ : libignore(LINKER_INITIALIZED) {
+ }
+};
+
+static ALIGNED(64) char interceptor_placeholder[sizeof(InterceptorContext)];
+InterceptorContext *interceptor_ctx() {
+ return reinterpret_cast<InterceptorContext*>(&interceptor_placeholder[0]);
+}
+
LibIgnore *libignore() {
- return reinterpret_cast<LibIgnore*>(&libignore_placeholder[0]);
+ return &interceptor_ctx()->libignore;
}
void InitializeLibIgnore() {
@@ -265,10 +283,6 @@ static ThreadSignalContext *SigCtx(ThreadState *thr) {
return ctx;
}
-#if !SANITIZER_MAC
-static unsigned g_thread_finalize_key;
-#endif
-
ScopedInterceptor::ScopedInterceptor(ThreadState *thr, const char *fname,
uptr pc)
: thr_(thr), pc_(pc), in_ignored_lib_(false), ignoring_(false) {
@@ -435,7 +449,7 @@ static int setup_at_exit_wrapper(ThreadState *thr, uptr pc, void(*f)(),
return res;
}
-#if !SANITIZER_MAC
+#if !SANITIZER_MAC && !SANITIZER_NETBSD
static void on_exit_wrapper(int status, void *arg) {
ThreadState *thr = cur_thread();
uptr pc = 0;
@@ -460,6 +474,9 @@ TSAN_INTERCEPTOR(int, on_exit, void(*f)(int, void*), void *arg) {
ThreadIgnoreEnd(thr, pc);
return res;
}
+#define TSAN_MAYBE_INTERCEPT_ON_EXIT TSAN_INTERCEPT(on_exit)
+#else
+#define TSAN_MAYBE_INTERCEPT_ON_EXIT
#endif
// Cleanup old bufs.
@@ -866,11 +883,12 @@ void DestroyThreadState() {
}
} // namespace __tsan
-#if !SANITIZER_MAC
+#if !SANITIZER_MAC && !SANITIZER_NETBSD
static void thread_finalize(void *v) {
uptr iter = (uptr)v;
if (iter > 1) {
- if (pthread_setspecific(g_thread_finalize_key, (void*)(iter - 1))) {
+ if (pthread_setspecific(interceptor_ctx()->finalize_key,
+ (void*)(iter - 1))) {
Printf("ThreadSanitizer: failed to set thread key\n");
Die();
}
@@ -896,9 +914,9 @@ extern "C" void *__tsan_thread_start_func(void *arg) {
ThreadState *thr = cur_thread();
// Thread-local state is not initialized yet.
ScopedIgnoreInterceptors ignore;
-#if !SANITIZER_MAC
+#if !SANITIZER_MAC && !SANITIZER_NETBSD
ThreadIgnoreBegin(thr, 0);
- if (pthread_setspecific(g_thread_finalize_key,
+ if (pthread_setspecific(interceptor_ctx()->finalize_key,
(void *)GetPthreadDestructorIterations())) {
Printf("ThreadSanitizer: failed to set thread key\n");
Die();
@@ -1799,6 +1817,7 @@ namespace __tsan {
static void CallUserSignalHandler(ThreadState *thr, bool sync, bool acquire,
bool sigact, int sig, my_siginfo_t *info, void *uctx) {
+ sigaction_t *sigactions = interceptor_ctx()->sigactions;
if (acquire)
Acquire(thr, 0, (uptr)&sigactions[sig]);
// Signals are generally asynchronous, so if we receive a signals when
@@ -1950,6 +1969,7 @@ TSAN_INTERCEPTOR(int, sigaction, int sig, sigaction_t *act, sigaction_t *old) {
// the signal handler through rtl_sigaction, very bad things will happen.
// The handler will run synchronously and corrupt tsan per-thread state.
SCOPED_INTERCEPTOR_RAW(sigaction, sig, act, old);
+ sigaction_t *sigactions = interceptor_ctx()->sigactions;
if (old)
internal_memcpy(old, &sigactions[sig], sizeof(*old));
if (act == 0)
@@ -2445,6 +2465,17 @@ TSAN_INTERCEPTOR(void *, __tls_get_addr, void *arg) {
}
#endif
+#if SANITIZER_NETBSD
+TSAN_INTERCEPTOR(void, _lwp_exit) {
+ SCOPED_TSAN_INTERCEPTOR(_lwp_exit);
+ DestroyThreadState();
+ REAL(_lwp_exit)();
+}
+#define TSAN_MAYBE_INTERCEPT__LWP_EXIT TSAN_INTERCEPT(_lwp_exit)
+#else
+#define TSAN_MAYBE_INTERCEPT__LWP_EXIT
+#endif
+
namespace __tsan {
static void finalize(void *arg) {
@@ -2476,6 +2507,8 @@ void InitializeInterceptors() {
mallopt(-3, 32*1024); // M_MMAP_THRESHOLD
#endif
+ new(interceptor_ctx()) InterceptorContext();
+
InitializeCommonInterceptors();
#if !SANITIZER_MAC
@@ -2605,7 +2638,7 @@ void InitializeInterceptors() {
#if !SANITIZER_ANDROID
TSAN_INTERCEPT(dl_iterate_phdr);
#endif
- TSAN_INTERCEPT(on_exit);
+ TSAN_MAYBE_INTERCEPT_ON_EXIT;
TSAN_INTERCEPT(__cxa_atexit);
TSAN_INTERCEPT(_exit);
@@ -2613,6 +2646,8 @@ void InitializeInterceptors() {
TSAN_INTERCEPT(__tls_get_addr);
#endif
+ TSAN_MAYBE_INTERCEPT__LWP_EXIT;
+
#if !SANITIZER_MAC && !SANITIZER_ANDROID
// Need to setup it, because interceptors check that the function is resolved.
// But atexit is emitted directly into the module, so can't be resolved.
@@ -2624,8 +2659,8 @@ void InitializeInterceptors() {
Die();
}
-#if !SANITIZER_MAC
- if (pthread_key_create(&g_thread_finalize_key, &thread_finalize)) {
+#if !SANITIZER_MAC && !SANITIZER_NETBSD
+ if (pthread_key_create(&interceptor_ctx()->finalize_key, &thread_finalize)) {
Printf("ThreadSanitizer: failed to create thread key\n");
Die();
}
diff --git a/lib/tsan/rtl/tsan_platform_mac.cc b/lib/tsan/rtl/tsan_platform_mac.cc
index 4570286b1..f8d7324b7 100644
--- a/lib/tsan/rtl/tsan_platform_mac.cc
+++ b/lib/tsan/rtl/tsan_platform_mac.cc
@@ -231,7 +231,7 @@ static void my_pthread_introspection_hook(unsigned int event, pthread_t thread,
void InitializePlatformEarly() {
#if defined(__aarch64__)
- uptr max_vm = GetMaxVirtualAddress() + 1;
+ uptr max_vm = GetMaxUserVirtualAddress() + 1;
if (max_vm != Mapping::kHiAppMemEnd) {
Printf("ThreadSanitizer: unsupported vm address limit %p, expected %p.\n",
max_vm, Mapping::kHiAppMemEnd);
diff --git a/test/asan/TestCases/contiguous_container_crash.cc b/test/asan/TestCases/contiguous_container_crash.cc
index af2102e6a..fe9792888 100644
--- a/test/asan/TestCases/contiguous_container_crash.cc
+++ b/test/asan/TestCases/contiguous_container_crash.cc
@@ -4,6 +4,12 @@
// RUN: not %run %t bad-alignment 2>&1 | FileCheck --check-prefix=CHECK-BAD-ALIGNMENT %s
// RUN: %env_asan_opts=detect_container_overflow=0 %run %t crash
//
+// RUN: %clangxx_asan -flto=thin -O %s -o %t.thinlto
+// RUN: not %run %t.thinlto crash 2>&1 | FileCheck --check-prefix=CHECK-CRASH %s
+// RUN: not %run %t.thinlto bad-bounds 2>&1 | FileCheck --check-prefix=CHECK-BAD-BOUNDS %s
+// RUN: not %run %t.thinlto bad-alignment 2>&1 | FileCheck --check-prefix=CHECK-BAD-ALIGNMENT %s
+// RUN: %env_asan_opts=detect_container_overflow=0 %run %t.thinlto crash
+//
// Test crash due to __sanitizer_annotate_contiguous_container.
#include <assert.h>