* warning only about subsequent ACK's. */
if (gdb_con->noack_mode > 1) {
LOG_WARNING("acknowledgment received, but no packet pending");
- } else {
+ } else if (gdb_con->noack_mode) {
LOG_DEBUG("Received first acknowledgment after entering noack mode. Ignoring it.");
gdb_con->noack_mode = 2;
}
static void gdb_signal_reply(struct target *target, struct connection *connection)
{
struct gdb_connection *gdb_connection = connection->priv;
- char sig_reply[20];
+ char sig_reply[45];
char stop_reason[20];
+ char current_thread[25];
int sig_reply_len;
int signal_var;
+ rtos_update_threads(target);
+
if (target->debug_reason == DBG_REASON_EXIT) {
sig_reply_len = snprintf(sig_reply, sizeof(sig_reply), "W00");
} else {
}
}
- sig_reply_len = snprintf(sig_reply, sizeof(sig_reply), "T%2.2x%s",
- signal_var, stop_reason);
+ current_thread[0] = '\0';
+ if (target->rtos != NULL) {
+ snprintf(current_thread, sizeof(current_thread), "thread:%016" PRIx64 ";", target->rtos->current_thread);
+ target->rtos->current_threadid = target->rtos->current_thread;
+ }
+
+ sig_reply_len = snprintf(sig_reply, sizeof(sig_reply), "T%2.2x%s%s",
+ signal_var, stop_reason, current_thread);
}
gdb_put_packet(connection, sig_reply, sig_reply_len);
gdb_connection->frontend_state = TARGET_HALTED;
- rtos_update_threads(target);
}
static void gdb_fileio_reply(struct target *target, struct connection *connection)
assert(reg_packet_size > 0);
reg_packet = malloc(reg_packet_size + 1); /* plus one for string termination null */
+ if (reg_packet == NULL)
+ return ERROR_FAIL;
+
reg_packet_p = reg_packet;
for (i = 0; i < reg_list_size; i++) {
}
}
-static int decode_xfer_read(char const *_buf, char **annex, int *ofs, unsigned int *len)
+static int decode_xfer_read(char const *buf, char **annex, int *ofs, unsigned int *len)
{
- int ret = 0;
- char *buf = strdup(_buf);
- char *_annex;
- char *separator;
-
- /* Extract and NUL-terminate the annex. */
- _annex = buf;
- while (*buf && *buf != ':')
- buf++;
- if (*buf == '\0') {
- ret = -1;
- goto out;
- }
- *buf++ = 0;
-
- /* Return annex as copy because "buf" will be freed in this function */
- *annex = strdup(_annex);
+ /* Locate the annex. */
+ const char *annex_end = strchr(buf, ':');
+ if (annex_end == NULL)
+ return ERROR_FAIL;
/* After the read marker and annex, qXfer looks like a
* traditional 'm' packet. */
+ char *separator;
+ *ofs = strtoul(annex_end + 1, &separator, 16);
- *ofs = strtoul(buf, &separator, 16);
-
- if (*separator != ',') {
- ret = -1;
- goto out;
- }
+ if (*separator != ',')
+ return ERROR_FAIL;
*len = strtoul(separator + 1, NULL, 16);
-out:
- free(buf);
- return ret;
+ /* Extract the annex if needed */
+ if (annex != NULL) {
+ *annex = strndup(buf, annex_end - buf);
+ if (*annex == NULL)
+ return ERROR_FAIL;
+ }
+
+ return ERROR_OK;
}
static int compare_bank(const void *a, const void *b)
/* Get a list of available target registers features. feature_list must
* be freed by caller.
*/
-static int get_reg_features_list(struct target *target, char **feature_list[], int *feature_list_size,
+static int get_reg_features_list(struct target *target, char const **feature_list[], int *feature_list_size,
struct reg **reg_list, int reg_list_size)
{
int tbl_sz = 0;
*/
for (int j = 0; j < (tbl_sz + 1); j++) {
if (!((*feature_list)[j])) {
- (*feature_list)[tbl_sz++] = strdup(reg_list[i]->feature->name);
+ (*feature_list)[tbl_sz++] = reg_list[i]->feature->name;
*feature_list = realloc(*feature_list, sizeof(char *) * (tbl_sz + 1));
(*feature_list)[tbl_sz] = NULL;
break;
static int gdb_generate_target_description(struct target *target, char **tdesc_out)
{
int retval = ERROR_OK;
- struct reg **reg_list;
+ struct reg **reg_list = NULL;
int reg_list_size;
+ char const **features = NULL;
+ int feature_list_size = 0;
char *tdesc = NULL;
int pos = 0;
int size = 0;
if (retval != ERROR_OK) {
LOG_ERROR("get register list failed");
- return ERROR_FAIL;
+ retval = ERROR_FAIL;
+ goto error;
}
if (reg_list_size <= 0) {
- free(reg_list);
- return ERROR_FAIL;
+ LOG_ERROR("get register list failed");
+ retval = ERROR_FAIL;
+ goto error;
}
- char **features = NULL;
/* Get a list of available target registers features */
- retval = get_reg_features_list(target, &features, NULL, reg_list, reg_list_size);
+ 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");
- free(reg_list);
- return ERROR_FAIL;
+ retval = ERROR_FAIL;
+ goto error;
}
/* If we found some features associated with registers, create sections */
xml_printf(&retval, &tdesc, &pos, &size,
"</target>\n");
- free(reg_list);
+error:
free(features);
+ free(reg_list);
if (retval == ERROR_OK)
*tdesc_out = tdesc;
int retval = ERROR_OK;
struct reg **reg_list = NULL;
int reg_list_size = 0;
+ char const **features = NULL;
int feature_list_size = 0;
- char **features = NULL;
retval = target_get_gdb_reg_list(target, ®_list,
®_list_size, REG_CLASS_ALL);
}
if (reg_list_size <= 0) {
+ LOG_ERROR("get register list failed");
retval = ERROR_FAIL;
goto error;
}
}
error:
- if (reg_list != NULL)
- free(reg_list);
+ free(features);
- if (features != NULL)
- free(features);
+ free(reg_list);
return retval;
}
int offset;
unsigned int length;
- char *annex = NULL;
/* skip command character */
packet += 20;
- if (decode_xfer_read(packet, &annex, &offset, &length) < 0) {
+ if (decode_xfer_read(packet, NULL, &offset, &length) < 0) {
gdb_send_error(connection, 01);
return ERROR_OK;
}
- free(annex);
/* Target should prepare correct target description for annex.
* The first character of returned xml is 'm' or 'l'. 'm' for