Saturday, October 17, 2009

[Level 3] How to use DTrace to trace your program fuction steps.

Sometime when we want to debug our program, we have to verify what's the program real step of function calls. We can use the DTrace to achieve it.

For example (scenario):
1. Create C file /tmp/t.c with following source.
#include <stdio.h>
int f1(int a) {
  f2(a+2);
}

int f2(int b) {
  printf("%d\n", b+3);
}

int main(int argc, char *argv) {

  char a='1';
  f1(a);
}



2. compiler then run it.
# gcc -o /tmp/t /tmp/t.c
# /tmp/t
54
#
When we got the answer 54, why the answer is '54', is rare(we think, 1+2+3, should be '6'). Then we can use DTrace to trace it.

3. write a D-Language script (/tmp/t.d), then change mode with 700.

# cat /tmp/t.d
#!/usr/sbin/dtrace -s
#pragma D option quiet
pid$1:t:f1:entry {
  printf("f1: %d\n", arg0);
}
pid$1:t:f2:entry {
  printf("f2: %d\n", arg0);
}
# chmod 700

4. use mdb to execute the program. (terminal 1)
PS.
_start:b, set breakpoint in _start function
:r, resume it (and the process will stop at breakpoint)
!ps, execute the ps command , then you will the progess pid(2176)
# mdb /tmp/t
> _start:b
> :r
mdb: stop at _start
mdb: target stopped at:
_start:         pushl  $0x0
> !ps
  PID TTY         TIME CMD
 2176 pts/5       0:00 t
 1980 pts/5       0:00 bash
 2175 pts/5       0:00 mdb
 2177 pts/5       0:00 ps

>


5. Open an other terminal(terminal 2), and run DTrace to debug and assign the pid (2176).
# /tmp/t.d 2176

6. In terminal 1, continue the program, then quit mdb.
> :r
54
mdb: target has terminated

> ::quit
#


7. In terminal 2, you will see the result.
# /tmp/t.d 2176
f1: 49
f2: 51

^C


#
The you willsee the f1 was called by argument 49, not 1.
Then when we review the source code,
you will find out, we use the wrong type in main function,
then we correct it.
int main(int argc, char *argv) {
  //char a='1';
  int a=1;
  f1(a);
}

8. Re-compiler the source and run again.
Then it's correct.
# gcc -o /tmp/t /tmp/t.c
# /tmp/t
6
#

Wish this helps.

regards,
Stanley Huang