Skip to content

Commit c135248

Browse files
committed
[ASan] Shared optimized callbacks implementation.
This change moves optimized callbacks from each .o file to compiler-rt. Instead of using code generation it uses direct assembly implementation. Please note that the 'or' version is not implemented and it will produce unresolved external if somehow 'or' version is requested. Reviewed By: vitalybuka Differential Revision: https://reviews.llvm.org/D114558
1 parent 3f066ac commit c135248

File tree

5 files changed

+267
-18
lines changed

5 files changed

+267
-18
lines changed

compiler-rt/lib/asan/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ set(ASAN_SOURCES
3434

3535
if (NOT WIN32 AND NOT APPLE)
3636
list(APPEND ASAN_SOURCES
37+
asan_rtl_x86_64.S
3738
asan_interceptors_vfork.S
3839
)
3940
endif()

compiler-rt/lib/asan/asan_interface.inc

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88
// Asan interface list.
99
//===----------------------------------------------------------------------===//
10+
1011
INTERFACE_FUNCTION(__asan_addr_is_in_fake_stack)
1112
INTERFACE_FUNCTION(__asan_address_is_poisoned)
1213
INTERFACE_FUNCTION(__asan_after_dynamic_init)
@@ -179,3 +180,37 @@ INTERFACE_FUNCTION(__asan_update_allocation_context)
179180
INTERFACE_WEAK_FUNCTION(__asan_default_options)
180181
INTERFACE_WEAK_FUNCTION(__asan_default_suppressions)
181182
INTERFACE_WEAK_FUNCTION(__asan_on_error)
183+
184+
#if defined(__x86_64__) && \
185+
!(defined(SANITIZER_MAC) || defined(SANITIZER_WINDOWS))
186+
187+
# define ASAN_MEMORY_ACCESS_CALLBACK_ADD(s, reg, op) \
188+
INTERFACE_FUNCTION(__asan_check_##op##_add_##s##_##reg)
189+
190+
# define ASAN_MEMORY_ACCESS_CALLBACKS_ADD(reg) \
191+
ASAN_MEMORY_ACCESS_CALLBACK_ADD(1, reg, load) \
192+
ASAN_MEMORY_ACCESS_CALLBACK_ADD(1, reg, store) \
193+
ASAN_MEMORY_ACCESS_CALLBACK_ADD(2, reg, load) \
194+
ASAN_MEMORY_ACCESS_CALLBACK_ADD(2, reg, store) \
195+
ASAN_MEMORY_ACCESS_CALLBACK_ADD(4, reg, load) \
196+
ASAN_MEMORY_ACCESS_CALLBACK_ADD(4, reg, store) \
197+
ASAN_MEMORY_ACCESS_CALLBACK_ADD(8, reg, load) \
198+
ASAN_MEMORY_ACCESS_CALLBACK_ADD(8, reg, store) \
199+
ASAN_MEMORY_ACCESS_CALLBACK_ADD(16, reg, load) \
200+
ASAN_MEMORY_ACCESS_CALLBACK_ADD(16, reg, store)
201+
202+
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RAX)
203+
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RBX)
204+
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RCX)
205+
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RDX)
206+
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RSI)
207+
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RDI)
208+
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RBP)
209+
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R8)
210+
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R9)
211+
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R12)
212+
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R13)
213+
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R14)
214+
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R15)
215+
216+
#endif // defined(__x86_64__)
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
#include "asan_mapping.h"
2+
#include "sanitizer_common/sanitizer_asm.h"
3+
4+
#if defined(__x86_64__)
5+
#include "sanitizer_common/sanitizer_platform.h"
6+
7+
.section .text
8+
.file "asan_rtl_x86_64.S"
9+
10+
#define NAME(n, reg, op, s, i) n##_##op##_##i##_##s##_##reg
11+
12+
#define FNAME(reg, op, s, i) NAME(__asan_check, reg, op, s, i)
13+
#define RLABEL(reg, op, s, i) NAME(.return, reg, op, s, i)
14+
#define CLABEL(reg, op, s, i) NAME(.check, reg, op, s, i)
15+
#define FLABEL(reg, op, s, i) NAME(.fail, reg, op, s, i)
16+
17+
#define BEGINF(reg, op, s, i) \
18+
.globl FNAME(reg, op, s, i) ;\
19+
ASM_TYPE_FUNCTION(FNAME(reg, op, s, i)) ;\
20+
.cfi_startproc ;\
21+
FNAME(reg, op, s, i): ;\
22+
23+
#define ENDF .cfi_endproc ;\
24+
25+
// Access check functions for 1,2 and 4 byte types, which require extra checks.
26+
#define ASAN_MEMORY_ACCESS_INITIAL_CHECK_ADD(reg, op, s) \
27+
mov %##reg,%r10 ;\
28+
shr $0x3,%r10 ;\
29+
movsbl ASAN_SHADOW_OFFSET_CONST(%r10),%r10d ;\
30+
test %r10d,%r10d ;\
31+
jne CLABEL(reg, op, s, add) ;\
32+
RLABEL(reg, op, s, add): ;\
33+
retq ;\
34+
35+
#define ASAN_MEMORY_ACCESS_EXTRA_CHECK_1(reg, op, i) \
36+
CLABEL(reg, op, 1, i): ;\
37+
push %rcx ;\
38+
mov %##reg,%rcx ;\
39+
and $0x7,%ecx ;\
40+
cmp %r10d,%ecx ;\
41+
pop %rcx ;\
42+
jl RLABEL(reg, op, 1, i);\
43+
mov %##reg,%rdi ;\
44+
jmp __asan_report_##op##1@PLT ;\
45+
46+
#define ASAN_MEMORY_ACCESS_EXTRA_CHECK_2(reg, op, i) \
47+
CLABEL(reg, op, 2, i): ;\
48+
push %rcx ;\
49+
mov %##reg,%rcx ;\
50+
and $0x7,%ecx ;\
51+
add $0x1,%ecx ;\
52+
cmp %r10d,%ecx ;\
53+
pop %rcx ;\
54+
jl RLABEL(reg, op, 2, i);\
55+
mov %##reg,%rdi ;\
56+
jmp __asan_report_##op##2@PLT ;\
57+
58+
#define ASAN_MEMORY_ACCESS_EXTRA_CHECK_4(reg, op, i) \
59+
CLABEL(reg, op, 4, i): ;\
60+
push %rcx ;\
61+
mov %##reg,%rcx ;\
62+
and $0x7,%ecx ;\
63+
add $0x3,%ecx ;\
64+
cmp %r10d,%ecx ;\
65+
pop %rcx ;\
66+
jl RLABEL(reg, op, 4, i);\
67+
mov %##reg,%rdi ;\
68+
jmp __asan_report_##op##4@PLT ;\
69+
70+
#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_1(reg, op) \
71+
BEGINF(reg, op, 1, add) ;\
72+
ASAN_MEMORY_ACCESS_INITIAL_CHECK_ADD(reg, op, 1) ;\
73+
ASAN_MEMORY_ACCESS_EXTRA_CHECK_1(reg, op, add) ;\
74+
ENDF
75+
76+
#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_2(reg, op) \
77+
BEGINF(reg, op, 2, add) ;\
78+
ASAN_MEMORY_ACCESS_INITIAL_CHECK_ADD(reg, op, 2) ;\
79+
ASAN_MEMORY_ACCESS_EXTRA_CHECK_2(reg, op, add) ;\
80+
ENDF
81+
82+
#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_4(reg, op) \
83+
BEGINF(reg, op, 4, add) ;\
84+
ASAN_MEMORY_ACCESS_INITIAL_CHECK_ADD(reg, op, 4) ;\
85+
ASAN_MEMORY_ACCESS_EXTRA_CHECK_4(reg, op, add) ;\
86+
ENDF
87+
88+
// Access check functions for 8 and 16 byte types: no extra checks required.
89+
#define ASAN_MEMORY_ACCESS_CHECK_ADD(reg, op, s, c) \
90+
mov %##reg,%r10 ;\
91+
shr $0x3,%r10 ;\
92+
##c $0x0,ASAN_SHADOW_OFFSET_CONST(%r10) ;\
93+
jne FLABEL(reg, op, s, add) ;\
94+
retq ;\
95+
96+
#define ASAN_MEMORY_ACCESS_FAIL(reg, op, s, i) \
97+
FLABEL(reg, op, s, i): ;\
98+
mov %##reg,%rdi ;\
99+
jmp __asan_report_##op##s@PLT;\
100+
101+
#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_8(reg, op) \
102+
BEGINF(reg, op, 8, add) ;\
103+
ASAN_MEMORY_ACCESS_CHECK_ADD(reg, op, 8, cmpb) ;\
104+
ASAN_MEMORY_ACCESS_FAIL(reg, op, 8, add) ;\
105+
ENDF
106+
107+
#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_16(reg, op) \
108+
BEGINF(reg, op, 16, add) ;\
109+
ASAN_MEMORY_ACCESS_CHECK_ADD(reg, op, 16, cmpw) ;\
110+
ASAN_MEMORY_ACCESS_FAIL(reg, op, 16, add) ;\
111+
ENDF
112+
113+
#define ASAN_MEMORY_ACCESS_CALLBACKS_ADD(reg) \
114+
ASAN_MEMORY_ACCESS_CALLBACK_ADD_1(reg, load) \
115+
ASAN_MEMORY_ACCESS_CALLBACK_ADD_1(reg, store) \
116+
ASAN_MEMORY_ACCESS_CALLBACK_ADD_2(reg, load) \
117+
ASAN_MEMORY_ACCESS_CALLBACK_ADD_2(reg, store) \
118+
ASAN_MEMORY_ACCESS_CALLBACK_ADD_4(reg, load) \
119+
ASAN_MEMORY_ACCESS_CALLBACK_ADD_4(reg, store) \
120+
ASAN_MEMORY_ACCESS_CALLBACK_ADD_8(reg, load) \
121+
ASAN_MEMORY_ACCESS_CALLBACK_ADD_8(reg, store) \
122+
ASAN_MEMORY_ACCESS_CALLBACK_ADD_16(reg, load) \
123+
ASAN_MEMORY_ACCESS_CALLBACK_ADD_16(reg, store) \
124+
125+
126+
// Instantiate all but R10 and R11 callbacks. We are using PLTSafe class with
127+
// the intrinsic, which guarantees that the code generation will never emit
128+
// R10 or R11 callback.
129+
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RAX)
130+
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RBX)
131+
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RCX)
132+
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RDX)
133+
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RSI)
134+
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RDI)
135+
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RBP)
136+
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R8)
137+
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R9)
138+
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R12)
139+
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R13)
140+
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R14)
141+
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R15)
142+
143+
#endif

