From: Hsiangkai W. <hsi...@gm...> - 2013-06-13 02:55:28
|
Hi, Franck, I agree your enhancement. I will do some modification and merge your patch in commit 1382. Thanks. 2013/6/10 Franck Jullien <fra...@gm...> > H > siangkai Wang, > > Could you try this patch on your target ? It implies only some minor > changes in your target code. > This way, the tdesc thing will be compatible with my openrisc port. > > Thanks. > > > 2013/6/9 <fra...@gm...> > > From: Franck Jullien <fra...@gm...> >> >> 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 <fra...@gm...> >> --- >> 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 >> >> > |