10eae32dcSDimitry Andric#include "asan_mapping.h" 20eae32dcSDimitry Andric#include "sanitizer_common/sanitizer_asm.h" 30eae32dcSDimitry Andric 40eae32dcSDimitry Andric#if defined(__x86_64__) 50eae32dcSDimitry Andric#include "sanitizer_common/sanitizer_platform.h" 60eae32dcSDimitry Andric 70eae32dcSDimitry Andric.file "asan_rtl_x86_64.S" 80eae32dcSDimitry Andric 90eae32dcSDimitry Andric#define NAME(n, reg, op, s, i) n##_##op##_##i##_##s##_##reg 100eae32dcSDimitry Andric 110eae32dcSDimitry Andric#define FNAME(reg, op, s, i) NAME(__asan_check, reg, op, s, i) 120eae32dcSDimitry Andric#define RLABEL(reg, op, s, i) NAME(.return, reg, op, s, i) 130eae32dcSDimitry Andric#define CLABEL(reg, op, s, i) NAME(.check, reg, op, s, i) 140eae32dcSDimitry Andric#define FLABEL(reg, op, s, i) NAME(.fail, reg, op, s, i) 150eae32dcSDimitry Andric 160eae32dcSDimitry Andric#define BEGINF(reg, op, s, i) \ 1781ad6265SDimitry Andric.section .text.FNAME(reg, op, s, i),"ax",@progbits ;\ 180eae32dcSDimitry Andric.globl FNAME(reg, op, s, i) ;\ 190eae32dcSDimitry Andric.hidden FNAME(reg, op, s, i) ;\ 200eae32dcSDimitry AndricASM_TYPE_FUNCTION(FNAME(reg, op, s, i)) ;\ 210eae32dcSDimitry Andric.cfi_startproc ;\ 220eae32dcSDimitry AndricFNAME(reg, op, s, i): ;\ 230eae32dcSDimitry Andric 240eae32dcSDimitry Andric#define ENDF .cfi_endproc ;\ 250eae32dcSDimitry Andric 260eae32dcSDimitry Andric// Access check functions for 1,2 and 4 byte types, which require extra checks. 270eae32dcSDimitry Andric#define ASAN_MEMORY_ACCESS_INITIAL_CHECK_ADD(reg, op, s) \ 280eae32dcSDimitry Andric mov %##reg,%r10 ;\ 290eae32dcSDimitry Andric shr $0x3,%r10 ;\ 30*cb14a3feSDimitry Andric .if ASAN_SHADOW_OFFSET_CONST < 0x80000000 ;\ 310eae32dcSDimitry Andric movsbl ASAN_SHADOW_OFFSET_CONST(%r10),%r10d ;\ 32*cb14a3feSDimitry Andric .else ;\ 33*cb14a3feSDimitry Andric movabsq $ASAN_SHADOW_OFFSET_CONST,%r11 ;\ 34*cb14a3feSDimitry Andric movsbl (%r10,%r11),%r10d ;\ 35*cb14a3feSDimitry Andric .endif ;\ 360eae32dcSDimitry Andric test %r10d,%r10d ;\ 370eae32dcSDimitry Andric jne CLABEL(reg, op, s, add) ;\ 380eae32dcSDimitry AndricRLABEL(reg, op, s, add): ;\ 390eae32dcSDimitry Andric retq ;\ 400eae32dcSDimitry Andric 410eae32dcSDimitry Andric#define ASAN_MEMORY_ACCESS_EXTRA_CHECK_1(reg, op, i) \ 420eae32dcSDimitry AndricCLABEL(reg, op, 1, i): ;\ 435f757f3fSDimitry Andric mov %##reg,%r11 ;\ 445f757f3fSDimitry Andric and $0x7,%r11d ;\ 455f757f3fSDimitry Andric cmp %r10d,%r11d ;\ 460eae32dcSDimitry Andric jl RLABEL(reg, op, 1, i);\ 470eae32dcSDimitry Andric mov %##reg,%rdi ;\ 4881ad6265SDimitry Andric jmp __asan_report_##op##1_asm ;\ 490eae32dcSDimitry Andric 500eae32dcSDimitry Andric#define ASAN_MEMORY_ACCESS_EXTRA_CHECK_2(reg, op, i) \ 510eae32dcSDimitry AndricCLABEL(reg, op, 2, i): ;\ 525f757f3fSDimitry Andric mov %##reg,%r11 ;\ 535f757f3fSDimitry Andric and $0x7,%r11d ;\ 545f757f3fSDimitry Andric add $0x1,%r11d ;\ 555f757f3fSDimitry Andric cmp %r10d,%r11d ;\ 560eae32dcSDimitry Andric jl RLABEL(reg, op, 2, i);\ 570eae32dcSDimitry Andric mov %##reg,%rdi ;\ 5881ad6265SDimitry Andric jmp __asan_report_##op##2_asm ;\ 590eae32dcSDimitry Andric 600eae32dcSDimitry Andric#define ASAN_MEMORY_ACCESS_EXTRA_CHECK_4(reg, op, i) \ 610eae32dcSDimitry AndricCLABEL(reg, op, 4, i): ;\ 625f757f3fSDimitry Andric mov %##reg,%r11 ;\ 635f757f3fSDimitry Andric and $0x7,%r11d ;\ 645f757f3fSDimitry Andric add $0x3,%r11d ;\ 655f757f3fSDimitry Andric cmp %r10d,%r11d ;\ 660eae32dcSDimitry Andric jl RLABEL(reg, op, 4, i);\ 670eae32dcSDimitry Andric mov %##reg,%rdi ;\ 6881ad6265SDimitry Andric jmp __asan_report_##op##4_asm ;\ 690eae32dcSDimitry Andric 700eae32dcSDimitry Andric#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_1(reg, op) \ 710eae32dcSDimitry AndricBEGINF(reg, op, 1, add) ;\ 720eae32dcSDimitry Andric ASAN_MEMORY_ACCESS_INITIAL_CHECK_ADD(reg, op, 1) ;\ 730eae32dcSDimitry Andric ASAN_MEMORY_ACCESS_EXTRA_CHECK_1(reg, op, add) ;\ 740eae32dcSDimitry AndricENDF 750eae32dcSDimitry Andric 760eae32dcSDimitry Andric#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_2(reg, op) \ 770eae32dcSDimitry AndricBEGINF(reg, op, 2, add) ;\ 780eae32dcSDimitry Andric ASAN_MEMORY_ACCESS_INITIAL_CHECK_ADD(reg, op, 2) ;\ 790eae32dcSDimitry Andric ASAN_MEMORY_ACCESS_EXTRA_CHECK_2(reg, op, add) ;\ 800eae32dcSDimitry AndricENDF 810eae32dcSDimitry Andric 820eae32dcSDimitry Andric#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_4(reg, op) \ 830eae32dcSDimitry AndricBEGINF(reg, op, 4, add) ;\ 840eae32dcSDimitry Andric ASAN_MEMORY_ACCESS_INITIAL_CHECK_ADD(reg, op, 4) ;\ 850eae32dcSDimitry Andric ASAN_MEMORY_ACCESS_EXTRA_CHECK_4(reg, op, add) ;\ 860eae32dcSDimitry AndricENDF 870eae32dcSDimitry Andric 880eae32dcSDimitry Andric// Access check functions for 8 and 16 byte types: no extra checks required. 890eae32dcSDimitry Andric#define ASAN_MEMORY_ACCESS_CHECK_ADD(reg, op, s, c) \ 900eae32dcSDimitry Andric mov %##reg,%r10 ;\ 910eae32dcSDimitry Andric shr $0x3,%r10 ;\ 92*cb14a3feSDimitry Andric .if ASAN_SHADOW_OFFSET_CONST < 0x80000000 ;\ 930eae32dcSDimitry Andric ##c $0x0,ASAN_SHADOW_OFFSET_CONST(%r10) ;\ 94*cb14a3feSDimitry Andric .else ;\ 95*cb14a3feSDimitry Andric movabsq $ASAN_SHADOW_OFFSET_CONST,%r11 ;\ 96*cb14a3feSDimitry Andric ##c $0x0,(%r10,%r11) ;\ 97*cb14a3feSDimitry Andric .endif ;\ 980eae32dcSDimitry Andric jne FLABEL(reg, op, s, add) ;\ 990eae32dcSDimitry Andric retq ;\ 1000eae32dcSDimitry Andric 1010eae32dcSDimitry Andric#define ASAN_MEMORY_ACCESS_FAIL(reg, op, s, i) \ 1020eae32dcSDimitry AndricFLABEL(reg, op, s, i): ;\ 1030eae32dcSDimitry Andric mov %##reg,%rdi ;\ 10481ad6265SDimitry Andric jmp __asan_report_##op##s##_asm;\ 1050eae32dcSDimitry Andric 1060eae32dcSDimitry Andric#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_8(reg, op) \ 1070eae32dcSDimitry AndricBEGINF(reg, op, 8, add) ;\ 1080eae32dcSDimitry Andric ASAN_MEMORY_ACCESS_CHECK_ADD(reg, op, 8, cmpb) ;\ 1090eae32dcSDimitry Andric ASAN_MEMORY_ACCESS_FAIL(reg, op, 8, add) ;\ 1100eae32dcSDimitry AndricENDF 1110eae32dcSDimitry Andric 1120eae32dcSDimitry Andric#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_16(reg, op) \ 1130eae32dcSDimitry AndricBEGINF(reg, op, 16, add) ;\ 1140eae32dcSDimitry Andric ASAN_MEMORY_ACCESS_CHECK_ADD(reg, op, 16, cmpw) ;\ 1150eae32dcSDimitry Andric ASAN_MEMORY_ACCESS_FAIL(reg, op, 16, add) ;\ 1160eae32dcSDimitry AndricENDF 1170eae32dcSDimitry Andric 1180eae32dcSDimitry Andric#define ASAN_MEMORY_ACCESS_CALLBACKS_ADD(reg) \ 1190eae32dcSDimitry AndricASAN_MEMORY_ACCESS_CALLBACK_ADD_1(reg, load) \ 1200eae32dcSDimitry AndricASAN_MEMORY_ACCESS_CALLBACK_ADD_1(reg, store) \ 1210eae32dcSDimitry AndricASAN_MEMORY_ACCESS_CALLBACK_ADD_2(reg, load) \ 1220eae32dcSDimitry AndricASAN_MEMORY_ACCESS_CALLBACK_ADD_2(reg, store) \ 1230eae32dcSDimitry AndricASAN_MEMORY_ACCESS_CALLBACK_ADD_4(reg, load) \ 1240eae32dcSDimitry AndricASAN_MEMORY_ACCESS_CALLBACK_ADD_4(reg, store) \ 1250eae32dcSDimitry AndricASAN_MEMORY_ACCESS_CALLBACK_ADD_8(reg, load) \ 1260eae32dcSDimitry AndricASAN_MEMORY_ACCESS_CALLBACK_ADD_8(reg, store) \ 1270eae32dcSDimitry AndricASAN_MEMORY_ACCESS_CALLBACK_ADD_16(reg, load) \ 1280eae32dcSDimitry AndricASAN_MEMORY_ACCESS_CALLBACK_ADD_16(reg, store) \ 1290eae32dcSDimitry Andric 1300eae32dcSDimitry Andric 1310eae32dcSDimitry Andric// Instantiate all but R10 and R11 callbacks. We are using PLTSafe class with 1320eae32dcSDimitry Andric// the intrinsic, which guarantees that the code generation will never emit 1330eae32dcSDimitry Andric// R10 or R11 callback. 1340eae32dcSDimitry AndricASAN_MEMORY_ACCESS_CALLBACKS_ADD(RAX) 1350eae32dcSDimitry AndricASAN_MEMORY_ACCESS_CALLBACKS_ADD(RBX) 1360eae32dcSDimitry AndricASAN_MEMORY_ACCESS_CALLBACKS_ADD(RCX) 1370eae32dcSDimitry AndricASAN_MEMORY_ACCESS_CALLBACKS_ADD(RDX) 1380eae32dcSDimitry AndricASAN_MEMORY_ACCESS_CALLBACKS_ADD(RSI) 1390eae32dcSDimitry AndricASAN_MEMORY_ACCESS_CALLBACKS_ADD(RDI) 1400eae32dcSDimitry AndricASAN_MEMORY_ACCESS_CALLBACKS_ADD(RBP) 1410eae32dcSDimitry AndricASAN_MEMORY_ACCESS_CALLBACKS_ADD(R8) 1420eae32dcSDimitry AndricASAN_MEMORY_ACCESS_CALLBACKS_ADD(R9) 1430eae32dcSDimitry AndricASAN_MEMORY_ACCESS_CALLBACKS_ADD(R12) 1440eae32dcSDimitry AndricASAN_MEMORY_ACCESS_CALLBACKS_ADD(R13) 1450eae32dcSDimitry AndricASAN_MEMORY_ACCESS_CALLBACKS_ADD(R14) 1460eae32dcSDimitry AndricASAN_MEMORY_ACCESS_CALLBACKS_ADD(R15) 1470eae32dcSDimitry Andric 1480eae32dcSDimitry Andric#endif 1490eae32dcSDimitry Andric 1500eae32dcSDimitry AndricNO_EXEC_STACK_DIRECTIVE 151