From f64f2211fb34add52e8d47c1835ac3329731e381 Mon Sep 17 00:00:00 2001 From: yossizap Date: Tue, 14 Jan 2020 22:46:07 +0000 Subject: [PATCH] Added reverse step and continue support to gdbr ##debug This feature only works with server implementations that have ReverseStep and ReverseContinue enabled, such as rr. The official gdbserver doesn't support it. --- libr/io/p/io_gdb.c | 59 +++++++++++++++++++++++++++++++++++++++++++ shlr/gdb/src/common.c | 4 +++ 2 files changed, 63 insertions(+) diff --git a/libr/io/p/io_gdb.c b/libr/io/p/io_gdb.c index e8d36a7ac4..6fda08faaa 100644 --- a/libr/io/p/io_gdb.c +++ b/libr/io/p/io_gdb.c @@ -216,6 +216,9 @@ static char *__system(RIO *io, RIODesc *fd, const char *cmd) { eprintf ("Usage: =!cmd args\n" " =!pid - show targeted pid\n" " =!pkt s - send packet 's'\n" + " =!rd - show reverse debugging availability\n" + " =!dsb - step backwards\n" + " =!dcb - continue backwards\n" " =!monitor cmd - hex-encode monitor command and pass" " to target interpreter\n" " =!detach [pid] - detach from remote/detach specific pid\n" @@ -270,6 +273,62 @@ static char *__system(RIO *io, RIODesc *fd, const char *cmd) { gdbr_lock_leave (desc); return NULL; } + if (r_str_startswith (cmd, "rd")) { + PJ *pj = pj_new (); + pj_o (pj); + pj_kb (pj, "reverse-continue", desc->stub_features.ReverseStep); + pj_kb (pj, "reverse-step", desc->stub_features.ReverseContinue); + pj_end (pj); + io->cb_printf ("%s\n", pj_string (pj)); + pj_free (pj); + return NULL; + } + if (r_str_startswith (cmd, "dsb")) { + if (!desc->stub_features.ReverseStep) { + eprintf ("Stepping backwards is not supported in this gdbserver implementation\n"); + return NULL; + } + gdbr_lock_enter (desc); + if (send_msg (desc, "bs") >= 0) { + (void)read_packet (desc); + desc->data[desc->data_len] = '\0'; + if (!desc->no_ack) { + eprintf ("[waiting for ack]\n"); + } else { + handle_stop_reason (desc); + if (desc->stop_reason.is_valid == false) { + eprintf("Thread (%d) stopped for an invalid reason: %d\n", + desc->stop_reason.thread, desc->stop_reason.reason); + } + } + gdbr_invalidate_reg_cache (); + } + gdbr_lock_leave (desc); + return NULL; + } + if (r_str_startswith (cmd, "dcb")) { + if (!desc->stub_features.ReverseContinue) { + eprintf ("Continue backwards is not supported in this gdbserver implementation\n"); + return NULL; + } + gdbr_lock_enter (desc); + if (send_msg (desc, "bc") >= 0) { + (void)read_packet (desc); + desc->data[desc->data_len] = '\0'; + if (!desc->no_ack) { + eprintf ("[waiting for ack]\n"); + } else { + handle_stop_reason (desc); + if (desc->stop_reason.is_valid == false) { + eprintf("Thread (%d) stopped for an invalid reason: %d\n", + desc->stop_reason.thread, desc->stop_reason.reason); + } + } + gdbr_invalidate_reg_cache (); + } + gdbr_lock_leave (desc); + return NULL; + } if (r_str_startswith (cmd, "pid")) { int pid = desc ? desc->pid : -1; if (!cmd[3]) { diff --git a/shlr/gdb/src/common.c b/shlr/gdb/src/common.c index 20e0b3cf97..65bc121020 100644 --- a/shlr/gdb/src/common.c +++ b/shlr/gdb/src/common.c @@ -113,6 +113,10 @@ int handle_qSupported(libgdbr_t *g) { } else if (r_str_startswith (tok, "qEcho")) { g->remote_type = GDB_REMOTE_TYPE_LLDB; g->stub_features.lldb.qEcho = (tok[strlen ("qEcho")] == '+'); + } else if (r_str_startswith (tok, "ReverseStep")) { + g->stub_features.ReverseStep = (tok[strlen ("ReverseStep")] == '+'); + } else if (r_str_startswith (tok, "ReverseContinue")) { + g->stub_features.ReverseContinue = (tok[strlen ("ReverseContinue")] == '+'); } // TODO tok = strtok (NULL, ";");