Using gdb as a monitor?

assembly, gdb

Solution

You can do this sort of thing with the `display` command.

`display/i $pc` will disassemble the current instruction just before the prompt is printed each time:

(gdb) b main
Breakpoint 1 at 0x80483b5: file hw.c, line 5.
(gdb) display/i $pc
(gdb) r
Starting program: /tmp/hw

Breakpoint 1, main () at hw.c:5
5         puts("Hello world");
1: x/i $pc
0x80483b5 <main+17>:    movl   $0x8048490,(%esp)

Now step an instruction (then just keep hitting Enter to repeat):

(gdb) si
0x080483bc      5         puts("Hello world");
1: x/i $pc
0x80483bc <main+24>:    call   0x80482d4 <puts@plt>
(gdb) 
0x080482d4 in puts@plt ()
1: x/i $pc
0x80482d4 <puts@plt>:   jmp    *0x804959c
Current language:  auto; currently asm
(gdb) 
0x080482da in puts@plt ()
1: x/i $pc
0x80482da <puts@plt+6>: push   $0x10
(gdb) 
0x080482df in puts@plt ()
1: x/i $pc
0x80482df <puts@plt+11>:        jmp    0x80482a4 <_init+48>

It still works when we get to this point:

(gdb) 
0x080482a4 in ?? ()
1: x/i $pc
0x80482a4 <_init+48>:   pushl  0x804958c
(gdb) 
0x080482aa in ?? ()
1: x/i $pc
0x80482aa <_init+54>:   jmp    *0x8049590
(gdb) 
0xb7f052d0 in _dl_runtime_resolve () from /lib/ld-linux.so.2
1: x/i $pc
0xb7f052d0 <_dl_runtime_resolve>:       push   %eax

More than one `display` expression can be active at once (use `undisplay <number>` to remove them). For example, to watch what happens to `%eax`:

(gdb) display/x $eax
2: /x $eax = 0xbf90ab34
(gdb) si
0xb7f052d1 in _dl_runtime_resolve () from /lib/ld-linux.so.2
2: /x $eax = 0xbf90ab34
1: x/i $pc
0xb7f052d1 <_dl_runtime_resolve+1>:     push   %ecx
(gdb) 
0xb7f052d2 in _dl_runtime_resolve () from /lib/ld-linux.so.2
2: /x $eax = 0xbf90ab34
1: x/i $pc
0xb7f052d2 <_dl_runtime_resolve+2>:     push   %edx
(gdb) 
0xb7f052d3 in _dl_runtime_resolve () from /lib/ld-linux.so.2
2: /x $eax = 0xbf90ab34
1: x/i $pc
0xb7f052d3 <_dl_runtime_resolve+3>:     mov    0x10(%esp),%edx
(gdb) 
0xb7f052d7 in _dl_runtime_resolve () from /lib/ld-linux.so.2
2: /x $eax = 0xbf90ab34
1: x/i $pc
0xb7f052d7 <_dl_runtime_resolve+7>:     mov    0xc(%esp),%eax

...and here the change in `%eax` can be seen:

(gdb) 
0xb7f052db in _dl_runtime_resolve () from /lib/ld-linux.so.2
2: /x $eax = 0xb7f0d668
1: x/i $pc
0xb7f052db <_dl_runtime_resolve+11>:    call   0xb7eff780 <_dl_fixup>
(gdb) 

Problem

Can GDB be used as if it was a traditional assembly monitor? As soon as you step into eg. library code it returns: ``` No function contains program counter for selected frame ``` GDB the debugger is able to step into unknown code but GDB the UI stops working. In this related question you can find a pair of proposed solutions but neither quite satisfies me. What if the binary library doesn't come with a debugging symbols package? What if the program jumps into run-time generated code? Disassembling the code isn't really a solution either as the UI ignores it, most importantly the values of registers aren't updated until you return to the original known code. `info registers` works, but that is hardly interactive. Any suggestion? Thanks!

Original source

Related problems