Index: llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp =================================================================== --- llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -196,9 +196,10 @@ "asan-memory-access-callback-prefix", cl::desc("Prefix for memory access callbacks"), cl::Hidden, cl::init("__asan_")); -static cl::opt ClInstrumentAllocas("asan-instrument-allocas", - cl::desc("instrument dynamic allocas"), - cl::Hidden, cl::init(true)); +static cl::opt + ClInstrumentDynamicAllocas("asan-instrument-dynamic-allocas", + cl::desc("instrument dynamic allocas"), + cl::Hidden, cl::init(true)); static cl::opt ClSkipPromotableAllocas( "asan-skip-promotable-allocas", cl::desc("Do not instrument promotable allocas"), cl::Hidden, @@ -622,7 +623,8 @@ uint64_t Size; bool DoPoison; }; - SmallVector AllocaPoisonCallVec; + SmallVector DynamicAllocaPoisonCallVec; + SmallVector StaticAllocaPoisonCallVec; SmallVector DynamicAllocaVec; SmallVector StackRestoreVec; @@ -657,7 +659,8 @@ initializeCallbacks(*F.getParent()); - poisonStack(); + processDynamicAllocas(); + processStaticAllocas(); if (ClDebugStack) { DEBUG(dbgs() << F); @@ -668,7 +671,8 @@ // Finds all Alloca instructions and puts // poisoned red zones around all of them. // Then unpoison everything back before the function returns. - void poisonStack(); + void processStaticAllocas(); + void processDynamicAllocas(); void createDynamicAllocasInitStorage(); @@ -767,7 +771,10 @@ return; bool DoPoison = (ID == Intrinsic::lifetime_end); AllocaPoisonCall APC = {&II, AI, SizeValue, DoPoison}; - AllocaPoisonCallVec.push_back(APC); + if (AI->isStaticAlloca()) + StaticAllocaPoisonCallVec.push_back(APC); + else if (ClInstrumentDynamicAllocas) + DynamicAllocaPoisonCallVec.push_back(APC); } void visitCallSite(CallSite CS) { @@ -2021,37 +2028,39 @@ DynamicAllocaLayout->setAlignment(32); } -void FunctionStackPoisoner::poisonStack() { - assert(AllocaVec.size() > 0 || DynamicAllocaVec.size() > 0); +void FunctionStackPoisoner::processDynamicAllocas() { + if (!ClInstrumentDynamicAllocas || DynamicAllocaVec.empty()) { + assert(DynamicAllocaPoisonCallVec.empty()); + return; + } - // Insert poison calls for lifetime intrinsics for alloca. - bool HavePoisonedStaticAllocas = false; - for (const auto &APC : AllocaPoisonCallVec) { + // Insert poison calls for lifetime intrinsics for dynamic allocas. + for (const auto &APC : DynamicAllocaPoisonCallVec) { assert(APC.InsBefore); assert(APC.AI); assert(ASan.isInterestingAlloca(*APC.AI)); - bool IsDynamicAlloca = !(*APC.AI).isStaticAlloca(); - if (!ClInstrumentAllocas && IsDynamicAlloca) - continue; + assert(!APC.AI->isStaticAlloca()); IRBuilder<> IRB(APC.InsBefore); poisonAlloca(APC.AI, APC.Size, IRB, APC.DoPoison); // Dynamic allocas will be unpoisoned unconditionally below in // unpoisonDynamicAllocas. // Flag that we need unpoison static allocas. - HavePoisonedStaticAllocas |= (APC.DoPoison && !IsDynamicAlloca); } - if (ClInstrumentAllocas && DynamicAllocaVec.size() > 0) { - // Handle dynamic allocas. - createDynamicAllocasInitStorage(); - for (auto &AI : DynamicAllocaVec) handleDynamicAllocaCall(AI); + // Handle dynamic allocas. + createDynamicAllocasInitStorage(); + for (auto &AI : DynamicAllocaVec) + handleDynamicAllocaCall(AI); + unpoisonDynamicAllocas(); +} - unpoisonDynamicAllocas(); +void FunctionStackPoisoner::processStaticAllocas() { + if (AllocaVec.empty()) { + assert(StaticAllocaPoisonCallVec.empty()); + return; } - if (AllocaVec.empty()) return; - int StackMallocIdx = -1; DebugLoc EntryDebugLocation; if (auto SP = F.getSubprogram()) @@ -2074,6 +2083,17 @@ // If we have a call to llvm.localescape, keep it in the entry block. if (LocalEscapeCall) LocalEscapeCall->moveBefore(InsBefore); + // Insert poison calls for lifetime intrinsics for static allocas. + for (const auto &APC : StaticAllocaPoisonCallVec) { + assert(APC.InsBefore); + assert(APC.AI); + assert(ASan.isInterestingAlloca(*APC.AI)); + assert(APC.AI->isStaticAlloca()); + + IRBuilder<> IRB(APC.InsBefore); + poisonAlloca(APC.AI, APC.Size, IRB, APC.DoPoison); + } + SmallVector SVD; SVD.reserve(AllocaVec.size()); for (AllocaInst *AI : AllocaVec) { @@ -2192,7 +2212,7 @@ // Do this always as poisonAlloca can be disabled with // detect_stack_use_after_scope=0. poisonRedZones(L.ShadowBytes, IRB, ShadowBase, false); - if (HavePoisonedStaticAllocas) { + if (!StaticAllocaPoisonCallVec.empty()) { // If we poisoned some allocas in llvm.lifetime analysis, // unpoison whole stack frame now. poisonAlloca(LocalStackBase, LocalStackSize, IRB, false); Index: llvm/trunk/test/Instrumentation/AddressSanitizer/debug_info_noninstrumented_alloca.ll =================================================================== --- llvm/trunk/test/Instrumentation/AddressSanitizer/debug_info_noninstrumented_alloca.ll +++ llvm/trunk/test/Instrumentation/AddressSanitizer/debug_info_noninstrumented_alloca.ll @@ -3,7 +3,7 @@ ; breaks debug info. ; RUN: opt < %s -asan -asan-module -S | FileCheck %s -; RUN: opt < %s -asan -asan-module -asan-instrument-allocas=1 -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -asan-instrument-dynamic-allocas -S | FileCheck %s target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.10.0" Index: llvm/trunk/test/Instrumentation/AddressSanitizer/do-not-instrument-promotable-allocas.ll =================================================================== --- llvm/trunk/test/Instrumentation/AddressSanitizer/do-not-instrument-promotable-allocas.ll +++ llvm/trunk/test/Instrumentation/AddressSanitizer/do-not-instrument-promotable-allocas.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -asan -asan-module -asan-instrument-allocas=1 -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -asan-instrument-dynamic-allocas -S | FileCheck %s target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.10.0" Index: llvm/trunk/test/Instrumentation/AddressSanitizer/instrument-dynamic-allocas.ll =================================================================== --- llvm/trunk/test/Instrumentation/AddressSanitizer/instrument-dynamic-allocas.ll +++ llvm/trunk/test/Instrumentation/AddressSanitizer/instrument-dynamic-allocas.ll @@ -1,7 +1,7 @@ ; Test asan internal compiler flags: -; -asan-instrument-allocas=1 +; -asan-instrument-dynamic-allocas -; RUN: opt < %s -asan -asan-module -asan-instrument-allocas=1 -S | FileCheck %s --check-prefix=CHECK-ALLOCA +; RUN: opt < %s -asan -asan-module -asan-instrument-dynamic-allocas -S | FileCheck %s --check-prefix=CHECK-ALLOCA target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-unknown-linux-gnu" Index: llvm/trunk/test/Instrumentation/AddressSanitizer/lifetime.ll =================================================================== --- llvm/trunk/test/Instrumentation/AddressSanitizer/lifetime.ll +++ llvm/trunk/test/Instrumentation/AddressSanitizer/lifetime.ll @@ -1,6 +1,6 @@ ; Test handling of llvm.lifetime intrinsics. ; RUN: opt < %s -asan -asan-module -asan-use-after-scope -asan-use-after-return=0 -S | FileCheck %s -; RUN: opt < %s -asan -asan-module -asan-use-after-scope -asan-use-after-return=0 -asan-instrument-allocas=0 -S | FileCheck %s --check-prefix=CHECK-NO-DYNAMIC +; RUN: opt < %s -asan -asan-module -asan-use-after-scope -asan-use-after-return=0 -asan-instrument-dynamic-allocas=0 -S | FileCheck %s --check-prefix=CHECK-NO-DYNAMIC target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu"