forked from OSchip/llvm-project
[NewPM] Make some sanitizer passes parameterized in the PassRegistry
Refactored implementation of AddressSanitizerPass and HWAddressSanitizerPass to use pass options similar to passes like MemorySanitizerPass. This makes sure that there is a single mapping from class name to pass name (needed by D108298), and options like -debug-only and -print-after makes a bit more sense when (despite that it is the unparameterized pass name that should be used in those options). A result of the above is that some pass names are removed in favor of the parameterized versions: - "khwasan" is now "hwasan<kernel;recover>" - "kasan" is now "asan<kernel>" - "kmsan" is now "msan<kernel>" Differential Revision: https://reviews.llvm.org/D105007
This commit is contained in:
parent
23b16d2453
commit
36d5138619
|
@ -1161,7 +1161,7 @@ static void addSanitizers(const Triple &TargetTriple,
|
|||
CompileKernel, Recover, ModuleUseAfterScope, UseOdrIndicator,
|
||||
DestructorKind));
|
||||
MPM.addPass(createModuleToFunctionPassAdaptor(AddressSanitizerPass(
|
||||
CompileKernel, Recover, UseAfterScope, UseAfterReturn)));
|
||||
{CompileKernel, Recover, UseAfterScope, UseAfterReturn})));
|
||||
}
|
||||
};
|
||||
ASanPass(SanitizerKind::Address, false);
|
||||
|
@ -1171,8 +1171,8 @@ static void addSanitizers(const Triple &TargetTriple,
|
|||
if (LangOpts.Sanitize.has(Mask)) {
|
||||
bool Recover = CodeGenOpts.SanitizeRecover.has(Mask);
|
||||
MPM.addPass(HWAddressSanitizerPass(
|
||||
CompileKernel, Recover,
|
||||
/*DisableOptimization=*/CodeGenOpts.OptimizationLevel == 0));
|
||||
{CompileKernel, Recover,
|
||||
/*DisableOptimization=*/CodeGenOpts.OptimizationLevel == 0}));
|
||||
}
|
||||
};
|
||||
HWASanPass(SanitizerKind::HWAddress, false);
|
||||
|
|
|
@ -89,6 +89,20 @@ private:
|
|||
static AnalysisKey Key;
|
||||
};
|
||||
|
||||
struct AddressSanitizerOptions {
|
||||
AddressSanitizerOptions()
|
||||
: AddressSanitizerOptions(false, false, false,
|
||||
AsanDetectStackUseAfterReturnMode::Runtime){};
|
||||
AddressSanitizerOptions(bool CompileKernel, bool Recover, bool UseAfterScope,
|
||||
AsanDetectStackUseAfterReturnMode UseAfterReturn)
|
||||
: CompileKernel(CompileKernel), Recover(Recover),
|
||||
UseAfterScope(UseAfterScope), UseAfterReturn(UseAfterReturn){};
|
||||
bool CompileKernel;
|
||||
bool Recover;
|
||||
bool UseAfterScope;
|
||||
AsanDetectStackUseAfterReturnMode UseAfterReturn;
|
||||
};
|
||||
|
||||
/// Public interface to the address sanitizer pass for instrumenting code to
|
||||
/// check for various memory errors at runtime.
|
||||
///
|
||||
|
@ -98,19 +112,13 @@ private:
|
|||
/// surrounding requested memory to be checked for invalid accesses.
|
||||
class AddressSanitizerPass : public PassInfoMixin<AddressSanitizerPass> {
|
||||
public:
|
||||
explicit AddressSanitizerPass(
|
||||
bool CompileKernel = false, bool Recover = false,
|
||||
bool UseAfterScope = false,
|
||||
AsanDetectStackUseAfterReturnMode UseAfterReturn =
|
||||
AsanDetectStackUseAfterReturnMode::Runtime);
|
||||
explicit AddressSanitizerPass(AddressSanitizerOptions Options)
|
||||
: Options(Options){};
|
||||
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
|
||||
static bool isRequired() { return true; }
|
||||
|
||||
private:
|
||||
bool CompileKernel;
|
||||
bool Recover;
|
||||
bool UseAfterScope;
|
||||
AsanDetectStackUseAfterReturnMode UseAfterReturn;
|
||||
AddressSanitizerOptions Options;
|
||||
};
|
||||
|
||||
/// Public interface to the address sanitizer module pass for instrumenting code
|
||||
|
|
|
@ -18,21 +18,30 @@
|
|||
|
||||
namespace llvm {
|
||||
|
||||
struct HWAddressSanitizerOptions {
|
||||
HWAddressSanitizerOptions()
|
||||
: HWAddressSanitizerOptions(false, false, false){};
|
||||
HWAddressSanitizerOptions(bool CompileKernel, bool Recover,
|
||||
bool DisableOptimization)
|
||||
: CompileKernel(CompileKernel), Recover(Recover),
|
||||
DisableOptimization(DisableOptimization){};
|
||||
bool CompileKernel;
|
||||
bool Recover;
|
||||
bool DisableOptimization;
|
||||
};
|
||||
|
||||
/// 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,
|
||||
bool DisableOptimization = false);
|
||||
explicit HWAddressSanitizerPass(HWAddressSanitizerOptions Options)
|
||||
: Options(Options){};
|
||||
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
|
||||
static bool isRequired() { return true; }
|
||||
|
||||
private:
|
||||
bool CompileKernel;
|
||||
bool Recover;
|
||||
bool DisableOptimization;
|
||||
HWAddressSanitizerOptions Options;
|
||||
};
|
||||
|
||||
FunctionPass *
|
||||
|
|
|
@ -453,6 +453,8 @@ PassBuilder::PassBuilder(TargetMachine *TM, PipelineTuningOptions PTO,
|
|||
if (PIC && shouldPopulateClassToPassNames()) {
|
||||
#define MODULE_PASS(NAME, CREATE_PASS) \
|
||||
PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);
|
||||
#define MODULE_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
|
||||
PIC->addClassToPassName(CLASS, NAME);
|
||||
#define MODULE_ANALYSIS(NAME, CREATE_PASS) \
|
||||
PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);
|
||||
#define FUNCTION_PASS(NAME, CREATE_PASS) \
|
||||
|
@ -2137,6 +2139,44 @@ Expected<LoopUnrollOptions> parseLoopUnrollOptions(StringRef Params) {
|
|||
return UnrollOpts;
|
||||
}
|
||||
|
||||
Expected<AddressSanitizerOptions> parseASanPassOptions(StringRef Params) {
|
||||
AddressSanitizerOptions Result;
|
||||
while (!Params.empty()) {
|
||||
StringRef ParamName;
|
||||
std::tie(ParamName, Params) = Params.split(';');
|
||||
|
||||
if (ParamName == "kernel") {
|
||||
Result.CompileKernel = true;
|
||||
} else {
|
||||
return make_error<StringError>(
|
||||
formatv("invalid AddressSanitizer pass parameter '{0}' ", ParamName)
|
||||
.str(),
|
||||
inconvertibleErrorCode());
|
||||
}
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
Expected<HWAddressSanitizerOptions> parseHWASanPassOptions(StringRef Params) {
|
||||
HWAddressSanitizerOptions Result;
|
||||
while (!Params.empty()) {
|
||||
StringRef ParamName;
|
||||
std::tie(ParamName, Params) = Params.split(';');
|
||||
|
||||
if (ParamName == "recover") {
|
||||
Result.Recover = true;
|
||||
} else if (ParamName == "kernel") {
|
||||
Result.CompileKernel = true;
|
||||
} else {
|
||||
return make_error<StringError>(
|
||||
formatv("invalid HWAddressSanitizer pass parameter '{0}' ", ParamName)
|
||||
.str(),
|
||||
inconvertibleErrorCode());
|
||||
}
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
Expected<MemorySanitizerOptions> parseMSanPassOptions(StringRef Params) {
|
||||
MemorySanitizerOptions Result;
|
||||
while (!Params.empty()) {
|
||||
|
@ -2356,6 +2396,9 @@ static bool isModulePassName(StringRef Name, CallbacksT &Callbacks) {
|
|||
#define MODULE_PASS(NAME, CREATE_PASS) \
|
||||
if (Name == NAME) \
|
||||
return true;
|
||||
#define MODULE_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
|
||||
if (checkParametrizedPassName(Name, NAME)) \
|
||||
return true;
|
||||
#define MODULE_ANALYSIS(NAME, CREATE_PASS) \
|
||||
if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \
|
||||
return true;
|
||||
|
@ -2600,6 +2643,14 @@ Error PassBuilder::parseModulePass(ModulePassManager &MPM,
|
|||
MPM.addPass(CREATE_PASS); \
|
||||
return Error::success(); \
|
||||
}
|
||||
#define MODULE_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
|
||||
if (checkParametrizedPassName(Name, NAME)) { \
|
||||
auto Params = parsePassParameters(PARSER, Name, NAME); \
|
||||
if (!Params) \
|
||||
return Params.takeError(); \
|
||||
MPM.addPass(CREATE_PASS(Params.get())); \
|
||||
return Error::success(); \
|
||||
}
|
||||
#define MODULE_ANALYSIS(NAME, CREATE_PASS) \
|
||||
if (Name == "require<" NAME ">") { \
|
||||
MPM.addPass( \
|
||||
|
@ -3176,6 +3227,11 @@ void PassBuilder::printPassNames(raw_ostream &OS) {
|
|||
#define MODULE_PASS(NAME, CREATE_PASS) printPassName(NAME, OS);
|
||||
#include "PassRegistry.def"
|
||||
|
||||
OS << "Module passes with params:\n";
|
||||
#define MODULE_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
|
||||
printPassName(NAME, PARAMS, OS);
|
||||
#include "PassRegistry.def"
|
||||
|
||||
OS << "Module analyses:\n";
|
||||
#define MODULE_ANALYSIS(NAME, CREATE_PASS) printPassName(NAME, OS);
|
||||
#include "PassRegistry.def"
|
||||
|
|
|
@ -60,8 +60,6 @@ MODULE_PASS("globaldce", GlobalDCEPass())
|
|||
MODULE_PASS("globalopt", GlobalOptPass())
|
||||
MODULE_PASS("globalsplit", GlobalSplitPass())
|
||||
MODULE_PASS("hotcoldsplit", HotColdSplittingPass())
|
||||
MODULE_PASS("hwasan", HWAddressSanitizerPass(false, false))
|
||||
MODULE_PASS("khwasan", HWAddressSanitizerPass(true, true))
|
||||
MODULE_PASS("inferattrs", InferFunctionAttrsPass())
|
||||
MODULE_PASS("inliner-wrapper", ModuleInlinerWrapperPass())
|
||||
MODULE_PASS("inliner-wrapper-no-mandatory-first", ModuleInlinerWrapperPass(
|
||||
|
@ -123,6 +121,18 @@ MODULE_PASS("poison-checking", PoisonCheckingPass())
|
|||
MODULE_PASS("pseudo-probe-update", PseudoProbeUpdatePass())
|
||||
#undef MODULE_PASS
|
||||
|
||||
#ifndef MODULE_PASS_WITH_PARAMS
|
||||
#define MODULE_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS)
|
||||
#endif
|
||||
MODULE_PASS_WITH_PARAMS("hwasan",
|
||||
"HWAddressSanitizerPass",
|
||||
[](HWAddressSanitizerOptions Opts) {
|
||||
return HWAddressSanitizerPass(Opts);
|
||||
},
|
||||
parseHWASanPassOptions,
|
||||
"kernel;recover")
|
||||
#undef MODULE_PASS_WITH_PARAMS
|
||||
|
||||
#ifndef CGSCC_ANALYSIS
|
||||
#define CGSCC_ANALYSIS(NAME, CREATE_PASS)
|
||||
#endif
|
||||
|
@ -322,10 +332,7 @@ FUNCTION_PASS("verify<scalar-evolution>", ScalarEvolutionVerifierPass())
|
|||
FUNCTION_PASS("view-cfg", CFGViewerPass())
|
||||
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("msan", MemorySanitizerPass({}))
|
||||
FUNCTION_PASS("kmsan", MemorySanitizerPass({0, false, /*Kernel=*/true}))
|
||||
FUNCTION_PASS("tsan", ThreadSanitizerPass())
|
||||
FUNCTION_PASS("memprof", MemProfilerPass())
|
||||
#undef FUNCTION_PASS
|
||||
|
@ -345,6 +352,13 @@ FUNCTION_PASS_WITH_PARAMS("loop-unroll",
|
|||
"no-profile-peeling;profile-peeling;"
|
||||
"no-runtime;runtime;"
|
||||
"no-upperbound;upperbound")
|
||||
FUNCTION_PASS_WITH_PARAMS("asan",
|
||||
"AddressSanitizerPass",
|
||||
[](AddressSanitizerOptions Opts) {
|
||||
return AddressSanitizerPass(Opts);
|
||||
},
|
||||
parseASanPassOptions,
|
||||
"kernel")
|
||||
FUNCTION_PASS_WITH_PARAMS("msan",
|
||||
"MemorySanitizerPass",
|
||||
[](MemorySanitizerOptions Opts) {
|
||||
|
|
|
@ -1212,20 +1212,14 @@ GlobalsMetadata ASanGlobalsMetadataAnalysis::run(Module &M,
|
|||
return GlobalsMetadata(M);
|
||||
}
|
||||
|
||||
AddressSanitizerPass::AddressSanitizerPass(
|
||||
bool CompileKernel, bool Recover, bool UseAfterScope,
|
||||
AsanDetectStackUseAfterReturnMode UseAfterReturn)
|
||||
: CompileKernel(CompileKernel), Recover(Recover),
|
||||
UseAfterScope(UseAfterScope), UseAfterReturn(UseAfterReturn) {}
|
||||
|
||||
PreservedAnalyses AddressSanitizerPass::run(Function &F,
|
||||
AnalysisManager<Function> &AM) {
|
||||
auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
|
||||
Module &M = *F.getParent();
|
||||
if (auto *R = MAMProxy.getCachedResult<ASanGlobalsMetadataAnalysis>(M)) {
|
||||
const TargetLibraryInfo *TLI = &AM.getResult<TargetLibraryAnalysis>(F);
|
||||
AddressSanitizer Sanitizer(M, R, CompileKernel, Recover, UseAfterScope,
|
||||
UseAfterReturn);
|
||||
AddressSanitizer Sanitizer(M, R, Options.CompileKernel, Options.Recover,
|
||||
Options.UseAfterScope, Options.UseAfterReturn);
|
||||
if (Sanitizer.instrumentFunction(F, TLI))
|
||||
return PreservedAnalyses::none();
|
||||
return PreservedAnalyses::all();
|
||||
|
|
|
@ -471,19 +471,14 @@ llvm::createHWAddressSanitizerLegacyPassPass(bool CompileKernel, bool Recover,
|
|||
DisableOptimization);
|
||||
}
|
||||
|
||||
HWAddressSanitizerPass::HWAddressSanitizerPass(bool CompileKernel, bool Recover,
|
||||
bool DisableOptimization)
|
||||
: CompileKernel(CompileKernel), Recover(Recover),
|
||||
DisableOptimization(DisableOptimization) {}
|
||||
|
||||
PreservedAnalyses HWAddressSanitizerPass::run(Module &M,
|
||||
ModuleAnalysisManager &MAM) {
|
||||
const StackSafetyGlobalInfo *SSI = nullptr;
|
||||
auto TargetTriple = llvm::Triple(M.getTargetTriple());
|
||||
if (shouldUseStackSafetyAnalysis(TargetTriple, DisableOptimization))
|
||||
if (shouldUseStackSafetyAnalysis(TargetTriple, Options.DisableOptimization))
|
||||
SSI = &MAM.getResult<StackSafetyGlobalAnalysis>(M);
|
||||
|
||||
HWAddressSanitizer HWASan(M, CompileKernel, Recover, SSI);
|
||||
HWAddressSanitizer HWASan(M, Options.CompileKernel, Options.Recover, SSI);
|
||||
bool Modified = false;
|
||||
auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
|
||||
for (Function &F : M) {
|
||||
|
|
|
@ -339,18 +339,19 @@ bool llvm::runPassPipeline(StringRef Arg0, Module &M, TargetMachine *TM,
|
|||
PB.registerPipelineParsingCallback(
|
||||
[](StringRef Name, ModulePassManager &MPM,
|
||||
ArrayRef<PassBuilder::PipelineElement>) {
|
||||
AddressSanitizerOptions Opts;
|
||||
if (Name == "asan-pipeline") {
|
||||
MPM.addPass(
|
||||
RequireAnalysisPass<ASanGlobalsMetadataAnalysis, Module>());
|
||||
MPM.addPass(
|
||||
createModuleToFunctionPassAdaptor(AddressSanitizerPass()));
|
||||
createModuleToFunctionPassAdaptor(AddressSanitizerPass(Opts)));
|
||||
MPM.addPass(ModuleAddressSanitizerPass());
|
||||
return true;
|
||||
} else if (Name == "asan-function-pipeline") {
|
||||
MPM.addPass(
|
||||
RequireAnalysisPass<ASanGlobalsMetadataAnalysis, Module>());
|
||||
MPM.addPass(
|
||||
createModuleToFunctionPassAdaptor(AddressSanitizerPass()));
|
||||
createModuleToFunctionPassAdaptor(AddressSanitizerPass(Opts)));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
Loading…
Reference in New Issue