asan_mapping.h revision 251034
197403Sobrien//===-- asan_mapping.h ------------------------------------------*- C++ -*-===// 297403Sobrien// 3169691Skan// The LLVM Compiler Infrastructure 4169691Skan// 597403Sobrien// This file is distributed under the University of Illinois Open Source 697403Sobrien// License. See LICENSE.TXT for details. 797403Sobrien// 897403Sobrien//===----------------------------------------------------------------------===// 997403Sobrien// 1097403Sobrien// This file is a part of AddressSanitizer, an address sanity checker. 1197403Sobrien// 1297403Sobrien// Defines ASan memory mapping. 1397403Sobrien//===----------------------------------------------------------------------===// 1497403Sobrien#ifndef ASAN_MAPPING_H 1597403Sobrien#define ASAN_MAPPING_H 1697403Sobrien 1797403Sobrien#include "asan_internal.h" 1897403Sobrien 19169691Skan// The full explanation of the memory mapping could be found here: 2097403Sobrien// http://code.google.com/p/address-sanitizer/wiki/AddressSanitizerAlgorithm 2197403Sobrien// 2297403Sobrien// Typical shadow mapping on Linux/x86_64 with SHADOW_OFFSET == 0x00007fff8000: 2397403Sobrien// || `[0x10007fff8000, 0x7fffffffffff]` || HighMem || 2497403Sobrien// || `[0x02008fff7000, 0x10007fff7fff]` || HighShadow || 2597403Sobrien// || `[0x00008fff7000, 0x02008fff6fff]` || ShadowGap || 2697403Sobrien// || `[0x00007fff8000, 0x00008fff6fff]` || LowShadow || 2797403Sobrien// || `[0x000000000000, 0x00007fff7fff]` || LowMem || 2897403Sobrien// 2997403Sobrien// When SHADOW_OFFSET is zero (-pie): 3097403Sobrien// || `[0x100000000000, 0x7fffffffffff]` || HighMem || 3197403Sobrien// || `[0x020000000000, 0x0fffffffffff]` || HighShadow || 3297403Sobrien// || `[0x000000040000, 0x01ffffffffff]` || ShadowGap || 3397403Sobrien// 3497403Sobrien// Special case when something is already mapped between 3597403Sobrien// 0x003000000000 and 0x005000000000 (e.g. when prelink is installed): 3697403Sobrien// || `[0x10007fff8000, 0x7fffffffffff]` || HighMem || 3797403Sobrien// || `[0x02008fff7000, 0x10007fff7fff]` || HighShadow || 3897403Sobrien// || `[0x005000000000, 0x02008fff6fff]` || ShadowGap3 || 3997403Sobrien// || `[0x003000000000, 0x004fffffffff]` || MidMem || 4097403Sobrien// || `[0x000a7fff8000, 0x002fffffffff]` || ShadowGap2 || 4197403Sobrien// || `[0x00067fff8000, 0x000a7fff7fff]` || MidShadow || 4297403Sobrien// || `[0x00008fff7000, 0x00067fff7fff]` || ShadowGap || 4397403Sobrien// || `[0x00007fff8000, 0x00008fff6fff]` || LowShadow || 44169691Skan// || `[0x000000000000, 0x00007fff7fff]` || LowMem || 45169691Skan// 4697403Sobrien// Default Linux/i386 mapping: 4797403Sobrien// || `[0x40000000, 0xffffffff]` || HighMem || 48132720Skan// || `[0x28000000, 0x3fffffff]` || HighShadow || 49132720Skan// || `[0x24000000, 0x27ffffff]` || ShadowGap || 5097403Sobrien// || `[0x20000000, 0x23ffffff]` || LowShadow || 5197403Sobrien// || `[0x00000000, 0x1fffffff]` || LowMem || 5297403Sobrien 53132720Skan#if ASAN_FLEXIBLE_MAPPING_AND_OFFSET == 1 54132720Skanextern SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_mapping_scale; 55132720Skanextern SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_mapping_offset; 5697403Sobrien# define SHADOW_SCALE (__asan_mapping_scale) 57132720Skan# define SHADOW_OFFSET (__asan_mapping_offset) 5897403Sobrien#else 59132720Skan# if SANITIZER_ANDROID 60132720Skan# define SHADOW_SCALE (3) 6197403Sobrien# define SHADOW_OFFSET (0) 62132720Skan# else 63132720Skan# define SHADOW_SCALE (3) 64169691Skan# if SANITIZER_WORDSIZE == 32 65169691Skan# define SHADOW_OFFSET (1 << 29) 6697403Sobrien# else 67169691Skan# if defined(__powerpc64__) 68169691Skan# define SHADOW_OFFSET (1ULL << 41) 6997403Sobrien# else 7097403Sobrien# if SANITIZER_MAC 7197403Sobrien# define SHADOW_OFFSET (1ULL << 44) 7297403Sobrien# else 7397403Sobrien# define SHADOW_OFFSET 0x7fff8000ULL 7497403Sobrien# endif 7597403Sobrien# endif 7697403Sobrien# endif 7797403Sobrien# endif 7897403Sobrien#endif // ASAN_FLEXIBLE_MAPPING_AND_OFFSET 7997403Sobrien 8097403Sobrien#define SHADOW_GRANULARITY (1ULL << SHADOW_SCALE) 8197403Sobrien#define MEM_TO_SHADOW(mem) (((mem) >> SHADOW_SCALE) + (SHADOW_OFFSET)) 8297403Sobrien#define SHADOW_TO_MEM(shadow) (((shadow) - SHADOW_OFFSET) << SHADOW_SCALE) 8397403Sobrien 8497403Sobrien#define kLowMemBeg 0 85169691Skan#define kLowMemEnd (SHADOW_OFFSET ? SHADOW_OFFSET - 1 : 0) 86169691Skan 87169691Skan#define kLowShadowBeg SHADOW_OFFSET 8897403Sobrien#define kLowShadowEnd MEM_TO_SHADOW(kLowMemEnd) 8997403Sobrien 9097403Sobrien#define kHighMemBeg (MEM_TO_SHADOW(kHighMemEnd) + 1) 9197403Sobrien 9297403Sobrien#define kHighShadowBeg MEM_TO_SHADOW(kHighMemBeg) 9397403Sobrien#define kHighShadowEnd MEM_TO_SHADOW(kHighMemEnd) 9497403Sobrien 9597403Sobrien# define kMidShadowBeg MEM_TO_SHADOW(kMidMemBeg) 96132720Skan# define kMidShadowEnd MEM_TO_SHADOW(kMidMemEnd) 9797403Sobrien 9897403Sobrien// With the zero shadow base we can not actually map pages starting from 0. 9997403Sobrien// This constant is somewhat arbitrary. 100132720Skan#define kZeroBaseShadowStart (1 << 18) 10197403Sobrien 10297403Sobrien#define kShadowGapBeg (kLowShadowEnd ? kLowShadowEnd + 1 \ 10397403Sobrien : kZeroBaseShadowStart) 104132720Skan#define kShadowGapEnd ((kMidMemBeg ? kMidShadowBeg : kHighShadowBeg) - 1) 10597403Sobrien 10697403Sobrien#define kShadowGap2Beg (kMidMemBeg ? kMidShadowEnd + 1 : 0) 10797403Sobrien#define kShadowGap2End (kMidMemBeg ? kMidMemBeg - 1 : 0) 10897403Sobrien 10997403Sobrien#define kShadowGap3Beg (kMidMemBeg ? kMidMemEnd + 1 : 0) 11097403Sobrien#define kShadowGap3End (kMidMemBeg ? kHighShadowBeg - 1 : 0) 11197403Sobrien 11297403Sobrien#define DO_ASAN_MAPPING_PROFILE 0 // Set to 1 to profile the functions below. 11397403Sobrien 11497403Sobrien#if DO_ASAN_MAPPING_PROFILE 11597403Sobrien# define PROFILE_ASAN_MAPPING() AsanMappingProfile[__LINE__]++; 11697403Sobrien#else 11797403Sobrien# define PROFILE_ASAN_MAPPING() 11897403Sobrien#endif 119169691Skan 120169691Skan// If 1, all shadow boundaries are constants. 12197403Sobrien// Don't set to 1 other than for testing. 12297403Sobrien#define ASAN_FIXED_MAPPING 0 123169691Skan 124169691Skannamespace __asan { 12597403Sobrien 12697403Sobrienextern uptr AsanMappingProfile[]; 12797403Sobrien 12897403Sobrien#if ASAN_FIXED_MAPPING 12997403Sobrien// Fixed mapping for 64-bit Linux. Mostly used for performance comparison 13097403Sobrien// with non-fixed mapping. As of r175253 (Feb 2013) the performance 13197403Sobrien// difference between fixed and non-fixed mapping is below the noise level. 13297403Sobrienstatic uptr kHighMemEnd = 0x7fffffffffffULL; 13397403Sobrienstatic uptr kMidMemBeg = 0x3000000000ULL; 13497403Sobrienstatic uptr kMidMemEnd = 0x4fffffffffULL; 13597403Sobrien#else 13697403SobrienSANITIZER_INTERFACE_ATTRIBUTE 13797403Sobrienextern uptr kHighMemEnd, kMidMemBeg, kMidMemEnd; // Initialized in __asan_init. 13897403Sobrien#endif 13997403Sobrien 14097403Sobrienstatic inline bool AddrIsInLowMem(uptr a) { 14197403Sobrien PROFILE_ASAN_MAPPING(); 14297403Sobrien return a < kLowMemEnd; 14397403Sobrien} 14497403Sobrien 14597403Sobrienstatic inline bool AddrIsInLowShadow(uptr a) { 14697403Sobrien PROFILE_ASAN_MAPPING(); 14797403Sobrien return a >= kLowShadowBeg && a <= kLowShadowEnd; 14897403Sobrien} 14997403Sobrien 15097403Sobrienstatic inline bool AddrIsInHighMem(uptr a) { 15197403Sobrien PROFILE_ASAN_MAPPING(); 15297403Sobrien return a >= kHighMemBeg && a <= kHighMemEnd; 15397403Sobrien} 15497403Sobrien 15597403Sobrienstatic inline bool AddrIsInMidMem(uptr a) { 15697403Sobrien PROFILE_ASAN_MAPPING(); 15797403Sobrien return kMidMemBeg && a >= kMidMemBeg && a <= kMidMemEnd; 15897403Sobrien} 15997403Sobrien 16097403Sobrienstatic inline bool AddrIsInMem(uptr a) { 16197403Sobrien PROFILE_ASAN_MAPPING(); 16297403Sobrien return AddrIsInLowMem(a) || AddrIsInMidMem(a) || AddrIsInHighMem(a); 16397403Sobrien} 16497403Sobrien 16597403Sobrienstatic inline uptr MemToShadow(uptr p) { 16697403Sobrien PROFILE_ASAN_MAPPING(); 16797403Sobrien CHECK(AddrIsInMem(p)); 168169691Skan return MEM_TO_SHADOW(p); 169169691Skan} 17097403Sobrien 17197403Sobrienstatic inline bool AddrIsInHighShadow(uptr a) { 17297403Sobrien PROFILE_ASAN_MAPPING(); 17397403Sobrien return a >= kHighShadowBeg && a <= kHighMemEnd; 17497403Sobrien} 17597403Sobrien 17697403Sobrienstatic inline bool AddrIsInMidShadow(uptr a) { 17797403Sobrien PROFILE_ASAN_MAPPING(); 17897403Sobrien return kMidMemBeg && a >= kMidShadowBeg && a <= kMidMemEnd; 17997403Sobrien} 18097403Sobrien 18197403Sobrienstatic inline bool AddrIsInShadow(uptr a) { 18297403Sobrien PROFILE_ASAN_MAPPING(); 18397403Sobrien return AddrIsInLowShadow(a) || AddrIsInMidShadow(a) || AddrIsInHighShadow(a); 18497403Sobrien} 18597403Sobrien 18697403Sobrienstatic inline bool AddrIsInShadowGap(uptr a) { 18797403Sobrien PROFILE_ASAN_MAPPING(); 18897403Sobrien if (kMidMemBeg) { 18997403Sobrien if (a <= kShadowGapEnd) 19097403Sobrien return SHADOW_OFFSET == 0 || a >= kShadowGapBeg; 19197403Sobrien return (a >= kShadowGap2Beg && a <= kShadowGap2End) || 19297403Sobrien (a >= kShadowGap3Beg && a <= kShadowGap3End); 19397403Sobrien } 19497403Sobrien // In zero-based shadow mode we treat addresses near zero as addresses 19597403Sobrien // in shadow gap as well. 19697403Sobrien if (SHADOW_OFFSET == 0) 197132720Skan return a <= kShadowGapEnd; 198132720Skan return a >= kShadowGapBeg && a <= kShadowGapEnd; 19997403Sobrien} 20097403Sobrien 20197403Sobrienstatic inline bool AddrIsAlignedByGranularity(uptr a) { 20297403Sobrien PROFILE_ASAN_MAPPING(); 20397403Sobrien return (a & (SHADOW_GRANULARITY - 1)) == 0; 20497403Sobrien} 20597403Sobrien 20697403Sobrienstatic inline bool AddressIsPoisoned(uptr a) { 20797403Sobrien PROFILE_ASAN_MAPPING(); 20897403Sobrien const uptr kAccessSize = 1; 20997403Sobrien u8 *shadow_address = (u8*)MEM_TO_SHADOW(a); 21097403Sobrien s8 shadow_value = *shadow_address; 21197403Sobrien if (shadow_value) { 21297403Sobrien u8 last_accessed_byte = (a & (SHADOW_GRANULARITY - 1)) 21397403Sobrien + kAccessSize - 1; 21497403Sobrien return (last_accessed_byte >= shadow_value); 21597403Sobrien } 21697403Sobrien return false; 21797403Sobrien} 21897403Sobrien 219117397Skan// Must be after all calls to PROFILE_ASAN_MAPPING(). 22097403Sobrienstatic const uptr kAsanMappingProfileSize = __LINE__; 221132720Skan 222132720Skan} // namespace __asan 22397403Sobrien 22497403Sobrien#endif // ASAN_MAPPING_H 22597403Sobrien