/// based on tagged addressing.
//===----------------------------------------------------------------------===//
+#include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
/// An instrumentation pass implementing detection of addressability bugs
/// using tagged pointers.
-class HWAddressSanitizer : public FunctionPass {
+class HWAddressSanitizer {
public:
- // Pass identification, replacement for typeid.
- static char ID;
-
- explicit HWAddressSanitizer(bool CompileKernel = false, bool Recover = false)
- : FunctionPass(ID) {
+ explicit HWAddressSanitizer(Module &M, bool CompileKernel = false,
+ bool Recover = false) {
this->Recover = ClRecover.getNumOccurrences() > 0 ? ClRecover : Recover;
this->CompileKernel = ClEnableKhwasan.getNumOccurrences() > 0 ?
ClEnableKhwasan : CompileKernel;
- }
- StringRef getPassName() const override { return "HWAddressSanitizer"; }
+ initializeModule(M);
+ }
- bool runOnFunction(Function &F) override;
- bool doInitialization(Module &M) override;
+ bool sanitizeFunction(Function &F);
+ void initializeModule(Module &M);
void initializeCallbacks(Module &M);
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
-char HWAddressSanitizer::ID = 0;
+char HWAddressSanitizerLegacyPass::ID = 0;
INITIALIZE_PASS_BEGIN(
- HWAddressSanitizer, "hwasan",
+ HWAddressSanitizerLegacyPass, "hwasan",
"HWAddressSanitizer: detect memory bugs using tagged addressing.", false,
false)
INITIALIZE_PASS_END(
- HWAddressSanitizer, "hwasan",
+ HWAddressSanitizerLegacyPass, "hwasan",
"HWAddressSanitizer: detect memory bugs using tagged addressing.", false,
false)
-FunctionPass *llvm::createHWAddressSanitizerPass(bool CompileKernel,
- bool Recover) {
+FunctionPass *llvm::createHWAddressSanitizerLegacyPassPass(bool CompileKernel,
+ bool 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.
///
/// 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");
auto &DL = M.getDataLayout();
HwasanCtorFunction = nullptr;
if (!CompileKernel) {
std::tie(HwasanCtorFunction, std::ignore) =
- createSanitizerCtorAndInitFunctions(M, kHwasanModuleCtorName,
- kHwasanInitName,
- /*InitArgTypes=*/{},
- /*InitArgs=*/{});
- Comdat *CtorComdat = M.getOrInsertComdat(kHwasanModuleCtorName);
- HwasanCtorFunction->setComdat(CtorComdat);
- appendToGlobalCtors(M, HwasanCtorFunction, 0, HwasanCtorFunction);
+ getOrCreateSanitizerCtorAndInitFunctions(
+ M, kHwasanModuleCtorName, kHwasanInitName,
+ /*InitArgTypes=*/{},
+ /*InitArgs=*/{},
+ // This callback is invoked when the functions are created the first
+ // time. Hook them into the global ctors list in that case:
+ [&](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
// always create start and stop symbols.
// N.B. If we ever start creating associated metadata in this pass this
// global will need to be associated with the ctor.
Type *Int8Arr0Ty = ArrayType::get(Int8Ty, 0);
- auto GV =
- new GlobalVariable(M, Int8Arr0Ty, /*isConstantGlobal*/ true,
- GlobalVariable::PrivateLinkage,
- Constant::getNullValue(Int8Arr0Ty), "__hwasan");
- GV->setSection(getFrameSection());
- GV->setComdat(CtorComdat);
- appendToCompilerUsed(M, GV);
-
- IRBuilder<> IRBCtor(HwasanCtorFunction->getEntryBlock().getTerminator());
- IRBCtor.CreateCall(
- declareSanitizerInitFunction(M, "__hwasan_init_frames",
- {Int8PtrTy, Int8PtrTy}),
- {createFrameSectionBound(M, Int8Ty, getFrameSectionBeg()),
- createFrameSectionBound(M, Int8Ty, getFrameSectionEnd())});
+ M.getOrInsertGlobal("__hwasan", Int8Arr0Ty, [&] {
+ auto *GV = new GlobalVariable(
+ M, Int8Arr0Ty, /*isConstantGlobal=*/true, GlobalValue::PrivateLinkage,
+ Constant::getNullValue(Int8Arr0Ty), "__hwasan");
+ GV->setSection(getFrameSection());
+ Comdat *CtorComdat = M.getOrInsertComdat(kHwasanModuleCtorName);
+ GV->setComdat(CtorComdat);
+ appendToCompilerUsed(M, GV);
+ return GV;
+ });
}
- if (!TargetTriple.isAndroid())
- appendToCompilerUsed(
- M, ThreadPtrGlobal = new GlobalVariable(
- M, IntptrTy, false, GlobalVariable::ExternalLinkage, nullptr,
- "__hwasan_tls", nullptr, GlobalVariable::InitialExecTLSModel));
-
- return true;
+ if (!TargetTriple.isAndroid()) {
+ Constant *C = M.getOrInsertGlobal("__hwasan_tls", IntptrTy, [&] {
+ auto *GV = new GlobalVariable(M, IntptrTy, /*isConstantGlobal=*/false,
+ GlobalValue::ExternalLinkage, nullptr,
+ "__hwasan_tls", nullptr,
+ GlobalVariable::InitialExecTLSModel);
+ appendToCompilerUsed(M, GV);
+ return GV;
+ });
+ ThreadPtrGlobal = cast<GlobalVariable>(C);
+ }
}
void HWAddressSanitizer::initializeCallbacks(Module &M) {
!AI.isSwiftError());
}
-bool HWAddressSanitizer::runOnFunction(Function &F) {
+bool HWAddressSanitizer::sanitizeFunction(Function &F) {
if (&F == HwasanCtorFunction)
return false;