static enum breakpoint_type gdb_breakpoint_override_type;
static int gdb_error(struct connection *connection, int retval);
-static const char *gdb_port;
-static const char *gdb_port_next;
+static char *gdb_port;
+static char *gdb_port_next;
static void gdb_log_callback(void *priv, const char *file, unsigned line,
const char *function, const char *string);
case '$':
break;
case '+':
- /* gdb sends a dummy ack '+' at every remote connect - see
- * remote_start_remote (remote.c)
- * in case anyone tries to debug why they receive this
- * warning every time */
- LOG_WARNING("acknowledgment received, but no packet pending");
+ /* According to the GDB documentation
+ * (https://sourceware.org/gdb/onlinedocs/gdb/Packet-Acknowledgment.html):
+ * "gdb sends a final `+` acknowledgment of the stub's `OK`
+ * response, which can be safely ignored by the stub."
+ * However OpenOCD server already is in noack mode at this
+ * point and instead of ignoring this it was emitting a
+ * warning. This code makes server ignore the first ACK
+ * that will be received after going into noack mode,
+ * warning only about subsequent ACK's. */
+ if (gdb_con->noack_mode > 1) {
+ LOG_WARNING("acknowledgment received, but no packet pending");
+ } else {
+ LOG_DEBUG("Received first acknowledgment after entering noack mode. Ignoring it.");
+ gdb_con->noack_mode = 2;
+ }
break;
case '-':
LOG_WARNING("negative acknowledgment, but no packet pending");
switch (hit_wp_type) {
case WPT_WRITE:
snprintf(stop_reason, sizeof(stop_reason),
- "watch:%08x;", hit_wp_address);
+ "watch:%08" PRIx32 ";", hit_wp_address);
break;
case WPT_READ:
snprintf(stop_reason, sizeof(stop_reason),
- "rwatch:%08x;", hit_wp_address);
+ "rwatch:%08" PRIx32 ";", hit_wp_address);
break;
case WPT_ACCESS:
snprintf(stop_reason, sizeof(stop_reason),
- "awatch:%08x;", hit_wp_address);
+ "awatch:%08" PRIx32 ";", hit_wp_address);
break;
default:
break;
bool program_exited = false;
if (strcmp(target->fileio_info->identifier, "open") == 0)
- sprintf(fileio_command, "F%s,%x/%x,%x,%x", target->fileio_info->identifier,
+ sprintf(fileio_command, "F%s,%" PRIx32 "/%" PRIx32 ",%" PRIx32 ",%" PRIx32, target->fileio_info->identifier,
target->fileio_info->param_1,
target->fileio_info->param_2,
target->fileio_info->param_3,
target->fileio_info->param_4);
else if (strcmp(target->fileio_info->identifier, "close") == 0)
- sprintf(fileio_command, "F%s,%x", target->fileio_info->identifier,
+ sprintf(fileio_command, "F%s,%" PRIx32, target->fileio_info->identifier,
target->fileio_info->param_1);
else if (strcmp(target->fileio_info->identifier, "read") == 0)
- sprintf(fileio_command, "F%s,%x,%x,%x", target->fileio_info->identifier,
+ sprintf(fileio_command, "F%s,%" PRIx32 ",%" PRIx32 ",%" PRIx32, target->fileio_info->identifier,
target->fileio_info->param_1,
target->fileio_info->param_2,
target->fileio_info->param_3);
else if (strcmp(target->fileio_info->identifier, "write") == 0)
- sprintf(fileio_command, "F%s,%x,%x,%x", target->fileio_info->identifier,
+ sprintf(fileio_command, "F%s,%" PRIx32 ",%" PRIx32 ",%" PRIx32, target->fileio_info->identifier,
target->fileio_info->param_1,
target->fileio_info->param_2,
target->fileio_info->param_3);
else if (strcmp(target->fileio_info->identifier, "lseek") == 0)
- sprintf(fileio_command, "F%s,%x,%x,%x", target->fileio_info->identifier,
+ sprintf(fileio_command, "F%s,%" PRIx32 ",%" PRIx32 ",%" PRIx32, target->fileio_info->identifier,
target->fileio_info->param_1,
target->fileio_info->param_2,
target->fileio_info->param_3);
else if (strcmp(target->fileio_info->identifier, "rename") == 0)
- sprintf(fileio_command, "F%s,%x/%x,%x/%x", target->fileio_info->identifier,
+ sprintf(fileio_command, "F%s,%" PRIx32 "/%" PRIx32 ",%" PRIx32 "/%" PRIx32, target->fileio_info->identifier,
target->fileio_info->param_1,
target->fileio_info->param_2,
target->fileio_info->param_3,
target->fileio_info->param_4);
else if (strcmp(target->fileio_info->identifier, "unlink") == 0)
- sprintf(fileio_command, "F%s,%x/%x", target->fileio_info->identifier,
+ sprintf(fileio_command, "F%s,%" PRIx32 "/%" PRIx32, target->fileio_info->identifier,
target->fileio_info->param_1,
target->fileio_info->param_2);
else if (strcmp(target->fileio_info->identifier, "stat") == 0)
- sprintf(fileio_command, "F%s,%x/%x,%x", target->fileio_info->identifier,
+ sprintf(fileio_command, "F%s,%" PRIx32 "/%" PRIx32 ",%" PRIx32, target->fileio_info->identifier,
target->fileio_info->param_1,
target->fileio_info->param_2,
target->fileio_info->param_3);
else if (strcmp(target->fileio_info->identifier, "fstat") == 0)
- sprintf(fileio_command, "F%s,%x,%x", target->fileio_info->identifier,
+ sprintf(fileio_command, "F%s,%" PRIx32 ",%" PRIx32, target->fileio_info->identifier,
target->fileio_info->param_1,
target->fileio_info->param_2);
else if (strcmp(target->fileio_info->identifier, "gettimeofday") == 0)
- sprintf(fileio_command, "F%s,%x,%x", target->fileio_info->identifier,
+ sprintf(fileio_command, "F%s,%" PRIx32 ",%" PRIx32, target->fileio_info->identifier,
target->fileio_info->param_1,
target->fileio_info->param_2);
else if (strcmp(target->fileio_info->identifier, "isatty") == 0)
- sprintf(fileio_command, "F%s,%x", target->fileio_info->identifier,
+ sprintf(fileio_command, "F%s,%" PRIx32, target->fileio_info->identifier,
target->fileio_info->param_1);
else if (strcmp(target->fileio_info->identifier, "system") == 0)
- sprintf(fileio_command, "F%s,%x/%x", target->fileio_info->identifier,
+ sprintf(fileio_command, "F%s,%" PRIx32 "/%" PRIx32, target->fileio_info->identifier,
target->fileio_info->param_1,
target->fileio_info->param_2);
else if (strcmp(target->fileio_info->identifier, "exit") == 0) {
/* If target hits exit syscall, report to GDB the program is terminated.
* In addition, let target run its own exit syscall handler. */
program_exited = true;
- sprintf(fileio_command, "W%02x", target->fileio_info->param_1);
+ sprintf(fileio_command, "W%02" PRIx32, target->fileio_info->param_1);
} else {
LOG_DEBUG("Unknown syscall: %s", target->fileio_info->identifier);
int i;
for (i = 0; i < flash_get_bank_count(); i++) {
struct flash_bank *p;
+ p = get_flash_bank_by_num_noprobe(i);
+ if (p->target != gdb_service->target)
+ continue;
retval = get_flash_bank_by_num(i, &p);
if (retval != ERROR_OK) {
LOG_ERROR("Connect failed. Consider setting up a gdb-attach event for the target " \
len = strtoul(separator + 1, NULL, 16);
+ if (!len) {
+ LOG_WARNING("invalid read memory packet received (len == 0)");
+ gdb_put_packet(connection, NULL, 0);
+ return ERROR_OK;
+ }
+
buffer = malloc(len);
LOG_DEBUG("addr: 0x%8.8" PRIx32 ", len: 0x%8.8" PRIx32 "", addr, len);
LOG_DEBUG("-");
- if (packet_size > 1) {
- packet[packet_size] = 0;
+ if (packet_size > 1)
address = strtoul(packet + 1, NULL, 16);
- } else
+ else
current = 1;
gdb_running_type = packet[0];
}
}
-static int decode_xfer_read(char *buf, char **annex, int *ofs, unsigned int *len)
+static int decode_xfer_read(char *_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;
+ _annex = buf;
while (*buf && *buf != ':')
buf++;
- if (*buf == '\0')
- return -1;
+ if (*buf == '\0') {
+ ret = -1;
+ goto out;
+ }
*buf++ = 0;
+ /* Return annex as copy because "buf" will be freed in this function */
+ *annex = strdup(_annex);
+
/* After the read marker and annex, qXfer looks like a
* traditional 'm' packet. */
*ofs = strtoul(buf, &separator, 16);
- if (*separator != ',')
- return -1;
+ if (*separator != ',') {
+ ret = -1;
+ goto out;
+ }
*len = strtoul(separator + 1, NULL, 16);
- return 0;
+out:
+ free(buf);
+ return ret;
}
static int compare_bank(const void *a, const void *b)
banks = malloc(sizeof(struct flash_bank *)*flash_get_bank_count());
for (i = 0; i < flash_get_bank_count(); i++) {
+ p = get_flash_bank_by_num_noprobe(i);
+ if (p->target != target)
+ continue;
retval = get_flash_bank_by_num(i, &p);
if (retval != ERROR_OK) {
free(banks);
gdb_error(connection, retval);
return retval;
}
- if (p->target == target)
- banks[target_flash_banks++] = p;
+ banks[target_flash_banks++] = p;
}
qsort(banks, target_flash_banks, sizeof(struct flash_bank *),
if (reg_list[i]->exist == false)
continue;
- if ((reg_list[i]->feature->name != NULL)
+ if (reg_list[i]->feature != NULL
+ && reg_list[i]->feature->name != NULL
&& (strcmp(reg_list[i]->feature->name, ""))) {
/* We found a feature, check if the feature is already in the
* table. If not, allocate a new entry for the table and
struct reg **reg_list = NULL;
int reg_list_size = 0;
int feature_list_size = 0;
+ char **features = NULL;
retval = target_get_gdb_reg_list(target, ®_list,
®_list_size, REG_CLASS_ALL);
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) {
int offset;
unsigned int length;
- char *annex;
+ char *annex = NULL;
/* skip command character */
packet += 20;
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
portnumber = strtol(gdb_port_next, &end, 0);
if (!*end) {
if (parse_long(gdb_port_next, &portnumber) == ERROR_OK) {
- free((void *)gdb_port_next);
+ free(gdb_port_next);
gdb_port_next = alloc_printf("%d", portnumber+1);
}
}
{
int retval = CALL_COMMAND_HANDLER(server_pipe_command, &gdb_port);
if (ERROR_OK == retval) {
- free((void *)gdb_port_next);
+ free(gdb_port_next);
gdb_port_next = strdup(gdb_port);
}
return retval;