fmayer created this revision. Herald added subscribers: ormris, hiraditya. fmayer updated this revision to Diff 357514. fmayer added a comment. fmayer edited the summary of this revision. fmayer updated this revision to Diff 357544. fmayer edited the summary of this revision. fmayer updated this revision to Diff 357881. fmayer edited the summary of this revision. fmayer published this revision for review. fmayer added a reviewer: eugenis. Herald added projects: clang, LLVM. Herald added subscribers: llvm-commits, cfe-commits.
Change commit message. fmayer added a comment. Formatting again. fmayer added a comment. Formatting. This avoids unnecessary instrumentation. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D105703 Files: clang/lib/CodeGen/BackendUtil.cpp clang/test/CodeGen/hwasan-stack-safety-analysis-asm.c clang/test/CodeGen/hwasan-stack-safety-analysis.c llvm/include/llvm/Transforms/Instrumentation/HWAddressSanitizer.h llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
Index: llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp =================================================================== --- llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp +++ llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp @@ -17,6 +17,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" +#include "llvm/Analysis/StackSafetyAnalysis.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/BasicBlock.h" @@ -109,6 +110,10 @@ cl::desc("instrument stack (allocas)"), cl::Hidden, cl::init(true)); +static cl::opt<bool> + ClUseStackSafety("hwasan-use-stack-safety", cl::Hidden, cl::init(true), + cl::Hidden, cl::desc("Use Stack Safety analysis results")); + static cl::opt<bool> ClUARRetagToZero( "hwasan-uar-retag-to-zero", cl::desc("Clear alloca tags before returning from the function to allow " @@ -192,13 +197,31 @@ namespace { +bool shouldUsePageAliases(const Triple &TargetTriple) { + return ClUsePageAliases && TargetTriple.getArch() == Triple::x86_64; +// No one should use the option directly. +#pragma GCC poison ClUsePageAliases +} + +bool shouldInstrumentStack(const Triple &TargetTriple) { + return shouldUsePageAliases(TargetTriple) ? false : ClInstrumentStack; +// No one should use the option directly. +#pragma GCC poison ClInstrumentStack +} + +bool shouldUseStackSafetyAnalysis(const Triple &TargetTriple) { + return shouldInstrumentStack(TargetTriple) && ClUseStackSafety; +// No one should use the option directly. +#pragma GCC poison ClUseStackSafety +} /// An instrumentation pass implementing detection of addressability bugs /// using tagged pointers. class HWAddressSanitizer { public: explicit HWAddressSanitizer(Module &M, bool CompileKernel = false, - bool Recover = false) - : M(M) { + bool Recover = false, + const StackSafetyGlobalInfo *SSI = nullptr) + : M(M), SSI(SSI) { this->Recover = ClRecover.getNumOccurrences() > 0 ? ClRecover : Recover; this->CompileKernel = ClEnableKhwasan.getNumOccurrences() > 0 ? ClEnableKhwasan @@ -207,6 +230,8 @@ initializeModule(); } + void setSSI(const StackSafetyGlobalInfo *S) { SSI = S; } + bool sanitizeFunction(Function &F); void initializeModule(); void createHwasanCtorComdat(); @@ -259,6 +284,7 @@ private: LLVMContext *C; Module &M; + const StackSafetyGlobalInfo *SSI; Triple TargetTriple; FunctionCallee HWAsanMemmove, HWAsanMemcpy, HWAsanMemset; FunctionCallee HWAsanHandleVfork; @@ -329,8 +355,10 @@ static char ID; explicit HWAddressSanitizerLegacyPass(bool CompileKernel = false, - bool Recover = false) - : FunctionPass(ID), CompileKernel(CompileKernel), Recover(Recover) { + bool Recover = false, + Triple TargetTriple = {}) + : FunctionPass(ID), CompileKernel(CompileKernel), Recover(Recover), + TargetTriple(TargetTriple) { initializeHWAddressSanitizerLegacyPassPass( *PassRegistry::getPassRegistry()); } @@ -338,11 +366,18 @@ StringRef getPassName() const override { return "HWAddressSanitizer"; } bool doInitialization(Module &M) override { - HWASan = std::make_unique<HWAddressSanitizer>(M, CompileKernel, Recover); + HWASan = std::make_unique<HWAddressSanitizer>(M, CompileKernel, Recover, + /*SSI=*/nullptr); return true; } bool runOnFunction(Function &F) override { + if (shouldUseStackSafetyAnalysis(TargetTriple)) { + // We cannot call getAnalysis in doInitialization, that would cause a + // crash as the required analyses are not initialized yet. + HWASan->setSSI( + &getAnalysis<StackSafetyGlobalInfoWrapperPass>().getResult()); + } return HWASan->sanitizeFunction(F); } @@ -351,10 +386,18 @@ return false; } + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesCFG(); + if (shouldUseStackSafetyAnalysis(TargetTriple)) { + AU.addRequired<StackSafetyGlobalInfoWrapperPass>(); + } + } + private: std::unique_ptr<HWAddressSanitizer> HWASan; bool CompileKernel; bool Recover; + Triple TargetTriple; }; } // end anonymous namespace @@ -370,18 +413,25 @@ "HWAddressSanitizer: detect memory bugs using tagged addressing.", false, false) -FunctionPass *llvm::createHWAddressSanitizerLegacyPassPass(bool CompileKernel, - bool Recover) { +FunctionPass * +llvm::createHWAddressSanitizerLegacyPassPass(bool CompileKernel, bool Recover, + Triple TargetTriple) { assert(!CompileKernel || Recover); - return new HWAddressSanitizerLegacyPass(CompileKernel, Recover); + return new HWAddressSanitizerLegacyPass(CompileKernel, Recover, TargetTriple); } -HWAddressSanitizerPass::HWAddressSanitizerPass(bool CompileKernel, bool Recover) - : CompileKernel(CompileKernel), Recover(Recover) {} +HWAddressSanitizerPass::HWAddressSanitizerPass(bool CompileKernel, bool Recover, + Triple TargetTriple) + : CompileKernel(CompileKernel), Recover(Recover), + TargetTriple(TargetTriple) {} PreservedAnalyses HWAddressSanitizerPass::run(Module &M, ModuleAnalysisManager &MAM) { - HWAddressSanitizer HWASan(M, CompileKernel, Recover); + const StackSafetyGlobalInfo *SSI = nullptr; + if (shouldUseStackSafetyAnalysis(TargetTriple)) { + SSI = &MAM.getResult<StackSafetyGlobalAnalysis>(M); + } + HWAddressSanitizer HWASan(M, CompileKernel, Recover, SSI); bool Modified = false; for (Function &F : M) Modified |= HWASan.sanitizeFunction(F); @@ -503,9 +553,9 @@ // - Intel LAM (default) // - pointer aliasing (heap only) bool IsX86_64 = TargetTriple.getArch() == Triple::x86_64; - UsePageAliases = ClUsePageAliases && IsX86_64; + UsePageAliases = shouldUsePageAliases(TargetTriple); InstrumentWithCalls = IsX86_64 ? true : ClInstrumentWithCalls; - InstrumentStack = UsePageAliases ? false : ClInstrumentStack; + InstrumentStack = shouldInstrumentStack(TargetTriple); PointerTagShift = IsX86_64 ? 57 : 56; TagMaskByte = IsX86_64 ? 0x3F : 0xFF; @@ -1223,6 +1273,7 @@ } bool HWAddressSanitizer::isInterestingAlloca(const AllocaInst &AI) { + // clang-format off return (AI.getAllocatedType()->isSized() && // FIXME: instrument dynamic allocas, too AI.isStaticAlloca() && @@ -1235,7 +1286,10 @@ // dynamic alloca instrumentation for them as well. !AI.isUsedWithInAlloca() && // swifterror allocas are register promoted by ISel - !AI.isSwiftError()); + !AI.isSwiftError()) && + // safe allocas are not interesting + !(SSI && SSI->isSafe(AI)); + // clang-format on } bool HWAddressSanitizer::sanitizeFunction(Function &F) { Index: llvm/include/llvm/Transforms/Instrumentation/HWAddressSanitizer.h =================================================================== --- llvm/include/llvm/Transforms/Instrumentation/HWAddressSanitizer.h +++ llvm/include/llvm/Transforms/Instrumentation/HWAddressSanitizer.h @@ -14,6 +14,8 @@ #ifndef LLVM_TRANSFORMS_INSTRUMENTATION_HWADDRESSSANITIZER_H #define LLVM_TRANSFORMS_INSTRUMENTATION_HWADDRESSSANITIZER_H +#include "llvm/ADT/Triple.h" + #include "llvm/IR/Function.h" #include "llvm/IR/PassManager.h" @@ -25,17 +27,20 @@ class HWAddressSanitizerPass : public PassInfoMixin<HWAddressSanitizerPass> { public: explicit HWAddressSanitizerPass(bool CompileKernel = false, - bool Recover = false); + bool Recover = false, + Triple TargetTriple = {}); PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); static bool isRequired() { return true; } private: bool CompileKernel; bool Recover; + Triple TargetTriple; }; FunctionPass *createHWAddressSanitizerLegacyPassPass(bool CompileKernel = false, - bool Recover = false); + bool Recover = false, + Triple TargetTriple = {}); namespace HWASanAccessInfo { Index: clang/test/CodeGen/hwasan-stack-safety-analysis.c =================================================================== --- /dev/null +++ clang/test/CodeGen/hwasan-stack-safety-analysis.c @@ -0,0 +1,11 @@ +// RUN: %clang -fsanitize=hwaddress -target aarch64-linux-gnu -S -emit-llvm -mllvm -hwasan-use-stack-safety=true -mllvm -hwasan-generate-tags-with-calls -O2 %s -o - | FileCheck %s --check-prefix=SAFETY +// RUN: %clang -fsanitize=hwaddress -target aarch64-linux-gnu -S -emit-llvm -mllvm -hwasan-use-stack-safety=false -mllvm -hwasan-generate-tags-with-calls -O2 %s -o - | FileCheck %s --check-prefix=NOSAFETY + +int main(int argc, char **argv) { + char buf[10]; + volatile char *x = buf; + *x = 0; + return buf[0]; + // NOSAFETY: __hwasan_generate_tag + // SAFETY-NOT: __hwasan_generate_tag +} Index: clang/test/CodeGen/hwasan-stack-safety-analysis-asm.c =================================================================== --- /dev/null +++ clang/test/CodeGen/hwasan-stack-safety-analysis-asm.c @@ -0,0 +1,11 @@ +// RUN: %clang -fsanitize=hwaddress -target aarch64-linux-gnu -S -mllvm -hwasan-use-stack-safety=true -mllvm -hwasan-generate-tags-with-calls -O2 %s -o - | FileCheck %s --check-prefix=SAFETY +// RUN: %clang -fsanitize=hwaddress -target aarch64-linux-gnu -S -mllvm -hwasan-use-stack-safety=false -mllvm -hwasan-generate-tags-with-calls -O2 %s -o - | FileCheck %s --check-prefix=NOSAFETY + +int main(int argc, char **argv) { + char buf[10]; + volatile char *x = buf; + *x = 0; + return buf[0]; + // NOSAFETY: __hwasan_generate_tag + // SAFETY-NOT: __hwasan_generate_tag +} Index: clang/lib/CodeGen/BackendUtil.cpp =================================================================== --- clang/lib/CodeGen/BackendUtil.cpp +++ clang/lib/CodeGen/BackendUtil.cpp @@ -314,14 +314,17 @@ static_cast<const PassManagerBuilderWrapper &>(Builder); const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts(); bool Recover = CGOpts.SanitizeRecover.has(SanitizerKind::HWAddress); - PM.add( - createHWAddressSanitizerLegacyPassPass(/*CompileKernel*/ false, Recover)); + PM.add(createHWAddressSanitizerLegacyPassPass( + /*CompileKernel*/ false, Recover, BuilderWrapper.getTargetTriple())); } static void addKernelHWAddressSanitizerPasses(const PassManagerBuilder &Builder, legacy::PassManagerBase &PM) { + const PassManagerBuilderWrapper &BuilderWrapper = + static_cast<const PassManagerBuilderWrapper &>(Builder); PM.add(createHWAddressSanitizerLegacyPassPass( - /*CompileKernel*/ true, /*Recover*/ true)); + /*CompileKernel*/ true, /*Recover*/ true, + BuilderWrapper.getTargetTriple())); } static void addGeneralOptsForMemorySanitizer(const PassManagerBuilder &Builder, @@ -1164,7 +1167,8 @@ auto HWASanPass = [&](SanitizerMask Mask, bool CompileKernel) { if (LangOpts.Sanitize.has(Mask)) { bool Recover = CodeGenOpts.SanitizeRecover.has(Mask); - MPM.addPass(HWAddressSanitizerPass(CompileKernel, Recover)); + MPM.addPass( + HWAddressSanitizerPass(CompileKernel, Recover, TargetTriple)); } }; HWASanPass(SanitizerKind::HWAddress, false);
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits