* gdbtypes.c (append_composite_type_field_raw): New.
(append_composite_type_field_aligned): Use the new function. * gdbtypes.h (append_composite_type_field_raw): Declare. * target-descriptions.c (struct tdesc_type_field): Add start and end. (struct tdesc_type_flag): New type. (struct tdesc_type): Add TDESC_TYPE_STRUCT and TDESC_TYPE_FLAGS to kind. Add size to u.u. Add u.f for flags. (tdesc_gdb_type): Handle TDESC_TYPE_STRUCT and TDESC_TYPE_FLAGS. (tdesc_free_type): Likewise. (tdesc_create_struct, tdesc_set_struct_size, tdesc_create_flags): New. (tdesc_add_field): Handle TDESC_TYPE_STRUCT. (tdesc_add_bitfield, tdesc_add_flag): New. * target-descriptions.h (tdesc_create_struct, tdesc_set_struct_size) (tdesc_create_flags, tdesc_add_bitfield, tdesc_add_flag): Declare. * xml-tdesc.c (struct tdesc_parsing_data): Rename current_union to current_type. Add current_type_size and current_type_is_flags. (tdesc_start_union): Clear the new fields. (tdesc_start_struct, tdesc_start_flags): New. (tdesc_start_field): Handle struct fields, including bitfields. (field_attributes): Make type optional. Add start and end. (union_children): Rename to struct_union_children. (union_attributes): Rename to struct_union_attributes. Add optional size. (flags_attributes): New. (feature_children): Add struct and flags. * features/gdb-target.dtd: Add flags and struct to features. Make field type optional. Add field start and end. doc/ * gdb.texinfo (Types): Describe <struct> and <flags>. testsuite/ * gdb.xml/extra-regs.xml: Add struct1, struct2, and flags types. Add structreg, bitfields, and flags registers. * gdb.xml/tdesc-regs.exp: Test structreg and bitfields registers.
This commit is contained in:
parent
bd56defd73
commit
f5dff77744
|
@ -1,3 +1,33 @@
|
||||||
|
2010-03-01 Daniel Jacobowitz <dan@codesourcery.com>
|
||||||
|
|
||||||
|
* gdbtypes.c (append_composite_type_field_raw): New.
|
||||||
|
(append_composite_type_field_aligned): Use the new function.
|
||||||
|
* gdbtypes.h (append_composite_type_field_raw): Declare.
|
||||||
|
* target-descriptions.c (struct tdesc_type_field): Add start and end.
|
||||||
|
(struct tdesc_type_flag): New type.
|
||||||
|
(struct tdesc_type): Add TDESC_TYPE_STRUCT and TDESC_TYPE_FLAGS to
|
||||||
|
kind. Add size to u.u. Add u.f for flags.
|
||||||
|
(tdesc_gdb_type): Handle TDESC_TYPE_STRUCT and TDESC_TYPE_FLAGS.
|
||||||
|
(tdesc_free_type): Likewise.
|
||||||
|
(tdesc_create_struct, tdesc_set_struct_size, tdesc_create_flags): New.
|
||||||
|
(tdesc_add_field): Handle TDESC_TYPE_STRUCT.
|
||||||
|
(tdesc_add_bitfield, tdesc_add_flag): New.
|
||||||
|
* target-descriptions.h (tdesc_create_struct, tdesc_set_struct_size)
|
||||||
|
(tdesc_create_flags, tdesc_add_bitfield, tdesc_add_flag): Declare.
|
||||||
|
* xml-tdesc.c (struct tdesc_parsing_data): Rename current_union to
|
||||||
|
current_type. Add current_type_size and current_type_is_flags.
|
||||||
|
(tdesc_start_union): Clear the new fields.
|
||||||
|
(tdesc_start_struct, tdesc_start_flags): New.
|
||||||
|
(tdesc_start_field): Handle struct fields, including bitfields.
|
||||||
|
(field_attributes): Make type optional. Add start and end.
|
||||||
|
(union_children): Rename to struct_union_children.
|
||||||
|
(union_attributes): Rename to struct_union_attributes. Add optional
|
||||||
|
size.
|
||||||
|
(flags_attributes): New.
|
||||||
|
(feature_children): Add struct and flags.
|
||||||
|
* features/gdb-target.dtd: Add flags and struct to features.
|
||||||
|
Make field type optional. Add field start and end.
|
||||||
|
|
||||||
2010-03-01 H.J. Lu <hongjiu.lu@intel.com>
|
2010-03-01 H.J. Lu <hongjiu.lu@intel.com>
|
||||||
|
|
||||||
* amd64-linux-nat.c (AMD64_LINUX_USER64_CS): New.
|
* amd64-linux-nat.c (AMD64_LINUX_USER64_CS): New.
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
2010-03-01 Daniel Jacobowitz <dan@codesourcery.com>
|
||||||
|
|
||||||
|
* gdb.texinfo (Types): Describe <struct> and <flags>.
|
||||||
|
|
||||||
2010-02-28 Phil Muldoon <pmuldoon@redhat.com>
|
2010-02-28 Phil Muldoon <pmuldoon@redhat.com>
|
||||||
|
|
||||||
* gdb.texinfo (Frames In Python): Add block parameter and
|
* gdb.texinfo (Frames In Python): Add block parameter and
|
||||||
|
|
|
@ -33073,6 +33073,47 @@ each of which has a @var{name} and a @var{type}:
|
||||||
</union>
|
</union>
|
||||||
@end smallexample
|
@end smallexample
|
||||||
|
|
||||||
|
@cindex <struct>
|
||||||
|
If a register's value is composed from several separate values, define
|
||||||
|
it with a structure type. There are two forms of the @samp{<struct>}
|
||||||
|
element; a @samp{<struct>} element must either contain only bitfields
|
||||||
|
or contain no bitfields. If the structure contains only bitfields,
|
||||||
|
its total size in bytes must be specified, each bitfield must have an
|
||||||
|
explicit start and end, and bitfields are automatically assigned an
|
||||||
|
integer type. The field's @var{start} should be less than or
|
||||||
|
equal to its @var{end}, and zero represents the least significant bit.
|
||||||
|
|
||||||
|
@smallexample
|
||||||
|
<struct id="@var{id}" size="@var{size}">
|
||||||
|
<field name="@var{name}" start="@var{start}" end="@var{end}"/>
|
||||||
|
@dots{}
|
||||||
|
</struct>
|
||||||
|
@end smallexample
|
||||||
|
|
||||||
|
If the structure contains no bitfields, then each field has an
|
||||||
|
explicit type, and no implicit padding is added.
|
||||||
|
|
||||||
|
@smallexample
|
||||||
|
<struct id="@var{id}">
|
||||||
|
<field name="@var{name}" type="@var{type}"/>
|
||||||
|
@dots{}
|
||||||
|
</struct>
|
||||||
|
@end smallexample
|
||||||
|
|
||||||
|
@cindex <flags>
|
||||||
|
If a register's value is a series of single-bit flags, define it with
|
||||||
|
a flags type. The @samp{<flags>} element has an explicit @var{size}
|
||||||
|
and contains one or more @samp{<field>} elements. Each field has a
|
||||||
|
@var{name}, a @var{start}, and an @var{end}. Only single-bit flags
|
||||||
|
are supported.
|
||||||
|
|
||||||
|
@smallexample
|
||||||
|
<flags id="@var{id}" size="@var{size}">
|
||||||
|
<field name="@var{name}" start="@var{start}" end="@var{end}"/>
|
||||||
|
@dots{}
|
||||||
|
</flags>
|
||||||
|
@end smallexample
|
||||||
|
|
||||||
@subsection Registers
|
@subsection Registers
|
||||||
@cindex <reg>
|
@cindex <reg>
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,8 @@
|
||||||
|
|
||||||
<!ELEMENT compatible (#PCDATA)>
|
<!ELEMENT compatible (#PCDATA)>
|
||||||
|
|
||||||
<!ELEMENT feature ((vector | union)*, reg*)>
|
<!ELEMENT feature
|
||||||
|
((vector | flags | struct | union )*, reg*)>
|
||||||
<!ATTLIST feature
|
<!ATTLIST feature
|
||||||
name ID #REQUIRED>
|
name ID #REQUIRED>
|
||||||
|
|
||||||
|
@ -39,6 +40,16 @@
|
||||||
type CDATA #REQUIRED
|
type CDATA #REQUIRED
|
||||||
count CDATA #REQUIRED>
|
count CDATA #REQUIRED>
|
||||||
|
|
||||||
|
<!ELEMENT flags (field+)>
|
||||||
|
<!ATTLIST flags
|
||||||
|
id CDATA #REQUIRED
|
||||||
|
size CDATA #REQUIRED>
|
||||||
|
|
||||||
|
<!ELEMENT struct (field+)>
|
||||||
|
<!ATTLIST struct
|
||||||
|
id CDATA #REQUIRED
|
||||||
|
size CDATA #IMPLIED>
|
||||||
|
|
||||||
<!ELEMENT union (field+)>
|
<!ELEMENT union (field+)>
|
||||||
<!ATTLIST union
|
<!ATTLIST union
|
||||||
id CDATA #REQUIRED>
|
id CDATA #REQUIRED>
|
||||||
|
@ -46,7 +57,9 @@
|
||||||
<!ELEMENT field EMPTY>
|
<!ELEMENT field EMPTY>
|
||||||
<!ATTLIST field
|
<!ATTLIST field
|
||||||
name CDATA #REQUIRED
|
name CDATA #REQUIRED
|
||||||
type CDATA #REQUIRED>
|
type CDATA #IMPLIED
|
||||||
|
start CDATA #IMPLIED
|
||||||
|
end CDATA #IMPLIED>
|
||||||
|
|
||||||
<!ENTITY % xinclude SYSTEM "xinclude.dtd">
|
<!ENTITY % xinclude SYSTEM "xinclude.dtd">
|
||||||
%xinclude;
|
%xinclude;
|
||||||
|
|
|
@ -3303,10 +3303,11 @@ arch_composite_type (struct gdbarch *gdbarch, char *name, enum type_code code)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add new field with name NAME and type FIELD to composite type T.
|
/* Add new field with name NAME and type FIELD to composite type T.
|
||||||
ALIGNMENT (if non-zero) specifies the minimum field alignment. */
|
Do not set the field's position or adjust the type's length;
|
||||||
void
|
the caller should do so. Return the new field. */
|
||||||
append_composite_type_field_aligned (struct type *t, char *name,
|
struct field *
|
||||||
struct type *field, int alignment)
|
append_composite_type_field_raw (struct type *t, char *name,
|
||||||
|
struct type *field)
|
||||||
{
|
{
|
||||||
struct field *f;
|
struct field *f;
|
||||||
TYPE_NFIELDS (t) = TYPE_NFIELDS (t) + 1;
|
TYPE_NFIELDS (t) = TYPE_NFIELDS (t) + 1;
|
||||||
|
@ -3316,6 +3317,16 @@ append_composite_type_field_aligned (struct type *t, char *name,
|
||||||
memset (f, 0, sizeof f[0]);
|
memset (f, 0, sizeof f[0]);
|
||||||
FIELD_TYPE (f[0]) = field;
|
FIELD_TYPE (f[0]) = field;
|
||||||
FIELD_NAME (f[0]) = name;
|
FIELD_NAME (f[0]) = name;
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add new field with name NAME and type FIELD to composite type T.
|
||||||
|
ALIGNMENT (if non-zero) specifies the minimum field alignment. */
|
||||||
|
void
|
||||||
|
append_composite_type_field_aligned (struct type *t, char *name,
|
||||||
|
struct type *field, int alignment)
|
||||||
|
{
|
||||||
|
struct field *f = append_composite_type_field_raw (t, name, field);
|
||||||
if (TYPE_CODE (t) == TYPE_CODE_UNION)
|
if (TYPE_CODE (t) == TYPE_CODE_UNION)
|
||||||
{
|
{
|
||||||
if (TYPE_LENGTH (t) < TYPE_LENGTH (field))
|
if (TYPE_LENGTH (t) < TYPE_LENGTH (field))
|
||||||
|
|
|
@ -1249,6 +1249,8 @@ extern void append_composite_type_field_aligned (struct type *t,
|
||||||
char *name,
|
char *name,
|
||||||
struct type *field,
|
struct type *field,
|
||||||
int alignment);
|
int alignment);
|
||||||
|
struct field *append_composite_type_field_raw (struct type *t, char *name,
|
||||||
|
struct type *field);
|
||||||
|
|
||||||
/* Helper functions to construct a bit flags type. An initially empty
|
/* Helper functions to construct a bit flags type. An initially empty
|
||||||
type is created using arch_flag_type(). Flags are then added using
|
type is created using arch_flag_type(). Flags are then added using
|
||||||
|
|
|
@ -90,9 +90,17 @@ typedef struct tdesc_type_field
|
||||||
{
|
{
|
||||||
char *name;
|
char *name;
|
||||||
struct tdesc_type *type;
|
struct tdesc_type *type;
|
||||||
|
int start, end;
|
||||||
} tdesc_type_field;
|
} tdesc_type_field;
|
||||||
DEF_VEC_O(tdesc_type_field);
|
DEF_VEC_O(tdesc_type_field);
|
||||||
|
|
||||||
|
typedef struct tdesc_type_flag
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
int start;
|
||||||
|
} tdesc_type_flag;
|
||||||
|
DEF_VEC_O(tdesc_type_flag);
|
||||||
|
|
||||||
typedef struct tdesc_type
|
typedef struct tdesc_type
|
||||||
{
|
{
|
||||||
/* The name of this type. */
|
/* The name of this type. */
|
||||||
|
@ -123,7 +131,9 @@ typedef struct tdesc_type
|
||||||
|
|
||||||
/* Types defined by a target feature. */
|
/* Types defined by a target feature. */
|
||||||
TDESC_TYPE_VECTOR,
|
TDESC_TYPE_VECTOR,
|
||||||
TDESC_TYPE_UNION
|
TDESC_TYPE_STRUCT,
|
||||||
|
TDESC_TYPE_UNION,
|
||||||
|
TDESC_TYPE_FLAGS
|
||||||
} kind;
|
} kind;
|
||||||
|
|
||||||
/* Kind-specific data. */
|
/* Kind-specific data. */
|
||||||
|
@ -136,11 +146,19 @@ typedef struct tdesc_type
|
||||||
int count;
|
int count;
|
||||||
} v;
|
} v;
|
||||||
|
|
||||||
/* Union type. */
|
/* Struct or union type. */
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
VEC(tdesc_type_field) *fields;
|
VEC(tdesc_type_field) *fields;
|
||||||
|
LONGEST size;
|
||||||
} u;
|
} u;
|
||||||
|
|
||||||
|
/* Flags type. */
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
VEC(tdesc_type_flag) *flags;
|
||||||
|
LONGEST size;
|
||||||
|
} f;
|
||||||
} u;
|
} u;
|
||||||
} *tdesc_type_p;
|
} *tdesc_type_p;
|
||||||
DEF_VEC_P(tdesc_type_p);
|
DEF_VEC_P(tdesc_type_p);
|
||||||
|
@ -652,6 +670,66 @@ tdesc_gdb_type (struct gdbarch *gdbarch, struct tdesc_type *tdesc_type)
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case TDESC_TYPE_STRUCT:
|
||||||
|
{
|
||||||
|
struct type *type, *field_type;
|
||||||
|
struct tdesc_type_field *f;
|
||||||
|
int ix;
|
||||||
|
|
||||||
|
type = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT);
|
||||||
|
TYPE_NAME (type) = xstrdup (tdesc_type->name);
|
||||||
|
TYPE_TAG_NAME (type) = TYPE_NAME (type);
|
||||||
|
|
||||||
|
for (ix = 0;
|
||||||
|
VEC_iterate (tdesc_type_field, tdesc_type->u.u.fields, ix, f);
|
||||||
|
ix++)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
if (tdesc_type->u.u.size > 4)
|
||||||
|
field_type = builtin_type (gdbarch)->builtin_uint64;
|
||||||
|
else
|
||||||
|
field_type = builtin_type (gdbarch)->builtin_uint32;
|
||||||
|
|
||||||
|
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),
|
||||||
|
field_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tdesc_type->u.u.size != 0)
|
||||||
|
TYPE_LENGTH (type) = tdesc_type->u.u.size;
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
case TDESC_TYPE_UNION:
|
case TDESC_TYPE_UNION:
|
||||||
{
|
{
|
||||||
struct type *type, *field_type;
|
struct type *type, *field_type;
|
||||||
|
@ -668,12 +746,30 @@ tdesc_gdb_type (struct gdbarch *gdbarch, struct tdesc_type *tdesc_type)
|
||||||
field_type = tdesc_gdb_type (gdbarch, f->type);
|
field_type = tdesc_gdb_type (gdbarch, f->type);
|
||||||
append_composite_type_field (type, xstrdup (f->name), field_type);
|
append_composite_type_field (type, xstrdup (f->name), field_type);
|
||||||
|
|
||||||
/* If any of the children of this union are vectors, flag the
|
/* If any of the children of a union are vectors, flag the
|
||||||
union as a vector also. This allows e.g. a union of two
|
union as a vector also. This allows e.g. a union of two
|
||||||
vector types to show up automatically in "info vector". */
|
vector types to show up automatically in "info vector". */
|
||||||
if (TYPE_VECTOR (field_type))
|
if (TYPE_VECTOR (field_type))
|
||||||
TYPE_VECTOR (type) = 1;
|
TYPE_VECTOR (type) = 1;
|
||||||
}
|
}
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TDESC_TYPE_FLAGS:
|
||||||
|
{
|
||||||
|
struct type *type, *field_type;
|
||||||
|
struct tdesc_type_flag *f;
|
||||||
|
int ix;
|
||||||
|
|
||||||
|
type = arch_flags_type (gdbarch, xstrdup (tdesc_type->name),
|
||||||
|
tdesc_type->u.f.size);
|
||||||
|
for (ix = 0;
|
||||||
|
VEC_iterate (tdesc_type_flag, tdesc_type->u.f.flags, ix, f);
|
||||||
|
ix++)
|
||||||
|
/* Note that contrary to the function name, this call will
|
||||||
|
just set the properties of an already-allocated
|
||||||
|
field. */
|
||||||
|
append_flags_type_flag (type, f->start, f->name);
|
||||||
|
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
@ -1161,6 +1257,7 @@ tdesc_free_type (struct tdesc_type *type)
|
||||||
|
|
||||||
switch (type->kind)
|
switch (type->kind)
|
||||||
{
|
{
|
||||||
|
case TDESC_TYPE_STRUCT:
|
||||||
case TDESC_TYPE_UNION:
|
case TDESC_TYPE_UNION:
|
||||||
{
|
{
|
||||||
struct tdesc_type_field *f;
|
struct tdesc_type_field *f;
|
||||||
|
@ -1175,6 +1272,20 @@ tdesc_free_type (struct tdesc_type *type)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TDESC_TYPE_FLAGS:
|
||||||
|
{
|
||||||
|
struct tdesc_type_flag *f;
|
||||||
|
int ix;
|
||||||
|
|
||||||
|
for (ix = 0;
|
||||||
|
VEC_iterate (tdesc_type_flag, type->u.f.flags, ix, f);
|
||||||
|
ix++)
|
||||||
|
xfree (f->name);
|
||||||
|
|
||||||
|
VEC_free (tdesc_type_flag, type->u.f.flags);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1198,6 +1309,29 @@ tdesc_create_vector (struct tdesc_feature *feature, const char *name,
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct tdesc_type *
|
||||||
|
tdesc_create_struct (struct tdesc_feature *feature, const char *name)
|
||||||
|
{
|
||||||
|
struct tdesc_type *type = XZALLOC (struct tdesc_type);
|
||||||
|
|
||||||
|
type->name = xstrdup (name);
|
||||||
|
type->kind = TDESC_TYPE_STRUCT;
|
||||||
|
|
||||||
|
VEC_safe_push (tdesc_type_p, feature->types, type);
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the total length of TYPE. Structs which contain bitfields may
|
||||||
|
omit the reserved bits, so the end of the last field may not
|
||||||
|
suffice. */
|
||||||
|
|
||||||
|
void
|
||||||
|
tdesc_set_struct_size (struct tdesc_type *type, LONGEST size)
|
||||||
|
{
|
||||||
|
gdb_assert (type->kind == TDESC_TYPE_STRUCT);
|
||||||
|
type->u.u.size = size;
|
||||||
|
}
|
||||||
|
|
||||||
struct tdesc_type *
|
struct tdesc_type *
|
||||||
tdesc_create_union (struct tdesc_feature *feature, const char *name)
|
tdesc_create_union (struct tdesc_feature *feature, const char *name)
|
||||||
{
|
{
|
||||||
|
@ -1210,13 +1344,32 @@ tdesc_create_union (struct tdesc_feature *feature, const char *name)
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct tdesc_type *
|
||||||
|
tdesc_create_flags (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_FLAGS;
|
||||||
|
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). */
|
||||||
|
|
||||||
void
|
void
|
||||||
tdesc_add_field (struct tdesc_type *type, const char *field_name,
|
tdesc_add_field (struct tdesc_type *type, const char *field_name,
|
||||||
struct tdesc_type *field_type)
|
struct tdesc_type *field_type)
|
||||||
{
|
{
|
||||||
struct tdesc_type_field f = { 0 };
|
struct tdesc_type_field f = { 0 };
|
||||||
|
|
||||||
gdb_assert (type->kind == TDESC_TYPE_UNION);
|
gdb_assert (type->kind == TDESC_TYPE_UNION
|
||||||
|
|| type->kind == TDESC_TYPE_STRUCT);
|
||||||
|
|
||||||
f.name = xstrdup (field_name);
|
f.name = xstrdup (field_name);
|
||||||
f.type = field_type;
|
f.type = field_type;
|
||||||
|
@ -1224,6 +1377,37 @@ tdesc_add_field (struct tdesc_type *type, const char *field_name,
|
||||||
VEC_safe_push (tdesc_type_field, type->u.u.fields, &f);
|
VEC_safe_push (tdesc_type_field, type->u.u.fields, &f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Add a new bitfield. */
|
||||||
|
|
||||||
|
void
|
||||||
|
tdesc_add_bitfield (struct tdesc_type *type, const char *field_name,
|
||||||
|
int start, int end)
|
||||||
|
{
|
||||||
|
struct tdesc_type_field f = { 0 };
|
||||||
|
|
||||||
|
gdb_assert (type->kind == TDESC_TYPE_STRUCT);
|
||||||
|
|
||||||
|
f.name = xstrdup (field_name);
|
||||||
|
f.start = start;
|
||||||
|
f.end = end;
|
||||||
|
|
||||||
|
VEC_safe_push (tdesc_type_field, type->u.u.fields, &f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
tdesc_add_flag (struct tdesc_type *type, int start,
|
||||||
|
const char *flag_name)
|
||||||
|
{
|
||||||
|
struct tdesc_type_flag f = { 0 };
|
||||||
|
|
||||||
|
gdb_assert (type->kind == TDESC_TYPE_FLAGS);
|
||||||
|
|
||||||
|
f.name = xstrdup (flag_name);
|
||||||
|
f.start = start;
|
||||||
|
|
||||||
|
VEC_safe_push (tdesc_type_flag, type->u.f.flags, &f);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
tdesc_free_feature (struct tdesc_feature *feature)
|
tdesc_free_feature (struct tdesc_feature *feature)
|
||||||
{
|
{
|
||||||
|
|
|
@ -205,10 +205,20 @@ struct tdesc_type *tdesc_create_vector (struct tdesc_feature *feature,
|
||||||
const char *name,
|
const char *name,
|
||||||
struct tdesc_type *field_type,
|
struct tdesc_type *field_type,
|
||||||
int count);
|
int count);
|
||||||
|
struct tdesc_type *tdesc_create_struct (struct tdesc_feature *feature,
|
||||||
|
const char *name);
|
||||||
|
void tdesc_set_struct_size (struct tdesc_type *type, LONGEST size);
|
||||||
struct tdesc_type *tdesc_create_union (struct tdesc_feature *feature,
|
struct tdesc_type *tdesc_create_union (struct tdesc_feature *feature,
|
||||||
const char *name);
|
const char *name);
|
||||||
|
struct tdesc_type *tdesc_create_flags (struct tdesc_feature *feature,
|
||||||
|
const char *name,
|
||||||
|
LONGEST size);
|
||||||
void tdesc_add_field (struct tdesc_type *type, const char *field_name,
|
void tdesc_add_field (struct tdesc_type *type, const char *field_name,
|
||||||
struct tdesc_type *field_type);
|
struct tdesc_type *field_type);
|
||||||
|
void tdesc_add_bitfield (struct tdesc_type *type, const char *field_name,
|
||||||
|
int start, int end);
|
||||||
|
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,
|
void tdesc_create_reg (struct tdesc_feature *feature, const char *name,
|
||||||
int regnum, int save_restore, const char *group,
|
int regnum, int save_restore, const char *group,
|
||||||
int bitsize, const char *type);
|
int bitsize, const char *type);
|
||||||
|
|
|
@ -1,3 +1,10 @@
|
||||||
|
2010-03-01 Daniel Jacobowitz <dan@codesourcery.com>
|
||||||
|
|
||||||
|
* gdb.xml/extra-regs.xml: Add struct1, struct2, and flags
|
||||||
|
types. Add structreg, bitfields, and flags registers.
|
||||||
|
* gdb.xml/tdesc-regs.exp: Test structreg and bitfields
|
||||||
|
registers.
|
||||||
|
|
||||||
2010-03-01 H.J. Lu <hongjiu.lu@intel.com>
|
2010-03-01 H.J. Lu <hongjiu.lu@intel.com>
|
||||||
|
|
||||||
* gdb.xml/tdesc-regs.exp (architecture): New. Set it for x86.
|
* gdb.xml/tdesc-regs.exp (architecture): New. Set it for x86.
|
||||||
|
|
|
@ -8,9 +8,27 @@
|
||||||
<field name="v2" type="v2int16"/>
|
<field name="v2" type="v2int16"/>
|
||||||
</union>
|
</union>
|
||||||
|
|
||||||
|
<struct id="struct1">
|
||||||
|
<field name="v4" type="v4int8"/>
|
||||||
|
<field name="v2" type="v2int16"/>
|
||||||
|
</struct>
|
||||||
|
|
||||||
|
<struct id="struct2" size="8">
|
||||||
|
<field name="f1" start="0" end="34"/>
|
||||||
|
<field name="f2" start="63" end="63"/>
|
||||||
|
</struct>
|
||||||
|
|
||||||
|
<flags id="flags" size="4">
|
||||||
|
<field name="X" start="0" end="0"/>
|
||||||
|
<field name="Y" start="2" end="2"/>
|
||||||
|
</flags>
|
||||||
|
|
||||||
<reg name="extrareg" bitsize="32"/>
|
<reg name="extrareg" bitsize="32"/>
|
||||||
<reg name="uintreg" bitsize="32" type="uint32"/>
|
<reg name="uintreg" bitsize="32" type="uint32"/>
|
||||||
<reg name="vecreg" bitsize="32" type="v4int8"/>
|
<reg name="vecreg" bitsize="32" type="v4int8"/>
|
||||||
<reg name="unionreg" bitsize="32" type="vecint"/>
|
<reg name="unionreg" bitsize="32" type="vecint"/>
|
||||||
|
<reg name="structreg" bitsize="64" type="struct1"/>
|
||||||
|
<reg name="bitfields" bitsize="64" type="struct2"/>
|
||||||
|
<reg name="flags" bitsize="32" type="flags"/>
|
||||||
</feature>
|
</feature>
|
||||||
</target>
|
</target>
|
||||||
|
|
|
@ -141,6 +141,11 @@ gdb_test "ptype \$vecreg" "type = int8_t \\\[4\\\]"
|
||||||
gdb_test "ptype \$unionreg" \
|
gdb_test "ptype \$unionreg" \
|
||||||
"type = union {\r\n *v4int8 v4;\r\n *v2int16 v2;\r\n}"
|
"type = union {\r\n *v4int8 v4;\r\n *v2int16 v2;\r\n}"
|
||||||
gdb_test "ptype \$unionreg.v4" "type = int8_t \\\[4\\\]"
|
gdb_test "ptype \$unionreg.v4" "type = int8_t \\\[4\\\]"
|
||||||
|
gdb_test "ptype \$structreg" \
|
||||||
|
"type = struct struct1 {\r\n *v4int8 v4;\r\n *v2int16 v2;\r\n}"
|
||||||
|
gdb_test "ptype \$structreg.v4" "type = int8_t \\\[4\\\]"
|
||||||
|
gdb_test "ptype \$bitfields" \
|
||||||
|
"type = struct struct2 {\r\n *uint64_t f1 : 35;\r\n *uint64_t f2 : 1;\r\n}"
|
||||||
|
|
||||||
load_description "core-only.xml" ""
|
load_description "core-only.xml" ""
|
||||||
# The extra register from the previous description should be gone.
|
# The extra register from the previous description should be gone.
|
||||||
|
|
164
gdb/xml-tdesc.c
164
gdb/xml-tdesc.c
|
@ -85,8 +85,15 @@ struct tdesc_parsing_data
|
||||||
it does not have its own. This starts at zero. */
|
it does not have its own. This starts at zero. */
|
||||||
int next_regnum;
|
int next_regnum;
|
||||||
|
|
||||||
/* The union we are currently parsing, or last parsed. */
|
/* The struct or union we are currently parsing, or last parsed. */
|
||||||
struct tdesc_type *current_union;
|
struct tdesc_type *current_type;
|
||||||
|
|
||||||
|
/* The byte size of the current struct type, if specified. Zero
|
||||||
|
if not specified. */
|
||||||
|
int current_type_size;
|
||||||
|
|
||||||
|
/* Whether the current type is a flags type. */
|
||||||
|
int current_type_is_flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Handle the end of an <architecture> element and its value. */
|
/* Handle the end of an <architecture> element and its value. */
|
||||||
|
@ -229,11 +236,57 @@ tdesc_start_union (struct gdb_xml_parser *parser,
|
||||||
struct tdesc_parsing_data *data = user_data;
|
struct tdesc_parsing_data *data = user_data;
|
||||||
char *id = VEC_index (gdb_xml_value_s, attributes, 0)->value;
|
char *id = VEC_index (gdb_xml_value_s, attributes, 0)->value;
|
||||||
|
|
||||||
data->current_union = tdesc_create_union (data->current_feature, id);
|
data->current_type = tdesc_create_union (data->current_feature, id);
|
||||||
|
data->current_type_size = 0;
|
||||||
|
data->current_type_is_flags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle the start of a <struct> element. Initialize the type and
|
||||||
|
record it with the current feature. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
tdesc_start_struct (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 = VEC_index (gdb_xml_value_s, attributes, 0)->value;
|
||||||
|
struct tdesc_type *type;
|
||||||
|
|
||||||
|
type = tdesc_create_struct (data->current_feature, id);
|
||||||
|
data->current_type = type;
|
||||||
|
data->current_type_size = 0;
|
||||||
|
data->current_type_is_flags = 0;
|
||||||
|
|
||||||
|
if (VEC_length (gdb_xml_value_s, attributes) > 1)
|
||||||
|
{
|
||||||
|
int size = (int) * (ULONGEST *)
|
||||||
|
VEC_index (gdb_xml_value_s, attributes, 1)->value;
|
||||||
|
tdesc_set_struct_size (type, size);
|
||||||
|
data->current_type_size = size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
tdesc_start_flags (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 = VEC_index (gdb_xml_value_s, attributes, 0)->value;
|
||||||
|
int length = (int) * (ULONGEST *)
|
||||||
|
VEC_index (gdb_xml_value_s, attributes, 1)->value;
|
||||||
|
struct tdesc_type *type;
|
||||||
|
|
||||||
|
type = tdesc_create_flags (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
|
/* Handle the start of a <field> element. Attach the field to the
|
||||||
current union. */
|
current struct or union. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
tdesc_start_field (struct gdb_xml_parser *parser,
|
tdesc_start_field (struct gdb_xml_parser *parser,
|
||||||
|
@ -241,20 +294,84 @@ tdesc_start_field (struct gdb_xml_parser *parser,
|
||||||
void *user_data, VEC(gdb_xml_value_s) *attributes)
|
void *user_data, VEC(gdb_xml_value_s) *attributes)
|
||||||
{
|
{
|
||||||
struct tdesc_parsing_data *data = user_data;
|
struct tdesc_parsing_data *data = user_data;
|
||||||
|
int ix = 0, length;
|
||||||
struct gdb_xml_value *attrs = VEC_address (gdb_xml_value_s, attributes);
|
struct gdb_xml_value *attrs = VEC_address (gdb_xml_value_s, attributes);
|
||||||
struct tdesc_type *field_type;
|
struct tdesc_type *field_type;
|
||||||
char *field_name, *field_type_id;
|
char *field_name, *field_type_id;
|
||||||
|
int start, end;
|
||||||
|
|
||||||
field_name = attrs[0].value;
|
length = VEC_length (gdb_xml_value_s, attributes);
|
||||||
field_type_id = attrs[1].value;
|
|
||||||
|
|
||||||
field_type = tdesc_named_type (data->current_feature, field_type_id);
|
field_name = attrs[ix++].value;
|
||||||
if (field_type == NULL)
|
|
||||||
gdb_xml_error (parser, _("Union field \"%s\" references undefined "
|
|
||||||
"type \"%s\""),
|
|
||||||
field_name, field_type_id);
|
|
||||||
|
|
||||||
tdesc_add_field (data->current_union, field_name, field_type);
|
if (ix < length && strcmp (attrs[ix].name, "type") == 0)
|
||||||
|
field_type_id = attrs[ix++].value;
|
||||||
|
else
|
||||||
|
field_type_id = NULL;
|
||||||
|
|
||||||
|
if (ix < length && strcmp (attrs[ix].name, "start") == 0)
|
||||||
|
start = * (ULONGEST *) attrs[ix++].value;
|
||||||
|
else
|
||||||
|
start = -1;
|
||||||
|
|
||||||
|
if (ix < length && strcmp (attrs[ix].name, "end") == 0)
|
||||||
|
end = * (ULONGEST *) attrs[ix++].value;
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
struct tdesc_type *t = data->current_type;
|
||||||
|
|
||||||
|
if (data->current_type_is_flags)
|
||||||
|
tdesc_add_flag (t, start, field_name);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (data->current_type_size == 0)
|
||||||
|
gdb_xml_error (parser,
|
||||||
|
_("Implicitly sized type can not contain bitfield \"%s\""),
|
||||||
|
field_name);
|
||||||
|
|
||||||
|
if (end >= 64)
|
||||||
|
gdb_xml_error (parser,
|
||||||
|
_("Bitfield \"%s\" goes past 64 bits (unsupported)"),
|
||||||
|
field_name);
|
||||||
|
|
||||||
|
/* Assume that the bit numbering in XML is "lsb-zero". Most
|
||||||
|
architectures other than PowerPC use this ordering. In
|
||||||
|
the future, we can add an XML tag to indicate "msb-zero"
|
||||||
|
numbering. */
|
||||||
|
if (start > end)
|
||||||
|
gdb_xml_error (parser, _("Bitfield \"%s\" has start after end"),
|
||||||
|
field_name);
|
||||||
|
|
||||||
|
if (end >= data->current_type_size * TARGET_CHAR_BIT)
|
||||||
|
gdb_xml_error (parser, _("Bitfield \"%s\" does not fit in struct"));
|
||||||
|
|
||||||
|
tdesc_add_bitfield (t, field_name, start, end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
gdb_xml_error (parser, _("Field \"%s\" has neither type nor bit position"),
|
||||||
|
field_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle the start of a <vector> element. Initialize the type and
|
/* Handle the start of a <vector> element. Initialize the type and
|
||||||
|
@ -287,11 +404,13 @@ tdesc_start_vector (struct gdb_xml_parser *parser,
|
||||||
|
|
||||||
static const struct gdb_xml_attribute field_attributes[] = {
|
static const struct gdb_xml_attribute field_attributes[] = {
|
||||||
{ "name", GDB_XML_AF_NONE, NULL, NULL },
|
{ "name", GDB_XML_AF_NONE, NULL, NULL },
|
||||||
{ "type", GDB_XML_AF_NONE, NULL, NULL },
|
{ "type", GDB_XML_AF_OPTIONAL, NULL, NULL },
|
||||||
|
{ "start", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL },
|
||||||
|
{ "end", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL },
|
||||||
{ NULL, GDB_XML_AF_NONE, NULL, NULL }
|
{ NULL, GDB_XML_AF_NONE, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct gdb_xml_element union_children[] = {
|
static const struct gdb_xml_element struct_union_children[] = {
|
||||||
{ "field", field_attributes, NULL, GDB_XML_EF_REPEATABLE,
|
{ "field", field_attributes, NULL, GDB_XML_EF_REPEATABLE,
|
||||||
tdesc_start_field, NULL },
|
tdesc_start_field, NULL },
|
||||||
{ NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
|
{ NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
|
||||||
|
@ -308,8 +427,15 @@ static const struct gdb_xml_attribute reg_attributes[] = {
|
||||||
{ NULL, GDB_XML_AF_NONE, NULL, NULL }
|
{ NULL, GDB_XML_AF_NONE, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct gdb_xml_attribute union_attributes[] = {
|
static const struct gdb_xml_attribute struct_union_attributes[] = {
|
||||||
{ "id", GDB_XML_AF_NONE, NULL, NULL },
|
{ "id", GDB_XML_AF_NONE, NULL, NULL },
|
||||||
|
{ "size", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL},
|
||||||
|
{ NULL, GDB_XML_AF_NONE, NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct gdb_xml_attribute flags_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 }
|
{ NULL, GDB_XML_AF_NONE, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -329,9 +455,15 @@ static const struct gdb_xml_element feature_children[] = {
|
||||||
{ "reg", reg_attributes, NULL,
|
{ "reg", reg_attributes, NULL,
|
||||||
GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
|
GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
|
||||||
tdesc_start_reg, NULL },
|
tdesc_start_reg, NULL },
|
||||||
{ "union", union_attributes, union_children,
|
{ "struct", struct_union_attributes, struct_union_children,
|
||||||
|
GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
|
||||||
|
tdesc_start_struct, NULL },
|
||||||
|
{ "union", struct_union_attributes, struct_union_children,
|
||||||
GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
|
GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
|
||||||
tdesc_start_union, NULL },
|
tdesc_start_union, NULL },
|
||||||
|
{ "flags", flags_attributes, struct_union_children,
|
||||||
|
GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
|
||||||
|
tdesc_start_flags, NULL },
|
||||||
{ "vector", vector_attributes, NULL,
|
{ "vector", vector_attributes, NULL,
|
||||||
GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
|
GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
|
||||||
tdesc_start_vector, NULL },
|
tdesc_start_vector, NULL },
|
||||||
|
|
Loading…
Reference in New Issue