Combine SMP group registers into one list for gdb
This makes behavior when you've configured an SMP group of heterogeneous targets a bit less weird. (You still shouldn't be doing that, since gdb and who knows what else assumes that the targets in an SMP group are homogeneous.) Specifically, if you have a HiFive Unleashed board (where the first core is fairly basic and the other 4 or more full-featured) this lets you connect to all 5, and still have access to the FPU etc. on the higher numbered cores. Change-Id: I2e01f63f8753f78c29d7f414ea603e02bf0390e0
This commit is contained in:
parent
91d00468b6
commit
885260505a
|
@ -2196,6 +2196,78 @@ static int get_reg_features_list(struct target *target, char const **feature_lis
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Create a register list that's the union of all the registers of the SMP
|
||||||
|
* group this target is in. If the target is not part of an SMP group, this
|
||||||
|
* returns the same as target_get_gdb_reg_list_noread().
|
||||||
|
*/
|
||||||
|
static int smp_reg_list_noread(struct target *target,
|
||||||
|
struct reg **combined_list[], int *combined_list_size,
|
||||||
|
enum target_register_class reg_class)
|
||||||
|
{
|
||||||
|
if (!target->smp)
|
||||||
|
return target_get_gdb_reg_list_noread(target, combined_list,
|
||||||
|
combined_list_size, REG_CLASS_ALL);
|
||||||
|
|
||||||
|
int combined_allocated = 256;
|
||||||
|
*combined_list = malloc(combined_allocated * sizeof(struct reg *));
|
||||||
|
if (*combined_list == NULL) {
|
||||||
|
LOG_ERROR("malloc(%d) failed", (int) (combined_allocated * sizeof(struct reg *)));
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
*combined_list_size = 0;
|
||||||
|
struct target_list *head;
|
||||||
|
foreach_smp_target(head, target->head) {
|
||||||
|
struct reg **reg_list = NULL;
|
||||||
|
int reg_list_size;
|
||||||
|
int result = target_get_gdb_reg_list_noread(head->target, ®_list,
|
||||||
|
®_list_size, reg_class);
|
||||||
|
if (result != ERROR_OK) {
|
||||||
|
free(*combined_list);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < reg_list_size; i++) {
|
||||||
|
bool found = false;
|
||||||
|
struct reg *a = reg_list[i];
|
||||||
|
if (a->exist) {
|
||||||
|
/* Nested loop makes this O(n^2), but this entire function with
|
||||||
|
* 5 RISC-V targets takes just 2ms on my computer. Fast enough
|
||||||
|
* for me. */
|
||||||
|
for (int j = 0; j < *combined_list_size; j++) {
|
||||||
|
struct reg *b = (*combined_list)[j];
|
||||||
|
if (!strcmp(a->name, b->name)) {
|
||||||
|
found = true;
|
||||||
|
if (a->size != b->size) {
|
||||||
|
LOG_ERROR("SMP register %s is %d bits on one "
|
||||||
|
"target, but %d bits on another target.",
|
||||||
|
a->name, a->size, b->size);
|
||||||
|
free(reg_list);
|
||||||
|
free(*combined_list);
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
LOG_DEBUG("[%s] %s not found in combined list", target_name(target), a->name);
|
||||||
|
if (*combined_list_size >= combined_allocated) {
|
||||||
|
combined_allocated *= 2;
|
||||||
|
*combined_list = realloc(*combined_list, combined_allocated * sizeof(struct reg *));
|
||||||
|
if (*combined_list == NULL) {
|
||||||
|
LOG_ERROR("realloc(%d) failed", (int) (combined_allocated * sizeof(struct reg *)));
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(*combined_list)[*combined_list_size] = a;
|
||||||
|
(*combined_list_size)++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(reg_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static int gdb_generate_target_description(struct target *target, char **tdesc_out)
|
static int gdb_generate_target_description(struct target *target, char **tdesc_out)
|
||||||
{
|
{
|
||||||
int retval = ERROR_OK;
|
int retval = ERROR_OK;
|
||||||
|
@ -2212,8 +2284,8 @@ static int gdb_generate_target_description(struct target *target, char **tdesc_o
|
||||||
|
|
||||||
arch_defined_types = calloc(1, sizeof(char *));
|
arch_defined_types = calloc(1, sizeof(char *));
|
||||||
|
|
||||||
retval = target_get_gdb_reg_list_noread(target, ®_list,
|
retval = smp_reg_list_noread(target, ®_list, ®_list_size,
|
||||||
®_list_size, REG_CLASS_ALL);
|
REG_CLASS_ALL);
|
||||||
|
|
||||||
if (retval != ERROR_OK) {
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("get register list failed");
|
LOG_ERROR("get register list failed");
|
||||||
|
|
Loading…
Reference in New Issue