LLVM/Clang静态分析器中的调试检查器详解

LLVM/Clang静态分析器中的调试检查器详解

【免费下载链接】clang Mirror kept for legacy. Moved to https://github.com/llvm/llvm-project 【免费下载链接】clang 项目地址: https://gitcode.com/gh_mirrors/cl/clang

概述

LLVM/Clang静态分析器是一个强大的源代码分析工具,它能够在编译时检测程序中的潜在错误。为了帮助开发者理解和调试分析器的行为,Clang提供了一系列特殊的调试检查器。这些检查器不会检测常规代码问题,而是专门用于输出分析过程中的内部信息。

调试检查器的启用方式

要使用这些调试检查器,需要在编译命令中添加-analyzer-checker=参数,后跟检查器名称。例如:

clang -cc1 -analyze -analyzer-checker=debug.DumpCFG test.c

主要调试检查器分类

1. 通用分析转储器

这类检查器用于转储各种基础设施分析的结果到标准错误输出(stderr)。部分检查器还提供"view"变体,能够以图形化方式展示结果。

  • debug.DumpCallGraph/debug.ViewCallGraph:显示当前翻译单元生成的调用图,用于确定函数内联时的分析顺序
  • debug.DumpCFG/debug.ViewCFG:显示每个顶层函数的控制流图(CFG)
  • debug.DumpDominators:显示每个顶层函数CFG的支配树
  • debug.DumpLiveVars:显示每个顶层函数的活跃变量分析结果
  • debug.DumpLiveStmts:显示每个顶层函数的活跃语句分析结果
  • debug.ViewExplodedGraph:显示为输入翻译单元中不同函数分析生成的爆炸图(Exploded Graphs)

注意:爆炸图可能会变得非常大,即使是分析小型函数时也是如此。

2. 路径追踪检查器

这些检查器打印分析引擎所采取路径的相关信息。

  • debug.DumpCalls:打印路径遍历过程中遇到的每个函数或方法调用,通过缩进显示调用栈
  • debug.DumpTraversal:打印路径遍历过程中遇到的分支语句名称("IfStmt"、"WhileStmt"等),用于检查分析引擎是使用BFS还是DFS

3. 状态检查检查器

这些检查器以分析警告的形式打印分析器状态信息,主要用于回归测试中的验证功能。

  • debug.TaintTest:为每个带有污点的表达式打印"tainted"字样
  • debug.ExprInspection:响应特定的函数调用,这些调用模拟内置函数的行为

ExprInspection检查器详解

debug.ExprInspection检查器是功能最丰富的调试工具之一,它通过识别特定的函数调用来提供各种调试功能。

主要功能函数

  1. clang_analyzer_eval(bool)

    • 功能:评估表达式的确定性
    • 输出:TRUE(已知非零)、FALSE(已知为零或null)、UNKNOWN(约束不足)
    • 示例:
      clang_analyzer_eval(x); // 若x值未知则输出UNKNOWN
      if (!x) return;
      clang_analyzer_eval(x); // 输出TRUE
      
  2. clang_analyzer_checkInlined(bool)

    • 功能:检查函数是否被内联
    • 示例:
      int inlined() {
        clang_analyzer_checkInlined(true); // 输出TRUE
        return 42;
      }
      
  3. clang_analyzer_warnIfReached()

    • 功能:当分析器到达该代码时生成警告
    • 示例:
      if (true) {
        clang_analyzer_warnIfReached();  // 输出REACHABLE
      }
      
  4. clang_analyzer_warnOnDeadSymbol(int)

    • 功能:当符号被垃圾回收时发出警告
    • 示例:
      do {
        int x = generate_some_integer();
        clang_analyzer_warnOnDeadSymbol(x);
      } while(0);  // 输出SYMBOL DEAD
      
  5. clang_analyzer_explain(any type)

    • 功能:以人类可读的方式解释参数值
    • 示例:
      void clang_analyzer_explain(int);
      void foo(int param) {
        clang_analyzer_explain(param); // 输出参数信息
      }
      
  6. clang_analyzer_printState()

    • 功能:将当前程序状态转储到stderr
    • 特点:不生成警告,直接输出到控制台

其他实用函数

  • clang_analyzer_dump():原始值转储
  • clang_analyzer_getExtent():获取内存区域大小
  • clang_analyzer_hashDump():生成报告哈希
  • clang_analyzer_denote()/clang_analyzer_express():符号标记和表达式

统计检查器

debug.Stats检查器收集每个函数分析的各种信息,如到达的块数和分析是否超时。

此外,-analyzer-stats标志可以启用分析器引擎内部的各种统计信息。需要注意的是,Stats检查器可能会改变-analyzer-stats报告的值。

输出测试检查器

debug.ReportStmts是一个特殊检查器,它在每个语句处报告警告,是测试错误报告构建和输出的极佳工具。

使用建议

  1. 调试复杂分析问题时,建议从debug.ViewCFG开始,理解程序的基本结构
  2. 当分析结果不符合预期时,使用clang_analyzer_eval检查关键点的值
  3. 内存相关问题可使用clang_analyzer_warnOnDeadSymbol跟踪符号生命周期
  4. 性能分析时可结合debug.Stats-analyzer-stats获取详细数据

这些调试工具为理解Clang静态分析器的内部工作机制提供了强大支持,是开发和调试自定义分析器的宝贵资源。

【免费下载链接】clang Mirror kept for legacy. Moved to https://github.com/llvm/llvm-project 【免费下载链接】clang 项目地址: https://gitcode.com/gh_mirrors/cl/clang

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值