@@ -86,6 +86,7 @@ const char SanCovPCsSectionName[] = "sancov_pcs";
86
86
const char SanCovCFsSectionName[] = " sancov_cfs" ;
87
87
const char SanCovCallbackGateSectionName[] = " sancov_gate" ;
88
88
89
+ const char SanCovStackDepthCallbackName[] = " __sanitizer_cov_stack_depth" ;
89
90
const char SanCovLowestStackName[] = " __sancov_lowest_stack" ;
90
91
const char SanCovCallbackGateName[] = " __sancov_should_track" ;
91
92
@@ -152,6 +153,12 @@ static cl::opt<bool> ClStackDepth("sanitizer-coverage-stack-depth",
152
153
cl::desc (" max stack depth tracing" ),
153
154
cl::Hidden);
154
155
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
+
155
162
static cl::opt<bool >
156
163
ClCollectCF (" sanitizer-coverage-control-flow" ,
157
164
cl::desc (" collect control flow for each function" ), cl::Hidden);
@@ -202,6 +209,8 @@ SanitizerCoverageOptions OverrideFromCL(SanitizerCoverageOptions Options) {
202
209
Options.PCTable |= ClCreatePCTable;
203
210
Options.NoPrune |= !ClPruneBlocks;
204
211
Options.StackDepth |= ClStackDepth;
212
+ Options.StackDepthCallbackMin = std::max (Options.StackDepthCallbackMin ,
213
+ ClStackDepthCallbackMin.getValue ());
205
214
Options.TraceLoads |= ClLoadTracing;
206
215
Options.TraceStores |= ClStoreTracing;
207
216
Options.GatedCallbacks |= ClGatedCallbacks;
@@ -271,6 +280,7 @@ class ModuleSanitizerCoverage {
271
280
DomTreeCallback DTCallback;
272
281
PostDomTreeCallback PDTCallback;
273
282
283
+ FunctionCallee SanCovStackDepthCallback;
274
284
FunctionCallee SanCovTracePCIndir;
275
285
FunctionCallee SanCovTracePC, SanCovTracePCGuard;
276
286
std::array<FunctionCallee, 4 > SanCovTraceCmpFunction;
@@ -514,6 +524,9 @@ bool ModuleSanitizerCoverage::instrumentModule() {
514
524
SanCovTracePCGuard =
515
525
M.getOrInsertFunction (SanCovTracePCGuardName, VoidTy, PtrTy);
516
526
527
+ SanCovStackDepthCallback =
528
+ M.getOrInsertFunction (SanCovStackDepthCallbackName, VoidTy);
529
+
517
530
for (auto &F : M)
518
531
instrumentFunction (F);
519
532
@@ -1078,22 +1091,65 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
1078
1091
Store->setNoSanitizeMetadata ();
1079
1092
}
1080
1093
if (Options.StackDepth && IsEntryBB && !IsLeafFunc) {
1081
- // Check stack depth. If it's the deepest so far, record it.
1082
1094
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
+ }
1097
1153
}
1098
1154
}
1099
1155
0 commit comments