[NewPM] Port HWASan and Kernel HWASan
Port hardware assisted address sanitizer to new PM following the same guidelines as msan and tsan. Changes: - Separate HWAddressSanitizer into a pass class and a sanitizer class. - Create new PM wrapper pass for the sanitizer class. - Use the getOrINsert pattern for some module level initialization declarations. - Also enable kernel-kwasan in new PM - Update llvm tests and add clang test. Differential Revision: https://reviews.llvm.org/D61709 llvm-svn: 360707
This commit is contained in:
parent
7baf528aba
commit
0cdd3b1d81
|
@ -57,6 +57,7 @@
|
||||||
#include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
|
#include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
|
||||||
#include "llvm/Transforms/Instrumentation/BoundsChecking.h"
|
#include "llvm/Transforms/Instrumentation/BoundsChecking.h"
|
||||||
#include "llvm/Transforms/Instrumentation/GCOVProfiler.h"
|
#include "llvm/Transforms/Instrumentation/GCOVProfiler.h"
|
||||||
|
#include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
|
||||||
#include "llvm/Transforms/Instrumentation/InstrProfiling.h"
|
#include "llvm/Transforms/Instrumentation/InstrProfiling.h"
|
||||||
#include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
|
#include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
|
||||||
#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
|
#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
|
||||||
|
@ -265,12 +266,13 @@ static void addHWAddressSanitizerPasses(const PassManagerBuilder &Builder,
|
||||||
static_cast<const PassManagerBuilderWrapper &>(Builder);
|
static_cast<const PassManagerBuilderWrapper &>(Builder);
|
||||||
const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts();
|
const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts();
|
||||||
bool Recover = CGOpts.SanitizeRecover.has(SanitizerKind::HWAddress);
|
bool Recover = CGOpts.SanitizeRecover.has(SanitizerKind::HWAddress);
|
||||||
PM.add(createHWAddressSanitizerPass(/*CompileKernel*/ false, Recover));
|
PM.add(
|
||||||
|
createHWAddressSanitizerLegacyPassPass(/*CompileKernel*/ false, Recover));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void addKernelHWAddressSanitizerPasses(const PassManagerBuilder &Builder,
|
static void addKernelHWAddressSanitizerPasses(const PassManagerBuilder &Builder,
|
||||||
legacy::PassManagerBase &PM) {
|
legacy::PassManagerBase &PM) {
|
||||||
PM.add(createHWAddressSanitizerPass(
|
PM.add(createHWAddressSanitizerLegacyPassPass(
|
||||||
/*CompileKernel*/ true, /*Recover*/ true));
|
/*CompileKernel*/ true, /*Recover*/ true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -962,6 +964,17 @@ static void addSanitizersAtO0(ModulePassManager &MPM,
|
||||||
if (LangOpts.Sanitize.has(SanitizerKind::Thread)) {
|
if (LangOpts.Sanitize.has(SanitizerKind::Thread)) {
|
||||||
MPM.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass()));
|
MPM.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (LangOpts.Sanitize.has(SanitizerKind::HWAddress)) {
|
||||||
|
bool Recover = CodeGenOpts.SanitizeRecover.has(SanitizerKind::HWAddress);
|
||||||
|
MPM.addPass(createModuleToFunctionPassAdaptor(
|
||||||
|
HWAddressSanitizerPass(/*CompileKernel=*/false, Recover)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LangOpts.Sanitize.has(SanitizerKind::KernelHWAddress)) {
|
||||||
|
MPM.addPass(createModuleToFunctionPassAdaptor(
|
||||||
|
HWAddressSanitizerPass(/*CompileKernel=*/true, /*Recover=*/true)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A clean version of `EmitAssembly` that uses the new pass manager.
|
/// A clean version of `EmitAssembly` that uses the new pass manager.
|
||||||
|
@ -1145,6 +1158,23 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
|
||||||
UseOdrIndicator));
|
UseOdrIndicator));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (LangOpts.Sanitize.has(SanitizerKind::HWAddress)) {
|
||||||
|
bool Recover =
|
||||||
|
CodeGenOpts.SanitizeRecover.has(SanitizerKind::HWAddress);
|
||||||
|
PB.registerOptimizerLastEPCallback(
|
||||||
|
[Recover](FunctionPassManager &FPM,
|
||||||
|
PassBuilder::OptimizationLevel Level) {
|
||||||
|
FPM.addPass(HWAddressSanitizerPass(
|
||||||
|
/*CompileKernel=*/false, Recover));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (LangOpts.Sanitize.has(SanitizerKind::KernelHWAddress)) {
|
||||||
|
PB.registerOptimizerLastEPCallback(
|
||||||
|
[](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) {
|
||||||
|
FPM.addPass(HWAddressSanitizerPass(
|
||||||
|
/*CompileKernel=*/true, /*Recover=*/true));
|
||||||
|
});
|
||||||
|
}
|
||||||
if (Optional<GCOVOptions> Options = getGCOVOptions(CodeGenOpts))
|
if (Optional<GCOVOptions> Options = getGCOVOptions(CodeGenOpts))
|
||||||
PB.registerPipelineStartEPCallback([Options](ModulePassManager &MPM) {
|
PB.registerPipelineStartEPCallback([Options](ModulePassManager &MPM) {
|
||||||
MPM.addPass(GCOVProfilerPass(*Options));
|
MPM.addPass(GCOVProfilerPass(*Options));
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
// Test that HWASan and KHWASan runs with the new pass manager.
|
||||||
|
// We run them under different optimizations and LTOs to ensure the IR is still
|
||||||
|
// being instrumented properly.
|
||||||
|
|
||||||
|
// RUN: %clang_cc1 -S -emit-llvm -o - -fexperimental-new-pass-manager -fsanitize=hwaddress %s | FileCheck %s --check-prefixes=CHECK,HWASAN,HWASAN-NOOPT
|
||||||
|
// RUN: %clang_cc1 -S -emit-llvm -o - -fexperimental-new-pass-manager -fsanitize=hwaddress -flto %s | FileCheck %s --check-prefixes=CHECK,HWASAN,HWASAN-NOOPT
|
||||||
|
// RUN: %clang_cc1 -S -emit-llvm -o - -fexperimental-new-pass-manager -fsanitize=hwaddress -flto=thin %s | FileCheck %s --check-prefixes=CHECK,HWASAN,HWASAN-NOOPT
|
||||||
|
// RUN: %clang_cc1 -S -emit-llvm -o - -O1 -fexperimental-new-pass-manager -fsanitize=hwaddress %s | FileCheck %s --check-prefixes=CHECK,HWASAN
|
||||||
|
// RUN: %clang_cc1 -S -emit-llvm -o - -O1 -fexperimental-new-pass-manager -fsanitize=hwaddress -flto %s | FileCheck %s --check-prefixes=CHECK,HWASAN
|
||||||
|
// RUN: %clang_cc1 -S -emit-llvm -o - -O1 -fexperimental-new-pass-manager -fsanitize=hwaddress -flto=thin %s | FileCheck %s
|
||||||
|
|
||||||
|
// RUN: %clang_cc1 -S -emit-llvm -o - -fexperimental-new-pass-manager -fsanitize=kernel-hwaddress %s | FileCheck %s --check-prefixes=CHECK,KHWASAN,KHWASAN-NOOPT
|
||||||
|
// RUN: %clang_cc1 -S -emit-llvm -o - -fexperimental-new-pass-manager -fsanitize=kernel-hwaddress -flto %s | FileCheck %s --check-prefixes=CHECK,KHWASAN,KHWASAN-NOOPT
|
||||||
|
// RUN: %clang_cc1 -S -emit-llvm -o - -fexperimental-new-pass-manager -fsanitize=kernel-hwaddress -flto=thin %s | FileCheck %s --check-prefixes=CHECK,KHWASAN,KHWASAN-NOOPT
|
||||||
|
// RUN: %clang_cc1 -S -emit-llvm -o - -O1 -fexperimental-new-pass-manager -fsanitize=kernel-hwaddress %s | FileCheck %s --check-prefixes=CHECK,KHWASAN
|
||||||
|
// RUN: %clang_cc1 -S -emit-llvm -o - -O1 -fexperimental-new-pass-manager -fsanitize=kernel-hwaddress -flto %s | FileCheck %s --check-prefixes=CHECK,KHWASAN
|
||||||
|
// RUN: %clang_cc1 -S -emit-llvm -o - -O1 -fexperimental-new-pass-manager -fsanitize=kernel-hwaddress -flto=thin %s | FileCheck %s
|
||||||
|
|
||||||
|
int foo(int *a) { return *a; }
|
||||||
|
|
||||||
|
// All the cases above mark the function with sanitize_hwaddress.
|
||||||
|
// CHECK-DAG: sanitize_hwaddress
|
||||||
|
|
||||||
|
// Both sanitizers produce %hwasan.shadow without both thinlto and optimizations.
|
||||||
|
// HWASAN-DAG: %hwasan.shadow
|
||||||
|
// KHWASAN-DAG: %hwasan.shadow
|
||||||
|
|
||||||
|
// Both sanitizers produce __hwasan_tls without both thinlto and optimizations.
|
||||||
|
// HWASAN-DAG: __hwasan_tls
|
||||||
|
// KHWASAN-DAG: __hwasan_tls
|
||||||
|
|
||||||
|
// For unoptimized cases, both sanitizers produce different load functions.
|
||||||
|
// HWASAN-NOOPT-DAG: __hwasan_loadN
|
||||||
|
// KHWASAN-NOOPT-DAG: __hwasan_loadN_noabort
|
|
@ -163,7 +163,7 @@ void initializeGlobalSplitPass(PassRegistry&);
|
||||||
void initializeGlobalsAAWrapperPassPass(PassRegistry&);
|
void initializeGlobalsAAWrapperPassPass(PassRegistry&);
|
||||||
void initializeGuardWideningLegacyPassPass(PassRegistry&);
|
void initializeGuardWideningLegacyPassPass(PassRegistry&);
|
||||||
void initializeHotColdSplittingLegacyPassPass(PassRegistry&);
|
void initializeHotColdSplittingLegacyPassPass(PassRegistry&);
|
||||||
void initializeHWAddressSanitizerPass(PassRegistry&);
|
void initializeHWAddressSanitizerLegacyPassPass(PassRegistry &);
|
||||||
void initializeIPCPPass(PassRegistry&);
|
void initializeIPCPPass(PassRegistry&);
|
||||||
void initializeIPSCCPLegacyPassPass(PassRegistry&);
|
void initializeIPSCCPLegacyPassPass(PassRegistry&);
|
||||||
void initializeIRCELegacyPassPass(PassRegistry&);
|
void initializeIRCELegacyPassPass(PassRegistry&);
|
||||||
|
|
|
@ -152,9 +152,6 @@ ModulePass *createInstrProfilingLegacyPass(
|
||||||
|
|
||||||
ModulePass *createInstrOrderFilePass();
|
ModulePass *createInstrOrderFilePass();
|
||||||
|
|
||||||
FunctionPass *createHWAddressSanitizerPass(bool CompileKernel = false,
|
|
||||||
bool Recover = false);
|
|
||||||
|
|
||||||
// Insert DataFlowSanitizer (dynamic data flow analysis) instrumentation
|
// Insert DataFlowSanitizer (dynamic data flow analysis) instrumentation
|
||||||
ModulePass *createDataFlowSanitizerPass(
|
ModulePass *createDataFlowSanitizerPass(
|
||||||
const std::vector<std::string> &ABIListFiles = std::vector<std::string>(),
|
const std::vector<std::string> &ABIListFiles = std::vector<std::string>(),
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
//===--------- Definition of the HWAddressSanitizer class -------*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This file declares the Hardware AddressSanitizer class which is a port of the
|
||||||
|
// legacy HWAddressSanitizer pass to use the new PassManager infrastructure.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
#ifndef LLVM_TRANSFORMS_INSTRUMENTATION_HWADDRESSSANITIZERPASS_H
|
||||||
|
#define LLVM_TRANSFORMS_INSTRUMENTATION_HWADDRESSSANITIZERPASS_H
|
||||||
|
|
||||||
|
#include "llvm/IR/Function.h"
|
||||||
|
#include "llvm/IR/PassManager.h"
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
|
||||||
|
/// This is a public interface to the hardware address sanitizer pass for
|
||||||
|
/// instrumenting code to check for various memory errors at runtime, similar to
|
||||||
|
/// AddressSanitizer but based on partial hardware assistance.
|
||||||
|
class HWAddressSanitizerPass : public PassInfoMixin<HWAddressSanitizerPass> {
|
||||||
|
public:
|
||||||
|
explicit HWAddressSanitizerPass(bool CompileKernel = false,
|
||||||
|
bool Recover = false);
|
||||||
|
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool CompileKernel;
|
||||||
|
bool Recover;
|
||||||
|
};
|
||||||
|
|
||||||
|
FunctionPass *createHWAddressSanitizerLegacyPassPass(bool CompileKernel = false,
|
||||||
|
bool Recover = false);
|
||||||
|
|
||||||
|
} // namespace llvm
|
||||||
|
|
||||||
|
#endif
|
|
@ -94,6 +94,7 @@
|
||||||
#include "llvm/Transforms/Instrumentation/CGProfile.h"
|
#include "llvm/Transforms/Instrumentation/CGProfile.h"
|
||||||
#include "llvm/Transforms/Instrumentation/ControlHeightReduction.h"
|
#include "llvm/Transforms/Instrumentation/ControlHeightReduction.h"
|
||||||
#include "llvm/Transforms/Instrumentation/GCOVProfiler.h"
|
#include "llvm/Transforms/Instrumentation/GCOVProfiler.h"
|
||||||
|
#include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
|
||||||
#include "llvm/Transforms/Instrumentation/InstrOrderFile.h"
|
#include "llvm/Transforms/Instrumentation/InstrOrderFile.h"
|
||||||
#include "llvm/Transforms/Instrumentation/InstrProfiling.h"
|
#include "llvm/Transforms/Instrumentation/InstrProfiling.h"
|
||||||
#include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
|
#include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
|
||||||
|
|
|
@ -237,6 +237,8 @@ FUNCTION_PASS("view-cfg-only", CFGOnlyViewerPass())
|
||||||
FUNCTION_PASS("transform-warning", WarnMissedTransformationsPass())
|
FUNCTION_PASS("transform-warning", WarnMissedTransformationsPass())
|
||||||
FUNCTION_PASS("asan", AddressSanitizerPass(false, false, false))
|
FUNCTION_PASS("asan", AddressSanitizerPass(false, false, false))
|
||||||
FUNCTION_PASS("kasan", AddressSanitizerPass(true, false, false))
|
FUNCTION_PASS("kasan", AddressSanitizerPass(true, false, false))
|
||||||
|
FUNCTION_PASS("hwasan", HWAddressSanitizerPass(false, false))
|
||||||
|
FUNCTION_PASS("khwasan", HWAddressSanitizerPass(true, true))
|
||||||
FUNCTION_PASS("msan", MemorySanitizerPass({}))
|
FUNCTION_PASS("msan", MemorySanitizerPass({}))
|
||||||
FUNCTION_PASS("kmsan", MemorySanitizerPass({0, false, /*Kernel=*/true}))
|
FUNCTION_PASS("kmsan", MemorySanitizerPass({0, false, /*Kernel=*/true}))
|
||||||
FUNCTION_PASS("tsan", ThreadSanitizerPass())
|
FUNCTION_PASS("tsan", ThreadSanitizerPass())
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
/// based on tagged addressing.
|
/// based on tagged addressing.
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include "llvm/ADT/StringExtras.h"
|
#include "llvm/ADT/StringExtras.h"
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
|
@ -164,22 +165,19 @@ namespace {
|
||||||
|
|
||||||
/// An instrumentation pass implementing detection of addressability bugs
|
/// An instrumentation pass implementing detection of addressability bugs
|
||||||
/// using tagged pointers.
|
/// using tagged pointers.
|
||||||
class HWAddressSanitizer : public FunctionPass {
|
class HWAddressSanitizer {
|
||||||
public:
|
public:
|
||||||
// Pass identification, replacement for typeid.
|
explicit HWAddressSanitizer(Module &M, bool CompileKernel = false,
|
||||||
static char ID;
|
bool Recover = false) {
|
||||||
|
|
||||||
explicit HWAddressSanitizer(bool CompileKernel = false, bool Recover = false)
|
|
||||||
: FunctionPass(ID) {
|
|
||||||
this->Recover = ClRecover.getNumOccurrences() > 0 ? ClRecover : Recover;
|
this->Recover = ClRecover.getNumOccurrences() > 0 ? ClRecover : Recover;
|
||||||
this->CompileKernel = ClEnableKhwasan.getNumOccurrences() > 0 ?
|
this->CompileKernel = ClEnableKhwasan.getNumOccurrences() > 0 ?
|
||||||
ClEnableKhwasan : CompileKernel;
|
ClEnableKhwasan : CompileKernel;
|
||||||
|
|
||||||
|
initializeModule(M);
|
||||||
}
|
}
|
||||||
|
|
||||||
StringRef getPassName() const override { return "HWAddressSanitizer"; }
|
bool sanitizeFunction(Function &F);
|
||||||
|
void initializeModule(Module &M);
|
||||||
bool runOnFunction(Function &F) override;
|
|
||||||
bool doInitialization(Module &M) override;
|
|
||||||
|
|
||||||
void initializeCallbacks(Module &M);
|
void initializeCallbacks(Module &M);
|
||||||
|
|
||||||
|
@ -279,29 +277,61 @@ private:
|
||||||
GlobalValue *ThreadPtrGlobal = nullptr;
|
GlobalValue *ThreadPtrGlobal = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class HWAddressSanitizerLegacyPass : public FunctionPass {
|
||||||
|
public:
|
||||||
|
// Pass identification, replacement for typeid.
|
||||||
|
static char ID;
|
||||||
|
|
||||||
|
explicit HWAddressSanitizerLegacyPass(bool CompileKernel = false,
|
||||||
|
bool Recover = false)
|
||||||
|
: FunctionPass(ID), CompileKernel(CompileKernel), Recover(Recover) {}
|
||||||
|
|
||||||
|
StringRef getPassName() const override { return "HWAddressSanitizer"; }
|
||||||
|
|
||||||
|
bool runOnFunction(Function &F) override {
|
||||||
|
HWAddressSanitizer HWASan(*F.getParent(), CompileKernel, Recover);
|
||||||
|
return HWASan.sanitizeFunction(F);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool CompileKernel;
|
||||||
|
bool Recover;
|
||||||
|
};
|
||||||
|
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
|
||||||
char HWAddressSanitizer::ID = 0;
|
char HWAddressSanitizerLegacyPass::ID = 0;
|
||||||
|
|
||||||
INITIALIZE_PASS_BEGIN(
|
INITIALIZE_PASS_BEGIN(
|
||||||
HWAddressSanitizer, "hwasan",
|
HWAddressSanitizerLegacyPass, "hwasan",
|
||||||
"HWAddressSanitizer: detect memory bugs using tagged addressing.", false,
|
"HWAddressSanitizer: detect memory bugs using tagged addressing.", false,
|
||||||
false)
|
false)
|
||||||
INITIALIZE_PASS_END(
|
INITIALIZE_PASS_END(
|
||||||
HWAddressSanitizer, "hwasan",
|
HWAddressSanitizerLegacyPass, "hwasan",
|
||||||
"HWAddressSanitizer: detect memory bugs using tagged addressing.", false,
|
"HWAddressSanitizer: detect memory bugs using tagged addressing.", false,
|
||||||
false)
|
false)
|
||||||
|
|
||||||
FunctionPass *llvm::createHWAddressSanitizerPass(bool CompileKernel,
|
FunctionPass *llvm::createHWAddressSanitizerLegacyPassPass(bool CompileKernel,
|
||||||
bool Recover) {
|
bool Recover) {
|
||||||
assert(!CompileKernel || Recover);
|
assert(!CompileKernel || Recover);
|
||||||
return new HWAddressSanitizer(CompileKernel, Recover);
|
return new HWAddressSanitizerLegacyPass(CompileKernel, Recover);
|
||||||
|
}
|
||||||
|
|
||||||
|
HWAddressSanitizerPass::HWAddressSanitizerPass(bool CompileKernel, bool Recover)
|
||||||
|
: CompileKernel(CompileKernel), Recover(Recover) {}
|
||||||
|
|
||||||
|
PreservedAnalyses HWAddressSanitizerPass::run(Function &F,
|
||||||
|
FunctionAnalysisManager &FAM) {
|
||||||
|
HWAddressSanitizer HWASan(*F.getParent(), CompileKernel, Recover);
|
||||||
|
if (HWASan.sanitizeFunction(F))
|
||||||
|
return PreservedAnalyses::none();
|
||||||
|
return PreservedAnalyses::all();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Module-level initialization.
|
/// Module-level initialization.
|
||||||
///
|
///
|
||||||
/// inserts a call to __hwasan_init to the module's constructor list.
|
/// inserts a call to __hwasan_init to the module's constructor list.
|
||||||
bool HWAddressSanitizer::doInitialization(Module &M) {
|
void HWAddressSanitizer::initializeModule(Module &M) {
|
||||||
LLVM_DEBUG(dbgs() << "Init " << M.getName() << "\n");
|
LLVM_DEBUG(dbgs() << "Init " << M.getName() << "\n");
|
||||||
auto &DL = M.getDataLayout();
|
auto &DL = M.getDataLayout();
|
||||||
|
|
||||||
|
@ -320,13 +350,24 @@ bool HWAddressSanitizer::doInitialization(Module &M) {
|
||||||
HwasanCtorFunction = nullptr;
|
HwasanCtorFunction = nullptr;
|
||||||
if (!CompileKernel) {
|
if (!CompileKernel) {
|
||||||
std::tie(HwasanCtorFunction, std::ignore) =
|
std::tie(HwasanCtorFunction, std::ignore) =
|
||||||
createSanitizerCtorAndInitFunctions(M, kHwasanModuleCtorName,
|
getOrCreateSanitizerCtorAndInitFunctions(
|
||||||
kHwasanInitName,
|
M, kHwasanModuleCtorName, kHwasanInitName,
|
||||||
/*InitArgTypes=*/{},
|
/*InitArgTypes=*/{},
|
||||||
/*InitArgs=*/{});
|
/*InitArgs=*/{},
|
||||||
Comdat *CtorComdat = M.getOrInsertComdat(kHwasanModuleCtorName);
|
// This callback is invoked when the functions are created the first
|
||||||
HwasanCtorFunction->setComdat(CtorComdat);
|
// time. Hook them into the global ctors list in that case:
|
||||||
appendToGlobalCtors(M, HwasanCtorFunction, 0, HwasanCtorFunction);
|
[&](Function *Ctor, FunctionCallee) {
|
||||||
|
Comdat *CtorComdat = M.getOrInsertComdat(kHwasanModuleCtorName);
|
||||||
|
Ctor->setComdat(CtorComdat);
|
||||||
|
appendToGlobalCtors(M, Ctor, 0, Ctor);
|
||||||
|
|
||||||
|
IRBuilder<> IRBCtor(Ctor->getEntryBlock().getTerminator());
|
||||||
|
IRBCtor.CreateCall(
|
||||||
|
declareSanitizerInitFunction(M, "__hwasan_init_frames",
|
||||||
|
{Int8PtrTy, Int8PtrTy}),
|
||||||
|
{createFrameSectionBound(M, Int8Ty, getFrameSectionBeg()),
|
||||||
|
createFrameSectionBound(M, Int8Ty, getFrameSectionEnd())});
|
||||||
|
});
|
||||||
|
|
||||||
// Create a zero-length global in __hwasan_frame so that the linker will
|
// Create a zero-length global in __hwasan_frame so that the linker will
|
||||||
// always create start and stop symbols.
|
// always create start and stop symbols.
|
||||||
|
@ -334,29 +375,29 @@ bool HWAddressSanitizer::doInitialization(Module &M) {
|
||||||
// N.B. If we ever start creating associated metadata in this pass this
|
// N.B. If we ever start creating associated metadata in this pass this
|
||||||
// global will need to be associated with the ctor.
|
// global will need to be associated with the ctor.
|
||||||
Type *Int8Arr0Ty = ArrayType::get(Int8Ty, 0);
|
Type *Int8Arr0Ty = ArrayType::get(Int8Ty, 0);
|
||||||
auto GV =
|
M.getOrInsertGlobal("__hwasan", Int8Arr0Ty, [&] {
|
||||||
new GlobalVariable(M, Int8Arr0Ty, /*isConstantGlobal*/ true,
|
auto *GV = new GlobalVariable(
|
||||||
GlobalVariable::PrivateLinkage,
|
M, Int8Arr0Ty, /*isConstantGlobal=*/true, GlobalValue::PrivateLinkage,
|
||||||
Constant::getNullValue(Int8Arr0Ty), "__hwasan");
|
Constant::getNullValue(Int8Arr0Ty), "__hwasan");
|
||||||
GV->setSection(getFrameSection());
|
GV->setSection(getFrameSection());
|
||||||
GV->setComdat(CtorComdat);
|
Comdat *CtorComdat = M.getOrInsertComdat(kHwasanModuleCtorName);
|
||||||
appendToCompilerUsed(M, GV);
|
GV->setComdat(CtorComdat);
|
||||||
|
appendToCompilerUsed(M, GV);
|
||||||
IRBuilder<> IRBCtor(HwasanCtorFunction->getEntryBlock().getTerminator());
|
return GV;
|
||||||
IRBCtor.CreateCall(
|
});
|
||||||
declareSanitizerInitFunction(M, "__hwasan_init_frames",
|
|
||||||
{Int8PtrTy, Int8PtrTy}),
|
|
||||||
{createFrameSectionBound(M, Int8Ty, getFrameSectionBeg()),
|
|
||||||
createFrameSectionBound(M, Int8Ty, getFrameSectionEnd())});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!TargetTriple.isAndroid())
|
if (!TargetTriple.isAndroid()) {
|
||||||
appendToCompilerUsed(
|
Constant *C = M.getOrInsertGlobal("__hwasan_tls", IntptrTy, [&] {
|
||||||
M, ThreadPtrGlobal = new GlobalVariable(
|
auto *GV = new GlobalVariable(M, IntptrTy, /*isConstantGlobal=*/false,
|
||||||
M, IntptrTy, false, GlobalVariable::ExternalLinkage, nullptr,
|
GlobalValue::ExternalLinkage, nullptr,
|
||||||
"__hwasan_tls", nullptr, GlobalVariable::InitialExecTLSModel));
|
"__hwasan_tls", nullptr,
|
||||||
|
GlobalVariable::InitialExecTLSModel);
|
||||||
return true;
|
appendToCompilerUsed(M, GV);
|
||||||
|
return GV;
|
||||||
|
});
|
||||||
|
ThreadPtrGlobal = cast<GlobalVariable>(C);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HWAddressSanitizer::initializeCallbacks(Module &M) {
|
void HWAddressSanitizer::initializeCallbacks(Module &M) {
|
||||||
|
@ -970,7 +1011,7 @@ bool HWAddressSanitizer::isInterestingAlloca(const AllocaInst &AI) {
|
||||||
!AI.isSwiftError());
|
!AI.isSwiftError());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HWAddressSanitizer::runOnFunction(Function &F) {
|
bool HWAddressSanitizer::sanitizeFunction(Function &F) {
|
||||||
if (&F == HwasanCtorFunction)
|
if (&F == HwasanCtorFunction)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
@ -114,7 +114,7 @@ void llvm::initializeInstrumentation(PassRegistry &Registry) {
|
||||||
initializeInstrOrderFileLegacyPassPass(Registry);
|
initializeInstrOrderFileLegacyPassPass(Registry);
|
||||||
initializeInstrProfilingLegacyPassPass(Registry);
|
initializeInstrProfilingLegacyPassPass(Registry);
|
||||||
initializeMemorySanitizerLegacyPassPass(Registry);
|
initializeMemorySanitizerLegacyPassPass(Registry);
|
||||||
initializeHWAddressSanitizerPass(Registry);
|
initializeHWAddressSanitizerLegacyPassPass(Registry);
|
||||||
initializeThreadSanitizerLegacyPassPass(Registry);
|
initializeThreadSanitizerLegacyPassPass(Registry);
|
||||||
initializeSanitizerCoverageModulePass(Registry);
|
initializeSanitizerCoverageModulePass(Registry);
|
||||||
initializeDataFlowSanitizerPass(Registry);
|
initializeDataFlowSanitizerPass(Registry);
|
||||||
|
|
|
@ -5,6 +5,12 @@
|
||||||
; RUN: opt < %s -hwasan -hwasan-recover=0 -hwasan-mapping-offset=0 -S | FileCheck %s --check-prefixes=CHECK,ABORT,ABORT-ZERO-BASED-SHADOW
|
; RUN: opt < %s -hwasan -hwasan-recover=0 -hwasan-mapping-offset=0 -S | FileCheck %s --check-prefixes=CHECK,ABORT,ABORT-ZERO-BASED-SHADOW
|
||||||
; RUN: opt < %s -hwasan -hwasan-recover=1 -hwasan-mapping-offset=0 -S | FileCheck %s --check-prefixes=CHECK,RECOVER,RECOVER-ZERO-BASED-SHADOW
|
; RUN: opt < %s -hwasan -hwasan-recover=1 -hwasan-mapping-offset=0 -S | FileCheck %s --check-prefixes=CHECK,RECOVER,RECOVER-ZERO-BASED-SHADOW
|
||||||
|
|
||||||
|
; Ensure than hwasan runs with the new PM pass
|
||||||
|
; RUN: opt < %s -passes='function(hwasan)' -hwasan-recover=0 -hwasan-with-ifunc=1 -hwasan-with-tls=0 -S | FileCheck %s --check-prefixes=CHECK,ABORT,ABORT-DYNAMIC-SHADOW
|
||||||
|
; RUN: opt < %s -passes='function(hwasan)' -hwasan-recover=1 -hwasan-with-ifunc=1 -hwasan-with-tls=0 -S | FileCheck %s --check-prefixes=CHECK,RECOVER,RECOVER-DYNAMIC-SHADOW
|
||||||
|
; RUN: opt < %s -passes='function(hwasan)' -hwasan-recover=0 -hwasan-mapping-offset=0 -S | FileCheck %s --check-prefixes=CHECK,ABORT,ABORT-ZERO-BASED-SHADOW
|
||||||
|
; RUN: opt < %s -passes='function(hwasan)' -hwasan-recover=1 -hwasan-mapping-offset=0 -S | FileCheck %s --check-prefixes=CHECK,RECOVER,RECOVER-ZERO-BASED-SHADOW
|
||||||
|
|
||||||
; CHECK: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @hwasan.module_ctor, i8* bitcast (void ()* @hwasan.module_ctor to i8*) }]
|
; CHECK: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @hwasan.module_ctor, i8* bitcast (void ()* @hwasan.module_ctor to i8*) }]
|
||||||
; CHECK: @__hwasan = private constant [0 x i8] zeroinitializer, section "__hwasan_frames", comdat($hwasan.module_ctor)
|
; CHECK: @__hwasan = private constant [0 x i8] zeroinitializer, section "__hwasan_frames", comdat($hwasan.module_ctor)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue