@@ -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
@@ -1078,22 +1091,65 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
10781091 Store->setNoSanitizeMetadata ();
10791092 }
10801093 if (Options.StackDepth && IsEntryBB && !IsLeafFunc) {
1081- // Check stack depth. If it's the deepest so far, record it.
10821094 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 ();
1095+ const DataLayout &DL = M->getDataLayout ();
1096+
1097+ if (Options.StackDepthCallbackMin ) {
1098+ // In callback mode, only add call when stack depth reaches minimum.
1099+ uint32_t EstimatedStackSize = 0 ;
1100+ // If dynamic alloca found, always add call.
1101+ bool HasDynamicAlloc = false ;
1102+ // Find an insertion point after last "alloca".
1103+ llvm::Instruction *InsertBefore = nullptr ;
1104+
1105+ // Examine all allocas in the basic block. since we're too early
1106+ // to have results from Intrinsic::frameaddress, we have to manually
1107+ // estimate the stack size.
1108+ for (auto &I : BB) {
1109+ if (auto *AI = dyn_cast<AllocaInst>(&I)) {
1110+ // Move potential insertion point past the "alloca".
1111+ InsertBefore = AI->getNextNode ();
1112+
1113+ // Make an estimate on the stack usage.
1114+ if (AI->isStaticAlloca ()) {
1115+ uint32_t Bytes = DL.getTypeAllocSize (AI->getAllocatedType ());
1116+ if (AI->isArrayAllocation ()) {
1117+ if (const ConstantInt *arraySize =
1118+ dyn_cast<ConstantInt>(AI->getArraySize ())) {
1119+ Bytes *= arraySize->getZExtValue ();
1120+ } else {
1121+ HasDynamicAlloc = true ;
1122+ }
1123+ }
1124+ EstimatedStackSize += Bytes;
1125+ } else {
1126+ HasDynamicAlloc = true ;
1127+ }
1128+ }
1129+ }
1130+
1131+ if (HasDynamicAlloc ||
1132+ EstimatedStackSize >= Options.StackDepthCallbackMin ) {
1133+ if (InsertBefore)
1134+ IRB.SetInsertPoint (InsertBefore);
1135+ IRB.CreateCall (SanCovStackDepthCallback)->setCannotMerge ();
1136+ }
1137+ } else {
1138+ // Check stack depth. If it's the deepest so far, record it.
1139+ auto FrameAddrPtr = IRB.CreateIntrinsic (
1140+ Intrinsic::frameaddress, IRB.getPtrTy (DL.getAllocaAddrSpace ()),
1141+ {Constant::getNullValue (Int32Ty)});
1142+ auto FrameAddrInt = IRB.CreatePtrToInt (FrameAddrPtr, IntptrTy);
1143+ auto LowestStack = IRB.CreateLoad (IntptrTy, SanCovLowestStack);
1144+ auto IsStackLower = IRB.CreateICmpULT (FrameAddrInt, LowestStack);
1145+ auto ThenTerm = SplitBlockAndInsertIfThen (
1146+ IsStackLower, &*IP, false ,
1147+ MDBuilder (IRB.getContext ()).createUnlikelyBranchWeights ());
1148+ IRBuilder<> ThenIRB (ThenTerm);
1149+ auto Store = ThenIRB.CreateStore (FrameAddrInt, SanCovLowestStack);
1150+ LowestStack->setNoSanitizeMetadata ();
1151+ Store->setNoSanitizeMetadata ();
1152+ }
10971153 }
10981154}
10991155
0 commit comments