[NewPM][MSan] Add Options Handling

Summary: This patch enables passing options to msan via the passes pipeline, e.e., -passes=msan<recover;kernel;track-origins=4>.

Reviewers: chandlerc, fedor.sergeev, leonardchan

Subscribers: hiraditya, bollu, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D57640

llvm-svn: 353090
This commit is contained in:
Philip Pfaffe 2019-02-04 21:02:49 +00:00
parent 90d856cd5f
commit 0ee6a933ce
7 changed files with 70 additions and 33 deletions

View File

@ -279,7 +279,8 @@ static void addGeneralOptsForMemorySanitizer(const PassManagerBuilder &Builder,
const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts(); const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts();
int TrackOrigins = CGOpts.SanitizeMemoryTrackOrigins; int TrackOrigins = CGOpts.SanitizeMemoryTrackOrigins;
bool Recover = CGOpts.SanitizeRecover.has(SanitizerKind::Memory); bool Recover = CGOpts.SanitizeRecover.has(SanitizerKind::Memory);
PM.add(createMemorySanitizerLegacyPassPass(TrackOrigins, Recover, CompileKernel)); PM.add(createMemorySanitizerLegacyPassPass(
MemorySanitizerOptions{TrackOrigins, Recover, CompileKernel}));
// MemorySanitizer inserts complex instrumentation that mostly follows // MemorySanitizer inserts complex instrumentation that mostly follows
// the logic of the original code, but operates on "shadow" values. // the logic of the original code, but operates on "shadow" values.
@ -1035,7 +1036,7 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
if (LangOpts.Sanitize.has(SanitizerKind::Memory)) if (LangOpts.Sanitize.has(SanitizerKind::Memory))
PB.registerOptimizerLastEPCallback( PB.registerOptimizerLastEPCallback(
[](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) { [](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) {
FPM.addPass(MemorySanitizerPass()); FPM.addPass(MemorySanitizerPass({}));
}); });
if (LangOpts.Sanitize.has(SanitizerKind::Thread)) if (LangOpts.Sanitize.has(SanitizerKind::Thread))
PB.registerOptimizerLastEPCallback( PB.registerOptimizerLastEPCallback(

View File

@ -18,10 +18,18 @@
namespace llvm { namespace llvm {
struct MemorySanitizerOptions {
MemorySanitizerOptions() = default;
MemorySanitizerOptions(int TrackOrigins, bool Recover, bool Kernel)
: TrackOrigins(TrackOrigins), Recover(Recover), Kernel(Kernel) {}
int TrackOrigins = 0;
bool Recover = false;
bool Kernel = false;
};
// Insert MemorySanitizer instrumentation (detection of uninitialized reads) // Insert MemorySanitizer instrumentation (detection of uninitialized reads)
FunctionPass *createMemorySanitizerLegacyPassPass(int TrackOrigins = 0, FunctionPass *
bool Recover = false, createMemorySanitizerLegacyPassPass(MemorySanitizerOptions Options = {});
bool EnableKmsan = false);
/// A function pass for msan instrumentation. /// A function pass for msan instrumentation.
/// ///
@ -30,17 +38,12 @@ FunctionPass *createMemorySanitizerLegacyPassPass(int TrackOrigins = 0,
/// yet, the pass inserts the declarations. Otherwise the existing globals are /// yet, the pass inserts the declarations. Otherwise the existing globals are
/// used. /// used.
struct MemorySanitizerPass : public PassInfoMixin<MemorySanitizerPass> { struct MemorySanitizerPass : public PassInfoMixin<MemorySanitizerPass> {
MemorySanitizerPass(int TrackOrigins = 0, bool Recover = false, MemorySanitizerPass(MemorySanitizerOptions Options) : Options(Options) {}
bool EnableKmsan = false)
: TrackOrigins(TrackOrigins), Recover(Recover), EnableKmsan(EnableKmsan) {
}
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM); PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM);
private: private:
int TrackOrigins; MemorySanitizerOptions Options;
bool Recover;
bool EnableKmsan;
}; };
} }

View File

@ -1335,6 +1335,34 @@ Expected<LoopUnrollOptions> parseLoopUnrollOptions(StringRef Params) {
return UnrollOpts; return UnrollOpts;
} }
Expected<MemorySanitizerOptions> parseMSanPassOptions(StringRef Params) {
MemorySanitizerOptions Result;
while (!Params.empty()) {
StringRef ParamName;
std::tie(ParamName, Params) = Params.split(';');
if (ParamName == "recover") {
Result.Recover = true;
} else if (ParamName == "kernel") {
Result.Kernel = true;
} else if (ParamName.consume_front("track-origins=")) {
if (ParamName.getAsInteger(0, Result.TrackOrigins))
return make_error<StringError>(
formatv("invalid argument to MemorySanitizer pass track-origins "
"parameter: '{0}' ",
ParamName)
.str(),
inconvertibleErrorCode());
} else {
return make_error<StringError>(
formatv("invalid MemorySanitizer pass parameter '{0}' ", ParamName)
.str(),
inconvertibleErrorCode());
}
}
return Result;
}
} // namespace } // namespace
/// Tests whether a pass name starts with a valid prefix for a default pipeline /// Tests whether a pass name starts with a valid prefix for a default pipeline

