2013-02-15 Jakub Jelinek * config/i386/i386.c: Use 0x7fff8000 as asan_shadow_offset on x86_64 linux. * All source files: Merge from upstream. --- gcc/config/i386/i386.c.jj 2013-02-13 17:04:34.000000000 +0100 +++ gcc/config/i386/i386.c 2013-02-15 13:27:47.674832994 +0100 @@ -5436,7 +5436,8 @@ ix86_legitimate_combined_insn (rtx insn) static unsigned HOST_WIDE_INT ix86_asan_shadow_offset (void) { - return TARGET_LP64 ? (HOST_WIDE_INT_1 << 44) + return TARGET_LP64 ? (TARGET_MACHO ? (HOST_WIDE_INT_1 << 44) + : HOST_WIDE_INT_C (0x7fff8000)) : (HOST_WIDE_INT_1 << 29); } --- libsanitizer/sanitizer_common/sanitizer_internal_defs.h.jj 2013-02-13 11:53:43.403336342 +0100 +++ libsanitizer/sanitizer_common/sanitizer_internal_defs.h 2013-02-15 13:24:17.410033137 +0100 @@ -29,7 +29,7 @@ # define SANITIZER_SUPPORTS_WEAK_HOOKS 0 #endif -// __has_feature +// GCC does not understand __has_feature #if !defined(__has_feature) # define __has_feature(x) 0 #endif --- libsanitizer/sanitizer_common/sanitizer_linux.cc.jj 2013-02-13 11:53:43.402336347 +0100 +++ libsanitizer/sanitizer_common/sanitizer_linux.cc 2013-02-15 13:24:17.410033137 +0100 @@ -232,6 +232,21 @@ const char *GetEnv(const char *name) { return 0; // Not found. } +#ifdef __GLIBC__ + +extern "C" { + extern void *__libc_stack_end; +} + +static void GetArgsAndEnv(char ***argv, char ***envp) { + uptr *stack_end = (uptr *)__libc_stack_end; + int argc = *stack_end; + *argv = (char**)(stack_end + 1); + *envp = (char**)(stack_end + argc + 2); +} + +#else // __GLIBC__ + static void ReadNullSepFileToArray(const char *path, char ***arr, int arr_size) { char *buff; @@ -251,11 +266,17 @@ static void ReadNullSepFileToArray(const (*arr)[count] = 0; } +static void GetArgsAndEnv(char ***argv, char ***envp) { + static const int kMaxArgv = 2000, kMaxEnvp = 2000; + ReadNullSepFileToArray("/proc/self/cmdline", argv, kMaxArgv); + ReadNullSepFileToArray("/proc/self/environ", envp, kMaxEnvp); +} + +#endif // __GLIBC__ + void ReExec() { - static const int kMaxArgv = 100, kMaxEnvp = 1000; char **argv, **envp; - ReadNullSepFileToArray("/proc/self/cmdline", &argv, kMaxArgv); - ReadNullSepFileToArray("/proc/self/environ", &envp, kMaxEnvp); + GetArgsAndEnv(&argv, &envp); execve(argv[0], argv, envp); } --- libsanitizer/asan/asan_internal.h.jj 2013-02-13 11:53:44.377330938 +0100 +++ libsanitizer/asan/asan_internal.h 2013-02-15 13:24:17.412033319 +0100 @@ -52,7 +52,7 @@ #define ASAN_POSIX (ASAN_LINUX || ASAN_MAC) -#if __has_feature(address_sanitizer) +#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) # error "The AddressSanitizer run-time should not be" " instrumented by AddressSanitizer" #endif --- libsanitizer/asan/asan_mac.cc.jj 2013-02-13 11:53:44.397330832 +0100 +++ libsanitizer/asan/asan_mac.cc 2013-02-15 13:24:17.412033319 +0100 @@ -104,7 +104,24 @@ void MaybeReexec() { _NSGetExecutablePath(program_name, &buf_size); // Ok to use setenv() since the wrappers don't depend on the value of // asan_inited. - setenv(kDyldInsertLibraries, info.dli_fname, /*overwrite*/0); + if (dyld_insert_libraries) { + // Append the runtime dylib name to the existing value of + // DYLD_INSERT_LIBRARIES. + uptr old_env_len = internal_strlen(dyld_insert_libraries); + uptr fname_len = internal_strlen(info.dli_fname); + LowLevelAllocator allocator_for_env; + char *new_env = + (char*)allocator_for_env.Allocate(old_env_len + fname_len + 2); + internal_strncpy(new_env, dyld_insert_libraries, old_env_len); + new_env[old_env_len] = ':'; + // Copy fname_len and add a trailing zero. + internal_strncpy(new_env + old_env_len + 1, info.dli_fname, + fname_len + 1); + setenv(kDyldInsertLibraries, new_env, /*overwrite*/1); + } else { + // Set DYLD_INSERT_LIBRARIES equal to the runtime dylib name. + setenv(kDyldInsertLibraries, info.dli_fname, /*overwrite*/0); + } if (flags()->verbosity >= 1) { Report("exec()-ing the program with\n"); Report("%s=%s\n", kDyldInsertLibraries, info.dli_fname); --- libsanitizer/asan/asan_mapping.h.jj 2013-02-13 17:04:34.680198753 +0100 +++ libsanitizer/asan/asan_mapping.h 2013-02-15 13:26:25.846301749 +0100 @@ -1,7 +1,5 @@ //===-- asan_mapping.h ------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // @@ -18,6 +16,37 @@ // The full explanation of the memory mapping could be found here: // http://code.google.com/p/address-sanitizer/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 0x004000000000 (e.g. when prelink is installed): +// || `[0x10007fff8000, 0x7fffffffffff]` || HighMem || +// || `[0x02008fff7000, 0x10007fff7fff]` || HighShadow || +// || `[0x004000000000, 0x02008fff6fff]` || ShadowGap3 || +// || `[0x003000000000, 0x003fffffffff]` || MidMem || +// || `[0x00087fff8000, 0x002fffffffff]` || ShadowGap2 || +// || `[0x00067fff8000, 0x00087fff7fff]` || MidShadow || +// || `[0x00008fff7000, 0x00067fff7fff]` || ShadowGap || +// || `[0x00007fff8000, 0x00008fff6fff]` || LowShadow || +// || `[0x000000000000, 0x00007fff7fff]` || LowMem || +// +// Default Linux/i386 mapping: +// || `[0x40000000, 0xffffffff]` || HighMem || +// || `[0x28000000, 0x3fffffff]` || HighShadow || +// || `[0x24000000, 0x27ffffff]` || ShadowGap || +// || `[0x20000000, 0x23ffffff]` || LowShadow || +// || `[0x00000000, 0x1fffffff]` || LowMem || #if ASAN_FLEXIBLE_MAPPING_AND_OFFSET == 1 extern SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_mapping_scale; @@ -36,7 +65,11 @@ extern SANITIZER_INTERFACE_ATTRIBUTE upt # if defined(__powerpc64__) # define SHADOW_OFFSET (1ULL << 41) # else -# define SHADOW_OFFSET (1ULL << 44) +# if ASAN_MAC +# define SHADOW_OFFSET (1ULL << 44) +# else +# define SHADOW_OFFSET 0x7fff8000ULL +# endif # endif # endif # endif @@ -57,49 +90,105 @@ extern SANITIZER_INTERFACE_ATTRIBUTE upt #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 (1 << 18) #define kShadowGapBeg (kLowShadowEnd ? kLowShadowEnd + 1 \ : kZeroBaseShadowStart) -#define kShadowGapEnd (kHighShadowBeg - 1) +#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) + +#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 = 0x3fffffffffULL; +#else SANITIZER_INTERFACE_ATTRIBUTE -extern uptr kHighMemEnd; // Initialized in __asan_init. +extern uptr kHighMemEnd, kMidMemBeg, kMidMemEnd; // Initialized in __asan_init. +#endif 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 AddrIsInHighMem(uptr a) { + PROFILE_ASAN_MAPPING(); return a >= kHighMemBeg && a <= kHighMemEnd; } +static inline bool AddrIsInMidMem(uptr a) { + PROFILE_ASAN_MAPPING(); + return kMidMemBeg && a >= kMidMemBeg && a <= kMidMemEnd; +} + static inline bool AddrIsInMem(uptr a) { - return AddrIsInLowMem(a) || AddrIsInHighMem(a); + PROFILE_ASAN_MAPPING(); + return AddrIsInLowMem(a) || AddrIsInMidMem(a) || AddrIsInHighMem(a); } static inline uptr MemToShadow(uptr p) { + PROFILE_ASAN_MAPPING(); CHECK(AddrIsInMem(p)); return MEM_TO_SHADOW(p); } static inline bool AddrIsInHighShadow(uptr a) { - return a >= kHighShadowBeg && a <= kHighMemEnd; + PROFILE_ASAN_MAPPING(); + return a >= kHighShadowBeg && a <= kHighMemEnd; +} + +static inline bool AddrIsInMidShadow(uptr a) { + PROFILE_ASAN_MAPPING(); + return kMidMemBeg && a >= kMidShadowBeg && a <= kMidMemEnd; } static inline bool AddrIsInShadow(uptr a) { - return AddrIsInLowShadow(a) || AddrIsInHighShadow(a); + PROFILE_ASAN_MAPPING(); + return AddrIsInLowShadow(a) || AddrIsInMidShadow(a) || AddrIsInHighShadow(a); } static inline bool AddrIsInShadowGap(uptr a) { + PROFILE_ASAN_MAPPING(); + if (kMidMemBeg) { + if (a <= kShadowGapEnd) + return 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 (SHADOW_OFFSET == 0) @@ -108,10 +197,12 @@ static inline bool AddrIsInShadowGap(upt } static inline bool AddrIsAlignedByGranularity(uptr a) { + PROFILE_ASAN_MAPPING(); return (a & (SHADOW_GRANULARITY - 1)) == 0; } static inline bool AddressIsPoisoned(uptr a) { + PROFILE_ASAN_MAPPING(); const uptr kAccessSize = 1; u8 *shadow_address = (u8*)MemToShadow(a); s8 shadow_value = *shadow_address; @@ -123,6 +214,9 @@ static inline bool AddressIsPoisoned(upt return false; } +// Must be after all calls to PROFILE_ASAN_MAPPING(). +static const uptr kAsanMappingProfileSize = __LINE__; + } // namespace __asan #endif // ASAN_MAPPING_H --- libsanitizer/asan/asan_rtl.cc.jj 2013-02-13 17:04:25.688240113 +0100 +++ libsanitizer/asan/asan_rtl.cc 2013-02-15 13:24:17.411033229 +0100 @@ -25,6 +25,8 @@ namespace __asan { +uptr AsanMappingProfile[kAsanMappingProfileSize]; + static void AsanDie() { static atomic_uint32_t num_calls; if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) { @@ -35,8 +37,14 @@ static void AsanDie() { Report("Sleeping for %d second(s)\n", flags()->sleep_before_dying); SleepForSeconds(flags()->sleep_before_dying); } - if (flags()->unmap_shadow_on_exit) - UnmapOrDie((void*)kLowShadowBeg, kHighShadowEnd - kLowShadowBeg); + if (flags()->unmap_shadow_on_exit) { + if (kMidMemBeg) { + UnmapOrDie((void*)kLowShadowBeg, kMidMemBeg - kLowShadowBeg); + UnmapOrDie((void*)kMidMemEnd, kHighShadowEnd - kMidMemEnd); + } else { + UnmapOrDie((void*)kLowShadowBeg, kHighShadowEnd - kLowShadowBeg); + } + } if (death_callback) death_callback(); if (flags()->abort_on_error) @@ -161,7 +169,10 @@ void InitializeFlags(Flags *f, const cha int asan_inited; bool asan_init_is_running; void (*death_callback)(void); -uptr kHighMemEnd; + +#if !ASAN_FIXED_MAPPING +uptr kHighMemEnd, kMidMemBeg, kMidMemEnd; +#endif // -------------------------- Misc ---------------- {{{1 void ShowStatsAndAbort() { @@ -259,9 +270,15 @@ static NOINLINE void force_interface_sym static void asan_atexit() { Printf("AddressSanitizer exit stats:\n"); __asan_print_accumulated_stats(); + // Print AsanMappingProfile. + for (uptr i = 0; i < kAsanMappingProfileSize; i++) { + if (AsanMappingProfile[i] == 0) continue; + Printf("asan_mapping.h:%zd -- %zd\n", i, AsanMappingProfile[i]); + } } static void InitializeHighMemEnd() { +#if !ASAN_FIXED_MAPPING #if SANITIZER_WORDSIZE == 64 # if defined(__powerpc64__) // FIXME: @@ -277,6 +294,58 @@ static void InitializeHighMemEnd() { #else // SANITIZER_WORDSIZE == 32 kHighMemEnd = (1ULL << 32) - 1; // 0xffffffff; #endif // SANITIZER_WORDSIZE +#endif // !ASAN_FIXED_MAPPING +} + +static void ProtectGap(uptr a, uptr size) { + CHECK_EQ(a, (uptr)Mprotect(a, size)); +} + +static void PrintAddressSpaceLayout() { + Printf("|| `[%p, %p]` || HighMem ||\n", + (void*)kHighMemBeg, (void*)kHighMemEnd); + Printf("|| `[%p, %p]` || HighShadow ||\n", + (void*)kHighShadowBeg, (void*)kHighShadowEnd); + if (kMidMemBeg) { + Printf("|| `[%p, %p]` || ShadowGap3 ||\n", + (void*)kShadowGap3Beg, (void*)kShadowGap3End); + Printf("|| `[%p, %p]` || MidMem ||\n", + (void*)kMidMemBeg, (void*)kMidMemEnd); + Printf("|| `[%p, %p]` || ShadowGap2 ||\n", + (void*)kShadowGap2Beg, (void*)kShadowGap2End); + Printf("|| `[%p, %p]` || MidShadow ||\n", + (void*)kMidShadowBeg, (void*)kMidShadowEnd); + } + Printf("|| `[%p, %p]` || ShadowGap ||\n", + (void*)kShadowGapBeg, (void*)kShadowGapEnd); + if (kLowShadowBeg) { + Printf("|| `[%p, %p]` || LowShadow ||\n", + (void*)kLowShadowBeg, (void*)kLowShadowEnd); + Printf("|| `[%p, %p]` || LowMem ||\n", + (void*)kLowMemBeg, (void*)kLowMemEnd); + } + Printf("MemToShadow(shadow): %p %p %p %p", + (void*)MEM_TO_SHADOW(kLowShadowBeg), + (void*)MEM_TO_SHADOW(kLowShadowEnd), + (void*)MEM_TO_SHADOW(kHighShadowBeg), + (void*)MEM_TO_SHADOW(kHighShadowEnd)); + if (kMidMemBeg) { + Printf(" %p %p", + (void*)MEM_TO_SHADOW(kMidShadowBeg), + (void*)MEM_TO_SHADOW(kMidShadowEnd)); + } + Printf("\n"); + Printf("red_zone=%zu\n", (uptr)flags()->redzone); + Printf("malloc_context_size=%zu\n", (uptr)flags()->malloc_context_size); + + Printf("SHADOW_SCALE: %zx\n", (uptr)SHADOW_SCALE); + Printf("SHADOW_GRANULARITY: %zx\n", (uptr)SHADOW_GRANULARITY); + Printf("SHADOW_OFFSET: %zx\n", (uptr)SHADOW_OFFSET); + CHECK(SHADOW_SCALE >= 3 && SHADOW_SCALE <= 7); + if (kMidMemBeg) + CHECK(kMidShadowBeg > kLowShadowEnd && + kMidMemBeg > kMidShadowEnd && + kHighShadowBeg > kMidMemEnd); } } // namespace __asan @@ -352,49 +421,48 @@ void __asan_init() { ReplaceSystemMalloc(); ReplaceOperatorsNewAndDelete(); - if (flags()->verbosity) { - Printf("|| `[%p, %p]` || HighMem ||\n", - (void*)kHighMemBeg, (void*)kHighMemEnd); - Printf("|| `[%p, %p]` || HighShadow ||\n", - (void*)kHighShadowBeg, (void*)kHighShadowEnd); - Printf("|| `[%p, %p]` || ShadowGap ||\n", - (void*)kShadowGapBeg, (void*)kShadowGapEnd); - Printf("|| `[%p, %p]` || LowShadow ||\n", - (void*)kLowShadowBeg, (void*)kLowShadowEnd); - Printf("|| `[%p, %p]` || LowMem ||\n", - (void*)kLowMemBeg, (void*)kLowMemEnd); - Printf("MemToShadow(shadow): %p %p %p %p\n", - (void*)MEM_TO_SHADOW(kLowShadowBeg), - (void*)MEM_TO_SHADOW(kLowShadowEnd), - (void*)MEM_TO_SHADOW(kHighShadowBeg), - (void*)MEM_TO_SHADOW(kHighShadowEnd)); - Printf("red_zone=%zu\n", (uptr)flags()->redzone); - Printf("malloc_context_size=%zu\n", (uptr)flags()->malloc_context_size); - - Printf("SHADOW_SCALE: %zx\n", (uptr)SHADOW_SCALE); - Printf("SHADOW_GRANULARITY: %zx\n", (uptr)SHADOW_GRANULARITY); - Printf("SHADOW_OFFSET: %zx\n", (uptr)SHADOW_OFFSET); - CHECK(SHADOW_SCALE >= 3 && SHADOW_SCALE <= 7); + uptr shadow_start = kLowShadowBeg; + if (kLowShadowBeg) shadow_start -= GetMmapGranularity(); + uptr shadow_end = kHighShadowEnd; + bool full_shadow_is_available = + MemoryRangeIsAvailable(shadow_start, shadow_end); + +#if ASAN_LINUX && defined(__x86_64__) && !ASAN_FIXED_MAPPING + if (!full_shadow_is_available) { + kMidMemBeg = kLowMemEnd < 0x3000000000ULL ? 0x3000000000ULL : 0; + kMidMemEnd = kLowMemEnd < 0x3000000000ULL ? 0x3fffffffffULL : 0; } +#endif + + if (flags()->verbosity) + PrintAddressSpaceLayout(); if (flags()->disable_core) { DisableCoreDumper(); } - uptr shadow_start = kLowShadowBeg; - if (kLowShadowBeg > 0) shadow_start -= GetMmapGranularity(); - uptr shadow_end = kHighShadowEnd; - if (MemoryRangeIsAvailable(shadow_start, shadow_end)) { - if (kLowShadowBeg != kLowShadowEnd) { - // mmap the low shadow plus at least one page. - ReserveShadowMemoryRange(kLowShadowBeg - GetMmapGranularity(), - kLowShadowEnd); - } + if (full_shadow_is_available) { + // mmap the low shadow plus at least one page at the left. + if (kLowShadowBeg) + ReserveShadowMemoryRange(shadow_start, kLowShadowEnd); + // mmap the high shadow. + ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd); + // protect the gap. + ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1); + } else if (kMidMemBeg && + MemoryRangeIsAvailable(shadow_start, kMidMemBeg - 1) && + MemoryRangeIsAvailable(kMidMemEnd + 1, shadow_end)) { + CHECK(kLowShadowBeg != kLowShadowEnd); + // mmap the low shadow plus at least one page at the left. + ReserveShadowMemoryRange(shadow_start, kLowShadowEnd); + // mmap the mid shadow. + ReserveShadowMemoryRange(kMidShadowBeg, kMidShadowEnd); // mmap the high shadow. ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd); - // protect the gap - void *prot = Mprotect(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1); - CHECK(prot == (void*)kShadowGapBeg); + // protect the gaps. + ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1); + ProtectGap(kShadowGap2Beg, kShadowGap2End - kShadowGap2Beg + 1); + ProtectGap(kShadowGap3Beg, kShadowGap3End - kShadowGap3Beg + 1); } else { Report("Shadow memory range interleaves with an existing memory mapping. " "ASan cannot proceed correctly. ABORTING.\n"); --- libsanitizer/include/sanitizer/common_interface_defs.h.jj 2013-02-13 11:53:44.531330044 +0100 +++ libsanitizer/include/sanitizer/common_interface_defs.h 2013-02-15 13:24:17.403032450 +0100 @@ -14,6 +14,11 @@ #include #include +// GCC does not understand __has_feature. +#if !defined(__has_feature) +# define __has_feature(x) 0 +#endif + #ifdef __cplusplus extern "C" { #endif --- libsanitizer/include/sanitizer/asan_interface.h.jj 2013-02-13 11:53:44.531330044 +0100 +++ libsanitizer/include/sanitizer/asan_interface.h 2013-02-15 13:24:17.403032450 +0100 @@ -35,8 +35,8 @@ extern "C" { // (un)poison memory in the same memory region simultaneously. void __asan_unpoison_memory_region(void const volatile *addr, size_t size); - // User code should use macro instead of functions. -#if __has_feature(address_sanitizer) +// User code should use macros instead of functions. +#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) #define ASAN_POISON_MEMORY_REGION(addr, size) \ __asan_poison_memory_region((addr), (size)) #define ASAN_UNPOISON_MEMORY_REGION(addr, size) \