1349cc55cSDimitry Andric//===-- tsan_interface.inc --------------------------------------*- C++ -*-===// 2349cc55cSDimitry Andric// 3349cc55cSDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4349cc55cSDimitry Andric// See https://llvm.org/LICENSE.txt for license information. 5349cc55cSDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6349cc55cSDimitry Andric// 7349cc55cSDimitry Andric//===----------------------------------------------------------------------===// 8349cc55cSDimitry Andric// 9349cc55cSDimitry Andric// This file is a part of ThreadSanitizer (TSan), a race detector. 10349cc55cSDimitry Andric// 11349cc55cSDimitry Andric//===----------------------------------------------------------------------===// 12349cc55cSDimitry Andric 13349cc55cSDimitry Andric#include "sanitizer_common/sanitizer_ptrauth.h" 14349cc55cSDimitry Andric#include "tsan_interface.h" 15349cc55cSDimitry Andric#include "tsan_rtl.h" 16349cc55cSDimitry Andric 17349cc55cSDimitry Andric#define CALLERPC ((uptr)__builtin_return_address(0)) 18349cc55cSDimitry Andric 19349cc55cSDimitry Andricusing namespace __tsan; 20349cc55cSDimitry Andric 21349cc55cSDimitry Andricvoid __tsan_read1(void *addr) { 22349cc55cSDimitry Andric MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 1, kAccessRead); 23349cc55cSDimitry Andric} 24349cc55cSDimitry Andric 25349cc55cSDimitry Andricvoid __tsan_read2(void *addr) { 26349cc55cSDimitry Andric MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 2, kAccessRead); 27349cc55cSDimitry Andric} 28349cc55cSDimitry Andric 29349cc55cSDimitry Andricvoid __tsan_read4(void *addr) { 30349cc55cSDimitry Andric MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 4, kAccessRead); 31349cc55cSDimitry Andric} 32349cc55cSDimitry Andric 33349cc55cSDimitry Andricvoid __tsan_read8(void *addr) { 34349cc55cSDimitry Andric MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 8, kAccessRead); 35349cc55cSDimitry Andric} 36349cc55cSDimitry Andric 37*0eae32dcSDimitry Andricvoid __tsan_read16(void *addr) { 38*0eae32dcSDimitry Andric MemoryAccess16(cur_thread(), CALLERPC, (uptr)addr, kAccessRead); 39*0eae32dcSDimitry Andric} 40*0eae32dcSDimitry Andric 41349cc55cSDimitry Andricvoid __tsan_write1(void *addr) { 42349cc55cSDimitry Andric MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 1, kAccessWrite); 43349cc55cSDimitry Andric} 44349cc55cSDimitry Andric 45349cc55cSDimitry Andricvoid __tsan_write2(void *addr) { 46349cc55cSDimitry Andric MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 2, kAccessWrite); 47349cc55cSDimitry Andric} 48349cc55cSDimitry Andric 49349cc55cSDimitry Andricvoid __tsan_write4(void *addr) { 50349cc55cSDimitry Andric MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 4, kAccessWrite); 51349cc55cSDimitry Andric} 52349cc55cSDimitry Andric 53349cc55cSDimitry Andricvoid __tsan_write8(void *addr) { 54349cc55cSDimitry Andric MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 8, kAccessWrite); 55349cc55cSDimitry Andric} 56349cc55cSDimitry Andric 57*0eae32dcSDimitry Andricvoid __tsan_write16(void *addr) { 58*0eae32dcSDimitry Andric MemoryAccess16(cur_thread(), CALLERPC, (uptr)addr, kAccessWrite); 59*0eae32dcSDimitry Andric} 60*0eae32dcSDimitry Andric 61349cc55cSDimitry Andricvoid __tsan_read1_pc(void *addr, void *pc) { 62349cc55cSDimitry Andric MemoryAccess(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, 1, kAccessRead | kAccessExternalPC); 63349cc55cSDimitry Andric} 64349cc55cSDimitry Andric 65349cc55cSDimitry Andricvoid __tsan_read2_pc(void *addr, void *pc) { 66349cc55cSDimitry Andric MemoryAccess(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, 2, kAccessRead | kAccessExternalPC); 67349cc55cSDimitry Andric} 68349cc55cSDimitry Andric 69349cc55cSDimitry Andricvoid __tsan_read4_pc(void *addr, void *pc) { 70349cc55cSDimitry Andric MemoryAccess(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, 4, kAccessRead | kAccessExternalPC); 71349cc55cSDimitry Andric} 72349cc55cSDimitry Andric 73349cc55cSDimitry Andricvoid __tsan_read8_pc(void *addr, void *pc) { 74349cc55cSDimitry Andric MemoryAccess(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, 8, kAccessRead | kAccessExternalPC); 75349cc55cSDimitry Andric} 76349cc55cSDimitry Andric 77349cc55cSDimitry Andricvoid __tsan_write1_pc(void *addr, void *pc) { 78349cc55cSDimitry Andric MemoryAccess(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, 1, kAccessWrite | kAccessExternalPC); 79349cc55cSDimitry Andric} 80349cc55cSDimitry Andric 81349cc55cSDimitry Andricvoid __tsan_write2_pc(void *addr, void *pc) { 82349cc55cSDimitry Andric MemoryAccess(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, 2, kAccessWrite | kAccessExternalPC); 83349cc55cSDimitry Andric} 84349cc55cSDimitry Andric 85349cc55cSDimitry Andricvoid __tsan_write4_pc(void *addr, void *pc) { 86349cc55cSDimitry Andric MemoryAccess(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, 4, kAccessWrite | kAccessExternalPC); 87349cc55cSDimitry Andric} 88349cc55cSDimitry Andric 89349cc55cSDimitry Andricvoid __tsan_write8_pc(void *addr, void *pc) { 90349cc55cSDimitry Andric MemoryAccess(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, 8, kAccessWrite | kAccessExternalPC); 91349cc55cSDimitry Andric} 92349cc55cSDimitry Andric 93349cc55cSDimitry AndricALWAYS_INLINE USED void __tsan_unaligned_read2(const void *addr) { 94349cc55cSDimitry Andric UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 2, kAccessRead); 95349cc55cSDimitry Andric} 96349cc55cSDimitry Andric 97349cc55cSDimitry AndricALWAYS_INLINE USED void __tsan_unaligned_read4(const void *addr) { 98349cc55cSDimitry Andric UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 4, kAccessRead); 99349cc55cSDimitry Andric} 100349cc55cSDimitry Andric 101349cc55cSDimitry AndricALWAYS_INLINE USED void __tsan_unaligned_read8(const void *addr) { 102349cc55cSDimitry Andric UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 8, kAccessRead); 103349cc55cSDimitry Andric} 104349cc55cSDimitry Andric 105349cc55cSDimitry AndricALWAYS_INLINE USED void __tsan_unaligned_write2(void *addr) { 106349cc55cSDimitry Andric UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 2, kAccessWrite); 107349cc55cSDimitry Andric} 108349cc55cSDimitry Andric 109349cc55cSDimitry AndricALWAYS_INLINE USED void __tsan_unaligned_write4(void *addr) { 110349cc55cSDimitry Andric UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 4, kAccessWrite); 111349cc55cSDimitry Andric} 112349cc55cSDimitry Andric 113349cc55cSDimitry AndricALWAYS_INLINE USED void __tsan_unaligned_write8(void *addr) { 114349cc55cSDimitry Andric UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 8, kAccessWrite); 115349cc55cSDimitry Andric} 116349cc55cSDimitry Andric 117349cc55cSDimitry Andricextern "C" { 118349cc55cSDimitry Andric// __sanitizer_unaligned_load/store are for user instrumentation. 119349cc55cSDimitry AndricSANITIZER_INTERFACE_ATTRIBUTE 120349cc55cSDimitry Andricu16 __sanitizer_unaligned_load16(const uu16 *addr) { 121349cc55cSDimitry Andric __tsan_unaligned_read2(addr); 122349cc55cSDimitry Andric return *addr; 123349cc55cSDimitry Andric} 124349cc55cSDimitry Andric 125349cc55cSDimitry AndricSANITIZER_INTERFACE_ATTRIBUTE 126349cc55cSDimitry Andricu32 __sanitizer_unaligned_load32(const uu32 *addr) { 127349cc55cSDimitry Andric __tsan_unaligned_read4(addr); 128349cc55cSDimitry Andric return *addr; 129349cc55cSDimitry Andric} 130349cc55cSDimitry Andric 131349cc55cSDimitry AndricSANITIZER_INTERFACE_ATTRIBUTE 132349cc55cSDimitry Andricu64 __sanitizer_unaligned_load64(const uu64 *addr) { 133349cc55cSDimitry Andric __tsan_unaligned_read8(addr); 134349cc55cSDimitry Andric return *addr; 135349cc55cSDimitry Andric} 136349cc55cSDimitry Andric 137349cc55cSDimitry AndricSANITIZER_INTERFACE_ATTRIBUTE 138349cc55cSDimitry Andricvoid __sanitizer_unaligned_store16(uu16 *addr, u16 v) { 139349cc55cSDimitry Andric *addr = v; 140349cc55cSDimitry Andric __tsan_unaligned_write2(addr); 141349cc55cSDimitry Andric} 142349cc55cSDimitry Andric 143349cc55cSDimitry AndricSANITIZER_INTERFACE_ATTRIBUTE 144349cc55cSDimitry Andricvoid __sanitizer_unaligned_store32(uu32 *addr, u32 v) { 145349cc55cSDimitry Andric *addr = v; 146349cc55cSDimitry Andric __tsan_unaligned_write4(addr); 147349cc55cSDimitry Andric} 148349cc55cSDimitry Andric 149349cc55cSDimitry AndricSANITIZER_INTERFACE_ATTRIBUTE 150349cc55cSDimitry Andricvoid __sanitizer_unaligned_store64(uu64 *addr, u64 v) { 151349cc55cSDimitry Andric *addr = v; 152349cc55cSDimitry Andric __tsan_unaligned_write8(addr); 153349cc55cSDimitry Andric} 154349cc55cSDimitry Andric} 155349cc55cSDimitry Andric 156349cc55cSDimitry Andricvoid __tsan_vptr_update(void **vptr_p, void *new_val) { 157349cc55cSDimitry Andric if (*vptr_p == new_val) 158349cc55cSDimitry Andric return; 159349cc55cSDimitry Andric MemoryAccess(cur_thread(), CALLERPC, (uptr)vptr_p, sizeof(*vptr_p), 160349cc55cSDimitry Andric kAccessWrite | kAccessVptr); 161349cc55cSDimitry Andric} 162349cc55cSDimitry Andric 163349cc55cSDimitry Andricvoid __tsan_vptr_read(void **vptr_p) { 164349cc55cSDimitry Andric MemoryAccess(cur_thread(), CALLERPC, (uptr)vptr_p, sizeof(*vptr_p), 165349cc55cSDimitry Andric kAccessRead | kAccessVptr); 166349cc55cSDimitry Andric} 167349cc55cSDimitry Andric 168349cc55cSDimitry Andricvoid __tsan_func_entry(void *pc) { FuncEntry(cur_thread(), STRIP_PAC_PC(pc)); } 169349cc55cSDimitry Andric 170349cc55cSDimitry Andricvoid __tsan_func_exit() { FuncExit(cur_thread()); } 171349cc55cSDimitry Andric 172349cc55cSDimitry Andricvoid __tsan_ignore_thread_begin() { ThreadIgnoreBegin(cur_thread(), CALLERPC); } 173349cc55cSDimitry Andric 174349cc55cSDimitry Andricvoid __tsan_ignore_thread_end() { ThreadIgnoreEnd(cur_thread()); } 175349cc55cSDimitry Andric 176349cc55cSDimitry Andricvoid __tsan_read_range(void *addr, uptr size) { 177349cc55cSDimitry Andric MemoryAccessRange(cur_thread(), CALLERPC, (uptr)addr, size, false); 178349cc55cSDimitry Andric} 179349cc55cSDimitry Andric 180349cc55cSDimitry Andricvoid __tsan_write_range(void *addr, uptr size) { 181349cc55cSDimitry Andric MemoryAccessRange(cur_thread(), CALLERPC, (uptr)addr, size, true); 182349cc55cSDimitry Andric} 183349cc55cSDimitry Andric 184349cc55cSDimitry Andricvoid __tsan_read_range_pc(void *addr, uptr size, void *pc) { 185349cc55cSDimitry Andric MemoryAccessRange(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, size, false); 186349cc55cSDimitry Andric} 187349cc55cSDimitry Andric 188349cc55cSDimitry Andricvoid __tsan_write_range_pc(void *addr, uptr size, void *pc) { 189349cc55cSDimitry Andric MemoryAccessRange(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, size, true); 190349cc55cSDimitry Andric} 191