This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[target-description] enum and typed fields in struct


Would it be nice if âprint $cpsrâ shows
`$1 = {[ #4 T C Z ], M = User, IT_cond = 0, GE = 0, DNM = 0}'
instead of `$1 = 1610612784' ?

Current target-description does not support enum type,
and typed bit-fields are not allowed. However, non-GPRRs
usually consist of flags and bit-fields, and it is likely
bit-fields are not just magic numbers but symbolic constants.

In this patch, I implement enum for target-description,
typed bit-fields and c-tdesc for struct and enum. So we can
use the following tdesc XML to describe, for example, ARM cprs registers.

Any idea?

Wei-cheng

  <flags id="arm_cpsr_flags" size="4">
    <field name="T" start="5" end="5"/>
    <field name="F" start="6" end="6"/>
    <field name="I" start="7" end="7"/>
    <field name="A" start="8" end="8"/>
    <field name="E" start="9" end="9"/>
    <field name="c" start="10" end="10"/>
    <field name="b" start="11" end="11"/>
    <field name="a" start="12" end="12"/>
    <field name="J" start="24" end="24"/>
    <field name="e" start="25" end="25"/>
    <field name="d" start="26" end="26"/>
    <field name="Q" start="27" end="27"/>
    <field name="V" start="28" end="28"/>
    <field name="C" start="29" end="29"/>
    <field name="Z" start="30" end="30"/>
    <field name="N" start="31" end="31"/>
  </flags>
  <enum id="arm_cpsr_mode" size="1">
    <field name="User" start="16" end="16"/>
    <field name="FIQ" start="17" end="17"/>
    <field name="IRQ" start="18" end="18"/>
    <field name="Supervisor" start="19" end="19"/>
    <field name="Abort" start="20" end="20"/>
    <field name="Undefined" start="27" end="27"/>
    <field name="System" start="31" end="31"/>
  </enum>
  <struct id="arm_cpsr" size="4">
    <field name="" type="arm_cpsr_flags" start="0" end="31"/>
    <field name="M" type="arm_cpsr_mode" start="0" end="4"/>
    <field name="IT_cond" type="uint8" start="14" end="15"/>
    <field name="GE" type="uint8" start="16" end="19"/>
    <field name="DNM" type="uint8" start="20" end="23"/>
  </struct>
  <reg name="cpsr" bitsize="32" type="arm_cpsr" regnum="25"/>


#	modified:   gdb/features/gdb-target.dtd
#	modified:   gdb/gdbtypes.c
#	modified:   gdb/gdbtypes.h
#	modified:   gdb/target-descriptions.c
#	modified:   gdb/target-descriptions.h
#	modified:   gdb/xml-tdesc.c
diff --git a/gdb/features/gdb-target.dtd b/gdb/features/gdb-target.dtd
index fd7dac3..ea4f7ce 100644
--- a/gdb/features/gdb-target.dtd
+++ b/gdb/features/gdb-target.dtd
@@ -45,6 +45,11 @@
 	id		CDATA	#REQUIRED
 	size		CDATA	#REQUIRED>

+<!ELEMENT enum		(field+)>
+<!ATTLIST enum
+	id		CDATA	#REQUIRED
+	size		CDATA	#REQUIRED>
+
 <!ELEMENT struct	(field+)>
 <!ATTLIST struct
 	id		CDATA	#REQUIRED
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index 2bdb4eb..7aa5631 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -3632,7 +3632,7 @@ append_composite_type_field_raw (struct type *t,
char *name,

 /* Add new field with name NAME and type FIELD to composite type T.
    ALIGNMENT (if non-zero) specifies the minimum field alignment.  */
-void
+struct field *
 append_composite_type_field_aligned (struct type *t, char *name,
 				     struct type *field, int alignment)
 {
@@ -3664,14 +3664,15 @@ append_composite_type_field_aligned (struct
type *t, char *name,
 	    }
 	}
     }
+  return f;
 }

 /* Add new field with name NAME and type FIELD to composite type T.  */
