最近我一直在研究 Clang 消毒剂。我发现标志-fsanitize-coverage
可以是trace-pc
or trace-pc-guard
。根据官方文档(Tracing PCs with guards,Tracing PCs ),两者都可以在每个边缘插入存根函数(__sanitizer_cov_trace_pc()
和)。__sanitizer_cov_trace_pc_guard()
但是,它们之间有什么区别呢?
1 回答
在我看来,这trace-pc-guard
只是trace-pc
. 虽然trace-pc
回调在没有进一步信息的情况下被调用,但trace-pc-guard
接收到唯一标识当前函数/基本块/边缘的保护值,这反映在它们的签名中,并且可用于禁用对各个调用者的跟踪(通过设置 *guard=0) :
void __sanitizer_cov_trace_pc();
void __sanitizer_cov_trace_pc_guard(uint32_t *guard);
如果您查看检测的源代码,您会发现保护变量的传递似乎是它们唯一的区别:
// 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();
}
/* ... */
}
引入选项的提交也添加了一些解释:
-fsanitize-coverage=trace-pc
d4590c7304575(2016 年 2 月 17 日星期三 21:34:43 +0000)
[sanitizer-coverage] 实施 -fsanitize-coverage=trace-pc。这类似于 trace-bb,但有不同的 API。我们已经在 GCC 中使用了等效的标志来进行 Linux 内核模糊测试。我们也可以在 AFL 中使用这个标志
-fsanitize-coverage=trace-pc-guard
da718e55cf0bd(2016 年 9 月 14 日星期三 01:39:35 +0000)
[sanitizer-coverage] 添加另一种覆盖工具:trace-pc-guard。目的是最终用这个替换所有 {bool coverage, 8bit-counters, trace-pc}。
不幸的是,我不知道为什么trace-pc
将其用于内核模糊测试(如 CoverageSanitizer 文档所述)而不是trace-pc-guard
- 也许只是为了兼容“遗留”代码检测?