20.3.6 Dwarf and traces

If you have the source code of the program you are debugging you can just use the rsc dwarf- helpers to get a source trace of the program. Here's a sample session:

$ nl hello.c
  1  main(int argc, char **argv)
  2  {
  3    int a = 3;
  4    if (a < argc) {
  5      printf("Fuck World\n");
  6    } else {
  7      printf("Hello World\n");
  8    }
  9  }

$ gcc -g hello.c

$ radare -d ./a.out
[0x465D8810]> !cont sym.main
Continue until (sym.main) = 0x08048374
pre-Breakpoint restored 465d8810

[0x465D8810]>
    1   main(int argc, char **argv)
  * 2   {
    3     int a = 3;
    4     if (a < argc) {
    5       printf("Fuck World\n");
    6     } else {

; 0x08048374 DATA xref from 0x08048307 (entrypoint+0x17)
0x08048374,  oeip: lea ecx, [esp+0x4]
0x08048378,   eip: and esp, 0xf0
0x0804837b         push dword [ecx-0x4]
0x0804837e         push ebp
0x0804837f         mov ebp, esp
0x08048381         push ecx
              ; Stack size +20 
0x08048382         sub esp, 0x14
              ; Set var0 
0x08048385         mov dword [ebp-0x8], 0x3 ; eax+0x7
              ; Set var0 
0x0804838c,        mov eax, [ebp-0x8] ; eax+0x7
              ; Get var0 
0x0804838f         cmp eax, [ecx] ; oeax+0xffffff84
0x08048391         jge 0x80483a1  ; 1 = eip+0x29
0x08048393         mov dword [esp], 0x8048480 ; str.Fuck_World
0x0804839a         call 0x80482d4  ; 2 = imp_puts
0x0804839f         jmp 0x80483ad  ; 3 = eip+0x35
0x080483a1         mov dword [esp], 0x804848b ; str.Hello_World
0x080483a8,        call 0x80482d4  ; 4 = imp_puts
              ; Stack size -20 
0x080483ad         add esp, 0x14
0x080483b0,        pop ecx
0x080483b1         pop ebp
0x080483b2         lea esp, [ecx-0x4]
0x080483b5         ret 
0x080483b5      ; ------------------------------------ 

So now we can step until reach the last opcode of sym.main at 0x080483b5:

[0x08048374]> !stepu 0x080483b5
[0x08048374]> at
0x080482d4 - 0x080482da
0x08048374 - 0x08048393
0x080483a1 - 0x080483b2
 ... (library code ) ...

We can get a one-opcode-trace per line by using the 'at*' command:

[0x080483AD]> at*
0x08048374 1 1
0x08048378 1 2
0x0804837b 1 3
0x0804837e 1 4
0x0804837f 1 5
0x08048381 1 6
0x08048382 1 7
0x08048385 1 8
0x0804838c 1 9
0x0804838f 1 10
0x08048391 1 11
0x080483a1 1 12
0x080483a8 1 13
0x080482d4 1 14
...

We're obviously skipping the library opcodes here, because they do not matter too much now..we have no source code for these libs.

With this output we can feed the 'rsc dwarf-traces' command and get a human-readable output.

[0x080483AD]> at* | rsc dwarf-traces $FILE
     2  {
     3    int a = 3;
     4    if (a < argc) {
     7      printf("Hello World\n");

You can modify dwarf-traces to get information about the addr -> file:line from another database and be able to add your own comments here.

You can do the same by using the 'atD' command which is an alias for the previous long command (at*|rsc...).