@@ -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
@@ -1029,6 +1042,8 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
1029
1042
if (IsEntryBB) {
1030
1043
if (auto SP = F.getSubprogram ())
1031
1044
EntryLoc = DILocation::get (SP->getContext (), SP->getScopeLine (), 0 , SP);
1045
+ // FIXME: stack-depth does not correctly instrument dynamic allocas.
1046
+ //
1032
1047
// Keep static allocas and llvm.localescape calls in the entry block. Even
1033
1048
// if we aren't splitting the block, it's nice for allocas to be before
1034
1049
// calls.
@@ -1078,22 +1093,50 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
1078
1093
Store->setNoSanitizeMetadata ();
1079
1094
}
1080
1095
if (Options.StackDepth && IsEntryBB && !IsLeafFunc) {
1081
- // Check stack depth. If it's the deepest so far, record it.
1082
1096
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
+ }
1097
1140
}
1098
1141
}
1099
1142
0 commit comments