gdb_server: Add check for malloc fail
[openocd.git] / src / server / gdb_server.c
index 40852ab30d148efb1ec98f18b01ac0e042683fb2..780359ea4510ac1ee344fcf6438834b9e338fdf2 100644 (file)
@@ -628,7 +628,7 @@ static int gdb_get_packet_inner(struct connection *connection,
                                         * 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;
                                        }
@@ -714,11 +714,14 @@ static int gdb_output(struct command_context *context, const char *line)
 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 {
@@ -754,13 +757,18 @@ static void gdb_signal_reply(struct target *target, struct connection *connectio
                        }
                }
 
-               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)
@@ -1044,7 +1052,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;
@@ -1101,7 +1109,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");
@@ -1122,7 +1130,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;
@@ -1151,6 +1159,9 @@ static int gdb_get_registers_packet(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++) {
@@ -1178,14 +1189,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("-");
@@ -1233,7 +1244,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;
@@ -1272,7 +1283,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;
@@ -1338,7 +1349,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;
@@ -1409,7 +1420,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;
@@ -1456,7 +1467,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;
@@ -1513,7 +1524,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;
@@ -1541,7 +1552,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;
@@ -1669,29 +1680,31 @@ 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)
 {
-       char *separator;
-
-       /* Extract and NUL-terminate the annex. */
-       *annex = buf;
-       while (*buf && *buf != ':')
-               buf++;
-       if (*buf == '\0')
-               return -1;
-       *buf++ = 0;
+       /* 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. */
-
-       *ofs = strtoul(buf, &separator, 16);
+       char *separator;
+       *ofs = strtoul(annex_end + 1, &separator, 16);
 
        if (*separator != ',')
-               return -1;
+               return ERROR_FAIL;
 
        *len = strtoul(separator + 1, NULL, 16);
 
-       return 0;
+       /* 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)
@@ -1709,7 +1722,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
@@ -1996,7 +2009,7 @@ static int gdb_generate_reg_type_description(struct target *target,
 /* 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;
@@ -2017,7 +2030,7 @@ static int get_reg_features_list(struct target *target, char **feature_list[], i
                         */
                        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;
@@ -2038,8 +2051,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 const **features = NULL;
+       int feature_list_size = 0;
        char *tdesc = NULL;
        int pos = 0;
        int size = 0;
@@ -2049,21 +2064,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 */
@@ -2143,8 +2159,9 @@ static int gdb_generate_target_description(struct target *target, char **tdesc_o
        xml_printf(&retval, &tdesc, &pos, &size,
                        "</target>\n");
 
-       free(reg_list);
+error:
        free(features);
+       free(reg_list);
 
        if (retval == ERROR_OK)
                *tdesc_out = tdesc;
@@ -2213,8 +2230,8 @@ 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 const **features = NULL;
        int feature_list_size = 0;
-       char **features = NULL;
 
        retval = target_get_gdb_reg_list(target, &reg_list,
                        &reg_list_size, REG_CLASS_ALL);
@@ -2224,6 +2241,7 @@ 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;
        }
@@ -2243,17 +2261,15 @@ static int gdb_target_description_supported(struct target *target, int *supporte
        }
 
 error:
-       if (reg_list != NULL)
-               free(reg_list);
+       free(features);
 
-       if (features != NULL)
-               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;
@@ -2364,12 +2380,11 @@ static int gdb_query_packet(struct connection *connection,
 
                int offset;
                unsigned int length;
-               char *annex;
 
                /* 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;
                }
@@ -2401,7 +2416,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;
@@ -2418,20 +2433,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");
@@ -2474,13 +2489,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;
@@ -2495,7 +2510,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;
 
@@ -2547,7 +2562,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;
@@ -2619,7 +2634,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;
@@ -2638,12 +2653,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') {

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)