@@ -159,8 +159,8 @@ static cl::opt<bool>
159
159
160
160
static cl::opt<bool > ClGatedCallbacks (
161
161
" sanitizer-coverage-gated-trace-callbacks" ,
162
- cl::desc (" Gate the invocation of the tracing callbacks on a global "
163
- " variable . Currently only supported for trace-pc-guard." ),
162
+ cl::desc (" Gate the invocation of the tracing callbacks on a global variable "
163
+ " . Currently only supported for trace-pc-guard and trace-cmp ." ),
164
164
cl::Hidden, cl::init(false ));
165
165
166
166
namespace {
@@ -235,22 +235,26 @@ class ModuleSanitizerCoverage {
235
235
void instrumentFunction (Function &F);
236
236
void InjectCoverageForIndirectCalls (Function &F,
237
237
ArrayRef<Instruction *> IndirCalls);
238
- void InjectTraceForCmp (Function &F, ArrayRef<Instruction *> CmpTraceTargets);
238
+ void InjectTraceForCmp (Function &F, ArrayRef<Instruction *> CmpTraceTargets,
239
+ Value *&FunctionGateCmp);
239
240
void InjectTraceForDiv (Function &F,
240
241
ArrayRef<BinaryOperator *> DivTraceTargets);
241
242
void InjectTraceForGep (Function &F,
242
243
ArrayRef<GetElementPtrInst *> GepTraceTargets);
243
244
void InjectTraceForLoadsAndStores (Function &F, ArrayRef<LoadInst *> Loads,
244
245
ArrayRef<StoreInst *> Stores);
245
246
void InjectTraceForSwitch (Function &F,
246
- ArrayRef<Instruction *> SwitchTraceTargets);
247
+ ArrayRef<Instruction *> SwitchTraceTargets,
248
+ Value *&FunctionGateCmp);
247
249
bool InjectCoverage (Function &F, ArrayRef<BasicBlock *> AllBlocks,
248
- bool IsLeafFunc = true );
250
+ Value *&FunctionGateCmp, bool IsLeafFunc = true );
249
251
GlobalVariable *CreateFunctionLocalArrayInSection (size_t NumElements,
250
252
Function &F, Type *Ty,
251
253
const char *Section);
252
254
GlobalVariable *CreatePCArray (Function &F, ArrayRef<BasicBlock *> AllBlocks);
253
255
void CreateFunctionLocalArrays (Function &F, ArrayRef<BasicBlock *> AllBlocks);
256
+ Instruction *CreateGateBranch (Function &F, Value *&FunctionGateCmp,
257
+ Instruction *I);
254
258
Value *CreateFunctionLocalGateCmp (IRBuilder<> &IRB);
255
259
void InjectCoverageAtBlock (Function &F, BasicBlock &BB, size_t Idx,
256
260
Value *&FunctionGateCmp, bool IsLeafFunc = true );
@@ -493,9 +497,9 @@ bool ModuleSanitizerCoverage::instrumentModule() {
493
497
SanCovLowestStack->setInitializer (Constant::getAllOnesValue (IntptrTy));
494
498
495
499
if (Options.GatedCallbacks ) {
496
- if (!Options.TracePCGuard ) {
500
+ if (!Options.TracePCGuard && !Options. TraceCmp ) {
497
501
C->emitError (StringRef (" '" ) + ClGatedCallbacks.ArgStr +
498
- " ' is only supported with trace-pc-guard" );
502
+ " ' is only supported with trace-pc-guard or trace-cmp " );
499
503
return true ;
500
504
}
501
505
@@ -724,10 +728,11 @@ void ModuleSanitizerCoverage::instrumentFunction(Function &F) {
724
728
if (Options.CollectControlFlow )
725
729
createFunctionControlFlow (F);
726
730
727
- InjectCoverage (F, BlocksToInstrument, IsLeafFunc);
731
+ Value *FunctionGateCmp = nullptr ;
732
+ InjectCoverage (F, BlocksToInstrument, FunctionGateCmp, IsLeafFunc);
728
733
InjectCoverageForIndirectCalls (F, IndirCalls);
729
- InjectTraceForCmp (F, CmpTraceTargets);
730
- InjectTraceForSwitch (F, SwitchTraceTargets);
734
+ InjectTraceForCmp (F, CmpTraceTargets, FunctionGateCmp );
735
+ InjectTraceForSwitch (F, SwitchTraceTargets, FunctionGateCmp );
731
736
InjectTraceForDiv (F, DivTraceTargets);
732
737
InjectTraceForGep (F, GepTraceTargets);
733
738
InjectTraceForLoadsAndStores (F, Loads, Stores);
@@ -816,12 +821,30 @@ Value *ModuleSanitizerCoverage::CreateFunctionLocalGateCmp(IRBuilder<> &IRB) {
816
821
return Cmp;
817
822
}
818
823
824
+ Instruction *ModuleSanitizerCoverage::CreateGateBranch (Function &F,
825
+ Value *&FunctionGateCmp,
826
+ Instruction *IP) {
827
+ if (!FunctionGateCmp) {
828
+ // Create this in the entry block
829
+ BasicBlock &BB = F.getEntryBlock ();
830
+ BasicBlock::iterator IP = BB.getFirstInsertionPt ();
831
+ IP = PrepareToSplitEntryBlock (BB, IP);
832
+ IRBuilder<> EntryIRB (&*IP);
833
+ FunctionGateCmp = CreateFunctionLocalGateCmp (EntryIRB);
834
+ }
835
+ // Set the branch weights in order to minimize the price paid when the
836
+ // gate is turned off, allowing the default enablement of this
837
+ // instrumentation with as little of a performance cost as possible
838
+ auto Weights = MDBuilder (*C).createBranchWeights (1 , 100000 );
839
+ return SplitBlockAndInsertIfThen (FunctionGateCmp, IP, false , Weights);
840
+ }
841
+
819
842
bool ModuleSanitizerCoverage::InjectCoverage (Function &F,
820
843
ArrayRef<BasicBlock *> AllBlocks,
844
+ Value *&FunctionGateCmp,
821
845
bool IsLeafFunc) {
822
846
if (AllBlocks.empty ()) return false ;
823
847
CreateFunctionLocalArrays (F, AllBlocks);
824
- Value *FunctionGateCmp = nullptr ;
825
848
for (size_t i = 0 , N = AllBlocks.size (); i < N; i++)
826
849
InjectCoverageAtBlock (F, *AllBlocks[i], i, FunctionGateCmp, IsLeafFunc);
827
850
return true ;
@@ -855,7 +878,8 @@ void ModuleSanitizerCoverage::InjectCoverageForIndirectCalls(
855
878
// {NumCases, ValueSizeInBits, Case0Value, Case1Value, Case2Value, ... })
856
879
857
880
void ModuleSanitizerCoverage::InjectTraceForSwitch (
858
- Function &, ArrayRef<Instruction *> SwitchTraceTargets) {
881
+ Function &F, ArrayRef<Instruction *> SwitchTraceTargets,
882
+ Value *&FunctionGateCmp) {
859
883
for (auto *I : SwitchTraceTargets) {
860
884
if (SwitchInst *SI = dyn_cast<SwitchInst>(I)) {
861
885
InstrumentationIRBuilder IRB (I);
@@ -886,7 +910,13 @@ void ModuleSanitizerCoverage::InjectTraceForSwitch(
886
910
*CurModule, ArrayOfInt64Ty, false , GlobalVariable::InternalLinkage,
887
911
ConstantArray::get (ArrayOfInt64Ty, Initializers),
888
912
" __sancov_gen_cov_switch_values" );
889
- IRB.CreateCall (SanCovTraceSwitchFunction, {Cond, GV});
913
+ if (Options.GatedCallbacks ) {
914
+ auto GateBranch = CreateGateBranch (F, FunctionGateCmp, I);
915
+ IRBuilder<> GateIRB (GateBranch);
916
+ GateIRB.CreateCall (SanCovTraceSwitchFunction, {Cond, GV});
917
+ } else {
918
+ IRB.CreateCall (SanCovTraceSwitchFunction, {Cond, GV});
919
+ }
890
920
}
891
921
}
892
922
}
@@ -950,7 +980,8 @@ void ModuleSanitizerCoverage::InjectTraceForLoadsAndStores(
950
980
}
951
981
952
982
void ModuleSanitizerCoverage::InjectTraceForCmp (
953
- Function &, ArrayRef<Instruction *> CmpTraceTargets) {
983
+ Function &F, ArrayRef<Instruction *> CmpTraceTargets,
984
+ Value *&FunctionGateCmp) {
954
985
for (auto *I : CmpTraceTargets) {
955
986
if (ICmpInst *ICMP = dyn_cast<ICmpInst>(I)) {
956
987
InstrumentationIRBuilder IRB (ICMP);
@@ -978,8 +1009,15 @@ void ModuleSanitizerCoverage::InjectTraceForCmp(
978
1009
}
979
1010
980
1011
auto Ty = Type::getIntNTy (*C, TypeSize);
981
- IRB.CreateCall (CallbackFunc, {IRB.CreateIntCast (A0, Ty, true ),
982
- IRB.CreateIntCast (A1, Ty, true )});
1012
+ if (Options.GatedCallbacks ) {
1013
+ auto GateBranch = CreateGateBranch (F, FunctionGateCmp, I);
1014
+ IRBuilder<> GateIRB (GateBranch);
1015
+ GateIRB.CreateCall (CallbackFunc, {GateIRB.CreateIntCast (A0, Ty, true ),
1016
+ GateIRB.CreateIntCast (A1, Ty, true )});
1017
+ } else {
1018
+ IRB.CreateCall (CallbackFunc, {IRB.CreateIntCast (A0, Ty, true ),
1019
+ IRB.CreateIntCast (A1, Ty, true )});
1020
+ }
983
1021
}
984
1022
}
985
1023
}
@@ -1013,19 +1051,10 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
1013
1051
ConstantInt::get (IntptrTy, Idx * 4 )),
1014
1052
PtrTy);
1015
1053
if (Options.GatedCallbacks ) {
1016
- if (!FunctionGateCmp) {
1017
- // Create this in the entry block
1018
- assert (IsEntryBB);
1019
- FunctionGateCmp = CreateFunctionLocalGateCmp (IRB);
1020
- }
1021
- // Set the branch weights in order to minimize the price paid when the
1022
- // gate is turned off, allowing the default enablement of this
1023
- // instrumentation with as little of a performance cost as possible
1024
- auto Weights = MDBuilder (*C).createBranchWeights (1 , 100000 );
1025
- auto ThenTerm =
1026
- SplitBlockAndInsertIfThen (FunctionGateCmp, &*IP, false , Weights);
1027
- IRBuilder<> ThenIRB (ThenTerm);
1028
- ThenIRB.CreateCall (SanCovTracePCGuard, GuardPtr)->setCannotMerge ();
1054
+ Instruction *I = &*IP;
1055
+ auto GateBranch = CreateGateBranch (F, FunctionGateCmp, I);
1056
+ IRBuilder<> GateIRB (GateBranch);
1057
+ GateIRB.CreateCall (SanCovTracePCGuard, GuardPtr)->setCannotMerge ();
1029
1058
} else {
1030
1059
IRB.CreateCall (SanCovTracePCGuard, GuardPtr)->setCannotMerge ();
1031
1060
}
0 commit comments