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