This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[target-description] enum and typed fields in struct
- From: Wei-cheng Wang <cole945 at gmail dot com>
- To: gdb-patches at sourceware dot org
- Date: Fri, 3 Jun 2011 19:05:39 +0800
- Subject: [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 },