我正在尝试生成调用图,用它来查找命中特定函数的所有可能的执行路径(这样我就不必手动找出所有路径,因为有许多路径可以导致这个功能)。例如:
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。
有谁知道如何实现这个目标?
答案 0 :(得分:104)
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
是一个占位符,假定由任何定义未知的函数调用。
答案 1 :(得分:13)
您可以通过使用doxygen实现这一点(可选择使用点生成图形)。
使用Johannes Schaub - litb main.cpp,它产生了这个:
doxygen / dot可能比clang / opt更容易安装和运行。我没有设法自己安装它,这就是为什么我试图寻找替代解决方案!
答案 2 :(得分:6)
静态计算准确的C ++调用图很难,因为你需要一个精确的语言解析器,正确的名称查找,以及一个能够正确理解语言语义的优秀分析器。 Doxygen没有这些,我不知道为什么人们声称喜欢C ++;很容易构建Doxygen错误分析的10行C ++示例。
你可能最好不要运行timing profiler which collects a call graph dynamically(这描述了我们的)并且只是运用了很多案例。此类分析器将显示实际调用图表。
编辑:我突然想起Understand for C++,声称构建了呼叫图。我不知道他们使用什么解析器,或者他们是否正确进行详细分析;我对他们的产品没有具体经验。
我对Schaub的答案印象深刻,使用了Clang;我希望Clang拥有正确的所有元素。
答案 3 :(得分:5)
答案 4 :(得分:2)
为了使clang++
命令能够找到mpi.h
等标准头文件,应使用另外两个选项-### -fsyntax-only
,即完整命令应如下所示:
clang++ -### -fsyntax-only -S -emit-llvm main1.cpp -o - | opt -analyze -dot-callgraph
答案 5 :(得分:1)
“C ++ Bsc Analyzer”可以显示调用图 - 通过读取bscmake实用程序生成的文件。
答案 6 :(得分:0)
doxygen + graphviz 可以解决大多数我们想生成调用图时要解决的问题,然后交给人力。
答案 7 :(得分:0)
Scitools Understand是一种奇妙的工具,比我对逆向工程所了解的要好,并且可以生成高质量的图形。< / p>
但是请注意,这非常昂贵,而且试用版的 butterfly调用图仅限于一个调用级别(恕我直言,我相信他们不会这样做…)