我正在尝试生成调用图,用它来找出所有可能执行特定函数的路径(这样我就不必手动找出所有路径,因为有很多路径导致这个功能)。例如:
path 1: A -> B -> C -> D
path 2: A -> B -> X -> Y -> D
path 3: A -> G -> M -> N -> O -> P -> S -> D
...
path n: ...
我已经尝试过 Codeviz 和 Doxygen,不知何故,这两个结果只显示目标函数 D 的调用者。在我的例子中,D 是一个类的成员函数,该类的对象将被包裹在一个智能指针中。客户端将始终通过工厂获取智能指针对象以调用 D.
有谁知道如何做到这一点?
static void D() { }
static void Y() { D(); }
static void X() { Y(); }
static void C() { D(); X(); }
static void B() { C(); }
static void S() { D(); }
static void P() { S(); }
static void O() { P(); }
static void N() { O(); }
static void M() { N(); }
static void G() { M(); }
static void A() { B(); G(); }
int main() {
A();
}
然后
$ clang++ -S -emit-llvm main1.cpp -o - | opt -analyze -dot-callgraph
$ dot -Tpng -ocallgraph.png callgraph.dot
产生一些闪亮的图片(有一个“外部节点”,因为
main
具有外部链接,也可能从该翻译单元外部调用):
您可能希望使用
c++filt
对其进行后处理,以便您可以获得所涉及的函数和类的完整名称。就像在下面
#include <vector>
struct A {
A(int);
void f(); // not defined, prevents inlining it!
};
int main() {
std::vector<A> v;
v.push_back(42);
v[0].f();
}
$ clang++ -S -emit-llvm main1.cpp -o - |
opt -analyze -std-link-opts -dot-callgraph
$ cat callgraph.dot |
c++filt |
sed 's,>,\\>,g; s,-\\>,->,g; s,<,\\<,g' |
gawk '/external node/{id=$1} $1 != id' |
dot -Tpng -ocallgraph.png
产生这种美丽(天哪,没有打开优化的尺寸太大了!)
那个神秘的未命名函数
Node0x884c4e0
是一个占位符,假定由任何定义未知的函数调用。
静态计算准确的 C++ 调用图很困难,因为您需要一个精确的语言解析器、正确的名称查找以及一个能够正确遵循语言语义的良好指向分析器。 Doxygen 没有这些,我不知道为什么人们声称喜欢 C++;构造一个 Doxygen 错误分析的 10 行 C++ 示例很容易)。
你可能最好运行一个 时序分析器动态收集调用图(这描述了我们的)并简单地练习了很多案例。这样的分析器将向您展示实际调用图。
编辑:突然想起Understand for C++,它号称构造调用图。我不知道他们使用什么解析器,或者他们是否正确地进行了详细分析;我对他们的产品没有什么具体经验。我的几次遭遇表明它不做指向分析。
我对 Schaub 使用 Clang 的回答印象深刻;我希望 Clang 拥有正确的所有元素。
为了让
clang++
命令找到像mpi.h
这样的标准头文件,应该使用两个额外的选项-### -fsyntax-only
,即完整的命令应该看起来像:
clang++ -### -fsyntax-only -S -emit-llvm main1.cpp -o - | opt -analyze -dot-callgraph
“C++ Bsc Analyzer”可以显示调用图 - 通过读取 bscmake 实用程序生成的文件。
doxygen + graphviz 可以解决我们想生成调用图的大部分问题,接下来交给人力。
Scitools Understand 是一个 fantastic 工具,比我所知道的一切都好逆向工程,并生成高质量的图表。
但请注意它非常昂贵,并且试用版的蝴蝶调用图仅限于一个级别的调用(恕我直言,我相信他们不会帮助自己这样做......)
GNU 流程
cflow --tree --number main.c a.c b.c