llvm.org GIT mirror llvm / 2e8de39
Insert module constructors in a module pass Summary: If we insert them from function pass some analysis may be missing or invalid. Fixes PR42877. Reviewers: eugenis, leonardchan Reviewed By: leonardchan Subscribers: hiraditya, cfe-commits, llvm-commits Tags: #clang, #llvm Differential Revision: https://reviews.llvm.org/D68832 llvm-svn: 374481 Signed-off-by: Vitaly Buka <vitalybuka@google.com> git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@374527 91177308-0d34-0410-b5e6-96231b3b80d8 Vitaly Buka 1 year, 1 month ago
7 changed file(s) with 69 addition(s) and 53 deletion(s). Raw diff Collapse all Expand all
3939 MemorySanitizerPass(MemorySanitizerOptions Options) : Options(Options) {}
4040
4141 PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM);
42 PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
4243
4344 private:
4445 MemorySanitizerOptions Options;
2626 /// yet, the pass inserts the declarations. Otherwise the existing globals are
2727 struct ThreadSanitizerPass : public PassInfoMixin {
2828 PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM);
29 PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
2930 };
31
3032 } // namespace llvm
3133 #endif /* LLVM_TRANSFORMS_INSTRUMENTATION_THREADSANITIZER_H */
8585 MODULE_PASS("wholeprogramdevirt", WholeProgramDevirtPass(nullptr, nullptr))
8686 MODULE_PASS("verify", VerifierPass())
8787 MODULE_PASS("asan-module", ModuleAddressSanitizerPass(/*CompileKernel=*/false, false, true, false))
88 MODULE_PASS("msan-module", MemorySanitizerPass({}))
89 MODULE_PASS("tsan-module", ThreadSanitizerPass())
8890 MODULE_PASS("kasan-module", ModuleAddressSanitizerPass(/*CompileKernel=*/true, false, true, false))
8991 MODULE_PASS("sancov-module", ModuleSanitizerCoveragePass())
9092 MODULE_PASS("poison-checking", PoisonCheckingPass())
586586
587587 /// An empty volatile inline asm that prevents callback merge.
588588 InlineAsm *EmptyAsm;
589
590 Function *MsanCtorFunction;
591589 };
590
591 void insertModuleCtor(Module &M) {
592 getOrCreateSanitizerCtorAndInitFunctions(
593 M, kMsanModuleCtorName, kMsanInitName,
594 /*InitArgTypes=*/{},
595 /*InitArgs=*/{},
596 // This callback is invoked when the functions are created the first
597 // time. Hook them into the global ctors list in that case:
598 [&](Function *Ctor, FunctionCallee) {
599 if (!ClWithComdat) {
600 appendToGlobalCtors(M, Ctor, 0);
601 return;
602 }
603 Comdat *MsanCtorComdat = M.getOrInsertComdat(kMsanModuleCtorName);
604 Ctor->setComdat(MsanCtorComdat);
605 appendToGlobalCtors(M, Ctor, 0, Ctor);
606 });
607 }
592608
593609 /// A legacy function pass for msan instrumentation.
594610 ///
632648 if (Msan.sanitizeFunction(F, FAM.getResult(F)))
633649 return PreservedAnalyses::none();
634650 return PreservedAnalyses::all();
651 }
652
653 PreservedAnalyses MemorySanitizerPass::run(Module &M,
654 ModuleAnalysisManager &AM) {
655 if (Options.Kernel)
656 return PreservedAnalyses::all();
657 insertModuleCtor(M);
658 return PreservedAnalyses::none();
635659 }
636660
637661 char MemorySanitizerLegacyPass::ID = 0;
919943 OriginStoreWeights = MDBuilder(*C).createBranchWeights(1, 1000);
920944
921945 if (!CompileKernel) {
922 std::tie(MsanCtorFunction, std::ignore) =
923 getOrCreateSanitizerCtorAndInitFunctions(
924 M, kMsanModuleCtorName, kMsanInitName,
925 /*InitArgTypes=*/{},
926 /*InitArgs=*/{},
927 // This callback is invoked when the functions are created the first
928 // time. Hook them into the global ctors list in that case:
929 [&](Function *Ctor, FunctionCallee) {
930 if (!ClWithComdat) {
931 appendToGlobalCtors(M, Ctor, 0);
932 return;
933 }
934 Comdat *MsanCtorComdat = M.getOrInsertComdat(kMsanModuleCtorName);
935 Ctor->setComdat(MsanCtorComdat);
936 appendToGlobalCtors(M, Ctor, 0, Ctor);
937 });
938
939946 if (TrackOrigins)
940947 M.getOrInsertGlobal("__msan_track_origins", IRB.getInt32Ty(), [&] {
941948 return new GlobalVariable(
953960 }
954961
955962 bool MemorySanitizerLegacyPass::doInitialization(Module &M) {
963 if (!Options.Kernel)
964 insertModuleCtor(M);
956965 MSan.emplace(M, Options);
957966 return true;
958967 }
45774586 }
45784587
45794588 bool MemorySanitizer::sanitizeFunction(Function &F, TargetLibraryInfo &TLI) {
4580 if (!CompileKernel && (&F == MsanCtorFunction))
4589 if (!CompileKernel && F.getName() == kMsanModuleCtorName)
45814590 return false;
4591
45824592 MemorySanitizerVisitor Visitor(F, *this, TLI);
45834593
45844594 // Clear out readonly/readnone attributes.
9191 /// ensures the __tsan_init function is in the list of global constructors for
9292 /// the module.
9393 struct ThreadSanitizer {
94 ThreadSanitizer(Module &M);
9594 bool sanitizeFunction(Function &F, const TargetLibraryInfo &TLI);
9695
9796 private:
98 void initializeCallbacks(Module &M);
97 void initialize(Module &M);
9998 bool instrumentLoadOrStore(Instruction *I, const DataLayout &DL);
10099 bool instrumentAtomic(Instruction *I, const DataLayout &DL);
101100 bool instrumentMemIntrinsic(Instruction *I);
107106 void InsertRuntimeIgnores(Function &F);
108107
109108 Type *IntptrTy;
110 IntegerType *OrdTy;
111 // Callbacks to run-time library are computed in doInitialization.
112109 FunctionCallee TsanFuncEntry;
113110 FunctionCallee TsanFuncExit;
114111 FunctionCallee TsanIgnoreBegin;
129126 FunctionCallee TsanVptrUpdate;
130127 FunctionCallee TsanVptrLoad;
131128 FunctionCallee MemmoveFn, MemcpyFn, MemsetFn;
132 Function *TsanCtorFunction;
133129 };
134130
135131 struct ThreadSanitizerLegacyPass : FunctionPass {
142138 private:
143139 Optional TSan;
144140 };
141
142 void insertModuleCtor(Module &M) {
143 getOrCreateSanitizerCtorAndInitFunctions(
144 M, kTsanModuleCtorName, kTsanInitName, /*InitArgTypes=*/{},
145 /*InitArgs=*/{},
146 // This callback is invoked when the functions are created the first
147 // time. Hook them into the global ctors list in that case:
148 [&](Function *Ctor, FunctionCallee) { appendToGlobalCtors(M, Ctor, 0); });
149 }
150
145151 } // namespace
146152
147153 PreservedAnalyses ThreadSanitizerPass::run(Function &F,
148154 FunctionAnalysisManager &FAM) {
149 ThreadSanitizer TSan(*F.getParent());
155 ThreadSanitizer TSan;
150156 if (TSan.sanitizeFunction(F, FAM.getResult(F)))
151157 return PreservedAnalyses::none();
152158 return PreservedAnalyses::all();
159 }
160
161 PreservedAnalyses ThreadSanitizerPass::run(Module &M,
162 ModuleAnalysisManager &MAM) {
163 insertModuleCtor(M);
164 return PreservedAnalyses::none();
153165 }
154166
155167 char ThreadSanitizerLegacyPass::ID = 0;
168180 }
169181
170182 bool ThreadSanitizerLegacyPass::doInitialization(Module &M) {
171 TSan.emplace(M);
183 insertModuleCtor(M);
184 TSan.emplace();
172185 return true;
173186 }
174187
182195 return new ThreadSanitizerLegacyPass();
183196 }
184197
185 void ThreadSanitizer::initializeCallbacks(Module &M) {
198 void ThreadSanitizer::initialize(Module &M) {
199 const DataLayout &DL = M.getDataLayout();
200 IntptrTy = DL.getIntPtrType(M.getContext());
201
186202 IRBuilder<> IRB(M.getContext());
187203 AttributeList Attr;
188204 Attr = Attr.addAttribute(M.getContext(), AttributeList::FunctionIndex,
196212 IRB.getVoidTy());
197213 TsanIgnoreEnd =
198214 M.getOrInsertFunction("__tsan_ignore_thread_end", Attr, IRB.getVoidTy());
199 OrdTy = IRB.getInt32Ty();
215 IntegerType *OrdTy = IRB.getInt32Ty();
200216 for (size_t i = 0; i < kNumberOfAccessSizes; ++i) {
201217 const unsigned ByteSize = 1U << i;
202218 const unsigned BitSize = ByteSize * 8;
277293 MemsetFn =
278294 M.getOrInsertFunction("memset", Attr, IRB.getInt8PtrTy(),
279295 IRB.getInt8PtrTy(), IRB.getInt32Ty(), IntptrTy);
280 }
281
282 ThreadSanitizer::ThreadSanitizer(Module &M) {
283 const DataLayout &DL = M.getDataLayout();
284 IntptrTy = DL.getIntPtrType(M.getContext());
285 std::tie(TsanCtorFunction, std::ignore) =
286 getOrCreateSanitizerCtorAndInitFunctions(
287 M, kTsanModuleCtorName, kTsanInitName, /*InitArgTypes=*/{},
288 /*InitArgs=*/{},
289 // This callback is invoked when the functions are created the first
290 // time. Hook them into the global ctors list in that case:
291 [&](Function *Ctor, FunctionCallee) {
292 appendToGlobalCtors(M, Ctor, 0);
293 });
294296 }
295297
296298 static bool isVtableAccess(Instruction *I) {
435437 const TargetLibraryInfo &TLI) {
436438 // This is required to prevent instrumenting call to __tsan_init from within
437439 // the module constructor.
438 if (&F == TsanCtorFunction)
440 if (F.getName() == kTsanModuleCtorName)
439441 return false;
440 initializeCallbacks(*F.getParent());
442 initialize(*F.getParent());
441443 SmallVector AllLoadsAndStores;
442444 SmallVector LocalLoadsAndStores;
443445 SmallVector AtomicAccesses;
None ; RUN: opt < %s -msan-check-access-address=0 -S -passes=msan 2>&1 | FileCheck \
1 ; RUN: -allow-deprecated-dag-overlap %s
2 ; RUN: opt < %s -msan -msan-check-access-address=0 -S | FileCheck -allow-deprecated-dag-overlap %s
3 ; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=1 -S \
4 ; RUN: -passes=msan 2>&1 | FileCheck -allow-deprecated-dag-overlap \
5 ; RUN: -check-prefix=CHECK -check-prefix=CHECK-ORIGINS %s
6 ; 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
0 ; RUN: opt < %s -msan-check-access-address=0 -S -passes='module(msan-module),function(msan)' 2>&1 | FileCheck -allow-deprecated-dag-overlap %s
1 ; RUN: opt < %s --passes='module(msan-module),function(msan)' -msan-check-access-address=0 -S | FileCheck -allow-deprecated-dag-overlap %s
2 ; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=1 -S -passes='module(msan-module),function(msan)' 2>&1 | \
3 ; RUN: FileCheck -allow-deprecated-dag-overlap -check-prefixes=CHECK,CHECK-ORIGINS %s
4 ; RUN: opt < %s -passes='module(msan-module),function(msan)' -msan-check-access-address=0 -msan-track-origins=1 -S | \
5 ; RUN: FileCheck -allow-deprecated-dag-overlap -check-prefixes=CHECK,CHECK-ORIGINS %s
76
87 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"
98 target triple = "x86_64-unknown-linux-gnu"
0 ; RUN: opt < %s -tsan -S | FileCheck %s
1 ; RUN: opt < %s -passes=tsan -S | FileCheck %s
1 ; RUN: opt < %s -passes='function(tsan),module(tsan-module)' -S | FileCheck %s
22
33 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"
44 target triple = "x86_64-unknown-linux-gnu"