aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/clang18-rt/lib/asan/asan_rtl_x86_64.S
blob: 9c5289856d8ae67736a2bf4086316be580b0378a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#include "asan_mapping.h"
#include "sanitizer_common/sanitizer_asm.h"

#if defined(__x86_64__)
#include "sanitizer_common/sanitizer_platform.h"

.file "asan_rtl_x86_64.S"

#define NAME(n, reg, op, s, i) n##_##op##_##i##_##s##_##reg

#define FNAME(reg, op, s, i) NAME(__asan_check, reg, op, s, i)
#define RLABEL(reg, op, s, i) NAME(.return, reg, op, s, i)
#define CLABEL(reg, op, s, i) NAME(.check, reg, op, s, i)
#define FLABEL(reg, op, s, i) NAME(.fail, reg, op, s, i)

#define BEGINF(reg, op, s, i) \
.section .text.FNAME(reg, op, s, i),"ax",@progbits ;\
.globl  FNAME(reg, op, s, i) ;\
.hidden  FNAME(reg, op, s, i) ;\
ASM_TYPE_FUNCTION(FNAME(reg, op, s, i)) ;\
.cfi_startproc ;\
FNAME(reg, op, s, i): ;\

#define ENDF .cfi_endproc ;\

// Access check functions for 1,2 and 4 byte types, which require extra checks.
#define ASAN_MEMORY_ACCESS_INITIAL_CHECK_ADD(reg, op, s) \
        mov    %##reg,%r10 ;\
        shr    $0x3,%r10 ;\
        .if ASAN_SHADOW_OFFSET_CONST < 0x80000000   ;\
        movsbl ASAN_SHADOW_OFFSET_CONST(%r10),%r10d ;\
        .else                                       ;\
        movabsq $ASAN_SHADOW_OFFSET_CONST,%r11      ;\
        movsbl (%r10,%r11),%r10d                    ;\
        .endif                                      ;\
        test   %r10d,%r10d ;\
        jne    CLABEL(reg, op, s, add) ;\
RLABEL(reg, op, s, add): ;\
        retq  ;\

#define ASAN_MEMORY_ACCESS_EXTRA_CHECK_1(reg, op, i) \
CLABEL(reg, op, 1, i): ;\
        mov    %##reg,%r11 ;\
        and    $0x7,%r11d ;\
        cmp    %r10d,%r11d ;\
        jl     RLABEL(reg, op, 1, i);\
        mov    %##reg,%rdi ;\
        jmp    __asan_report_##op##1_asm ;\

#define ASAN_MEMORY_ACCESS_EXTRA_CHECK_2(reg, op, i) \
CLABEL(reg, op, 2, i): ;\
        mov    %##reg,%r11 ;\
        and    $0x7,%r11d ;\
        add    $0x1,%r11d ;\
        cmp    %r10d,%r11d ;\
        jl     RLABEL(reg, op, 2, i);\
        mov    %##reg,%rdi ;\
        jmp    __asan_report_##op##2_asm ;\

#define ASAN_MEMORY_ACCESS_EXTRA_CHECK_4(reg, op, i) \
CLABEL(reg, op, 4, i): ;\
        mov    %##reg,%r11 ;\
        and    $0x7,%r11d ;\
        add    $0x3,%r11d ;\
        cmp    %r10d,%r11d ;\
        jl     RLABEL(reg, op, 4, i);\
        mov    %##reg,%rdi ;\
        jmp    __asan_report_##op##4_asm ;\

#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_1(reg, op) \
BEGINF(reg, op, 1, add) ;\
        ASAN_MEMORY_ACCESS_INITIAL_CHECK_ADD(reg, op, 1) ;\
        ASAN_MEMORY_ACCESS_EXTRA_CHECK_1(reg, op, add) ;\
ENDF

#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_2(reg, op) \
BEGINF(reg, op, 2, add) ;\
        ASAN_MEMORY_ACCESS_INITIAL_CHECK_ADD(reg, op, 2) ;\
        ASAN_MEMORY_ACCESS_EXTRA_CHECK_2(reg, op, add) ;\
ENDF

#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_4(reg, op) \
BEGINF(reg, op, 4, add) ;\
        ASAN_MEMORY_ACCESS_INITIAL_CHECK_ADD(reg, op, 4) ;\
        ASAN_MEMORY_ACCESS_EXTRA_CHECK_4(reg, op, add) ;\
ENDF

// Access check functions for 8 and 16 byte types: no extra checks required.
#define ASAN_MEMORY_ACCESS_CHECK_ADD(reg, op, s, c) \
        mov    %##reg,%r10 ;\
        shr    $0x3,%r10 ;\
        .if ASAN_SHADOW_OFFSET_CONST < 0x80000000  ;\
        ##c    $0x0,ASAN_SHADOW_OFFSET_CONST(%r10) ;\
        .else                                      ;\
        movabsq $ASAN_SHADOW_OFFSET_CONST,%r11     ;\
        ##c    $0x0,(%r10,%r11)                    ;\
        .endif                                     ;\
        jne    FLABEL(reg, op, s, add) ;\
        retq  ;\

#define ASAN_MEMORY_ACCESS_FAIL(reg, op, s, i) \
FLABEL(reg, op, s, i): ;\
        mov    %##reg,%rdi ;\
        jmp    __asan_report_##op##s##_asm;\

#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_8(reg, op) \
BEGINF(reg, op, 8, add) ;\
        ASAN_MEMORY_ACCESS_CHECK_ADD(reg, op, 8, cmpb) ;\
        ASAN_MEMORY_ACCESS_FAIL(reg, op, 8, add) ;\
ENDF

#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_16(reg, op) \
BEGINF(reg, op, 16, add) ;\
        ASAN_MEMORY_ACCESS_CHECK_ADD(reg, op, 16, cmpw) ;\
        ASAN_MEMORY_ACCESS_FAIL(reg, op, 16, add) ;\
ENDF

#define ASAN_MEMORY_ACCESS_CALLBACKS_ADD(reg) \
ASAN_MEMORY_ACCESS_CALLBACK_ADD_1(reg, load) \
ASAN_MEMORY_ACCESS_CALLBACK_ADD_1(reg, store) \
ASAN_MEMORY_ACCESS_CALLBACK_ADD_2(reg, load) \
ASAN_MEMORY_ACCESS_CALLBACK_ADD_2(reg, store) \
ASAN_MEMORY_ACCESS_CALLBACK_ADD_4(reg, load) \
ASAN_MEMORY_ACCESS_CALLBACK_ADD_4(reg, store) \
ASAN_MEMORY_ACCESS_CALLBACK_ADD_8(reg, load) \
ASAN_MEMORY_ACCESS_CALLBACK_ADD_8(reg, store) \
ASAN_MEMORY_ACCESS_CALLBACK_ADD_16(reg, load) \
ASAN_MEMORY_ACCESS_CALLBACK_ADD_16(reg, store) \


// Instantiate all but R10 and R11 callbacks. We are using PLTSafe class with
// the intrinsic, which guarantees that the code generation will never emit
// R10 or R11 callback.
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RAX)
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RBX)
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RCX)
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RDX)
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RSI)
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RDI)
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RBP)
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R8)
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R9)
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R12)
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R13)
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R14)
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R15)

#endif

NO_EXEC_STACK_DIRECTIVE