radareorg / radare2

UNIX-like reverse engineering framework and command-line toolset
https://www.radare.org/
GNU Lesser General Public License v3.0
20.66k stars 3k forks source link

gdbserver reverse continue/step support #8966

Open Manouchehri opened 6 years ago

Manouchehri commented 6 years ago
vagrant@vagrant:~$ r2 -D gdb gdb://127.0.0.1:4444 `which curl`
= attach 6371 1
= attach 6371 0
 -- Get a free shell with 'ragg2 -i exec -x'
[0x00006dc0]> dc
= attach 6371 0
[+] signal 9 aka SIGKILL received 0
[0x70000002]> dcb
cannot continue back
[0x70000002]>
vagrant@vagrant:~$ r2 -D gdb gdb://127.0.0.1:4444 `which curl`
= attach 6371 1
= attach 6371 0
 -- Run .dmm* to load the flags of the symbols of all modules loaded in the debugger
[0x00006dc0]> ds 16
= attach 6371 6371
[0x7f4c386849d6]> dsb
cannot step back

Example session with gdb:

vagrant@vagrant:~$ gdb -q `which curl`
Reading symbols from /usr/bin/curl...(no debugging symbols found)...done.
(gdb) target remote localhost:4444
Remote debugging using localhost:4444
0x00007f4c38683c30 in ?? ()
(gdb) c
Continuing.

Program received signal SIGKILL, Killed.
0x0000000070000002 in ?? ()
(gdb) rc
Continuing.

Program stopped.
0x00007f4c38683c30 in ?? ()
(gdb) c
Continuing.

Program received signal SIGKILL, Killed.
0x0000000070000002 in ?? ()
(gdb) rsi 1
0x00007f4c3845a3ed in ?? ()
(gdb) si
0x0000000070000000 in ?? ()
(gdb) rsi 16
0x00007f4c38456be3 in ?? ()
radare commented 6 years ago

The gdb thing doesnt works like that but the crash must be fixed

On 6 Dec 2017, at 00:46, David Manouchehri notifications@github.com wrote:

vagrant@vagrant:~$ r2 -D gdb gdb://127.0.0.1:4444 which curl = attach 6371 1 = attach 6371 0 -- Get a free shell with 'ragg2 -i exec -x' [0x00006dc0]> dc = attach 6371 0 [+] signal 9 aka SIGKILL received 0 [0x70000002]> dcb cannot continue back [0x70000002]> vagrant@vagrant:~$ r2 -D gdb gdb://127.0.0.1:4444 which curl = attach 6371 1 = attach 6371 0 -- Run .dmm* to load the flags of the symbols of all modules loaded in the debugger [0x00006dc0]> ds 16 = attach 6371 6371 [0x7f4c386849d6]> dsb cannot step back Example session with gdb:

vagrant@vagrant:~$ gdb -q which curl Reading symbols from /usr/bin/curl...(no debugging symbols found)...done. (gdb) target remote localhost:4444 Remote debugging using localhost:4444 0x00007f4c38683c30 in ?? () (gdb) c Continuing.

Program received signal SIGKILL, Killed. 0x0000000070000002 in ?? () (gdb) rc Continuing.

Program stopped. 0x00007f4c38683c30 in ?? () (gdb) c Continuing.

Program received signal SIGKILL, Killed. 0x0000000070000002 in ?? () (gdb) rsi 1 0x00007f4c3845a3ed in ?? () (gdb) si 0x0000000070000000 in ?? () (gdb) rsi 16 0x00007f4c38456be3 in ?? () — You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or mute the thread.

Manouchehri commented 6 years ago

The SIGKILL is expected. The remote gdb-server target is being provided by mozilla/rr.

XVilka commented 6 years ago

@radare no, it's just a matter of supporting reverse debugging in gdb protocol, and connecting it with reverse step/continue commands.

yossizap commented 4 years ago

no, it's just a matter of supporting reverse debugging in gdb protocol, and connecting it with reverse step/continue commands

@XVilka why should r2 depend on gdbserver's record implementation, which isn't always available, when it's possible to simply set the state from r2's history as in any other debugger?

It seems that a wrong implementation/usage of gdbserver's 'G' (write registers) is the issue. Currently looking into this.

For reference, gdbserver's output after r_debug_session_set: gdbserver: Wrong sized register packet (expected 1792 bytes, got 4) Printed by registers_from_string which is called by gdb/gdbserver/server.c's command parsing loop.

XVilka commented 4 years ago

@yossizap it's not a requirement. Whatever works best. Thanks for working on this! 💯

yossizap commented 4 years ago

Solved the reg writing protocol issue in #15455 but it still doesn't work since r_reg_next_diff which is iterated on by r_debug_write_reg only returns rax and orig_rax, other registers can't be found in r_reg_get_at due to size and offset mismatches. Tried simply writing buf with gdbr_write_bin_registers(changed args to receive buf and len instead of taking it from g->data), as other debuggers do, but it wrote lots of wrong values instead. This seems very weird to me since afaik, that buf should be the same buf that read_regs returned, which is exactly how gdbr_write_reg does it.

I am probably missing something so I would appreciate some clues. Also seems that gdbr and qnx are the only ones using r_reg_next_diff, could be outdated? dr doesn't seem to have an issue finding the delta between commands but it compares two reg lists while dreg.c still uses bufs.

yossizap commented 4 years ago

Solved the previous issue but dsb is partially broken and dcb has issues when stepping back multiple times in a row, could be a limit on session size?

radare commented 4 years ago

fixed in master

XVilka commented 4 years ago

Not completely - see the PR description, it supports only RR, but not the rest.

yossizap commented 4 years ago

*RR and any other gdbserver with ReverseContinue and ReverseStep, could also work with r2 gdbserver etc.

For proper reverse debug with regular gdbserver we'll need to do it on r2's side by fixing dsb/dcb.