栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

Getting Control Flow Graph from ANSI C code

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Getting Control Flow Graph from ANSI C code

源:https://stackoverflow.com/questions/16393985/getting-control-flow-graph-from-ansi-c-code/17844310
https://abdulmateenabdul1mate1en.blogspot.com/2015/05/gcc-geting-control-flow-graph-from-ansi.html

For the control flow graph of a C Program you could look at existing Python parsers for C:

albertz PyCParser
eliben PyCParser
pyclibrary (fork of pyclibrary)
joern
CoFlo C/C++ control flow graph generator and analyzer

Call graphs are a closely related construct to control flow graphs. There are several approaches available to create call graphs (function dependencies) for C code. This might prove of help for progressing with control flow graph generation. Ways to create dependency graphs in C:
Using cflow:
cflow +pycflow2dot +dot (GPL, BSD) cflow is robust, because it can handle code which cannot compile, e.g. missing includes. If preprocessor directives are heavily used, it may need the --cpp option to preprocess the code.
cflow + cflow2dot + dot (GPL v2, GPL v3, Eclipse Public License (EPL) v1) (note that cflow2dot needs some path fixing before it works)
cflow +cflow2dot.bash (GPL v2, ?)
cflow +cflow2vcg (GPL v2 , GPL v2)
enhanced cflow (GPL v2) with list to exclude symbols from graph
Using cscope:
cscope (BSD)
cscope +callgraphviz +dot +xdot
cscope +vim CCTree (C Call-Tree Explorer)
cscope +ccglue
cscope +CodeQuery for C, C++, Python & Java
cscope +Python html producer
cscope +calltree.sh
ncc (cflow like)
KCachegrind (KDE dependency viewer)
Calltree
The following tools unfortunately require that the code be compilable, because they depend on output from gcc:

CodeViz (GPL v2) (weak point: needs compilable source, because it uses gcc to dump cdepn files)
gcc +egypt +dot (GPL v*, Perl = GPL | Artistic license, EPL v1) (egypt uses gcc to produce RTL, so fails for any buggy source code, or even in case you just want to focus on a single file from a larger project. Therefore, it is not very useful compared to the more robust cflow-based toolchains. Note that egypt has by default good support for excluding library calls from the graph, to make it cleaner.

Also, file dependency graphs for C/C++ can be created with crowfood.

===============================================================

Dynamic analysis methods

In this answer I describe a few dynamic analysis methods.

Dynamic methods actually run the program to determine the call graph.

The opposite of dynamic methods are static methods, which try to determine it from the source alone without running the program.

Advantages of dynamic methods:

catches function pointers and virtual C++ calls. These are present in large numbers in any non-trivial software.

Disadvantages of dynamic methods:
you have to run the program, which might be slow, or require a setup that you don’t have, e.g. cross-compilation
only functions that were actually called will show. E.g., some functions could be called or not depending on the command line arguments.

KcacheGrind

https://kcachegrind.github.io/html/Home.html

Test program:

int f2(int i) { return i + 2; }
int f1(int i) { return f2(2) + i + 1; }
int f0(int i) { return f1(1) + f2(2); }
int pointed(int i) { return i; }
int not_called(int i) { return 0; }

int main(int argc, char **argv) {
    int (*f)(int);
    f0(1);
    f1(1);
    f = pointed;
    if (argc == 1)
        f(1);
    if (argc == 2)
        not_called(1);
    return 0;
}

Usage:

sudo apt-get install -y kcachegrind valgrind

# Compile the program as usual, no special flags.
gcc -ggdb3 -O0 -o main -std=c99 main.c

# Generate a callgrind.out. file.
valgrind --tool=callgrind ./main

# Open a GUI tool to visualize callgrind data.
kcachegrind callgrind.out.1234

You are now left inside an awesome GUI program that contains a lot of interesting performance data.

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”. The exported PNG looks like this:

From that we can see that:

the root node is _start, which is the actual ELF entry point, and contains glibc initialization boilerplate
f0, f1 and f2 are called as expected from one another
pointed is also shown, even though we called it with a function pointer. It might not have been called if we had passed a command line argument.
not_called is not shown because it didn’t get called in the run, because we didn’t pass an extra command line argument.

The cool thing about valgrind is that it does not require any special compilation options.

Therefore, you could use it even if you don’t have the source code, only the executable.

valgrind manages to do that by running your code through a lightweight “virtual machine”.

Tested on Ubuntu 18.04.

gcc -finstrument-functions + etrace

https://github.com/elcritch/etrace

-finstrument-functions adds callbacks, etrace parses the ELF file and implements all callbacks.

I couldn’t get it working however unfortunately: Why doesn’t -finstrument-functions work for me?

Claimed output is of format:

-- main
|   -- Crumble_make_apple_crumble
|   |   -- Crumble_buy_stuff
|   |   |   -- Crumble_buy
|   |   |   -- Crumble_buy
|   |   |   -- Crumble_buy
|   |   |   -- Crumble_buy
|   |   |   -- Crumble_buy
|   |   -- Crumble_prepare_apples
|   |   |   -- Crumble_skin_and_dice
|   |   -- Crumble_mix
|   |   -- Crumble_finalize
|   |   |   -- Crumble_put
|   |   |   -- Crumble_put
|   |   -- Crumble_cook
|   |   |   -- Crumble_put
|   |   |   -- Crumble_bake

Likely the most efficient method besides specific hardware tracing support, but has the downside that you have to recompile the code.

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/385003.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号