[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/BoundsChecking.h"
|
||||
#include "llvm/Transforms/Instrumentation/GCOVProfiler.h"
|
||||
#include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
|
||||
#include "llvm/Transforms/Instrumentation/InstrProfiling.h"
|
||||
#include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
|
||||
#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
|
||||
|
@ -265,12 +266,13 @@ static void addHWAddressSanitizerPasses(const PassManagerBuilder &Builder,
|
|||
static_cast<const PassManagerBuilderWrapper &>(Builder);
|
||||
const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts();
|
||||
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,
|
||||
legacy::PassManagerBase &PM) {
|
||||
PM.add(createHWAddressSanitizerPass(
|
||||
PM.add(createHWAddressSanitizerLegacyPassPass(
|
||||
/*CompileKernel*/ true, /*Recover*/ true));
|
||||
}
|
||||
|
||||
|
@ -962,6 +964,17 @@ static void addSanitizersAtO0(ModulePassManager &MPM,
|
|||
if (LangOpts.Sanitize.has(SanitizerKind::Thread)) {
|
||||
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.
|
||||
|
@ -1145,6 +1158,23 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
|
|||
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))
|
||||
PB.registerPipelineStartEPCallback([Options](ModulePassManager &MPM) {
|
||||
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 initializeGuardWideningLegacyPassPass(PassRegistry&);
|
||||
void initializeHotColdSplittingLegacyPassPass(PassRegistry&);
|
||||
void initializeHWAddressSanitizerPass(PassRegistry&);
|
||||
void initializeHWAddressSanitizerLegacyPassPass(PassRegistry &);
|
||||
void initializeIPCPPass(PassRegistry&);
|
||||
void initializeIPSCCPLegacyPassPass(PassRegistry&);
|
||||
void initializeIRCELegacyPassPass(PassRegistry&);
|
||||
|
|
|
@ -152,9 +152,6 @@ ModulePass *createInstrProfilingLegacyPass(
|
|||
|
||||
ModulePass *createInstrOrderFilePass();
|
||||
|
||||
FunctionPass *createHWAddressSanitizerPass(bool CompileKernel = false,
|
||||
bool Recover = false);
|
||||
|
||||
// Insert DataFlowSanitizer (dynamic data flow analysis) instrumentation
|
||||
ModulePass *createDataFlowSanitizerPass(
|
||||
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/ControlHeightReduction.h"
|
||||
#include "llvm/Transforms/Instrumentation/GCOVProfiler.h"
|
||||
#include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
|
||||
#include "llvm/Transforms/Instrumentation/InstrOrderFile.h"
|
||||
#include "llvm/Transforms/Instrumentation/InstrProfiling.h"
|
||||
#include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
|
||||
|
|
|
@ -237,6 +237,8 @@ FUNCTION_PASS("view-cfg-only", CFGOnlyViewerPass())
|
|||
FUNCTION_PASS("transform-warning", WarnMissedTransformationsPass())
|
||||
FUNCTION_PASS("asan", AddressSanitizerPass(false, 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("kmsan", MemorySanitizerPass({0, false, /*Kernel=*/true}))
|
||||
FUNCTION_PASS("tsan", ThreadSanitizerPass())
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
/// 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"
|
||||
|
@ -164,22 +165,19 @@ namespace {
|
|||
|
||||
/// 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;
|
||||
|
||||
initializeModule(M);
|
||||
}
|
||||
|
||||
StringRef getPassName() const override { return "HWAddressSanitizer"; }
|
||||
|
||||
bool runOnFunction(Function &F) override;
|
||||
bool doInitialization(Module &M) override;
|
||||
bool sanitizeFunction(Function &F);
|
||||
void initializeModule(Module &M);
|
||||
|
||||
void initializeCallbacks(Module &M);
|
||||
|
||||
|
@ -279,29 +277,61 @@ private:
|
|||
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,
|
||||
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();
|
||||
|
||||
|
@ -320,13 +350,24 @@ bool HWAddressSanitizer::doInitialization(Module &M) {
|
|||
HwasanCtorFunction = nullptr;
|
||||
if (!CompileKernel) {
|
||||
std::tie(HwasanCtorFunction, std::ignore) =
|
||||
createSanitizerCtorAndInitFunctions(M, kHwasanModuleCtorName,
|
||||
kHwasanInitName,
|
||||
getOrCreateSanitizerCtorAndInitFunctions(
|
||||
M, kHwasanModuleCtorName, kHwasanInitName,
|
||||
/*InitArgTypes=*/{},
|
||||
/*InitArgs=*/{});
|
||||
/*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);
|
||||
HwasanCtorFunction->setComdat(CtorComdat);
|
||||
appendToGlobalCtors(M, HwasanCtorFunction, 0, HwasanCtorFunction);
|
||||
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.
|
||||
|
@ -334,29 +375,29 @@ bool HWAddressSanitizer::doInitialization(Module &M) {
|
|||
// 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,
|
||||
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);
|
||||
|
||||
IRBuilder<> IRBCtor(HwasanCtorFunction->getEntryBlock().getTerminator());
|
||||
IRBCtor.CreateCall(
|
||||
declareSanitizerInitFunction(M, "__hwasan_init_frames",
|
||||
{Int8PtrTy, Int8PtrTy}),
|
||||
{createFrameSectionBound(M, Int8Ty, getFrameSectionBeg()),
|
||||
createFrameSectionBound(M, Int8Ty, getFrameSectionEnd())});
|
||||
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) {
|
||||
|
@ -970,7 +1011,7 @@ bool HWAddressSanitizer::isInterestingAlloca(const AllocaInst &AI) {
|
|||
!AI.isSwiftError());
|
||||
}
|
||||
|
||||
bool HWAddressSanitizer::runOnFunction(Function &F) {
|
||||
bool HWAddressSanitizer::sanitizeFunction(Function &F) {
|
||||
if (&F == HwasanCtorFunction)
|
||||
return false;
|
||||
|
||||
|
|
|
@ -114,7 +114,7 @@ void llvm::initializeInstrumentation(PassRegistry &Registry) {
|
|||
initializeInstrOrderFileLegacyPassPass(Registry);
|
||||
initializeInstrProfilingLegacyPassPass(Registry);
|
||||
initializeMemorySanitizerLegacyPassPass(Registry);
|
||||
initializeHWAddressSanitizerPass(Registry);
|
||||
initializeHWAddressSanitizerLegacyPassPass(Registry);
|
||||
initializeThreadSanitizerLegacyPassPass(Registry);
|
||||
initializeSanitizerCoverageModulePass(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=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: @__hwasan = private constant [0 x i8] zeroinitializer, section "__hwasan_frames", comdat($hwasan.module_ctor)
|
||||
|
||||
|
|
Loading…
Reference in New Issue