Frama-c pdg-dot插件生成的PDG dot文件缺失被调用函数的子图信息
看起来你遇到的问题是Frama-C的PDG插件在生成调用子图时的范围限制导致的,我来帮你拆解一下原因和对应的解决办法:
问题根源:PDG的默认分析范围限制
当你用-main function_analyzed指定单个函数进行分析时,Frama-C的PDG插件默认只会聚焦于该目标函数内部的控制流、数据流依赖,以及能被Frama-C成功分析到定义的被调用函数。只有当被调用的函数满足以下条件时,才会在生成的dot文件中创建对应的cluster_Call子图:
- 该函数的定义被传递给了Frama-C(即包含在你指定的源文件中);
- Frama-C成功为该函数生成了PDG节点。
对比你的两个例子就能看出差异:
- 在
xmlNodeDump的例子中,被调用的xmlBufFromBuffer、xmlBufNodeDump等函数的定义应该和xmlNodeDump在同一个文件(xmlslave.c),或者你传递给Frama-C的文件集合包含了这些函数的定义,所以Frama-C能生成它们的调用子图。 - 而在
installDirs的例子中,getString有对应的子图,大概率是因为它的定义就在runsuite.c里;但installResources、composeDir这些函数的定义在你没有传递给Frama-C的其他文件中,导致Frama-C无法获取它们的实现细节,也就没法生成对应的调用子图。
解决办法
根据你的需求,你可以尝试以下几种方案:
1. 传递所有依赖的源文件给Frama-C
确保将定义了installResources、composeDir等被调用函数的源文件也作为参数传给Frama-C,而不仅仅是包含installDirs的runsuite.c。比如修改你的命令:
frama-c -pdg -pdg-dot pdg.dot ./runsuite.c ./path/to/installResources_def.c ./path/to/composeDir_def.c -cpp-command "$gcc_cmd" -main installDirs
这样Frama-C就能分析到这些被调用函数的完整定义,进而为它们生成对应的PDG调用子图。
2. 结合Eva(值分析)启用全程序分析
PDG的生成可以依赖Eva(Frama-C的值分析插件)的全程序分析结果,来更准确地识别跨函数的调用关系和依赖。你可以在命令中加入Eva的相关参数,强制进行全程序分析:
frama-c -eva -pdg -pdg-dot pdg.dot "$file_path" -cpp-command "$gcc_cmd" -main installDirs
如果需要更高精度的分析,还可以加上分析级别参数:
frama-c -eva -analysis-level 3 -pdg -pdg-dot pdg.dot "$file_path" -cpp-command "$gcc_cmd" -main installDirs
注意:针对libxml2这类大型项目,全程序分析可能会消耗更多时间和资源,你可能需要根据实际情况调整Eva的参数(比如启用上下文敏感分析、配置指针处理规则等)来优化结果。
3. 生成全程序完整PDG
如果你希望一次性生成整个项目中所有函数的PDG(包括所有调用关系),可以添加-pdg-full选项,这样Frama-C会跳出单个函数的限制,生成覆盖所有分析到的函数的完整PDG:
frama-c -pdg -pdg-full -pdg-dot pdg.dot ./all_your_source_files -cpp-command "$gcc_cmd" -main installDirs
不过这个选项会生成体积更大的dot文件,可视化时可能需要调整布局工具(比如Graphviz的neato或fdp)来获得更清晰的展示效果。
验证建议
你可以先检查installResources函数的定义所在的文件,把它加入到Frama-C的分析文件列表中,再重新运行命令,应该就能看到对应的cluster_Call子图出现在生成的dot文件里了。
备注:内容来源于stack exchange,提问作者null024

