【问题标题】:What is the difference between -fsanitize-coverage=trace-pc and trace-pc-guard?-fsanitize-coverage=trace-pc 和 trace-pc-guard 有什么区别?
【发布时间】:2021-10-21 23:16:20
【问题描述】:
最近我一直在研究 Clang 消毒剂。我发现标志-fsanitize-coverage 可以是trace-pc 或trace-pc-guard。根据官方文档(Tracing PCs with guards,Tracing PCs),两者都可以在每个边缘插入存根函数(__sanitizer_cov_trace_pc() 和__sanitizer_cov_trace_pc_guard())。但是,它们有什么区别呢?
【问题讨论】:
标签:
clang
llvm
fuzzing
sanitizer
【解决方案1】:
在我看来trace-pc-guard 只是trace-pc 的更新替代品。而trace-pc 回调在没有进一步信息的情况下被调用,trace-pc-guard 接收唯一标识当前函数/基本块/边缘的保护值,反映在它们的签名中,并可用于禁用对相应调用者的跟踪(通过设置 *guard=0):
如果您查看检测的源代码,您会发现保护变量的传递似乎是它们唯一的区别:
// llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
void ModuleSanitizerCoverage::InjectCoverageAtBlock(
Function &F,
BasicBlock &BB,
size_t Idx,
bool IsLeafFunc) {
/* ... */
if (Options.TracePC) {
IRB.CreateCall(SanCovTracePC)
->setCannotMerge(); // gets the PC using GET_CALLER_PC.
}
if (Options.TracePCGuard) {
auto GuardPtr = IRB.CreateIntToPtr(
IRB.CreateAdd(IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
ConstantInt::get(IntptrTy, Idx * 4)),
Int32PtrTy);
IRB.CreateCall(SanCovTracePCGuard, GuardPtr)->setCannotMerge();
}
/* ... */
}
引入选项的提交也添加了一些解释:
不幸的是,我不知道为什么 trace-pc 用于内核模糊测试(如 CoverageSanitizer 文档所述)而不是 trace-pc-guard - 也许只是为了兼容“遗留”代码检测?