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, &reg_list, 
&reg_list_size,
-                               reg_class);
+       retval = target_get_gdb_reg_list(target, &reg_list, &reg_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

Reply via email to