@@ -159,8 +159,8 @@ static cl::opt<bool>
159159
160160static cl::opt<bool > ClGatedCallbacks (
161161 " 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 ." ),
164164 cl::Hidden, cl::init(false ));
165165
166166namespace {
@@ -235,22 +235,26 @@ class ModuleSanitizerCoverage {
235235 void instrumentFunction (Function &F);
236236 void InjectCoverageForIndirectCalls (Function &F,
237237 ArrayRef<Instruction *> IndirCalls);
238- void InjectTraceForCmp (Function &F, ArrayRef<Instruction *> CmpTraceTargets);
238+ void InjectTraceForCmp (Function &F, ArrayRef<Instruction *> CmpTraceTargets,
239+ Value *&FunctionGateCmp);
239240 void InjectTraceForDiv (Function &F,
240241 ArrayRef<BinaryOperator *> DivTraceTargets);
241242 void InjectTraceForGep (Function &F,
242243 ArrayRef<GetElementPtrInst *> GepTraceTargets);
243244 void InjectTraceForLoadsAndStores (Function &F, ArrayRef<LoadInst *> Loads,
244245 ArrayRef<StoreInst *> Stores);
245246 void InjectTraceForSwitch (Function &F,
246- ArrayRef<Instruction *> SwitchTraceTargets);
247+ ArrayRef<Instruction *> SwitchTraceTargets,
248+ Value *&FunctionGateCmp);
247249 bool InjectCoverage (Function &F, ArrayRef<BasicBlock *> AllBlocks,
248- bool IsLeafFunc = true );
250+ Value *&FunctionGateCmp, bool IsLeafFunc = true );
249251 GlobalVariable *CreateFunctionLocalArrayInSection (size_t NumElements,
250252 Function &F, Type *Ty,
251253 const char *Section);
252254 GlobalVariable *CreatePCArray (Function &F, ArrayRef<BasicBlock *> AllBlocks);
253255 void CreateFunctionLocalArrays (Function &F, ArrayRef<BasicBlock *> AllBlocks);
256+ Instruction *CreateGateBranch (Function &F, Value *&FunctionGateCmp,
257+ Instruction *I);
254258 Value *CreateFunctionLocalGateCmp (IRBuilder<> &IRB);
255259 void InjectCoverageAtBlock (Function &F, BasicBlock &BB, size_t Idx,
256260 Value *&FunctionGateCmp, bool IsLeafFunc = true );
@@ -493,9 +497,9 @@ bool ModuleSanitizerCoverage::instrumentModule() {
493497 SanCovLowestStack->setInitializer (Constant::getAllOnesValue (IntptrTy));
494498
495499 if (Options.GatedCallbacks ) {
496- if (!Options.TracePCGuard ) {
500+ if (!Options.TracePCGuard && !Options. TraceCmp ) {
497501 C->emitError (StringRef (" '" ) + ClGatedCallbacks.ArgStr +
498- " ' is only supported with trace-pc-guard" );
502+ " ' is only supported with trace-pc-guard or trace-cmp " );
499503 return true ;
500504 }
501505
@@ -724,10 +728,11 @@ void ModuleSanitizerCoverage::instrumentFunction(Function &F) {
724728 if (Options.CollectControlFlow )
725729 createFunctionControlFlow (F);
726730
727- InjectCoverage (F, BlocksToInstrument, IsLeafFunc);
731+ Value *FunctionGateCmp = nullptr ;
732+ InjectCoverage (F, BlocksToInstrument, FunctionGateCmp, IsLeafFunc);
728733 InjectCoverageForIndirectCalls (F, IndirCalls);
729- InjectTraceForCmp (F, CmpTraceTargets);
730- InjectTraceForSwitch (F, SwitchTraceTargets);
734+ InjectTraceForCmp (F, CmpTraceTargets, FunctionGateCmp );
735+ InjectTraceForSwitch (F, SwitchTraceTargets, FunctionGateCmp );
731736 InjectTraceForDiv (F, DivTraceTargets);
732737 InjectTraceForGep (F, GepTraceTargets);
733738 InjectTraceForLoadsAndStores (F, Loads, Stores);
@@ -816,12 +821,30 @@ Value *ModuleSanitizerCoverage::CreateFunctionLocalGateCmp(IRBuilder<> &IRB) {
816821 return Cmp;
817822}
818823
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+
819842bool ModuleSanitizerCoverage::InjectCoverage (Function &F,
820843 ArrayRef<BasicBlock *> AllBlocks,
844+ Value *&FunctionGateCmp,
821845 bool IsLeafFunc) {
822846 if (AllBlocks.empty ()) return false ;
823847 CreateFunctionLocalArrays (F, AllBlocks);
824- Value *FunctionGateCmp = nullptr ;
825848 for (size_t i = 0 , N = AllBlocks.size (); i < N; i++)
826849 InjectCoverageAtBlock (F, *AllBlocks[i], i, FunctionGateCmp, IsLeafFunc);
827850 return true ;
@@ -855,7 +878,8 @@ void ModuleSanitizerCoverage::InjectCoverageForIndirectCalls(
855878// {NumCases, ValueSizeInBits, Case0Value, Case1Value, Case2Value, ... })
856879
857880void ModuleSanitizerCoverage::InjectTraceForSwitch (
858- Function &, ArrayRef<Instruction *> SwitchTraceTargets) {
881+ Function &F, ArrayRef<Instruction *> SwitchTraceTargets,
882+ Value *&FunctionGateCmp) {
859883 for (auto *I : SwitchTraceTargets) {
860884 if (SwitchInst *SI = dyn_cast<SwitchInst>(I)) {
861885 InstrumentationIRBuilder IRB (I);
@@ -886,7 +910,13 @@ void ModuleSanitizerCoverage::InjectTraceForSwitch(
886910 *CurModule, ArrayOfInt64Ty, false , GlobalVariable::InternalLinkage,
887911 ConstantArray::get (ArrayOfInt64Ty, Initializers),
888912 " __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+ }
890920 }
891921 }
892922}
@@ -950,7 +980,8 @@ void ModuleSanitizerCoverage::InjectTraceForLoadsAndStores(
950980}
951981
952982void ModuleSanitizerCoverage::InjectTraceForCmp (
953- Function &, ArrayRef<Instruction *> CmpTraceTargets) {
983+ Function &F, ArrayRef<Instruction *> CmpTraceTargets,
984+ Value *&FunctionGateCmp) {
954985 for (auto *I : CmpTraceTargets) {
955986 if (ICmpInst *ICMP = dyn_cast<ICmpInst>(I)) {
956987 InstrumentationIRBuilder IRB (ICMP);
@@ -978,8 +1009,15 @@ void ModuleSanitizerCoverage::InjectTraceForCmp(
9781009 }
9791010
9801011 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+ }
9831021 }
9841022 }
9851023}
@@ -1013,19 +1051,10 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
10131051 ConstantInt::get (IntptrTy, Idx * 4 )),
10141052 PtrTy);
10151053 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 ();
10291058 } else {
10301059 IRB.CreateCall (SanCovTracePCGuard, GuardPtr)->setCannotMerge ();
10311060 }
0 commit comments