Call graphs using the GNU Project Debugger

Chris Ball asked everyone who likes Unix for a tool which would be to function calls what strace and ltrace are for system and library calls respectively.

I wanted to write this myself for a long time but what prevented me from doing so was the fact that I had come up with a trivial shell/awk script that achieved almost the same goal. Since that little program was useful for someone other than me, I thought I’d polish it slightly and post it here.

This tool’s original intent was to print a call graph from a given program. It works by taking control of GDB and automatically setting breakpoints at each function call. Of course, the executable must include debugging symbols (that is, it must have been compiled with gcc’s -g option). Here’s some sample output (the format is: caller callee arguments):

xmltree_parse xmltree_itor_next (self=0x80571e8)
xmltree_itor_next xmlnode_stack_push (stack=0x80571f0, n=0x8056780)
xmltree_parse h_requires (n=0x8056808, u=0xbff9d504)
h_requires xmlnode_get_attr (self=0x8056808, name=0x80520ea "plugin")
h_requires probe_get_name (self=0x8056af0)
h_requires htab_lookup (self=0x8058100, key=0x8056868, len=3, create=0, value=0x0)

You can use the included cg2dot.awk script to produce files suitable for processing with graphviz.

13 Responses to “Call graphs using the GNU Project Debugger”

  1. Nicolas January 28, 2008 at 21:33 #

    Hi!
    Thanks for this very useful script!
    I was wondering if you could add a -p option to connect to a running process, as strace or gdb can already do. With this option, callgraph would be a really handy debugging tool.
    Regards,
    Nicolas

  2. jmbr January 29, 2008 at 21:38 #

    Hi Nicolas,

    I’m glad you like callgraph.

    I’ll implement the feature you mention as soon as time permits (currently I have a shortage of free time).

    Thank you very much for your suggestion

  3. alex December 3, 2009 at 17:26 #

    Cool script… but it is rather slow on really big projects ( >8k functions).
    It takes around 100 sec to create breakpoints by gdb and a eternity to run program.

  4. alex December 15, 2009 at 18:24 #

    It is very useful! I’ve added filtering of function list with grep and now I can use it on any project.

  5. Gwyn Fireman April 13, 2010 at 17:22 #

    Great tool!

    I had a little trouble with fortran functions defined like
    REAL(4) acoss(REAL(4));
    The trace file would include an entry for a function named “REAL”, which would of course displease gdb.

    Solved this by piping the “getfuncs” output through
    sed “s/([0-9][0-9]*)//g”
    to get rid of all numbers within parens.

    Thanks!

  6. su chen May 12, 2010 at 09:02 #

    Thanks for the great tool!

    however, this works on my rhel wich gcc 4.1.2 and gdb Fedora (6.8-37.el5) but does not work on freeBSD with gcc version 2.95.4 and GNU gdb 4.18 (FreeBSD) – no output at all on freeBSD, callgraph ends silently.

    Could you please give some suggestions on modifying the shell script? thanks.

  7. Vijay August 30, 2010 at 14:39 #

    Thanks, with little changes i was able to adapt the script to attach to running process and get info about interested functions.
    To use this after modifications, callgraph
    note you have to remove some sanity checks as needed. major difference being:
    ————
    /dev/null | awk ‘

    > gdb –batch –command=$GETFUNCS $FILE 2>/dev/null | awk ‘
    71c96
    print “run”
    75c100
    /dev/null | awk ‘

    > gdb –batch –command=$TRACE –tty=/dev/null –args $FILE $@ 2>/dev/null | awk ‘

  8. niu zj September 2, 2010 at 14:57 #

    when I use the test example,input ./callgraph test foo 23,then as the errors like below:
    “awk: line 27: regular expression compile failed (missing operand)
    * print “info args”; *”

    could you help me?

  9. Vijay September 8, 2010 at 06:06 #

    Hi,
    Am adding on this technique to narrow down the scope of the logical problem without spending long time debugging ( like stepping through code for 50 iterations etc)

    This idea is based on “breakpoint commands” in GDB.
    Note the idea of breakpoint commands exists for long time, but its uniquely used here to trace function calls/variables without user intervention in gdb.
    It could used in other debuggers as well in different forms.

    Step 1:
    Prereq: must have debugging symbols in the binary(built via –g flag for gcc).

    Step 2:
    Place all your GDB commands in one file say:

    breakpoints_file:

    set width 0
    set height 0
    set verbose off
    break do_query # this is where I want GDB to break automatically after attaching
    commands 1 #this is where I issue breakpoint commands on above breakpoint
    backtrace 2 #this is where I print a short stack-trace and further issue display commands to print certain local vars always
    info args
    # place any number of GDB display commands that you might want to see
    p *(*reqp).data1.cursor #printing some variables always on hitting a breakpoint.
    p sql_stmt
    p *reqp
    continue
    end # place an end to end breakpoint commands

    Step 3: Then start with gdb as follows:

    =====================================
    gdb –batch –command=breakpoints_file –p
    =====================================

    This will attach to the run-time daemon(process) and start printing or executing commands in background. Use ^c to exit finally. Very useful if you want to what’s there in any local variable every time a function runs and in different test cases.

  10. Vijay September 8, 2010 at 06:10 #


    step 3 again:
    =====================================
    gdb --batch --command=breakpoints_file –p
    =====================================

  11. Vijay September 8, 2010 at 06:12 #


    =====================================
    gdb --batch --command=breakpoints_file –p 'PID of process'
    =====================================

  12. Andruk October 22, 2010 at 14:06 #

    Thanks for this, it worked very well for my project!

Trackbacks/Pingbacks:

  1. linux tracing tools | 阿喵就像家 - December 22, 2011

    [...] call-graphs-using-the-gnu-project-debugger : 這個 script 寫的很好,可以無腦套用。 [...]

Leave a Reply:

Gravatar Image

XHTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>