Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 5 years ago.
Improve this question
I have a large work space which has many source files of C code. Although I can see the functions called from a function in MS VS2005 using the Object browser, and in MSVC 6.0 also, this only shows functions called from a particular function in a non-graphical kind of display. Additionally, it does not show the function called starting from say main(), and then the functions called from it, and so on, deeper inside to the leaf level function.
I need a tool which will give me a function call graph pictorially with functions callee and caller connected by arrows or something like that, starting from main() to the last level of function, or at least showing a call graph of all functions in one C source file pictorially. It would be great if I could print this graph.
Any good tools to do that (need not be free tools)?
Egypt (free software)
ncc
KcacheGrind (GPL)
Graphviz (CPL)
CodeViz (GPL)
Dynamic analysis methods
Here 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.<PID> 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". This also makes execution extremely slow compared to native execution.
As can be seen on the graph, timing information about each function call is also obtained, and this can be used to profile the program, which is likely the original use case of this setup, not just to see call graphs: How can I profile C++ code running on Linux?
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.
Understand does a very good job of creating call graphs.
Our DMS Software Reengineering Toolkit has static control/dataflow/points-to/call graph analysis that has been applied to huge systems (~~25 million lines) of C code, and produced such call graphs, including functions called via function pointers.
You may try CScope + tceetree + Graphviz.
You can check out my bash-based C call tree generator here. It lets you specify one or more C functions for which you want caller and/or called information, or you can specify a set of functions and determine the reachability graph of function calls that connects them... I.e. tell me all the ways main(), foo(), and bar() are connected. It uses graphviz/dot for a graphing engine.
Astrée is the most robust and sophisticated tool out there, IMHO.
Related
This question already has answers here:
Tools to get a pictorial function call graph of code [closed]
(7 answers)
Closed 8 years ago.
I would really like to know if there are any methods or applications which can show me which functions are referencing which functions. So say I would like to see from where a function change_state() is called/referenced, I get something like:
/--app_init()<--main()
|
change_state() <--|
|
\--afile.c |<--trigger()
/ line 100|
| line 156|
|
\--bfile.c|
line 26|<--|--button_event()<--process_event()
line 30| |
\--move_event()
EDIT: I am using the Keil compiler in Windows 7.
You can use gperf for that type of use.
It will show you a call graph, which is basically what you want, including performance mesurement.
First, assuming you're using gcc, compile with the option -gp.
Then, run your binary normally. It will output a gmon.out file. You can then use gperf to analyse that file, which contains the data you're requesting.
I'm building tool for testing ansi c applications. Simply load code, view control flow graph, run test, mark all vertexes which was hit. I'm trying to build CFG all by myself from parsing code. Unfortunately It gets messed up if code is nested. GCC gives ability to get CFG from compiled code. I might write parser for its output, but I need line numbers for setting breakpoints. Is there way for getting line numbers when outputting Control Flow Graph with -fdump-tree-cfg or -fdump-tree-vcg?
For the control flow graph of a C Program you could look at existing Python parsers for C:
PyCParser
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.
So I've made some more research and it is not hard to get line numbers for nodes. Just add lineno option to one of those options to get it. So use -fdump-tree-cfg-lineno or -fdump-tree-vcg-lineno. It took me some time to check if those numbers are reliable. In case of graph in VCG format label of each node contains two numbers. Those are line numbers for start and end of code portion represented by this node.
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.<PID> 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.
I'm getting multiple definition link errors after conditionally compiling platform-specific code.
My project is laid out like this:
/
|__+ include/
| |__+ native/
| | |__ impl.h
| |
| |__ general.h
|
|__+ src/
|__+ native/
| |__ impl.linux.c
| |__ impl.win32.c
|
|__ general.c
At the top of the general.c file:
#if defined(LIBRARY_PLATFORM_LINUX)
#include "native/impl.linux.c"
#elsif defined(LIBRARY_PLATFORM_WIN32)
#include "native/impl.win32.c"
#endif
I set up introspection in CMake in order to detect the operating system and define the corresponding constants. The thing is, I didn't want to maintain one CMakeLists.txt file in every directory, so I simply globbed all the .c files as suggested in this answer:
file(GLOB_RECURSE LIBRARY_SOURCE_FILES "${PROJECT_SOURCE_DIR}/src/*.c")
Apparently, this is what is causing the problem. It seems to be compiling the code #included in general.c as well as the individual src/native/impl.*.c files.
CMakeFiles/lib.dir/src/native/impl.linux.c.o: In function `declared_in_impl_h':
impl.linux.c:(.text+0x0): multiple definition of `declared_in_impl_h'
CMakeFiles/lib.dir/src/general.c.o:general.c:(.text+0x0): first defined here
How can I untangle this situation?
The best practice for that sort of cross-platform situation is to create two libraries, one for linux and one for windows and stop doing conditional includes. Each platform only compiles and links the relevant library.
The recommended way to do that with cmake is to stop globbing and just include each file. There are some situations where it can get confused and not realize that it needs to recompile. You can make an argument that non-changing legacy code won't have that problem.
If you really want to avoid doing either of these things, I would put the included code in a header instead of a c file. You don't really want the include guards so that people don't get it confused for something that should be used like a regular header. Put a bunch of comments in the file to warn them off of said behavior as well.
I've always wanted to know if there is a default directory layout for C projects. You know, which folders should i put which files and such.
So I've downloaded lots of project's source codes on SourceForge and they were all different than each other.
Generally, I found more or less this structure:
/project (root project folder, has project name)
|
|____/bin (the final executable file)
|
|
|____/doc (project documentation)
| |
| |____/html (documentation on html)
| |
| |____/latex (documentation on latex)
|
|
|____/src (every source file, .c and .c)
| |
| |____/test (unit testing files)
|
|
|____/obj (where the generated .o files will be)
|
|
|____/lib (any library dependences)
|
|
|____BUGS (known bugs)
|
|____ChangeLog (list of changes and such)
|
|____COPYING (project license and warranty info)
|
|____Doxyfile (Doxygen instructions file)
|
|____INSTALL (install instructions)
| |
|____Makefile (make instructions file)
|
|____README (general readme of the project)
|
|____TODO (todo list)
Is there a default standard somewhere?
Edit: Sorry, really. I realised there are numerous similar questions for recommended C project directory files. But I've seen people say what they think is best. I'm looking for a standard, something that people usually follow.
Related Questions:
C - Starting a big project. File/Directory structure and names. Good example required
Folder structure for a C project
File and Folder structure of a App/Project based in C
Project Organization in C Best Practices
I would say "no", and your empirical evidence seems to support that.
I usually get confused right around when I need to decide between doc/ and docs/ ...
Well, there is “libabc” which is showcasing common practice.
How can I store a version number in a static library (file.a) and later check for its version in Linux?
P.S. I need possibility to check version of file any time without any special executable using only by shell utilities.
In addition to providing a static string as mentioned by Puppe, it is common practice to provide a macro to retrieve the version check for compatibility. For example, you could have the following macros (declared in a header file to be used with your library):
#define MYLIB_MAJOR_VERSION 1
#define MYLIB_MINOR_VERSION 2
#define MYLIB_REVISION 3
#define MYLIB_VERSION "1.2.3"
#define MYLIB_VERSION_CHECK(maj, min) ((maj==MYLIB_MAJOR_VERSION) && (min<=MYLIB_MINOR_VERSION))
Notice with the MYLIB_CHECK_VERSION macro, I'm assuming you want a specific major rev and a minor rev greater than or equal to your desired version. Change as required for your application.
Then use it from a calling application, something like:
if (! MYLIB_VERSION_CHECK(1, 2)) {
fprintf(stderr, "ERROR: incompatible library version\n");
exit(-1);
}
This approach will cause the version information to come from the included header file. Additionally, it will be optimized at compile time for the calling application. With a little more work, you can extract it from the library itself. Read on...
You can also use this information to create a static string stored inside your library, as mentioned by Puppe. Place something like this inside your library:
struct {
const char* string;
const unsigned major;
const unsigned minor;
const unsigned revision;
} mylib_version = {
MYLIB_VERSION, MYLIB_MAJOR_VERSION, MYLIB_MINOR_VERSION, MYLIB_REVISION
};
This will create a struct called mylib_version in your library. You can use this to do further verifications by creating functions inside your library and accessing those from a calling application, etc.
Maybe you could create a string with the version like this:
char* library_version = { "Version: 1.3.6" };
and to be able to check it from the shell just use:
strings library.a | grep Version | cut -d " " -f 2
Creating a new answer based on your edit... Just to avoid confusion :)
If you are looking for a non-code way to solve the problem, you could try this. It's (yet again) an alternative to the strings approach defined by Puppe.
Maybe you could just touch a file called version_1.2.3 and add it to the archive. Then, you could determine the version by looking for the version file using the ar command:
ar t libmylib.a | grep 'version_' | sed -e 's/^version_//'
I'm not sure if that will get you what you need, but there is no standard method for embedding metadata like this in an archive. Maybe you'll find other information you want to store in this "metafile" for the archive.
If you are using gcc, you can use the #ident directive
#ident "Foo Version 1.2.3.4"
void foo(void){ /* foo code here */ }
To get the version just use one of the following:
strings -a foo.o | grep "Foo Version"
strings -a foo.a | grep "Foo Version"
strings -a foo.so | grep "Foo Version"
This will allow you to compile the version into the library with the capability of later stripping it out using strip -R .comment your_file or completely omit it by passing -fno-ident (This will also omit the compiler version comments from the compiled objects)
Several times man 1 ident has been mentioned, so here are details about using that method.
ident is a command that comes with the RCS (Revision Control System), but might also be available if you are using CVS (Concurrent Versions System), or Subversion.
You would use it like this (cloned from the man page):
#include <stdio.h>
static char const rcsid[] =
"$Id: f.c,v 5.4 1993/11/09 17:40:15 eggert Exp $";
int main() { return printf("%s\n", rcsid) == EOF; }
and f.c is compiled into f.o, then the command
ident f.c f.o
will output
f.c:
$Id: f.c,v 5.4 1993/11/09 17:40:15 eggert Exp $
f.o:
$Id: f.c,v 5.4 1993/11/09 17:40:15 eggert Exp $
If your f.o were added to a static library f.a then ident f.a should show a similar output. If you have several similarly built [a-z].o in your az.a you should find all their strings in the az.a file.
CAVEAT: Just because they are in the .a file doesn't mean they will be included in your program file. Unless the program references them the linker sees no need to include them. So you usually have to have a method in each module to return the string, and the app needs to call that method. There are ways to convince most linkers that it is a required symbol without actually referencing it, but it depends on the linker, and is beyond the scope of this answer.
If instead you are familiar with the SCCS (Source Code Control System) then you would use man 1 what instead, and it would look like this (done with macros to show the flexibility available):
#include <stdio.h>
#define VERSION_STR "5.4"
#define CONFIG "EXP"
#define AUTHOR "eggert"
static char const sccsid[] =
"#(#) " CONFIG " v " VERSION_STR " " __DATE__ " " __TIME__ " " AUTHOR;
int main() { return printf("%s\n", sccsid) == EOF; }
and f.c is compiled into f.o, then the command
what f.c f.o
will output
f.c:
#(#) EXP v 5.4 1993/11/09 17:40:15 eggert
f.o:
#(#) EXP v 5.4 1993/11/09 17:40:15 eggert
PS: both ident and what are commands that come with specific centralized source control systems. If you are using a distributed source control system (like git) the entire concept may not make sense. For some ideas using git see this thread: Moving from CVS to git: $Id:$ equivalent? though the hash isn't the same as a version number. :)