xref: /freebsd/contrib/llvm-project/compiler-rt/lib/asan/asan_rtl_x86_64.S (revision 18054d0220cfc8df9c9568c437bd6fbb59d53c3c)
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.hidden  FNAME(reg, op, s, i) ;\
20ASM_TYPE_FUNCTION(FNAME(reg, op, s, i)) ;\
21.cfi_startproc ;\
22FNAME(reg, op, s, i): ;\
23
24#define ENDF .cfi_endproc ;\
25
26// Access check functions for 1,2 and 4 byte types, which require extra checks.
27#define ASAN_MEMORY_ACCESS_INITIAL_CHECK_ADD(reg, op, s) \
28        mov    %##reg,%r10 ;\
29        shr    $0x3,%r10 ;\
30        movsbl ASAN_SHADOW_OFFSET_CONST(%r10),%r10d ;\
31        test   %r10d,%r10d ;\
32        jne    CLABEL(reg, op, s, add) ;\
33RLABEL(reg, op, s, add): ;\
34        retq  ;\
35
36#define ASAN_MEMORY_ACCESS_EXTRA_CHECK_1(reg, op, i) \
37CLABEL(reg, op, 1, i): ;\
38        push   %rcx ;\
39        mov    %##reg,%rcx ;\
40        and    $0x7,%ecx ;\
41        cmp    %r10d,%ecx ;\
42        pop    %rcx ;\
43        jl     RLABEL(reg, op, 1, i);\
44        mov    %##reg,%rdi ;\
45        jmp    __asan_report_##op##1@PLT ;\
46
47#define ASAN_MEMORY_ACCESS_EXTRA_CHECK_2(reg, op, i) \
48CLABEL(reg, op, 2, i): ;\
49        push   %rcx ;\
50        mov    %##reg,%rcx ;\
51        and    $0x7,%ecx ;\
52        add    $0x1,%ecx ;\
53        cmp    %r10d,%ecx ;\
54        pop    %rcx ;\
55        jl     RLABEL(reg, op, 2, i);\
56        mov    %##reg,%rdi ;\
57        jmp    __asan_report_##op##2@PLT ;\
58
59#define ASAN_MEMORY_ACCESS_EXTRA_CHECK_4(reg, op, i) \
60CLABEL(reg, op, 4, i): ;\
61        push   %rcx ;\
62        mov    %##reg,%rcx ;\
63        and    $0x7,%ecx ;\
64        add    $0x3,%ecx ;\
65        cmp    %r10d,%ecx ;\
66        pop    %rcx ;\
67        jl     RLABEL(reg, op, 4, i);\
68        mov    %##reg,%rdi ;\
69        jmp    __asan_report_##op##4@PLT ;\
70
71#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_1(reg, op) \
72BEGINF(reg, op, 1, add) ;\
73        ASAN_MEMORY_ACCESS_INITIAL_CHECK_ADD(reg, op, 1) ;\
74        ASAN_MEMORY_ACCESS_EXTRA_CHECK_1(reg, op, add) ;\
75ENDF
76
77#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_2(reg, op) \
78BEGINF(reg, op, 2, add) ;\
79        ASAN_MEMORY_ACCESS_INITIAL_CHECK_ADD(reg, op, 2) ;\
80        ASAN_MEMORY_ACCESS_EXTRA_CHECK_2(reg, op, add) ;\
81ENDF
82
83#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_4(reg, op) \
84BEGINF(reg, op, 4, add) ;\
85        ASAN_MEMORY_ACCESS_INITIAL_CHECK_ADD(reg, op, 4) ;\
86        ASAN_MEMORY_ACCESS_EXTRA_CHECK_4(reg, op, add) ;\
87ENDF
88
89// Access check functions for 8 and 16 byte types: no extra checks required.
90#define ASAN_MEMORY_ACCESS_CHECK_ADD(reg, op, s, c) \
91        mov    %##reg,%r10 ;\
92        shr    $0x3,%r10 ;\
93        ##c    $0x0,ASAN_SHADOW_OFFSET_CONST(%r10) ;\
94        jne    FLABEL(reg, op, s, add) ;\
95        retq  ;\
96
97#define ASAN_MEMORY_ACCESS_FAIL(reg, op, s, i) \
98FLABEL(reg, op, s, i): ;\
99        mov    %##reg,%rdi ;\
100        jmp    __asan_report_##op##s@PLT;\
101
102#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_8(reg, op) \
103BEGINF(reg, op, 8, add) ;\
104        ASAN_MEMORY_ACCESS_CHECK_ADD(reg, op, 8, cmpb) ;\
105        ASAN_MEMORY_ACCESS_FAIL(reg, op, 8, add) ;\
106ENDF
107
108#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_16(reg, op) \
109BEGINF(reg, op, 16, add) ;\
110        ASAN_MEMORY_ACCESS_CHECK_ADD(reg, op, 16, cmpw) ;\
111        ASAN_MEMORY_ACCESS_FAIL(reg, op, 16, add) ;\
112ENDF
113
114#define ASAN_MEMORY_ACCESS_CALLBACKS_ADD(reg) \
115ASAN_MEMORY_ACCESS_CALLBACK_ADD_1(reg, load) \
116ASAN_MEMORY_ACCESS_CALLBACK_ADD_1(reg, store) \
117ASAN_MEMORY_ACCESS_CALLBACK_ADD_2(reg, load) \
118ASAN_MEMORY_ACCESS_CALLBACK_ADD_2(reg, store) \
119ASAN_MEMORY_ACCESS_CALLBACK_ADD_4(reg, load) \
120ASAN_MEMORY_ACCESS_CALLBACK_ADD_4(reg, store) \
121ASAN_MEMORY_ACCESS_CALLBACK_ADD_8(reg, load) \
122ASAN_MEMORY_ACCESS_CALLBACK_ADD_8(reg, store) \
123ASAN_MEMORY_ACCESS_CALLBACK_ADD_16(reg, load) \
124ASAN_MEMORY_ACCESS_CALLBACK_ADD_16(reg, store) \
125
126
127// Instantiate all but R10 and R11 callbacks. We are using PLTSafe class with
128// the intrinsic, which guarantees that the code generation will never emit
129// R10 or R11 callback.
130ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RAX)
131ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RBX)
132ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RCX)
133ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RDX)
134ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RSI)
135ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RDI)
136ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RBP)
137ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R8)
138ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R9)
139ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R12)
140ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R13)
141ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R14)
142ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R15)
143
144#endif
145
146NO_EXEC_STACK_DIRECTIVE
147