如何为 C++ 代码生成调用图
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5373714/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to Generate a calling graph for C++ code
提问by shiouming
I'm trying to generate calling graph with which to find out all the possible execution paths that are hitting a particular function (so that I don't have to figure out all the paths manually, as there are many paths that lead to this function). For instance:
我正在尝试生成调用图,用它找出所有可能命中特定函数的执行路径(这样我就不必手动找出所有路径,因为有很多路径可以通向这个函数) )。例如:
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: ...
I have tried Codeviz and Doxygen, somehow both results show nothing but callees of target function, D. In my case, D is a member function of a class whose object will be wrapped within a smart pointer. Clients will always obtain the smart pointer object through a factory in order to invoke D.
我尝试过 Codeviz 和 Doxygen,不知何故,这两个结果只显示目标函数 D 的被调用者。在我的例子中,D 是一个类的成员函数,其对象将被包装在一个智能指针中。客户端将始终通过工厂获取智能指针对象以调用 D。
Does anyone know how to achieve this?
有谁知道如何实现这一目标?
回答by Johannes Schaub - litb
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();
}
Then
然后
$ clang++ -S -emit-llvm main1.cpp -o - | opt -analyze -dot-callgraph
$ dot -Tpng -ocallgraph.png callgraph.dot
Yields some shiny picture (there is an "external node", because main
has external linkage and might be called from outside that translation unit too):
产生一些闪亮的图片(有一个“外部节点”,因为main
具有外部链接并且也可能从该翻译单元外部调用):
You may want to postprocess this with c++filt
, so that you can get the unmangled names of the functions and classes involved. Like in the following
您可能希望使用 对它进行后处理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=} != id' |
dot -Tpng -ocallgraph.png
Yields this beauty (oh my, the size without optimizations turned on was too big!)
产生这种美感(哦,天哪,没有开启优化的尺寸太大了!)
That mystical unnamed function, Node0x884c4e0
, is a placeholder assumed to be called by any function whose definition is not known.
那个神秘的未命名函数 ,Node0x884c4e0
是一个占位符,假定由任何定义未知的函数调用。
回答by jpo38
You can achieve that by using doxygen (with option to use dot for graphs generation).
您可以通过使用 doxygen(可以选择使用点来生成图形)来实现这一点。
With Johannes Schaub - litb main.cpp, it generates this:
使用 Johannes Schaub - litb main.cpp,它会生成以下内容:
doxygen/dot are probably easier than clang/opt to install and run. I did not manage to install it myself and that's why I tried to find an alternative solution!
doxygen/dot 可能比 clang/opt 更容易安装和运行。我没有设法自己安装它,这就是为什么我试图找到替代解决方案!
回答by Ira Baxter
Statically computing an accurate C++ call graph is hard, because you need a precise langauge parser, correct name lookup, and a good points-to analyzer that honors the language semantics properly. Doxygen doesn't have any of these, I don't know why people claim to like it for C++; it is easy to construct a 10 line C++ example that Doxygen erroneously analyzes).
静态计算准确的 C++ 调用图是很困难的,因为您需要一个精确的语言解析器、正确的名称查找和一个正确地尊重语言语义的好的指向分析器。Doxygen 没有这些,我不知道为什么人们声称喜欢它用于 C++;很容易构建一个 Doxygen 错误分析的 10 行 C++ 示例)。
You might be better off running a timing profiler which collects a call graph dynamically(this describes ours) and simply exercise a lot of cases. Such profilers will show you the actual call graph exercised.
您最好运行一个时序分析器,它动态收集调用图(这描述了我们的)并简单地练习了很多情况。此类分析器将向您显示实际执行的调用图。
EDIT: I suddenly remembered Understand for C++, which claims to construct call graphs. I don't know what they use for a parser, or whether they do the detailed analysis right; I have no specific experience with their product.
编辑:我突然想起 了 C++ 的理解,它声称可以构造调用图。我不知道他们用什么做解析器,也不知道他们做的详细分析是否正确;我对他们的产品没有特别的经验。
I am impressed by Schaub's answer, using Clang; I would expect Clang to have all the elements right.
Schaub 使用 Clang 的回答给我留下了深刻的印象;我希望 Clang 拥有正确的所有元素。
回答by Issam
回答by mabalenk
In order for the clang++
command to find standard header files like mpi.h
two additional options should be used -### -fsyntax-only
, i.e. the full command should look as:
为了让clang++
命令找到标准头文件,mpi.h
应该使用两个附加选项-### -fsyntax-only
,即完整命令应如下所示:
clang++ -### -fsyntax-only -S -emit-llvm main1.cpp -o - | opt -analyze -dot-callgraph
回答by Resonantium
The "C++ Bsc Analyzer" can display call graphs - by reading the file generated by the bscmake utility.
“C++ Bsc Analyzer”可以显示调用图 - 通过读取 bscmake 实用程序生成的文件。
回答by Crawl.W
doxygen + graphvizcould solve most problems when we wanna generate call graph,next handed to manpower.
当我们想要生成调用图时,doxygen + graphviz可以解决大多数问题,其次是人力。
回答by franckspike
Scitools Understandis a fantastictool, better than everything I know for reverse engineering, and generates high quality graphs.
Scitools理解是一个很棒的工具,比我所知道的逆向工程更好,并生成高质量的图表。
But note it is quite expensive and that the trial version has its butterfly call graphlimited to only one level of call (IMHO I believe they don't help themselves doing so…)
但请注意,它非常昂贵,并且试用版的蝴蝶调用图仅限于一个级别的调用(恕我直言,我相信他们不会帮助自己这样做……)