static int _server_handle_qSupported(libgdbr_t *g) { int ret; char *buf; if (!(buf = malloc (128))) { return -1; } snprintf (buf, 127, "PacketSize=%x", g->read_max - 1); ret = handle_qSupported (g); if (ret < 0) { return ret; } return send_msg (g, buf); }
static int _server_handle_qSupported(libgdbr_t *g) { int ret; char *buf; if (!(buf = malloc (128))) { return -1; } snprintf (buf, 127, "PacketSize=%x;QStartNoAckMode+", (ut32) (g->read_max - 1)); if ((ret = handle_qSupported (g)) < 0) { return -1; } ret = send_msg (g, buf); free (buf); return ret; }
int gdbr_connect(libgdbr_t *g, const char *host, int port) { const char *message = "qSupported:multiprocess+;qRelocInsn+;xmlRegisters=i386"; RStrBuf tmp; r_strbuf_init (&tmp); int ret; if (!g || !host) { return -1; } // Initial max_packet_size for remote target (minimum so far for AVR = 64) g->stub_features.pkt_sz = 64; char *env_pktsz_str; ut32 env_pktsz; if ((env_pktsz_str = getenv ("R2_GDB_PKTSZ"))) { if ((env_pktsz = (ut32) strtoul (env_pktsz_str, NULL, 10))) { g->stub_features.pkt_sz = R_MAX (env_pktsz, 64); } } ret = snprintf (tmp.buf, sizeof (tmp.buf) - 1, "%d", port); if (!ret) { return -1; } if (*host == '/') { ret = r_socket_connect_serial (g->sock, host, port, 1); } else { ret = r_socket_connect_tcp (g->sock, host, tmp.buf, 200); } if (!ret) { return -1; } if (send_ack (g) < 0) { return -1; } read_packet (g); g->connected = 1; // TODO add config possibility here ret = send_msg (g, message); if (ret < 0) { return ret; } read_packet (g); ret = handle_qSupported (g); if (ret < 0) { return ret; } if (env_pktsz > 0) { g->stub_features.pkt_sz = R_MAX (R_MIN (env_pktsz, g->stub_features.pkt_sz), 64); } // If no-ack supported, enable no-ack mode (should speed up things) if (g->stub_features.QStartNoAckMode) { if (send_msg (g, "QStartNoAckMode") < 0) { return -1; } read_packet (g); if (!strncmp (g->data, "OK", 2)) { // Just in case, send ack send_ack (g); g->no_ack = true; } } if (g->remote_type == GDB_REMOTE_TYPE_LLDB) { return gdbr_connect_lldb (g); } // Query the thread / process id g->stub_features.qC = true; g->pid = g->tid = 0; ret = send_msg (g, "qC"); if (ret < 0) { return ret; } read_packet (g); ret = handle_qC (g); if (ret < 0) { g->stub_features.qC = false; } // Check if vCont is supported gdbr_check_vcont (g); // Set pid/thread for operations other than "step" and "continue" if (g->stub_features.multiprocess) { snprintf (tmp.buf, sizeof (tmp.buf) - 1, "Hgp%x.0", (ut32) g->pid); #if 0 if (g->tid < 0) { snprintf (tmp.buf, sizeof (tmp.buf) - 1, "Hgp%x.-1", (ut32) g->pid); } else { snprintf (tmp.buf, sizeof (tmp.buf) - 1, "Hgp%x.%x", (ut32) g->pid, (ut32) g->tid); } #endif } else { snprintf (tmp.buf, sizeof (tmp.buf) - 1, "Hg0"); #if 0 if (g->tid < 0) { snprintf (tmp.buf, sizeof (tmp.buf) - 1, "Hg-1"); } else { snprintf (tmp.buf, sizeof (tmp.buf) - 1, "Hg%x", (ut32) g->tid); } #endif } ret = send_msg (g, tmp.buf); if (ret < 0) { return ret; } read_packet (g); ret = send_ack (g); if (strncmp (g->data, "OK", 2)) { // return -1; } // Set thread for "step" and "continue" operations snprintf (tmp.buf, sizeof (tmp.buf) - 1, "Hc-1"); ret = send_msg (g, tmp.buf); if (ret < 0) { return ret; } read_packet (g); ret = send_ack (g); if (strncmp (g->data, "OK", 2)) { // return -1; } if (g->stub_features.qXfer_features_read) { gdbr_read_target_xml (g); } reg_cache_init (g); return ret; }