compiler-rt/lib/asan/tests/asan_noinst_test.cpp

Lines changed: 85 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -231,23 +231,8 @@ TEST(AddressSanitizer, ShadowRegionIsPoisonedTest) {
231231
}
232232

233233
// Test __asan_load1 & friends.
234-
TEST(AddressSanitizer, LoadStoreCallbacks) {
235-
typedef void (*CB)(uptr p);
236-
CB cb[2][5] = {{
237-
__asan_load1,
238-
__asan_load2,
239-
__asan_load4,
240-
__asan_load8,
241-
__asan_load16,
242-
},
243-
{
244-
__asan_store1,
245-
__asan_store2,
246-
__asan_store4,
247-
__asan_store8,
248-
__asan_store16,
249-
}};
250-
234+
typedef void (*CB)(uptr p);
235+
static void TestLoadStoreCallbacks(CB cb[2][5]) {
251236
uptr buggy_ptr;
252237

253238
__asan_test_only_reported_buggy_pointer = &buggy_ptr;
@@ -277,3 +262,86 @@ TEST(AddressSanitizer, LoadStoreCallbacks) {
277262
}
278263
__asan_test_only_reported_buggy_pointer = 0;
279264
}
265+
266+
TEST(AddressSanitizer, LoadStoreCallbacks) {
267+
CB cb[2][5] = {{
268+
__asan_load1,
269+
__asan_load2,
270+
__asan_load4,
271+
__asan_load8,
272+
__asan_load16,
273+
},
274+
{
275+
__asan_store1,
276+
__asan_store2,
277+
__asan_store4,
278+
__asan_store8,
279+
__asan_store16,
280+
}};
281+
TestLoadStoreCallbacks(cb);
282+
}
283+
284+
#if defined(__x86_64__) && \
285+
!(defined(SANITIZER_MAC) || defined(SANITIZER_WINDOWS))
286+
// clang-format off
287+
288+
#define CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(s, reg, op) \
289+
void CallAsanMemoryAccessAdd##reg##op##s(uptr address) { \
290+
asm("push %%" #reg " \n" \
291+
"mov %[x], %%" #reg " \n" \
292+
"call __asan_check_" #op "_add_" #s "_" #reg "\n" \
293+
"pop %%" #reg " \n" \
294+
: \
295+
: [x] "r"(address) \
296+
: "r8", "rdi"); \
297+
}
298+
299+
#define TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(reg) \
300+
CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(1, reg, load) \
301+
CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(1, reg, store) \
302+
CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(2, reg, load) \
303+
CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(2, reg, store) \
304+
CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(4, reg, load) \
305+
CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(4, reg, store) \
306+
CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(8, reg, load) \
307+
CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(8, reg, store) \
308+
CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(16, reg, load) \
309+
CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(16, reg, store) \
310+
\
311+
TEST(AddressSanitizer, LoadStoreCallbacksAddX86##reg) { \
312+
CB cb[2][5] = {{ \
313+
CallAsanMemoryAccessAdd##reg##load1, \
314+
CallAsanMemoryAccessAdd##reg##load2, \
315+
CallAsanMemoryAccessAdd##reg##load4, \
316+
CallAsanMemoryAccessAdd##reg##load8, \
317+
CallAsanMemoryAccessAdd##reg##load16, \
318+
}, \
319+
{ \
320+
CallAsanMemoryAccessAdd##reg##store1, \
321+
CallAsanMemoryAccessAdd##reg##store2, \
322+
CallAsanMemoryAccessAdd##reg##store4, \
323+
CallAsanMemoryAccessAdd##reg##store8, \
324+
CallAsanMemoryAccessAdd##reg##store16, \
325+
}}; \
326+
TestLoadStoreCallbacks(cb); \
327+
}
328+
329+
// Instantiate all but R10 and R11 callbacks. We are using PLTSafe class with
330+
// the intrinsic, which guarantees that the code generation will never emit
331+
// R10 or R11 callbacks.
332+
TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RAX)
333+
TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RBX)
334+
TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RCX)
335+
TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RDX)
336+
TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RSI)
337+
TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RDI)
338+
TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RBP)
339+
TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R8)
340+
TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R9)
341+
TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R12)
342+
TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R13)
343+
TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R14)
344+
TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R15)
345+
346+
// clang-format on
347+
#endif

