3

I want to trace a C program under Linux, and record all function calls and returns in a format of tree. For example, the source code:

void a ()
{
    printf("a\n");
}
void b ()
{
    printf("b\n");
}

void c ()
{
    a();
    b();
}

int main()
{
    a();
    b();
    c();
}

And I want a output like the following:

call main
    call a
    exit a
    call b
    exit b
    call c
        call a
        exit a
        call b
        exit b
    exit c
exit main

It is a idealistic output. I just want to get all the process of local function calls and returns, so the similar output is also welcome.

tvkanters
  • 3,519
  • 4
  • 29
  • 45
river
  • 694
  • 6
  • 22
  • 1
    Well use `printf` to track the entry and exit out of functions (The constructor/destructor concept of C++). To print in file use `fprintf` – 0xF1 Mar 26 '14 at 09:04
  • 2
    please check this link.. it might be helpful. http://stackoverflow.com/questions/10374005/how-to-trace-function-call-in-c – Manish_Dubey Mar 26 '14 at 09:09
  • It is a big project, so it's hard to inject fprintf statements to all the functions manually. Is there any tools to help me? – river Mar 26 '14 at 09:09
  • You could probably find useful ltrace. http://man7.org/linux/man-pages/man1/ltrace.1.html for tracing the calls but I didn't see if you can trace the exits. – Varvarigos Emmanouil Mar 26 '14 at 09:45
  • SystemTap has what you need https://sourceware.org/systemtap/tutorial/Tracing.html#SECTION00032000000000000000. The only thing that can cause a problem is that your project can be too big to trace it with SystemTap. Once I answered more or less the same quesiton https://stackoverflow.com/questions/20764462/following-a-programs-execution –  Mar 26 '14 at 10:07

3 Answers3

2

gcc -finstrument-functions does my job

river
  • 694
  • 6
  • 22
0

To produce such an output by modifying code, try something like this (not optimized but does the job):

size_t indent;

#define ENTER_FUNC(function_name)                     \
    indent++;                                         \
    for(size_t i=0; i<indent; i++) printf("\t");      \
    printf("Call %s\n", function_name);

#define EXIT_FUNC(function_name)                     \
    for(size_t i=0; i<indent; i++) printf("\t");     \
    printf("Exit %s\n", function_name);              \
    indent--;

Call ENTER_FUNC at the beginning of each function to trace and EXIT_FUNC prior to any return. You can also enrich the macro to write in a log file.

Otherwise there are some profiling tools like gprof for example

n0p
  • 3,399
  • 2
  • 29
  • 50
  • Thanks very much! It is a big project, so it's hard to inject ENTER_FUNC statements to all the functions manually. Is there any tools to help me to insert the ENTER_FUNC to all the functions ? – river Mar 26 '14 at 09:47
  • Well, if you know Python for instance you could write a script to do the job. It can also be (carefully) done in an editor like Vim with the proper search & replace command. For example: wherever there is a `return [whatever];` insert `EXIT_FUNC`. Also note that if you have a big program with a lot of calls, these macros will deeply affect your performances. And they're not protected against competitive calls (threads, etc...) – n0p Mar 26 '14 at 09:53
0

Use cflow would be a good choice as well. The information of cflow could be found in gnu website, https://www.gnu.org/software/cflow/

Below is an example of cflow,

$ cflow foo.c cl.12.*.c
main() <int main (void) at foo.c:18>:
    foo_trivial_questions() <void foo_trivial_questions (void) at foo.c:13>:
        foo_cl_12_test() <void foo_cl_12_test (void) at cl.12.IntegertoRoman.c:32>:
            foo() <void foo (int n) at cl.12.IntegertoRoman.c:24>:
                intToRoman() <char *intToRoman (int num) at cl.12.IntegertoRoman.c:3>:
                    malloc()
                    strcat()
                printf()
                free()

djiang
  • 48
  • 7