168d75effSDimitry Andric //===-- tsan_interface.cpp ------------------------------------------------===// 268d75effSDimitry Andric // 368d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 468d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 568d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 668d75effSDimitry Andric // 768d75effSDimitry Andric //===----------------------------------------------------------------------===// 868d75effSDimitry Andric // 968d75effSDimitry Andric // This file is a part of ThreadSanitizer (TSan), a race detector. 1068d75effSDimitry Andric // 1168d75effSDimitry Andric //===----------------------------------------------------------------------===// 1268d75effSDimitry Andric 1368d75effSDimitry Andric #include "tsan_interface.h" 1468d75effSDimitry Andric #include "tsan_interface_ann.h" 1568d75effSDimitry Andric #include "tsan_rtl.h" 1668d75effSDimitry Andric #include "sanitizer_common/sanitizer_internal_defs.h" 17e8d8bef9SDimitry Andric #include "sanitizer_common/sanitizer_ptrauth.h" 1868d75effSDimitry Andric 1968d75effSDimitry Andric #define CALLERPC ((uptr)__builtin_return_address(0)) 2068d75effSDimitry Andric 2168d75effSDimitry Andric using namespace __tsan; 2268d75effSDimitry Andric 23*349cc55cSDimitry Andric void __tsan_init() { Initialize(cur_thread_init()); } 2468d75effSDimitry Andric 2568d75effSDimitry Andric void __tsan_flush_memory() { 2668d75effSDimitry Andric FlushShadowMemory(); 2768d75effSDimitry Andric } 2868d75effSDimitry Andric 2968d75effSDimitry Andric void __tsan_read16(void *addr) { 30*349cc55cSDimitry Andric uptr pc = CALLERPC; 31*349cc55cSDimitry Andric ThreadState *thr = cur_thread(); 32*349cc55cSDimitry Andric MemoryAccess(thr, pc, (uptr)addr, 8, kAccessRead); 33*349cc55cSDimitry Andric MemoryAccess(thr, pc, (uptr)addr + 8, 8, kAccessRead); 3468d75effSDimitry Andric } 3568d75effSDimitry Andric 3668d75effSDimitry Andric void __tsan_write16(void *addr) { 37*349cc55cSDimitry Andric uptr pc = CALLERPC; 38*349cc55cSDimitry Andric ThreadState *thr = cur_thread(); 39*349cc55cSDimitry Andric MemoryAccess(thr, pc, (uptr)addr, 8, kAccessWrite); 40*349cc55cSDimitry Andric MemoryAccess(thr, pc, (uptr)addr + 8, 8, kAccessWrite); 4168d75effSDimitry Andric } 4268d75effSDimitry Andric 4368d75effSDimitry Andric void __tsan_read16_pc(void *addr, void *pc) { 44*349cc55cSDimitry Andric uptr pc_no_pac = STRIP_PAC_PC(pc); 45*349cc55cSDimitry Andric ThreadState *thr = cur_thread(); 46*349cc55cSDimitry Andric MemoryAccess(thr, pc_no_pac, (uptr)addr, 8, kAccessRead); 47*349cc55cSDimitry Andric MemoryAccess(thr, pc_no_pac, (uptr)addr + 8, 8, kAccessRead); 4868d75effSDimitry Andric } 4968d75effSDimitry Andric 5068d75effSDimitry Andric void __tsan_write16_pc(void *addr, void *pc) { 51*349cc55cSDimitry Andric uptr pc_no_pac = STRIP_PAC_PC(pc); 52*349cc55cSDimitry Andric ThreadState *thr = cur_thread(); 53*349cc55cSDimitry Andric MemoryAccess(thr, pc_no_pac, (uptr)addr, 8, kAccessWrite); 54*349cc55cSDimitry Andric MemoryAccess(thr, pc_no_pac, (uptr)addr + 8, 8, kAccessWrite); 5568d75effSDimitry Andric } 5668d75effSDimitry Andric 5768d75effSDimitry Andric // __tsan_unaligned_read/write calls are emitted by compiler. 5868d75effSDimitry Andric 5968d75effSDimitry Andric void __tsan_unaligned_read16(const void *addr) { 60*349cc55cSDimitry Andric uptr pc = CALLERPC; 61*349cc55cSDimitry Andric ThreadState *thr = cur_thread(); 62*349cc55cSDimitry Andric UnalignedMemoryAccess(thr, pc, (uptr)addr, 8, kAccessRead); 63*349cc55cSDimitry Andric UnalignedMemoryAccess(thr, pc, (uptr)addr + 8, 8, kAccessRead); 6468d75effSDimitry Andric } 6568d75effSDimitry Andric 6668d75effSDimitry Andric void __tsan_unaligned_write16(void *addr) { 67*349cc55cSDimitry Andric uptr pc = CALLERPC; 68*349cc55cSDimitry Andric ThreadState *thr = cur_thread(); 69*349cc55cSDimitry Andric UnalignedMemoryAccess(thr, pc, (uptr)addr, 8, kAccessWrite); 70*349cc55cSDimitry Andric UnalignedMemoryAccess(thr, pc, (uptr)addr + 8, 8, kAccessWrite); 7168d75effSDimitry Andric } 7268d75effSDimitry Andric 7368d75effSDimitry Andric extern "C" { 7468d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 7568d75effSDimitry Andric void *__tsan_get_current_fiber() { 7668d75effSDimitry Andric return cur_thread(); 7768d75effSDimitry Andric } 7868d75effSDimitry Andric 7968d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 8068d75effSDimitry Andric void *__tsan_create_fiber(unsigned flags) { 8168d75effSDimitry Andric return FiberCreate(cur_thread(), CALLERPC, flags); 8268d75effSDimitry Andric } 8368d75effSDimitry Andric 8468d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 8568d75effSDimitry Andric void __tsan_destroy_fiber(void *fiber) { 8668d75effSDimitry Andric FiberDestroy(cur_thread(), CALLERPC, static_cast<ThreadState *>(fiber)); 8768d75effSDimitry Andric } 8868d75effSDimitry Andric 8968d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 9068d75effSDimitry Andric void __tsan_switch_to_fiber(void *fiber, unsigned flags) { 9168d75effSDimitry Andric FiberSwitch(cur_thread(), CALLERPC, static_cast<ThreadState *>(fiber), flags); 9268d75effSDimitry Andric } 9368d75effSDimitry Andric 9468d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 9568d75effSDimitry Andric void __tsan_set_fiber_name(void *fiber, const char *name) { 9668d75effSDimitry Andric ThreadSetName(static_cast<ThreadState *>(fiber), name); 9768d75effSDimitry Andric } 9868d75effSDimitry Andric } // extern "C" 9968d75effSDimitry Andric 10068d75effSDimitry Andric void __tsan_acquire(void *addr) { 10168d75effSDimitry Andric Acquire(cur_thread(), CALLERPC, (uptr)addr); 10268d75effSDimitry Andric } 10368d75effSDimitry Andric 10468d75effSDimitry Andric void __tsan_release(void *addr) { 10568d75effSDimitry Andric Release(cur_thread(), CALLERPC, (uptr)addr); 10668d75effSDimitry Andric } 107