diff --git a/compiler-rt/lib/asan/CMakeLists.txt b/compiler-rt/lib/asan/CMakeLists.txt --- a/compiler-rt/lib/asan/CMakeLists.txt +++ b/compiler-rt/lib/asan/CMakeLists.txt @@ -24,6 +24,7 @@ asan_premap_shadow.cpp asan_report.cpp asan_rtl.cpp + asan_rtl_x86_64.S asan_shadow_setup.cpp asan_stack.cpp asan_stats.cpp diff --git a/compiler-rt/lib/asan/asan_interface.inc b/compiler-rt/lib/asan/asan_interface.inc --- a/compiler-rt/lib/asan/asan_interface.inc +++ b/compiler-rt/lib/asan/asan_interface.inc @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// // Asan interface list. //===----------------------------------------------------------------------===// + INTERFACE_FUNCTION(__asan_addr_is_in_fake_stack) INTERFACE_FUNCTION(__asan_address_is_poisoned) INTERFACE_FUNCTION(__asan_after_dynamic_init) @@ -179,3 +180,36 @@ INTERFACE_WEAK_FUNCTION(__asan_default_options) INTERFACE_WEAK_FUNCTION(__asan_default_suppressions) INTERFACE_WEAK_FUNCTION(__asan_on_error) + +#if defined(__x86_64__) + +# define ASAN_MEMORY_ACCESS_CALLBACK_ADD(s, reg, op) \ + INTERFACE_FUNCTION(__asan_check_##op##_add_##s##_##reg) + +# 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) + +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 // defined(__x86_64__) diff --git a/compiler-rt/lib/asan/asan_mapping.h b/compiler-rt/lib/asan/asan_mapping.h deleted file mode 100644 --- a/compiler-rt/lib/asan/asan_mapping.h +++ /dev/null @@ -1,385 +0,0 @@ -//===-- asan_mapping.h ------------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file is a part of AddressSanitizer, an address sanity checker. -// -// Defines ASan memory mapping. -//===----------------------------------------------------------------------===// -#ifndef ASAN_MAPPING_H -#define ASAN_MAPPING_H - -#include "asan_internal.h" - -// The full explanation of the memory mapping could be found here: -// https://github.com/google/sanitizers/wiki/AddressSanitizerAlgorithm -// -// Typical shadow mapping on Linux/x86_64 with SHADOW_OFFSET == 0x00007fff8000: -// || `[0x10007fff8000, 0x7fffffffffff]` || HighMem || -// || `[0x02008fff7000, 0x10007fff7fff]` || HighShadow || -// || `[0x00008fff7000, 0x02008fff6fff]` || ShadowGap || -// || `[0x00007fff8000, 0x00008fff6fff]` || LowShadow || -// || `[0x000000000000, 0x00007fff7fff]` || LowMem || -// -// When SHADOW_OFFSET is zero (-pie): -// || `[0x100000000000, 0x7fffffffffff]` || HighMem || -// || `[0x020000000000, 0x0fffffffffff]` || HighShadow || -// || `[0x000000040000, 0x01ffffffffff]` || ShadowGap || -// -// Special case when something is already mapped between -// 0x003000000000 and 0x005000000000 (e.g. when prelink is installed): -// || `[0x10007fff8000, 0x7fffffffffff]` || HighMem || -// || `[0x02008fff7000, 0x10007fff7fff]` || HighShadow || -// || `[0x005000000000, 0x02008fff6fff]` || ShadowGap3 || -// || `[0x003000000000, 0x004fffffffff]` || MidMem || -// || `[0x000a7fff8000, 0x002fffffffff]` || ShadowGap2 || -// || `[0x00067fff8000, 0x000a7fff7fff]` || MidShadow || -// || `[0x00008fff7000, 0x00067fff7fff]` || ShadowGap || -// || `[0x00007fff8000, 0x00008fff6fff]` || LowShadow || -// || `[0x000000000000, 0x00007fff7fff]` || LowMem || -// -// Default Linux/i386 mapping on x86_64 machine: -// || `[0x40000000, 0xffffffff]` || HighMem || -// || `[0x28000000, 0x3fffffff]` || HighShadow || -// || `[0x24000000, 0x27ffffff]` || ShadowGap || -// || `[0x20000000, 0x23ffffff]` || LowShadow || -// || `[0x00000000, 0x1fffffff]` || LowMem || -// -// Default Linux/i386 mapping on i386 machine -// (addresses starting with 0xc0000000 are reserved -// for kernel and thus not sanitized): -// || `[0x38000000, 0xbfffffff]` || HighMem || -// || `[0x27000000, 0x37ffffff]` || HighShadow || -// || `[0x24000000, 0x26ffffff]` || ShadowGap || -// || `[0x20000000, 0x23ffffff]` || LowShadow || -// || `[0x00000000, 0x1fffffff]` || LowMem || -// -// Default Linux/MIPS32 mapping: -// || `[0x2aaa0000, 0xffffffff]` || HighMem || -// || `[0x0fff4000, 0x2aa9ffff]` || HighShadow || -// || `[0x0bff4000, 0x0fff3fff]` || ShadowGap || -// || `[0x0aaa0000, 0x0bff3fff]` || LowShadow || -// || `[0x00000000, 0x0aa9ffff]` || LowMem || -// -// Default Linux/MIPS64 mapping: -// || `[0x4000000000, 0xffffffffff]` || HighMem || -// || `[0x2800000000, 0x3fffffffff]` || HighShadow || -// || `[0x2400000000, 0x27ffffffff]` || ShadowGap || -// || `[0x2000000000, 0x23ffffffff]` || LowShadow || -// || `[0x0000000000, 0x1fffffffff]` || LowMem || -// -// Default Linux/RISCV64 Sv39 mapping: -// || `[0x1555550000, 0x3fffffffff]` || HighMem || -// || `[0x0fffffa000, 0x1555555fff]` || HighShadow || -// || `[0x0effffa000, 0x0fffff9fff]` || ShadowGap || -// || `[0x0d55550000, 0x0effff9fff]` || LowShadow || -// || `[0x0000000000, 0x0d5554ffff]` || LowMem || -// -// Default Linux/AArch64 (39-bit VMA) mapping: -// || `[0x2000000000, 0x7fffffffff]` || highmem || -// || `[0x1400000000, 0x1fffffffff]` || highshadow || -// || `[0x1200000000, 0x13ffffffff]` || shadowgap || -// || `[0x1000000000, 0x11ffffffff]` || lowshadow || -// || `[0x0000000000, 0x0fffffffff]` || lowmem || -// -// Default Linux/AArch64 (42-bit VMA) mapping: -// || `[0x10000000000, 0x3ffffffffff]` || highmem || -// || `[0x0a000000000, 0x0ffffffffff]` || highshadow || -// || `[0x09000000000, 0x09fffffffff]` || shadowgap || -// || `[0x08000000000, 0x08fffffffff]` || lowshadow || -// || `[0x00000000000, 0x07fffffffff]` || lowmem || -// -// Default Linux/S390 mapping: -// || `[0x30000000, 0x7fffffff]` || HighMem || -// || `[0x26000000, 0x2fffffff]` || HighShadow || -// || `[0x24000000, 0x25ffffff]` || ShadowGap || -// || `[0x20000000, 0x23ffffff]` || LowShadow || -// || `[0x00000000, 0x1fffffff]` || LowMem || -// -// Default Linux/SystemZ mapping: -// || `[0x14000000000000, 0x1fffffffffffff]` || HighMem || -// || `[0x12800000000000, 0x13ffffffffffff]` || HighShadow || -// || `[0x12000000000000, 0x127fffffffffff]` || ShadowGap || -// || `[0x10000000000000, 0x11ffffffffffff]` || LowShadow || -// || `[0x00000000000000, 0x0fffffffffffff]` || LowMem || -// -// Default Linux/SPARC64 (52-bit VMA) mapping: -// || `[0x8000000000000, 0xfffffffffffff]` || HighMem || -// || `[0x1080000000000, 0x207ffffffffff]` || HighShadow || -// || `[0x0090000000000, 0x107ffffffffff]` || ShadowGap || -// || `[0x0080000000000, 0x008ffffffffff]` || LowShadow || -// || `[0x0000000000000, 0x007ffffffffff]` || LowMem || -// -// Shadow mapping on FreeBSD/x86-64 with SHADOW_OFFSET == 0x400000000000: -// || `[0x500000000000, 0x7fffffffffff]` || HighMem || -// || `[0x4a0000000000, 0x4fffffffffff]` || HighShadow || -// || `[0x480000000000, 0x49ffffffffff]` || ShadowGap || -// || `[0x400000000000, 0x47ffffffffff]` || LowShadow || -// || `[0x000000000000, 0x3fffffffffff]` || LowMem || -// -// Shadow mapping on FreeBSD/i386 with SHADOW_OFFSET == 0x40000000: -// || `[0x60000000, 0xffffffff]` || HighMem || -// || `[0x4c000000, 0x5fffffff]` || HighShadow || -// || `[0x48000000, 0x4bffffff]` || ShadowGap || -// || `[0x40000000, 0x47ffffff]` || LowShadow || -// || `[0x00000000, 0x3fffffff]` || LowMem || -// -// Shadow mapping on NetBSD/x86-64 with SHADOW_OFFSET == 0x400000000000: -// || `[0x4feffffffe01, 0x7f7ffffff000]` || HighMem || -// || `[0x49fdffffffc0, 0x4feffffffe00]` || HighShadow || -// || `[0x480000000000, 0x49fdffffffbf]` || ShadowGap || -// || `[0x400000000000, 0x47ffffffffff]` || LowShadow || -// || `[0x000000000000, 0x3fffffffffff]` || LowMem || -// -// Shadow mapping on NetBSD/i386 with SHADOW_OFFSET == 0x40000000: -// || `[0x60000000, 0xfffff000]` || HighMem || -// || `[0x4c000000, 0x5fffffff]` || HighShadow || -// || `[0x48000000, 0x4bffffff]` || ShadowGap || -// || `[0x40000000, 0x47ffffff]` || LowShadow || -// || `[0x00000000, 0x3fffffff]` || LowMem || -// -// Default Windows/i386 mapping: -// (the exact location of HighShadow/HighMem may vary depending -// on WoW64, /LARGEADDRESSAWARE, etc). -// || `[0x50000000, 0xffffffff]` || HighMem || -// || `[0x3a000000, 0x4fffffff]` || HighShadow || -// || `[0x36000000, 0x39ffffff]` || ShadowGap || -// || `[0x30000000, 0x35ffffff]` || LowShadow || -// || `[0x00000000, 0x2fffffff]` || LowMem || - -#define ASAN_SHADOW_SCALE 3 - -static const u64 kDefaultShadowSentinel = ~(uptr)0; - -#if SANITIZER_FUCHSIA -# define ASAN_SHADOW_OFFSET_CONST (0) -#elif SANITIZER_WORDSIZE == 32 -# if SANITIZER_ANDROID -# define ASAN_SHADOW_OFFSET_DYNAMIC -# elif defined(__mips__) -# define ASAN_SHADOW_OFFSET_CONST 0x0aaa0000 -# elif SANITIZER_FREEBSD -# define ASAN_SHADOW_OFFSET_CONST 0x40000000 -# elif SANITIZER_NETBSD -# define ASAN_SHADOW_OFFSET_CONST 0x40000000 -# elif SANITIZER_WINDOWS -# define ASAN_SHADOW_OFFSET_CONST 0x30000000 -# elif SANITIZER_IOS -# define ASAN_SHADOW_OFFSET_DYNAMIC -# else -# define ASAN_SHADOW_OFFSET_CONST 0x20000000 -# endif -#else -# if SANITIZER_IOS -# define ASAN_SHADOW_OFFSET_DYNAMIC -# elif SANITIZER_MAC && defined(__aarch64__) -# define ASAN_SHADOW_OFFSET_DYNAMIC -# elif SANITIZER_RISCV64 -# define ASAN_SHADOW_OFFSET_CONST 0x0000000d55550000 -# elif defined(__aarch64__) -# define ASAN_SHADOW_OFFSET_CONST 0x0000001000000000 -# elif defined(__powerpc64__) -# define ASAN_SHADOW_OFFSET_CONST 0x0000100000000000 -# elif defined(__s390x__) -# define ASAN_SHADOW_OFFSET_CONST 0x0010000000000000 -# elif SANITIZER_FREEBSD -# define ASAN_SHADOW_OFFSET_CONST 0x0000400000000000 -# elif SANITIZER_NETBSD -# define ASAN_SHADOW_OFFSET_CONST 0x0000400000000000 -# elif SANITIZER_MAC -# define ASAN_SHADOW_OFFSET_CONST 0x0000100000000000 -# elif defined(__mips64) -# define ASAN_SHADOW_OFFSET_CONST 0x0000002000000000 -# elif defined(__sparc__) -# define ASAN_SHADOW_OFFSET_CONST 0x0000080000000000 -# elif SANITIZER_WINDOWS64 -# define ASAN_SHADOW_OFFSET_DYNAMIC -# else -# define ASAN_SHADOW_OFFSET_CONST \ - 0x000000007FFFFFFF & (~0xFFFULL << ASAN_SHADOW_SCALE) -# endif -#endif - -#if defined(ASAN_SHADOW_OFFSET_CONST) -static const u64 kConstShadowOffset = ASAN_SHADOW_OFFSET_CONST; -# define ASAN_SHADOW_OFFSET kConstShadowOffset -#elif defined(ASAN_SHADOW_OFFSET_DYNAMIC) -# define ASAN_SHADOW_OFFSET __asan_shadow_memory_dynamic_address -#else -# error "ASAN_SHADOW_OFFSET can't be determined." -#endif - -#if SANITIZER_ANDROID && defined(__arm__) -# define ASAN_PREMAP_SHADOW 1 -#else -# define ASAN_PREMAP_SHADOW 0 -#endif - -#define ASAN_SHADOW_GRANULARITY (1ULL << ASAN_SHADOW_SCALE) - -#define DO_ASAN_MAPPING_PROFILE 0 // Set to 1 to profile the functions below. - -#if DO_ASAN_MAPPING_PROFILE -# define PROFILE_ASAN_MAPPING() AsanMappingProfile[__LINE__]++; -#else -# define PROFILE_ASAN_MAPPING() -#endif - -// If 1, all shadow boundaries are constants. -// Don't set to 1 other than for testing. -#define ASAN_FIXED_MAPPING 0 - -namespace __asan { - -extern uptr AsanMappingProfile[]; - -#if ASAN_FIXED_MAPPING -// Fixed mapping for 64-bit Linux. Mostly used for performance comparison -// with non-fixed mapping. As of r175253 (Feb 2013) the performance -// difference between fixed and non-fixed mapping is below the noise level. -static uptr kHighMemEnd = 0x7fffffffffffULL; -static uptr kMidMemBeg = 0x3000000000ULL; -static uptr kMidMemEnd = 0x4fffffffffULL; -#else -extern uptr kHighMemEnd, kMidMemBeg, kMidMemEnd; // Initialized in __asan_init. -#endif - -} // namespace __asan - -#if defined(__sparc__) && SANITIZER_WORDSIZE == 64 -# include "asan_mapping_sparc64.h" -#else -# define MEM_TO_SHADOW(mem) \ - (((mem) >> ASAN_SHADOW_SCALE) + (ASAN_SHADOW_OFFSET)) - -# define kLowMemBeg 0 -# define kLowMemEnd (ASAN_SHADOW_OFFSET ? ASAN_SHADOW_OFFSET - 1 : 0) - -# define kLowShadowBeg ASAN_SHADOW_OFFSET -# define kLowShadowEnd MEM_TO_SHADOW(kLowMemEnd) - -# define kHighMemBeg (MEM_TO_SHADOW(kHighMemEnd) + 1) - -# define kHighShadowBeg MEM_TO_SHADOW(kHighMemBeg) -# define kHighShadowEnd MEM_TO_SHADOW(kHighMemEnd) - -# define kMidShadowBeg MEM_TO_SHADOW(kMidMemBeg) -# define kMidShadowEnd MEM_TO_SHADOW(kMidMemEnd) - -// With the zero shadow base we can not actually map pages starting from 0. -// This constant is somewhat arbitrary. -# define kZeroBaseShadowStart 0 -# define kZeroBaseMaxShadowStart (1 << 18) - -# define kShadowGapBeg \ - (kLowShadowEnd ? kLowShadowEnd + 1 : kZeroBaseShadowStart) -# define kShadowGapEnd ((kMidMemBeg ? kMidShadowBeg : kHighShadowBeg) - 1) - -# define kShadowGap2Beg (kMidMemBeg ? kMidShadowEnd + 1 : 0) -# define kShadowGap2End (kMidMemBeg ? kMidMemBeg - 1 : 0) - -# define kShadowGap3Beg (kMidMemBeg ? kMidMemEnd + 1 : 0) -# define kShadowGap3End (kMidMemBeg ? kHighShadowBeg - 1 : 0) - -namespace __asan { - -static inline bool AddrIsInLowMem(uptr a) { - PROFILE_ASAN_MAPPING(); - return a <= kLowMemEnd; -} - -static inline bool AddrIsInLowShadow(uptr a) { - PROFILE_ASAN_MAPPING(); - return a >= kLowShadowBeg && a <= kLowShadowEnd; -} - -static inline bool AddrIsInMidMem(uptr a) { - PROFILE_ASAN_MAPPING(); - return kMidMemBeg && a >= kMidMemBeg && a <= kMidMemEnd; -} - -static inline bool AddrIsInMidShadow(uptr a) { - PROFILE_ASAN_MAPPING(); - return kMidMemBeg && a >= kMidShadowBeg && a <= kMidShadowEnd; -} - -static inline bool AddrIsInHighMem(uptr a) { - PROFILE_ASAN_MAPPING(); - return kHighMemBeg && a >= kHighMemBeg && a <= kHighMemEnd; -} - -static inline bool AddrIsInHighShadow(uptr a) { - PROFILE_ASAN_MAPPING(); - return kHighMemBeg && a >= kHighShadowBeg && a <= kHighShadowEnd; -} - -static inline bool AddrIsInShadowGap(uptr a) { - PROFILE_ASAN_MAPPING(); - if (kMidMemBeg) { - if (a <= kShadowGapEnd) - return ASAN_SHADOW_OFFSET == 0 || a >= kShadowGapBeg; - return (a >= kShadowGap2Beg && a <= kShadowGap2End) || - (a >= kShadowGap3Beg && a <= kShadowGap3End); - } - // In zero-based shadow mode we treat addresses near zero as addresses - // in shadow gap as well. - if (ASAN_SHADOW_OFFSET == 0) - return a <= kShadowGapEnd; - return a >= kShadowGapBeg && a <= kShadowGapEnd; -} - -} // namespace __asan - -#endif - -namespace __asan { - -static inline uptr MemToShadowSize(uptr size) { - return size >> ASAN_SHADOW_SCALE; -} - -static inline bool AddrIsInMem(uptr a) { - PROFILE_ASAN_MAPPING(); - return AddrIsInLowMem(a) || AddrIsInMidMem(a) || AddrIsInHighMem(a) || - (flags()->protect_shadow_gap == 0 && AddrIsInShadowGap(a)); -} - -static inline uptr MemToShadow(uptr p) { - PROFILE_ASAN_MAPPING(); - CHECK(AddrIsInMem(p)); - return MEM_TO_SHADOW(p); -} - -static inline bool AddrIsInShadow(uptr a) { - PROFILE_ASAN_MAPPING(); - return AddrIsInLowShadow(a) || AddrIsInMidShadow(a) || AddrIsInHighShadow(a); -} - -static inline bool AddrIsAlignedByGranularity(uptr a) { - PROFILE_ASAN_MAPPING(); - return (a & (ASAN_SHADOW_GRANULARITY - 1)) == 0; -} - -static inline bool AddressIsPoisoned(uptr a) { - PROFILE_ASAN_MAPPING(); - const uptr kAccessSize = 1; - u8 *shadow_address = (u8*)MEM_TO_SHADOW(a); - s8 shadow_value = *shadow_address; - if (shadow_value) { - u8 last_accessed_byte = - (a & (ASAN_SHADOW_GRANULARITY - 1)) + kAccessSize - 1; - return (last_accessed_byte >= shadow_value); - } - return false; -} - -// Must be after all calls to PROFILE_ASAN_MAPPING(). -static const uptr kAsanMappingProfileSize = __LINE__; - -} // namespace __asan - -#endif // ASAN_MAPPING_H diff --git a/compiler-rt/lib/asan/asan_rtl_x86_64.S b/compiler-rt/lib/asan/asan_rtl_x86_64.S new file mode 100644 --- /dev/null +++ b/compiler-rt/lib/asan/asan_rtl_x86_64.S @@ -0,0 +1,143 @@ +#include "asan_mapping.h" +#include "sanitizer_common/sanitizer_asm.h" + +#if defined(__x86_64__) +#include "sanitizer_common/sanitizer_platform.h" + +.section .text +.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) \ +.globl 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 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 ;\ + +#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 ;\ + +#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 ;\ + +#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,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 ;\ + +#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 diff --git a/compiler-rt/lib/asan/asan_shadow_defines.h b/compiler-rt/lib/asan/asan_shadow_defines.h new file mode 100644 --- /dev/null +++ b/compiler-rt/lib/asan/asan_shadow_defines.h @@ -0,0 +1,56 @@ +//===-- asan_shadow_defines.h -----------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file is a part of AddressSanitizer, an address sanity checker. +// +// Defines ASan memory mapping used by assembly portion. +//===----------------------------------------------------------------------===// + +#include "sanitizer_common/sanitizer_platform.h" + +#if !defined(SANITIZER_WORDSIZE) +# error "SANITIZER_WORDSIZE must be defined." +#endif + +#if SANITIZER_FUCHSIA +# define SHADOW_OFFSET_CONST 0 +#elif SANITIZER_WORDSIZE == 32 +# if defined(__mips__) +# define SHADOW_OFFSET_CONST 0xaaa0000 +# elif SANITIZER_FREEBSD +# define SHADOW_OFFSET_CONST 0x40000000 +# elif SANITIZER_NETBSD +# define SHADOW_OFFSET_CONST 0x40000000 +# elif SANITIZER_WINDOWS +# define SHADOW_OFFSET_CONST 0x30000000 +# elif SANITIZER_IOS +# define SHADOW_OFFSET_CONST 0 +# else +# define SHADOW_OFFSET_CONST 0x20000000 +# endif +#else +# if SANITIZER_RISCV64 +# define SHADOW_OFFSET_CONST 0x55550000 +# elif defined(__aarch64__) +# define SHADOW_OFFSET_CONST 0x1000000000 +# elif defined(__powerpc64__) +# define SHADOW_OFFSET_CONST 0x100000000000 +# elif defined(__s390x__) +# define SHADOW_OFFSET_CONST 0x10000000000000 +# elif SANITIZER_FREEBSD +# define SHADOW_OFFSET_CONST 0x400000000000 +# elif SANITIZER_NETBSD +# define SHADOW_OFFSET_CONST 0x400000000000 +# elif SANITIZER_MAC +# define SHADOW_OFFSET_CONST 0x7fff8000 +# elif defined(__mips64) +# define SHADOW_OFFSET_CONST 0x2000000000 +# else +# define SHADOW_OFFSET_CONST 0x7fff8000 +# endif +#endif diff --git a/compiler-rt/lib/asan/tests/asan_noinst_test.cpp b/compiler-rt/lib/asan/tests/asan_noinst_test.cpp --- a/compiler-rt/lib/asan/tests/asan_noinst_test.cpp +++ b/compiler-rt/lib/asan/tests/asan_noinst_test.cpp @@ -11,6 +11,7 @@ // This test file should be compiled w/o asan instrumentation. //===----------------------------------------------------------------------===// +#include #include #include #include @@ -231,17 +232,8 @@ } // Test __asan_load1 & friends. -TEST(AddressSanitizer, LoadStoreCallbacks) { - typedef void (*CB)(uptr p); - CB cb[2][5] = { - { - __asan_load1, __asan_load2, __asan_load4, __asan_load8, __asan_load16, - }, { - __asan_store1, __asan_store2, __asan_store4, __asan_store8, - __asan_store16, - } - }; - +typedef void (*CB)(uptr p); +static void TestLoadStoreCallbacks(CB cb[2][5]) { uptr buggy_ptr; __asan_test_only_reported_buggy_pointer = &buggy_ptr; @@ -271,3 +263,92 @@ } __asan_test_only_reported_buggy_pointer = 0; } + +TEST(AddressSanitizer, LoadStoreCallbacks) { + CB cb[2][5] = {{ + __asan_load1, + __asan_load2, + __asan_load4, + __asan_load8, + __asan_load16, + }, + { + __asan_store1, + __asan_store2, + __asan_store4, + __asan_store8, + __asan_store16, + }}; + TestLoadStoreCallbacks(cb); +} + +// clang-format off +#if defined(__x86_64__) + +#define CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(s, reg, op) \ + void CallAsanMemoryAccessAdd##reg##op##s(uptr address) { \ + asm("push %%" #reg " \n" \ + "mov %[x], %%" #reg " \n" \ + "call __asan_check_" #op "_add_" #s "_" #reg "\n" \ + "pop %%" #reg " \n" \ + : \ + : [x] "r"(address) \ + : "r8", "rdi"); \ + } + +#define TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(reg) \ + CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(1, reg, load) \ + CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(1, reg, store) \ + CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(2, reg, load) \ + CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(2, reg, store) \ + CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(4, reg, load) \ + CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(4, reg, store) \ + CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(8, reg, load) \ + CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(8, reg, store) \ + CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(16, reg, load) \ + CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(16, reg, store) \ + \ + TEST(AddressSanitizer, LoadStoreCallbacksAddX86##reg) { \ + CB cb[2][5] = {{ \ + CallAsanMemoryAccessAdd##reg##load1, \ + CallAsanMemoryAccessAdd##reg##load2, \ + CallAsanMemoryAccessAdd##reg##load4, \ + CallAsanMemoryAccessAdd##reg##load8, \ + CallAsanMemoryAccessAdd##reg##load16, \ + }, \ + { \ + CallAsanMemoryAccessAdd##reg##store1, \ + CallAsanMemoryAccessAdd##reg##store2, \ + CallAsanMemoryAccessAdd##reg##store4, \ + CallAsanMemoryAccessAdd##reg##store8, \ + CallAsanMemoryAccessAdd##reg##store16, \ + }}; \ + TestLoadStoreCallbacks(cb); \ + } + +// 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 callbacks. +TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RAX) +TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RBX) +TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RCX) +TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RDX) +TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RSI) +TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RDI) +TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RBP) +TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R8) +TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R9) +TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R12) +TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R13) +TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R14) +TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R15) + +#endif // defined(__x86_64__) +// clang-format on + +#if defined(SHADOW_OFFSET_CONST) +TEST(AddressSanitizer, TestShadowGlobalVar) { + constexpr u64 shadow_offset = SHADOW_OFFSET_CONST; + EXPECT_EQ(SHADOW_OFFSET, shadow_offset); +} +#endif diff --git a/compiler-rt/test/asan/TestCases/Linux/interface_symbols_linux.cpp b/compiler-rt/test/asan/TestCases/Linux/interface_symbols_linux.cpp --- a/compiler-rt/test/asan/TestCases/Linux/interface_symbols_linux.cpp +++ b/compiler-rt/test/asan/TestCases/Linux/interface_symbols_linux.cpp @@ -1,5 +1,7 @@ // Check the presence of interface symbols in compiled file. +// RUN: %clangxx -x c++-header -o - -E %p/../../../../lib/asan/asan_interface.inc \ +// RUN: | sed "s/INTERFACE_FUNCTION/\nINTERFACE_FUNCTION/g" > %t.asan_interface.inc // RUN: %clangxx_asan -O2 %s -o %t.exe // RUN: nm -D %t.exe | grep " [TWw] " \ // RUN: | grep -o "\(__asan_\|__ubsan_\|__sancov_\|__sanitizer_\)[^ ]*" \ @@ -10,7 +12,7 @@ // RUN: > %t.exports // // RUN: grep -e "INTERFACE_\(WEAK_\)\?FUNCTION" \ -// RUN: %p/../../../../lib/asan/asan_interface.inc \ +// RUN: %t.asan_interface.inc \ // RUN: %p/../../../../lib/ubsan/ubsan_interface.inc \ // RUN: %p/../../../../lib/sanitizer_common/sanitizer_common_interface.inc \ // RUN: %p/../../../../lib/sanitizer_common/sanitizer_common_interface_posix.inc \ diff --git a/llvm/lib/Target/X86/X86AsmPrinter.h b/llvm/lib/Target/X86/X86AsmPrinter.h --- a/llvm/lib/Target/X86/X86AsmPrinter.h +++ b/llvm/lib/Target/X86/X86AsmPrinter.h @@ -100,20 +100,6 @@ // Address sanitizer specific lowering for X86. void LowerASAN_CHECK_MEMACCESS(const MachineInstr &MI); - void emitAsanMemaccessSymbols(Module &M); - void emitAsanMemaccessPartial(Module &M, unsigned Reg, - const ASanAccessInfo &AccessInfo, - MCSubtargetInfo &STI); - void emitAsanMemaccessFull(Module &M, unsigned Reg, - const ASanAccessInfo &AccessInfo, - MCSubtargetInfo &STI); - void emitAsanReportError(Module &M, unsigned Reg, - const ASanAccessInfo &AccessInfo, - MCSubtargetInfo &STI); - - typedef std::tuple - AsanMemaccessTuple; - std::map AsanMemaccessSymbols; // Choose between emitting .seh_ directives and .cv_fpo_ directives. void EmitSEHInstruction(const MachineInstr *MI); diff --git a/llvm/lib/Target/X86/X86AsmPrinter.cpp b/llvm/lib/Target/X86/X86AsmPrinter.cpp --- a/llvm/lib/Target/X86/X86AsmPrinter.cpp +++ b/llvm/lib/Target/X86/X86AsmPrinter.cpp @@ -754,8 +754,6 @@ void X86AsmPrinter::emitEndOfAsmFile(Module &M) { const Triple &TT = TM.getTargetTriple(); - emitAsanMemaccessSymbols(M); - if (TT.isOSBinFormatMachO()) { // Mach-O uses non-lazy symbol stubs to encode per-TU information into // global table for symbol lookup. diff --git a/llvm/lib/Target/X86/X86MCInstLower.cpp b/llvm/lib/Target/X86/X86MCInstLower.cpp --- a/llvm/lib/Target/X86/X86MCInstLower.cpp +++ b/llvm/lib/Target/X86/X86MCInstLower.cpp @@ -48,6 +48,7 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/Transforms/Instrumentation/AddressSanitizer.h" #include "llvm/Transforms/Instrumentation/AddressSanitizerCommon.h" +#include using namespace llvm; @@ -1336,235 +1337,26 @@ return; } - unsigned Reg = MI.getOperand(0).getReg().id(); + const auto &Reg = MI.getOperand(0).getReg(); ASanAccessInfo AccessInfo(MI.getOperand(1).getImm()); - MCSymbol *&Sym = - AsanMemaccessSymbols[AsanMemaccessTuple(Reg, AccessInfo.Packed)]; - if (!Sym) { - std::string Name = AccessInfo.IsWrite ? "store" : "load"; - std::string SymName = "__asan_check_" + Name + - utostr(1ULL << AccessInfo.AccessSizeIndex) + "_rn" + - utostr(Reg); - Sym = OutContext.getOrCreateSymbol(SymName); - } - - EmitAndCountInstruction( - MCInstBuilder(X86::CALL64pcrel32) - .addExpr(MCSymbolRefExpr::create(Sym, OutContext))); -} - -void X86AsmPrinter::emitAsanMemaccessPartial(Module &M, unsigned Reg, - const ASanAccessInfo &AccessInfo, - MCSubtargetInfo &STI) { - assert(AccessInfo.AccessSizeIndex == 0 || AccessInfo.AccessSizeIndex == 1 || - AccessInfo.AccessSizeIndex == 2); - assert(Reg != X86::R10); - assert(Reg != X86::R11); - - uint64_t ShadowBase; - int MappingScale; - bool OrShadowOffset; - getAddressSanitizerParams( - Triple(M.getTargetTriple()), M.getDataLayout().getPointerSizeInBits(), - AccessInfo.CompileKernel, &ShadowBase, &MappingScale, &OrShadowOffset); - - OutStreamer->emitInstruction(MCInstBuilder(X86::MOV64rr) - .addReg(X86::R10) - .addReg(X86::NoRegister + Reg), - STI); - OutStreamer->emitInstruction(MCInstBuilder(X86::SHR64ri) - .addReg(X86::R10) - .addReg(X86::R10) - .addImm(MappingScale), - STI); - if (OrShadowOffset) { - OutStreamer->emitInstruction(MCInstBuilder(X86::OR64ri32) - .addReg(X86::R10) - .addReg(X86::R10) - .addImm(ShadowBase), - STI); - OutStreamer->emitInstruction(MCInstBuilder(X86::MOV8rm) - .addReg(X86::R10B) - .addReg(X86::R10) - .addImm(1) - .addReg(X86::NoRegister) - .addImm(0) - .addReg(X86::NoRegister), - STI); - OutStreamer->emitInstruction( - MCInstBuilder(X86::TEST8rr).addReg(X86::R10B).addReg(X86::R10B), STI); - } else { - OutStreamer->emitInstruction(MCInstBuilder(X86::MOVSX32rm8) - .addReg(X86::R10D) - .addReg(X86::R10) - .addImm(1) - .addReg(X86::NoRegister) - .addImm(ShadowBase) - .addReg(X86::NoRegister), - STI); - OutStreamer->emitInstruction( - MCInstBuilder(X86::TEST32rr).addReg(X86::R10D).addReg(X86::R10D), STI); - } - MCSymbol *AdditionalCheck = OutContext.createTempSymbol(); - OutStreamer->emitInstruction( - MCInstBuilder(X86::JCC_1) - .addExpr(MCSymbolRefExpr::create(AdditionalCheck, OutContext)) - .addImm(X86::COND_NE), - STI); - MCSymbol *ReturnSym = OutContext.createTempSymbol(); - OutStreamer->emitLabel(ReturnSym); - OutStreamer->emitInstruction(MCInstBuilder(getRetOpcode(*Subtarget)), STI); - - // Shadow byte is non-zero so we need to perform additional checks. - OutStreamer->emitLabel(AdditionalCheck); - OutStreamer->emitInstruction(MCInstBuilder(X86::MOV64rr) - .addReg(X86::R11) - .addReg(X86::NoRegister + Reg), - STI); - const size_t Granularity = 1ULL << MappingScale; - OutStreamer->emitInstruction(MCInstBuilder(X86::AND32ri8) - .addReg(X86::NoRegister) - .addReg(X86::R11D) - .addImm(Granularity - 1), - STI); - if (AccessInfo.AccessSizeIndex == 1) { - OutStreamer->emitInstruction(MCInstBuilder(X86::ADD32ri8) - .addReg(X86::NoRegister) - .addReg(X86::R11D) - .addImm(1), - STI); - } else if (AccessInfo.AccessSizeIndex == 2) { - OutStreamer->emitInstruction(MCInstBuilder(X86::ADD32ri8) - .addReg(X86::NoRegister) - .addReg(X86::R11D) - .addImm(3), - STI); - } - - OutStreamer->emitInstruction( - MCInstBuilder(X86::CMP32rr).addReg(X86::R11D).addReg(X86::R10D).addImm(1), - STI); - OutStreamer->emitInstruction( - MCInstBuilder(X86::JCC_1) - .addExpr(MCSymbolRefExpr::create(ReturnSym, OutContext)) - .addImm(X86::COND_L), - STI); - - emitAsanReportError(M, Reg, AccessInfo, STI); -} - -void X86AsmPrinter::emitAsanMemaccessFull(Module &M, unsigned Reg, - const ASanAccessInfo &AccessInfo, - MCSubtargetInfo &STI) { - assert(AccessInfo.AccessSizeIndex == 3 || AccessInfo.AccessSizeIndex == 4); - assert(Reg != X86::R10); - assert(Reg != X86::R11); - uint64_t ShadowBase; int MappingScale; bool OrShadowOffset; - getAddressSanitizerParams( - Triple(M.getTargetTriple()), M.getDataLayout().getPointerSizeInBits(), - AccessInfo.CompileKernel, &ShadowBase, &MappingScale, &OrShadowOffset); - - OutStreamer->emitInstruction(MCInstBuilder(X86::MOV64rr) - .addReg(X86::R10) - .addReg(X86::NoRegister + Reg), - STI); - OutStreamer->emitInstruction(MCInstBuilder(X86::SHR64ri) - .addReg(X86::R10) - .addReg(X86::R10) - .addImm(MappingScale), - STI); - if (OrShadowOffset) { - OutStreamer->emitInstruction(MCInstBuilder(X86::OR64ri32) - .addReg(X86::R10) - .addReg(X86::R10) - .addImm(ShadowBase), - STI); - auto OpCode = AccessInfo.AccessSizeIndex == 3 ? X86::CMP8mi : X86::CMP16mi8; - OutStreamer->emitInstruction(MCInstBuilder(OpCode) - .addReg(X86::R10) - .addImm(1) - .addReg(X86::NoRegister) - .addImm(0) - .addReg(X86::NoRegister) - .addImm(0), - STI); - } else { - auto OpCode = AccessInfo.AccessSizeIndex == 3 ? X86::CMP8mi : X86::CMP16mi8; - OutStreamer->emitInstruction(MCInstBuilder(OpCode) - .addReg(X86::R10) - .addImm(1) - .addReg(X86::NoRegister) - .addImm(ShadowBase) - .addReg(X86::NoRegister) - .addImm(0), - STI); - } - MCSymbol *ReportCode = OutContext.createTempSymbol(); - OutStreamer->emitInstruction( - MCInstBuilder(X86::JCC_1) - .addExpr(MCSymbolRefExpr::create(ReportCode, OutContext)) - .addImm(X86::COND_NE), - STI); - MCSymbol *ReturnSym = OutContext.createTempSymbol(); - OutStreamer->emitLabel(ReturnSym); - OutStreamer->emitInstruction(MCInstBuilder(getRetOpcode(*Subtarget)), STI); - - OutStreamer->emitLabel(ReportCode); - emitAsanReportError(M, Reg, AccessInfo, STI); -} + getAddressSanitizerParams(Triple(TM.getTargetTriple()), 64, + AccessInfo.CompileKernel, &ShadowBase, + &MappingScale, &OrShadowOffset); -void X86AsmPrinter::emitAsanReportError(Module &M, unsigned Reg, - const ASanAccessInfo &AccessInfo, - MCSubtargetInfo &STI) { std::string Name = AccessInfo.IsWrite ? "store" : "load"; - MCSymbol *ReportError = OutContext.getOrCreateSymbol( - "__asan_report_" + Name + utostr(1ULL << AccessInfo.AccessSizeIndex)); - OutStreamer->emitInstruction(MCInstBuilder(X86::MOV64rr) - .addReg(X86::RDI) - .addReg(X86::NoRegister + Reg), - STI); - OutStreamer->emitInstruction( - MCInstBuilder(X86::JMP_4) - .addExpr(MCSymbolRefExpr::create(ReportError, MCSymbolRefExpr::VK_PLT, - OutContext)), - STI); -} + std::string Op = OrShadowOffset ? "or" : "add"; + std::string SymName = "__asan_check_" + Name + "_" + Op + "_" + + utostr(1ULL << AccessInfo.AccessSizeIndex) + "_" + + TM.getMCRegisterInfo()->getName(Reg.asMCReg()); -void X86AsmPrinter::emitAsanMemaccessSymbols(Module &M) { - if (AsanMemaccessSymbols.empty()) - return; - - const Triple &TT = TM.getTargetTriple(); - assert(TT.isOSBinFormatELF()); - std::unique_ptr STI( - TM.getTarget().createMCSubtargetInfo(TT.str(), "", "")); - assert(STI && "Unable to create subtarget info"); - - for (auto &P : AsanMemaccessSymbols) { - MCSymbol *Sym = P.second; - OutStreamer->SwitchSection(OutContext.getELFSection( - ".text.hot", ELF::SHT_PROGBITS, - ELF::SHF_EXECINSTR | ELF::SHF_ALLOC | ELF::SHF_GROUP, 0, Sym->getName(), - /*IsComdat=*/true)); - - OutStreamer->emitSymbolAttribute(Sym, MCSA_ELF_TypeFunction); - OutStreamer->emitSymbolAttribute(Sym, MCSA_Weak); - OutStreamer->emitSymbolAttribute(Sym, MCSA_Hidden); - OutStreamer->emitLabel(Sym); - - unsigned Reg = std::get<0>(P.first); - ASanAccessInfo AccessInfo(std::get<1>(P.first)); - - if (AccessInfo.AccessSizeIndex < 3) { - emitAsanMemaccessPartial(M, Reg, AccessInfo, *STI); - } else { - emitAsanMemaccessFull(M, Reg, AccessInfo, *STI); - } - } + EmitAndCountInstruction( + MCInstBuilder(X86::CALL64pcrel32) + .addExpr(MCSymbolRefExpr::create( + OutContext.getOrCreateSymbol(SymName), OutContext))); } void X86AsmPrinter::LowerPATCHABLE_OP(const MachineInstr &MI, diff --git a/llvm/test/CodeGen/X86/asan-check-memaccess-add.ll b/llvm/test/CodeGen/X86/asan-check-memaccess-add.ll --- a/llvm/test/CodeGen/X86/asan-check-memaccess-add.ll +++ b/llvm/test/CodeGen/X86/asan-check-memaccess-add.ll @@ -5,8 +5,8 @@ define void @load1(i8* nocapture readonly %x) { ; CHECK: pushq %rax ; CHECK-NOT: push %rbp -; CHECK: callq __asan_check_load1_rn[[RN1:.*]] -; CHECK: callq __asan_check_store1_rn[[RN1]] +; CHECK: callq __asan_check_load_add_1_[[REG1:.*]] +; CHECK: callq __asan_check_store_add_1_[[REG1]] ; CHECK-NOT: pop %rbp ; CHECK: popq %rax call void @llvm.asan.check.memaccess(i8* %x, i32 0) @@ -17,8 +17,8 @@ define void @load2(i16* nocapture readonly %x) { ; CHECK: pushq %rax ; CHECK-NOT: push %rbp -; CHECK: callq __asan_check_load2_rn[[RN2:.*]] -; CHECK: callq __asan_check_store2_rn[[RN2]] +; CHECK: callq __asan_check_load_add_2_[[REG2:.*]] +; CHECK: callq __asan_check_store_add_2_[[REG2]] ; CHECK-NOT: pop %rbp ; CHECK: popq %rax %1 = ptrtoint i16* %x to i64 @@ -31,8 +31,8 @@ define void @load4(i32* nocapture readonly %x) { ; CHECK: pushq %rax ; CHECK-NOT: push %rbp -; CHECK: callq __asan_check_load4_rn[[RN4:.*]] -; CHECK: callq __asan_check_store4_rn[[RN4]] +; CHECK: callq __asan_check_load_add_4_[[REG4:.*]] +; CHECK: callq __asan_check_store_add_4_[[REG4]] ; CHECK-NOT: pop %rbp ; CHECK: popq %rax %1 = ptrtoint i32* %x to i64 @@ -44,8 +44,8 @@ define void @load8(i64* nocapture readonly %x) { ; CHECK: pushq %rax ; CHECK-NOT: push %rbp -; CHECK: callq __asan_check_load8_rn[[RN8:.*]] -; CHECK: callq __asan_check_store8_rn[[RN8]] +; CHECK: callq __asan_check_load_add_8_[[REG8:.*]] +; CHECK: callq __asan_check_store_add_8_[[REG8]] ; CHECK-NOT: pop %rbp ; CHECK: popq %rax %1 = ptrtoint i64* %x to i64 @@ -58,8 +58,8 @@ define void @load16(i128* nocapture readonly %x) { ; CHECK: pushq %rax ; CHECK-NOT: push %rbp -; CHECK: callq __asan_check_load16_rn[[RN16:.*]] -; CHECK: callq __asan_check_store16_rn[[RN16]] +; CHECK: callq __asan_check_load_add_16_[[REG16:.*]] +; CHECK: callq __asan_check_store_add_16_[[REG16]] ; CHECK-NOT: pop %rbp ; CHECK: popq %rax %1 = ptrtoint i128* %x to i64 @@ -69,178 +69,4 @@ ret void } -; CHECK: .type __asan_check_load1_rn[[RN1]],@function -; CHECK-NEXT: .weak __asan_check_load1_rn[[RN1]] -; CHECK-NEXT: .hidden __asan_check_load1_rn[[RN1]] -; CHECK-NEXT: __asan_check_load1_rn[[RN1]]: -; CHECK-NEXT: movq [[REG:.*]], %r10 -; CHECK-NEXT: shrq $3, %r10 -; CHECK-NEXT: movsbl 2147450880(%r10), %r10d -; CHECK-NEXT: testl %r10d, %r10d -; CHECK-NEXT: jne [[EXTRA:.*]] -; CHECK-NEXT: [[RET:.*]]: -; CHECK-NEXT: retq -; CHECK-NEXT: [[EXTRA]]: -; CHECK-NEXT: movq [[REG]], %r11 -; CHECK-NEXT: andl $7, %r11d -; CHECK-NEXT: cmpl %r10d, %r11d -; CHECK-NEXT: jl [[RET]] -; CHECK-NEXT: movq [[REG:.*]], %rdi -; CHECK-NEXT: jmp __asan_report_load1 - -; CHECK: .type __asan_check_load2_rn[[RN2]],@function -; CHECK-NEXT: .weak __asan_check_load2_rn[[RN2]] -; CHECK-NEXT: .hidden __asan_check_load2_rn[[RN2]] -; CHECK-NEXT: __asan_check_load2_rn[[RN2]]: -; CHECK-NEXT: movq [[REG:.*]], %r10 -; CHECK-NEXT: shrq $3, %r10 -; CHECK-NEXT: movsbl 2147450880(%r10), %r10d -; CHECK-NEXT: testl %r10d, %r10d -; CHECK-NEXT: jne [[EXTRA:.*]] -; CHECK-NEXT: [[RET:.*]]: -; CHECK-NEXT: retq -; CHECK-NEXT: [[EXTRA]]: -; CHECK-NEXT: movq [[REG]], %r11 -; CHECK-NEXT: andl $7, %r11d -; CHECK-NEXT: addl $1, %r11d -; CHECK-NEXT: cmpl %r10d, %r11d -; CHECK-NEXT: jl [[RET]] -; CHECK-NEXT: movq [[REG:.*]], %rdi -; CHECK-NEXT: jmp __asan_report_load2 - -; CHECK: .type __asan_check_load4_rn[[RN4]],@function -; CHECK-NEXT: .weak __asan_check_load4_rn[[RN4]] -; CHECK-NEXT: .hidden __asan_check_load4_rn[[RN4]] -; CHECK-NEXT: __asan_check_load4_rn[[RN4]]: -; CHECK-NEXT: movq [[REG:.*]], %r10 -; CHECK-NEXT: shrq $3, %r10 -; CHECK-NEXT: movsbl 2147450880(%r10), %r10d -; CHECK-NEXT: testl %r10d, %r10d -; CHECK-NEXT: jne [[EXTRA:.*]] -; CHECK-NEXT: [[RET:.*]]: -; CHECK-NEXT: retq -; CHECK-NEXT: [[EXTRA]]: -; CHECK-NEXT: movq [[REG]], %r11 -; CHECK-NEXT: andl $7, %r11d -; CHECK-NEXT: addl $3, %r11d -; CHECK-NEXT: cmpl %r10d, %r11d -; CHECK-NEXT: jl [[RET]] -; CHECK-NEXT: movq [[REG:.*]], %rdi -; CHECK-NEXT: jmp __asan_report_load4 - -; CHECK: .type __asan_check_load8_rn[[RN8]],@function -; CHECK-NEXT: .weak __asan_check_load8_rn[[RN8]] -; CHECK-NEXT: .hidden __asan_check_load8_rn[[RN8]] -; CHECK-NEXT: __asan_check_load8_rn[[RN8]]: -; CHECK-NEXT: movq [[REG:.*]], %r10 -; CHECK-NEXT: shrq $3, %r10 -; CHECK-NEXT: cmpb $0, 2147450880(%r10) -; CHECK-NEXT: jne [[FAIL:.*]] -; CHECK-NEXT: [[RET:.*]]: -; CHECK-NEXT: retq -; CHECK-NEXT: [[FAIL]]: -; CHECK-NEXT: movq [[REG:.*]], %rdi -; CHECK-NEXT: jmp __asan_report_load8 - -; CHECK: .type __asan_check_load16_rn[[RN16]],@function -; CHECK-NEXT: .weak __asan_check_load16_rn[[RN16]] -; CHECK-NEXT: .hidden __asan_check_load16_rn[[RN16]] -; CHECK-NEXT: __asan_check_load16_rn[[RN16]]: -; CHECK-NEXT: movq [[REG:.*]], %r10 -; CHECK-NEXT: shrq $3, %r10 -; CHECK-NEXT: cmpw $0, 2147450880(%r10) -; CHECK-NEXT: jne [[FAIL:.*]] -; CHECK-NEXT: [[RET:.*]]: -; CHECK-NEXT: retq -; CHECK-NEXT: [[FAIL]]: -; CHECK-NEXT: movq [[REG:.*]], %rdi -; CHECK-NEXT: jmp __asan_report_load16 - -; CHECK: .type __asan_check_store1_rn[[RN1]],@function -; CHECK-NEXT: .weak __asan_check_store1_rn[[RN1]] -; CHECK-NEXT: .hidden __asan_check_store1_rn[[RN1]] -; CHECK-NEXT: __asan_check_store1_rn[[RN1]]: -; CHECK-NEXT: movq [[REG:.*]], %r10 -; CHECK-NEXT: shrq $3, %r10 -; CHECK-NEXT: movsbl 2147450880(%r10), %r10d -; CHECK-NEXT: testl %r10d, %r10d -; CHECK-NEXT: jne [[EXTRA:.*]] -; CHECK-NEXT: [[RET:.*]]: -; CHECK-NEXT: retq -; CHECK-NEXT: [[EXTRA]]: -; CHECK-NEXT: movq [[REG]], %r11 -; CHECK-NEXT: andl $7, %r11d -; CHECK-NEXT: cmpl %r10d, %r11d -; CHECK-NEXT: jl [[RET]] -; CHECK-NEXT: movq [[REG:.*]], %rdi -; CHECK-NEXT: jmp __asan_report_store1@PLT - -; CHECK: .type __asan_check_store2_rn[[RN2]],@function -; CHECK-NEXT: .weak __asan_check_store2_rn[[RN2]] -; CHECK-NEXT: .hidden __asan_check_store2_rn[[RN2]] -; CHECK-NEXT: __asan_check_store2_rn[[RN2]]: -; CHECK-NEXT: movq [[REG:.*]], %r10 -; CHECK-NEXT: shrq $3, %r10 -; CHECK-NEXT: movsbl 2147450880(%r10), %r10d -; CHECK-NEXT: testl %r10d, %r10d -; CHECK-NEXT: jne [[EXTRA:.*]] -; CHECK-NEXT: [[RET:.*]]: -; CHECK-NEXT: retq -; CHECK-NEXT: [[EXTRA]]: -; CHECK-NEXT: movq [[REG]], %r11 -; CHECK-NEXT: andl $7, %r11d -; CHECK-NEXT: addl $1, %r11d -; CHECK-NEXT: cmpl %r10d, %r11d -; CHECK-NEXT: jl [[RET]] -; CHECK-NEXT: movq [[REG:.*]], %rdi -; CHECK-NEXT: jmp __asan_report_store2@PLT - -; CHECK: .type __asan_check_store4_rn[[RN4]],@function -; CHECK-NEXT: .weak __asan_check_store4_rn[[RN4]] -; CHECK-NEXT: .hidden __asan_check_store4_rn[[RN4]] -; CHECK-NEXT: __asan_check_store4_rn[[RN4]]: -; CHECK-NEXT: movq [[REG:.*]], %r10 -; CHECK-NEXT: shrq $3, %r10 -; CHECK-NEXT: movsbl 2147450880(%r10), %r10d -; CHECK-NEXT: testl %r10d, %r10d -; CHECK-NEXT: jne [[EXTRA:.*]] -; CHECK-NEXT: [[RET:.*]]: -; CHECK-NEXT: retq -; CHECK-NEXT: [[EXTRA]]: -; CHECK-NEXT: movq [[REG]], %r11 -; CHECK-NEXT: andl $7, %r11d -; CHECK-NEXT: addl $3, %r11d -; CHECK-NEXT: cmpl %r10d, %r11d -; CHECK-NEXT: jl [[RET]] -; CHECK-NEXT: movq [[REG:.*]], %rdi -; CHECK-NEXT: jmp __asan_report_store4@PLT - -; CHECK: .type __asan_check_store8_rn[[RN8]],@function -; CHECK-NEXT: .weak __asan_check_store8_rn[[RN8]] -; CHECK-NEXT: .hidden __asan_check_store8_rn[[RN8]] -; CHECK-NEXT: __asan_check_store8_rn[[RN8]]: -; CHECK-NEXT: movq [[REG:.*]], %r10 -; CHECK-NEXT: shrq $3, %r10 -; CHECK-NEXT: cmpb $0, 2147450880(%r10) -; CHECK-NEXT: jne [[FAIL:.*]] -; CHECK-NEXT: [[RET:.*]]: -; CHECK-NEXT: retq -; CHECK-NEXT: [[FAIL]]: -; CHECK-NEXT: movq [[REG:.*]], %rdi -; CHECK-NEXT: jmp __asan_report_store8@PLT - -; CHECK: .type __asan_check_store16_rn[[RN16]],@function -; CHECK-NEXT: .weak __asan_check_store16_rn[[RN16]] -; CHECK-NEXT: .hidden __asan_check_store16_rn[[RN16]] -; CHECK-NEXT: __asan_check_store16_rn[[RN16]]: -; CHECK-NEXT: movq [[REG:.*]], %r10 -; CHECK-NEXT: shrq $3, %r10 -; CHECK-NEXT: cmpw $0, 2147450880(%r10) -; CHECK-NEXT: jne [[FAIL:.*]] -; CHECK-NEXT: [[RET:.*]]: -; CHECK-NEXT: retq -; CHECK-NEXT: [[FAIL]]: -; CHECK-NEXT: movq [[REG:.*]], %rdi -; CHECK-NEXT: jmp __asan_report_store16@PLT - declare void @llvm.asan.check.memaccess(i8*, i32 immarg) diff --git a/llvm/test/CodeGen/X86/asan-check-memaccess-or.ll b/llvm/test/CodeGen/X86/asan-check-memaccess-or.ll --- a/llvm/test/CodeGen/X86/asan-check-memaccess-or.ll +++ b/llvm/test/CodeGen/X86/asan-check-memaccess-or.ll @@ -5,8 +5,8 @@ define void @load1(i8* nocapture readonly %x) { ; CHECK: pushq %rax ; CHECK-NOT: push %rbp -; CHECK: callq __asan_check_load1_rn[[RN1:.*]] -; CHECK: callq __asan_check_store1_rn[[RN1]] +; CHECK: callq __asan_check_load_or_1_[[REG1:.*]] +; CHECK: callq __asan_check_store_or_1_[[REG1]] ; CHECK-NOT: pop %rbp ; CHECK: popq %rax call void @llvm.asan.check.memaccess(i8* %x, i32 0) @@ -17,8 +17,8 @@ define void @load2(i16* nocapture readonly %x) { ; CHECK: pushq %rax ; CHECK-NOT: push %rbp -; CHECK: callq __asan_check_load2_rn[[RN2:.*]] -; CHECK: callq __asan_check_store2_rn[[RN2]] +; CHECK: callq __asan_check_load_or_2_[[REG2:.*]] +; CHECK: callq __asan_check_store_or_2_[[REG2]] ; CHECK-NOT: pop %rbp ; CHECK: popq %rax %1 = ptrtoint i16* %x to i64 @@ -31,8 +31,8 @@ define void @load4(i32* nocapture readonly %x) { ; CHECK: pushq %rax ; CHECK-NOT: push %rbp -; CHECK: callq __asan_check_load4_rn[[RN4:.*]] -; CHECK: callq __asan_check_store4_rn[[RN4]] +; CHECK: callq __asan_check_load_or_4_[[REG4:.*]] +; CHECK: callq __asan_check_store_or_4_[[REG4]] ; CHECK-NOT: pop %rbp ; CHECK: popq %rax %1 = ptrtoint i32* %x to i64 @@ -44,8 +44,8 @@ define void @load8(i64* nocapture readonly %x) { ; CHECK: pushq %rax ; CHECK-NOT: push %rbp -; CHECK: callq __asan_check_load8_rn[[RN8:.*]] -; CHECK: callq __asan_check_store8_rn[[RN8]] +; CHECK: callq __asan_check_load_or_8_[[REG8:.*]] +; CHECK: callq __asan_check_store_or_8_[[REG8]] ; CHECK-NOT: pop %rbp ; CHECK: popq %rax %1 = ptrtoint i64* %x to i64 @@ -58,8 +58,8 @@ define void @load16(i128* nocapture readonly %x) { ; CHECK: pushq %rax ; CHECK-NOT: push %rbp -; CHECK: callq __asan_check_load16_rn[[RN16:.*]] -; CHECK: callq __asan_check_store16_rn[[RN16]] +; CHECK: callq __asan_check_load_or_16_[[REG16:.*]] +; CHECK: callq __asan_check_store_or_16_[[REG16]] ; CHECK-NOT: pop %rbp ; CHECK: popq %rax %1 = ptrtoint i128* %x to i64 @@ -69,188 +69,4 @@ ret void } -; CHECK: .type __asan_check_load1_rn[[RN1]],@function -; CHECK-NEXT: .weak __asan_check_load1_rn[[RN1]] -; CHECK-NEXT: .hidden __asan_check_load1_rn[[RN1]] -; CHECK-NEXT: __asan_check_load1_rn[[RN1]]: -; CHECK-NEXT: movq [[REG:.*]], %r10 -; CHECK-NEXT: shrq $3, %r10 -; CHECK-NEXT: orq $17592186044416, %r10{{.*}} -; CHECK-NEXT: movb (%r10), %r10b -; CHECK-NEXT: testb %r10b, %r10b -; CHECK-NEXT: jne [[EXTRA:.*]] -; CHECK-NEXT: [[RET:.*]]: -; CHECK-NEXT: retq -; CHECK-NEXT: [[EXTRA]]: -; CHECK-NEXT: movq [[REG]], %r11 -; CHECK-NEXT: andl $7, %r11d -; CHECK-NEXT: cmpl %r10d, %r11d -; CHECK-NEXT: jl [[RET]] -; CHECK-NEXT: movq [[REG:.*]], %rdi -; CHECK-NEXT: jmp __asan_report_load1 - -; CHECK: .type __asan_check_load2_rn[[RN2]],@function -; CHECK-NEXT: .weak __asan_check_load2_rn[[RN2]] -; CHECK-NEXT: .hidden __asan_check_load2_rn[[RN2]] -; CHECK-NEXT: __asan_check_load2_rn[[RN2]]: -; CHECK-NEXT: movq [[REG:.*]], %r10 -; CHECK-NEXT: shrq $3, %r10 -; CHECK-NEXT: orq $17592186044416, %r10{{.*}} -; CHECK-NEXT: movb (%r10), %r10b -; CHECK-NEXT: testb %r10b, %r10b -; CHECK-NEXT: jne [[EXTRA:.*]] -; CHECK-NEXT: [[RET:.*]]: -; CHECK-NEXT: retq -; CHECK-NEXT: [[EXTRA]]: -; CHECK-NEXT: movq [[REG]], %r11 -; CHECK-NEXT: andl $7, %r11d -; CHECK-NEXT: addl $1, %r11d -; CHECK-NEXT: cmpl %r10d, %r11d -; CHECK-NEXT: jl [[RET]] -; CHECK-NEXT: movq [[REG:.*]], %rdi -; CHECK-NEXT: jmp __asan_report_load2 - -; CHECK: .type __asan_check_load4_rn[[RN4]],@function -; CHECK-NEXT: .weak __asan_check_load4_rn[[RN4]] -; CHECK-NEXT: .hidden __asan_check_load4_rn[[RN4]] -; CHECK-NEXT: __asan_check_load4_rn[[RN4]]: -; CHECK-NEXT: movq [[REG:.*]], %r10 -; CHECK-NEXT: shrq $3, %r10 -; CHECK-NEXT: orq $17592186044416, %r10{{.*}} -; CHECK-NEXT: movb (%r10), %r10b -; CHECK-NEXT: testb %r10b, %r10b -; CHECK-NEXT: jne [[EXTRA:.*]] -; CHECK-NEXT: [[RET:.*]]: -; CHECK-NEXT: retq -; CHECK-NEXT: [[EXTRA]]: -; CHECK-NEXT: movq [[REG]], %r11 -; CHECK-NEXT: andl $7, %r11d -; CHECK-NEXT: addl $3, %r11d -; CHECK-NEXT: cmpl %r10d, %r11d -; CHECK-NEXT: jl [[RET]] -; CHECK-NEXT: movq [[REG:.*]], %rdi -; CHECK-NEXT: jmp __asan_report_load4 - -; CHECK: .type __asan_check_load8_rn[[RN8]],@function -; CHECK-NEXT: .weak __asan_check_load8_rn[[RN8]] -; CHECK-NEXT: .hidden __asan_check_load8_rn[[RN8]] -; CHECK-NEXT: __asan_check_load8_rn[[RN8]]: -; CHECK-NEXT: movq [[REG:.*]], %r10 -; CHECK-NEXT: shrq $3, %r10 -; CHECK-NEXT: orq $17592186044416, %r10{{.*}} -; CHECK-NEXT: cmpb $0, (%r10) -; CHECK-NEXT: jne [[FAIL:.*]] -; CHECK-NEXT: [[RET:.*]]: -; CHECK-NEXT: retq -; CHECK-NEXT: [[FAIL]]: -; CHECK-NEXT: movq [[REG:.*]], %rdi -; CHECK-NEXT: jmp __asan_report_load8 - -; CHECK: .type __asan_check_load16_rn[[RN16]],@function -; CHECK-NEXT: .weak __asan_check_load16_rn[[RN16]] -; CHECK-NEXT: .hidden __asan_check_load16_rn[[RN16]] -; CHECK-NEXT: __asan_check_load16_rn[[RN16]]: -; CHECK-NEXT: movq [[REG:.*]], %r10 -; CHECK-NEXT: shrq $3, %r10 -; CHECK-NEXT: orq $17592186044416, %r10{{.*}} -; CHECK-NEXT: cmpw $0, (%r10) -; CHECK-NEXT: jne [[FAIL:.*]] -; CHECK-NEXT: [[RET:.*]]: -; CHECK-NEXT: retq -; CHECK-NEXT: [[FAIL]]: -; CHECK-NEXT: movq [[REG:.*]], %rdi -; CHECK-NEXT: jmp __asan_report_load16 - -; CHECK: .type __asan_check_store1_rn[[RN1]],@function -; CHECK-NEXT: .weak __asan_check_store1_rn[[RN1]] -; CHECK-NEXT: .hidden __asan_check_store1_rn[[RN1]] -; CHECK-NEXT: __asan_check_store1_rn[[RN1]]: -; CHECK-NEXT: movq [[REG:.*]], %r10 -; CHECK-NEXT: shrq $3, %r10 -; CHECK-NEXT: orq $17592186044416, %r10 -; CHECK-NEXT: movb (%r10), %r10b -; CHECK-NEXT: testb %r10b, %r10b -; CHECK-NEXT: jne [[EXTRA:.*]] -; CHECK-NEXT: [[RET:.*]]: -; CHECK-NEXT: retq -; CHECK-NEXT: [[EXTRA]]: -; CHECK-NEXT: movq [[REG]], %r11 -; CHECK-NEXT: andl $7, %r11d -; CHECK-NEXT: cmpl %r10d, %r11d -; CHECK-NEXT: jl [[RET]] -; CHECK-NEXT: movq [[REG:.*]], %rdi -; CHECK-NEXT: jmp __asan_report_store1@PLT - -; CHECK: .type __asan_check_store2_rn[[RN2]],@function -; CHECK-NEXT: .weak __asan_check_store2_rn[[RN2]] -; CHECK-NEXT: .hidden __asan_check_store2_rn[[RN2]] -; CHECK-NEXT: __asan_check_store2_rn[[RN2]]: -; CHECK-NEXT: movq [[REG:.*]], %r10 -; CHECK-NEXT: shrq $3, %r10 -; CHECK-NEXT: orq $17592186044416, %r10 -; CHECK-NEXT: movb (%r10), %r10b -; CHECK-NEXT: testb %r10b, %r10b -; CHECK-NEXT: jne [[EXTRA:.*]] -; CHECK-NEXT: [[RET:.*]]: -; CHECK-NEXT: retq -; CHECK-NEXT: [[EXTRA]]: -; CHECK-NEXT: movq [[REG]], %r11 -; CHECK-NEXT: andl $7, %r11d -; CHECK-NEXT: addl $1, %r11d -; CHECK-NEXT: cmpl %r10d, %r11d -; CHECK-NEXT: jl [[RET]] -; CHECK-NEXT: movq [[REG:.*]], %rdi -; CHECK-NEXT: jmp __asan_report_store2@PLT - -; CHECK: .type __asan_check_store4_rn[[RN4]],@function -; CHECK-NEXT: .weak __asan_check_store4_rn[[RN4]] -; CHECK-NEXT: .hidden __asan_check_store4_rn[[RN4]] -; CHECK-NEXT: __asan_check_store4_rn[[RN4]]: -; CHECK-NEXT: movq [[REG:.*]], %r10 -; CHECK-NEXT: shrq $3, %r10 -; CHECK-NEXT: orq $17592186044416, %r10 -; CHECK-NEXT: movb (%r10), %r10b -; CHECK-NEXT: testb %r10b, %r10b -; CHECK-NEXT: jne [[EXTRA:.*]] -; CHECK-NEXT: [[RET:.*]]: -; CHECK-NEXT: retq -; CHECK-NEXT: [[EXTRA]]: -; CHECK-NEXT: movq [[REG]], %r11 -; CHECK-NEXT: andl $7, %r11d -; CHECK-NEXT: addl $3, %r11d -; CHECK-NEXT: cmpl %r10d, %r11d -; CHECK-NEXT: jl [[RET]] -; CHECK-NEXT: movq [[REG:.*]], %rdi -; CHECK-NEXT: jmp __asan_report_store4@PLT - -; CHECK: .type __asan_check_store8_rn[[RN8]],@function -; CHECK-NEXT: .weak __asan_check_store8_rn[[RN8]] -; CHECK-NEXT: .hidden __asan_check_store8_rn[[RN8]] -; CHECK-NEXT: __asan_check_store8_rn[[RN8]]: -; CHECK-NEXT: movq [[REG:.*]], %r10 -; CHECK-NEXT: shrq $3, %r10 -; CHECK-NEXT: orq $17592186044416, %r10{{.*}} -; CHECK-NEXT: cmpb $0, (%r10) -; CHECK-NEXT: jne [[FAIL:.*]] -; CHECK-NEXT: [[RET:.*]]: -; CHECK-NEXT: retq -; CHECK-NEXT: [[FAIL]]: -; CHECK-NEXT: movq [[REG:.*]], %rdi -; CHECK-NEXT: jmp __asan_report_store8@PLT - -; CHECK: .type __asan_check_store16_rn[[RN16]],@function -; CHECK-NEXT: .weak __asan_check_store16_rn[[RN16]] -; CHECK-NEXT: .hidden __asan_check_store16_rn[[RN16]] -; CHECK-NEXT: __asan_check_store16_rn[[RN16]]: -; CHECK-NEXT: movq [[REG:.*]], %r10 -; CHECK-NEXT: shrq $3, %r10 -; CHECK-NEXT: orq $17592186044416, %r10{{.*}} -; CHECK-NEXT: cmpw $0, (%r10) -; CHECK-NEXT: jne [[FAIL:.*]] -; CHECK-NEXT: [[RET:.*]]: -; CHECK-NEXT: retq -; CHECK-NEXT: [[FAIL]]: -; CHECK-NEXT: movq [[REG:.*]], %rdi -; CHECK-NEXT: jmp __asan_report_store16@PLT - declare void @llvm.asan.check.memaccess(i8*, i32 immarg)