diff options
author | Julian Lettner <jlettner@apple.com> | 2019-09-09 18:57:32 +0000 |
---|---|---|
committer | Julian Lettner <jlettner@apple.com> | 2019-09-09 18:57:32 +0000 |
commit | a5142c0c415d0c6565a82a7c109d6f9677971bda (patch) | |
tree | b080bbd5813daaade2a87491903c0b0fadbe91e4 /lib | |
parent | 111bf961e73352018a6500dd4658f5dd000bc7d8 (diff) | |
download | compiler-rt-a5142c0c415d0c6565a82a7c109d6f9677971bda.tar.gz |
[TSan] Add interceptors for mach_vm_[de]allocate
I verified that the test is red without the interceptors.
rdar://40334350
Reviewed By: kubamracek, vitalybuka
Differential Revision: https://reviews.llvm.org/D66616
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@371439 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/tsan/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_interceptors.cpp | 14 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_interceptors_mach_vm.cpp | 52 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_rtl.cpp | 17 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_rtl.h | 3 |
5 files changed, 77 insertions, 10 deletions
diff --git a/lib/tsan/CMakeLists.txt b/lib/tsan/CMakeLists.txt index b5a751dbb..fcadacfe1 100644 --- a/lib/tsan/CMakeLists.txt +++ b/lib/tsan/CMakeLists.txt @@ -63,6 +63,7 @@ set(TSAN_CXX_SOURCES if(APPLE) list(APPEND TSAN_SOURCES rtl/tsan_interceptors_mac.cpp + rtl/tsan_interceptors_mach_vm.cpp rtl/tsan_platform_mac.cpp rtl/tsan_platform_posix.cpp ) diff --git a/lib/tsan/rtl/tsan_interceptors.cpp b/lib/tsan/rtl/tsan_interceptors.cpp index 9e1b9ed77..cf84e2870 100644 --- a/lib/tsan/rtl/tsan_interceptors.cpp +++ b/lib/tsan/rtl/tsan_interceptors.cpp @@ -745,6 +745,8 @@ TSAN_INTERCEPTOR(char*, strdup, const char *str) { return REAL(strdup)(str); } +// Zero out addr if it points into shadow memory and was provided as a hint +// only, i.e., MAP_FIXED is not set. static bool fix_mmap_addr(void **addr, long_t sz, int flags) { if (*addr) { if (!IsAppMem((uptr)*addr) || !IsAppMem((uptr)*addr + sz - 1)) { @@ -767,22 +769,14 @@ static void *mmap_interceptor(ThreadState *thr, uptr pc, Mmap real_mmap, void *res = real_mmap(addr, sz, prot, flags, fd, off); if (res != MAP_FAILED) { if (fd > 0) FdAccess(thr, pc, fd); - if (thr->ignore_reads_and_writes == 0) - MemoryRangeImitateWrite(thr, pc, (uptr)res, sz); - else - MemoryResetRange(thr, pc, (uptr)res, sz); + MemoryRangeImitateWriteOrResetRange(thr, pc, (uptr)res, sz); } return res; } TSAN_INTERCEPTOR(int, munmap, void *addr, long_t sz) { SCOPED_TSAN_INTERCEPTOR(munmap, addr, sz); - if (sz != 0) { - // If sz == 0, munmap will return EINVAL and don't unmap any memory. - DontNeedShadowFor((uptr)addr, sz); - ScopedGlobalProcessor sgp; - ctx->metamap.ResetRange(thr->proc(), (uptr)addr, (uptr)sz); - } + UnmapShadow(thr, (uptr)addr, sz); int res = REAL(munmap)(addr, sz); return res; } diff --git a/lib/tsan/rtl/tsan_interceptors_mach_vm.cpp b/lib/tsan/rtl/tsan_interceptors_mach_vm.cpp new file mode 100644 index 000000000..cd318f8af --- /dev/null +++ b/lib/tsan/rtl/tsan_interceptors_mach_vm.cpp @@ -0,0 +1,52 @@ +//===-- tsan_interceptors_mach_vm.cpp -------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file is a part of ThreadSanitizer (TSan), a race detector. +// +// Interceptors for mach_vm_* user space memory routines on Darwin. +//===----------------------------------------------------------------------===// + +#include "interception/interception.h" +#include "tsan_interceptors.h" +#include "tsan_platform.h" + +#include <mach/mach.h> + +namespace __tsan { + +static bool intersects_with_shadow(mach_vm_address_t *address, + mach_vm_size_t size, int flags) { + // VM_FLAGS_FIXED is 0x0, so we have to test for VM_FLAGS_ANYWHERE. + if (flags & VM_FLAGS_ANYWHERE) return false; + uptr ptr = *address; + return !IsAppMem(ptr) || !IsAppMem(ptr + size - 1); +} + +TSAN_INTERCEPTOR(kern_return_t, mach_vm_allocate, vm_map_t target, + mach_vm_address_t *address, mach_vm_size_t size, int flags) { + SCOPED_TSAN_INTERCEPTOR(mach_vm_allocate, target, address, size, flags); + if (target != mach_task_self()) + return REAL(mach_vm_allocate)(target, address, size, flags); + if (intersects_with_shadow(address, size, flags)) + return KERN_NO_SPACE; + kern_return_t res = REAL(mach_vm_allocate)(target, address, size, flags); + if (res == KERN_SUCCESS) + MemoryRangeImitateWriteOrResetRange(thr, pc, *address, size); + return res; +} + +TSAN_INTERCEPTOR(kern_return_t, mach_vm_deallocate, vm_map_t target, + mach_vm_address_t address, mach_vm_size_t size) { + SCOPED_TSAN_INTERCEPTOR(mach_vm_deallocate, target, address, size); + if (target != mach_task_self()) + return REAL(mach_vm_deallocate)(target, address, size); + UnmapShadow(thr, address, size); + return REAL(mach_vm_deallocate)(target, address, size); +} + +} // namespace __tsan diff --git a/lib/tsan/rtl/tsan_rtl.cpp b/lib/tsan/rtl/tsan_rtl.cpp index 1ac390709..39b9cea52 100644 --- a/lib/tsan/rtl/tsan_rtl.cpp +++ b/lib/tsan/rtl/tsan_rtl.cpp @@ -239,6 +239,15 @@ void DontNeedShadowFor(uptr addr, uptr size) { ReleaseMemoryPagesToOS(MemToShadow(addr), MemToShadow(addr + size)); } +#if !SANITIZER_GO +void UnmapShadow(ThreadState *thr, uptr addr, uptr size) { + if (size == 0) return; + DontNeedShadowFor(addr, size); + ScopedGlobalProcessor sgp; + ctx->metamap.ResetRange(thr->proc(), addr, size); +} +#endif + void MapShadow(uptr addr, uptr size) { // Global data is not 64K aligned, but there are no adjacent mappings, // so we can get away with unaligned mapping. @@ -987,6 +996,14 @@ void MemoryRangeImitateWrite(ThreadState *thr, uptr pc, uptr addr, uptr size) { MemoryRangeSet(thr, pc, addr, size, s.raw()); } +void MemoryRangeImitateWriteOrResetRange(ThreadState *thr, uptr pc, uptr addr, + uptr size) { + if (thr->ignore_reads_and_writes == 0) + MemoryRangeImitateWrite(thr, pc, addr, size); + else + MemoryResetRange(thr, pc, addr, size); +} + ALWAYS_INLINE USED void FuncEntry(ThreadState *thr, uptr pc) { StatInc(thr, StatFuncEnter); diff --git a/lib/tsan/rtl/tsan_rtl.h b/lib/tsan/rtl/tsan_rtl.h index 3a8231bda..53367d9cf 100644 --- a/lib/tsan/rtl/tsan_rtl.h +++ b/lib/tsan/rtl/tsan_rtl.h @@ -680,6 +680,7 @@ void ALWAYS_INLINE StatSet(ThreadState *thr, StatType typ, u64 n) { void MapShadow(uptr addr, uptr size); void MapThreadTrace(uptr addr, uptr size, const char *name); void DontNeedShadowFor(uptr addr, uptr size); +void UnmapShadow(ThreadState *thr, uptr addr, uptr size); void InitializeShadowMemory(); void InitializeInterceptors(); void InitializeLibIgnore(); @@ -759,6 +760,8 @@ void ALWAYS_INLINE MemoryWriteAtomic(ThreadState *thr, uptr pc, void MemoryResetRange(ThreadState *thr, uptr pc, uptr addr, uptr size); void MemoryRangeFreed(ThreadState *thr, uptr pc, uptr addr, uptr size); void MemoryRangeImitateWrite(ThreadState *thr, uptr pc, uptr addr, uptr size); +void MemoryRangeImitateWriteOrResetRange(ThreadState *thr, uptr pc, uptr addr, + uptr size); void ThreadIgnoreBegin(ThreadState *thr, uptr pc, bool save_stack = true); void ThreadIgnoreEnd(ThreadState *thr, uptr pc); |