|
33 | 33 | #include "llvm/Support/CommandLine.h"
|
34 | 34 | #include "llvm/Support/SpecialCaseList.h"
|
35 | 35 | #include "llvm/Support/VirtualFileSystem.h"
|
| 36 | +#include "llvm/Support/raw_ostream.h" |
36 | 37 | #include "llvm/TargetParser/Triple.h"
|
37 | 38 | #include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
38 | 39 | #include "llvm/Transforms/Utils/ModuleUtils.h"
|
@@ -86,6 +87,7 @@ const char SanCovPCsSectionName[] = "sancov_pcs";
|
86 | 87 | const char SanCovCFsSectionName[] = "sancov_cfs";
|
87 | 88 | const char SanCovCallbackGateSectionName[] = "sancov_gate";
|
88 | 89 |
|
| 90 | +const char SanCovStackDepthCallbackName[] = "__sanitizer_cov_stack_depth"; |
89 | 91 | const char SanCovLowestStackName[] = "__sancov_lowest_stack";
|
90 | 92 | const char SanCovCallbackGateName[] = "__sancov_should_track";
|
91 | 93 |
|
@@ -152,6 +154,12 @@ static cl::opt<bool> ClStackDepth("sanitizer-coverage-stack-depth",
|
152 | 154 | cl::desc("max stack depth tracing"),
|
153 | 155 | cl::Hidden);
|
154 | 156 |
|
| 157 | +static cl::opt<int> ClStackDepthCallbackMin( |
| 158 | + "sanitizer-coverage-stack-depth-callback-min", |
| 159 | + cl::desc("max stack depth tracing should use callback and only when " |
| 160 | + "stack depth more than specified"), |
| 161 | + cl::Hidden); |
| 162 | + |
155 | 163 | static cl::opt<bool>
|
156 | 164 | ClCollectCF("sanitizer-coverage-control-flow",
|
157 | 165 | cl::desc("collect control flow for each function"), cl::Hidden);
|
@@ -202,6 +210,8 @@ SanitizerCoverageOptions OverrideFromCL(SanitizerCoverageOptions Options) {
|
202 | 210 | Options.PCTable |= ClCreatePCTable;
|
203 | 211 | Options.NoPrune |= !ClPruneBlocks;
|
204 | 212 | Options.StackDepth |= ClStackDepth;
|
| 213 | + Options.StackDepthCallbackMin = std::max(Options.StackDepthCallbackMin, |
| 214 | + ClStackDepthCallbackMin.getValue()); |
205 | 215 | Options.TraceLoads |= ClLoadTracing;
|
206 | 216 | Options.TraceStores |= ClStoreTracing;
|
207 | 217 | Options.GatedCallbacks |= ClGatedCallbacks;
|
@@ -271,6 +281,7 @@ class ModuleSanitizerCoverage {
|
271 | 281 | DomTreeCallback DTCallback;
|
272 | 282 | PostDomTreeCallback PDTCallback;
|
273 | 283 |
|
| 284 | + FunctionCallee SanCovStackDepthCallback; |
274 | 285 | FunctionCallee SanCovTracePCIndir;
|
275 | 286 | FunctionCallee SanCovTracePC, SanCovTracePCGuard;
|
276 | 287 | std::array<FunctionCallee, 4> SanCovTraceCmpFunction;
|
@@ -514,6 +525,9 @@ bool ModuleSanitizerCoverage::instrumentModule() {
|
514 | 525 | SanCovTracePCGuard =
|
515 | 526 | M.getOrInsertFunction(SanCovTracePCGuardName, VoidTy, PtrTy);
|
516 | 527 |
|
| 528 | + SanCovStackDepthCallback = |
| 529 | + M.getOrInsertFunction(SanCovStackDepthCallbackName, VoidTy); |
| 530 | + |
517 | 531 | for (auto &F : M)
|
518 | 532 | instrumentFunction(F);
|
519 | 533 |
|
@@ -1029,6 +1043,8 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
|
1029 | 1043 | if (IsEntryBB) {
|
1030 | 1044 | if (auto SP = F.getSubprogram())
|
1031 | 1045 | EntryLoc = DILocation::get(SP->getContext(), SP->getScopeLine(), 0, SP);
|
| 1046 | + // FIXME: stack-depth does not correctly instrument dynamic allocas. |
| 1047 | + // |
1032 | 1048 | // Keep static allocas and llvm.localescape calls in the entry block. Even
|
1033 | 1049 | // if we aren't splitting the block, it's nice for allocas to be before
|
1034 | 1050 | // calls.
|
@@ -1078,22 +1094,50 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
|
1078 | 1094 | Store->setNoSanitizeMetadata();
|
1079 | 1095 | }
|
1080 | 1096 | if (Options.StackDepth && IsEntryBB && !IsLeafFunc) {
|
1081 |
| - // Check stack depth. If it's the deepest so far, record it. |
1082 | 1097 | 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(); |
| 1098 | + if (Options.StackDepthCallbackMin) { |
| 1099 | + // In callback mode, only add call when stack depth reaches minimum. |
| 1100 | + const DataLayout &DL = M->getDataLayout(); |
| 1101 | + uint32_t EstimatedStackSize = 0; |
| 1102 | + |
| 1103 | + // Make an estimate on the stack usage. |
| 1104 | + for (auto &I : F.getEntryBlock()) { |
| 1105 | + if (auto *AI = dyn_cast<AllocaInst>(&I)) { |
| 1106 | + if (AI->isStaticAlloca()) { |
| 1107 | + uint32_t Bytes = DL.getTypeAllocSize(AI->getAllocatedType()); |
| 1108 | + if (AI->isArrayAllocation()) { |
| 1109 | + if (const ConstantInt *arraySize = |
| 1110 | + dyn_cast<ConstantInt>(AI->getArraySize())) |
| 1111 | + Bytes *= arraySize->getZExtValue(); |
| 1112 | + } |
| 1113 | + EstimatedStackSize += Bytes; |
| 1114 | + } else { |
| 1115 | + // Dynamic alloca: require we always perform callback. |
| 1116 | + EstimatedStackSize = Options.StackDepthCallbackMin; |
| 1117 | + break; |
| 1118 | + } |
| 1119 | + } |
| 1120 | + } |
| 1121 | + |
| 1122 | + if (EstimatedStackSize >= Options.StackDepthCallbackMin) |
| 1123 | + IRB.CreateCall(SanCovStackDepthCallback)->setCannotMerge(); |
| 1124 | + } else { |
| 1125 | + // Check stack depth. If it's the deepest so far, record it. |
| 1126 | + auto FrameAddrPtr = IRB.CreateIntrinsic( |
| 1127 | + Intrinsic::frameaddress, |
| 1128 | + IRB.getPtrTy(M->getDataLayout().getAllocaAddrSpace()), |
| 1129 | + {Constant::getNullValue(Int32Ty)}); |
| 1130 | + auto FrameAddrInt = IRB.CreatePtrToInt(FrameAddrPtr, IntptrTy); |
| 1131 | + auto LowestStack = IRB.CreateLoad(IntptrTy, SanCovLowestStack); |
| 1132 | + auto IsStackLower = IRB.CreateICmpULT(FrameAddrInt, LowestStack); |
| 1133 | + auto ThenTerm = SplitBlockAndInsertIfThen( |
| 1134 | + IsStackLower, &*IP, false, |
| 1135 | + MDBuilder(IRB.getContext()).createUnlikelyBranchWeights()); |
| 1136 | + IRBuilder<> ThenIRB(ThenTerm); |
| 1137 | + auto Store = ThenIRB.CreateStore(FrameAddrInt, SanCovLowestStack); |
| 1138 | + LowestStack->setNoSanitizeMetadata(); |
| 1139 | + Store->setNoSanitizeMetadata(); |
| 1140 | + } |
1097 | 1141 | }
|
1098 | 1142 | }
|
1099 | 1143 |
|
|
0 commit comments