LLVM/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检查器是功能最丰富的调试工具之一,它通过识别特定的函数调用来提供各种调试功能。
主要功能函数
-
clang_analyzer_eval(bool)
- 功能:评估表达式的确定性
- 输出:TRUE(已知非零)、FALSE(已知为零或null)、UNKNOWN(约束不足)
- 示例:
clang_analyzer_eval(x); // 若x值未知则输出UNKNOWN if (!x) return; clang_analyzer_eval(x); // 输出TRUE
-
clang_analyzer_checkInlined(bool)
- 功能:检查函数是否被内联
- 示例:
int inlined() { clang_analyzer_checkInlined(true); // 输出TRUE return 42; }
-
clang_analyzer_warnIfReached()
- 功能:当分析器到达该代码时生成警告
- 示例:
if (true) { clang_analyzer_warnIfReached(); // 输出REACHABLE }
-
clang_analyzer_warnOnDeadSymbol(int)
- 功能:当符号被垃圾回收时发出警告
- 示例:
do { int x = generate_some_integer(); clang_analyzer_warnOnDeadSymbol(x); } while(0); // 输出SYMBOL DEAD
-
clang_analyzer_explain(any type)
- 功能:以人类可读的方式解释参数值
- 示例:
void clang_analyzer_explain(int); void foo(int param) { clang_analyzer_explain(param); // 输出参数信息 }
-
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是一个特殊检查器,它在每个语句处报告警告,是测试错误报告构建和输出的极佳工具。
使用建议
- 调试复杂分析问题时,建议从
debug.ViewCFG开始,理解程序的基本结构 - 当分析结果不符合预期时,使用
clang_analyzer_eval检查关键点的值 - 内存相关问题可使用
clang_analyzer_warnOnDeadSymbol跟踪符号生命周期 - 性能分析时可结合
debug.Stats和-analyzer-stats获取详细数据
这些调试工具为理解Clang静态分析器的内部工作机制提供了强大支持,是开发和调试自定义分析器的宝贵资源。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



