int gdbr_write_memory(libgdbr_t *g, ut64 address, const uint8_t *data, ut64 len) { int ret = 0; int command_len, pkt, max_cmd_len = 64; ut64 num_pkts, last, data_sz; char *tmp; if (!g || !data) { return -1; } g->stub_features.pkt_sz = R_MAX (g->stub_features.pkt_sz, 64); data_sz = g->stub_features.pkt_sz / 2; if (data_sz < 1) { return -1; } num_pkts = len / data_sz; last = len % data_sz; if (!(tmp = calloc (max_cmd_len + g->stub_features.pkt_sz, sizeof (char)))) { return -1; } for (pkt = num_pkts - 1; pkt >= 0; pkt--) { if ((command_len = snprintf (tmp, max_cmd_len, "%s%016"PFMT64x ",%"PFMT64x ":", CMD_WRITEMEM, address + (pkt * data_sz), data_sz)) < 0) { goto fail; } pack_hex ((char *) data + (pkt * data_sz), data_sz, (tmp + command_len)); if ((ret = send_msg (g, tmp)) < 0) { goto fail; } if ((ret = read_packet (g)) < 0) { goto fail; } if ((ret = handle_M (g)) < 0) { goto fail; } } if (last) { if ((command_len = snprintf (tmp, max_cmd_len, "%s%016"PFMT64x ",%"PFMT64x ":", CMD_WRITEMEM, address + (num_pkts * data_sz), last)) < 0) { goto fail; } pack_hex ((char *) data + (num_pkts * data_sz), last, (tmp + command_len)); if ((ret = send_msg (g, tmp)) < 0) { goto fail; } if ((ret = read_packet (g)) < 0) { goto fail; } if ((ret = handle_M (g)) < 0) { goto fail; } } free (tmp); return 0; fail: free (tmp); return -1; }
int gdbr_open_file(libgdbr_t *g, const char *filename, int flags, int mode) { if (!g || !filename || !*filename) { return -1; } if (g->remote_file_fd >= 0) { eprintf ("%s: Remote file already open\n", __func__); return -1; } char *buf; size_t buf_len = (strlen (filename) * 2) + strlen ("vFile:open:") + 30; if (!(buf = calloc (buf_len, sizeof (char)))) { return -1; } strcpy (buf, "vFile:open:"); pack_hex (filename, strlen (filename), buf + strlen (buf)); snprintf (buf + strlen (buf), buf_len - strlen (buf) - 1, ",%x,%x", flags, mode); if (send_msg (g, buf) < 0) { free (buf); return -1; } read_packet (g); if (handle_vFile_open (g) < 0) { free (buf); return -1; } free (buf); return 0; }
int gdbr_write_registers(libgdbr_t* g, char* registers) { // read current register set gdbr_read_registers(g); int x, len = strlen(registers); char* buff = calloc(len, sizeof(char)); memcpy(buff, registers, len); char* reg = strtok(buff, ","); while ( reg != NULL ) { char* name_end = strchr(reg, '='); if (name_end == NULL) { printf("Malformed argument: %s\n", reg); free(buff); return -1; } *name_end = '\0'; // change '=' to '\0' // time to find the current register int i = 0; while ( g->registers[i].size > 0) { if (strcmp(g->registers[i].name, reg) == 0) { uint64_t register_size = g->registers[i].size; uint64_t offset = g->registers[i].offset; char* value = calloc (register_size * 2, sizeof(char)); memset (value, '0', register_size * 2); name_end++; // be able to take hex with and without 0x if (name_end[1] == 'x' || name_end[1] == 'X') name_end += 2; int val_len = strlen (name_end); // size of the rest strcpy (value+(register_size * 2 - val_len), name_end); for (x=0; x < register_size; x++) { g->data[offset + register_size - x - 1] = hex2char(&value[x * 2]); } free(value); } i++; } reg = strtok(NULL, " ,"); } free(buff); uint64_t buffer_size = g->data_len * 2 + 8; char* command = calloc(buffer_size, sizeof(char)); snprintf (command, buffer_size, "%s", CMD_WRITEREGS); pack_hex (g->data, g->data_len, command+1); send_command (g, command); read_packet (g); free (command); handle_G (g); return 0; }
int gdbr_write_bin_registers(libgdbr_t* g, char* registers) { gdbr_read_registers(g); uint64_t buffer_size = g->data_len * 2 + 8; char* command = calloc(buffer_size, sizeof(char)); snprintf(command, buffer_size, "%s", CMD_WRITEREGS); pack_hex(g->data, g->data_len, command+1); send_command(g, command); free(command); return 0; }
int gdbr_write_register(libgdbr_t* g, int index, char* value, int len) { char command[255] = {}; int ret = snprintf (command, 255, "%s%d=", CMD_WRITEREG, index); memcpy(command + ret, value, len); pack_hex (value, len, (command + ret)); if (send_command (g, command) < 0) return -1; if (read_packet (g) > 0) { parse_packet (g, 0); handle_P (g); } return 0; }
int gdbr_write_bin_registers(libgdbr_t* g){ uint64_t buffer_size = g->data_len * 2 + 8; char* command = calloc (buffer_size, sizeof (char)); if (!command) return -1; snprintf (command, buffer_size, "%s", CMD_WRITEREGS); pack_hex (g->data, g->data_len, command+1); if (send_command (g, command) < 0) return -1; read_packet (g); free (command); handle_G (g); return 0; }
int gdbr_send_qRcmd(libgdbr_t *g, const char *cmd, void (*cb_printf) (const char *fmt, ...)) { if (!g || !cmd) { return -1; } char *buf; size_t len = strlen (cmd) * 2 + 8; if (!(buf = calloc (len, sizeof (char)))) { return -1; } strcpy (buf, "qRcmd,"); g->stop_reason.is_valid = false; reg_cache.valid = false; pack_hex (cmd, strlen (cmd), buf + 6); if (send_msg (g, buf) < 0) { free (buf); return -1; } if (read_packet (g, false) < 0) { free (buf); return -1; } while (1) { if (send_ack (g) < 0) { free (buf); return -1; } if (g->data_len == 0) { free (buf); return -1; } if (g->data_len == 3 && g->data[0] == 'E' && isxdigit (g->data[1]) && isxdigit (g->data[2])) { free (buf); return -1; } if (!strncmp (g->data, "OK", 2)) { free (buf); return 0; } if (g->data[0] == 'O' && g->data_len % 2 == 1) { // Console output from gdbserver unpack_hex (g->data + 1, g->data_len - 1, g->data + 1); g->data[g->data_len - 1] = '\0'; cb_printf ("%s", g->data + 1); } if (read_packet (g, false) < 0) { free (buf); return -1; } } free (buf); return -1; }
int gdbr_send_command(libgdbr_t* g, char* command) { int ret; char* cmd = calloc((strlen(command) * 2 + strlen(CMD_QRCMD) + 2), sizeof(char)); strcpy (cmd, CMD_QRCMD); pack_hex (command, strlen(command), (cmd + strlen(CMD_QRCMD))); ret = send_command (g, cmd); free (cmd); if (ret < 0) return ret; if (read_packet (g) > 0) { parse_packet (g, 1); return handle_cmd (g); } return -1; }
int gdbr_write_memory(libgdbr_t* g, uint64_t address, const uint8_t* data, uint64_t len) { char command[255] = {}; int command_len = snprintf(command, 255, "%s%016"PFMT64x",%"PFMT64d":", CMD_WRITEMEM, address, len); char* tmp = calloc(command_len + (len * 2), sizeof(ut8)); memcpy (tmp, command, command_len); // XXX: we should pack_hex ((char*)data, len, (tmp + command_len)); send_command (g, tmp); free (tmp); if (read_packet (g) > 0) { parse_packet(g, 0); return 0; } return -1; }
int gdbr_write_register(libgdbr_t *g, int index, char *value, int len) { int ret; char command[255] = { 0 }; if (!g) { return -1; } reg_cache.valid = false; ret = snprintf (command, 255, "%s%d=", CMD_WRITEREG, index); memcpy (command + ret, value, len); pack_hex (value, len, (command + ret)); if (send_msg (g, command) < 0) { return -1; } if (read_packet (g) >= 0) { handle_P (g); } return 0; }
int gdbr_write_memory(libgdbr_t* g, uint64_t address, const uint8_t* data, uint64_t len) { int ret = 0; char command[255] = {}; int command_len = snprintf (command, 255, "%s%016lx,%ld:", CMD_WRITEMEM, address, len); char* tmp = calloc (command_len + (len * 2), sizeof (uint8_t)); if (!tmp) return -1; memcpy (tmp, command, command_len); pack_hex ((char*)data, len, (tmp + command_len)); ret = send_command (g, tmp); free (tmp); if (ret < 0) return ret; if (read_packet (g) > 0) { parse_packet (g, 0); return handle_M (g); } return -1; }
int gdbr_write_bin_registers(libgdbr_t *g){ if (!g) { return -1; } reg_cache.valid = false; uint64_t buffer_size = g->data_len * 2 + 8; char *command = calloc (buffer_size, sizeof (char)); if (!command) { return -1; } snprintf (command, buffer_size, "%s", CMD_WRITEREGS); pack_hex (g->data, g->data_len, command + 1); if (send_msg (g, command) < 0) { free (command); return -1; } read_packet (g); free (command); handle_G (g); return 0; }
static int _server_handle_m(libgdbr_t *g, gdbr_server_cmd_cb cmd_cb, void *core_ptr) { int ret; ut64 addr; int length; char *buf1, *buf2, cmd[64]; int buf1_len, buf2_len; if (send_ack (g) < 0) { return -1; } g->data[g->data_len] = 0; sscanf (g->data, "m%"PFMT64x",%d", &addr, &length); if (g->data_len < 4 || !strchr (g->data, ',')) { return send_msg (g, "E01"); } buf1_len = length; buf2_len = length * 2 + 1; if (!(buf1 = malloc (buf1_len))) { return -1; } if (!(buf2 = malloc (buf2_len))) { free (buf1); return -1; } memset (buf2, 0, buf2_len); snprintf (cmd, sizeof (cmd) - 1, "m %"PFMT64x" %d", addr, length); if ((buf1_len = cmd_cb (g, core_ptr, cmd, buf1, buf1_len)) < 0) { free (buf1); free (buf2); send_msg (g, "E01"); return -1; } pack_hex (buf1, buf1_len, buf2); ret = send_msg (g, buf2); free (buf1); free (buf2); return ret; }
int gdbr_write_registers(libgdbr_t *g, char *registers) { uint64_t buffer_size; int ret, i = 0; unsigned int x, len; char *command, *reg, *buff; // read current register set if (!g) { return -1; } gdbr_read_registers (g); reg_cache.valid = false; len = strlen (registers); buff = calloc (len, sizeof (char)); if (!buff) { return -1; } memcpy (buff, registers, len); reg = strtok (buff, ","); while (reg != NULL) { char *name_end = strchr (reg, '='); if (name_end == NULL) { eprintf ("Malformed argument: %s\n", reg); free (buff); return -1; } *name_end = '\0'; // change '=' to '\0' // time to find the current register while (g->registers[i].size > 0) { if (strcmp (g->registers[i].name, reg) == 0) { const ut64 register_size = g->registers[i].size; const ut64 offset = g->registers[i].offset; char *value = calloc (register_size + 1, 2); if (!value) { free (buff); return -1; } memset (value, '0', register_size * 2); name_end++; // be able to take hex with and without 0x if (name_end[1] == 'x' || name_end[1] == 'X') { name_end += 2; } const int val_len = strlen (name_end); // size of the rest strcpy (value + (register_size * 2 - val_len), name_end); for (x = 0; x < register_size; x++) { g->data[offset + register_size - x - 1] = hex2char (&value[x * 2]); } free (value); } i++; } reg = strtok (NULL, " ,"); } free (buff); buffer_size = g->data_len * 2 + 8; command = calloc (buffer_size, sizeof(char)); if (!command) { return -1; } snprintf (command, buffer_size, "%s", CMD_WRITEREGS); pack_hex (g->data, g->data_len, command + 1); ret = send_msg (g, command); if (ret < 0) { free (command); return ret; } read_packet (g); free (command); handle_G (g); return 0; }