2

最近我一直在研究 Clang 消毒剂。我发现标志-fsanitize-coverage可以是trace-pcor trace-pc-guard。根据官方文档(Tracing PCs with guardsTracing PCs ),两者都可以在每个边缘插入存根函数(__sanitizer_cov_trace_pc()和)。__sanitizer_cov_trace_pc_guard()但是,它们之间有什么区别呢?

4

1 回答 1

0

在我看来,这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- 也许只是为了兼容“遗留”代码检测?

于 2021-08-25T08:54:29.267 回答