llvm.org GIT mirror llvm / d84b0f9
[tsan] Add support for C++ exceptions into TSan (call __tsan_func_exit during unwinding), LLVM part This adds support for TSan C++ exception handling, where we need to add extra calls to __tsan_func_exit when a function is exitted via exception mechanisms. Otherwise the shadow stack gets corrupted (leaked). This patch moves and enhances the existing implementation of EscapeEnumerator that finds all possible function exit points, and adds extra EH cleanup blocks where needed. Differential Revision: https://reviews.llvm.org/D26177 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@286893 91177308-0d34-0410-b5e6-96231b3b80d8 Kuba Brecka 4 years ago
14 changed file(s) with 322 addition(s) and 187 deletion(s). Raw diff Collapse all Expand all
1111
1212 #include "llvm/ADT/DenseMap.h"
1313 #include "llvm/ADT/TinyPtrVector.h"
14 #include "llvm/ADT/Triple.h"
1415 #include "llvm/Support/ErrorHandling.h"
1516
1617 namespace llvm {
3738 /// that we understand. If so, return a description of it; otherwise return
3839 /// Unknown.
3940 EHPersonality classifyEHPersonality(const Value *Pers);
41
42 StringRef getEHPersonalityName(EHPersonality Pers);
43
44 EHPersonality getDefaultEHPersonality(const Triple &T);
4045
4146 /// \brief Returns true if this personality function catches asynchronous
4247 /// exceptions.
0 //===-- EscapeEnumerator.h --------------------------------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Defines a helper class that enumerates all possible exits from a function,
10 // including exception handling.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_TRANSFORMS_UTILS_ESCAPEENUMERATOR_H
15 #define LLVM_TRANSFORMS_UTILS_ESCAPEENUMERATOR_H
16
17 #include "llvm/IR/IRBuilder.h"
18 #include "llvm/IR/Function.h"
19
20 namespace llvm {
21
22 /// EscapeEnumerator - This is a little algorithm to find all escape points
23 /// from a function so that "finally"-style code can be inserted. In addition
24 /// to finding the existing return and unwind instructions, it also (if
25 /// necessary) transforms any call instructions into invokes and sends them to
26 /// a landing pad.
27 class EscapeEnumerator {
28 Function &F;
29 const char *CleanupBBName;
30
31 Function::iterator StateBB, StateE;
32 IRBuilder<> Builder;
33 bool Done;
34 bool HandleExceptions;
35
36 public:
37 EscapeEnumerator(Function &F, const char *N = "cleanup",
38 bool HandleExceptions = true)
39 : F(F), CleanupBBName(N), StateBB(F.begin()), StateE(F.end()),
40 Builder(F.getContext()), Done(false),
41 HandleExceptions(HandleExceptions) {}
42
43 IRBuilder<> *Next();
44 };
45
46 }
47
48 #endif // LLVM_TRANSFORMS_UTILS_ESCAPEENUMERATOR_H
313313 /// instruction, making it and the rest of the code in the block dead.
314314 unsigned changeToUnreachable(Instruction *I, bool UseLLVMTrap);
315315
316 /// Convert the CallInst to InvokeInst with the specified unwind edge basic
317 /// block. This also splits the basic block where CI is located, because
318 /// InvokeInst is a terminator instruction. Returns the newly split basic
319 /// block.
320 BasicBlock *changeToInvokeAndSplitBasicBlock(CallInst *CI,
321 BasicBlock *UnwindEdge);
322
316323 /// Replace 'BB's terminator with one that does not have an unwind successor
317324 /// block. Rewrites `invoke` to `call`, etc. Updates any PHIs in unwind
318325 /// successor.
3737 .Case("ProcessCLRException", EHPersonality::CoreCLR)
3838 .Case("rust_eh_personality", EHPersonality::Rust)
3939 .Default(EHPersonality::Unknown);
40 }
41
42 StringRef llvm::getEHPersonalityName(EHPersonality Pers) {
43 switch (Pers) {
44 case EHPersonality::GNU_Ada: return "__gnat_eh_personality";
45 case EHPersonality::GNU_CXX: return "__gxx_personality_v0";
46 case EHPersonality::GNU_CXX_SjLj: return "__gxx_personality_sj0";
47 case EHPersonality::GNU_C: return "__gcc_personality_v0";
48 case EHPersonality::GNU_C_SjLj: return "__gcc_personality_sj0";
49 case EHPersonality::GNU_ObjC: return "__objc_personality_v0";
50 case EHPersonality::MSVC_X86SEH: return "_except_handler3";
51 case EHPersonality::MSVC_Win64SEH: return "__C_specific_handler";
52 case EHPersonality::MSVC_CXX: return "__CxxFrameHandler3";
53 case EHPersonality::CoreCLR: return "ProcessCLRException";
54 case EHPersonality::Rust: return "rust_eh_personality";
55 case EHPersonality::Unknown: llvm_unreachable("Unknown EHPersonality!");
56 }
57
58 llvm_unreachable("Invalid EHPersonality!");
59 }
60
61 EHPersonality llvm::getDefaultEHPersonality(const Triple &T) {
62 return EHPersonality::GNU_C;
4063 }
4164
4265 bool llvm::canSimplifyInvokeNoUnwind(const Function *F) {
2222 #include "llvm/IR/IRBuilder.h"
2323 #include "llvm/IR/IntrinsicInst.h"
2424 #include "llvm/IR/Module.h"
25 #include "llvm/Transforms/Utils/EscapeEnumerator.h"
2526
2627 using namespace llvm;
2728
7980 FrameMapTy(nullptr) {
8081 initializeShadowStackGCLoweringPass(*PassRegistry::getPassRegistry());
8182 }
82
83 namespace {
84 /// EscapeEnumerator - This is a little algorithm to find all escape points
85 /// from a function so that "finally"-style code can be inserted. In addition
86 /// to finding the existing return and unwind instructions, it also (if
87 /// necessary) transforms any call instructions into invokes and sends them to
88 /// a landing pad.
89 ///
90 /// It's wrapped up in a state machine using the same transform C# uses for
91 /// 'yield return' enumerators, This transform allows it to be non-allocating.
92 class EscapeEnumerator {
93 Function &F;
94 const char *CleanupBBName;
95
96 // State.
97 int State;
98 Function::iterator StateBB, StateE;
99 IRBuilder<> Builder;
100
101 public:
102 EscapeEnumerator(Function &F, const char *N = "cleanup")
103 : F(F), CleanupBBName(N), State(0), Builder(F.getContext()) {}
104
105 IRBuilder<> *Next() {
106 switch (State) {
107 default:
108 return nullptr;
109
110 case 0:
111 StateBB = F.begin();
112 StateE = F.end();
113 State = 1;
114
115 case 1:
116 // Find all 'return', 'resume', and 'unwind' instructions.
117 while (StateBB != StateE) {
118 BasicBlock *CurBB = &*StateBB++;
119
120 // Branches and invokes do not escape, only unwind, resume, and return
121 // do.
122 TerminatorInst *TI = CurBB->getTerminator();
123 if (!isa(TI) && !isa(TI))
124 continue;
125
126 Builder.SetInsertPoint(TI);
127 return &Builder;
128 }
129
130 State = 2;
131
132 // Find all 'call' instructions.
133 SmallVector Calls;
134 for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
135 for (BasicBlock::iterator II = BB->begin(), EE = BB->end(); II != EE;
136 ++II)
137 if (CallInst *CI = dyn_cast(II))
138 if (!CI->getCalledFunction() ||
139 !CI->getCalledFunction()->getIntrinsicID())
140 Calls.push_back(CI);
141
142 if (Calls.empty())
143 return nullptr;
144
145 // Create a cleanup block.
146 LLVMContext &C = F.getContext();
147 BasicBlock *CleanupBB = BasicBlock::Create(C, CleanupBBName, &F);
148 Type *ExnTy =
149 StructType::get(Type::getInt8PtrTy(C), Type::getInt32Ty(C), nullptr);
150 if (!F.hasPersonalityFn()) {
151 Constant *PersFn = F.getParent()->getOrInsertFunction(
152 "__gcc_personality_v0",
153 FunctionType::get(Type::getInt32Ty(C), true));
154 F.setPersonalityFn(PersFn);
155 }
156 LandingPadInst *LPad =
157 LandingPadInst::Create(ExnTy, 1, "cleanup.lpad", CleanupBB);
158 LPad->setCleanup(true);
159 ResumeInst *RI = ResumeInst::Create(LPad, CleanupBB);
160
161 // Transform the 'call' instructions into 'invoke's branching to the
162 // cleanup block. Go in reverse order to make prettier BB names.
163 SmallVector Args;
164 for (unsigned I = Calls.size(); I != 0;) {
165 CallInst *CI = cast(Calls[--I]);
166
167 // Split the basic block containing the function call.
168 BasicBlock *CallBB = CI->getParent();
169 BasicBlock *NewBB = CallBB->splitBasicBlock(
170 CI->getIterator(), CallBB->getName() + ".cont");
171
172 // Remove the unconditional branch inserted at the end of CallBB.
173 CallBB->getInstList().pop_back();
174 NewBB->getInstList().remove(CI);
175
176 // Create a new invoke instruction.
177 Args.clear();
178 CallSite CS(CI);
179 Args.append(CS.arg_begin(), CS.arg_end());
180
181 InvokeInst *II =
182 InvokeInst::Create(CI->getCalledValue(), NewBB, CleanupBB, Args,
183 CI->getName(), CallBB);
184 II->setCallingConv(CI->getCallingConv());
185 II->setAttributes(CI->getAttributes());
186 CI->replaceAllUsesWith(II);
187 delete CI;
188 }
189
190 Builder.SetInsertPoint(RI);
191 return &Builder;
192 }
193 }
194 };
195 }
196
19783
19884 Constant *ShadowStackGCLowering::GetFrameMap(Function &F) {
19985 // doInitialization creates the abstract type of this value.
4242 #include "llvm/Support/MathExtras.h"
4343 #include "llvm/Support/raw_ostream.h"
4444 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
45 #include "llvm/Transforms/Utils/EscapeEnumerator.h"
4546 #include "llvm/Transforms/Utils/Local.h"
4647 #include "llvm/Transforms/Utils/ModuleUtils.h"
4748
5556 static cl::opt ClInstrumentFuncEntryExit(
5657 "tsan-instrument-func-entry-exit", cl::init(true),
5758 cl::desc("Instrument function entry and exit"), cl::Hidden);
59 static cl::opt ClHandleCxxExceptions(
60 "tsan-handle-cxx-exceptions", cl::init(true),
61 cl::desc("Handle C++ exceptions (insert cleanup blocks for unwinding)"),
62 cl::Hidden);
5863 static cl::opt ClInstrumentAtomics(
5964 "tsan-instrument-atomics", cl::init(true),
6065 cl::desc("Instrument atomics"), cl::Hidden);
98103 const DataLayout &DL);
99104 bool addrPointsToConstantData(Value *Addr);
100105 int getMemoryAccessFuncIndex(Value *Addr, const DataLayout &DL);
101 void InsertRuntimeIgnores(Function &F, SmallVector &RetVec);
106 void InsertRuntimeIgnores(Function &F);
102107
103108 Type *IntptrTy;
104109 IntegerType *OrdTy;
149154
150155 void ThreadSanitizer::initializeCallbacks(Module &M) {
151156 IRBuilder<> IRB(M.getContext());
157 AttributeSet Attr;
158 Attr = Attr.addAttribute(M.getContext(), AttributeSet::FunctionIndex, Attribute::NoUnwind);
152159 // Initialize the callbacks.
153160 TsanFuncEntry = checkSanitizerInterfaceFunction(M.getOrInsertFunction(
154 "__tsan_func_entry", IRB.getVoidTy(), IRB.getInt8PtrTy(), nullptr));
161 "__tsan_func_entry", Attr, IRB.getVoidTy(), IRB.getInt8PtrTy(), nullptr));
155162 TsanFuncExit = checkSanitizerInterfaceFunction(
156 M.getOrInsertFunction("__tsan_func_exit", IRB.getVoidTy(), nullptr));
163 M.getOrInsertFunction("__tsan_func_exit", Attr, IRB.getVoidTy(), nullptr));
157164 TsanIgnoreBegin = checkSanitizerInterfaceFunction(M.getOrInsertFunction(
158 "__tsan_ignore_thread_begin", IRB.getVoidTy(), nullptr));
165 "__tsan_ignore_thread_begin", Attr, IRB.getVoidTy(), nullptr));
159166 TsanIgnoreEnd = checkSanitizerInterfaceFunction(M.getOrInsertFunction(
160 "__tsan_ignore_thread_end", IRB.getVoidTy(), nullptr));
167 "__tsan_ignore_thread_end", Attr, IRB.getVoidTy(), nullptr));
161168 OrdTy = IRB.getInt32Ty();
162169 for (size_t i = 0; i < kNumberOfAccessSizes; ++i) {
163170 const unsigned ByteSize = 1U << i;
166173 std::string BitSizeStr = utostr(BitSize);
167174 SmallString<32> ReadName("__tsan_read" + ByteSizeStr);
168175 TsanRead[i] = checkSanitizerInterfaceFunction(M.getOrInsertFunction(
169 ReadName, IRB.getVoidTy(), IRB.getInt8PtrTy(), nullptr));
176 ReadName, Attr, IRB.getVoidTy(), IRB.getInt8PtrTy(), nullptr));
170177
171178 SmallString<32> WriteName("__tsan_write" + ByteSizeStr);
172179 TsanWrite[i] = checkSanitizerInterfaceFunction(M.getOrInsertFunction(
173 WriteName, IRB.getVoidTy(), IRB.getInt8PtrTy(), nullptr));
180 WriteName, Attr, IRB.getVoidTy(), IRB.getInt8PtrTy(), nullptr));
174181
175182 SmallString<64> UnalignedReadName("__tsan_unaligned_read" + ByteSizeStr);
176183 TsanUnalignedRead[i] =
177184 checkSanitizerInterfaceFunction(M.getOrInsertFunction(
178 UnalignedReadName, IRB.getVoidTy(), IRB.getInt8PtrTy(), nullptr));
185 UnalignedReadName, Attr, IRB.getVoidTy(), IRB.getInt8PtrTy(), nullptr));
179186
180187 SmallString<64> UnalignedWriteName("__tsan_unaligned_write" + ByteSizeStr);
181188 TsanUnalignedWrite[i] =
182189 checkSanitizerInterfaceFunction(M.getOrInsertFunction(
183 UnalignedWriteName, IRB.getVoidTy(), IRB.getInt8PtrTy(), nullptr));
190 UnalignedWriteName, Attr, IRB.getVoidTy(), IRB.getInt8PtrTy(), nullptr));
184191
185192 Type *Ty = Type::getIntNTy(M.getContext(), BitSize);
186193 Type *PtrTy = Ty->getPointerTo();
187194 SmallString<32> AtomicLoadName("__tsan_atomic" + BitSizeStr + "_load");
188195 TsanAtomicLoad[i] = checkSanitizerInterfaceFunction(
189 M.getOrInsertFunction(AtomicLoadName, Ty, PtrTy, OrdTy, nullptr));
196 M.getOrInsertFunction(AtomicLoadName, Attr, Ty, PtrTy, OrdTy, nullptr));
190197
191198 SmallString<32> AtomicStoreName("__tsan_atomic" + BitSizeStr + "_store");
192199 TsanAtomicStore[i] = checkSanitizerInterfaceFunction(M.getOrInsertFunction(
193 AtomicStoreName, IRB.getVoidTy(), PtrTy, Ty, OrdTy, nullptr));
200 AtomicStoreName, Attr, IRB.getVoidTy(), PtrTy, Ty, OrdTy, nullptr));
194201
195202 for (int op = AtomicRMWInst::FIRST_BINOP;
196203 op <= AtomicRMWInst::LAST_BINOP; ++op) {
214221 continue;
215222 SmallString<32> RMWName("__tsan_atomic" + itostr(BitSize) + NamePart);
216223 TsanAtomicRMW[op][i] = checkSanitizerInterfaceFunction(
217 M.getOrInsertFunction(RMWName, Ty, PtrTy, Ty, OrdTy, nullptr));
224 M.getOrInsertFunction(RMWName, Attr, Ty, PtrTy, Ty, OrdTy, nullptr));
218225 }
219226
220227 SmallString<32> AtomicCASName("__tsan_atomic" + BitSizeStr +
221228 "_compare_exchange_val");
222229 TsanAtomicCAS[i] = checkSanitizerInterfaceFunction(M.getOrInsertFunction(
223 AtomicCASName, Ty, PtrTy, Ty, Ty, OrdTy, OrdTy, nullptr));
230 AtomicCASName, Attr, Ty, PtrTy, Ty, Ty, OrdTy, OrdTy, nullptr));
224231 }
225232 TsanVptrUpdate = checkSanitizerInterfaceFunction(
226 M.getOrInsertFunction("__tsan_vptr_update", IRB.getVoidTy(),
233 M.getOrInsertFunction("__tsan_vptr_update", Attr, IRB.getVoidTy(),
227234 IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), nullptr));
228235 TsanVptrLoad = checkSanitizerInterfaceFunction(M.getOrInsertFunction(
229 "__tsan_vptr_read", IRB.getVoidTy(), IRB.getInt8PtrTy(), nullptr));
236 "__tsan_vptr_read", Attr, IRB.getVoidTy(), IRB.getInt8PtrTy(), nullptr));
230237 TsanAtomicThreadFence = checkSanitizerInterfaceFunction(M.getOrInsertFunction(
231 "__tsan_atomic_thread_fence", IRB.getVoidTy(), OrdTy, nullptr));
238 "__tsan_atomic_thread_fence", Attr, IRB.getVoidTy(), OrdTy, nullptr));
232239 TsanAtomicSignalFence = checkSanitizerInterfaceFunction(M.getOrInsertFunction(
233 "__tsan_atomic_signal_fence", IRB.getVoidTy(), OrdTy, nullptr));
240 "__tsan_atomic_signal_fence", Attr, IRB.getVoidTy(), OrdTy, nullptr));
234241
235242 MemmoveFn = checkSanitizerInterfaceFunction(
236 M.getOrInsertFunction("memmove", IRB.getInt8PtrTy(), IRB.getInt8PtrTy(),
243 M.getOrInsertFunction("memmove", Attr, IRB.getInt8PtrTy(), IRB.getInt8PtrTy(),
237244 IRB.getInt8PtrTy(), IntptrTy, nullptr));
238245 MemcpyFn = checkSanitizerInterfaceFunction(
239 M.getOrInsertFunction("memcpy", IRB.getInt8PtrTy(), IRB.getInt8PtrTy(),
246 M.getOrInsertFunction("memcpy", Attr, IRB.getInt8PtrTy(), IRB.getInt8PtrTy(),
240247 IRB.getInt8PtrTy(), IntptrTy, nullptr));
241248 MemsetFn = checkSanitizerInterfaceFunction(
242 M.getOrInsertFunction("memset", IRB.getInt8PtrTy(), IRB.getInt8PtrTy(),
249 M.getOrInsertFunction("memset", Attr, IRB.getInt8PtrTy(), IRB.getInt8PtrTy(),
243250 IRB.getInt32Ty(), IntptrTy, nullptr));
244251 }
245252
382389 return false;
383390 }
384391
385 void ThreadSanitizer::InsertRuntimeIgnores(Function &F,
386 SmallVector &RetVec) {
392 void ThreadSanitizer::InsertRuntimeIgnores(Function &F) {
387393 IRBuilder<> IRB(F.getEntryBlock().getFirstNonPHI());
388394 IRB.CreateCall(TsanIgnoreBegin);
389 for (auto RetInst : RetVec) {
390 IRBuilder<> IRB(RetInst);
391 IRB.CreateCall(TsanIgnoreEnd);
395 EscapeEnumerator EE(F, "tsan_ignore_cleanup", ClHandleCxxExceptions);
396 while (IRBuilder<> *AtExit = EE.Next()) {
397 AtExit->CreateCall(TsanIgnoreEnd);
392398 }
393399 }
394400
398404 if (&F == TsanCtorFunction)
399405 return false;
400406 initializeCallbacks(*F.getParent());
401 SmallVector RetVec;
402407 SmallVector AllLoadsAndStores;
403408 SmallVector LocalLoadsAndStores;
404409 SmallVector AtomicAccesses;
417422 AtomicAccesses.push_back(&Inst);
418423 else if (isa(Inst) || isa(Inst))
419424 LocalLoadsAndStores.push_back(&Inst);
420 else if (isa(Inst))
421 RetVec.push_back(&Inst);
422425 else if (isa(Inst) || isa(Inst)) {
423426 if (CallInst *CI = dyn_cast(&Inst))
424427 maybeMarkSanitizerLibraryCallNoBuiltin(CI, TLI);
457460 if (F.hasFnAttribute("sanitize_thread_no_checking_at_run_time")) {
458461 assert(!F.hasFnAttribute(Attribute::SanitizeThread));
459462 if (HasCalls)
460 InsertRuntimeIgnores(F, RetVec);
463 InsertRuntimeIgnores(F);
461464 }
462465
463466 // Instrument function entry/exit points if there were instrumented accesses.
467470 Intrinsic::getDeclaration(F.getParent(), Intrinsic::returnaddress),
468471 IRB.getInt32(0));
469472 IRB.CreateCall(TsanFuncEntry, ReturnAddress);
470 for (auto RetInst : RetVec) {
471 IRBuilder<> IRBRet(RetInst);
472 IRBRet.CreateCall(TsanFuncExit, {});
473
474 EscapeEnumerator EE(F, "tsan_cleanup", ClHandleCxxExceptions);
475 while (IRBuilder<> *AtExit = EE.Next()) {
476 AtExit->CreateCall(TsanFuncExit, {});
473477 }
474478 Res = true;
475479 }
1010 CodeExtractor.cpp
1111 CtorUtils.cpp
1212 DemoteRegToStack.cpp
13 EscapeEnumerator.cpp
1314 Evaluator.cpp
1415 FlattenCFG.cpp
1516 FunctionComparator.cpp
0 //===- EscapeEnumerator.cpp -----------------------------------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Defines a helper class that enumerates all possible exits from a function,
10 // including exception handling.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/Transforms/Utils/EscapeEnumerator.h"
15 #include "llvm/Analysis/EHPersonalities.h"
16 #include "llvm/IR/CallSite.h"
17 #include "llvm/IR/Module.h"
18 #include "llvm/Transforms/Utils/Local.h"
19 using namespace llvm;
20
21 static Constant *getDefaultPersonalityFn(Module *M) {
22 LLVMContext &C = M->getContext();
23 Triple T(M->getTargetTriple());
24 EHPersonality Pers = getDefaultEHPersonality(T);
25 return M->getOrInsertFunction(getEHPersonalityName(Pers),
26 FunctionType::get(Type::getInt32Ty(C), true));
27 }
28
29 IRBuilder<> *EscapeEnumerator::Next() {
30 if (Done)
31 return nullptr;
32
33 // Find all 'return', 'resume', and 'unwind' instructions.
34 while (StateBB != StateE) {
35 BasicBlock *CurBB = &*StateBB++;
36
37 // Branches and invokes do not escape, only unwind, resume, and return
38 // do.
39 TerminatorInst *TI = CurBB->getTerminator();
40 if (!isa(TI) && !isa(TI))
41 continue;
42
43 Builder.SetInsertPoint(TI);
44 return &Builder;
45 }
46
47 Done = true;
48
49 if (!HandleExceptions)
50 return nullptr;
51
52 if (F.doesNotThrow())
53 return nullptr;
54
55 // Find all 'call' instructions that may throw.
56 SmallVector Calls;
57 for (BasicBlock &BB : F)
58 for (Instruction &II : BB)
59 if (CallInst *CI = dyn_cast(&II))
60 if (!CI->doesNotThrow())
61 Calls.push_back(CI);
62
63 if (Calls.empty())
64 return nullptr;
65
66 // Create a cleanup block.
67 LLVMContext &C = F.getContext();
68 BasicBlock *CleanupBB = BasicBlock::Create(C, CleanupBBName, &F);
69 Type *ExnTy =
70 StructType::get(Type::getInt8PtrTy(C), Type::getInt32Ty(C), nullptr);
71 if (!F.hasPersonalityFn()) {
72 Constant *PersFn = getDefaultPersonalityFn(F.getParent());
73 F.setPersonalityFn(PersFn);
74 }
75
76 if (isFuncletEHPersonality(classifyEHPersonality(F.getPersonalityFn()))) {
77 report_fatal_error("Funclet EH not supported");
78 }
79
80 LandingPadInst *LPad =
81 LandingPadInst::Create(ExnTy, 1, "cleanup.lpad", CleanupBB);
82 LPad->setCleanup(true);
83 ResumeInst *RI = ResumeInst::Create(LPad, CleanupBB);
84
85 // Transform the 'call' instructions into 'invoke's branching to the
86 // cleanup block. Go in reverse order to make prettier BB names.
87 SmallVector Args;
88 for (unsigned I = Calls.size(); I != 0;) {
89 CallInst *CI = cast(Calls[--I]);
90 changeToInvokeAndSplitBasicBlock(CI, CleanupBB);
91 }
92
93 Builder.SetInsertPoint(RI);
94 return &Builder;
95 }
534534 #endif // NDEBUG
535535 }
536536
537 // Convert this function call into an invoke instruction. First, split the
538 // basic block.
539 BasicBlock *Split =
540 BB->splitBasicBlock(CI->getIterator(), CI->getName() + ".noexc");
541
542 // Delete the unconditional branch inserted by splitBasicBlock
543 BB->getInstList().pop_back();
544
545 // Create the new invoke instruction.
546 SmallVector InvokeArgs(CI->arg_begin(), CI->arg_end());
547 SmallVector OpBundles;
548
549 CI->getOperandBundlesAsDefs(OpBundles);
550
551 // Note: we're round tripping operand bundles through memory here, and that
552 // can potentially be avoided with a cleverer API design that we do not have
553 // as of this time.
554
555 InvokeInst *II =
556 InvokeInst::Create(CI->getCalledValue(), Split, UnwindEdge, InvokeArgs,
557 OpBundles, CI->getName(), BB);
558 II->setDebugLoc(CI->getDebugLoc());
559 II->setCallingConv(CI->getCallingConv());
560 II->setAttributes(CI->getAttributes());
561
562 // Make sure that anything using the call now uses the invoke! This also
563 // updates the CallGraph if present, because it uses a WeakVH.
564 CI->replaceAllUsesWith(II);
565
566 // Delete the original call
567 Split->getInstList().pop_front();
537 changeToInvokeAndSplitBasicBlock(CI, UnwindEdge);
568538 return BB;
569539 }
570540 return nullptr;
14051405 // Update PHI nodes in the unwind destination
14061406 II->getUnwindDest()->removePredecessor(II->getParent());
14071407 II->eraseFromParent();
1408 }
1409
1410 BasicBlock *llvm::changeToInvokeAndSplitBasicBlock(CallInst *CI,
1411 BasicBlock *UnwindEdge) {
1412 BasicBlock *BB = CI->getParent();
1413
1414 // Convert this function call into an invoke instruction. First, split the
1415 // basic block.
1416 BasicBlock *Split =
1417 BB->splitBasicBlock(CI->getIterator(), CI->getName() + ".noexc");
1418
1419 // Delete the unconditional branch inserted by splitBasicBlock
1420 BB->getInstList().pop_back();
1421
1422 // Create the new invoke instruction.
1423 SmallVector InvokeArgs(CI->arg_begin(), CI->arg_end());
1424 SmallVector OpBundles;
1425
1426 CI->getOperandBundlesAsDefs(OpBundles);
1427
1428 // Note: we're round tripping operand bundles through memory here, and that
1429 // can potentially be avoided with a cleverer API design that we do not have
1430 // as of this time.
1431
1432 InvokeInst *II = InvokeInst::Create(CI->getCalledValue(), Split, UnwindEdge,
1433 InvokeArgs, OpBundles, CI->getName(), BB);
1434 II->setDebugLoc(CI->getDebugLoc());
1435 II->setCallingConv(CI->getCallingConv());
1436 II->setAttributes(CI->getAttributes());
1437
1438 // Make sure that anything using the call now uses the invoke! This also
1439 // updates the CallGraph if present, because it uses a WeakVH.
1440 CI->replaceAllUsesWith(II);
1441
1442 // Delete the original call
1443 Split->getInstList().pop_front();
1444 return Split;
14081445 }
14091446
14101447 static bool markAliveBlocks(Function &F,
0 ; RUN: opt < %s -tsan -S | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-EXC
1 ; RUN: opt < %s -tsan -S -tsan-handle-cxx-exceptions=0 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NOEXC
2
3 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"
4
5 declare void @can_throw()
6 declare void @cannot_throw() nounwind
7
8 define i32 @func1() sanitize_thread {
9 call void @can_throw()
10 ret i32 0
11 ; CHECK-EXC: define i32 @func1()
12 ; CHECK-EXC: call void @__tsan_func_entry
13 ; CHECK-EXC: invoke void @can_throw()
14 ; CHECK-EXC: .noexc:
15 ; CHECK-EXC: call void @__tsan_func_exit()
16 ; CHECK-EXC: ret i32 0
17 ; CHECK-EXC: tsan_cleanup:
18 ; CHECK-EXC: call void @__tsan_func_exit()
19 ; CHECK-EXC: resume
20 ; CHECK-NOEXC: define i32 @func1()
21 ; CHECK-NOEXC: call void @__tsan_func_entry
22 ; CHECK-NOEXC: call void @can_throw()
23 ; CHECK-NOEXC: call void @__tsan_func_exit()
24 ; CHECK-NOEXC: ret i32 0
25 }
26
27 define i32 @func2() sanitize_thread {
28 call void @cannot_throw()
29 ret i32 0
30 ; CHECK: define i32 @func2()
31 ; CHECK: call void @__tsan_func_entry
32 ; CHECK: call void @cannot_throw()
33 ; CHECK: call void @__tsan_func_exit()
34 ; CHECK: ret i32 0
35 }
36
37 define i32 @func3(i32* %p) sanitize_thread {
38 %a = load i32, i32* %p
39 ret i32 %a
40 ; CHECK: define i32 @func3(i32* %p)
41 ; CHECK: call void @__tsan_func_entry
42 ; CHECK: call void @__tsan_read4
43 ; CHECK: %a = load i32, i32* %p
44 ; CHECK: call void @__tsan_func_exit()
45 ; CHECK: ret i32 %a
46 }
47
48 define i32 @func4() sanitize_thread nounwind {
49 call void @can_throw()
50 ret i32 0
51 ; CHECK: define i32 @func4()
52 ; CHECK: call void @__tsan_func_entry
53 ; CHECK: call void @can_throw()
54 ; CHECK: call void @__tsan_func_exit()
55 ; CHECK: ret i32 0
56 }
3131 ; CHECK-NEXT: call void @__tsan_func_exit()
3232 ; CHECK-NEXT: ret i32 %tmp1
3333
34 declare void @foo()
34 declare void @foo() nounwind
3535
1313 ; CHECK-NEXT: %tmp1 = load i32, i32* %a, align 4
1414 ; CHECK-NEXT: ret i32 %tmp1
1515
16 declare void @"foo"()
16 declare void @"foo"() nounwind
1717
1818 define i32 @"\01-[WithCalls dealloc]"(i32* %a) "sanitize_thread_no_checking_at_run_time" {
1919 entry:
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"
55
6 declare i8* @memchr(i8* %a, i32 %b, i64 %c)
7 declare i32 @memcmp(i8* %a, i8* %b, i64 %c)
8 declare i32 @strcmp(i8* %a, i8* %b)
9 declare i8* @strcpy(i8* %a, i8* %b)
10 declare i8* @stpcpy(i8* %a, i8* %b)
11 declare i64 @strlen(i8* %a)
12 declare i64 @strnlen(i8* %a, i64 %b)
6 declare i8* @memchr(i8* %a, i32 %b, i64 %c) nounwind
7 declare i32 @memcmp(i8* %a, i8* %b, i64 %c) nounwind
8 declare i32 @strcmp(i8* %a, i8* %b) nounwind
9 declare i8* @strcpy(i8* %a, i8* %b) nounwind
10 declare i8* @stpcpy(i8* %a, i8* %b) nounwind
11 declare i64 @strlen(i8* %a) nounwind
12 declare i64 @strnlen(i8* %a, i64 %b) nounwind
1313
1414 ; CHECK: call{{.*}}@memchr{{.*}} #[[ATTR:[0-9]+]]
1515 ; CHECK: call{{.*}}@memcmp{{.*}} #[[ATTR]]