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