/* set if we are sending target descriptions to gdb
* via qXfer:features:read packet */
-/* disabled by default */
-static int gdb_use_target_description;
+/* enabled by default */
+static int gdb_use_target_description = 1;
/* current processing free-run type, used by file-I/O */
static char gdb_running_type;
int sig_reply_len;
int signal_var;
- if (gdb_connection->ctrl_c) {
- signal_var = 0x2;
- gdb_connection->ctrl_c = 0;
- } else
- signal_var = gdb_last_signal(target);
+ if (target->debug_reason == DBG_REASON_EXIT) {
+ sig_reply_len = snprintf(sig_reply, sizeof(sig_reply), "W00");
+ } else {
+ if (gdb_connection->ctrl_c) {
+ signal_var = 0x2;
+ gdb_connection->ctrl_c = 0;
+ } else
+ signal_var = gdb_last_signal(target);
- stop_reason[0] = '\0';
- if (target->debug_reason == DBG_REASON_WATCHPOINT) {
- enum watchpoint_rw hit_wp_type;
- uint32_t hit_wp_address;
+ stop_reason[0] = '\0';
+ if (target->debug_reason == DBG_REASON_WATCHPOINT) {
+ enum watchpoint_rw hit_wp_type;
+ uint32_t hit_wp_address;
- if (watchpoint_hit(target, &hit_wp_type, &hit_wp_address) == ERROR_OK) {
+ if (watchpoint_hit(target, &hit_wp_type, &hit_wp_address) == ERROR_OK) {
- switch (hit_wp_type) {
- case WPT_WRITE:
- snprintf(stop_reason, sizeof(stop_reason),
- "watch:%08x;", hit_wp_address);
- break;
- case WPT_READ:
- snprintf(stop_reason, sizeof(stop_reason),
- "rwatch:%08x;", hit_wp_address);
- break;
- case WPT_ACCESS:
- snprintf(stop_reason, sizeof(stop_reason),
- "awatch:%08x;", hit_wp_address);
- break;
- default:
- break;
+ switch (hit_wp_type) {
+ case WPT_WRITE:
+ snprintf(stop_reason, sizeof(stop_reason),
+ "watch:%08x;", hit_wp_address);
+ break;
+ case WPT_READ:
+ snprintf(stop_reason, sizeof(stop_reason),
+ "rwatch:%08x;", hit_wp_address);
+ break;
+ case WPT_ACCESS:
+ snprintf(stop_reason, sizeof(stop_reason),
+ "awatch:%08x;", hit_wp_address);
+ break;
+ default:
+ break;
+ }
}
}
- }
- sig_reply_len = snprintf(sig_reply, sizeof(sig_reply), "T%2.2x%s",
- signal_var, stop_reason);
+ sig_reply_len = snprintf(sig_reply, sizeof(sig_reply), "T%2.2x%s",
+ signal_var, stop_reason);
+ }
gdb_put_packet(connection, sig_reply, sig_reply_len);
gdb_connection->frontend_state = TARGET_HALTED;
{
int retval;
struct connection *connection = priv;
+ struct gdb_service *gdb_service = connection->service->priv;
+
+ if (gdb_service->target != target)
+ return ERROR_OK;
switch (event) {
case TARGET_EVENT_GDB_HALT:
gdb_connection->closed = 0;
gdb_connection->busy = 0;
gdb_connection->noack_mode = 0;
- gdb_connection->sync = true;
+ gdb_connection->sync = false;
gdb_connection->mem_write_error = false;
gdb_connection->attached = true;
static const char *gdb_get_reg_type_name(enum reg_type type)
{
switch (type) {
+ case REG_TYPE_INT:
+ return "int";
case REG_TYPE_INT8:
return "int8";
case REG_TYPE_INT16:
return "code_ptr";
case REG_TYPE_DATA_PTR:
return "data_ptr";
+ case REG_TYPE_FLOAT:
+ return "float";
case REG_TYPE_IEEE_SINGLE:
return "ieee_single";
case REG_TYPE_IEEE_DOUBLE:
return ERROR_OK;
}
+static int gdb_target_description_supported(struct target *target, int *supported)
+{
+ int retval = ERROR_OK;
+ struct reg **reg_list = NULL;
+ int reg_list_size = 0;
+ int feature_list_size = 0;
+
+ retval = target_get_gdb_reg_list(target, ®_list,
+ ®_list_size, REG_CLASS_ALL);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("get register list failed");
+ goto error;
+ }
+
+ if (reg_list_size <= 0) {
+ retval = ERROR_FAIL;
+ goto error;
+ }
+
+ char **features = NULL;
+ /* Get a list of available target registers features */
+ retval = get_reg_features_list(target, &features, &feature_list_size, reg_list, reg_list_size);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Can't get the registers feature list");
+ goto error;
+ }
+
+ if (supported) {
+ if (feature_list_size)
+ *supported = 1;
+ else
+ *supported = 0;
+ }
+
+error:
+ if (reg_list != NULL)
+ free(reg_list);
+
+ if (features != NULL)
+ free(features);
+
+ return retval;
+}
+
static int gdb_query_packet(struct connection *connection,
char *packet, int packet_size)
{
}
} else if (strncmp(packet, "qSupported", 10) == 0) {
/* we currently support packet size and qXfer:memory-map:read (if enabled)
- * disable qXfer:features:read for the moment */
+ * qXfer:features:read is supported for some targets */
int retval = ERROR_OK;
char *buffer = NULL;
int pos = 0;
int size = 0;
+ int gdb_target_desc_supported = 0;
+
+ /* we need to test that the target supports target descriptions */
+ retval = gdb_target_description_supported(target, &gdb_target_desc_supported);
+ if (retval != ERROR_OK) {
+ LOG_INFO("Failed detecting Target Description Support, disabling");
+ gdb_target_desc_supported = 0;
+ }
+
+ /* support may be disabled globally */
+ if (gdb_use_target_description == 0) {
+ if (gdb_target_desc_supported)
+ LOG_WARNING("Target Descriptions Supported, but disabled");
+ gdb_target_desc_supported = 0;
+ }
xml_printf(&retval,
&buffer,
"PacketSize=%x;qXfer:memory-map:read%c;qXfer:features:read%c;QStartNoAckMode+",
(GDB_BUFFER_SIZE - 1),
((gdb_use_memory_map == 1) && (flash_get_bank_count() > 0)) ? '+' : '-',
- (gdb_use_target_description == 1) ? '+' : '-');
+ (gdb_target_desc_supported == 1) ? '+' : '-');
if (retval != ERROR_OK) {
gdb_send_error(connection, 01);
int retval = fileio_open(&fileio, tdesc_filename, FILEIO_WRITE, FILEIO_TEXT);
- free(tdesc_filename);
-
if (retval != ERROR_OK) {
LOG_WARNING("Can't open %s for writing", tdesc_filename);
+ free(tdesc_filename);
return ERROR_FAIL;
}
retval = fileio_write(&fileio, tdesc_length, tdesc, &size_written);
fileio_close(&fileio);
+ free(tdesc_filename);
if (retval != ERROR_OK) {
LOG_WARNING("Error while writing the tdesc file");