-void
+struct field *
 append_composite_type_field (struct type *t, char *name,
 			     struct type *field)
 {
-  append_composite_type_field_aligned (t, name, field, 0);
+  return append_composite_type_field_aligned (t, name, field, 0);
 }


diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index 60da35b..b6b9bb3 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -1311,9 +1311,9 @@ extern struct type *arch_complex_type (struct
gdbarch *, char *,

 extern struct type *arch_composite_type (struct gdbarch *gdbarch,
 					 char *name, enum type_code code);
-extern void append_composite_type_field (struct type *t, char *name,
+extern struct field *append_composite_type_field (struct type *t, char *name,
 					 struct type *field);
-extern void append_composite_type_field_aligned (struct type *t,
+extern struct field *append_composite_type_field_aligned (struct type *t,
 						 char *name,
 						 struct type *field,
 						 int alignment);
diff --git a/gdb/target-descriptions.c b/gdb/target-descriptions.c
index a3096d7..edecc0d 100644
--- a/gdb/target-descriptions.c
+++ b/gdb/target-descriptions.c
@@ -132,7 +132,8 @@ typedef struct tdesc_type
     TDESC_TYPE_VECTOR,
     TDESC_TYPE_STRUCT,
     TDESC_TYPE_UNION,
-    TDESC_TYPE_FLAGS
+    TDESC_TYPE_FLAGS,
+    TDESC_TYPE_ENUM
   } kind;

   /* Kind-specific data.  */
@@ -152,7 +153,7 @@ typedef struct tdesc_type
       LONGEST size;
     } u;

-    /* Flags type.  */
+    /* Flags or enum type.  */
     struct
     {
       VEC(tdesc_type_flag) *flags;
@@ -630,13 +631,16 @@ tdesc_gdb_type (struct gdbarch *gdbarch, struct
tdesc_type *tdesc_type)
 	     VEC_iterate (tdesc_type_field, tdesc_type->u.u.fields, ix, f);
 	     ix++)
 	  {
+	    struct field *fld;
+	    struct type *field_type;
+	    int bitsize, total_size;
+
+	    /* This code should backward compatible with old tdesc.
+	       For non-sized struct with typed-fields,
+	       the size of struct should be the sum of size of all fields.
+	       append_composite_type_field()  */
 	    if (f->type == NULL)
 	      {
-		/* Bitfield.  */
-		struct field *fld;
-		struct type *field_type;
-		int bitsize, total_size;
-
 		/* This invariant should be preserved while creating
 		   types.  */
 		gdb_assert (tdesc_type->u.u.size != 0);
@@ -647,28 +651,42 @@ tdesc_gdb_type (struct gdbarch *gdbarch, struct
tdesc_type *tdesc_type)

 		fld = append_composite_type_field_raw (type, xstrdup (f->name),
 						       field_type);
-
-		/* For little-endian, BITPOS counts from the LSB of
-		   the structure and marks the LSB of the field.  For
-		   big-endian, BITPOS counts from the MSB of the
-		   structure and marks the MSB of the field.  Either
-		   way, it is the number of bits to the "left" of the
-		   field.  To calculate this in big-endian, we need
-		   the total size of the structure.  */
-		bitsize = f->end - f->start + 1;
-		total_size = tdesc_type->u.u.size * TARGET_CHAR_BIT;
-		if (gdbarch_bits_big_endian (gdbarch))
-		  FIELD_BITPOS (fld[0]) = total_size - f->start - bitsize;
-		else
-		  FIELD_BITPOS (fld[0]) = f->start;
-		FIELD_BITSIZE (fld[0]) = bitsize;
 	      }
 	    else
 	      {
 		field_type = tdesc_gdb_type (gdbarch, f->type);
-		append_composite_type_field (type, xstrdup (f->name),
+		fld = append_composite_type_field (type, xstrdup (f->name),
 					     field_type);
 	      }
+
+	    /* This will turn all fields into bitfileds */
+	    if (f->start == -1)
+	      {
+		if (TYPE_NFIELDS (type) > 1)
+		  f->start = (FIELD_BITPOS (fld[-1]) + FIELD_BITSIZE (fld[-1]));
+		else
+		  f->start = 0;
+	      }
+	    if (f->end == -1)
+	      {
+		f->end = f->start - 1 + TYPE_LENGTH (field_type)
+					* TARGET_CHAR_BIT;
+	      }
+
+	    /* For little-endian, BITPOS counts from the LSB of
+	       the structure and marks the LSB of the field.  For
+	       big-endian, BITPOS counts from the MSB of the
+	       structure and marks the MSB of the field.  Either
+	       way, it is the number of bits to the "left" of the
+	       field.  To calculate this in big-endian, we need
+	       the total size of the structure.  */
+	    bitsize = f->end - f->start + 1;
+	    total_size = tdesc_type->u.u.size * TARGET_CHAR_BIT;
+	    if (gdbarch_bits_big_endian (gdbarch))
+	      FIELD_BITPOS (fld[0]) = total_size - f->start - bitsize;
+	    else
+	      FIELD_BITPOS (fld[0]) = f->start;
+	    FIELD_BITSIZE (fld[0]) = bitsize;
 	  }

 	if (tdesc_type->u.u.size != 0)
@@ -719,6 +737,27 @@ tdesc_gdb_type (struct gdbarch *gdbarch, struct
tdesc_type *tdesc_type)

 	return type;
       }
+
+    case TDESC_TYPE_ENUM:
+      {
+	struct tdesc_type_flag *f;
+	int ix;
+
+	type = arch_type (gdbarch, TYPE_CODE_ENUM,
+			  tdesc_type->u.f.size, tdesc_type->name);
+	TYPE_UNSIGNED (type) = 1;
+	for (ix = 0;
+	     VEC_iterate (tdesc_type_flag, tdesc_type->u.f.flags, ix, f);
+	     ix++)
+	  {
+	    struct field *fld;
+	    fld = append_composite_type_field_raw (type,
+					xstrdup (f->name), NULL);
+	    FIELD_BITPOS (fld[0]) = f->start;
+	  }
+
+	return type;
+      }
     }

   internal_error (__FILE__, __LINE__,
@@ -1220,6 +1259,7 @@ tdesc_free_type (struct tdesc_type *type)
       }
       break;

