1 | //===-- tsan_interface.inc --------------------------------------*- C++ -*-===// |
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 "sanitizer_common/sanitizer_ptrauth.h" |
14 | #include "tsan_interface.h" |
15 | #include "tsan_rtl.h" |
16 | |
17 | #define CALLERPC ((uptr)__builtin_return_address(0)) |
18 | |
19 | using namespace __tsan; |
20 | |
21 | void __tsan_read1(void *addr) { |
22 | MemoryAccess(thr: cur_thread(), CALLERPC, addr: (uptr)addr, size: 1, typ: kAccessRead); |
23 | } |
24 | |
25 | void __tsan_read2(void *addr) { |
26 | MemoryAccess(thr: cur_thread(), CALLERPC, addr: (uptr)addr, size: 2, typ: kAccessRead); |
27 | } |
28 | |
29 | void __tsan_read4(void *addr) { |
30 | MemoryAccess(thr: cur_thread(), CALLERPC, addr: (uptr)addr, size: 4, typ: kAccessRead); |
31 | } |
32 | |
33 | void __tsan_read8(void *addr) { |
34 | MemoryAccess(thr: cur_thread(), CALLERPC, addr: (uptr)addr, size: 8, typ: kAccessRead); |
35 | } |
36 | |
37 | void __tsan_read16(void *addr) { |
38 | MemoryAccess16(thr: cur_thread(), CALLERPC, addr: (uptr)addr, typ: kAccessRead); |
39 | } |
40 | |
41 | void __tsan_write1(void *addr) { |
42 | MemoryAccess(thr: cur_thread(), CALLERPC, addr: (uptr)addr, size: 1, typ: kAccessWrite); |
43 | } |
44 | |
45 | void __tsan_write2(void *addr) { |
46 | MemoryAccess(thr: cur_thread(), CALLERPC, addr: (uptr)addr, size: 2, typ: kAccessWrite); |
47 | } |
48 | |
49 | void __tsan_write4(void *addr) { |
50 | MemoryAccess(thr: cur_thread(), CALLERPC, addr: (uptr)addr, size: 4, typ: kAccessWrite); |
51 | } |
52 | |
53 | void __tsan_write8(void *addr) { |
54 | MemoryAccess(thr: cur_thread(), CALLERPC, addr: (uptr)addr, size: 8, typ: kAccessWrite); |
55 | } |
56 | |
57 | void __tsan_write16(void *addr) { |
58 | MemoryAccess16(thr: cur_thread(), CALLERPC, addr: (uptr)addr, typ: kAccessWrite); |
59 | } |
60 | |
61 | void __tsan_read1_pc(void *addr, void *pc) { |
62 | MemoryAccess(thr: cur_thread(), STRIP_PAC_PC(pc), addr: (uptr)addr, size: 1, typ: kAccessRead | kAccessExternalPC); |
63 | } |
64 | |
65 | void __tsan_read2_pc(void *addr, void *pc) { |
66 | MemoryAccess(thr: cur_thread(), STRIP_PAC_PC(pc), addr: (uptr)addr, size: 2, typ: kAccessRead | kAccessExternalPC); |
67 | } |
68 | |
69 | void __tsan_read4_pc(void *addr, void *pc) { |
70 | MemoryAccess(thr: cur_thread(), STRIP_PAC_PC(pc), addr: (uptr)addr, size: 4, typ: kAccessRead | kAccessExternalPC); |
71 | } |
72 | |
73 | void __tsan_read8_pc(void *addr, void *pc) { |
74 | MemoryAccess(thr: cur_thread(), STRIP_PAC_PC(pc), addr: (uptr)addr, size: 8, typ: kAccessRead | kAccessExternalPC); |
75 | } |
76 | |
77 | void __tsan_write1_pc(void *addr, void *pc) { |
78 | MemoryAccess(thr: cur_thread(), STRIP_PAC_PC(pc), addr: (uptr)addr, size: 1, typ: kAccessWrite | kAccessExternalPC); |
79 | } |
80 | |
81 | void __tsan_write2_pc(void *addr, void *pc) { |
82 | MemoryAccess(thr: cur_thread(), STRIP_PAC_PC(pc), addr: (uptr)addr, size: 2, typ: kAccessWrite | kAccessExternalPC); |
83 | } |
84 | |
85 | void __tsan_write4_pc(void *addr, void *pc) { |
86 | MemoryAccess(thr: cur_thread(), STRIP_PAC_PC(pc), addr: (uptr)addr, size: 4, typ: kAccessWrite | kAccessExternalPC); |
87 | } |
88 | |
89 | void __tsan_write8_pc(void *addr, void *pc) { |
90 | MemoryAccess(thr: cur_thread(), STRIP_PAC_PC(pc), addr: (uptr)addr, size: 8, typ: kAccessWrite | kAccessExternalPC); |
91 | } |
92 | |
93 | ALWAYS_INLINE USED void __tsan_unaligned_read2(const void *addr) { |
94 | UnalignedMemoryAccess(thr: cur_thread(), CALLERPC, addr: (uptr)addr, size: 2, typ: kAccessRead); |
95 | } |
96 | |
97 | ALWAYS_INLINE USED void __tsan_unaligned_read4(const void *addr) { |
98 | UnalignedMemoryAccess(thr: cur_thread(), CALLERPC, addr: (uptr)addr, size: 4, typ: kAccessRead); |
99 | } |
100 | |
101 | ALWAYS_INLINE USED void __tsan_unaligned_read8(const void *addr) { |
102 | UnalignedMemoryAccess(thr: cur_thread(), CALLERPC, addr: (uptr)addr, size: 8, typ: kAccessRead); |
103 | } |
104 | |
105 | ALWAYS_INLINE USED void __tsan_unaligned_write2(void *addr) { |
106 | UnalignedMemoryAccess(thr: cur_thread(), CALLERPC, addr: (uptr)addr, size: 2, typ: kAccessWrite); |
107 | } |
108 | |
109 | ALWAYS_INLINE USED void __tsan_unaligned_write4(void *addr) { |
110 | UnalignedMemoryAccess(thr: cur_thread(), CALLERPC, addr: (uptr)addr, size: 4, typ: kAccessWrite); |
111 | } |
112 | |
113 | ALWAYS_INLINE USED void __tsan_unaligned_write8(void *addr) { |
114 | UnalignedMemoryAccess(thr: cur_thread(), CALLERPC, addr: (uptr)addr, size: 8, typ: kAccessWrite); |
115 | } |
116 | |
117 | extern "C" { |
118 | // __sanitizer_unaligned_load/store are for user instrumentation. |
119 | SANITIZER_INTERFACE_ATTRIBUTE |
120 | u16 __sanitizer_unaligned_load16(const uu16 *addr) { |
121 | __tsan_unaligned_read2(addr); |
122 | return *addr; |
123 | } |
124 | |
125 | SANITIZER_INTERFACE_ATTRIBUTE |
126 | u32 __sanitizer_unaligned_load32(const uu32 *addr) { |
127 | __tsan_unaligned_read4(addr); |
128 | return *addr; |
129 | } |
130 | |
131 | SANITIZER_INTERFACE_ATTRIBUTE |
132 | u64 __sanitizer_unaligned_load64(const uu64 *addr) { |
133 | __tsan_unaligned_read8(addr); |
134 | return *addr; |
135 | } |
136 | |
137 | SANITIZER_INTERFACE_ATTRIBUTE |
138 | void __sanitizer_unaligned_store16(uu16 *addr, u16 v) { |
139 | *addr = v; |
140 | __tsan_unaligned_write2(addr); |
141 | } |
142 | |
143 | SANITIZER_INTERFACE_ATTRIBUTE |
144 | void __sanitizer_unaligned_store32(uu32 *addr, u32 v) { |
145 | *addr = v; |
146 | __tsan_unaligned_write4(addr); |
147 | } |
148 | |
149 | SANITIZER_INTERFACE_ATTRIBUTE |
150 | void __sanitizer_unaligned_store64(uu64 *addr, u64 v) { |
151 | *addr = v; |
152 | __tsan_unaligned_write8(addr); |
153 | } |
154 | } |
155 | |
156 | void __tsan_vptr_update(void **vptr_p, void *new_val) { |
157 | if (*vptr_p == new_val) |
158 | return; |
159 | MemoryAccess(thr: cur_thread(), CALLERPC, addr: (uptr)vptr_p, size: sizeof(*vptr_p), |
160 | typ: kAccessWrite | kAccessVptr); |
161 | } |
162 | |
163 | void __tsan_vptr_read(void **vptr_p) { |
164 | MemoryAccess(thr: cur_thread(), CALLERPC, addr: (uptr)vptr_p, size: sizeof(*vptr_p), |
165 | typ: kAccessRead | kAccessVptr); |
166 | } |
167 | |
168 | void __tsan_func_entry(void *pc) { FuncEntry(thr: cur_thread(), STRIP_PAC_PC(pc)); } |
169 | |
170 | void __tsan_func_exit() { FuncExit(thr: cur_thread()); } |
171 | |
172 | void __tsan_ignore_thread_begin() { ThreadIgnoreBegin(thr: cur_thread(), CALLERPC); } |
173 | |
174 | void __tsan_ignore_thread_end() { ThreadIgnoreEnd(thr: cur_thread()); } |
175 | |
176 | void __tsan_read_range(void *addr, uptr size) { |
177 | MemoryAccessRange(thr: cur_thread(), CALLERPC, addr: (uptr)addr, size, is_write: false); |
178 | } |
179 | |
180 | void __tsan_write_range(void *addr, uptr size) { |
181 | MemoryAccessRange(thr: cur_thread(), CALLERPC, addr: (uptr)addr, size, is_write: true); |
182 | } |
183 | |
184 | void __tsan_read_range_pc(void *addr, uptr size, void *pc) { |
185 | MemoryAccessRange(thr: cur_thread(), STRIP_PAC_PC(pc), addr: (uptr)addr, size, is_write: false); |
186 | } |
187 | |
188 | void __tsan_write_range_pc(void *addr, uptr size, void *pc) { |
189 | MemoryAccessRange(thr: cur_thread(), STRIP_PAC_PC(pc), addr: (uptr)addr, size, is_write: true); |
190 | } |
191 | |