From: Franck Jullien <[email protected]> This patch adds the possibility to create feature sections from the feature name. The feature name can be anything.
It also adds a command to save the tdesc file (for debug purpose). Change-Id: I47f51028c6a1a2a2bb41e61170438e576eb05890 Signed-off-by: Franck Jullien <[email protected]> --- src/server/gdb_server.c | 223 +++++++++++++++++++++++++++++++++-------------- src/target/register.h | 8 +-- 2 files changed, 157 insertions(+), 74 deletions(-) diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index bcd1a66..5f9552f 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -1717,20 +1717,6 @@ static const char *gdb_get_reg_type_name(enum reg_type type) return "int"; /* "int" as default value */ } -static const char *gdb_get_reg_group_name(enum reg_group group) -{ - switch (group) { - case REG_GROUP_GENERAL: - return "general"; - case REG_GROUP_FLOAT: - return "float"; - case REG_GROUP_VECTOR: - return "vector"; - } - - return NULL; -} - static int gdb_generate_reg_type_description(struct target *target, char **tdesc, int *pos, int *size, struct reg_data_type *type) { @@ -1828,10 +1814,46 @@ static int gdb_generate_reg_type_description(struct target *target, return ERROR_OK; } +/* Get a list of available target registers features. feature_list must + * be freed by caller. + */ +int get_reg_features_list(struct target *target, char **feature_list[], int *feature_list_size, + struct reg **reg_list, int reg_list_size) +{ + int tbl_sz = 0; + + /* Start with only one element */ + *feature_list = calloc(1, sizeof(char *)); + + for (int i = 0; i < reg_list_size; i++) { + if (reg_list[i]->feature->name != NULL && strcmp(reg_list[i]->feature->name, "")) { + /* We found a feature, check if the feature is already in the + * table. If not, allocate a new entry for the table and + * put the new feature in it. + */ + 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 = realloc(*feature_list, sizeof(char *) * (tbl_sz + 1)); + (*feature_list)[tbl_sz] = NULL; + break; + } else { + if (!strcmp((*feature_list)[j], reg_list[i]->feature->name)) + break; + } + } + } + } + + if (feature_list_size) + *feature_list_size = tbl_sz; + + return ERROR_OK; +} + static int gdb_generate_target_description(struct target *target, char **tdesc) { int retval = ERROR_OK; - enum target_register_class reg_class; struct reg **reg_list; int reg_list_size; int pos = 0; @@ -1842,75 +1864,97 @@ static int gdb_generate_target_description(struct target *target, char **tdesc) "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">\n" "<target version=\"1.0\">\n"); - for (reg_class = REG_CLASS_GENERAL; reg_class != REG_CLASS_END; reg_class++) { - retval = target_get_gdb_reg_list(target, ®_list, ®_list_size, - reg_class); + retval = target_get_gdb_reg_list(target, ®_list, ®_list_size, + REG_CLASS_ALL); + + if (retval != ERROR_OK) { + LOG_ERROR("get register list failed"); + return ERROR_FAIL; + } - if (retval != ERROR_OK) { - LOG_ERROR("get register list %d failed", reg_class); - continue; - } + if (reg_list_size <= 0) + return ERROR_FAIL; - if (reg_list_size <= 0) - continue; + char **features = NULL; + /* Get a list of available target registers features */ + retval = get_reg_features_list(target, &features, NULL, reg_list, reg_list_size); + if (retval != ERROR_OK) { + LOG_ERROR("Can't get the registers feature list"); + return ERROR_FAIL; + } - /* generate target description according to register list */ - xml_printf(&retval, tdesc, &pos, &size, - "<feature name=\"%s\">\n", - reg_list[0]->feature->name); + /* If we found some features associated with registers, create sections */ + int current_feature = 0; - int i; - for (i = 0; i < reg_list_size; i++) { - const char *type_str; - if (reg_list[i]->reg_data_type != NULL) { - if (reg_list[i]->reg_data_type->type == REG_TYPE_ARCH_DEFINED) { - /* generate <type... first, if there are architecture-defined types. */ - gdb_generate_reg_type_description(target, tdesc, &pos, &size, - reg_list[i]->reg_data_type); - - type_str = reg_list[i]->reg_data_type->id; + /* generate target description according to register list */ + if (features != NULL) { + while (features[current_feature]) { + + xml_printf(&retval, tdesc, &pos, &size, + "<feature name=\"%s\">\n", + features[current_feature]); + + int i; + for (i = 0; i < reg_list_size; i++) { + + if (strcmp(reg_list[i]->feature->name, features[current_feature])) + continue; + + const char *type_str; + if (reg_list[i]->reg_data_type != NULL) { + if (reg_list[i]->reg_data_type->type == REG_TYPE_ARCH_DEFINED) { + /* generate <type... first, if there are architecture-defined types. */ + gdb_generate_reg_type_description(target, tdesc, &pos, &size, + reg_list[i]->reg_data_type); + + type_str = reg_list[i]->reg_data_type->id; + } else { + /* predefined type */ + type_str = gdb_get_reg_type_name( + reg_list[i]->reg_data_type->type); + } } else { - /* predefined type */ - type_str = gdb_get_reg_type_name( - reg_list[i]->reg_data_type->type); + /* Default type is "int" */ + type_str = "int"; } - } else { - /* Default type is "int" */ - type_str = "int"; - } - xml_printf(&retval, tdesc, &pos, &size, - "<reg name=\"%s\"", reg_list[i]->name); - xml_printf(&retval, tdesc, &pos, &size, - " bitsize=\"%d\"", reg_list[i]->size); - xml_printf(&retval, tdesc, &pos, &size, - " regnum=\"%d\"", reg_list[i]->number); - if (reg_list[i]->caller_save) xml_printf(&retval, tdesc, &pos, &size, - " save-restore=\"yes\""); - else + "<reg name=\"%s\"", reg_list[i]->name); + xml_printf(&retval, tdesc, &pos, &size, - " save-restore=\"no\""); + " bitsize=\"%d\"", reg_list[i]->size); - xml_printf(&retval, tdesc, &pos, &size, - " type=\"%s\"", type_str); + xml_printf(&retval, tdesc, &pos, &size, + " regnum=\"%d\"", reg_list[i]->number); + + if (reg_list[i]->caller_save) + xml_printf(&retval, tdesc, &pos, &size, + " save-restore=\"yes\""); + else + xml_printf(&retval, tdesc, &pos, &size, + " save-restore=\"no\""); - const char *group_str; - group_str = gdb_get_reg_group_name(reg_list[i]->group); - if (group_str != NULL) xml_printf(&retval, tdesc, &pos, &size, - " group=\"%s\"", group_str); + " type=\"%s\"", type_str); - xml_printf(&retval, tdesc, &pos, &size, - "/>\n"); - } + if (reg_list[i]->group != NULL) + xml_printf(&retval, tdesc, &pos, &size, + " group=\"%s\"", reg_list[i]->group); - xml_printf(&retval, tdesc, &pos, &size, - "</feature>\n"); + xml_printf(&retval, tdesc, &pos, &size, + "/>\n"); + } - free(reg_list); + xml_printf(&retval, tdesc, &pos, &size, + "</feature>\n"); + + current_feature++; + } } + free(reg_list); + free(features); + xml_printf(&retval, tdesc, &pos, &size, "</target>\n"); @@ -2658,6 +2702,45 @@ COMMAND_HANDLER(handle_gdb_target_description_command) return ERROR_OK; } +COMMAND_HANDLER(handle_gdb_save_tdesc) +{ + static char *tdesc; + static uint32_t tdesc_length; + struct target *target = get_current_target(CMD_CTX); + char *tdesc_filename; + + if (tdesc == NULL) { + gdb_generate_target_description(target, &tdesc); + tdesc_length = strlen(tdesc); + } + + struct fileio fileio; + size_t size_written; + + tdesc_filename = malloc(strlen(target_type_name(target)) + 5); + sprintf(tdesc_filename, "%s.xml", target_type_name(target)); + + int retval = fileio_open(&fileio, tdesc_filename, FILEIO_WRITE, FILEIO_TEXT); + + free(tdesc_filename); + + if (retval != ERROR_OK) { + LOG_WARNING("Can't open %s for writing", tdesc_filename); + return ERROR_FAIL; + } + + retval = fileio_write(&fileio, tdesc_length, tdesc, &size_written); + + fileio_close(&fileio); + + if (retval != ERROR_OK) { + LOG_WARNING("Error while writing the tdesc file"); + return ERROR_FAIL; + } + + return ERROR_OK; +} + static const struct command_registration gdb_command_handlers[] = { { .name = "gdb_sync", @@ -2717,6 +2800,12 @@ static const struct command_registration gdb_command_handlers[] = { .help = "enable or disable target description", .usage = "('enable'|'disable')" }, + { + .name = "save_tdesc", + .handler = handle_gdb_save_tdesc, + .mode = COMMAND_ANY, + .help = "print the target description file", + }, COMMAND_REGISTRATION_DONE }; diff --git a/src/target/register.h b/src/target/register.h index 25824bf..cffcf57 100644 --- a/src/target/register.h +++ b/src/target/register.h @@ -44,12 +44,6 @@ enum reg_type { REG_TYPE_ARCH_DEFINED, }; -enum reg_group { - REG_GROUP_GENERAL, - REG_GROUP_FLOAT, - REG_GROUP_VECTOR, -}; - struct reg_feature { const char *name; }; @@ -129,7 +123,7 @@ struct reg { bool valid; uint32_t size; struct reg_data_type *reg_data_type; - enum reg_group group; + const char *group; void *arch_info; const struct reg_arch_type *type; }; -- 1.7.1 ------------------------------------------------------------------------------ How ServiceNow helps IT people transform IT departments: 1. A cloud service to automate IT design, transition and operations 2. Dashboards that offer high-level views of enterprise services 3. A single system of record for all IT processes http://p.sf.net/sfu/servicenow-d2d-j _______________________________________________ OpenOCD-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/openocd-devel