+    case TDESC_TYPE_ENUM:
     case TDESC_TYPE_FLAGS:
       {
 	struct tdesc_type_flag *f;
@@ -1306,6 +1346,20 @@ tdesc_create_flags (struct tdesc_feature
*feature, const char *name,
   return type;
 }

+struct tdesc_type *
+tdesc_create_enum (struct tdesc_feature *feature, const char *name,
+		    LONGEST size)
+{
+  struct tdesc_type *type = XZALLOC (struct tdesc_type);
+
+  type->name = xstrdup (name);
+  type->kind = TDESC_TYPE_ENUM;
+  type->u.f.size = size;
+
+  VEC_safe_push (tdesc_type_p, feature->types, type);
+  return type;
+}
+
 /* Add a new field.  Return a temporary pointer to the field, which
    is only valid until the next call to tdesc_add_field (the vector
    might be reallocated).  */
@@ -1321,6 +1375,8 @@ tdesc_add_field (struct tdesc_type *type, const
char *field_name,

   f.name = xstrdup (field_name);
   f.type = field_type;
+  f.start = -1;
+  f.end = -1;

   VEC_safe_push (tdesc_type_field, type->u.u.fields, &f);
 }
@@ -1329,7 +1385,7 @@ tdesc_add_field (struct tdesc_type *type, const
char *field_name,

 void
 tdesc_add_bitfield (struct tdesc_type *type, const char *field_name,
-		    int start, int end)
+		    int start, int end, struct tdesc_type *field_type)
 {
   struct tdesc_type_field f = { 0 };

@@ -1338,6 +1394,7 @@ tdesc_add_bitfield (struct tdesc_type *type,
const char *field_name,
   f.name = xstrdup (field_name);
   f.start = start;
   f.end = end;
+  f.type = field_type;

   VEC_safe_push (tdesc_type_field, type->u.u.fields, &f);
 }
@@ -1348,7 +1405,8 @@ tdesc_add_flag (struct tdesc_type *type, int start,
 {
   struct tdesc_type_flag f = { 0 };

-  gdb_assert (type->kind == TDESC_TYPE_FLAGS);
+  gdb_assert (type->kind == TDESC_TYPE_FLAGS
+	      || type->kind == TDESC_TYPE_ENUM);

   f.name = xstrdup (flag_name);
   f.start = start;
@@ -1664,6 +1722,27 @@ feature = tdesc_create_feature (result, \"%s\");\n",
 		     f->name);
 		}
 	      break;
+	    case TDESC_TYPE_STRUCT:
+	      printf_unfiltered
+		("  type = tdesc_create_struct (feature, \"%s\");\n",
+		 type->name);
+	      for (ix3 = 0;
+		   VEC_iterate (tdesc_type_field, type->u.u.fields, ix3, f);
+		   ix3++)
+		{
+		  printf_unfiltered
+		    ("  field_type = tdesc_named_type (feature, \"%s\");\n",
+		     f->type->name);
+		  if (f->start == -1 || f->end == -1)
+		    printf_unfiltered
+		      ("  tdesc_add_field (type, \"%s\", field_type);\n",
+		       f->name);
+		  else
+		    printf_unfiltered
+		      ("  tdesc_add_bitfield (type, \"%s\", %d, %d, field_type);\n",
+		       f->name, f->start, f->end);
+		}
+	      break;
 	    case TDESC_TYPE_FLAGS:
 	      printf_unfiltered
 		("  field_type = tdesc_create_flags (feature, \"%s\", %d);\n",
@@ -1676,6 +1755,18 @@ feature = tdesc_create_feature (result, \"%s\");\n",
 		  ("  tdesc_add_flag (field_type, %d, \"%s\");\n",
 		   flag->start, flag->name);
 	      break;
+	    case TDESC_TYPE_ENUM:
+	      printf_unfiltered
+		("  field_type = tdesc_create_enum (feature, \"%s\", %d);\n",
+		 type->name, (int) type->u.f.size);
+	      for (ix3 = 0;
+		   VEC_iterate (tdesc_type_flag, type->u.f.flags, ix3,
+				flag);
+		   ix3++)
+		printf_unfiltered
+		  ("  tdesc_add_flag (field_type, %d, \"%s\");\n",
+		   flag->start, flag->name);
+	      break;
 	    default:
 	      error (_("C output is not supported type \"%s\"."), type->name);
 	    }
diff --git a/gdb/target-descriptions.h b/gdb/target-descriptions.h
index 5f0b7d5..810d88b 100644
--- a/gdb/target-descriptions.h
+++ b/gdb/target-descriptions.h
@@ -214,10 +214,13 @@ struct tdesc_type *tdesc_create_union (struct
tdesc_feature *feature,
 struct tdesc_type *tdesc_create_flags (struct tdesc_feature *feature,
 				       const char *name,
 				       LONGEST size);
+struct tdesc_type *tdesc_create_enum (struct tdesc_feature *feature,
+				       const char *name,
+				       LONGEST size);
 void tdesc_add_field (struct tdesc_type *type, const char *field_name,
 		      struct tdesc_type *field_type);
 void tdesc_add_bitfield (struct tdesc_type *type, const char *field_name,
-			 int start, int end);
+			 int start, int end, struct tdesc_type *field_type);
 void tdesc_add_flag (struct tdesc_type *type, int start,
 		     const char *flag_name);
 void tdesc_create_reg (struct tdesc_feature *feature, const char *name,
diff --git a/gdb/xml-tdesc.c b/gdb/xml-tdesc.c
index 5073e7b..318554d 100644
--- a/gdb/xml-tdesc.c
+++ b/gdb/xml-tdesc.c
@@ -286,6 +286,24 @@ tdesc_start_flags (struct gdb_xml_parser *parser,
   data->current_type_is_flags = 1;
 }

+static void
+tdesc_start_enum (struct gdb_xml_parser *parser,
+		  const struct gdb_xml_element *element,
+		  void *user_data, VEC(gdb_xml_value_s) *attributes)
+{
+  struct tdesc_parsing_data *data = user_data;
+  char *id = xml_find_attribute (attributes, "id")->value;
+  int length = (int) * (ULONGEST *)
+    xml_find_attribute (attributes, "size")->value;
+  struct tdesc_type *type;
+
+  type = tdesc_create_enum (data->current_feature, id, length);
+
+  data->current_type = type;
+  data->current_type_size = 0;
+  data->current_type_is_flags = 1;
+}
+
 /* Handle the start of a <field> element.  Attach the field to the
    current struct or union.  */

@@ -304,9 +322,15 @@ tdesc_start_field (struct gdb_xml_parser *parser,

   attr = xml_find_attribute (attributes, "type");
   if (attr != NULL)
-    field_type_id = attr->value;
+    {
+      field_type_id = attr->value;
+      field_type = tdesc_named_type (data->current_feature, field_type_id);
+    }
   else
-    field_type_id = NULL;
+    {
+      field_type_id = NULL;
+      field_type = NULL;
+    }

   attr = xml_find_attribute (attributes, "start");
   if (attr != NULL)
@@ -320,26 +344,7 @@ tdesc_start_field (struct gdb_xml_parser *parser,
   else
     end = -1;

-  if (field_type_id != NULL)
-    {
-      if (data->current_type_is_flags)
-	gdb_xml_error (parser, _("Cannot add typed field \"%s\" to flags"),
-		       field_name);
-      if (data->current_type_size != 0)
-	gdb_xml_error (parser,
-		       _("Explicitly sized type can not "
-			 "contain non-bitfield \"%s\""),
-		       field_name);
-
-      field_type = tdesc_named_type (data->current_feature, field_type_id);
-      if (field_type == NULL)
-	gdb_xml_error (parser, _("Field \"%s\" references undefined "
-				 "type \"%s\""),
-		       field_name, field_type_id);
-
-      tdesc_add_field (data->current_type, field_name, field_type);
-    }
-  else if (start != -1 && end != -1)
+  if (start != -1 && end != -1)
     {
       struct tdesc_type *t = data->current_type;

@@ -371,9 +376,22 @@ tdesc_start_field (struct gdb_xml_parser *parser,
 	    gdb_xml_error (parser,
 			   _("Bitfield \"%s\" does not fit in struct"));

-	  tdesc_add_bitfield (t, field_name, start, end);
+	  tdesc_add_bitfield (t, field_name, start, end, field_type);
 	}
     }
+  else if (field_type_id != NULL)
+    {
+      if (data->current_type_is_flags)
+	gdb_xml_error (parser, _("Cannot add typed field \"%s\" to flags"),
+		       field_name);
+
+      if (field_type == NULL)
+	gdb_xml_error (parser, _("Field \"%s\" references undefined "
+				 "type \"%s\""),
+		       field_name, field_type_id);
+
+      tdesc_add_field (data->current_type, field_name, field_type);
+    }
   else
     gdb_xml_error (parser, _("Field \"%s\" has neither type nor bit position"),
 		   field_name);
@@ -444,6 +462,12 @@ static const struct gdb_xml_attribute
flags_attributes[] = {
   { NULL, GDB_XML_AF_NONE, NULL, NULL }
 };

+static const struct gdb_xml_attribute enum_attributes[] = {
+  { "id", GDB_XML_AF_NONE, NULL, NULL },
+  { "size", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL},
+  { NULL, GDB_XML_AF_NONE, NULL, NULL }
+};
+
 static const struct gdb_xml_attribute vector_attributes[] = {
   { "id", GDB_XML_AF_NONE, NULL, NULL },
   { "type", GDB_XML_AF_NONE, NULL, NULL },
@@ -469,6 +493,9 @@ static const struct gdb_xml_element feature_children[] = {
   { "flags", flags_attributes, struct_union_children,
     GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
     tdesc_start_flags, NULL },
+  { "enum", enum_attributes, struct_union_children,
+    GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
+    tdesc_start_enum, NULL },
   { "vector", vector_attributes, NULL,
     GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
     tdesc_start_vector, NULL },


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]