gdb_server: support qXfer:threads:read packet

This patch adds support for the qXfer:threads:read packet. In addition
to providing a more efficient method of updating thread state, recent
versions of GDB (7.11.1 and up) can also report remote thread names.
While thread names are not enabled in this patch due to its limited
applicability at the moment, it can be enabled at a later date with
little effort.

As a part of revamping how threads are presented to GDB, extra info
strings for each of the supported RTOSes were updated to match
conventions present in the GDB source code. For more information, see
remote_threads_extra_info() in remote.c. This results in a much smoother
experience when interacting with GDB.

It is also worth mentioning that use of qXfer:threads:read works around
a number of regressions in older versions of GDB regarding remote thread
display. Trust me, it's great.

Change-Id: I97dd6a93c342ceb9b9d0023b6359db0e5604c6e6
Signed-off-by: Steven Stallion <stallion@squareup.com>
Reviewed-on: http://openocd.zylin.com/3559
Tested-by: jenkins
Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
Reviewed-by: Paul Fertser <fercerpav@gmail.com>
This commit is contained in:
Steven Stallion
2016-07-20 21:09:24 -05:00
committed by Paul Fertser
parent c0e7ccbd87
commit 50dd7207ea
9 changed files with 145 additions and 24 deletions

View File

@@ -440,11 +440,11 @@ static int ChibiOS_update_threads(struct rtos *rtos)
if (threadState < CHIBIOS_NUM_STATES)
state_desc = ChibiOS_thread_states[threadState];
else
state_desc = "Unknown state";
state_desc = "Unknown";
curr_thrd_details->extra_info_str = malloc(strlen(
state_desc)+1);
strcpy(curr_thrd_details->extra_info_str, state_desc);
state_desc)+8);
sprintf(curr_thrd_details->extra_info_str, "State: %s", state_desc);
curr_thrd_details->exists = true;

View File

@@ -362,7 +362,7 @@ static int FreeRTOS_update_threads(struct rtos *rtos)
rtos->thread_details[tasks_found].exists = true;
if (rtos->thread_details[tasks_found].threadid == rtos->current_thread) {
char running_str[] = "Running";
char running_str[] = "State: Running";
rtos->thread_details[tasks_found].extra_info_str = malloc(
sizeof(running_str));
strcpy(rtos->thread_details[tasks_found].extra_info_str,

View File

@@ -408,8 +408,8 @@ static int ThreadX_update_threads(struct rtos *rtos)
state_desc = "Unknown state";
rtos->thread_details[tasks_found].extra_info_str = malloc(strlen(
state_desc)+1);
strcpy(rtos->thread_details[tasks_found].extra_info_str, state_desc);
state_desc)+8);
sprintf(rtos->thread_details[tasks_found].extra_info_str, "State: %s", state_desc);
rtos->thread_details[tasks_found].exists = true;

View File

@@ -261,8 +261,8 @@ static int eCos_update_threads(struct rtos *rtos)
state_desc = "Unknown state";
rtos->thread_details[tasks_found].extra_info_str = malloc(strlen(
state_desc)+1);
strcpy(rtos->thread_details[tasks_found].extra_info_str, state_desc);
state_desc)+8);
sprintf(rtos->thread_details[tasks_found].extra_info_str, "State: %s", state_desc);
rtos->thread_details[tasks_found].exists = true;

View File

@@ -168,11 +168,11 @@ static int embKernel_get_tasks_details(struct rtos *rtos, int64_t iterable, cons
return retval;
details->extra_info_str = malloc(EMBKERNEL_MAX_THREAD_NAME_STR_SIZE);
if (task == rtos->current_thread) {
snprintf(details->extra_info_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "Pri=%u, Running",
snprintf(details->extra_info_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "State: Running, Priority: %u",
(unsigned int) priority);
} else {
snprintf(details->extra_info_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "Pri=%u, %s", (unsigned int) priority,
state_str);
snprintf(details->extra_info_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "State: %s, Priority: %u",
state_str, (unsigned int) priority);
}
LOG_OUTPUT("Getting task details: iterable=0x%08X, task=0x%08X, name=%s\n", (unsigned int)iterable,

View File

@@ -1213,7 +1213,7 @@ int linux_thread_extra_info(struct target *target,
if (temp->threadid == threadid) {
char *pid = " PID: ";
char *pid_current = "*PID: ";
char *name = "NAME: ";
char *name = "Name: ";
int str_size = strlen(pid) + strlen(name);
char *tmp_str = calloc(1, str_size + 50);
char *tmp_str_ptr = tmp_str;
@@ -1225,9 +1225,7 @@ int linux_thread_extra_info(struct target *target,
else
tmp_str_ptr += sprintf(tmp_str_ptr, "%s", pid);
tmp_str_ptr +=
sprintf(tmp_str_ptr, "%d", (int)temp->pid);
tmp_str_ptr += sprintf(tmp_str_ptr, "%s", " | ");
tmp_str_ptr += sprintf(tmp_str_ptr, "%d, ", (int)temp->pid);
sprintf(tmp_str_ptr, "%s", name);
sprintf(tmp_str_ptr, "%s", temp->name);
char *hex_str = calloc(1, strlen(tmp_str) * 2 + 1);

View File

@@ -353,7 +353,7 @@ static int mqx_update_threads(
uint32_t task_name_addr = 0, task_id = 0, task_errno = 0;
uint32_t state_index = 0, state_max = 0;
uint32_t extra_info_length = 0;
char *state_name = "unknown state";
char *state_name = "Unknown";
/* set current taskpool address */
if (ERROR_OK != mqx_get_member(
@@ -435,13 +435,13 @@ static int mqx_update_threads(
* calculate length as:
* state length + address length + errno length + formatter length
*/
extra_info_length += strlen((void *)state_name) + 8 + 8 + 8;
extra_info_length += strlen((void *)state_name) + 7 + 13 + 8 + 15 + 8;
rtos->thread_details[i].extra_info_str = malloc(extra_info_length + 1);
if (NULL == rtos->thread_details[i].extra_info_str)
return ERROR_FAIL;
snprintf(
rtos->thread_details[i].extra_info_str, extra_info_length, "%s : 0x%"PRIx32 " : %" PRIu32,
state_name, task_addr, task_errno
snprintf(rtos->thread_details[i].extra_info_str, extra_info_length,
"State: %s, Address: 0x%" PRIx32 ", Error Code: %" PRIu32,
state_name, task_addr, task_errno
);
/* set active thread */
if (active_td_addr == task_addr)

View File

@@ -306,14 +306,14 @@ int rtos_thread_packet(struct connection *connection, char const *packet, int pa
if (detail->extra_info_str != NULL)
str_size += strlen(detail->extra_info_str);
char *tmp_str = calloc(str_size + 4, sizeof(char));
char *tmp_str = calloc(str_size + 9, sizeof(char));
char *tmp_str_ptr = tmp_str;
if (detail->thread_name_str != NULL)
tmp_str_ptr += sprintf(tmp_str_ptr, "%s", detail->thread_name_str);
tmp_str_ptr += sprintf(tmp_str_ptr, "Name: %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, ", ");
tmp_str_ptr += sprintf(tmp_str_ptr, "%s", detail->extra_info_str);
}