Revert 374481 "[tsan,msan] Insert module constructors in a module pass"

CodeGen/sanitizer-module-constructor.c fails on mac and windows, see e.g.
http://lab.llvm.org:8011/builders/clang-x64-windows-msvc/builds/11424

llvm-svn: 374503
This commit is contained in:
Nico Weber 2019-10-11 02:44:20 +00:00
parent c1f8e04eee
commit d38332981f
9 changed files with 55 additions and 102 deletions

View File

@ -974,7 +974,6 @@ static void addSanitizersAtO0(ModulePassManager &MPM,
}
if (LangOpts.Sanitize.has(SanitizerKind::Memory)) {
MPM.addPass(MemorySanitizerPass({}));
MPM.addPass(createModuleToFunctionPassAdaptor(MemorySanitizerPass({})));
}
@ -984,7 +983,6 @@ static void addSanitizersAtO0(ModulePassManager &MPM,
}
if (LangOpts.Sanitize.has(SanitizerKind::Thread)) {
MPM.addPass(ThreadSanitizerPass());
MPM.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass()));
}
}
@ -1164,23 +1162,16 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
[](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) {
FPM.addPass(BoundsCheckingPass());
});
if (LangOpts.Sanitize.has(SanitizerKind::Memory)) {
PB.registerPipelineStartEPCallback([](ModulePassManager &MPM) {
MPM.addPass(MemorySanitizerPass({}));
});
if (LangOpts.Sanitize.has(SanitizerKind::Memory))
PB.registerOptimizerLastEPCallback(
[](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) {
FPM.addPass(MemorySanitizerPass({}));
});
}
if (LangOpts.Sanitize.has(SanitizerKind::Thread)) {
PB.registerPipelineStartEPCallback(
[](ModulePassManager &MPM) { MPM.addPass(ThreadSanitizerPass()); });
if (LangOpts.Sanitize.has(SanitizerKind::Thread))
PB.registerOptimizerLastEPCallback(
[](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) {
FPM.addPass(ThreadSanitizerPass());
});
}
if (LangOpts.Sanitize.has(SanitizerKind::Address)) {
PB.registerPipelineStartEPCallback([&](ModulePassManager &MPM) {
MPM.addPass(

View File

@ -1,22 +0,0 @@
// RUN: %clang_cc1 -fsanitize=address -emit-llvm -O3 -fdebug-pass-manager -fexperimental-new-pass-manager -o - %s 2>&1 | FileCheck %s
// RUN: %clang_cc1 -fsanitize=thread -emit-llvm -O3 -fdebug-pass-manager -fexperimental-new-pass-manager -o - %s 2>&1 | FileCheck %s
// RUN: %clang_cc1 -fsanitize=memory -emit-llvm -O3 -fdebug-pass-manager -fexperimental-new-pass-manager -o - %s 2>&1 | FileCheck %s
// This is regression test for PR42877
typedef struct a *b;
struct a {
int c;
};
int d;
b e;
static void f(b g) {
for (d = g->c;;)
;
}
void h() { f(e); }
// CHECK: Running pass: {{.*}}SanitizerPass on {{.*}}sanitizer-module-constructor.c
// CHECK-NOT: Running pass: LoopSimplifyPass on {{.*}}san.module_ctor
// CHECK: Running analysis: DominatorTreeAnalysis on {{.*}}san.module_ctor
// CHECK: Running pass: LoopSimplifyPass on {{.*}}san.module_ctor

View File

@ -40,7 +40,6 @@ struct MemorySanitizerPass : public PassInfoMixin<MemorySanitizerPass> {
MemorySanitizerPass(MemorySanitizerOptions Options) : Options(Options) {}
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM);
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
private:
MemorySanitizerOptions Options;

View File

@ -27,8 +27,6 @@ FunctionPass *createThreadSanitizerLegacyPassPass();
/// yet, the pass inserts the declarations. Otherwise the existing globals are
struct ThreadSanitizerPass : public PassInfoMixin<ThreadSanitizerPass> {
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM);
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
};
} // namespace llvm
#endif /* LLVM_TRANSFORMS_INSTRUMENTATION_THREADSANITIZER_H */

View File

@ -86,8 +86,6 @@ MODULE_PASS("synthetic-counts-propagation", SyntheticCountsPropagation())
MODULE_PASS("wholeprogramdevirt", WholeProgramDevirtPass(nullptr, nullptr))
MODULE_PASS("verify", VerifierPass())
MODULE_PASS("asan-module", ModuleAddressSanitizerPass(/*CompileKernel=*/false, false, true, false))
MODULE_PASS("msan-module", MemorySanitizerPass({}))
MODULE_PASS("tsan-module", ThreadSanitizerPass())
MODULE_PASS("kasan-module", ModuleAddressSanitizerPass(/*CompileKernel=*/true, false, true, false))
MODULE_PASS("sancov-module", ModuleSanitizerCoveragePass())
MODULE_PASS("poison-checking", PoisonCheckingPass())

View File

@ -587,25 +587,9 @@ private:
/// An empty volatile inline asm that prevents callback merge.
InlineAsm *EmptyAsm;
};
void insertModuleCtor(Module &M) {
getOrCreateSanitizerCtorAndInitFunctions(
M, kMsanModuleCtorName, kMsanInitName,
/*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) {
if (!ClWithComdat) {
appendToGlobalCtors(M, Ctor, 0);
return;
}
Comdat *MsanCtorComdat = M.getOrInsertComdat(kMsanModuleCtorName);
Ctor->setComdat(MsanCtorComdat);
appendToGlobalCtors(M, Ctor, 0, Ctor);
});
}
Function *MsanCtorFunction;
};
/// A legacy function pass for msan instrumentation.
///
@ -651,14 +635,6 @@ PreservedAnalyses MemorySanitizerPass::run(Function &F,
return PreservedAnalyses::all();
}
PreservedAnalyses MemorySanitizerPass::run(Module &M,
ModuleAnalysisManager &AM) {
if (Options.Kernel)
return PreservedAnalyses::all();
insertModuleCtor(M);
return PreservedAnalyses::none();
}
char MemorySanitizerLegacyPass::ID = 0;
INITIALIZE_PASS_BEGIN(MemorySanitizerLegacyPass, "msan",
@ -944,6 +920,23 @@ void MemorySanitizer::initializeModule(Module &M) {
OriginStoreWeights = MDBuilder(*C).createBranchWeights(1, 1000);
if (!CompileKernel) {
std::tie(MsanCtorFunction, std::ignore) =
getOrCreateSanitizerCtorAndInitFunctions(
M, kMsanModuleCtorName, kMsanInitName,
/*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) {
if (!ClWithComdat) {
appendToGlobalCtors(M, Ctor, 0);
return;
}
Comdat *MsanCtorComdat = M.getOrInsertComdat(kMsanModuleCtorName);
Ctor->setComdat(MsanCtorComdat);
appendToGlobalCtors(M, Ctor, 0, Ctor);
});
if (TrackOrigins)
M.getOrInsertGlobal("__msan_track_origins", IRB.getInt32Ty(), [&] {
return new GlobalVariable(
@ -961,8 +954,6 @@ void MemorySanitizer::initializeModule(Module &M) {
}
bool MemorySanitizerLegacyPass::doInitialization(Module &M) {
if (!Options.Kernel)
insertModuleCtor(M);
MSan.emplace(M, Options);
return true;
}
@ -4587,9 +4578,8 @@ static VarArgHelper *CreateVarArgHelper(Function &Func, MemorySanitizer &Msan,
}
bool MemorySanitizer::sanitizeFunction(Function &F, TargetLibraryInfo &TLI) {
if (!CompileKernel && F.getName() == kMsanModuleCtorName)
if (!CompileKernel && (&F == MsanCtorFunction))
return false;
MemorySanitizerVisitor Visitor(F, *this, TLI);
// Clear out readonly/readnone attributes.

View File

@ -92,10 +92,11 @@ namespace {
/// ensures the __tsan_init function is in the list of global constructors for
/// the module.
struct ThreadSanitizer {
ThreadSanitizer(Module &M);
bool sanitizeFunction(Function &F, const TargetLibraryInfo &TLI);
private:
void initialize(Module &M);
void initializeCallbacks(Module &M);
bool instrumentLoadOrStore(Instruction *I, const DataLayout &DL);
bool instrumentAtomic(Instruction *I, const DataLayout &DL);
bool instrumentMemIntrinsic(Instruction *I);
@ -107,6 +108,8 @@ private:
void InsertRuntimeIgnores(Function &F);
Type *IntptrTy;
IntegerType *OrdTy;
// Callbacks to run-time library are computed in doInitialization.
FunctionCallee TsanFuncEntry;
FunctionCallee TsanFuncExit;
FunctionCallee TsanIgnoreBegin;
@ -127,6 +130,7 @@ private:
FunctionCallee TsanVptrUpdate;
FunctionCallee TsanVptrLoad;
FunctionCallee MemmoveFn, MemcpyFn, MemsetFn;
Function *TsanCtorFunction;
};
struct ThreadSanitizerLegacyPass : FunctionPass {
@ -139,32 +143,16 @@ struct ThreadSanitizerLegacyPass : FunctionPass {
private:
Optional<ThreadSanitizer> TSan;
};
void insertModuleCtor(Module &M) {
getOrCreateSanitizerCtorAndInitFunctions(
M, kTsanModuleCtorName, kTsanInitName, /*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) { appendToGlobalCtors(M, Ctor, 0); });
}
} // namespace
PreservedAnalyses ThreadSanitizerPass::run(Function &F,
FunctionAnalysisManager &FAM) {
ThreadSanitizer TSan;
ThreadSanitizer TSan(*F.getParent());
if (TSan.sanitizeFunction(F, FAM.getResult<TargetLibraryAnalysis>(F)))
return PreservedAnalyses::none();
return PreservedAnalyses::all();
}
PreservedAnalyses ThreadSanitizerPass::run(Module &M,
ModuleAnalysisManager &MAM) {
insertModuleCtor(M);
return PreservedAnalyses::none();
}
char ThreadSanitizerLegacyPass::ID = 0;
INITIALIZE_PASS_BEGIN(ThreadSanitizerLegacyPass, "tsan",
"ThreadSanitizer: detects data races.", false, false)
@ -181,8 +169,7 @@ void ThreadSanitizerLegacyPass::getAnalysisUsage(AnalysisUsage &AU) const {
}
bool ThreadSanitizerLegacyPass::doInitialization(Module &M) {
insertModuleCtor(M);
TSan.emplace();
TSan.emplace(M);
return true;
}
@ -196,10 +183,7 @@ FunctionPass *llvm::createThreadSanitizerLegacyPassPass() {
return new ThreadSanitizerLegacyPass();
}
void ThreadSanitizer::initialize(Module &M) {
const DataLayout &DL = M.getDataLayout();
IntptrTy = DL.getIntPtrType(M.getContext());
void ThreadSanitizer::initializeCallbacks(Module &M) {
IRBuilder<> IRB(M.getContext());
AttributeList Attr;
Attr = Attr.addAttribute(M.getContext(), AttributeList::FunctionIndex,
@ -213,7 +197,7 @@ void ThreadSanitizer::initialize(Module &M) {
IRB.getVoidTy());
TsanIgnoreEnd =
M.getOrInsertFunction("__tsan_ignore_thread_end", Attr, IRB.getVoidTy());
IntegerType *OrdTy = IRB.getInt32Ty();
OrdTy = IRB.getInt32Ty();
for (size_t i = 0; i < kNumberOfAccessSizes; ++i) {
const unsigned ByteSize = 1U << i;
const unsigned BitSize = ByteSize * 8;
@ -296,6 +280,20 @@ void ThreadSanitizer::initialize(Module &M) {
IRB.getInt8PtrTy(), IRB.getInt32Ty(), IntptrTy);
}
ThreadSanitizer::ThreadSanitizer(Module &M) {
const DataLayout &DL = M.getDataLayout();
IntptrTy = DL.getIntPtrType(M.getContext());
std::tie(TsanCtorFunction, std::ignore) =
getOrCreateSanitizerCtorAndInitFunctions(
M, kTsanModuleCtorName, kTsanInitName, /*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) {
appendToGlobalCtors(M, Ctor, 0);
});
}
static bool isVtableAccess(Instruction *I) {
if (MDNode *Tag = I->getMetadata(LLVMContext::MD_tbaa))
return Tag->isTBAAVtableAccess();
@ -438,9 +436,9 @@ bool ThreadSanitizer::sanitizeFunction(Function &F,
const TargetLibraryInfo &TLI) {
// This is required to prevent instrumenting call to __tsan_init from within
// the module constructor.
if (F.getName() == kTsanModuleCtorName)
if (&F == TsanCtorFunction)
return false;
initialize(*F.getParent());
initializeCallbacks(*F.getParent());
SmallVector<Instruction*, 8> AllLoadsAndStores;
SmallVector<Instruction*, 8> LocalLoadsAndStores;
SmallVector<Instruction*, 8> AtomicAccesses;

View File

@ -1,9 +1,10 @@
; RUN: opt < %s -msan-check-access-address=0 -S -passes='module(msan-module),function(msan)' 2>&1 | FileCheck -allow-deprecated-dag-overlap %s
; RUN: opt < %s --passes='module(msan-module),function(msan)' -msan-check-access-address=0 -S | FileCheck -allow-deprecated-dag-overlap %s
; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=1 -S -passes='module(msan-module),function(msan)' 2>&1 | \
; RUN: FileCheck -allow-deprecated-dag-overlap -check-prefixes=CHECK,CHECK-ORIGINS %s
; RUN: opt < %s -passes='module(msan-module),function(msan)' -msan-check-access-address=0 -msan-track-origins=1 -S | \
; RUN: FileCheck -allow-deprecated-dag-overlap -check-prefixes=CHECK,CHECK-ORIGINS %s
; RUN: opt < %s -msan-check-access-address=0 -S -passes=msan 2>&1 | FileCheck \
; RUN: -allow-deprecated-dag-overlap %s
; RUN: opt < %s -msan -msan-check-access-address=0 -S | FileCheck -allow-deprecated-dag-overlap %s
; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=1 -S \
; RUN: -passes=msan 2>&1 | FileCheck -allow-deprecated-dag-overlap \
; RUN: -check-prefix=CHECK -check-prefix=CHECK-ORIGINS %s
; RUN: opt < %s -msan -msan-check-access-address=0 -msan-track-origins=1 -S | FileCheck -allow-deprecated-dag-overlap -check-prefix=CHECK -check-prefix=CHECK-ORIGINS %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"

View File

@ -1,5 +1,5 @@
; RUN: opt < %s -tsan -S | FileCheck %s
; RUN: opt < %s -passes='function(tsan),module(tsan-module)' -S | FileCheck %s
; RUN: opt < %s -passes=tsan -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"
target triple = "x86_64-unknown-linux-gnu"