Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Log all parameters values from each C function call [closed]

I have a C binary file (source code available) and a pre-defined workload. I want to log all the function calls and its respective parameters, and also the return value, in call order. For example, in the code below:

int myfunc(int value){
    return value*2;
}

int main(void){
    int i;
    i = myfunc(10);
    i = myfunc(12);
    i = myfunc(20);
    return 0;
}

It shoud result in a log file like this:

int main()
int myfunc(10)
myfunc return 20
int myfunc(12)
myfunc return 24
int myfunc(21)
myfunc return 42
main return 0

I've already tried to use Intel PIN to do it, and it works very well, except that when the variable is a pointer, an array, a struct or a typedef. I need all the variables.

I have the source code and I can compile it using debug options.

Any ideas?

P.S. debug manually is unfeasible, since my actual workload has around 5000 calls from 90 different functions.

Edit: OS is Arch Linux 64bit

like image 670
William Avatar asked Oct 29 '25 07:10

William


1 Answers

You can use gdb to track function calls and its returned values using breakpoints 'events' at run-time:

(gdb) help command
Set commands to be executed when a breakpoint is hit.
Give breakpoint number as argument after "commands".
With no argument, the targeted breakpoint is the last one set.
The commands themselves follow starting on the next line.
Type a line containing "end" to indicate the end of them.
Give "silent" as the first line to make the breakpoint silent;
then no output is printed when it is hit, except what the commands print.

Check out my approach:

Source code:

int myfunc( int n )
{
    int val = n * 2;

    return val;
}

int main(void)
{
    int i;

    i = myfunc(10);
    i = myfunc(12);
    i = myfunc(20);

    return 0;
}

1) Compile your program in debug mode with -g option:

$ gcc -g program.c -o program

2) Run gdb:

$ gdb ./program

3) In gdb shell, you can set breakpoints for each function and/or lines you want to trace:

(gdb) break myfunc
Breakpoint 1 at 0x4011d6: file program.c, line 3.

(gdb) break program.c:5
Breakpoint 2 at 0x4011de: file program.c, line 5.

4) Set silent breakpoint events using the silent command:

(gdb) command 1
Type commands for breakpoint(s) 1, one per line.
End with a line saying just "end".
>silent
>printf "calling myfunc( %d )\n", n
>cont
>end

(gdb) command 2
Type commands for breakpoint(s) 2, one per line.
End with a line saying just "end".
>silent
>printf "myfunc return %d\n", val
>cont
>end

5) Run the program:

(gdb) run
Starting program: /home/Administrator/program
[New Thread 192.0xe00]
[New Thread 192.0x55c]
calling myfunc( 10 )
myfunc return 20
calling myfunc( 12 )
myfunc return 24
calling myfunc( 20 )
myfunc return 40
[Inferior 1 (process 192) exited normally]

Obs: gdb reads a script file called .gdbinit when called. This file contain gdb commands to automatically execute during gdb startup and can be used to automate debug operations.

Hope it helps!

like image 147
Lacobus Avatar answered Oct 30 '25 23:10

Lacobus



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!