List of all function calls made in an application
Asked Answered
P

5

29

How can we list all the functions being called in an application. I tried using GDB but its backtrace list only upto the main function call.

I need deeper list i.e list of all the functions being called by the main function and the function being called from these called functions and so on.

Is there a way to get this in gdb? Or could you give me suggestions on how to get this?

Pelayo answered 3/3, 2012 at 20:41 Comment(3)
With any tool: stackoverflow.com/questions/311840/…Caffrey
Possible duplicate of Make GDB print control flow of functions as they are calledTurnip
balau82.wordpress.com/2010/10/06/…Amah
B
33

How can we list all the functions being called in an application

For any realistically sized application, this list will have thousands of entries, which will probably make it useless.

You can find out all functions defined (but not necessarily called) in an application with the nm command, e.g.

nm /path/to/a.out | egrep ' [TW] '

You can also use GDB to set a breakpoint on each function:

(gdb) set logging on     # collect trace in gdb.txt
(gdb) set confirm off    # you wouldn't want to confirm every one of them
(gdb) rbreak .           # set a breakpoint on each function

Once you continue, you'll hit a breakpoint for each function called. Use the disable and continue commands to move forward. I don't believe there is an easy way to automate that, unless you want to use Python scripting.

Already mentioned gprof is another good option.

Burro answered 3/3, 2012 at 20:58 Comment(5)
Note: this will also break on code that runs before _start: stackoverflow.com/questions/31379422/…Caffrey
gdb has been sitting at 100% cpu since I entered the command rbreak .Liselisetta
without logging, set height 0 will be helpful (no paging for output)Fervid
You can try rbreak ^s[^@]*$ if you only want to set breakpoints on non system functions, i.e. exclude malloc, strlen & co.Colonist
@Colonist I think you need to remove that s after ^ - all I got was non-system functions that starting in s...Thoracoplasty
R
14

You want a call graph. The tool that you want to use is not gdb, it's gprof. You compile your program with -pg and then run it. When it runs a file gmon.out will be produced. You then process this file with gprof and enjoy the output.

Reagan answered 3/3, 2012 at 20:47 Comment(6)
I doubt gprof gives you the sequence of all function invocations.Halakah
It's not complete, but it's pretty good. Check out ftp.gnu.org/old-gnu/Manuals/gprof-2.9.1/html_chapter/… and docs.oracle.com/cd/E19059-01/wrkshp50/805-4947/6j4m8jrn7/…Reagan
So, no, it's neither complete nor close. The link you gave shows it's one line per stack of functions, not per call to a function or stack-of-functions. This is not what I need. If from main, I call a() then b() then a() then b() etc. - I want to get "main a b a b a b a b etc."Halakah
Do you mean that you want every function call that your program makes? Do you want just your functions, or all library functions, all compiler support functions, etc. And what is your definition of a "function call" ?Reagan
Every call, in sequence.Halakah
Your best bet is instrumenting the compiler or modifying the intermediate code or the assembler. It is possible that this is what happens with gprof.Reagan
C
11

record function-call-history

https://sourceware.org/gdb/onlinedocs/gdb/Process-Record-and-Replay.html

This should be a great hardware accelerated possibility if you are one of the few people (2015) with a CPU that supports Intel Processor Tracing (Intel PT, intel_pt in /proc/cpuinfo).

GDB docs claim that it can produce output like:

(gdb) list 1, 10
1   void foo (void)
2   {
3   }
4
5   void bar (void)
6   {
7     ...
8     foo ();
9     ...
10  }
(gdb) record function-call-history /ilc
1  bar     inst 1,4     at foo.c:6,8
2    foo   inst 5,10    at foo.c:2,3
3  bar     inst 11,13   at foo.c:9,10

Before using it you need to run:

start
record btrace

which is where a non capable CPU fails with:

 Target does not support branch tracing.

CPU support is further discussed at: How to run record instruction-history and function-call-history in GDB?

Related threads:

For embedded, you also consider JTAG and supporting hardware like ARM's DSTREAM, but x86 support does not seem very good: debugging x86 kernel using a hardware debugger

Caffrey answered 4/8, 2015 at 16:26 Comment(0)
H
3

This question might need clarification to decide between what are currently 2 answers. Depends on what you need:

1) You need to know how many times each function is being called in straight list/graph format of functions matched with # of calls. This could lead to ambiguous/inconclusive results if your code is not procedural (i.e. functions calling other functions in a branch out structure without ambiguity of what is calling what). This is basic gprof functionality which requires recompilation with -pg flag.

2) You need a list of functions in the order in which they were called, this depends on your program which is the best/feasible option: a) IF your program runs and terminates without runtime errors you can use gprof for this purpose. b) ELSE option above using dbg with logging and break points is the left over option that I learned upon reading this.

3) You need to know not only the order but, for example, the function arguments for each call as well. My current work is simulations in physics of particle transport, so this would ABSOLUTELY be useful in tracking down where anomalous results are coming from... i.e. when the arguments getting passed around stop making sense. I imagine one way to do this is would be a variation on what Employed Russian did except using the following:

(gdb) info args

Logging the results of this command with every break point (set at every function call) gives the args of the current function.

Heilner answered 2/9, 2013 at 18:37 Comment(0)
W
1

With gdb, if you can find the most child function, you can list its all ancestors like this:

gdb <your-binary>

(gdb) b theMostChildFunction ## put breakpoint on the desired function
(gdb) r ## run the program
(gdb) bt ## backtrace starting from the breakpoint

Otherwise, on linux, you can use perf tool to trace programs and their function calls. The advantage of this, it is tracing all processes including child processes and also it shows usage percentages of the functions in the program.

You can install perf like this:

sudo apt install linux-tools-generic
sudo apt install linux-cloud-tools-generic

Before using perf you may also need to remove some kernel restrictions temporarily:

sudo sh -c 'echo 0 >/proc/sys/kernel/kptr_restrict'
sudo sh -c 'echo 0 >/proc/sys/kernel/perf_event_paranoid' 
sudo sh -c 'echo 0 >/proc/sys/kernel/yama/ptrace_scope'

After this, you can run your program binary with perf like this:

perf record -g -s -a <your-binary-and-its-flags>

Then either you can look the output on terminal like this:

perf report

or on text file like this:

perf report -i perf.data > output.txt
vim output.txt

when you are recording the function calls with perf also you may want to filter kernel calls with --all-user flag:

perf record -g -s -a --all-user <your-binary-and-its-flags>

For further information you can look here: https://perf.wiki.kernel.org/index.php/Tutorial

Wynne answered 17/11, 2022 at 10:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.