int rtos_thread_packet(struct connection *connection, char const *packet, int packet_size) { struct target *target = get_target_from_connection(connection); if (strncmp(packet, "qThreadExtraInfo,", 17) == 0) { if ((target->rtos != NULL) && (target->rtos->thread_details != NULL) && (target->rtos->thread_count != 0)) { threadid_t threadid = 0; int found = -1; sscanf(packet, "qThreadExtraInfo,%" SCNx64, &threadid); if ((target->rtos != NULL) && (target->rtos->thread_details != NULL)) { int thread_num; for (thread_num = 0; thread_num < target->rtos->thread_count; thread_num++) { if (target->rtos->thread_details[thread_num].threadid == threadid) { if (target->rtos->thread_details[thread_num].exists) found = thread_num; } } } if (found == -1) { gdb_put_packet(connection, "E01", 3); /* thread not found */ return ERROR_OK; } struct thread_detail *detail = &target->rtos->thread_details[found]; int str_size = 0; if (detail->display_str != NULL) str_size += strlen(detail->display_str); if (detail->thread_name_str != NULL) str_size += strlen(detail->thread_name_str); if (detail->extra_info_str != NULL) str_size += strlen(detail->extra_info_str); char *tmp_str = calloc(str_size + 7, sizeof(char)); char *tmp_str_ptr = tmp_str; if (detail->display_str != NULL) tmp_str_ptr += sprintf(tmp_str_ptr, "%s", detail->display_str); if (detail->thread_name_str != NULL) { if (tmp_str_ptr != tmp_str) tmp_str_ptr += sprintf(tmp_str_ptr, " : "); tmp_str_ptr += sprintf(tmp_str_ptr, "%s", detail->thread_name_str); } if (detail->extra_info_str != NULL) { if (tmp_str_ptr != tmp_str) tmp_str_ptr += sprintf(tmp_str_ptr, " : "); tmp_str_ptr += sprintf(tmp_str_ptr, " : %s", detail->extra_info_str); } assert(strlen(tmp_str) == (size_t) (tmp_str_ptr - tmp_str)); char *hex_str = malloc(strlen(tmp_str) * 2 + 1); int pkt_len = hexify(hex_str, tmp_str, 0, strlen(tmp_str) * 2 + 1); gdb_put_packet(connection, hex_str, pkt_len); free(hex_str); free(tmp_str); return ERROR_OK; } gdb_put_packet(connection, "", 0); return ERROR_OK; } else if (strncmp(packet, "qSymbol", 7) == 0) { if (rtos_qsymbol(connection, packet, packet_size) == 1) { target->rtos_auto_detect = false; target->rtos->type->create(target); target->rtos->type->update_threads(target->rtos); } return ERROR_OK; } else if (strncmp(packet, "qfThreadInfo", 12) == 0) { int i; if (target->rtos != NULL) { if (target->rtos->thread_count == 0) { gdb_put_packet(connection, "l", 1); } else { /*thread id are 16 char +1 for ',' */ char *out_str = malloc(17 * target->rtos->thread_count + 1); char *tmp_str = out_str; for (i = 0; i < target->rtos->thread_count; i++) { tmp_str += sprintf(tmp_str, "%c%016" PRIx64, i == 0 ? 'm' : ',', target->rtos->thread_details[i].threadid); } gdb_put_packet(connection, out_str, strlen(out_str)); free(out_str); } } else gdb_put_packet(connection, "l", 1); return ERROR_OK; } else if (strncmp(packet, "qsThreadInfo", 12) == 0) { gdb_put_packet(connection, "l", 1); return ERROR_OK; } else if (strncmp(packet, "qAttached", 9) == 0) { gdb_put_packet(connection, "1", 1); return ERROR_OK; } else if (strncmp(packet, "qOffsets", 8) == 0) { char offsets[] = "Text=0;Data=0;Bss=0"; gdb_put_packet(connection, offsets, sizeof(offsets)-1); return ERROR_OK; } else if (strncmp(packet, "qCRC:", 5) == 0) { /* make sure we check this before "qC" packet below * otherwise it gets incorrectly handled */ return GDB_THREAD_PACKET_NOT_CONSUMED; } else if (strncmp(packet, "qC", 2) == 0) { if (target->rtos != NULL) { char buffer[19]; int size; size = snprintf(buffer, 19, "QC%016" PRIx64, target->rtos->current_thread); gdb_put_packet(connection, buffer, size); } else gdb_put_packet(connection, "QC0", 3); return ERROR_OK; } else if (packet[0] == 'T') { /* Is thread alive? */ threadid_t threadid; int found = -1; sscanf(packet, "T%" SCNx64, &threadid); if ((target->rtos != NULL) && (target->rtos->thread_details != NULL)) { int thread_num; for (thread_num = 0; thread_num < target->rtos->thread_count; thread_num++) { if (target->rtos->thread_details[thread_num].threadid == threadid) { if (target->rtos->thread_details[thread_num].exists) found = thread_num; } } } if (found != -1) gdb_put_packet(connection, "OK", 2); /* thread alive */ else gdb_put_packet(connection, "E01", 3); /* thread not found */ return ERROR_OK; } else if (packet[0] == 'H') { /* Set current thread ( 'c' for step and continue, 'g' for * all other operations ) */ if ((packet[1] == 'g') && (target->rtos != NULL)) { sscanf(packet, "Hg%16" SCNx64, &target->rtos->current_threadid); LOG_DEBUG("RTOS: GDB requested to set current thread to 0x%" PRIx64 "\r\n", target->rtos->current_threadid); } gdb_put_packet(connection, "OK", 2); return ERROR_OK; } return GDB_THREAD_PACKET_NOT_CONSUMED; }
static int linux_thread_packet(struct connection *connection, char *packet, int packet_size) { int retval = ERROR_OK; struct current_thread *ct; struct target *target = get_target_from_connection(connection); struct linux_os *linux_os = (struct linux_os *) target->rtos->rtos_specific_params; switch (packet[0]) { case 'T': /* Is thread alive?*/ linux_gdb_T_packet(connection, target, packet, packet_size); break; case 'H': /* Set current thread */ /* ( 'c' for step and continue, 'g' for all other operations )*/ /*LOG_INFO(" H packet received '%s'", packet);*/ linux_gdb_h_packet(connection, target, packet, packet_size); break; case 'q': if (strncmp(packet, "qSymbol", 7) == 0) { if (rtos_qsymbol(connection, packet, packet_size) == 1) { linux_compute_virt2phys(target, target->rtos-> symbols[INIT_TASK]. address); } break; } else if (strncmp(packet, "qfThreadInfo", 12) == 0) { if (linux_os->thread_list == NULL) { retval = linux_gdb_thread_packet(target, connection, packet, packet_size); break; } else { retval = linux_gdb_thread_update(target, connection, packet, packet_size); break; } } else if (strncmp(packet, "qsThreadInfo", 12) == 0) { gdb_put_packet(connection, "l", 1); break; } else if (strncmp(packet, "qThreadExtraInfo,", 17) == 0) { linux_thread_extra_info(target, connection, packet, packet_size); break; } else { retval = GDB_THREAD_PACKET_NOT_CONSUMED; break; } case 'Q': /* previously response was : thread not found * gdb_put_packet(connection, "E01", 3); */ retval = GDB_THREAD_PACKET_NOT_CONSUMED; break; case 'c': case 's': { if (linux_os->threads_lookup == 1) { ct = linux_os->current_threads; while ((ct != NULL) && (ct->core_id) != target->coreid) ct = ct->next; if ((ct != NULL) && (ct->threadid == -1)) { ct = linux_os->current_threads; while ((ct != NULL) && (ct->threadid == -1)) ct = ct->next; } if ((ct != NULL) && (ct->threadid != target->rtos-> current_threadid) && (target->rtos->current_threadid != -1)) LOG_WARNING("WARNING! current GDB thread do not match" \ "current thread running." \ "Switch thread in GDB to threadid %d", (int)ct->threadid); LOG_INFO("threads_needs_update = 1"); linux_os->threads_needs_update = 1; } } /* if a packet handler returned an error, exit input loop */ if (retval != ERROR_OK) return retval; } return retval; }