io_gdb: gdb://host:port/pid support; Add gdbr_{attach,detach,detach_pid,kill_pid} to gdbclient. (#7759)

Try to activate extended mode; Attach helper function requires extended mode to actually do something.

Tries to attach to the given pid in io_gdb.
This isn't proper, but it's better than running into the two-pid-vals-no-sync issue.
This commit is contained in:
Adrian Pistol 2017-06-18 00:59:13 +02:00 committed by radare
parent ba1bba5401
commit d8f5cdb11c
9 changed files with 219 additions and 20 deletions

View File

@ -206,9 +206,7 @@ static int r_debug_gdb_attach(RDebug *dbg, int pid) {
}
static int r_debug_gdb_detach(RDebug *dbg, int pid) {
gdbr_disconnect (desc);
free (reg_buf);
return true;
return gdbr_detach_pid (desc, pid);
}
static const char *r_debug_gdb_reg_profile(RDebug *dbg) {

View File

@ -75,7 +75,7 @@ static int debug_gdb_write_at(const ut8 *buf, int sz, ut64 addr) {
static RIODesc *__open(RIO *io, const char *file, int rw, int mode) {
RIOGdb *riog;
char host[128], *port, *p;
char host[128], *port, *pid;
if (!__plugin_open (io, file, 0))
return NULL;
@ -87,13 +87,17 @@ static RIODesc *__open(RIO *io, const char *file, int rw, int mode) {
host [sizeof (host)-1] = '\0';
port = strchr (host , ':');
if (!port) {
eprintf ("Port not specified. Please use gdb://[host]:[port]\n");
eprintf ("Port not specified. Please use gdb://host:port[/port]\n");
return NULL;
}
*port = '\0';
port++;
p = strchr (port, '/');
if (p) *p = 0;
pid = strchr (port, '/');
if (pid) {
*pid = 0;
pid++;
}
if (r_sandbox_enable (0)) {
eprintf ("sandbox: Cannot use network\n");
@ -102,8 +106,18 @@ static RIODesc *__open(RIO *io, const char *file, int rw, int mode) {
riog = R_NEW0 (RIOGdb);
gdbr_init (&riog->desc, false);
int i_port = atoi(port);
int i_pid = -1;
if (pid)
i_pid = atoi(pid);
if (gdbr_connect (&riog->desc, host, i_port) == 0) {
desc = &riog->desc;
desc->pid = i_pid;
if (pid) { // FIXME this is here for now because RDebug's pid and libgdbr's aren't properly synced.
int ret = gdbr_attach (desc, i_pid);
if (ret < 0)
eprintf ("gdbr: Failed to attach to PID %i\n", i_pid);
}
riogdb = r_io_desc_new (&r_io_plugin_gdb, riog->desc.sock->fd, file, rw, mode, riog);
return riogdb;
}

View File

@ -19,12 +19,34 @@ int gdbr_connect(libgdbr_t *g, const char *server, int port);
*/
int gdbr_disconnect(libgdbr_t *g);
/*!
* \brief checks for extended mode availability
* \returns a failure code (currently -1) or 0 if call successfully
*/
int gdbr_check_extended_mode(libgdbr_t *g);
/*!
* \brief attaches to a process
* \param pid of the process to attach to
* \returns a failure code (currently -1) or 0 if call successfully
*/
int gdbr_attach(libgdbr_t *g, int pid);
/*!
* \brief detaches from a process
* \param pid of the process to detach from (only the multiprocess/pid variant)
* \returns a failure code (currently -1) or 0 if call successfully
*/
int gdbr_detach(libgdbr_t *g);
int gdbr_detach_pid(libgdbr_t *g, int pid);
/*!
* \brief kills the process the remote gdbserver is debugging (TODO: handle pid)
* \param pid of the process to detach from (only the multiprocess/pid variant)
* \retuns a failure code (currently -1) or 0 if call successfully
*/
bool gdbr_kill(libgdbr_t *g);
bool gdbr_kill_pid(libgdbr_t *g, int pid);
// Commands
int gdbr_continue(libgdbr_t *g, int thread_id);

View File

@ -13,6 +13,10 @@
#include "../utils.h"
#include "../arch.h"
#define CMD_ATTACH "vAttach;"
#define CMD_DETACH_MP "D;"
#define CMD_KILL_MP "vKill;"
#define CMD_READREGS "g"
#define CMD_WRITEREGS "G"
#define CMD_READREG "p"

View File

@ -28,5 +28,6 @@ int handle_fstat(libgdbr_t* g);
int handle_qSupported(libgdbr_t* g);
int handle_setbp(libgdbr_t* g);
int handle_removebp(libgdbr_t* g);
int handle_attach(libgdbr_t* g);
#endif // RESPONSES_H

View File

@ -83,6 +83,8 @@ typedef struct libgdbr_stub_features_t {
bool BreakpointCommands;
// Cannot be determined with qSupported, found out on query
bool qC;
bool extended_mode;
} libgdbr_stub_features_t;
/*!

View File

@ -139,6 +139,9 @@ int gdbr_connect(libgdbr_t *g, const char *host, int port) {
if (strncmp (g->data, "OK", 2)) {
// return -1;
}
gdbr_check_extended_mode (g);
return ret;
}
@ -151,26 +154,170 @@ int gdbr_disconnect(libgdbr_t *g) {
return 0;
}
bool gdbr_kill(libgdbr_t *g) {
char buf[20];
int gdbr_check_extended_mode(libgdbr_t *g) {
int ret;
// Activate extended mode if possible.
ret = send_msg (g, "!");
if (ret < 0) {
g->stub_features.extended_mode = false;
return ret;
}
read_packet (g);
ret = send_ack (g);
if (strncmp (g->data, "OK", 2)) {
g->stub_features.extended_mode = false;
return -1;
}
g->stub_features.extended_mode = true;
return 0;
}
int gdbr_attach(libgdbr_t *g, int pid) {
int ret;
char *cmd;
size_t buffer_size;
if (!g || !g->sock || !g->stub_features.multiprocess) {
return -1;
}
if (!g->stub_features.extended_mode) {
// vAttach needs extended mode to do anything.
return -2;
}
buffer_size = strlen (CMD_ATTACH) + (sizeof (int) * 2) + 1;
cmd = calloc (buffer_size, sizeof (char));
if (!cmd) {
return -1;
}
ret = snprintf (cmd, buffer_size, "%s%x", CMD_ATTACH, pid);
if (ret < 0) {
free(cmd);
return ret;
}
ret = send_msg (g, cmd);
free(cmd);
if (ret < 0) {
return ret;
}
if (read_packet (g) >= 0) {
return handle_attach (g);
}
return -1;
}
int gdbr_detach(libgdbr_t *g) {
int ret;
if (!g || !g->sock) {
return -1;
}
if (g->stub_features.multiprocess) {
if (!g->pid) {
return -1;
}
return gdbr_detach_pid (g, g->pid);
}
ret = send_msg (g, "D");
if (ret < 0) {
return -1;
}
return 0;
}
int gdbr_detach_pid(libgdbr_t *g, int pid) {
char *cmd;
int ret;
size_t buffer_size;
if (!g || !g->sock || !g->stub_features.multiprocess) {
return -1;
}
buffer_size = strlen (CMD_DETACH_MP) + (sizeof (pid) * 2) + 1;
cmd = calloc(buffer_size, sizeof (char));
if (!cmd) {
return -1;
}
if ((snprintf (cmd, buffer_size, "%s%x", CMD_DETACH_MP, g->pid)) < 0) {
free(cmd);
return -1;
}
ret = send_msg (g, cmd);
free(cmd);
if (ret < 0) {
return ret;
}
read_packet (g);
if ((ret = send_ack (g)) < 0) {
return ret;
}
if (strncmp (g->data, "OK", 2)) {
return -1;
}
return 0;
}
bool gdbr_kill(libgdbr_t *g) {
int ret;
if (!g || g->sock) {
return false;
}
if (g->stub_features.multiprocess) {
if (!g->pid) {
return false;
}
snprintf (buf, sizeof (buf) - 1, "vKill;%x", g->pid);
} else {
snprintf (buf, sizeof (buf) - 1, "k");
return gdbr_kill_pid (g, g->pid);
}
if ((ret = send_msg (g, buf)) < 0) {
ret = send_msg (g, "k");
if (ret < 0) {
return false;
}
if (!g->stub_features.multiprocess) {
return true;
return true;
}
bool gdbr_kill_pid(libgdbr_t *g, int pid) {
char *cmd;
int ret;
size_t buffer_size;
if (!g || !g->sock || !g->stub_features.multiprocess) {
return false;
}
buffer_size = strlen(CMD_KILL_MP) + (sizeof(pid) * 2) + 1;
cmd = calloc(buffer_size, sizeof (char));
if (!cmd) {
return false;
}
if ((snprintf (cmd, buffer_size, "%s%x", CMD_KILL_MP, g->pid)) < 0) {
free(cmd);
return false;
}
ret = send_msg (g, cmd);
free(cmd);
if (ret < 0) {
return false;
}
read_packet (g);
if ((ret = send_ack (g)) < 0) {
return false;

View File

@ -170,3 +170,11 @@ int handle_setbp(libgdbr_t *g) {
int handle_removebp(libgdbr_t *g) {
return send_ack (g);
}
int handle_attach(libgdbr_t *g) {
if (g->data_len == 3 && g->data[0] == 'E') {
send_ack (g);
return -1;
}
return send_ack (g);
}

View File

@ -1,5 +1,8 @@
#!/bin/sh
# Requires GNU Make, but some distros probably don't have the gmake symlink.
[ -z "$MAKE" ] && MAKE=make
while : ; do
if [ -f sys/rebuild.sh ]; then
break
@ -13,14 +16,14 @@ done
Rebuild() {
cd "$1" || exit 1
make clean
make -j8 || exit 1
$MAKE clean
$MAKE -j8 || exit 1
cd -
}
Build() {
cd "$1" || exit 1
make -j8 || exit 1
$MAKE -j8 || exit 1
cd -
}
@ -29,7 +32,7 @@ RebuildIOSDebug() {
# Rebuild libr/util
# Rebuild libr/core
Rebuild binr/radare2
make -C binr/radare2 ios-sign
$MAKE -C binr/radare2 ios-sign
if [ -n "${IOSIP}" ]; then
scp binr/radare2/radare2 root@"${IOSIP}:."
else