rtos: support gdb_get_register_packet

This patch adds support for p packet responses by targets configured
with RTOS support. This change required moving to a rtos_reg struct,
which is similar to struct reg used by targets, which resulted in
needing to update each stacking with register numbers. This patch also
allows targets with non-linear register numbers to function with RTOSes
as well.

Change-Id: I5b189d74110d6b6f2fa851a67ab0762ae6b1832f
Signed-off-by: Steven Stallion <stallion@squareup.com>
Reviewed-on: http://openocd.zylin.com/4121
Tested-by: jenkins
Reviewed-by: Matthias Welwarsky <matthias@welwarsky.de>
This commit is contained in:
Steven Stallion
2017-05-03 12:46:11 -05:00
committed by Matthias Welwarsky
parent b5964191f0
commit d92adf8abf
18 changed files with 470 additions and 471 deletions

View File

@@ -144,16 +144,6 @@ static int linux_read_memory(struct target *target,
return ERROR_OK;
}
static char *reg_converter(char *buffer, void *reg, int size)
{
int i;
for (i = 0; i < size; i++)
buffer += sprintf(buffer, "%02x", ((uint8_t *) reg)[i]);
return buffer;
}
int fill_buffer(struct target *target, uint32_t addr, uint8_t *buffer)
{
@@ -174,15 +164,13 @@ uint32_t get_buffer(struct target *target, const uint8_t *buffer)
}
static int linux_os_thread_reg_list(struct rtos *rtos,
int64_t thread_id, char **hex_reg_list)
int64_t thread_id, struct rtos_reg **reg_list, int *num_regs)
{
struct target *target = rtos->target;
struct linux_os *linux_os = (struct linux_os *)
target->rtos->rtos_specific_params;
int i = 0;
struct current_thread *tmp = linux_os->current_threads;
struct current_thread *next;
char *hex_string;
int found = 0;
int retval;
/* check if a current thread is requested */
@@ -195,117 +183,52 @@ static int linux_os_thread_reg_list(struct rtos *rtos,
next = next->next;
} while ((found == 0) && (next != tmp) && (next != NULL));
if (found == 1) {
/* search target to perfom the access */
struct reg **reg_list;
int reg_list_size, reg_packet_size = 0;
struct target_list *head;
head = target->head;
found = 0;
do {
if (head->target->coreid == next->core_id) {
target = head->target;
found = 1;
} else
head = head->next;
} while ((head != (struct target_list *)NULL) && (found == 0));
if (found == 0) {
LOG_ERROR
(
"current thread %" PRIx64 ": no target to perform access of core id %" PRIx32,
thread_id,
next->core_id);
return ERROR_FAIL;
}
/*LOG_INFO("thread %lx current on core %x",thread_id,
* target->coreid);*/
retval =
target_get_gdb_reg_list(target, &reg_list, &reg_list_size,
REG_CLASS_GENERAL);
if (retval != ERROR_OK)
return retval;
for (i = 0; i < reg_list_size; i++)
reg_packet_size += reg_list[i]->size;
assert(reg_packet_size > 0);
*hex_reg_list = malloc(DIV_ROUND_UP(reg_packet_size, 8) * 2);
hex_string = *hex_reg_list;
for (i = 0; i < reg_list_size; i++) {
if (!reg_list[i]->valid)
reg_list[i]->type->get(reg_list[i]);
hex_string = reg_converter(hex_string,
reg_list[i]->value,
(reg_list[i]->size) / 8);
}
free(reg_list);
} else {
struct threads *temp = linux_os->thread_list;
*hex_reg_list = calloc(1, 500 * sizeof(char));
hex_string = *hex_reg_list;
for (i = 0; i < 16; i++)
hex_string += sprintf(hex_string, "%02x", 0);
while ((temp != NULL) &&
(temp->threadid != target->rtos->current_threadid))
temp = temp->next;
if (temp != NULL) {
if (temp->context == NULL)
temp->context = cpu_context_read(target,
temp->
base_addr,
&temp->
thread_info_addr);
hex_string =
reg_converter(hex_string, &temp->context->R4, 4);
hex_string =
reg_converter(hex_string, &temp->context->R5, 4);
hex_string =
reg_converter(hex_string, &temp->context->R6, 4);
hex_string =
reg_converter(hex_string, &temp->context->R7, 4);
hex_string =
reg_converter(hex_string, &temp->context->R8, 4);
hex_string =
reg_converter(hex_string, &temp->context->R9, 4);
for (i = 0; i < 4; i++) /*R10 = 0x0 */
hex_string += sprintf(hex_string, "%02x", 0);
hex_string =
reg_converter(hex_string, &temp->context->FP, 4);
hex_string =
reg_converter(hex_string, &temp->context->IP, 4);
hex_string =
reg_converter(hex_string, &temp->context->SP, 4);
for (i = 0; i < 4; i++)
hex_string += sprintf(hex_string, "%02x", 0);
hex_string =
reg_converter(hex_string, &temp->context->PC, 4);
for (i = 0; i < 100; i++) /*100 */
hex_string += sprintf(hex_string, "%02x", 0);
uint32_t cpsr = 0x00000000;
reg_converter(hex_string, &cpsr, 4);
}
if (found == 0) {
LOG_ERROR("could not find thread: %" PRIx64, thread_id);
return ERROR_FAIL;
}
/* search target to perfom the access */
struct reg **gdb_reg_list;
struct target_list *head;
head = target->head;
found = 0;
do {
if (head->target->coreid == next->core_id) {
target = head->target;
found = 1;
} else
head = head->next;
} while ((head != (struct target_list *)NULL) && (found == 0));
if (found == 0) {
LOG_ERROR
(
"current thread %" PRIx64 ": no target to perform access of core id %" PRIx32,
thread_id,
next->core_id);
return ERROR_FAIL;
}
/*LOG_INFO("thread %lx current on core %x",thread_id, target->coreid);*/
retval = target_get_gdb_reg_list(target, &gdb_reg_list, num_regs, REG_CLASS_GENERAL);
if (retval != ERROR_OK)
return retval;
*reg_list = calloc(*num_regs, sizeof(struct rtos_reg));
for (int i = 0; i < *num_regs; ++i) {
if (!gdb_reg_list[i]->valid)
gdb_reg_list[i]->type->get(gdb_reg_list[i]);
(*reg_list)[i].number = gdb_reg_list[i]->number;
(*reg_list)[i].size = gdb_reg_list[i]->size;
buf_cpy(gdb_reg_list[i]->value, (*reg_list)[i].value, (*reg_list)[i].size);
}
return ERROR_OK;
}