Index: compiler-rt/lib/asan/asan_activation.cc =================================================================== --- compiler-rt/lib/asan/asan_activation.cc +++ compiler-rt/lib/asan/asan_activation.cc @@ -16,8 +16,10 @@ #include "asan_allocator.h" #include "asan_flags.h" #include "asan_internal.h" +#include "asan_mapping.h" #include "asan_poisoning.h" #include "asan_stack.h" +#include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_flags.h" namespace __asan { @@ -110,8 +112,9 @@ AllocatorOptions disabled = asan_deactivated_flags.allocator_options; disabled.quarantine_size_mb = 0; disabled.thread_local_quarantine_size_kb = 0; - disabled.min_redzone = 16; // Redzone must be at least 16 bytes long. - disabled.max_redzone = 16; + // Redzone must be at least Max(16, granularity) bytes long. + disabled.min_redzone = Max(16, (int)SHADOW_GRANULARITY); + disabled.max_redzone = Max(16, (int)SHADOW_GRANULARITY); disabled.alloc_dealloc_mismatch = false; disabled.may_return_null = true; ReInitializeAllocator(disabled); Index: compiler-rt/lib/asan/asan_errors.cc =================================================================== --- compiler-rt/lib/asan/asan_errors.cc +++ compiler-rt/lib/asan/asan_errors.cc @@ -296,6 +296,12 @@ if (*shadow_addr == 0 && access_size > SHADOW_GRANULARITY) shadow_addr++; // If we are in the partial right redzone, look at the next shadow byte. if (*shadow_addr > 0 && *shadow_addr < 128) shadow_addr++; + // For large shadow granularity, skip pass all partial right redzones. + if (SHADOW_GRANULARITY >= 32) { + while (AddrIsInShadow((uptr)shadow_addr) && *shadow_addr > 0 && + *shadow_addr < 128) + shadow_addr++; + } bool far_from_bounds = false; shadow_val = *shadow_addr; int bug_type_score = 0; Index: compiler-rt/lib/asan/asan_fake_stack.cc =================================================================== --- compiler-rt/lib/asan/asan_fake_stack.cc +++ compiler-rt/lib/asan/asan_fake_stack.cc @@ -28,9 +28,9 @@ // For small size classes inline PoisonShadow for better performance. ALWAYS_INLINE void SetShadow(uptr ptr, uptr size, uptr class_id, u64 magic) { - CHECK_EQ(SHADOW_SCALE, 3); // This code expects SHADOW_SCALE=3. u64 *shadow = reinterpret_cast(MemToShadow(ptr)); - if (class_id <= 6) { + if (SHADOW_SCALE == 3 && class_id <= 6) { + // This code expects SHADOW_SCALE=3. for (uptr i = 0; i < (((uptr)1) << class_id); i++) { shadow[i] = magic; // Make sure this does not become memset. Index: compiler-rt/lib/asan/asan_flags.cc =================================================================== --- compiler-rt/lib/asan/asan_flags.cc +++ compiler-rt/lib/asan/asan_flags.cc @@ -70,6 +70,8 @@ } Flags *f = flags(); f->SetDefaults(); + if (f->redzone < (int)SHADOW_GRANULARITY) + f->redzone = SHADOW_GRANULARITY; FlagParser asan_parser; RegisterAsanFlags(&asan_parser, f); Index: compiler-rt/lib/asan/asan_mapping.h =================================================================== --- compiler-rt/lib/asan/asan_mapping.h +++ compiler-rt/lib/asan/asan_mapping.h @@ -131,11 +131,16 @@ // || `[0x30000000, 0x35ffffff]` || LowShadow || // || `[0x00000000, 0x2fffffff]` || LowMem || +#if defined(OVERRIDE_SHADOW_SCALE) +static const u64 kDefaultShadowScale = OVERRIDE_SHADOW_SCALE; +#else static const u64 kDefaultShadowScale = 3; +#endif static const u64 kDefaultShadowSentinel = ~(uptr)0; static const u64 kDefaultShadowOffset32 = 1ULL << 29; // 0x20000000 static const u64 kDefaultShadowOffset64 = 1ULL << 44; -static const u64 kDefaultShort64bitShadowOffset = 0x7FFF8000; // < 2G. +static const u64 kDefaultShort64bitShadowOffset = + 0x7FFFFFFF & ~((1 << (12 + kDefaultShadowScale)) - 1); // < 2G. static const u64 kIosShadowOffset32 = 1ULL << 30; // 0x40000000 static const u64 kIosShadowOffset64 = 0x120200000; static const u64 kIosSimShadowOffset32 = 1ULL << 30; Index: compiler-rt/lib/asan/tests/CMakeLists.txt =================================================================== --- compiler-rt/lib/asan/tests/CMakeLists.txt +++ compiler-rt/lib/asan/tests/CMakeLists.txt @@ -56,6 +56,10 @@ -DASAN_HAS_EXCEPTIONS=1 -DASAN_UAR=0) +if(NOT LLVM_ASAN_SHADOW_SCALE EQUAL 0) + list(APPEND ASAN_UNITTEST_COMMON_CFLAGS -DOVERRIDE_SHADOW_SCALE=${LLVM_ASAN_SHADOW_SCALE}) +endif() + if(APPLE) list(APPEND ASAN_UNITTEST_COMMON_CFLAGS ${DARWIN_osx_CFLAGS}) list(APPEND ASAN_UNITTEST_COMMON_LINK_FLAGS ${DARWIN_osx_LINK_FLAGS}) Index: compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc =================================================================== --- compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc +++ compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc @@ -181,8 +181,9 @@ static LowLevelAllocateCallback low_level_alloc_callback; void *LowLevelAllocator::Allocate(uptr size) { - // Align allocation size. - size = RoundUpTo(size, 8); + // Align allocation size. Must be aligned to maximum supported + // shadow granularity. + size = RoundUpTo(size, 32); if (allocated_end_ - allocated_current_ < (sptr)size) { uptr size_to_allocate = Max(size, GetPageSizeCached()); allocated_current_ = Index: compiler-rt/test/asan/CMakeLists.txt =================================================================== --- compiler-rt/test/asan/CMakeLists.txt +++ compiler-rt/test/asan/CMakeLists.txt @@ -56,6 +56,9 @@ string(TOLOWER "-${arch}-${OS_NAME}" ASAN_TEST_CONFIG_SUFFIX) get_bits_for_arch(${arch} ASAN_TEST_BITS) get_test_cc_for_arch(${arch} ASAN_TEST_TARGET_CC ASAN_TEST_TARGET_CFLAGS) + if(NOT LLVM_ASAN_SHADOW_SCALE EQUAL 0) + set(ASAN_TEST_TARGET_CFLAGS "-DOVERRIDE_SHADOW_SCALE=${LLVM_ASAN_SHADOW_SCALE} ${ASAN_TEST_TARGET_CFLAGS}") + endif() if(ANDROID) set(ASAN_TEST_DYNAMIC True) else() @@ -99,6 +102,9 @@ pythonize_bool(ASAN_TEST_IOSSIM) set(ASAN_TEST_TARGET_ARCH ${arch}) set(ASAN_TEST_TARGET_CFLAGS "-arch ${arch} -isysroot ${DARWIN_iossim_SYSROOT} ${COMPILER_RT_TEST_COMPILER_CFLAGS}") + if(NOT LLVM_ASAN_SHADOW_SCALE EQUAL 0) + set(ASAN_TEST_TARGET_CFLAGS "-DOVERRIDE_SHADOW_SCALE=${LLVM_ASAN_SHADOW_SCALE} ${ASAN_TEST_TARGET_CFLAGS}") + endif() set(ASAN_TEST_CONFIG_SUFFIX "-${arch}-iossim") get_bits_for_arch(${arch} ASAN_TEST_BITS) string(TOUPPER ${arch} ARCH_UPPER_CASE) @@ -117,6 +123,9 @@ pythonize_bool(ASAN_TEST_IOSSIM) set(ASAN_TEST_TARGET_ARCH ${arch}) set(ASAN_TEST_TARGET_CFLAGS "-arch ${arch} -isysroot ${DARWIN_ios_SYSROOT} ${COMPILER_RT_TEST_COMPILER_CFLAGS}") + if(NOT LLVM_ASAN_SHADOW_SCALE EQUAL 0) + set(ASAN_TEST_TARGET_CFLAGS "-DOVERRIDE_SHADOW_SCALE=${LLVM_ASAN_SHADOW_SCALE} ${ASAN_TEST_TARGET_CFLAGS}") + endif() set(ASAN_TEST_CONFIG_SUFFIX "-${arch}-ios") get_bits_for_arch(${arch} ASAN_TEST_BITS) string(TOUPPER ${arch} ARCH_UPPER_CASE) Index: llvm/CMakeLists.txt =================================================================== --- llvm/CMakeLists.txt +++ llvm/CMakeLists.txt @@ -556,6 +556,14 @@ set(LLVM_ADD_NATIVE_VISUALIZERS_TO_SOLUTION FALSE CACHE INTERNAL "For Visual Studio 2013, manually copy natvis files to Documents\\Visual Studio 2013\\Visualizers" FORCE) endif() +set(LLVM_ASAN_SHADOW_SCALE "0" + CACHE STRING "The Shadow Scale to use for ASan (0 means default)") + +# Check that LLVM_ASAN_SHADOW_SCALE is sensible. +if (NOT (LLVM_ASAN_SHADOW_SCALE GREATER -1 AND LLVM_ASAN_SHADOW_SCALE LESS 8)) + message(FATAL_ERROR "Invalid Shadow Scale '${LLVM_ASAN_SHADOW_SCALE}' (Valid range [0, 7])") +endif() + if (LLVM_BUILD_INSTRUMENTED OR LLVM_BUILD_INSTRUMENTED_COVERAGE OR LLVM_ENABLE_IR_PGO) if(NOT LLVM_PROFILE_MERGE_POOL_SIZE) Index: llvm/cmake/modules/HandleLLVMOptions.cmake =================================================================== --- llvm/cmake/modules/HandleLLVMOptions.cmake +++ llvm/cmake/modules/HandleLLVMOptions.cmake @@ -682,6 +682,10 @@ add_definitions( -D__STDC_FORMAT_MACROS ) add_definitions( -D__STDC_LIMIT_MACROS ) +if(NOT LLVM_ASAN_SHADOW_SCALE EQUAL 0) + add_definitions( -DOVERRIDE_SHADOW_SCALE=${LLVM_ASAN_SHADOW_SCALE} ) +endif() + # clang doesn't print colored diagnostics when invoked from Ninja if (UNIX AND CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND Index: llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp =================================================================== --- llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -89,7 +89,11 @@ #define DEBUG_TYPE "asan" +#if defined(OVERRIDE_SHADOW_SCALE) +static const uint64_t kDefaultShadowScale = OVERRIDE_SHADOW_SCALE; +#else static const uint64_t kDefaultShadowScale = 3; +#endif static const uint64_t kDefaultShadowOffset32 = 1ULL << 29; static const uint64_t kDefaultShadowOffset64 = 1ULL << 44; static const uint64_t kDynamicShadowSentinel = @@ -97,7 +101,8 @@ static const uint64_t kIOSShadowOffset32 = 1ULL << 30; static const uint64_t kIOSSimShadowOffset32 = 1ULL << 30; static const uint64_t kIOSSimShadowOffset64 = kDefaultShadowOffset64; -static const uint64_t kSmallX86_64ShadowOffset = 0x7FFF8000; // < 2G. +static const uint64_t kSmallX86_64ShadowOffset = + 0x7FFFFFFF & ~((1 << (12 + kDefaultShadowScale)) - 1); // < 2G. static const uint64_t kLinuxKasan_ShadowOffset64 = 0xdffffc0000000000; static const uint64_t kPPC64_ShadowOffset64 = 1ULL << 41; static const uint64_t kSystemZ_ShadowOffset64 = 1ULL << 52; @@ -1952,6 +1957,8 @@ auto AllGlobals = new GlobalVariable( M, ArrayOfGlobalStructTy, false, GlobalVariable::InternalLinkage, ConstantArray::get(ArrayOfGlobalStructTy, MetadataInitializers), ""); + if (Mapping.Scale > 3) + AllGlobals->setAlignment(1ULL << Mapping.Scale); IRB.CreateCall(AsanRegisterGlobals, {IRB.CreatePointerCast(AllGlobals, IntptrTy), @@ -2760,9 +2767,10 @@ // Minimal header size (left redzone) is 4 pointers, // i.e. 32 bytes on 64-bit platforms and 16 bytes in 32-bit platforms. - size_t MinHeaderSize = ASan.LongSize / 2; + size_t Granularity = 1ULL << Mapping.Scale; + size_t MinHeaderSize = std::max((size_t)ASan.LongSize / 2, Granularity); const ASanStackFrameLayout &L = - ComputeASanStackFrameLayout(SVD, 1ULL << Mapping.Scale, MinHeaderSize); + ComputeASanStackFrameLayout(SVD, Granularity, MinHeaderSize); // Build AllocaToSVDMap for ASanStackVariableDescription lookup. DenseMap AllocaToSVDMap; Index: llvm/lib/Transforms/Utils/ASanStackFrameLayout.cpp =================================================================== --- llvm/lib/Transforms/Utils/ASanStackFrameLayout.cpp +++ llvm/lib/Transforms/Utils/ASanStackFrameLayout.cpp @@ -81,6 +81,9 @@ size_t NextAlignment = IsLast ? Granularity : std::max(Granularity, Vars[i + 1].Alignment); size_t SizeWithRedzone = VarAndRedzoneSize(Size, NextAlignment); + // Add a sentinel to end of stack. + if (IsLast && SizeWithRedzone == Granularity) + SizeWithRedzone += Granularity; Vars[i].Offset = Offset; Offset += SizeWithRedzone; } Index: llvm/unittests/Transforms/Utils/ASanStackFrameLayoutTest.cpp =================================================================== --- llvm/unittests/Transforms/Utils/ASanStackFrameLayoutTest.cpp +++ llvm/unittests/Transforms/Utils/ASanStackFrameLayoutTest.cpp @@ -70,7 +70,7 @@ VAR(a, 105, 103, 1, 0); TEST_LAYOUT({a1_1}, 8, 16, "1 16 1 4 a1_1", "LL1R", "LL1R"); - TEST_LAYOUT({a1_1}, 64, 64, "1 64 1 4 a1_1", "L1", "L1"); + TEST_LAYOUT({a1_1}, 64, 64, "1 64 1 4 a1_1", "L1R", "L1R"); TEST_LAYOUT({p1_32}, 8, 32, "1 32 1 8 p1_32:15", "LLLL1RRR", "LLLL1RRR"); TEST_LAYOUT({p1_32}, 8, 64, "1 64 1 8 p1_32:15", "LLLLLLLL1RRRRRRR", "LLLLLLLL1RRRRRRR");