22
22
#include " llvm/IR/DataLayout.h"
23
23
#include " llvm/IR/Function.h"
24
24
#include " llvm/IR/IRBuilder.h"
25
+ #include " llvm/IR/InstIterator.h"
25
26
#include " llvm/IR/Instructions.h"
26
27
#include " llvm/IR/IntrinsicInst.h"
27
28
#include " llvm/IR/Intrinsics.h"
@@ -72,7 +73,7 @@ namespace {
72
73
struct TypeSanitizer {
73
74
TypeSanitizer (Module &M);
74
75
bool run (Function &F, const TargetLibraryInfo &TLI);
75
- void instrumentGlobals ();
76
+ void instrumentGlobals (Module &M );
76
77
77
78
private:
78
79
typedef SmallDenseMap<const MDNode *, GlobalVariable *, 8 >
@@ -114,9 +115,11 @@ struct TypeSanitizer {
114
115
uint64_t PtrShift;
115
116
IntegerType *OrdTy;
116
117
117
- // Callbacks to run-time library are computed in doInitialization.
118
- Function *TysanCheck;
119
- Function *TysanCtorFunction;
118
+ // / Callbacks to run-time library are computed in initializeCallbacks.
119
+ FunctionCallee TysanCheck;
120
+ FunctionCallee TysanCtorFunction;
121
+
122
+ // / Callback to set types for gloabls.
120
123
Function *TysanGlobalsSetTypeFunction;
121
124
};
122
125
} // namespace
@@ -139,29 +142,33 @@ void TypeSanitizer::initializeCallbacks(Module &M) {
139
142
AttributeList Attr;
140
143
Attr = Attr.addFnAttribute (M.getContext (), Attribute::NoUnwind);
141
144
// Initialize the callbacks.
142
- TysanCheck = cast<Function>(
145
+ TysanCheck =
143
146
M.getOrInsertFunction (kTysanCheckName , Attr, IRB.getVoidTy (),
144
147
IRB.getPtrTy (), // Pointer to data to be read.
145
148
OrdTy, // Size of the data in bytes.
146
149
IRB.getPtrTy (), // Pointer to type descriptor.
147
150
OrdTy // Flags.
148
- )
149
- .getCallee ());
151
+ );
150
152
151
153
TysanCtorFunction = cast<Function>(
152
154
M.getOrInsertFunction (kTysanModuleCtorName , Attr, IRB.getVoidTy ())
153
155
.getCallee ());
154
156
}
155
157
156
- void TypeSanitizer::instrumentGlobals () {
157
- Module &M = *TysanCtorFunction->getParent ();
158
- initializeCallbacks (M);
158
+ void TypeSanitizer::instrumentGlobals (Module &M) {
159
159
TysanGlobalsSetTypeFunction = nullptr ;
160
160
161
161
NamedMDNode *Globals = M.getNamedMetadata (" llvm.tysan.globals" );
162
162
if (!Globals)
163
163
return ;
164
164
165
+ TysanGlobalsSetTypeFunction = Function::Create (
166
+ FunctionType::get (Type::getVoidTy (M.getContext ()), false ),
167
+ GlobalValue::InternalLinkage, " __tysan_set_globals_types" , &M);
168
+ BasicBlock *BB =
169
+ BasicBlock::Create (M.getContext (), " " , TysanGlobalsSetTypeFunction);
170
+ ReturnInst::Create (M.getContext (), BB);
171
+
165
172
const DataLayout &DL = M.getDataLayout ();
166
173
Value *ShadowBase = nullptr , *AppMemMask = nullptr ;
167
174
TypeDescriptorsMapTy TypeDescriptors;
@@ -175,15 +182,6 @@ void TypeSanitizer::instrumentGlobals() {
175
182
if (!generateBaseTypeDescriptor (TBAAMD, TypeDescriptors, TypeNames, M))
176
183
continue ;
177
184
178
- if (!TysanGlobalsSetTypeFunction) {
179
- TysanGlobalsSetTypeFunction = Function::Create (
180
- FunctionType::get (Type::getVoidTy (M.getContext ()), false ),
181
- GlobalValue::InternalLinkage, " __tysan_set_globals_types" , &M);
182
- BasicBlock *BB =
183
- BasicBlock::Create (M.getContext (), " " , TysanGlobalsSetTypeFunction);
184
- ReturnInst::Create (M.getContext (), BB);
185
- }
186
-
187
185
IRBuilder<> IRB (
188
186
TysanGlobalsSetTypeFunction->getEntryBlock ().getTerminator ());
189
187
Type *AccessTy = GV->getValueType ();
@@ -195,23 +193,13 @@ void TypeSanitizer::instrumentGlobals() {
195
193
}
196
194
197
195
if (TysanGlobalsSetTypeFunction) {
198
- IRBuilder<> IRB (TysanCtorFunction->getEntryBlock ().getTerminator ());
196
+ IRBuilder<> IRB (cast<Function>(TysanCtorFunction.getCallee ())
197
+ ->getEntryBlock ()
198
+ .getTerminator ());
199
199
IRB.CreateCall (TysanGlobalsSetTypeFunction, {});
200
200
}
201
201
}
202
202
203
- static void insertModuleCtor (Module &M) {
204
- Function *TysanCtorFunction;
205
- std::tie (TysanCtorFunction, std::ignore) =
206
- createSanitizerCtorAndInitFunctions (M, kTysanModuleCtorName ,
207
- kTysanInitName , /* InitArgTypes=*/ {},
208
- /* InitArgs=*/ {});
209
-
210
- TypeSanitizer TySan (M);
211
- TySan.instrumentGlobals ();
212
- appendToGlobalCtors (M, TysanCtorFunction, 0 );
213
- }
214
-
215
203
static const char LUT[] = " 0123456789abcdef" ;
216
204
217
205
static std::string encodeName (StringRef Name) {
@@ -220,7 +208,7 @@ static std::string encodeName(StringRef Name) {
220
208
Output.reserve (Output.size () + 3 * Length);
221
209
for (size_t i = 0 ; i < Length; ++i) {
222
210
const unsigned char c = Name[i];
223
- if (isalnum (( int ) c)) {
211
+ if (isalnum (c)) {
224
212
Output.push_back (c);
225
213
continue ;
226
214
}
@@ -337,11 +325,13 @@ bool TypeSanitizer::generateBaseTypeDescriptor(
337
325
SmallVector<Type *> TDSubTys;
338
326
SmallVector<Constant *> TDSubData;
339
327
340
- TDSubTys.push_back (IntptrTy);
341
- TDSubData.push_back (ConstantInt::get (IntptrTy, 2 ));
328
+ auto PushTDSub = [&](Constant *C) {
329
+ TDSubTys.push_back (C->getType ());
330
+ TDSubData.push_back (C);
331
+ };
342
332
343
- TDSubTys. push_back ( IntptrTy);
344
- TDSubData. push_back (ConstantInt::get (IntptrTy, Members.size ()));
333
+ PushTDSub ( ConstantInt::get ( IntptrTy, 2 ) );
334
+ PushTDSub (ConstantInt::get (IntptrTy, Members.size ()));
345
335
346
336
// Types that are in an anonymous namespace are local to this module.
347
337
// FIXME: This should really be marked by the frontend in the metadata
@@ -351,15 +341,11 @@ bool TypeSanitizer::generateBaseTypeDescriptor(
351
341
// anonymous namespace is a template parameter, etc.).
352
342
bool ShouldBeComdat = !AnonNameRegex.match (NameNode->getString ());
353
343
for (auto &Member : Members) {
354
- TDSubTys.push_back (Member.first ->getType ());
355
- TDSubData.push_back (Member.first );
356
-
357
- TDSubTys.push_back (IntptrTy);
358
- TDSubData.push_back (ConstantInt::get (IntptrTy, Member.second ));
344
+ PushTDSub (Member.first );
345
+ PushTDSub (ConstantInt::get (IntptrTy, Member.second ));
359
346
}
360
347
361
- TDSubTys.push_back (NameData->getType ());
362
- TDSubData.push_back (NameData);
348
+ PushTDSub (NameData);
363
349
364
350
StructType *TDTy = StructType::get (C, TDSubTys);
365
351
Constant *TD = ConstantStruct::get (TDTy, TDSubData);
@@ -482,72 +468,77 @@ Value *TypeSanitizer::getAppMemMask(Function &F) {
482
468
return IRB.CreateLoad (IntptrTy, GlobalAppMemMask, " app.mem.mask" );
483
469
}
484
470
485
- bool TypeSanitizer::run (Function &F, const TargetLibraryInfo &TLI) {
486
- // This is required to prevent instrumenting call to __tysan_init from within
487
- // the module constructor.
488
- if (&F == TysanCtorFunction || &F == TysanGlobalsSetTypeFunction)
489
- return false ;
490
- initializeCallbacks (*F.getParent ());
491
-
492
- SmallVector<std::pair<Instruction *, MemoryLocation>> MemoryAccesses;
493
- SmallSetVector<const MDNode *, 8 > TBAAMetadata;
494
- SmallVector<Value *> MemTypeResetInsts;
495
-
496
- bool Res = false ;
497
- bool SanitizeFunction = F.hasFnAttribute (Attribute::SanitizeType);
498
- const DataLayout &DL = F.getParent ()->getDataLayout ();
471
+ // / Collect all loads and stores, and for what TBAA nodes we need to generate
472
+ // / type descriptors.
473
+ void collectMemAccessInfo (
474
+ Function &F, const TargetLibraryInfo &TLI,
475
+ SmallVectorImpl<std::pair<Instruction *, MemoryLocation>> &MemoryAccesses,
476
+ SmallSetVector<const MDNode *, 8 > &TBAAMetadata,
477
+ SmallVectorImpl<Value *> &MemTypeResetInsts) {
499
478
// Traverse all instructions, collect loads/stores/returns, check for calls.
500
- for (auto &BB : F) {
501
- for (auto &Inst : BB) {
502
- // Skip memory accesses inserted by another instrumentation.
503
- if (Inst.getMetadata (LLVMContext::MD_nosanitize))
504
- continue ;
479
+ for (Instruction &Inst : instructions (F)) {
480
+ // Skip memory accesses inserted by another instrumentation.
481
+ if (Inst.getMetadata (LLVMContext::MD_nosanitize))
482
+ continue ;
505
483
506
- if (isa<LoadInst>(Inst) || isa<StoreInst>(Inst) ||
507
- isa<AtomicCmpXchgInst>(Inst) || isa<AtomicRMWInst>(Inst)) {
508
- MemoryLocation MLoc = MemoryLocation::get (&Inst);
484
+ if (isa<LoadInst>(Inst) || isa<StoreInst>(Inst) ||
485
+ isa<AtomicCmpXchgInst>(Inst) || isa<AtomicRMWInst>(Inst)) {
486
+ MemoryLocation MLoc = MemoryLocation::get (&Inst);
509
487
510
- // Swift errors are special (we can't introduce extra uses on them).
511
- if (MLoc.Ptr ->isSwiftError ())
512
- continue ;
488
+ // Swift errors are special (we can't introduce extra uses on them).
489
+ if (MLoc.Ptr ->isSwiftError ())
490
+ continue ;
513
491
514
- // Skip non-address-space-0 pointers; we don't know how to handle them.
515
- Type *PtrTy = cast<PointerType>(MLoc.Ptr ->getType ());
516
- if (PtrTy->getPointerAddressSpace () != 0 )
517
- continue ;
492
+ // Skip non-address-space-0 pointers; we don't know how to handle them.
493
+ Type *PtrTy = cast<PointerType>(MLoc.Ptr ->getType ());
494
+ if (PtrTy->getPointerAddressSpace () != 0 )
495
+ continue ;
518
496
519
- if (MLoc.AATags .TBAA )
520
- TBAAMetadata.insert (MLoc.AATags .TBAA );
521
- MemoryAccesses.push_back (std::make_pair (&Inst, MLoc));
522
- } else if (isa<CallInst>(Inst) || isa<InvokeInst>(Inst)) {
523
- if (CallInst *CI = dyn_cast<CallInst>(&Inst))
524
- maybeMarkSanitizerLibraryCallNoBuiltin (CI, &TLI);
497
+ if (MLoc.AATags .TBAA )
498
+ TBAAMetadata.insert (MLoc.AATags .TBAA );
499
+ MemoryAccesses.push_back (std::make_pair (&Inst, MLoc));
500
+ } else if (isa<CallInst>(Inst) || isa<InvokeInst>(Inst)) {
501
+ if (CallInst *CI = dyn_cast<CallInst>(&Inst))
502
+ maybeMarkSanitizerLibraryCallNoBuiltin (CI, &TLI);
525
503
526
- if (isa<MemIntrinsic>(Inst)) {
527
- MemTypeResetInsts.push_back (&Inst);
528
- } else if (auto *II = dyn_cast<IntrinsicInst>(&Inst)) {
529
- if (II->getIntrinsicID () == Intrinsic::lifetime_start ||
530
- II->getIntrinsicID () == Intrinsic::lifetime_end)
531
- MemTypeResetInsts.push_back (&Inst);
532
- }
533
- } else if (isa<AllocaInst>(Inst)) {
504
+ if (isa<MemIntrinsic>(Inst)) {
534
505
MemTypeResetInsts.push_back (&Inst);
506
+ } else if (auto *II = dyn_cast<IntrinsicInst>(&Inst)) {
507
+ if (II->getIntrinsicID () == Intrinsic::lifetime_start ||
508
+ II->getIntrinsicID () == Intrinsic::lifetime_end)
509
+ MemTypeResetInsts.push_back (&Inst);
535
510
}
511
+ } else if (isa<AllocaInst>(Inst)) {
512
+ MemTypeResetInsts.push_back (&Inst);
536
513
}
537
514
}
515
+ }
516
+
517
+ bool TypeSanitizer::run (Function &F, const TargetLibraryInfo &TLI) {
518
+ // This is required to prevent instrumenting call to __tysan_init from within
519
+ // the module constructor.
520
+ if (&F == TysanCtorFunction.getCallee () || &F == TysanGlobalsSetTypeFunction)
521
+ return false ;
522
+ initializeCallbacks (*F.getParent ());
523
+
524
+ // We need to collect all loads and stores, and know for what TBAA nodes we
525
+ // need to generate type descriptors.
526
+ SmallVector<std::pair<Instruction *, MemoryLocation>> MemoryAccesses;
527
+ SmallSetVector<const MDNode *, 8 > TBAAMetadata;
528
+ SmallVector<Value *> MemTypeResetInsts;
529
+ collectMemAccessInfo (F, TLI, MemoryAccesses, TBAAMetadata, MemTypeResetInsts);
538
530
539
531
// byval arguments also need their types reset (they're new stack memory,
540
532
// just like allocas).
541
533
for (auto &A : F.args ())
542
534
if (A.hasByValAttr ())
543
535
MemTypeResetInsts.push_back (&A);
544
536
545
- // We have collected all loads and stores, and know for what TBAA nodes we
546
- // need to generate type descriptors.
547
537
548
538
Module &M = *F.getParent ();
549
539
TypeDescriptorsMapTy TypeDescriptors;
550
540
TypeNameMapTy TypeNames;
541
+ bool Res = false ;
551
542
for (const MDNode *MD : TBAAMetadata) {
552
543
if (TypeDescriptors.count (MD))
553
544
continue ;
@@ -558,6 +549,8 @@ bool TypeSanitizer::run(Function &F, const TargetLibraryInfo &TLI) {
558
549
Res = true ;
559
550
}
560
551
552
+ const DataLayout &DL = F.getParent ()->getDataLayout ();
553
+ bool SanitizeFunction = F.hasFnAttribute (Attribute::SanitizeType);
561
554
Value *ShadowBase = nullptr , *AppMemMask = nullptr ;
562
555
for (auto &MA : MemoryAccesses)
563
556
Res |= instrumentMemoryAccess (MA.first , MA.second , ShadowBase, AppMemMask,
@@ -863,6 +856,14 @@ PreservedAnalyses TypeSanitizerPass::run(Function &F,
863
856
864
857
PreservedAnalyses ModuleTypeSanitizerPass::run (Module &M,
865
858
ModuleAnalysisManager &AM) {
866
- insertModuleCtor (M);
859
+ Function *TysanCtorFunction;
860
+ std::tie (TysanCtorFunction, std::ignore) =
861
+ createSanitizerCtorAndInitFunctions (M, kTysanModuleCtorName ,
862
+ kTysanInitName , /* InitArgTypes=*/ {},
863
+ /* InitArgs=*/ {});
864
+
865
+ TypeSanitizer TySan (M);
866
+ TySan.instrumentGlobals (M);
867
+ appendToGlobalCtors (M, TysanCtorFunction, 0 );
867
868
return PreservedAnalyses::none ();
868
869
}
0 commit comments