1*3cab2bb3Spatrick //===-- tsan_interface.cpp ------------------------------------------------===// 2*3cab2bb3Spatrick // 3*3cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*3cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information. 5*3cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*3cab2bb3Spatrick // 7*3cab2bb3Spatrick //===----------------------------------------------------------------------===// 8*3cab2bb3Spatrick // 9*3cab2bb3Spatrick // This file is a part of ThreadSanitizer (TSan), a race detector. 10*3cab2bb3Spatrick // 11*3cab2bb3Spatrick //===----------------------------------------------------------------------===// 12*3cab2bb3Spatrick 13*3cab2bb3Spatrick #include "tsan_interface.h" 14*3cab2bb3Spatrick #include "tsan_interface_ann.h" 15*3cab2bb3Spatrick #include "tsan_rtl.h" 16*3cab2bb3Spatrick #include "sanitizer_common/sanitizer_internal_defs.h" 17*3cab2bb3Spatrick 18*3cab2bb3Spatrick #define CALLERPC ((uptr)__builtin_return_address(0)) 19*3cab2bb3Spatrick 20*3cab2bb3Spatrick using namespace __tsan; 21*3cab2bb3Spatrick 22*3cab2bb3Spatrick typedef u16 uint16_t; 23*3cab2bb3Spatrick typedef u32 uint32_t; 24*3cab2bb3Spatrick typedef u64 uint64_t; 25*3cab2bb3Spatrick 26*3cab2bb3Spatrick void __tsan_init() { 27*3cab2bb3Spatrick cur_thread_init(); 28*3cab2bb3Spatrick Initialize(cur_thread()); 29*3cab2bb3Spatrick } 30*3cab2bb3Spatrick 31*3cab2bb3Spatrick void __tsan_flush_memory() { 32*3cab2bb3Spatrick FlushShadowMemory(); 33*3cab2bb3Spatrick } 34*3cab2bb3Spatrick 35*3cab2bb3Spatrick void __tsan_read16(void *addr) { 36*3cab2bb3Spatrick MemoryRead(cur_thread(), CALLERPC, (uptr)addr, kSizeLog8); 37*3cab2bb3Spatrick MemoryRead(cur_thread(), CALLERPC, (uptr)addr + 8, kSizeLog8); 38*3cab2bb3Spatrick } 39*3cab2bb3Spatrick 40*3cab2bb3Spatrick void __tsan_write16(void *addr) { 41*3cab2bb3Spatrick MemoryWrite(cur_thread(), CALLERPC, (uptr)addr, kSizeLog8); 42*3cab2bb3Spatrick MemoryWrite(cur_thread(), CALLERPC, (uptr)addr + 8, kSizeLog8); 43*3cab2bb3Spatrick } 44*3cab2bb3Spatrick 45*3cab2bb3Spatrick void __tsan_read16_pc(void *addr, void *pc) { 46*3cab2bb3Spatrick MemoryRead(cur_thread(), (uptr)pc, (uptr)addr, kSizeLog8); 47*3cab2bb3Spatrick MemoryRead(cur_thread(), (uptr)pc, (uptr)addr + 8, kSizeLog8); 48*3cab2bb3Spatrick } 49*3cab2bb3Spatrick 50*3cab2bb3Spatrick void __tsan_write16_pc(void *addr, void *pc) { 51*3cab2bb3Spatrick MemoryWrite(cur_thread(), (uptr)pc, (uptr)addr, kSizeLog8); 52*3cab2bb3Spatrick MemoryWrite(cur_thread(), (uptr)pc, (uptr)addr + 8, kSizeLog8); 53*3cab2bb3Spatrick } 54*3cab2bb3Spatrick 55*3cab2bb3Spatrick // __tsan_unaligned_read/write calls are emitted by compiler. 56*3cab2bb3Spatrick 57*3cab2bb3Spatrick void __tsan_unaligned_read2(const void *addr) { 58*3cab2bb3Spatrick UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 2, false, false); 59*3cab2bb3Spatrick } 60*3cab2bb3Spatrick 61*3cab2bb3Spatrick void __tsan_unaligned_read4(const void *addr) { 62*3cab2bb3Spatrick UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 4, false, false); 63*3cab2bb3Spatrick } 64*3cab2bb3Spatrick 65*3cab2bb3Spatrick void __tsan_unaligned_read8(const void *addr) { 66*3cab2bb3Spatrick UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 8, false, false); 67*3cab2bb3Spatrick } 68*3cab2bb3Spatrick 69*3cab2bb3Spatrick void __tsan_unaligned_read16(const void *addr) { 70*3cab2bb3Spatrick UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 16, false, false); 71*3cab2bb3Spatrick } 72*3cab2bb3Spatrick 73*3cab2bb3Spatrick void __tsan_unaligned_write2(void *addr) { 74*3cab2bb3Spatrick UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 2, true, false); 75*3cab2bb3Spatrick } 76*3cab2bb3Spatrick 77*3cab2bb3Spatrick void __tsan_unaligned_write4(void *addr) { 78*3cab2bb3Spatrick UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 4, true, false); 79*3cab2bb3Spatrick } 80*3cab2bb3Spatrick 81*3cab2bb3Spatrick void __tsan_unaligned_write8(void *addr) { 82*3cab2bb3Spatrick UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 8, true, false); 83*3cab2bb3Spatrick } 84*3cab2bb3Spatrick 85*3cab2bb3Spatrick void __tsan_unaligned_write16(void *addr) { 86*3cab2bb3Spatrick UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 16, true, false); 87*3cab2bb3Spatrick } 88*3cab2bb3Spatrick 89*3cab2bb3Spatrick // __sanitizer_unaligned_load/store are for user instrumentation. 90*3cab2bb3Spatrick 91*3cab2bb3Spatrick extern "C" { 92*3cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE 93*3cab2bb3Spatrick u16 __sanitizer_unaligned_load16(const uu16 *addr) { 94*3cab2bb3Spatrick __tsan_unaligned_read2(addr); 95*3cab2bb3Spatrick return *addr; 96*3cab2bb3Spatrick } 97*3cab2bb3Spatrick 98*3cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE 99*3cab2bb3Spatrick u32 __sanitizer_unaligned_load32(const uu32 *addr) { 100*3cab2bb3Spatrick __tsan_unaligned_read4(addr); 101*3cab2bb3Spatrick return *addr; 102*3cab2bb3Spatrick } 103*3cab2bb3Spatrick 104*3cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE 105*3cab2bb3Spatrick u64 __sanitizer_unaligned_load64(const uu64 *addr) { 106*3cab2bb3Spatrick __tsan_unaligned_read8(addr); 107*3cab2bb3Spatrick return *addr; 108*3cab2bb3Spatrick } 109*3cab2bb3Spatrick 110*3cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE 111*3cab2bb3Spatrick void __sanitizer_unaligned_store16(uu16 *addr, u16 v) { 112*3cab2bb3Spatrick __tsan_unaligned_write2(addr); 113*3cab2bb3Spatrick *addr = v; 114*3cab2bb3Spatrick } 115*3cab2bb3Spatrick 116*3cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE 117*3cab2bb3Spatrick void __sanitizer_unaligned_store32(uu32 *addr, u32 v) { 118*3cab2bb3Spatrick __tsan_unaligned_write4(addr); 119*3cab2bb3Spatrick *addr = v; 120*3cab2bb3Spatrick } 121*3cab2bb3Spatrick 122*3cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE 123*3cab2bb3Spatrick void __sanitizer_unaligned_store64(uu64 *addr, u64 v) { 124*3cab2bb3Spatrick __tsan_unaligned_write8(addr); 125*3cab2bb3Spatrick *addr = v; 126*3cab2bb3Spatrick } 127*3cab2bb3Spatrick 128*3cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE 129*3cab2bb3Spatrick void *__tsan_get_current_fiber() { 130*3cab2bb3Spatrick return cur_thread(); 131*3cab2bb3Spatrick } 132*3cab2bb3Spatrick 133*3cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE 134*3cab2bb3Spatrick void *__tsan_create_fiber(unsigned flags) { 135*3cab2bb3Spatrick return FiberCreate(cur_thread(), CALLERPC, flags); 136*3cab2bb3Spatrick } 137*3cab2bb3Spatrick 138*3cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE 139*3cab2bb3Spatrick void __tsan_destroy_fiber(void *fiber) { 140*3cab2bb3Spatrick FiberDestroy(cur_thread(), CALLERPC, static_cast<ThreadState *>(fiber)); 141*3cab2bb3Spatrick } 142*3cab2bb3Spatrick 143*3cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE 144*3cab2bb3Spatrick void __tsan_switch_to_fiber(void *fiber, unsigned flags) { 145*3cab2bb3Spatrick FiberSwitch(cur_thread(), CALLERPC, static_cast<ThreadState *>(fiber), flags); 146*3cab2bb3Spatrick } 147*3cab2bb3Spatrick 148*3cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE 149*3cab2bb3Spatrick void __tsan_set_fiber_name(void *fiber, const char *name) { 150*3cab2bb3Spatrick ThreadSetName(static_cast<ThreadState *>(fiber), name); 151*3cab2bb3Spatrick } 152*3cab2bb3Spatrick } // extern "C" 153*3cab2bb3Spatrick 154*3cab2bb3Spatrick void __tsan_acquire(void *addr) { 155*3cab2bb3Spatrick Acquire(cur_thread(), CALLERPC, (uptr)addr); 156*3cab2bb3Spatrick } 157*3cab2bb3Spatrick 158*3cab2bb3Spatrick void __tsan_release(void *addr) { 159*3cab2bb3Spatrick Release(cur_thread(), CALLERPC, (uptr)addr); 160*3cab2bb3Spatrick } 161