Index: compiler-rt/lib/asan/asan_linux.cc =================================================================== --- compiler-rt/lib/asan/asan_linux.cc +++ compiler-rt/lib/asan/asan_linux.cc @@ -83,7 +83,7 @@ } #if ASAN_PREMAP_SHADOW -uptr FindDynamicShadowStart() { +uptr FindPremappedShadowStart() { uptr granularity = GetMmapGranularity(); uptr shadow_start = reinterpret_cast(&__asan_shadow); uptr shadow_size = PremapShadowSize(); @@ -93,8 +93,14 @@ IncreaseTotalMmap(shadow_size + granularity); return shadow_start; } -#else +#endif + uptr FindDynamicShadowStart() { +#if ASAN_PREMAP_SHADOW + if (!PremapShadowFailed()) + return FindPremappedShadowStart(); +#endif + uptr granularity = GetMmapGranularity(); uptr alignment = granularity * 8; uptr left_padding = granularity; @@ -112,7 +118,6 @@ return shadow_start; } -#endif void AsanApplyToGlobals(globals_op_fptr op, const void *needle) { UNIMPLEMENTED(); Index: compiler-rt/lib/asan/asan_premap_shadow.h =================================================================== --- compiler-rt/lib/asan/asan_premap_shadow.h +++ compiler-rt/lib/asan/asan_premap_shadow.h @@ -20,9 +20,11 @@ namespace __asan { // Conservative upper limit. uptr PremapShadowSize(); +bool PremapShadowFailed(); } #endif extern "C" INTERFACE_ATTRIBUTE void __asan_shadow(); +extern "C" decltype(__asan_shadow)* __asan_premap_shadow(); #endif // ASAN_PREMAP_SHADOW_H Index: compiler-rt/lib/asan/asan_premap_shadow.cc =================================================================== --- compiler-rt/lib/asan/asan_premap_shadow.cc +++ compiler-rt/lib/asan/asan_premap_shadow.cc @@ -50,6 +50,15 @@ return shadow_start; } +bool PremapShadowFailed() { + uptr shadow = reinterpret_cast(&__asan_shadow); + uptr resolver = reinterpret_cast(&__asan_premap_shadow); + // shadow == resolver is how Android KitKat and older handles ifunc. + // shadow == 0 just in case. + if (shadow == 0 || shadow == resolver) + return true; + return false; +} } // namespace __asan extern "C" { Index: llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp =================================================================== --- llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -565,7 +565,9 @@ Mapping.OrShadowOffset = !IsAArch64 && !IsPPC64 && !IsSystemZ && !IsPS4CPU && !(Mapping.Offset & (Mapping.Offset - 1)) && Mapping.Offset != kDynamicShadowSentinel; - Mapping.InGlobal = ClWithIfunc && IsAndroid && IsArmOrThumb; + bool IsAndroidWithIfuncSupport = + IsAndroid && !TargetTriple.isAndroidVersionLT(21); + Mapping.InGlobal = ClWithIfunc && IsAndroidWithIfuncSupport && IsArmOrThumb; return Mapping; } Index: llvm/test/Instrumentation/AddressSanitizer/with-ifunc.ll =================================================================== --- llvm/test/Instrumentation/AddressSanitizer/with-ifunc.ll +++ llvm/test/Instrumentation/AddressSanitizer/with-ifunc.ll @@ -7,8 +7,16 @@ ; RUN: opt -asan -asan-module -S -asan-with-ifunc=1 -asan-with-ifunc-suppress-remat=1 < %s | \ ; RUN: FileCheck %s --check-prefixes=CHECK,CHECK-IFUNC-NOREMAT +; Pre-Lollipop Android does not support ifunc. +; RUN: opt -asan -asan-module -S -asan-with-ifunc=1 -asan-with-ifunc-suppress-remat=0 -mtriple=armv7-linux-android20 < %s | \ +; RUN: FileCheck %s --check-prefixes=CHECK,CHECK-NOIFUNC +; RUN: opt -asan -asan-module -S -asan-with-ifunc=1 -asan-with-ifunc-suppress-remat=0 -mtriple=armv7-linux-android < %s | \ +; RUN: FileCheck %s --check-prefixes=CHECK,CHECK-NOIFUNC +; RUN: opt -asan -asan-module -S -asan-with-ifunc=1 -asan-with-ifunc-suppress-remat=0 -mtriple=armv7-linux-android21 < %s | \ +; RUN: FileCheck %s --check-prefixes=CHECK,CHECK-IFUNC + target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" -target triple = "armv7--linux-android" +target triple = "armv7--linux-android22" ; CHECK-IFUNC: @__asan_shadow = external global [0 x i8] ; CHECK-NOIFUNC: @__asan_shadow_memory_dynamic_address = external global i32