View File

@ -231,7 +231,7 @@ FUNCTION_PASS("verify<regions>", RegionInfoVerifierPass())
FUNCTION_PASS("view-cfg", CFGViewerPass()) FUNCTION_PASS("view-cfg", CFGViewerPass())
FUNCTION_PASS("view-cfg-only", CFGOnlyViewerPass()) FUNCTION_PASS("view-cfg-only", CFGOnlyViewerPass())
FUNCTION_PASS("transform-warning", WarnMissedTransformationsPass()) FUNCTION_PASS("transform-warning", WarnMissedTransformationsPass())
FUNCTION_PASS("msan", MemorySanitizerPass()) FUNCTION_PASS("msan", MemorySanitizerPass({}))
FUNCTION_PASS("tsan", ThreadSanitizerPass()) FUNCTION_PASS("tsan", ThreadSanitizerPass())
#undef FUNCTION_PASS #undef FUNCTION_PASS
@ -239,8 +239,15 @@ FUNCTION_PASS("tsan", ThreadSanitizerPass())
#define FUNCTION_PASS_WITH_PARAMS(NAME, CREATE_PASS, PARSER) #define FUNCTION_PASS_WITH_PARAMS(NAME, CREATE_PASS, PARSER)
#endif #endif
FUNCTION_PASS_WITH_PARAMS("unroll", FUNCTION_PASS_WITH_PARAMS("unroll",
[](LoopUnrollOptions Opts) { return LoopUnrollPass(Opts); }, [](LoopUnrollOptions Opts) {
parseLoopUnrollOptions) return LoopUnrollPass(Opts);
},
parseLoopUnrollOptions)
FUNCTION_PASS_WITH_PARAMS("msan",
[](MemorySanitizerOptions Opts) {
return MemorySanitizerPass(Opts);
},
parseMSanPassOptions)
#undef FUNCTION_PASS_WITH_PARAMS #undef FUNCTION_PASS_WITH_PARAMS
#ifndef LOOP_ANALYSIS #ifndef LOOP_ANALYSIS

View File

