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.file "asan_rtl_x86_64.S"
8
9#define NAME(n, reg, op, s, i) n##_##op##_##i##_##s##_##reg
10
11#define FNAME(reg, op, s, i) NAME(__asan_check, reg, op, s, i)
12#define RLABEL(reg, op, s, i) NAME(.return, reg, op, s, i)
13#define CLABEL(reg, op, s, i) NAME(.check, reg, op, s, i)
14#define FLABEL(reg, op, s, i) NAME(.fail, reg, op, s, i)
15
16#define BEGINF(reg, op, s, i) \
17.section .text.FNAME(reg, op, s, i),"ax",@progbits ;\
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        .if ASAN_SHADOW_OFFSET_CONST < 0x80000000   ;\
31        movsbl ASAN_SHADOW_OFFSET_CONST(%r10),%r10d ;\
32        .else                                       ;\
33        movabsq $ASAN_SHADOW_OFFSET_CONST,%r11      ;\
34        movsbl (%r10,%r11),%r10d                    ;\
35        .endif                                      ;\
36        test   %r10d,%r10d ;\
37        jne    CLABEL(reg, op, s, add) ;\
38RLABEL(reg, op, s, add): ;\
39        retq  ;\
40
41#define ASAN_MEMORY_ACCESS_EXTRA_CHECK_1(reg, op, i) \
42CLABEL(reg, op, 1, i): ;\
43        mov    %##reg,%r11 ;\
44        and    $0x7,%r11d ;\
45        cmp    %r10d,%r11d ;\
46        jl     RLABEL(reg, op, 1, i);\
47        mov    %##reg,%rdi ;\
48        jmp    __asan_report_##op##1_asm ;\
49
50#define ASAN_MEMORY_ACCESS_EXTRA_CHECK_2(reg, op, i) \
51CLABEL(reg, op, 2, i): ;\
52        mov    %##reg,%r11 ;\
53        and    $0x7,%r11d ;\
54        add    $0x1,%r11d ;\
55        cmp    %r10d,%r11d ;\
56        jl     RLABEL(reg, op, 2, i);\
57        mov    %##reg,%rdi ;\
58        jmp    __asan_report_##op##2_asm ;\
59
60#define ASAN_MEMORY_ACCESS_EXTRA_CHECK_4(reg, op, i) \
61CLABEL(reg, op, 4, i): ;\
62        mov    %##reg,%r11 ;\
63        and    $0x7,%r11d ;\
64        add    $0x3,%r11d ;\
65        cmp    %r10d,%r11d ;\
66        jl     RLABEL(reg, op, 4, i);\
67        mov    %##reg,%rdi ;\
68        jmp    __asan_report_##op##4_asm ;\
69
70#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_1(reg, op) \
71BEGINF(reg, op, 1, add) ;\
72        ASAN_MEMORY_ACCESS_INITIAL_CHECK_ADD(reg, op, 1) ;\
73        ASAN_MEMORY_ACCESS_EXTRA_CHECK_1(reg, op, add) ;\
74ENDF
75
76#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_2(reg, op) \
77BEGINF(reg, op, 2, add) ;\
78        ASAN_MEMORY_ACCESS_INITIAL_CHECK_ADD(reg, op, 2) ;\
79        ASAN_MEMORY_ACCESS_EXTRA_CHECK_2(reg, op, add) ;\
80ENDF
81
82#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_4(reg, op) \
83BEGINF(reg, op, 4, add) ;\
84        ASAN_MEMORY_ACCESS_INITIAL_CHECK_ADD(reg, op, 4) ;\
85        ASAN_MEMORY_ACCESS_EXTRA_CHECK_4(reg, op, add) ;\
86ENDF
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        .if ASAN_SHADOW_OFFSET_CONST < 0x80000000  ;\
93        ##c    $0x0,ASAN_SHADOW_OFFSET_CONST(%r10) ;\
94        .else                                      ;\
95        movabsq $ASAN_SHADOW_OFFSET_CONST,%r11     ;\
96        ##c    $0x0,(%r10,%r11)                    ;\
97        .endif                                     ;\
98        jne    FLABEL(reg, op, s, add) ;\
99        retq  ;\
100
101#define ASAN_MEMORY_ACCESS_FAIL(reg, op, s, i) \
102FLABEL(reg, op, s, i): ;\
103        mov    %##reg,%rdi ;\
104        jmp    __asan_report_##op##s##_asm;\
105
106#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_8(reg, op) \
107BEGINF(reg, op, 8, add) ;\
108        ASAN_MEMORY_ACCESS_CHECK_ADD(reg, op, 8, cmpb) ;\
109        ASAN_MEMORY_ACCESS_FAIL(reg, op, 8, add) ;\
110ENDF
111
112#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_16(reg, op) \
113BEGINF(reg, op, 16, add) ;\
114        ASAN_MEMORY_ACCESS_CHECK_ADD(reg, op, 16, cmpw) ;\
115        ASAN_MEMORY_ACCESS_FAIL(reg, op, 16, add) ;\
116ENDF
117
118#define ASAN_MEMORY_ACCESS_CALLBACKS_ADD(reg) \
119ASAN_MEMORY_ACCESS_CALLBACK_ADD_1(reg, load) \
120ASAN_MEMORY_ACCESS_CALLBACK_ADD_1(reg, store) \
121ASAN_MEMORY_ACCESS_CALLBACK_ADD_2(reg, load) \
122ASAN_MEMORY_ACCESS_CALLBACK_ADD_2(reg, store) \
123ASAN_MEMORY_ACCESS_CALLBACK_ADD_4(reg, load) \
124ASAN_MEMORY_ACCESS_CALLBACK_ADD_4(reg, store) \
125ASAN_MEMORY_ACCESS_CALLBACK_ADD_8(reg, load) \
126ASAN_MEMORY_ACCESS_CALLBACK_ADD_8(reg, store) \
127ASAN_MEMORY_ACCESS_CALLBACK_ADD_16(reg, load) \
128ASAN_MEMORY_ACCESS_CALLBACK_ADD_16(reg, store) \
129
130
131// Instantiate all but R10 and R11 callbacks. We are using PLTSafe class with
132// the intrinsic, which guarantees that the code generation will never emit
133// R10 or R11 callback.
134ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RAX)
135ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RBX)
136ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RCX)
137ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RDX)
138ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RSI)
139ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RDI)
140ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RBP)
141ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R8)
142ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R9)
143ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R12)
144ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R13)
145ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R14)
146ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R15)
147
148#endif
149
150NO_EXEC_STACK_DIRECTIVE
151