Skip to content

Commit

Permalink
[msan] Convert Msan to ModulePass
Browse files Browse the repository at this point in the history
MemorySanitizerPass function pass violatied requirement 4 of function
pass to do not insert globals. Msan nees to insert globals for origin
tracking, and paramereters tracking.

https://llvm.org/docs/WritingAnLLVMPass.html#the-functionpass-class

Reviewed By: kstoimenov, fmayer

Differential Revision: https://reviews.llvm.org/D133336
  • Loading branch information
vitalybuka committed Sep 6, 2022
1 parent 82b6549 commit e7bac3b
Show file tree
Hide file tree
Showing 16 changed files with 48 additions and 63 deletions.
5 changes: 1 addition & 4 deletions clang/lib/CodeGen/BackendUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -640,21 +640,18 @@ static void addSanitizers(const Triple &TargetTriple,
MemorySanitizerOptions options(TrackOrigins, Recover, CompileKernel,
CodeGenOpts.SanitizeMemoryParamRetval);
MPM.addPass(ModuleMemorySanitizerPass(options));
FunctionPassManager FPM;
FPM.addPass(MemorySanitizerPass(options));
if (Level != OptimizationLevel::O0) {
// MemorySanitizer inserts complex instrumentation that mostly
// follows the logic of the original code, but operates on
// "shadow" values. It can benefit from re-running some
// general purpose optimization passes.
FPM.addPass(EarlyCSEPass());
MPM.addPass(createModuleToFunctionPassAdaptor(EarlyCSEPass()));
// TODO: Consider add more passes like in
// addGeneralOptsForMemorySanitizer. EarlyCSEPass makes visible
// difference on size. It's not clear if the rest is still
// usefull. InstCombinePass breakes
// compiler-rt/test/msan/select_origin.cpp.
}
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
}
};
MSanPass(SanitizerKind::Memory, false);
Expand Down
20 changes: 2 additions & 18 deletions llvm/include/llvm/Transforms/Instrumentation/MemorySanitizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,24 +34,6 @@ struct MemorySanitizerOptions {
bool EagerChecks;
};

/// A function pass for msan instrumentation.
///
/// Instruments functions to detect unitialized reads. This function pass
/// inserts calls to runtime library functions. If the functions aren't declared
/// yet, the pass inserts the declarations. Otherwise the existing globals are
/// used.
struct MemorySanitizerPass : public PassInfoMixin<MemorySanitizerPass> {
MemorySanitizerPass(MemorySanitizerOptions Options) : Options(Options) {}

PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM);
void printPipeline(raw_ostream &OS,
function_ref<StringRef(StringRef)> MapClassName2PassName);
static bool isRequired() { return true; }

private:
MemorySanitizerOptions Options;
};

/// A module pass for msan instrumentation.
///
/// Instruments functions to detect unitialized reads. This function pass
Expand All @@ -62,6 +44,8 @@ struct ModuleMemorySanitizerPass : public PassInfoMixin<ModuleMemorySanitizerPas
ModuleMemorySanitizerPass(MemorySanitizerOptions Options) : Options(Options) {}

PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
void printPipeline(raw_ostream &OS,
function_ref<StringRef(StringRef)> MapClassName2PassName);
static bool isRequired() { return true; }

private:
Expand Down
15 changes: 7 additions & 8 deletions llvm/lib/Passes/PassRegistry.def
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,6 @@ MODULE_PASS("verify", VerifierPass())
MODULE_PASS("view-callgraph", CallGraphViewerPass())
MODULE_PASS("wholeprogramdevirt", WholeProgramDevirtPass())
MODULE_PASS("dfsan", DataFlowSanitizerPass())
MODULE_PASS("msan-module", ModuleMemorySanitizerPass({}))
MODULE_PASS("module-inline", ModuleInlinerPass())
MODULE_PASS("tsan-module", ModuleThreadSanitizerPass())
MODULE_PASS("sancov-module", ModuleSanitizerCoveragePass())
Expand Down Expand Up @@ -154,6 +153,13 @@ MODULE_PASS_WITH_PARAMS("asan-module",
},
parseASanPassOptions,
"kernel")
MODULE_PASS_WITH_PARAMS("msan",
"ModuleMemorySanitizerPass",
[](MemorySanitizerOptions Opts) {
return ModuleMemorySanitizerPass(Opts);
},
parseMSanPassOptions,
"recover;kernel;eager-checks;track-origins=N")
#undef MODULE_PASS_WITH_PARAMS

