Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Generate a calling graph for C++ code

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.

Does anyone know how to achieve this?

like image 508
shiouming Avatar asked Mar 21 '11 04:03

shiouming


People also ask

What is a call graph in C?

A call graph (also known as a call multigraph) is a control-flow graph, which represents calling relationships between subroutines in a computer program. Each node represents a procedure and each edge (f, g) indicates that procedure f calls procedure g. Thus, a cycle in the graph indicates recursive procedure calls.

How do you extract a call from a graph?

On the bottom right, select the "Call graph" tab. This shows an interactive call graph that correlates to performance metrics in other windows as you click the functions. To export the graph, right click it and select "Export Graph".

How cflow works?

The cflow utility analyzes a collection of source files written in C programming language and outputs a graph charting dependencies between various functions.

What is function call graph?

Function call graphs, or call trees, are a standard tool often found in reverse engineering tools, code browsers, IDEs, and even file editors. They provide fundamental information about the control flow dependencies for the functions you're examining in your tool.


1 Answers

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):

Callgraph

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

#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     

Yields this beauty (oh my, the size without optimizations turned on was too big!)

Beauty

That mystical unnamed function, Node0x884c4e0, is a placeholder assumed to be called by any function whose definition is not known.

like image 179
Johannes Schaub - litb Avatar answered Oct 04 '22 08:10

Johannes Schaub - litb