kstoimenov updated this revision to Diff 380829. kstoimenov added a comment.
Fixed the test to pass. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D112098/new/ https://reviews.llvm.org/D112098 Files: clang/include/clang/Basic/CodeGenOptions.def clang/include/clang/Driver/Options.td clang/include/clang/Driver/SanitizerArgs.h clang/lib/CodeGen/BackendUtil.cpp clang/lib/Driver/SanitizerArgs.cpp clang/test/CodeGen/asan-stack-safety-analysis.c clang/test/Driver/fsanitize.c llvm/include/llvm/Analysis/StackSafetyAnalysis.h llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
Index: llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp =================================================================== --- llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -26,6 +26,7 @@ #include "llvm/ADT/Triple.h" #include "llvm/ADT/Twine.h" #include "llvm/Analysis/MemoryBuiltins.h" +#include "llvm/Analysis/StackSafetyAnalysis.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/BinaryFormat/MachO.h" @@ -47,6 +48,7 @@ #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/InlineAsm.h" +#include "llvm/IR/InstIterator.h" #include "llvm/IR/InstVisitor.h" #include "llvm/IR/InstrTypes.h" #include "llvm/IR/Instruction.h" @@ -211,6 +213,11 @@ "asan-instrument-writes", cl::desc("instrument write instructions"), cl::Hidden, cl::init(true)); +static cl::opt<bool> + ClUseStackSafety("asan-use-stack-safety", cl::Hidden, cl::init(false), + cl::Hidden, cl::desc("Use Stack Safety analysis results"), + cl::Optional); + static cl::opt<bool> ClInstrumentAtomics( "asan-instrument-atomics", cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden, @@ -647,8 +654,8 @@ /// AddressSanitizer: instrument the code in module to find memory bugs. struct AddressSanitizer { AddressSanitizer(Module &M, const GlobalsMetadata *GlobalsMD, - bool CompileKernel = false, bool Recover = false, - bool UseAfterScope = false, + const StackSafetyGlobalInfo *SSI, bool CompileKernel = false, + bool Recover = false, bool UseAfterScope = false, AsanDetectStackUseAfterReturnMode UseAfterReturn = AsanDetectStackUseAfterReturnMode::Runtime) : CompileKernel(ClEnableKasan.getNumOccurrences() > 0 ? ClEnableKasan @@ -657,7 +664,7 @@ UseAfterScope(UseAfterScope || ClUseAfterScope), UseAfterReturn(ClUseAfterReturn.getNumOccurrences() ? ClUseAfterReturn : UseAfterReturn), - GlobalsMD(*GlobalsMD) { + GlobalsMD(*GlobalsMD), SSI(SSI) { C = &(M.getContext()); LongSize = M.getDataLayout().getPointerSizeInBits(); IntptrTy = Type::getIntNTy(*C, LongSize); @@ -686,7 +693,7 @@ /// Check if we want (and can) handle this alloca. bool isInterestingAlloca(const AllocaInst &AI); - bool ignoreAccess(Value *Ptr); + bool ignoreAccess(Instruction *Inst, Value *Ptr); void getInterestingMemoryOperands( Instruction *I, SmallVectorImpl<InterestingMemoryOperand> &Interesting); @@ -771,6 +778,7 @@ FunctionCallee AsanMemmove, AsanMemcpy, AsanMemset; Value *LocalDynamicShadow = nullptr; const GlobalsMetadata &GlobalsMD; + const StackSafetyGlobalInfo *SSI; DenseMap<const AllocaInst *, bool> ProcessedAllocas; FunctionCallee AMDGPUAddressShared; @@ -801,12 +809,16 @@ } bool runOnFunction(Function &F) override { + if (ClUseStackSafety) { + report_fatal_error("Stack safety analysis is not supported " + "with legacy pass manager."); + } GlobalsMetadata &GlobalsMD = getAnalysis<ASanGlobalsMetadataWrapperPass>().getGlobalsMD(); const TargetLibraryInfo *TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F); - AddressSanitizer ASan(*F.getParent(), &GlobalsMD, CompileKernel, Recover, - UseAfterScope, UseAfterReturn); + AddressSanitizer ASan(*F.getParent(), &GlobalsMD, nullptr, CompileKernel, + Recover, UseAfterScope, UseAfterReturn); return ASan.instrumentFunction(F, TLI); } @@ -1260,8 +1272,11 @@ Module &M = *F.getParent(); if (auto *R = MAMProxy.getCachedResult<ASanGlobalsMetadataAnalysis>(M)) { const TargetLibraryInfo *TLI = &AM.getResult<TargetLibraryAnalysis>(F); - AddressSanitizer Sanitizer(M, R, Options.CompileKernel, Options.Recover, - Options.UseAfterScope, Options.UseAfterReturn); + const StackSafetyGlobalInfo *SSI = + MAMProxy.getCachedResult<StackSafetyGlobalAnalysis>(M); + AddressSanitizer Sanitizer(M, R, SSI, Options.CompileKernel, + Options.Recover, Options.UseAfterScope, + Options.UseAfterReturn); if (Sanitizer.instrumentFunction(F, TLI)) return PreservedAnalyses::none(); return PreservedAnalyses::all(); @@ -1460,7 +1475,7 @@ return IsInteresting; } -bool AddressSanitizer::ignoreAccess(Value *Ptr) { +bool AddressSanitizer::ignoreAccess(Instruction *Inst, Value *Ptr) { // Instrument acesses from different address spaces only for AMDGPU. Type *PtrTy = cast<PointerType>(Ptr->getType()->getScalarType()); if (PtrTy->getPointerAddressSpace() != 0 && @@ -1481,6 +1496,12 @@ if (ClSkipPromotableAllocas && !isInterestingAlloca(*AI)) return true; + if (ClUseStackSafety && findAllocaForValue(Ptr)) { + if (SSI && SSI->stackAccessIsSafe(*Inst)) { + return true; + } + } + return false; } @@ -1495,22 +1516,22 @@ return; if (LoadInst *LI = dyn_cast<LoadInst>(I)) { - if (!ClInstrumentReads || ignoreAccess(LI->getPointerOperand())) + if (!ClInstrumentReads || ignoreAccess(I, LI->getPointerOperand())) return; Interesting.emplace_back(I, LI->getPointerOperandIndex(), false, LI->getType(), LI->getAlign()); } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) { - if (!ClInstrumentWrites || ignoreAccess(SI->getPointerOperand())) + if (!ClInstrumentWrites || ignoreAccess(I, SI->getPointerOperand())) return; Interesting.emplace_back(I, SI->getPointerOperandIndex(), true, SI->getValueOperand()->getType(), SI->getAlign()); } else if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(I)) { - if (!ClInstrumentAtomics || ignoreAccess(RMW->getPointerOperand())) + if (!ClInstrumentAtomics || ignoreAccess(I, RMW->getPointerOperand())) return; Interesting.emplace_back(I, RMW->getPointerOperandIndex(), true, RMW->getValOperand()->getType(), None); } else if (AtomicCmpXchgInst *XCHG = dyn_cast<AtomicCmpXchgInst>(I)) { - if (!ClInstrumentAtomics || ignoreAccess(XCHG->getPointerOperand())) + if (!ClInstrumentAtomics || ignoreAccess(I, XCHG->getPointerOperand())) return; Interesting.emplace_back(I, XCHG->getPointerOperandIndex(), true, XCHG->getCompareOperand()->getType(), None); @@ -1525,7 +1546,7 @@ return; auto BasePtr = CI->getOperand(OpOffset); - if (ignoreAccess(BasePtr)) + if (ignoreAccess(I, BasePtr)) return; auto Ty = cast<PointerType>(BasePtr->getType())->getElementType(); MaybeAlign Alignment = Align(1); @@ -1537,7 +1558,7 @@ } else { for (unsigned ArgNo = 0; ArgNo < CI->arg_size(); ArgNo++) { if (!ClInstrumentByval || !CI->isByValArgument(ArgNo) || - ignoreAccess(CI->getArgOperand(ArgNo))) + ignoreAccess(I, CI->getArgOperand(ArgNo))) continue; Type *Ty = CI->getParamByValType(ArgNo); Interesting.emplace_back(I, ArgNo, false, Ty, Align(1)); Index: llvm/include/llvm/Analysis/StackSafetyAnalysis.h =================================================================== --- llvm/include/llvm/Analysis/StackSafetyAnalysis.h +++ llvm/include/llvm/Analysis/StackSafetyAnalysis.h @@ -86,6 +86,17 @@ bool stackAccessIsSafe(const Instruction &I) const; void print(raw_ostream &O) const; void dump() const; + + /// Handle invalidation from the pass manager. + /// These results are never invalidated. + bool invalidate(Module &, const PreservedAnalyses &, + ModuleAnalysisManager::Invalidator &) { + return false; + } + bool invalidate(Function &, const PreservedAnalyses &, + FunctionAnalysisManager::Invalidator &) { + return false; + } }; /// StackSafetyInfo wrapper for the new pass manager. Index: clang/test/Driver/fsanitize.c =================================================================== --- clang/test/Driver/fsanitize.c +++ clang/test/Driver/fsanitize.c @@ -261,6 +261,22 @@ // RUN: FileCheck %s --check-prefix=CHECK-NO-CHECK-ASAN-CALLBACK // CHECK-NO-CHECK-ASAN-CALLBACK-NOT: "-mllvm" "-asan-instrumentation-with-call-threshold=0" +// RUN: %clang -target x86_64-linux-gnu -fsanitize-address-use-stack-safety %s -### 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CHECK-ASAN-OUTLINE-STACK-SAFETY-WARN +// CHECK-ASAN-OUTLINE-STACK-SAFETY-WARN: warning: argument unused during compilation: '-fsanitize-address-use-stack-safety' +// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-address-use-stack-safety %s -### 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CHECK-ASAN-OUTLINE-STACK-SAFETY-OK +// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fno-sanitize-address-use-stack-safety \ +// RUN: -fsanitize-address-use-stack-safety %s -### 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CHECK-ASAN-OUTLINE-STACK-SAFETY-OK +// CHECK-ASAN-OUTLINE-STACK-SAFETY-OK: "-fsanitize-address-use-stack-safety" "-mllvm" "-asan-use-stack-safety" +// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fno-sanitize-address-use-stack-safety %s -### 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CHECK-NO-CHECK-ASAN-CALLBACK +// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-address-use-stack-safety \ +// RUN: -fno-sanitize-address-use-stack-safety %s -### 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CHECK-NO-CHECK-ASAN-CALLBACK +// CHECK-NO-CHECK-ASAN-CALLBACK-NOT: "-fsanitize-address-use-stack-safety" "-mllvm" "-asan-use-stack-safety" + // RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-address-use-odr-indicator %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-ODR-INDICATOR // RUN: %clang_cl --target=x86_64-windows -fsanitize=address -fsanitize-address-use-odr-indicator -### -- %s 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-ODR-INDICATOR // CHECK-ASAN-ODR-INDICATOR: -cc1{{.*}}-fsanitize-address-use-odr-indicator Index: clang/test/CodeGen/asan-stack-safety-analysis.c =================================================================== --- /dev/null +++ clang/test/CodeGen/asan-stack-safety-analysis.c @@ -0,0 +1,13 @@ +// REQUIRES: x86-registered-target + +// RUN: %clang -fsanitize=address -fsanitize-address-outline-instrumentation -S -emit-llvm -O2 %s -o - | FileCheck %s --check-prefix=NOSAFETY +// RUN: %clang -fsanitize=address -fsanitize-address-outline-instrumentation -S -emit-llvm -fsanitize-address-use-stack-safety -O2 %s -o - | FileCheck %s --check-prefix=SAFETY + +int main(int argc, char **argv) { + char buf[10]; + volatile char *x = buf; + *x = 0; + return buf[0]; + // NOSAFETY: call void @__asan_store1 + // SAFETY-NOT: call void @__asan_store1 +} Index: clang/lib/Driver/SanitizerArgs.cpp =================================================================== --- clang/lib/Driver/SanitizerArgs.cpp +++ clang/lib/Driver/SanitizerArgs.cpp @@ -810,6 +810,10 @@ options::OPT_fno_sanitize_address_outline_instrumentation, AsanOutlineInstrumentation); + AsanUseStackSafety = Args.hasFlag( + options::OPT_fsanitize_address_use_stack_safety, + options::OPT_fno_sanitize_address_use_stack_safety, AsanUseStackSafety); + // As a workaround for a bug in gold 2.26 and earlier, dead stripping of // globals in ASan is disabled by default on ELF targets. // See https://sourceware.org/bugzilla/show_bug.cgi?id=19002 @@ -1128,6 +1132,12 @@ CmdArgs.push_back("-asan-instrumentation-with-call-threshold=0"); } + if (AsanUseStackSafety) { + CmdArgs.push_back("-fsanitize-address-use-stack-safety"); + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back("-asan-use-stack-safety"); + } + // Only pass the option to the frontend if the user requested, // otherwise the frontend will just use the codegen default. if (AsanDtorKind != llvm::AsanDtorKind::Invalid) { Index: clang/lib/CodeGen/BackendUtil.cpp =================================================================== --- clang/lib/CodeGen/BackendUtil.cpp +++ clang/lib/CodeGen/BackendUtil.cpp @@ -1185,6 +1185,9 @@ llvm::AsanDetectStackUseAfterReturnMode UseAfterReturn = CodeGenOpts.getSanitizeAddressUseAfterReturn(); MPM.addPass(RequireAnalysisPass<ASanGlobalsMetadataAnalysis, Module>()); + if (CodeGenOpts.SanitizeAddressUseStackSafety) { + MPM.addPass(RequireAnalysisPass<StackSafetyGlobalAnalysis, Module>()); + } MPM.addPass(ModuleAddressSanitizerPass( CompileKernel, Recover, ModuleUseAfterScope, UseOdrIndicator, DestructorKind)); Index: clang/include/clang/Driver/SanitizerArgs.h =================================================================== --- clang/include/clang/Driver/SanitizerArgs.h +++ clang/include/clang/Driver/SanitizerArgs.h @@ -45,6 +45,7 @@ bool AsanInvalidPointerCmp = false; bool AsanInvalidPointerSub = false; bool AsanOutlineInstrumentation = false; + bool AsanUseStackSafety = false; llvm::AsanDtorKind AsanDtorKind = llvm::AsanDtorKind::Invalid; std::string HwasanAbi; bool LinkRuntimes = true; Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -1599,6 +1599,11 @@ def fno_sanitize_address_outline_instrumentation : Flag<["-"], "fno-sanitize-address-outline-instrumentation">, Group<f_clang_Group>, HelpText<"Use default code inlining logic for the address sanitizer">; +defm sanitize_address_use_stack_safety : BoolOption<"f", "sanitize-address-use-stack-safety", + CodeGenOpts<"SanitizeAddressUseStackSafety">, DefaultFalse, + PosFlag<SetTrue, [CC1Option], "Enable">, NegFlag<SetFalse, [], "Disable">, + BothFlags<[], "Use stack safety result to optimize instrumentation">>, + Group<f_clang_Group>; def fsanitize_hwaddress_experimental_aliasing : Flag<["-"], "fsanitize-hwaddress-experimental-aliasing">, Group<f_clang_Group>, @@ -2430,13 +2435,13 @@ HelpText<"Enable debugging in the OpenMP offloading device RTL">; def fno_openmp_target_debug : Flag<["-"], "fno-openmp-target-debug">, Group<f_Group>, Flags<[NoArgumentUnused]>; def fopenmp_target_debug_EQ : Joined<["-"], "fopenmp-target-debug=">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused, HelpHidden]>; -def fopenmp_assume_teams_oversubscription : Flag<["-"], "fopenmp-assume-teams-oversubscription">, +def fopenmp_assume_teams_oversubscription : Flag<["-"], "fopenmp-assume-teams-oversubscription">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused, HelpHidden]>; -def fopenmp_assume_threads_oversubscription : Flag<["-"], "fopenmp-assume-threads-oversubscription">, +def fopenmp_assume_threads_oversubscription : Flag<["-"], "fopenmp-assume-threads-oversubscription">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused, HelpHidden]>; -def fno_openmp_assume_teams_oversubscription : Flag<["-"], "fno-openmp-assume-teams-oversubscription">, +def fno_openmp_assume_teams_oversubscription : Flag<["-"], "fno-openmp-assume-teams-oversubscription">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused, HelpHidden]>; -def fno_openmp_assume_threads_oversubscription : Flag<["-"], "fno-openmp-assume-threads-oversubscription">, +def fno_openmp_assume_threads_oversubscription : Flag<["-"], "fno-openmp-assume-threads-oversubscription">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused, HelpHidden]>; defm openmp_target_new_runtime: BoolFOption<"openmp-target-new-runtime", LangOpts<"OpenMPTargetNewRuntime">, DefaultFalse, Index: clang/include/clang/Basic/CodeGenOptions.def =================================================================== --- clang/include/clang/Basic/CodeGenOptions.def +++ clang/include/clang/Basic/CodeGenOptions.def @@ -224,6 +224,7 @@ CODEGENOPT(SanitizeAddressGlobalsDeadStripping, 1, 0) ///< Enable linker dead stripping ///< of globals in AddressSanitizer CODEGENOPT(SanitizeAddressUseOdrIndicator, 1, 0) ///< Enable ODR indicator globals +CODEGENOPT(SanitizeAddressUseStackSafety, 1, 0) ///< Use stack safety result. CODEGENOPT(SanitizeMemoryTrackOrigins, 2, 0) ///< Enable tracking origins in ///< MemorySanitizer ENUM_CODEGENOPT(SanitizeAddressDtor, llvm::AsanDtorKind, 2,
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits