1 //===-- tsan_interceptors_mach_vm.cpp -------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file is a part of ThreadSanitizer (TSan), a race detector.
11 // Interceptors for mach_vm_* user space memory routines on Darwin.
12 //===----------------------------------------------------------------------===//
14 #include "interception/interception.h"
15 #include "tsan_interceptors.h"
16 #include "tsan_platform.h"
18 #include <mach/mach.h>
22 static bool intersects_with_shadow(mach_vm_address_t
*address
,
23 mach_vm_size_t size
, int flags
) {
24 // VM_FLAGS_FIXED is 0x0, so we have to test for VM_FLAGS_ANYWHERE.
25 if (flags
& VM_FLAGS_ANYWHERE
) return false;
27 return !IsAppMem(ptr
) || !IsAppMem(ptr
+ size
- 1);
30 TSAN_INTERCEPTOR(kern_return_t
, mach_vm_allocate
, vm_map_t target
,
31 mach_vm_address_t
*address
, mach_vm_size_t size
, int flags
) {
32 SCOPED_TSAN_INTERCEPTOR(mach_vm_allocate
, target
, address
, size
, flags
);
33 if (target
!= mach_task_self())
34 return REAL(mach_vm_allocate
)(target
, address
, size
, flags
);
35 if (intersects_with_shadow(address
, size
, flags
))
37 kern_return_t res
= REAL(mach_vm_allocate
)(target
, address
, size
, flags
);
38 if (res
== KERN_SUCCESS
)
39 MemoryRangeImitateWriteOrResetRange(thr
, pc
, *address
, size
);
43 TSAN_INTERCEPTOR(kern_return_t
, mach_vm_deallocate
, vm_map_t target
,
44 mach_vm_address_t address
, mach_vm_size_t size
) {
45 SCOPED_TSAN_INTERCEPTOR(mach_vm_deallocate
, target
, address
, size
);
46 if (target
!= mach_task_self())
47 return REAL(mach_vm_deallocate
)(target
, address
, size
);
48 UnmapShadow(thr
, address
, size
);
49 return REAL(mach_vm_deallocate
)(target
, address
, size
);