@@ -86,6 +86,7 @@ const char SanCovPCsSectionName[] = "sancov_pcs";
8686const char SanCovCFsSectionName[] = " sancov_cfs" ;
8787const char SanCovCallbackGateSectionName[] = " sancov_gate" ;
8888
89+ const char SanCovStackDepthCallbackName[] = " __sanitizer_cov_stack_depth" ;
8990const char SanCovLowestStackName[] = " __sancov_lowest_stack" ;
9091const char SanCovCallbackGateName[] = " __sancov_should_track" ;
9192
@@ -152,6 +153,12 @@ static cl::opt<bool> ClStackDepth("sanitizer-coverage-stack-depth",
152153 cl::desc (" max stack depth tracing" ),
153154 cl::Hidden);
154155
156+ static cl::opt<int > ClStackDepthCallbackMin (
157+ " sanitizer-coverage-stack-depth-callback-min" ,
158+ cl::desc (" max stack depth tracing should use callback and only when "
159+ " stack depth more than specified" ),
160+ cl::Hidden);
161+
155162static cl::opt<bool >
156163 ClCollectCF (" sanitizer-coverage-control-flow" ,
157164 cl::desc (" collect control flow for each function" ), cl::Hidden);
@@ -202,6 +209,8 @@ SanitizerCoverageOptions OverrideFromCL(SanitizerCoverageOptions Options) {
202209 Options.PCTable |= ClCreatePCTable;
203210 Options.NoPrune |= !ClPruneBlocks;
204211 Options.StackDepth |= ClStackDepth;
212+ Options.StackDepthCallbackMin = std::max (Options.StackDepthCallbackMin ,
213+ ClStackDepthCallbackMin.getValue ());
205214 Options.TraceLoads |= ClLoadTracing;
206215 Options.TraceStores |= ClStoreTracing;
207216 Options.GatedCallbacks |= ClGatedCallbacks;
@@ -271,6 +280,7 @@ class ModuleSanitizerCoverage {
271280 DomTreeCallback DTCallback;
272281 PostDomTreeCallback PDTCallback;
273282
283+ FunctionCallee SanCovStackDepthCallback;
274284 FunctionCallee SanCovTracePCIndir;
275285 FunctionCallee SanCovTracePC, SanCovTracePCGuard;
276286 std::array<FunctionCallee, 4 > SanCovTraceCmpFunction;
@@ -514,6 +524,9 @@ bool ModuleSanitizerCoverage::instrumentModule() {
514524 SanCovTracePCGuard =
515525 M.getOrInsertFunction (SanCovTracePCGuardName, VoidTy, PtrTy);
516526
527+ SanCovStackDepthCallback =
528+ M.getOrInsertFunction (SanCovStackDepthCallbackName, VoidTy);
529+
517530 for (auto &F : M)
518531 instrumentFunction (F);
519532
@@ -1029,6 +1042,8 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
10291042 if (IsEntryBB) {
10301043 if (auto SP = F.getSubprogram ())
10311044 EntryLoc = DILocation::get (SP->getContext (), SP->getScopeLine (), 0 , SP);
1045+ // FIXME: stack-depth does not correctly instrument dynamic allocas.
1046+ //
10321047 // Keep static allocas and llvm.localescape calls in the entry block. Even
10331048 // if we aren't splitting the block, it's nice for allocas to be before
10341049 // calls.
@@ -1078,22 +1093,50 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
10781093 Store->setNoSanitizeMetadata ();
10791094 }
10801095 if (Options.StackDepth && IsEntryBB && !IsLeafFunc) {
1081- // Check stack depth. If it's the deepest so far, record it.
10821096 Module *M = F.getParent ();
1083- auto FrameAddrPtr = IRB.CreateIntrinsic (
1084- Intrinsic::frameaddress,
1085- IRB.getPtrTy (M->getDataLayout ().getAllocaAddrSpace ()),
1086- {Constant::getNullValue (Int32Ty)});
1087- auto FrameAddrInt = IRB.CreatePtrToInt (FrameAddrPtr, IntptrTy);
1088- auto LowestStack = IRB.CreateLoad (IntptrTy, SanCovLowestStack);
1089- auto IsStackLower = IRB.CreateICmpULT (FrameAddrInt, LowestStack);
1090- auto ThenTerm = SplitBlockAndInsertIfThen (
1091- IsStackLower, &*IP, false ,
1092- MDBuilder (IRB.getContext ()).createUnlikelyBranchWeights ());
1093- IRBuilder<> ThenIRB (ThenTerm);
1094- auto Store = ThenIRB.CreateStore (FrameAddrInt, SanCovLowestStack);
1095- LowestStack->setNoSanitizeMetadata ();
1096- Store->setNoSanitizeMetadata ();
1097+ if (Options.StackDepthCallbackMin ) {
1098+ // In callback mode, only add call when stack depth reaches minimum.
1099+ const DataLayout &DL = M->getDataLayout ();
1100+ uint32_t EstimatedStackSize = 0 ;
1101+
1102+ // Make an estimate on the stack usage.
1103+ for (auto &I : BB) {
1104+ if (auto *AI = dyn_cast<AllocaInst>(&I)) {
1105+ if (AI->isStaticAlloca ()) {
1106+ uint32_t Bytes = DL.getTypeAllocSize (AI->getAllocatedType ());
1107+ if (AI->isArrayAllocation ()) {
1108+ if (const ConstantInt *arraySize =
1109+ dyn_cast<ConstantInt>(AI->getArraySize ()))
1110+ Bytes *= arraySize->getZExtValue ();
1111+ }
1112+ EstimatedStackSize += Bytes;
1113+ } else {
1114+ // Dynamic alloca: require we always perform callback.
1115+ EstimatedStackSize = Options.StackDepthCallbackMin ;
1116+ break ;
1117+ }
1118+ }
1119+ }
1120+
1121+ if (EstimatedStackSize >= Options.StackDepthCallbackMin )
1122+ IRB.CreateCall (SanCovStackDepthCallback)->setCannotMerge ();
1123+ } else {
1124+ // Check stack depth. If it's the deepest so far, record it.
1125+ auto FrameAddrPtr = IRB.CreateIntrinsic (
1126+ Intrinsic::frameaddress,
1127+ IRB.getPtrTy (M->getDataLayout ().getAllocaAddrSpace ()),
1128+ {Constant::getNullValue (Int32Ty)});
1129+ auto FrameAddrInt = IRB.CreatePtrToInt (FrameAddrPtr, IntptrTy);
1130+ auto LowestStack = IRB.CreateLoad (IntptrTy, SanCovLowestStack);
1131+ auto IsStackLower = IRB.CreateICmpULT (FrameAddrInt, LowestStack);
1132+ auto ThenTerm = SplitBlockAndInsertIfThen (
1133+ IsStackLower, &*IP, false ,
1134+ MDBuilder (IRB.getContext ()).createUnlikelyBranchWeights ());
1135+ IRBuilder<> ThenIRB (ThenTerm);
1136+ auto Store = ThenIRB.CreateStore (FrameAddrInt, SanCovLowestStack);
1137+ LowestStack->setNoSanitizeMetadata ();
1138+ Store->setNoSanitizeMetadata ();
1139+ }
10971140 }
10981141}
10991142
0 commit comments