| #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 ;\ |
| movsbl ASAN_SHADOW_OFFSET_CONST(%r10),%r10d ;\ |
| 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): ;\ |
| push %rcx ;\ |
| mov %##reg,%rcx ;\ |
| and $0x7,%ecx ;\ |
| cmp %r10d,%ecx ;\ |
| pop %rcx ;\ |
| 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): ;\ |
| push %rcx ;\ |
| mov %##reg,%rcx ;\ |
| and $0x7,%ecx ;\ |
| add $0x1,%ecx ;\ |
| cmp %r10d,%ecx ;\ |
| pop %rcx ;\ |
| 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): ;\ |
| push %rcx ;\ |
| mov %##reg,%rcx ;\ |
| and $0x7,%ecx ;\ |
| add $0x3,%ecx ;\ |
| cmp %r10d,%ecx ;\ |
| pop %rcx ;\ |
| 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 ;\ |
| ##c $0x0,ASAN_SHADOW_OFFSET_CONST(%r10) ;\ |
| 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 |