#ifndef CGSCC_ANALYSIS
Expand Down Expand Up @@ -420,13 +426,6 @@ FUNCTION_PASS_WITH_PARAMS("loop-unroll",
"no-profile-peeling;profile-peeling;"
"no-runtime;runtime;"
"no-upperbound;upperbound")
FUNCTION_PASS_WITH_PARAMS("msan",
"MemorySanitizerPass",
[](MemorySanitizerOptions Opts) {
return MemorySanitizerPass(Opts);
},
parseMSanPassOptions,
"recover;kernel;eager-checks;track-origins=N")
FUNCTION_PASS_WITH_PARAMS("simplifycfg",
"SimplifyCFGPass",
[](SimplifyCFGOptions Opts) {
Expand Down
31 changes: 17 additions & 14 deletions llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -669,25 +669,28 @@ MemorySanitizerOptions::MemorySanitizerOptions(int TO, bool R, bool K,
Recover(getOptOrDefault(ClKeepGoing, Kernel || R)),
EagerChecks(getOptOrDefault(ClEagerChecks, EagerChecks)) {}

PreservedAnalyses MemorySanitizerPass::run(Function &F,
FunctionAnalysisManager &FAM) {
MemorySanitizer Msan(*F.getParent(), Options);
if (Msan.sanitizeFunction(F, FAM.getResult<TargetLibraryAnalysis>(F)))
return PreservedAnalyses::none();
return PreservedAnalyses::all();
}

PreservedAnalyses ModuleMemorySanitizerPass::run(Module &M,
ModuleAnalysisManager &AM) {
if (Options.Kernel)
return PreservedAnalyses::all();
insertModuleCtor(M);
return PreservedAnalyses::none();
bool Modified = false;
if (!Options.Kernel) {
insertModuleCtor(M);
Modified = true;
}

auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
for (Function &F : M) {
if (F.empty())
continue;
MemorySanitizer Msan(*F.getParent(), Options);
Modified |=
Msan.sanitizeFunction(F, FAM.getResult<TargetLibraryAnalysis>(F));
}
return Modified ? PreservedAnalyses::none() : PreservedAnalyses::all();
}

void MemorySanitizerPass::printPipeline(
void ModuleMemorySanitizerPass::printPipeline(
raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {
static_cast<PassInfoMixin<MemorySanitizerPass> *>(this)->printPipeline(
static_cast<PassInfoMixin<ModuleMemorySanitizerPass> *>(this)->printPipeline(
OS, MapClassName2PassName);
OS << "<";
if (Options.Recover)
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/Instrumentation/MemorySanitizer/attributes.ll
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
; RUN: opt < %s -S -passes='module(msan-module),function(msan)' 2>&1 | FileCheck %s
; RUN: opt < %s -S -passes='module(msan)' 2>&1 | FileCheck %s

target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/Instrumentation/MemorySanitizer/check-array.ll
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
; RUN: opt < %s -msan-eager-checks -msan-check-access-address=0 -msan-track-origins=1 -S -passes='module(msan-module),function(msan)' 2>&1 | \
; RUN: opt < %s -msan-eager-checks -msan-check-access-address=0 -msan-track-origins=1 -S -passes='module(msan)' 2>&1 | \
; RUN: FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK %s

target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,5 @@ entry:
; CHECK-LABEL: @MaybeUninitializedRetNoUndef
; CONST: br i1 icmp ne (i32 extractelement (<4 x i32> bitcast (<2 x i64> <i64 0, i64 undef> to <4 x i32>), i64 0), i32 0)
; CONST: call void @__msan_warning_with_origin_noreturn

; CHECK: call void @__msan_init()
2 changes: 1 addition & 1 deletion llvm/test/Instrumentation/MemorySanitizer/check-struct.ll
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=1 -S -passes='module(msan-module),function(msan)' 2>&1 | \
; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=1 -S -passes='module(msan)' 2>&1 | \
; RUN: FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK %s

target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
; Test for -msan-disable-checks, which should treat every function in the file
; as if it didn't have the sanitize_memory attribute.
; RUN: opt < %s -msan-check-access-address=0 -S -passes='module(msan-module),function(msan)' 2>&1 | FileCheck -allow-deprecated-dag-overlap -check-prefixes=CHECK,INSTR %s
; RUN: opt < %s -msan-check-access-address=0 -S -passes='module(msan-module),function(msan)' -msan-disable-checks=1 2>&1 | FileCheck -allow-deprecated-dag-overlap -check-prefixes=CHECK,NOSANITIZE %s
; RUN: opt < %s -msan-check-access-address=0 -S -passes='module(msan)' 2>&1 | FileCheck -allow-deprecated-dag-overlap -check-prefixes=CHECK,INSTR %s
; RUN: opt < %s -msan-check-access-address=0 -S -passes='module(msan)' -msan-disable-checks=1 2>&1 | FileCheck -allow-deprecated-dag-overlap -check-prefixes=CHECK,NOSANITIZE %s

target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
Expand Down
10 changes: 5 additions & 5 deletions llvm/test/Instrumentation/MemorySanitizer/msan_basic.ll
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
; RUN: opt < %s -msan-check-access-address=0 -S -passes='module(msan-module),function(msan)' 2>&1 | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=CHECK,NOORIGINS --implicit-check-not="call void @__msan_warning"
; RUN: opt < %s --passes='module(msan-module),function(msan)' -msan-check-access-address=0 -S | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=CHECK,NOORIGINS --implicit-check-not="call void @__msan_warning"
; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=1 -S -passes='module(msan-module),function(msan)' 2>&1 | FileCheck -allow-deprecated-dag-overlap -check-prefixes=CHECK,ORIGINS %s --implicit-check-not="call void @__msan_warning"
; RUN: opt < %s -passes='module(msan-module),function(msan)' -msan-check-access-address=0 -msan-track-origins=1 -S | FileCheck -allow-deprecated-dag-overlap -check-prefixes=CHECK,ORIGINS %s --implicit-check-not="call void @__msan_warning"
; RUN: opt < %s -passes='module(msan-module),function(msan)' -msan-instrumentation-with-call-threshold=0 -msan-track-origins=1 -S | FileCheck -allow-deprecated-dag-overlap -check-prefixes=CHECK-CALLS %s --implicit-check-not="call void @__msan_warning"
; RUN: opt < %s -msan-check-access-address=0 -S -passes='module(msan)' 2>&1 | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=CHECK,NOORIGINS --implicit-check-not="call void @__msan_warning"
; RUN: opt < %s --passes='module(msan)' -msan-check-access-address=0 -S | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=CHECK,NOORIGINS --implicit-check-not="call void @__msan_warning"
; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=1 -S -passes='module(msan)' 2>&1 | FileCheck -allow-deprecated-dag-overlap -check-prefixes=CHECK,ORIGINS %s --implicit-check-not="call void @__msan_warning"
; RUN: opt < %s -passes='module(msan)' -msan-check-access-address=0 -msan-track-origins=1 -S | FileCheck -allow-deprecated-dag-overlap -check-prefixes=CHECK,ORIGINS %s --implicit-check-not="call void @__msan_warning"
; RUN: opt < %s -passes='module(msan)' -msan-instrumentation-with-call-threshold=0 -msan-track-origins=1 -S | FileCheck -allow-deprecated-dag-overlap -check-prefixes=CHECK-CALLS %s --implicit-check-not="call void @__msan_warning"

target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -passes='module(msan-module),function(msan)' -msan-instrumentation-with-call-threshold=0 -msan-track-origins=1 -S | FileCheck %s
; RUN: opt < %s -passes='module(msan)' -msan-instrumentation-with-call-threshold=0 -msan-track-origins=1 -S | FileCheck %s

target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/Instrumentation/MemorySanitizer/msan_eager.ll
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=1 -msan-eager-checks -S -passes='module(msan-module),function(msan)' 2>&1 | \
; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=1 -msan-eager-checks -S -passes='module(msan)' 2>&1 | \
; RUN: FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK %s
; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=1 -S -passes='msan<eager-checks>' 2>&1 | \
; RUN: FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK %s
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
; Make sure MSan handles llvm.launder.invariant.group correctly.

; RUN: opt < %s -passes='function(msan),default<O1>' -msan-kernel=1 -S | FileCheck -check-prefixes=CHECK %s
; RUN: opt < %s -passes='function(msan),default<O1>' -S | FileCheck -check-prefixes=CHECK %s
; RUN: opt < %s -passes='module(msan),default<O1>' -msan-kernel=1 -S | FileCheck -check-prefixes=CHECK %s
; RUN: opt < %s -passes='module(msan),default<O1>' -S | FileCheck -check-prefixes=CHECK %s

target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
; Make sure MSan handles llvm.launder.invariant.group correctly.

; RUN: opt < %s -passes='function(msan),default<O1>' -msan-kernel=1 -S | FileCheck -check-prefixes=CHECK %s
; RUN: opt < %s -passes='function(msan),default<O1>' -S | FileCheck -check-prefixes=CHECK %s
; RUN: opt < %s -passes='module(msan),default<O1>' -msan-kernel=1 -S | FileCheck -check-prefixes=CHECK %s
; RUN: opt < %s -passes='module(msan),default<O1>' -S | FileCheck -check-prefixes=CHECK %s

target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/Instrumentation/MemorySanitizer/reduce.ll
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=1 -S -passes='module(msan-module),function(msan)' 2>&1 | \
; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=1 -S -passes='module(msan)' 2>&1 | \
; RUN: FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK %s

target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/Other/new-pm-print-pipeline.ll
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@
; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='function(early-cse<>,early-cse<memssa>)' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-12
; CHECK-12: function(early-cse<>,early-cse<memssa>)

; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='msan-module,function(msan,msan<>,msan<recover;kernel;eager-checks;track-origins=5>)' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-13
; CHECK-13: msan-module,function(msan<track-origins=0>,msan<track-origins=0>,msan<recover;kernel;eager-checks;track-origins=5>)
; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='msan,module(msan,msan<>,msan<recover;kernel;eager-checks;track-origins=5>)' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-13
; CHECK-13: msan<track-origins=0>,msan<track-origins=0>,msan<track-origins=0>,msan<recover;kernel;eager-checks;track-origins=5>

; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='module(hwasan<>,hwasan<kernel;recover>)' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-14
; CHECK-14: hwasan<>,hwasan<kernel;recover>
Expand Down

0 comments on commit e7bac3b

Please sign in to comment.