diff --git a/libr/core/cconfig.c b/libr/core/cconfig.c index a345b68a0f..88fa72297f 100644 --- a/libr/core/cconfig.c +++ b/libr/core/cconfig.c @@ -1013,6 +1013,9 @@ static int cb_dbg_forks(void *user, void *data) { static int cb_dbg_gdb_page_size(void *user, void *data) { RCore *core = (RCore*) user; RConfigNode *node = (RConfigNode*) data; + if (node->i_value < 64) { // 64 is hardcoded min packet size + return false; + } if (core->io && core->io->desc && core->io->desc->plugin && core->io->desc->plugin->name && !strcmp (core->io->desc->plugin->name, "gdb")) { @@ -1023,6 +1026,22 @@ static int cb_dbg_gdb_page_size(void *user, void *data) { return true; } +static int cb_dbg_gdb_retries(void *user, void *data) { + RCore *core = (RCore*) user; + RConfigNode *node = (RConfigNode*) data; + if (node->i_value <= 0) { + return false; + } + if (core->io && core->io->desc && core->io->desc->plugin + && core->io->desc->plugin->name + && !strcmp (core->io->desc->plugin->name, "gdb")) { + char cmd[64]; + snprintf (cmd, sizeof (cmd), "retries %"PFMT64d, node->i_value); + r_io_system (core->io, cmd); + } + return true; +} + static int cb_dbg_execs(void *user, void *data) { RCore *core = (RCore*) user; RConfigNode *node = (RConfigNode*) data; @@ -2410,6 +2429,7 @@ R_API int r_core_config_init(RCore *core) { SETPREF ("dbg.exitkills", "true", "Kill process on exit"); SETPREF ("dbg.exe.path", NULL, "Path to binary being debugged"); SETICB ("dbg.gdb.page_size", 4096, &cb_dbg_gdb_page_size, "Page size on gdb target (useful for QEMU)"); + SETICB ("dbg.gdb.retries", 10, &cb_dbg_gdb_retries, "Number of retries before gdb packet read times out"); SETCB ("dbg.consbreak", "false", &cb_consbreak, "SIGINT handle for attached processes"); r_config_set_getter (cfg, "dbg.swstep", (RConfigCallback)__dbg_swstep_getter); diff --git a/libr/io/p/io_gdb.c b/libr/io/p/io_gdb.c index b99c3c0d27..881c918f78 100644 --- a/libr/io/p/io_gdb.c +++ b/libr/io/p/io_gdb.c @@ -217,24 +217,11 @@ static int __system(RIO *io, RIODesc *fd, const char *cmd) { " =!inv.reg - invalidate reg cache\n" " =!pktsz - get max packet size used\n" " =!pktsz bytes - set max. packet size as 'bytes' bytes\n" - " =!page_size - get current setting for page size\n" - " =!page_size bytes - set page size for memory reads (useful for qemu)\n" " =!exec_file [pid] - get file which was executed for" " current/specified pid\n"); return true; } - if (!strncmp (cmd, "page_size", 9)) { - int page_size; - if (isspace (cmd[9]) && isdigit (cmd[10])) { - if ((page_size = atoi (cmd + 10)) >= 64) { // 64 is hardcoded min packet size - desc->page_size = page_size; - } - return true; - } - io->cb_printf ("page size: %d bytes\n", desc->page_size); - return true; - } - if (!strncmp (cmd, "pktsz", 5)) { + if (r_str_startswith (cmd, "pktsz")) { const char *ptr = r_str_chop_ro (cmd + 5); if (!isdigit (*ptr)) { io->cb_printf ("packet size: %u bytes\n", @@ -249,7 +236,7 @@ static int __system(RIO *io, RIODesc *fd, const char *cmd) { desc->stub_features.pkt_sz = R_MAX (pktsz, 8); // min = 64 return true; } - if (!strncmp (cmd, "detach", 6)) { + if (r_str_startswith (cmd, "detach")) { int pid; if (!isspace (cmd[6]) || !desc->stub_features.multiprocess) { return gdbr_detach (desc) >= 0; @@ -260,7 +247,7 @@ static int __system(RIO *io, RIODesc *fd, const char *cmd) { } return gdbr_detach_pid (desc, pid) >= 0; } - if (!strncmp (cmd, "pkt ", 4)) { + if (r_str_startswith (cmd, "pkt ")) { if (send_msg (desc, cmd + 4) == -1) { return false; } @@ -272,14 +259,14 @@ static int __system(RIO *io, RIODesc *fd, const char *cmd) { } return r >= 0; } - if (!strncmp (cmd, "pid", 3)) { + if (r_str_startswith (cmd, "pid")) { int pid = desc ? desc->pid : -1; if (!cmd[3]) { io->cb_printf ("%d\n", pid); } return pid; } - if (!strncmp (cmd, "monitor", 7)) { + if (r_str_startswith (cmd, "monitor")) { const char *qrcmd = cmd + 8; if (!isspace (cmd[7])) { qrcmd = "help"; @@ -290,7 +277,7 @@ static int __system(RIO *io, RIODesc *fd, const char *cmd) { } return true; } - if (!strncmp (cmd, "inv.reg", 7)) { + if (r_str_startswith (cmd, "inv.reg")) { gdbr_invalidate_reg_cache (); return true; } @@ -321,8 +308,30 @@ static int __system(RIO *io, RIODesc *fd, const char *cmd) { free (file); return true; } - // This is internal, not available to user. Sets a flag that next call to - // get memmap will be for getting baddr + // These are internal, not available to user directly + if (r_str_startswith (cmd, "retries")) { + int num_retries; + if (isspace (cmd[7]) && isdigit (cmd[8])) { + if ((num_retries = atoi (cmd + 8)) >= 1) { + desc->num_retries = num_retries; + } + return true; + } + io->cb_printf ("num_retries: %d bytes\n", desc->page_size); + return true; + } + if (r_str_startswith (cmd, "page_size")) { + int page_size; + if (isspace (cmd[9]) && isdigit (cmd[10])) { + if ((page_size = atoi (cmd + 10)) >= 64) { + desc->page_size = page_size; + } + return true; + } + io->cb_printf ("page size: %d bytes\n", desc->page_size); + return true; + } + // Sets a flag that next call to get memmap will be for getting baddr if (!strcmp (cmd, "baddr")) { desc->get_baddr = true; return true; diff --git a/shlr/gdb/include/libgdbr.h b/shlr/gdb/include/libgdbr.h index d6c05fb185..9dc01da231 100644 --- a/shlr/gdb/include/libgdbr.h +++ b/shlr/gdb/include/libgdbr.h @@ -177,6 +177,7 @@ typedef struct libgdbr_t { libgdbr_stub_features_t stub_features; int remote_file_fd; // For remote file I/O + int num_retries; // number of retries for packet reading int remote_type; bool no_ack; diff --git a/shlr/gdb/src/libgdbr.c b/shlr/gdb/src/libgdbr.c index e4d6ead1c9..c39a96f417 100644 --- a/shlr/gdb/src/libgdbr.c +++ b/shlr/gdb/src/libgdbr.c @@ -18,6 +18,7 @@ int gdbr_init(libgdbr_t *g, bool is_server) { g->send_max = 2500; g->send_buff = (char *) calloc (g->send_max, 1); g->page_size = 4096; + g->num_retries = 10; // safe number, should be ~2.5 seconds if (!g->send_buff) { return -1; } diff --git a/shlr/gdb/src/packet.c b/shlr/gdb/src/packet.c index e46ef216b7..282b001c02 100644 --- a/shlr/gdb/src/packet.c +++ b/shlr/gdb/src/packet.c @@ -141,7 +141,7 @@ static int unpack(libgdbr_t *g, struct parse_ctx *ctx, int len) { int read_packet(libgdbr_t *g, bool vcont) { struct parse_ctx ctx = { 0 }; - int ret; + int ret, i; if (!g) { eprintf ("Initialize libgdbr_t first\n"); return -1; @@ -159,7 +159,7 @@ int read_packet(libgdbr_t *g, bool vcont) { } } g->data_len = 0; - while (1) { + for (i = 0; i < g->num_retries; vcont ? 0 : i++) { ret = r_socket_ready (g->sock, 0, READ_TIMEOUT); if (ret == 0 && !vcont) { continue;