static unsigned short gdb_port;
+enum gdb_detach_mode
+{
+ GDB_DETACH_RESUME,
+ GDB_DETACH_RESET,
+ GDB_DETACH_HALT,
+ GDB_DETACH_NOTHING
+};
+
+enum gdb_detach_mode detach_mode = GDB_DETACH_RESUME;
+
int gdb_last_signal(target_t *target)
{
switch (target->debug_reason)
while (1)
{
-
debug_buffer = malloc(len + 1);
memcpy(debug_buffer, buffer, len);
debug_buffer[len] = 0;
return ERROR_OK;
}
-void gdb_query_packet(connection_t *connection, char *packet, int packet_size)
+int gdb_query_packet(connection_t *connection, target_t *target, char *packet, int packet_size)
{
command_context_t *cmd_ctx = connection->cmd_ctx;
free(cmd);
}
gdb_put_packet(connection, "OK", 2);
- return;
+ return ERROR_OK;
}
+ if (strstr(packet, "qCRC:"))
+ {
+ if (packet_size > 5)
+ {
+ int retval;
+ u8 gdb_reply[9];
+ char *separator;
+ u32 checksum;
+ u32 addr = 0;
+ u32 len = 0;
+
+ /* skip command character */
+ packet += 5;
+
+ addr = strtoul(packet, &separator, 16);
+
+ if (*separator != ',')
+ {
+ ERROR("incomplete read memory packet received, dropping connection");
+ return ERROR_SERVER_REMOTE_CLOSED;
+ }
+
+ len = strtoul(separator+1, NULL, 16);
+
+ retval = target_checksum_memory(target, addr, len, &checksum);
+
+ if (retval == ERROR_OK)
+ {
+ snprintf(gdb_reply, 9, "C%2.2x", checksum);
+ gdb_put_packet(connection, gdb_reply, 9);
+ }
+ else
+ {
+ if ((retval = gdb_memory_packet_error(connection, retval)) != ERROR_OK)
+ return retval;
+ }
+
+ return ERROR_OK;
+ }
+ }
+
gdb_put_packet(connection, "", 0);
+ return ERROR_OK;
}
int gdb_v_packet(connection_t *connection, target_t *target, char *packet, int packet_size)
if (!strcmp(packet, "vFlashDone"))
{
- u32 image_size;
+ u32 written;
char *error_str;
- u32 *failed = malloc(sizeof(u32) * gdb_connection->vflash_image->num_sections);
-
+
/* process the flashing buffer */
- if ((result = flash_write(gdb_service->target, gdb_connection->vflash_image, &image_size, &error_str, failed)) != ERROR_OK)
+ if ((result = flash_write(gdb_service->target, gdb_connection->vflash_image, &written, &error_str, NULL, 0)) != ERROR_OK)
{
if (result == ERROR_FLASH_DST_OUT_OF_BANK)
gdb_put_packet(connection, "E.memtype", 9);
else
gdb_send_error(connection, EIO);
- ERROR("flash writing failed: %s", error_str);
- free(error_str);
+ if (error_str)
+ {
+ ERROR("flash writing failed: %s", error_str);
+ free(error_str);
+ }
}
else
{
- DEBUG("wrote %u bytes from vFlash image to flash", image_size);
+ DEBUG("wrote %u bytes from vFlash image to flash", written);
gdb_put_packet(connection, "OK", 2);
}
- free(failed);
-
image_close(gdb_connection->vflash_image);
free(gdb_connection->vflash_image);
gdb_connection->vflash_image = NULL;
return ERROR_OK;
}
+int gdb_detach(connection_t *connection, target_t *target)
+{
+ switch( detach_mode )
+ {
+ case GDB_DETACH_RESUME:
+ target->type->resume(target, 1, 0, 1, 0);
+ break;
+
+ case GDB_DETACH_RESET:
+ target_process_reset(connection->cmd_ctx);
+ break;
+
+ case GDB_DETACH_HALT:
+ target->type->halt(target);
+ break;
+
+ case GDB_DETACH_NOTHING:
+ break;
+ }
+
+ gdb_put_packet(connection, "OK", 2);
+
+ return ERROR_OK;
+}
+
int gdb_input(connection_t *connection)
{
gdb_service_t *gdb_service = connection->service->priv;
/* terminate with zero */
packet[packet_size] = 0;
- DEBUG("recevied packet: '%s'", packet);
+ DEBUG("received packet: '%s'", packet);
if (packet_size > 0)
{
gdb_put_packet(connection, NULL, 0);
break;
case 'q':
- gdb_query_packet(connection, packet, packet_size);
+ retval = gdb_query_packet(connection, target, packet, packet_size);
break;
case 'g':
retval = gdb_get_registers_packet(connection, target, packet, packet_size);
retval = gdb_v_packet(connection, target, packet, packet_size);
break;
case 'D':
- target->type->resume(target, 1, 0, 1, 0);
- gdb_put_packet(connection, "OK", 2);
+ retval = gdb_detach(connection, target);
break;
case 'X':
if ((retval = gdb_write_memory_binary_packet(connection, target, packet, packet_size)) != ERROR_OK)
return ERROR_OK;
}
+int handle_gdb_detach_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+ if (argc == 1)
+ {
+ if (strcmp(args[0], "resume") == 0)
+ {
+ detach_mode = GDB_DETACH_RESUME;
+ return ERROR_OK;
+ }
+ else if (strcmp(args[0], "reset") == 0)
+ {
+ detach_mode = GDB_DETACH_RESET;
+ return ERROR_OK;
+ }
+ else if (strcmp(args[0], "halt") == 0)
+ {
+ detach_mode = GDB_DETACH_HALT;
+ return ERROR_OK;
+ }
+ else if (strcmp(args[0], "nothing") == 0)
+ {
+ detach_mode = GDB_DETACH_NOTHING;
+ return ERROR_OK;
+ }
+ }
+
+ WARNING("invalid gdb_detach configuration directive: %s", args[0]);
+ return ERROR_OK;
+}
+
int gdb_register_commands(command_context_t *command_context)
{
register_command(command_context, NULL, "gdb_port", handle_gdb_port_command,
COMMAND_CONFIG, "");
-
+ register_command(command_context, NULL, "gdb_detach", handle_gdb_detach_command,
+ COMMAND_CONFIG, "");
+
return ERROR_OK;
}