gdbserver: fix duplicate declaration
[fw/openocd] / src / server / gdb_server.c
index 28cb3ab71baaa42f2a31f9bb7cfd34a877543e79..e417bf45ca4228d4120a5d05a96e890259943cc4 100644 (file)
@@ -617,11 +617,21 @@ static int gdb_get_packet_inner(struct connection *connection,
                                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");
@@ -728,15 +738,15 @@ static void gdb_signal_reply(struct target *target, struct connection *connectio
                                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;
@@ -761,64 +771,64 @@ static void gdb_fileio_reply(struct target *target, struct connection *connectio
        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);
 
@@ -1034,7 +1044,7 @@ static void gdb_send_error(struct connection *connection, uint8_t the_error)
 }
 
 static int gdb_last_signal_packet(struct connection *connection,
-               char *packet, int packet_size)
+               char const *packet, int packet_size)
 {
        struct target *target = get_target_from_connection(connection);
        struct gdb_connection *gdb_con = connection->priv;
@@ -1091,7 +1101,7 @@ static void gdb_str_to_target(struct target *target,
 
 /* copy over in register buffer */
 static void gdb_target_to_reg(struct target *target,
-               char *tstr, int str_len, uint8_t *bin)
+               char const *tstr, int str_len, uint8_t *bin)
 {
        if (str_len % 2) {
                LOG_ERROR("BUG: gdb value with uneven number of characters encountered");
@@ -1112,7 +1122,7 @@ static void gdb_target_to_reg(struct target *target,
 }
 
 static int gdb_get_registers_packet(struct connection *connection,
-               char *packet, int packet_size)
+               char const *packet, int packet_size)
 {
        struct target *target = get_target_from_connection(connection);
        struct reg **reg_list;
@@ -1168,14 +1178,14 @@ static int gdb_get_registers_packet(struct connection *connection,
 }
 
 static int gdb_set_registers_packet(struct connection *connection,
-               char *packet, int packet_size)
+               char const *packet, int packet_size)
 {
        struct target *target = get_target_from_connection(connection);
        int i;
        struct reg **reg_list;
        int reg_list_size;
        int retval;
-       char *packet_p;
+       char const *packet_p;
 
 #ifdef _DEBUG_GDB_IO_
        LOG_DEBUG("-");
@@ -1223,7 +1233,7 @@ static int gdb_set_registers_packet(struct connection *connection,
 }
 
 static int gdb_get_register_packet(struct connection *connection,
-       char *packet, int packet_size)
+       char const *packet, int packet_size)
 {
        struct target *target = get_target_from_connection(connection);
        char *reg_packet;
@@ -1262,7 +1272,7 @@ static int gdb_get_register_packet(struct connection *connection,
 }
 
 static int gdb_set_register_packet(struct connection *connection,
-       char *packet, int packet_size)
+       char const *packet, int packet_size)
 {
        struct target *target = get_target_from_connection(connection);
        char *separator;
@@ -1328,7 +1338,7 @@ static int gdb_error(struct connection *connection, int retval)
  * 8191 bytes by the looks of it. Why 8191 bytes instead of 8192?????
  */
 static int gdb_read_memory_packet(struct connection *connection,
-               char *packet, int packet_size)
+               char const *packet, int packet_size)
 {
        struct target *target = get_target_from_connection(connection);
        char *separator;
@@ -1352,6 +1362,12 @@ static int gdb_read_memory_packet(struct connection *connection,
 
        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);
@@ -1393,7 +1409,7 @@ static int gdb_read_memory_packet(struct connection *connection,
 }
 
 static int gdb_write_memory_packet(struct connection *connection,
-               char *packet, int packet_size)
+               char const *packet, int packet_size)
 {
        struct target *target = get_target_from_connection(connection);
        char *separator;
@@ -1440,7 +1456,7 @@ static int gdb_write_memory_packet(struct connection *connection,
 }
 
 static int gdb_write_memory_binary_packet(struct connection *connection,
-               char *packet, int packet_size)
+               char const *packet, int packet_size)
 {
        struct target *target = get_target_from_connection(connection);
        char *separator;
@@ -1497,7 +1513,7 @@ static int gdb_write_memory_binary_packet(struct connection *connection,
 }
 
 static int gdb_step_continue_packet(struct connection *connection,
-               char *packet, int packet_size)
+               char const *packet, int packet_size)
 {
        struct target *target = get_target_from_connection(connection);
        int current = 0;
@@ -1506,10 +1522,9 @@ static int gdb_step_continue_packet(struct connection *connection,
 
        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];
@@ -1526,7 +1541,7 @@ static int gdb_step_continue_packet(struct connection *connection,
 }
 
 static int gdb_breakpoint_watchpoint_packet(struct connection *connection,
-               char *packet, int packet_size)
+               char const *packet, int packet_size)
 {
        struct target *target = get_target_from_connection(connection);
        int type;
@@ -1654,29 +1669,41 @@ static void xml_printf(int *retval, char **xml, int *pos, int *size,
        }
 }
 
-static int decode_xfer_read(char *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;
+       _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)
@@ -1694,7 +1721,7 @@ static int compare_bank(const void *a, const void *b)
 }
 
 static int gdb_memory_map(struct connection *connection,
-               char *packet, int packet_size)
+               char const *packet, int packet_size)
 {
        /* We get away with only specifying flash here. Regions that are not
         * specified are treated as if we provided no memory map(if not we
@@ -2023,8 +2050,10 @@ static int get_reg_features_list(struct target *target, char **feature_list[], i
 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 **features = NULL;
+       int feature_list_size = 0;
        char *tdesc = NULL;
        int pos = 0;
        int size = 0;
@@ -2034,21 +2063,22 @@ static int gdb_generate_target_description(struct target *target, char **tdesc_o
 
        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 */
@@ -2128,8 +2158,13 @@ static int gdb_generate_target_description(struct target *target, char **tdesc_o
        xml_printf(&retval, &tdesc, &pos, &size,
                        "</target>\n");
 
-       free(reg_list);
+error:
+
+       /* note: features[] contains (feature_list_size + 1) elements */
+       for (int j = feature_list_size; j >= 0; j--)
+               free(features[j]);
        free(features);
+       free(reg_list);
 
        if (retval == ERROR_OK)
                *tdesc_out = tdesc;
@@ -2198,6 +2233,7 @@ static int gdb_target_description_supported(struct target *target, int *supporte
        int retval = ERROR_OK;
        struct reg **reg_list = NULL;
        int reg_list_size = 0;
+       char **features = NULL;
        int feature_list_size = 0;
 
        retval = target_get_gdb_reg_list(target, &reg_list,
@@ -2208,11 +2244,11 @@ static int gdb_target_description_supported(struct target *target, int *supporte
        }
 
        if (reg_list_size <= 0) {
+               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, &feature_list_size, reg_list, reg_list_size);
        if (retval != ERROR_OK) {
@@ -2228,17 +2264,19 @@ static int gdb_target_description_supported(struct target *target, int *supporte
        }
 
 error:
-       if (reg_list != NULL)
-               free(reg_list);
 
-       if (features != NULL)
-               free(features);
+       /* note: features[] contains (feature_list_size + 1) elements */
+       for (int j = feature_list_size; j >= 0; j--)
+               free(features[j]);
+       free(features);
+
+       free(reg_list);
 
        return retval;
 }
 
 static int gdb_query_packet(struct connection *connection,
-               char *packet, int packet_size)
+               char const *packet, int packet_size)
 {
        struct command_context *cmd_ctx = connection->cmd_ctx;
        struct gdb_connection *gdb_connection = connection->priv;
@@ -2349,7 +2387,7 @@ static int gdb_query_packet(struct connection *connection,
 
                int offset;
                unsigned int length;
-               char *annex;
+               char *annex = NULL;
 
                /* skip command character */
                packet += 20;
@@ -2358,6 +2396,7 @@ static int gdb_query_packet(struct connection *connection,
                        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
@@ -2386,7 +2425,7 @@ static int gdb_query_packet(struct connection *connection,
 }
 
 static int gdb_v_packet(struct connection *connection,
-               char *packet, int packet_size)
+               char const *packet, int packet_size)
 {
        struct gdb_connection *gdb_connection = connection->priv;
        struct gdb_service *gdb_service = connection->service->priv;
@@ -2403,20 +2442,20 @@ static int gdb_v_packet(struct connection *connection,
                unsigned long addr;
                unsigned long length;
 
-               char *parse = packet + 12;
+               char const *parse = packet + 12;
                if (*parse == '\0') {
                        LOG_ERROR("incomplete vFlashErase packet received, dropping connection");
                        return ERROR_SERVER_REMOTE_CLOSED;
                }
 
-               addr = strtoul(parse, &parse, 16);
+               addr = strtoul(parse, (char **)&parse, 16);
 
                if (*(parse++) != ',' || *parse == '\0') {
                        LOG_ERROR("incomplete vFlashErase packet received, dropping connection");
                        return ERROR_SERVER_REMOTE_CLOSED;
                }
 
-               length = strtoul(parse, &parse, 16);
+               length = strtoul(parse, (char **)&parse, 16);
 
                if (*parse != '\0') {
                        LOG_ERROR("incomplete vFlashErase packet received, dropping connection");
@@ -2459,13 +2498,13 @@ static int gdb_v_packet(struct connection *connection,
                int retval;
                unsigned long addr;
                unsigned long length;
-               char *parse = packet + 12;
+               char const *parse = packet + 12;
 
                if (*parse == '\0') {
                        LOG_ERROR("incomplete vFlashErase packet received, dropping connection");
                        return ERROR_SERVER_REMOTE_CLOSED;
                }
-               addr = strtoul(parse, &parse, 16);
+               addr = strtoul(parse, (char **)&parse, 16);
                if (*(parse++) != ':') {
                        LOG_ERROR("incomplete vFlashErase packet received, dropping connection");
                        return ERROR_SERVER_REMOTE_CLOSED;
@@ -2480,7 +2519,7 @@ static int gdb_v_packet(struct connection *connection,
 
                /* create new section with content from packet buffer */
                retval = image_add_section(gdb_connection->vflash_image,
-                               addr, length, 0x0, (uint8_t *)parse);
+                               addr, length, 0x0, (uint8_t const *)parse);
                if (retval != ERROR_OK)
                        return retval;
 
@@ -2532,7 +2571,7 @@ static int gdb_detach(struct connection *connection)
  * Fretcode,errno,Ctrl-C flag;call-specific attachment
  */
 static int gdb_fileio_response_packet(struct connection *connection,
-               char *packet, int packet_size)
+               char const *packet, int packet_size)
 {
        struct target *target = get_target_from_connection(connection);
        char *separator;
@@ -2604,7 +2643,7 @@ static int gdb_input_inner(struct connection *connection)
 
        struct gdb_service *gdb_service = connection->service->priv;
        struct target *target = gdb_service->target;
-       char *packet = gdb_packet_buffer;
+       char const *packet = gdb_packet_buffer;
        int packet_size;
        int retval;
        struct gdb_connection *gdb_con = connection->priv;
@@ -2623,12 +2662,12 @@ static int gdb_input_inner(struct connection *connection)
         */
        do {
                packet_size = GDB_BUFFER_SIZE-1;
-               retval = gdb_get_packet(connection, packet, &packet_size);
+               retval = gdb_get_packet(connection, gdb_packet_buffer, &packet_size);
                if (retval != ERROR_OK)
                        return retval;
 
                /* terminate with zero */
-               packet[packet_size] = 0;
+               gdb_packet_buffer[packet_size] = '\0';
 
                if (LOG_LEVEL_IS(LOG_LVL_DEBUG)) {
                        if (packet[0] == 'X') {