@ -454,17 +454,16 @@ namespace {
/// the module. /// the module.
class MemorySanitizer { class MemorySanitizer {
public: public:
MemorySanitizer(Module &M, int TrackOrigins = 0, bool Recover = false, MemorySanitizer(Module &M, MemorySanitizerOptions Options) {
bool EnableKmsan = false) {
this->CompileKernel = this->CompileKernel =
ClEnableKmsan.getNumOccurrences() > 0 ? ClEnableKmsan : EnableKmsan; ClEnableKmsan.getNumOccurrences() > 0 ? ClEnableKmsan : Options.Kernel;
if (ClTrackOrigins.getNumOccurrences() > 0) if (ClTrackOrigins.getNumOccurrences() > 0)
this->TrackOrigins = ClTrackOrigins; this->TrackOrigins = ClTrackOrigins;
else else
this->TrackOrigins = this->CompileKernel ? 2 : TrackOrigins; this->TrackOrigins = this->CompileKernel ? 2 : Options.TrackOrigins;
this->Recover = ClKeepGoing.getNumOccurrences() > 0 this->Recover = ClKeepGoing.getNumOccurrences() > 0
? ClKeepGoing ? ClKeepGoing
: (this->CompileKernel | Recover); : (this->CompileKernel | Options.Recover);
initializeModule(M); initializeModule(M);
} }
@ -598,10 +597,8 @@ struct MemorySanitizerLegacyPass : public FunctionPass {
// Pass identification, replacement for typeid. // Pass identification, replacement for typeid.
static char ID; static char ID;
MemorySanitizerLegacyPass(int TrackOrigins = 0, bool Recover = false, MemorySanitizerLegacyPass(MemorySanitizerOptions Options = {})
bool EnableKmsan = false) : FunctionPass(ID), Options(Options) {}
: FunctionPass(ID), TrackOrigins(TrackOrigins), Recover(Recover),
EnableKmsan(EnableKmsan) {}
StringRef getPassName() const override { return "MemorySanitizerLegacyPass"; } StringRef getPassName() const override { return "MemorySanitizerLegacyPass"; }
void getAnalysisUsage(AnalysisUsage &AU) const override { void getAnalysisUsage(AnalysisUsage &AU) const override {
@ -615,16 +612,14 @@ struct MemorySanitizerLegacyPass : public FunctionPass {
bool doInitialization(Module &M) override; bool doInitialization(Module &M) override;
Optional<MemorySanitizer> MSan; Optional<MemorySanitizer> MSan;
int TrackOrigins; MemorySanitizerOptions Options;
bool Recover;
bool EnableKmsan;
}; };
} // end anonymous namespace } // end anonymous namespace
PreservedAnalyses MemorySanitizerPass::run(Function &F, PreservedAnalyses MemorySanitizerPass::run(Function &F,
FunctionAnalysisManager &FAM) { FunctionAnalysisManager &FAM) {
MemorySanitizer Msan(*F.getParent(), TrackOrigins, Recover, EnableKmsan); MemorySanitizer Msan(*F.getParent(), Options);
if (Msan.sanitizeFunction(F, FAM.getResult<TargetLibraryAnalysis>(F))) if (Msan.sanitizeFunction(F, FAM.getResult<TargetLibraryAnalysis>(F)))
return PreservedAnalyses::none(); return PreservedAnalyses::none();
return PreservedAnalyses::all(); return PreservedAnalyses::all();
@ -640,10 +635,9 @@ INITIALIZE_PASS_END(MemorySanitizerLegacyPass, "msan",
"MemorySanitizer: detects uninitialized reads.", false, "MemorySanitizer: detects uninitialized reads.", false,
false) false)
FunctionPass *llvm::createMemorySanitizerLegacyPassPass(int TrackOrigins, FunctionPass *
bool Recover, llvm::createMemorySanitizerLegacyPassPass(MemorySanitizerOptions Options) {
bool CompileKernel) { return new MemorySanitizerLegacyPass(Options);
return new MemorySanitizerLegacyPass(TrackOrigins, Recover, CompileKernel);
} }
/// Create a non-const global initialized with the given string. /// Create a non-const global initialized with the given string.
@ -950,7 +944,7 @@ void MemorySanitizer::initializeModule(Module &M) {
} }
bool MemorySanitizerLegacyPass::doInitialization(Module &M) { bool MemorySanitizerLegacyPass::doInitialization(Module &M) {
MSan.emplace(M, TrackOrigins, Recover, EnableKmsan); MSan.emplace(M, Options);
return true; return true;
} }

View File

@ -3,6 +3,8 @@
; RUN: opt < %s -msan -msan-check-access-address=0 -S | FileCheck %s ; RUN: opt < %s -msan -msan-check-access-address=0 -S | FileCheck %s
; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=1 -S \ ; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=1 -S \
; RUN: -passes=msan 2>&1 | FileCheck %s "--check-prefixes=CHECK,CHECK-ORIGIN" ; RUN: -passes=msan 2>&1 | FileCheck %s "--check-prefixes=CHECK,CHECK-ORIGIN"
; RUN: opt < %s -msan-check-access-address=0 -S \
; RUN: -passes="msan<track-origins=1>" 2>&1 | FileCheck %s "--check-prefixes=CHECK,CHECK-ORIGIN"
; RUN: opt < %s -msan -msan-check-access-address=0 -msan-track-origins=1 -S | FileCheck %s --check-prefixes=CHECK,CHECK-ORIGIN ; RUN: opt < %s -msan -msan-check-access-address=0 -msan-track-origins=1 -S | FileCheck %s --check-prefixes=CHECK,CHECK-ORIGIN
; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=2 -S \ ; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=2 -S \
; RUN: -passes=msan 2>&1 | FileCheck %s "--check-prefixes=CHECK,CHECK-ORIGIN" ; RUN: -passes=msan 2>&1 | FileCheck %s "--check-prefixes=CHECK,CHECK-ORIGIN"

View File

@ -10,6 +10,8 @@
; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=2 -S \ ; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=2 -S \
; RUN: -passes=msan 2>&1 | FileCheck %s "--check-prefixes=CHECK,ORIGIN" ; RUN: -passes=msan 2>&1 | FileCheck %s "--check-prefixes=CHECK,ORIGIN"
; RUN: opt < %s -msan -msan-check-access-address=0 -msan-track-origins=2 -S | FileCheck %s --check-prefixes=CHECK,ORIGIN ; RUN: opt < %s -msan -msan-check-access-address=0 -msan-track-origins=2 -S | FileCheck %s --check-prefixes=CHECK,ORIGIN
; RUN: opt < %s -S -passes="msan<kernel>" 2>&1 | FileCheck %s \
; RUN: "--check-prefixes=CHECK,KMSAN"
; RUN: opt < %s -msan-kernel=1 -S -passes=msan 2>&1 | FileCheck %s \ ; RUN: opt < %s -msan-kernel=1 -S -passes=msan 2>&1 | FileCheck %s \
; RUN: "--check-prefixes=CHECK,KMSAN" ; RUN: "--check-prefixes=CHECK,KMSAN"
; RUN: opt < %s -msan -msan-kernel=1 -S | FileCheck %s --check-prefixes=CHECK,KMSAN ; RUN: opt < %s -msan -msan-kernel=1 -S | FileCheck %s --check-prefixes=CHECK,KMSAN