compiler-rt/test/asan/TestCases/Linux/interface_symbols_linux.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// Check the presence of interface symbols in compiled file.
22

3+
// RUN: %clangxx -x c++-header -o - -E %p/../../../../lib/asan/asan_interface.inc \
4+
// RUN: | sed "s/INTERFACE_FUNCTION/\nINTERFACE_FUNCTION/g" > %t.asan_interface.inc
35
// RUN: %clangxx_asan -O2 %s -o %t.exe
46
// RUN: nm -D %t.exe | grep " [TWw] " \
57
// RUN: | grep -o "\(__asan_\|__ubsan_\|__sancov_\|__sanitizer_\)[^ ]*" \
@@ -10,7 +12,7 @@
1012
// RUN: > %t.exports
1113
//
1214
// RUN: grep -e "INTERFACE_\(WEAK_\)\?FUNCTION" \
13-
// RUN: %p/../../../../lib/asan/asan_interface.inc \
15+
// RUN: %t.asan_interface.inc \
1416
// RUN: %p/../../../../lib/ubsan/ubsan_interface.inc \
1517
// RUN: %p/../../../../lib/sanitizer_common/sanitizer_common_interface.inc \
1618
// RUN: %p/../../../../lib/sanitizer_common/sanitizer_common_interface_posix.inc \

0 commit comments

Comments
 (0)