Extend flags to support multibit and enum bitfields.
gdb/ChangeLog: Extend flags to support multibit and enum bitfields. NEWS: Document new features. * c-typeprint.c (c_type_print_varspec_prefix): Handle TYPE_CODE_FLAGS. (c_type_print_varspec_suffix, c_type_print_base): Ditto. * gdbtypes.c (arch_flags_type): Don't assume all fields are one bit. (append_flags_type_field): New function. (append_flags_type_flag): Call it. * gdbtypes.h (append_flags_type_field): Declare. * target-descriptions.c (struct tdesc_type_flag): Delete. (enum tdesc_type_kind) <TDESC_TYPE_BOOL>: New enum value. (enum tdesc_type_kind) <TDESC_TYPE_ENUM>: Ditto. (struct tdesc_type) <u.f>: Delete. (tdesc_predefined_types): Add "bool". (tdesc_predefined_type): New function. (tdesc_gdb_type): Handle TDESC_TYPE_BOOL, TDESC_TYPE_ENUM. Update TDESC_TYPE_FLAGS support. (tdesc_free_type): Handle TDESC_TYPE_ENUM. Update TDESC_TYPE_FLAGS. (tdesc_create_flags): Update. (tdesc_create_enum): New function. (tdesc_add_field): Initialize start,end to -1. (tdesc_add_typed_bitfield): New function. (tdesc_add_bitfield): Call it. (tdesc_add_flag): Allow TDESC_TYPE_STRUCT. Update. (tdesc_add_enum_value): New function. (maint_print_c_tdesc_cmd): Fold TDESC_TYPE_FLAGS support into TDESC_TYPE_STRUCT. Handle TDESC_TYPE_ENUM. * target-descriptions.h (tdesc_create_enum): Declare. (tdesc_add_typed_bitfield, tdesc_add_enum_value): Declare. * valprint.c (generic_val_print_enum_1): New function. (generic_val_print_enum): Call it. (val_print_type_code_flags): Make static. Handle multibit bitfields and enum bitfields. * valprint.h (val_print_type_code_flags): Delete. * xml-tdesc.c (struct tdesc_parsing_data) <current_type_is_flags>: Delete. All uses removed. (tdesc_start_enum): New function. (tdesc_start_field): Handle multibit and enum bitfields. (tdesc_start_enum_value): New function. (enum_value_attributes, enum_children, enum_attributes): New static globals. (feature_children): Add "enum". * features/gdb-target.dtd (enum, evalue): New elements. gdb/doc/ChangeLog: * gdb.texinfo (Target Descriptions): New menu item "Enum Target Types". (Target Description Format): Mention enum types. Update docs on flags types. (Predefined Target Types): Add "bool". (Enum Target Types): New node. gdb/testsuite/ChangeLog: * gdb.xml/extra-regs.xml: Add enum, mixed_flags values. * gdb.xml/tdesc-regs.exp (load_description): New arg xml_file. All callers updated. Add tests for enums, mixed flags register.
This commit is contained in:
parent
54157a25aa
commit
8151645076
16 changed files with 735 additions and 220 deletions
|
@ -1,3 +1,48 @@
|
|||
2016-03-15 Doug Evans <dje@google.com>
|
||||
|
||||
Extend flags to support multibit and enum bitfields.
|
||||
NEWS: Document new features.
|
||||
* c-typeprint.c (c_type_print_varspec_prefix): Handle TYPE_CODE_FLAGS.
|
||||
(c_type_print_varspec_suffix, c_type_print_base): Ditto.
|
||||
* gdbtypes.c (arch_flags_type): Don't assume all fields are one bit.
|
||||
(append_flags_type_field): New function.
|
||||
(append_flags_type_flag): Call it.
|
||||
* gdbtypes.h (append_flags_type_field): Declare.
|
||||
* target-descriptions.c (struct tdesc_type_flag): Delete.
|
||||
(enum tdesc_type_kind) <TDESC_TYPE_BOOL>: New enum value.
|
||||
(enum tdesc_type_kind) <TDESC_TYPE_ENUM>: Ditto.
|
||||
(struct tdesc_type) <u.f>: Delete.
|
||||
(tdesc_predefined_types): Add "bool".
|
||||
(tdesc_predefined_type): New function.
|
||||
(tdesc_gdb_type): Handle TDESC_TYPE_BOOL, TDESC_TYPE_ENUM.
|
||||
Update TDESC_TYPE_FLAGS support.
|
||||
(tdesc_free_type): Handle TDESC_TYPE_ENUM. Update TDESC_TYPE_FLAGS.
|
||||
(tdesc_create_flags): Update.
|
||||
(tdesc_create_enum): New function.
|
||||
(tdesc_add_field): Initialize start,end to -1.
|
||||
(tdesc_add_typed_bitfield): New function.
|
||||
(tdesc_add_bitfield): Call it.
|
||||
(tdesc_add_flag): Allow TDESC_TYPE_STRUCT. Update.
|
||||
(tdesc_add_enum_value): New function.
|
||||
(maint_print_c_tdesc_cmd): Fold TDESC_TYPE_FLAGS support into
|
||||
TDESC_TYPE_STRUCT. Handle TDESC_TYPE_ENUM.
|
||||
* target-descriptions.h (tdesc_create_enum): Declare.
|
||||
(tdesc_add_typed_bitfield, tdesc_add_enum_value): Declare.
|
||||
* valprint.c (generic_val_print_enum_1): New function.
|
||||
(generic_val_print_enum): Call it.
|
||||
(val_print_type_code_flags): Make static. Handle multibit bitfields
|
||||
and enum bitfields.
|
||||
* valprint.h (val_print_type_code_flags): Delete.
|
||||
* xml-tdesc.c (struct tdesc_parsing_data) <current_type_is_flags>:
|
||||
Delete. All uses removed.
|
||||
(tdesc_start_enum): New function.
|
||||
(tdesc_start_field): Handle multibit and enum bitfields.
|
||||
(tdesc_start_enum_value): New function.
|
||||
(enum_value_attributes, enum_children, enum_attributes): New static
|
||||
globals.
|
||||
(feature_children): Add "enum".
|
||||
* features/gdb-target.dtd (enum, evalue): New elements.
|
||||
|
||||
2016-03-15 Doug Evans <dje@google.com>
|
||||
|
||||
* target-descriptions.c (struct tdesc_type) <u.u.size>: Change type
|
||||
|
|
3
gdb/NEWS
3
gdb/NEWS
|
@ -3,6 +3,9 @@
|
|||
|
||||
*** Changes since GDB 7.11
|
||||
|
||||
* GDB now supports multibit bitfields and enums in target register
|
||||
descriptions.
|
||||
|
||||
* New Python-based convenience function $_as_string(val), which returns
|
||||
the textual representation of a value. This function is especially
|
||||
useful to obtain the text label of an enum value.
|
||||
|
|
|
@ -371,6 +371,7 @@ c_type_print_varspec_prefix (struct type *type,
|
|||
case TYPE_CODE_STRUCT:
|
||||
case TYPE_CODE_UNION:
|
||||
case TYPE_CODE_ENUM:
|
||||
case TYPE_CODE_FLAGS:
|
||||
case TYPE_CODE_INT:
|
||||
case TYPE_CODE_FLT:
|
||||
case TYPE_CODE_VOID:
|
||||
|
@ -748,6 +749,7 @@ c_type_print_varspec_suffix (struct type *type,
|
|||
case TYPE_CODE_UNDEF:
|
||||
case TYPE_CODE_STRUCT:
|
||||
case TYPE_CODE_UNION:
|
||||
case TYPE_CODE_FLAGS:
|
||||
case TYPE_CODE_ENUM:
|
||||
case TYPE_CODE_INT:
|
||||
case TYPE_CODE_FLT:
|
||||
|
@ -1402,6 +1404,54 @@ c_type_print_base (struct type *type, struct ui_file *stream,
|
|||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_FLAGS:
|
||||
{
|
||||
struct type_print_options local_flags = *flags;
|
||||
|
||||
local_flags.local_typedefs = NULL;
|
||||
|
||||
c_type_print_modifier (type, stream, 0, 1);
|
||||
fprintf_filtered (stream, "flag ");
|
||||
print_name_maybe_canonical (TYPE_NAME (type), flags, stream);
|
||||
if (show > 0)
|
||||
{
|
||||
fputs_filtered (" ", stream);
|
||||
fprintf_filtered (stream, "{\n");
|
||||
if (TYPE_NFIELDS (type) == 0)
|
||||
{
|
||||
if (TYPE_STUB (type))
|
||||
fprintfi_filtered (level + 4, stream,
|
||||
_("<incomplete type>\n"));
|
||||
else
|
||||
fprintfi_filtered (level + 4, stream,
|
||||
_("<no data fields>\n"));
|
||||
}
|
||||
len = TYPE_NFIELDS (type);
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
QUIT;
|
||||
print_spaces_filtered (level + 4, stream);
|
||||
/* We pass "show" here and not "show - 1" to get enum types
|
||||
printed. There's no other way to see them. */
|
||||
c_print_type (TYPE_FIELD_TYPE (type, i),
|
||||
TYPE_FIELD_NAME (type, i),
|
||||
stream, show, level + 4,
|
||||
&local_flags);
|
||||
fprintf_filtered (stream, " @%d",
|
||||
TYPE_FIELD_BITPOS (type, i));
|
||||
if (TYPE_FIELD_BITSIZE (type, i) > 1)
|
||||
{
|
||||
fprintf_filtered (stream, "-%d",
|
||||
TYPE_FIELD_BITPOS (type, i)
|
||||
+ TYPE_FIELD_BITSIZE (type, i) - 1);
|
||||
}
|
||||
fprintf_filtered (stream, ";\n");
|
||||
}
|
||||
fprintfi_filtered (level, stream, "}");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_VOID:
|
||||
fprintf_filtered (stream, "void");
|
||||
break;
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
2016-03-15 Doug Evans <dje@google.com>
|
||||
|
||||
* gdb.texinfo (Target Descriptions): New menu item "Enum Target Types".
|
||||
(Target Description Format): Mention enum types. Update docs on
|
||||
flags types.
|
||||
(Predefined Target Types): Add "bool".
|
||||
(Enum Target Types): New node.
|
||||
|
||||
2016-03-15 Pedro Alves <palves@redhat.com>
|
||||
|
||||
* gdb.texinfo (Tracepoint Actions): Fix typo.
|
||||
|
|
|
@ -40359,6 +40359,7 @@ target descriptions. @xref{Expat}.
|
|||
* Target Description Format:: The contents of a target description.
|
||||
* Predefined Target Types:: Standard types available for target
|
||||
descriptions.
|
||||
* Enum Target Types:: How to define enum target types.
|
||||
* Standard Target Features:: Features @value{GDBN} knows about.
|
||||
@end menu
|
||||
|
||||
|
@ -40559,7 +40560,8 @@ Any register's value is a collection of bits which @value{GDBN} must
|
|||
interpret. The default interpretation is a two's complement integer,
|
||||
but other types can be requested by name in the register description.
|
||||
Some predefined types are provided by @value{GDBN} (@pxref{Predefined
|
||||
Target Types}), and the description can define additional composite types.
|
||||
Target Types}), and the description can define additional composite
|
||||
and enum types.
|
||||
|
||||
Each type element must have an @samp{id} attribute, which gives
|
||||
a unique (within the containing @samp{<feature>}) name to the type.
|
||||
|
@ -40589,24 +40591,15 @@ each of which has a @var{name} and a @var{type}:
|
|||
@end smallexample
|
||||
|
||||
@cindex <struct>
|
||||
@cindex <flags>
|
||||
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.
|
||||
it with either a structure type or a flags type.
|
||||
A flags type may only contain bitfields.
|
||||
A structure type may either contain only bitfields or contain no bitfields.
|
||||
If the value contains only bitfields, its total size in bytes must be
|
||||
specified.
|
||||
|
||||
@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.
|
||||
Non-bitfield values have a @var{name} and @var{type}.
|
||||
|
||||
@smallexample
|
||||
<struct id="@var{id}">
|
||||
|
@ -40615,20 +40608,67 @@ explicit type, and no implicit padding is added.
|
|||
</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.
|
||||
Both @var{name} and @var{type} values are required.
|
||||
No implicit padding is added.
|
||||
|
||||
Bitfield values have a @var{name}, @var{start}, @var{end} and @var{type}.
|
||||
|
||||
@smallexample
|
||||
<struct id="@var{id}" size="@var{size}">
|
||||
<field name="@var{name}" start="@var{start}" end="@var{end}" type="@var{type}"/>
|
||||
@dots{}
|
||||
</struct>
|
||||
@end smallexample
|
||||
|
||||
@smallexample
|
||||
<flags id="@var{id}" size="@var{size}">
|
||||
<field name="@var{name}" start="@var{start}" end="@var{end}"/>
|
||||
<field name="@var{name}" start="@var{start}" end="@var{end}" type="@var{type}"/>
|
||||
@dots{}
|
||||
</flags>
|
||||
@end smallexample
|
||||
|
||||
The @var{name} value is required.
|
||||
Bitfield values may be named with the empty string, @samp{""},
|
||||
in which case the field is ``filler'' and its value is not printed.
|
||||
Not all bits need to be specified, so ``filler'' fields are optional.
|
||||
|
||||
The @var{start} value is required, and @var{end} and @var{type}
|
||||
are optional.
|
||||
The field's @var{start} must be less than or equal to its @var{end},
|
||||
and zero represents the least significant bit.
|
||||
The default value of @var{end} is @var{start}, a single bit field.
|
||||
|
||||
The default value of @var{type} depends on whether the
|
||||
@var{end} was specified. If @var{end} is specified then the default
|
||||
value of @var{type} is an unsigned integer. If @var{end} is unspecified
|
||||
then the default value of @var{type} is @code{bool}.
|
||||
|
||||
Which to choose? Structures or flags?
|
||||
|
||||
Registers defined with @samp{flags} have these advantages over
|
||||
defining them with @samp{struct}:
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
Arithmetic may be performed on them as if they were integers.
|
||||
@item
|
||||
They are printed in a more readable fashion.
|
||||
@end itemize
|
||||
|
||||
Registers defined with @samp{struct} have one advantage over
|
||||
defining them with @samp{flags}:
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
One can fetch individual fields like in @samp{C}.
|
||||
|
||||
@smallexample
|
||||
(gdb) print $my_struct_reg.field3
|
||||
$1 = 42
|
||||
@end smallexample
|
||||
|
||||
@end itemize
|
||||
|
||||
@subsection Registers
|
||||
@cindex <reg>
|
||||
|
||||
|
@ -40697,6 +40737,9 @@ types. The currently supported types are:
|
|||
|
||||
@table @code
|
||||
|
||||
@item bool
|
||||
Boolean type, occupying a single bit.
|
||||
|
||||
@item int8
|
||||
@itemx int16
|
||||
@itemx int32
|
||||
|
@ -40739,6 +40782,44 @@ The 10-byte extended precision format used by x87 registers.
|
|||
|
||||
@end table
|
||||
|
||||
@node Enum Target Types
|
||||
@section Enum Target Types
|
||||
@cindex target descriptions, enum types
|
||||
|
||||
Enum target types are useful in @samp{struct} and @samp{flags}
|
||||
register descriptions. @xref{Target Description Format}.
|
||||
|
||||
Enum types have a name, size and a list of name/value pairs.
|
||||
|
||||
@smallexample
|
||||
<enum id="@var{id}" size="@var{size}">
|
||||
<evalue name="@var{name}" value="@var{value}"/>
|
||||
@dots{}
|
||||
</enum>
|
||||
@end smallexample
|
||||
|
||||
Enums must be defined before they are used.
|
||||
|
||||
@smallexample
|
||||
<enum id="levels_type" size="4">
|
||||
<evalue name="low" value="0"/>
|
||||
<evalue name="high" value="1"/>
|
||||
</enum>
|
||||
<flags id="flags_type" size="4">
|
||||
<field name="X" start="0"/>
|
||||
<field name="LEVEL" start="1" end="1" type="levels_type"/>
|
||||
</flags>
|
||||
<reg name="flags" bitsize="32" type="flags_type"/>
|
||||
@end smallexample
|
||||
|
||||
Given that description, a value of 3 for the @samp{flags} register
|
||||
would be printed as:
|
||||
|
||||
@smallexample
|
||||
(gdb) info register flags
|
||||
flags 0x3 [ X LEVEL=high ]
|
||||
@end smallexample
|
||||
|
||||
@node Standard Target Features
|
||||
@section Standard Target Features
|
||||
@cindex target descriptions, standard features
|
||||
|
|
|
@ -45,6 +45,11 @@
|
|||
id CDATA #REQUIRED
|
||||
size CDATA #REQUIRED>
|
||||
|
||||
<!ELEMENT enum (evalue+)>
|
||||
<!ATTLIST enum
|
||||
id CDATA #REQUIRED
|
||||
size CDATA #REQUIRED>
|
||||
|
||||
<!ELEMENT struct (field+)>
|
||||
<!ATTLIST struct
|
||||
id CDATA #REQUIRED
|
||||
|
@ -61,5 +66,10 @@
|
|||
start CDATA #IMPLIED
|
||||
end CDATA #IMPLIED>
|
||||
|
||||
<!ELEMENT evalue EMPTY>
|
||||
<!ATTLIST evalue
|
||||
name CDATA #REQUIRED
|
||||
value CDATA #REQUIRED>
|
||||
|
||||
<!ENTITY % xinclude SYSTEM "xinclude.dtd">
|
||||
%xinclude;
|
||||
|
|
|
@ -4715,38 +4715,55 @@ arch_complex_type (struct gdbarch *gdbarch,
|
|||
struct type *
|
||||
arch_flags_type (struct gdbarch *gdbarch, char *name, int length)
|
||||
{
|
||||
int nfields = length * TARGET_CHAR_BIT;
|
||||
int max_nfields = length * TARGET_CHAR_BIT;
|
||||
struct type *type;
|
||||
|
||||
type = arch_type (gdbarch, TYPE_CODE_FLAGS, length, name);
|
||||
TYPE_UNSIGNED (type) = 1;
|
||||
TYPE_NFIELDS (type) = nfields;
|
||||
TYPE_NFIELDS (type) = 0;
|
||||
/* Pre-allocate enough space assuming every field is one bit. */
|
||||
TYPE_FIELDS (type)
|
||||
= (struct field *) TYPE_ZALLOC (type, nfields * sizeof (struct field));
|
||||
= (struct field *) TYPE_ZALLOC (type, max_nfields * sizeof (struct field));
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
/* Add field to TYPE_CODE_FLAGS type TYPE to indicate the bit at
|
||||
position BITPOS is called NAME. Pass NAME as "" for fields that
|
||||
should not be printed. */
|
||||
|
||||
void
|
||||
append_flags_type_field (struct type *type, int start_bitpos, int nr_bits,
|
||||
struct type *field_type, char *name)
|
||||
{
|
||||
int type_bitsize = TYPE_LENGTH (type) * TARGET_CHAR_BIT;
|
||||
int field_nr = TYPE_NFIELDS (type);
|
||||
|
||||
gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLAGS);
|
||||
gdb_assert (TYPE_NFIELDS (type) + 1 <= type_bitsize);
|
||||
gdb_assert (start_bitpos >= 0 && start_bitpos < type_bitsize);
|
||||
gdb_assert (nr_bits >= 1 && nr_bits <= type_bitsize);
|
||||
gdb_assert (name != NULL);
|
||||
|
||||
TYPE_FIELD_NAME (type, field_nr) = xstrdup (name);
|
||||
TYPE_FIELD_TYPE (type, field_nr) = field_type;
|
||||
SET_FIELD_BITPOS (TYPE_FIELD (type, field_nr), start_bitpos);
|
||||
TYPE_FIELD_BITSIZE (type, field_nr) = nr_bits;
|
||||
++TYPE_NFIELDS (type);
|
||||
}
|
||||
|
||||
/* Special version of append_flags_type_field to add a flag field.
|
||||
Add field to TYPE_CODE_FLAGS type TYPE to indicate the bit at
|
||||
position BITPOS is called NAME. */
|
||||
|
||||
void
|
||||
append_flags_type_flag (struct type *type, int bitpos, char *name)
|
||||
{
|
||||
gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLAGS);
|
||||
gdb_assert (bitpos < TYPE_NFIELDS (type));
|
||||
gdb_assert (bitpos >= 0);
|
||||
struct gdbarch *gdbarch = get_type_arch (type);
|
||||
|
||||
if (name)
|
||||
{
|
||||
TYPE_FIELD_NAME (type, bitpos) = xstrdup (name);
|
||||
SET_FIELD_BITPOS (TYPE_FIELD (type, bitpos), bitpos);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Don't show this field to the user. */
|
||||
SET_FIELD_BITPOS (TYPE_FIELD (type, bitpos), -1);
|
||||
}
|
||||
append_flags_type_field (type, bitpos, 1,
|
||||
builtin_type (gdbarch)->builtin_bool,
|
||||
name);
|
||||
}
|
||||
|
||||
/* Allocate a TYPE_CODE_STRUCT or TYPE_CODE_UNION type structure (as
|
||||
|
|
|
@ -1704,9 +1704,12 @@ struct field *append_composite_type_field_raw (struct type *t, char *name,
|
|||
|
||||
/* Helper functions to construct a bit flags type. An initially empty
|
||||
type is created using arch_flag_type(). Flags are then added using
|
||||
append_flag_type_flag(). */
|
||||
append_flag_type_field() and append_flag_type_flag(). */
|
||||
extern struct type *arch_flags_type (struct gdbarch *gdbarch,
|
||||
char *name, int length);
|
||||
extern void append_flags_type_field (struct type *type,
|
||||
int start_bitpos, int nr_bits,
|
||||
struct type *field_type, char *name);
|
||||
extern void append_flags_type_flag (struct type *type, int bitpos, char *name);
|
||||
|
||||
extern void make_vector_type (struct type *array_type);
|
||||
|
|
|
@ -90,20 +90,17 @@ typedef struct tdesc_type_field
|
|||
{
|
||||
char *name;
|
||||
struct tdesc_type *type;
|
||||
/* For non-enum-values, either both are -1 (non-bitfield), or both are
|
||||
not -1 (bitfield). For enum values, start is the value (which could be
|
||||
-1), end is -1. */
|
||||
int start, end;
|
||||
} 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);
|
||||
|
||||
enum tdesc_type_kind
|
||||
{
|
||||
/* Predefined types. */
|
||||
TDESC_TYPE_BOOL,
|
||||
TDESC_TYPE_INT8,
|
||||
TDESC_TYPE_INT16,
|
||||
TDESC_TYPE_INT32,
|
||||
|
@ -125,7 +122,8 @@ enum tdesc_type_kind
|
|||
TDESC_TYPE_VECTOR,
|
||||
TDESC_TYPE_STRUCT,
|
||||
TDESC_TYPE_UNION,
|
||||
TDESC_TYPE_FLAGS
|
||||
TDESC_TYPE_FLAGS,
|
||||
TDESC_TYPE_ENUM
|
||||
};
|
||||
|
||||
typedef struct tdesc_type
|
||||
|
@ -146,19 +144,12 @@ typedef struct tdesc_type
|
|||
int count;
|
||||
} v;
|
||||
|
||||
/* Struct or union type. */
|
||||
/* Struct, union, flags, or enum type. */
|
||||
struct
|
||||
{
|
||||
VEC(tdesc_type_field) *fields;
|
||||
int size;
|
||||
} u;
|
||||
|
||||
/* Flags type. */
|
||||
struct
|
||||
{
|
||||
VEC(tdesc_type_flag) *flags;
|
||||
int size;
|
||||
} f;
|
||||
} u;
|
||||
} *tdesc_type_p;
|
||||
DEF_VEC_P(tdesc_type_p);
|
||||
|
@ -527,6 +518,7 @@ tdesc_feature_name (const struct tdesc_feature *feature)
|
|||
/* Predefined types. */
|
||||
static struct tdesc_type tdesc_predefined_types[] =
|
||||
{
|
||||
{ "bool", TDESC_TYPE_BOOL },
|
||||
{ "int8", TDESC_TYPE_INT8 },
|
||||
{ "int16", TDESC_TYPE_INT16 },
|
||||
{ "int32", TDESC_TYPE_INT32 },
|
||||
|
@ -545,6 +537,21 @@ static struct tdesc_type tdesc_predefined_types[] =
|
|||
{ "i387_ext", TDESC_TYPE_I387_EXT }
|
||||
};
|
||||
|
||||
/* Lookup a predefined type. */
|
||||
|
||||
static struct tdesc_type *
|
||||
tdesc_predefined_type (enum tdesc_type_kind kind)
|
||||
{
|
||||
int ix;
|
||||
struct tdesc_type *type;
|
||||
|
||||
for (ix = 0; ix < ARRAY_SIZE (tdesc_predefined_types); ix++)
|
||||
if (tdesc_predefined_types[ix].kind == kind)
|
||||
return &tdesc_predefined_types[ix];
|
||||
|
||||
gdb_assert_not_reached ("bad predefined tdesc type");
|
||||
}
|
||||
|
||||
/* Return the type associated with ID in the context of FEATURE, or
|
||||
NULL if none. */
|
||||
|
||||
|
@ -602,6 +609,9 @@ tdesc_gdb_type (struct gdbarch *gdbarch, struct tdesc_type *tdesc_type)
|
|||
switch (tdesc_type->kind)
|
||||
{
|
||||
/* Predefined types. */
|
||||
case TDESC_TYPE_BOOL:
|
||||
return builtin_type (gdbarch)->builtin_bool;
|
||||
|
||||
case TDESC_TYPE_INT8:
|
||||
return builtin_type (gdbarch)->builtin_int8;
|
||||
|
||||
|
@ -690,17 +700,18 @@ tdesc_gdb_type (struct gdbarch *gdbarch, struct tdesc_type *tdesc_type)
|
|||
VEC_iterate (tdesc_type_field, tdesc_type->u.u.fields, ix, f);
|
||||
ix++)
|
||||
{
|
||||
if (f->type == NULL)
|
||||
if (f->start != -1 && f->end != -1)
|
||||
{
|
||||
/* Bitfield. */
|
||||
struct field *fld;
|
||||
struct type *field_type;
|
||||
int bitsize, total_size;
|
||||
|
||||
/* This invariant should be preserved while creating
|
||||
types. */
|
||||
/* This invariant should be preserved while creating types. */
|
||||
gdb_assert (tdesc_type->u.u.size != 0);
|
||||
if (tdesc_type->u.u.size > 4)
|
||||
if (f->type != NULL)
|
||||
field_type = tdesc_gdb_type (gdbarch, f->type);
|
||||
else if (tdesc_type->u.u.size > 4)
|
||||
field_type = builtin_type (gdbarch)->builtin_uint64;
|
||||
else
|
||||
field_type = builtin_type (gdbarch)->builtin_uint32;
|
||||
|
@ -725,6 +736,7 @@ tdesc_gdb_type (struct gdbarch *gdbarch, struct tdesc_type *tdesc_type)
|
|||
}
|
||||
else
|
||||
{
|
||||
gdb_assert (f->start == -1 && f->end == -1);
|
||||
field_type = tdesc_gdb_type (gdbarch, f->type);
|
||||
append_composite_type_field (type, xstrdup (f->name),
|
||||
field_type);
|
||||
|
@ -763,19 +775,45 @@ tdesc_gdb_type (struct gdbarch *gdbarch, struct tdesc_type *tdesc_type)
|
|||
|
||||
case TDESC_TYPE_FLAGS:
|
||||
{
|
||||
struct tdesc_type_flag *f;
|
||||
struct tdesc_type_field *f;
|
||||
int ix;
|
||||
|
||||
type = arch_flags_type (gdbarch, tdesc_type->name,
|
||||
tdesc_type->u.f.size);
|
||||
tdesc_type->u.u.size);
|
||||
for (ix = 0;
|
||||
VEC_iterate (tdesc_type_flag, tdesc_type->u.f.flags, ix, f);
|
||||
VEC_iterate (tdesc_type_field, tdesc_type->u.u.fields, 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 ? f->name : NULL);
|
||||
{
|
||||
struct type *field_type;
|
||||
int bitsize = f->end - f->start + 1;
|
||||
|
||||
gdb_assert (f->type != NULL);
|
||||
field_type = tdesc_gdb_type (gdbarch, f->type);
|
||||
append_flags_type_field (type, f->start, bitsize,
|
||||
field_type, f->name);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
case TDESC_TYPE_ENUM:
|
||||
{
|
||||
struct tdesc_type_field *f;
|
||||
int ix;
|
||||
|
||||
type = arch_type (gdbarch, TYPE_CODE_ENUM,
|
||||
tdesc_type->u.u.size, tdesc_type->name);
|
||||
TYPE_UNSIGNED (type) = 1;
|
||||
for (ix = 0;
|
||||
VEC_iterate (tdesc_type_field, tdesc_type->u.u.fields, ix, f);
|
||||
ix++)
|
||||
{
|
||||
struct field *fld
|
||||
= append_composite_type_field_raw (type, xstrdup (f->name),
|
||||
NULL);
|
||||
|
||||
SET_FIELD_BITPOS (fld[0], f->start);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
@ -1266,6 +1304,11 @@ tdesc_create_reg (struct tdesc_feature *feature, const char *name,
|
|||
VEC_safe_push (tdesc_reg_p, feature->registers, reg);
|
||||
}
|
||||
|
||||
/* Subroutine of tdesc_free_feature to simplify it.
|
||||
Note: We do not want to free any referenced types here (e.g., types of
|
||||
fields of a struct). All types of a feature are recorded in
|
||||
feature->types and are freed that way. */
|
||||
|
||||
static void
|
||||
tdesc_free_type (struct tdesc_type *type)
|
||||
{
|
||||
|
@ -1273,6 +1316,8 @@ tdesc_free_type (struct tdesc_type *type)
|
|||
{
|
||||
case TDESC_TYPE_STRUCT:
|
||||
case TDESC_TYPE_UNION:
|
||||
case TDESC_TYPE_FLAGS:
|
||||
case TDESC_TYPE_ENUM:
|
||||
{
|
||||
struct tdesc_type_field *f;
|
||||
int ix;
|
||||
|
@ -1286,20 +1331,6 @@ tdesc_free_type (struct tdesc_type *type)
|
|||
}
|
||||
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:
|
||||
break;
|
||||
}
|
||||
|
@ -1369,15 +1400,29 @@ tdesc_create_flags (struct tdesc_feature *feature, const char *name,
|
|||
|
||||
type->name = xstrdup (name);
|
||||
type->kind = TDESC_TYPE_FLAGS;
|
||||
type->u.f.size = size;
|
||||
type->u.u.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). */
|
||||
struct tdesc_type *
|
||||
tdesc_create_enum (struct tdesc_feature *feature, const char *name,
|
||||
int size)
|
||||
{
|
||||
struct tdesc_type *type = XCNEW (struct tdesc_type);
|
||||
|
||||
gdb_assert (size > 0);
|
||||
|
||||
type->name = xstrdup (name);
|
||||
type->kind = TDESC_TYPE_ENUM;
|
||||
type->u.u.size = size;
|
||||
|
||||
VEC_safe_push (tdesc_type_p, feature->types, type);
|
||||
return type;
|
||||
}
|
||||
|
||||
/* Add a new field to TYPE. */
|
||||
|
||||
void
|
||||
tdesc_add_field (struct tdesc_type *type, const char *field_name,
|
||||
|
@ -1390,39 +1435,88 @@ tdesc_add_field (struct tdesc_type *type, const char *field_name,
|
|||
|
||||
f.name = xstrdup (field_name);
|
||||
f.type = field_type;
|
||||
/* Initialize these values so we know this is not a bit-field
|
||||
when we print-c-tdesc. */
|
||||
f.start = -1;
|
||||
f.end = -1;
|
||||
|
||||
VEC_safe_push (tdesc_type_field, type->u.u.fields, &f);
|
||||
}
|
||||
|
||||
/* Add a new bitfield. */
|
||||
/* Add a new typed bitfield to TYPE. */
|
||||
|
||||
void
|
||||
tdesc_add_typed_bitfield (struct tdesc_type *type, const char *field_name,
|
||||
int start, int end, struct tdesc_type *field_type)
|
||||
{
|
||||
struct tdesc_type_field f = { 0 };
|
||||
|
||||
gdb_assert (type->kind == TDESC_TYPE_STRUCT
|
||||
|| type->kind == TDESC_TYPE_FLAGS);
|
||||
gdb_assert (start >= 0 && end >= start);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/* Add a new untyped bitfield to TYPE.
|
||||
Untyped bitfields become either uint32 or uint64 depending on the size
|
||||
of the underlying type. */
|
||||
|
||||
void
|
||||
tdesc_add_bitfield (struct tdesc_type *type, const char *field_name,
|
||||
int start, int end)
|
||||
{
|
||||
struct tdesc_type_field f = { 0 };
|
||||
struct tdesc_type *field_type;
|
||||
|
||||
gdb_assert (type->kind == TDESC_TYPE_STRUCT);
|
||||
gdb_assert (start >= 0 && end >= start);
|
||||
|
||||
f.name = xstrdup (field_name);
|
||||
f.start = start;
|
||||
f.end = end;
|
||||
if (type->u.u.size > 4)
|
||||
field_type = tdesc_predefined_type (TDESC_TYPE_UINT64);
|
||||
else
|
||||
field_type = tdesc_predefined_type (TDESC_TYPE_UINT32);
|
||||
|
||||
VEC_safe_push (tdesc_type_field, type->u.u.fields, &f);
|
||||
tdesc_add_typed_bitfield (type, field_name, start, end, field_type);
|
||||
}
|
||||
|
||||
/* A flag is just a typed(bool) single-bit bitfield.
|
||||
This function is kept to minimize changes in generated files. */
|
||||
|
||||
void
|
||||
tdesc_add_flag (struct tdesc_type *type, int start,
|
||||
const char *flag_name)
|
||||
{
|
||||
struct tdesc_type_flag f = { 0 };
|
||||
struct tdesc_type_field f = { 0 };
|
||||
|
||||
gdb_assert (type->kind == TDESC_TYPE_FLAGS);
|
||||
gdb_assert (type->kind == TDESC_TYPE_FLAGS
|
||||
|| type->kind == TDESC_TYPE_STRUCT);
|
||||
|
||||
f.name = xstrdup (flag_name);
|
||||
f.start = start;
|
||||
f.end = start;
|
||||
f.type = tdesc_predefined_type (TDESC_TYPE_BOOL);
|
||||
|
||||
VEC_safe_push (tdesc_type_flag, type->u.f.flags, &f);
|
||||
VEC_safe_push (tdesc_type_field, type->u.u.fields, &f);
|
||||
}
|
||||
|
||||
void
|
||||
tdesc_add_enum_value (struct tdesc_type *type, int value,
|
||||
const char *name)
|
||||
{
|
||||
struct tdesc_type_field f = { 0 };
|
||||
|
||||
gdb_assert (type->kind == TDESC_TYPE_ENUM);
|
||||
|
||||
f.name = xstrdup (name);
|
||||
f.start = value;
|
||||
f.end = -1;
|
||||
f.type = tdesc_predefined_type (TDESC_TYPE_INT32);
|
||||
|
||||
VEC_safe_push (tdesc_type_field, type->u.u.fields, &f);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1623,7 +1717,6 @@ maint_print_c_tdesc_cmd (char *args, int from_tty)
|
|||
struct tdesc_reg *reg;
|
||||
struct tdesc_type *type;
|
||||
struct tdesc_type_field *f;
|
||||
struct tdesc_type_flag *flag;
|
||||
int ix, ix2, ix3;
|
||||
int printed_field_type = 0;
|
||||
|
||||
|
@ -1686,11 +1779,11 @@ maint_print_c_tdesc_cmd (char *args, int from_tty)
|
|||
printed_field_type = 1;
|
||||
}
|
||||
|
||||
if (((type->kind == TDESC_TYPE_UNION
|
||||
|| type->kind == TDESC_TYPE_STRUCT)
|
||||
&& VEC_length (tdesc_type_field, type->u.u.fields) > 0)
|
||||
|| (type->kind == TDESC_TYPE_FLAGS
|
||||
&& VEC_length (tdesc_type_flag, type->u.f.flags) > 0))
|
||||
if ((type->kind == TDESC_TYPE_UNION
|
||||
|| type->kind == TDESC_TYPE_STRUCT
|
||||
|| type->kind == TDESC_TYPE_FLAGS
|
||||
|| type->kind == TDESC_TYPE_ENUM)
|
||||
&& VEC_length (tdesc_type_field, type->u.u.fields) > 0)
|
||||
{
|
||||
printf_unfiltered (" struct tdesc_type *type;\n");
|
||||
printed_desc_type = 1;
|
||||
|
@ -1761,33 +1854,77 @@ feature = tdesc_create_feature (result, \"%s\");\n",
|
|||
type->name, type->u.v.count);
|
||||
break;
|
||||
case TDESC_TYPE_STRUCT:
|
||||
printf_unfiltered
|
||||
(" type = tdesc_create_struct (feature, \"%s\");\n",
|
||||
type->name);
|
||||
if (type->u.u.size != 0)
|
||||
printf_unfiltered
|
||||
(" tdesc_set_struct_size (type, %s);\n",
|
||||
plongest (type->u.u.size));
|
||||
case TDESC_TYPE_FLAGS:
|
||||
if (type->kind == TDESC_TYPE_STRUCT)
|
||||
{
|
||||
printf_unfiltered
|
||||
(" type = tdesc_create_struct (feature, \"%s\");\n",
|
||||
type->name);
|
||||
if (type->u.u.size != 0)
|
||||
printf_unfiltered
|
||||
(" tdesc_set_struct_size (type, %d);\n",
|
||||
type->u.u.size);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf_unfiltered
|
||||
(" type = tdesc_create_flags (feature, \"%s\", %d);\n",
|
||||
type->name, type->u.u.size);
|
||||
}
|
||||
for (ix3 = 0;
|
||||
VEC_iterate (tdesc_type_field, type->u.u.fields, ix3, f);
|
||||
ix3++)
|
||||
{
|
||||
/* Going first for implicitly sized types, else part handles
|
||||
bitfields. As reported on xml-tdesc.c implicitly sized types
|
||||
cannot contain a bitfield. */
|
||||
if (f->type != NULL)
|
||||
const char *type_name;
|
||||
|
||||
gdb_assert (f->type != NULL);
|
||||
type_name = f->type->name;
|
||||
|
||||
/* To minimize changes to generated files, don't emit type
|
||||
info for fields that have defaulted types. */
|
||||
if (f->start != -1)
|
||||
{
|
||||
gdb_assert (f->end != -1);
|
||||
if (f->type->kind == TDESC_TYPE_BOOL)
|
||||
{
|
||||
gdb_assert (f->start == f->end);
|
||||
printf_unfiltered
|
||||
(" tdesc_add_flag (type, %d, \"%s\");\n",
|
||||
f->start, f->name);
|
||||
}
|
||||
else if ((type->u.u.size == 4
|
||||
&& f->type->kind == TDESC_TYPE_UINT32)
|
||||
|| (type->u.u.size == 8
|
||||
&& f->type->kind == TDESC_TYPE_UINT64))
|
||||
{
|
||||
printf_unfiltered
|
||||
(" tdesc_add_bitfield (type, \"%s\", %d, %d);\n",
|
||||
f->name, f->start, f->end);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf_unfiltered
|
||||
(" field_type = tdesc_named_type (feature,"
|
||||
" \"%s\");\n",
|
||||
type_name);
|
||||
printf_unfiltered
|
||||
(" tdesc_add_typed_bitfield (type, \"%s\","
|
||||
" %d, %d, field_type);\n",
|
||||
f->name, f->start, f->end);
|
||||
}
|
||||
}
|
||||
else /* Not a bitfield. */
|
||||
{
|
||||
gdb_assert (f->end == -1);
|
||||
gdb_assert (type->kind == TDESC_TYPE_STRUCT);
|
||||
printf_unfiltered
|
||||
(" field_type = tdesc_named_type (feature, \"%s\");\n",
|
||||
f->type->name);
|
||||
(" field_type = tdesc_named_type (feature,"
|
||||
" \"%s\");\n",
|
||||
type_name);
|
||||
printf_unfiltered
|
||||
(" tdesc_add_field (type, \"%s\", field_type);\n",
|
||||
f->name);
|
||||
}
|
||||
else
|
||||
printf_unfiltered
|
||||
(" tdesc_add_bitfield (type, \"%s\", %d, %d);\n",
|
||||
f->name, f->start, f->end);
|
||||
}
|
||||
break;
|
||||
case TDESC_TYPE_UNION:
|
||||
|
@ -1806,17 +1943,16 @@ feature = tdesc_create_feature (result, \"%s\");\n",
|
|||
f->name);
|
||||
}
|
||||
break;
|
||||
case TDESC_TYPE_FLAGS:
|
||||
case TDESC_TYPE_ENUM:
|
||||
printf_unfiltered
|
||||
(" type = tdesc_create_flags (feature, \"%s\", %d);\n",
|
||||
type->name, (int) type->u.f.size);
|
||||
(" type = tdesc_create_enum (feature, \"%s\", %d);\n",
|
||||
type->name, type->u.u.size);
|
||||
for (ix3 = 0;
|
||||
VEC_iterate (tdesc_type_flag, type->u.f.flags, ix3,
|
||||
flag);
|
||||
VEC_iterate (tdesc_type_field, type->u.u.fields, ix3, f);
|
||||
ix3++)
|
||||
printf_unfiltered
|
||||
(" tdesc_add_flag (type, %d, \"%s\");\n",
|
||||
flag->start, flag->name);
|
||||
(" tdesc_add_enum_value (type, %d, \"%s\");\n",
|
||||
f->start, f->name);
|
||||
break;
|
||||
default:
|
||||
error (_("C output is not supported type \"%s\"."), type->name);
|
||||
|
|
|
@ -235,12 +235,20 @@ struct tdesc_type *tdesc_create_union (struct tdesc_feature *feature,
|
|||
struct tdesc_type *tdesc_create_flags (struct tdesc_feature *feature,
|
||||
const char *name,
|
||||
int size);
|
||||
struct tdesc_type *tdesc_create_enum (struct tdesc_feature *feature,
|
||||
const char *name,
|
||||
int size);
|
||||
void tdesc_add_field (struct tdesc_type *type, const char *field_name,
|
||||
struct tdesc_type *field_type);
|
||||
void tdesc_add_typed_bitfield (struct tdesc_type *type, const char *field_name,
|
||||
int start, int end,
|
||||
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_add_enum_value (struct tdesc_type *type, int value,
|
||||
const char *name);
|
||||
void tdesc_create_reg (struct tdesc_feature *feature, const char *name,
|
||||
int regnum, int save_restore, const char *group,
|
||||
int bitsize, const char *type);
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2016-03-15 Doug Evans <dje@google.com>
|
||||
|
||||
* gdb.xml/extra-regs.xml: Add enum, mixed_flags values.
|
||||
* gdb.xml/tdesc-regs.exp (load_description): New arg xml_file.
|
||||
All callers updated. Add tests for enums, mixed flags register.
|
||||
|
||||
2016-03-15 Doug Evans <dje@google.com>
|
||||
|
||||
* gdb.base/skip.c (main): Call test_skip_file_and_function.
|
||||
|
|
|
@ -23,6 +23,30 @@
|
|||
<field name="Y" start="2" end="2"/>
|
||||
</flags>
|
||||
|
||||
<enum id="Z_values" size="4">
|
||||
<evalue name="yes" value="1"/>
|
||||
<evalue name="no" value="0"/>
|
||||
<evalue name="maybe" value="2"/>
|
||||
<evalue name="so" value="3"/>
|
||||
</enum>
|
||||
|
||||
<flags id="mixed_flags" size="4">
|
||||
<!-- Elided end and type. -->
|
||||
<field name="A" start="0"/>
|
||||
<!-- Elided end, unsigned int. -->
|
||||
<field name="B" start="1" type="uint32"/>
|
||||
<!-- Elided end, bool. -->
|
||||
<field name="C" start="2" type="bool"/>
|
||||
<!-- Elided type, single bitfield. -->
|
||||
<field name="D" start="3" end="3"/>
|
||||
<!-- Anonymous field. -->
|
||||
<field name="" start="4" end="5"/>
|
||||
<!-- Multi-bit bitfield, elided type. -->
|
||||
<field name="E" start="6" end="7"/>
|
||||
<!-- Enum bitfield. -->
|
||||
<field name="Z" start="8" end="9" type="Z_values"/>
|
||||
</flags>
|
||||
|
||||
<reg name="extrareg" bitsize="32"/>
|
||||
<reg name="uintreg" bitsize="32" type="uint32"/>
|
||||
<reg name="vecreg" bitsize="32" type="v4int8"/>
|
||||
|
@ -30,5 +54,6 @@
|
|||
<reg name="structreg" bitsize="64" type="struct1"/>
|
||||
<reg name="bitfields" bitsize="64" type="struct2"/>
|
||||
<reg name="flags" bitsize="32" type="flags"/>
|
||||
<reg name="mixed_flags" bitsize="32" type="mixed_flags"/>
|
||||
</feature>
|
||||
</target>
|
||||
|
|
|
@ -106,7 +106,7 @@ foreach src ${core-regs} {
|
|||
}
|
||||
|
||||
# Similarly, we need to copy files under test into the objdir.
|
||||
proc load_description { file errmsg } {
|
||||
proc load_description { file errmsg xml_file } {
|
||||
global srcdir
|
||||
global subdir
|
||||
global gdb_prompt
|
||||
|
@ -114,7 +114,7 @@ proc load_description { file errmsg } {
|
|||
global architecture
|
||||
global remote_filename
|
||||
|
||||
set regs_file [standard_output_file regs.xml]
|
||||
set regs_file [standard_output_file $xml_file]
|
||||
|
||||
file delete $regs_file
|
||||
set ifd [open "$srcdir/$subdir/$file" r]
|
||||
|
@ -135,22 +135,18 @@ proc load_description { file errmsg } {
|
|||
close $ofd
|
||||
|
||||
if {[is_remote host]} {
|
||||
set regs_file [remote_download host "$subdir/regs.xml" "regs.xml"]
|
||||
set regs_file [remote_download host "$subdir/$xml_file" $xml_file]
|
||||
}
|
||||
|
||||
# Anchor the test output, so that error messages are detected.
|
||||
set cmd "set tdesc filename [file tail $regs_file]"
|
||||
set msg "set tdesc filename regs.xml - from $file"
|
||||
set msg "set tdesc filename $xml_file - from $file"
|
||||
set cmd_regex [string_to_regexp $cmd]
|
||||
gdb_test_multiple $cmd $msg {
|
||||
-re "^$cmd_regex\r\n$errmsg$gdb_prompt $" {
|
||||
pass $msg
|
||||
}
|
||||
}
|
||||
|
||||
if {[is_remote host]} {
|
||||
remote_file host delete "regs.xml"
|
||||
}
|
||||
}
|
||||
|
||||
if {![is_remote host]} {
|
||||
|
@ -158,7 +154,7 @@ if {![is_remote host]} {
|
|||
"cd to directory holding xml"
|
||||
}
|
||||
|
||||
load_description "extra-regs.xml" ""
|
||||
load_description "extra-regs.xml" "" "test-extra-regs.xml"
|
||||
gdb_test "ptype \$extrareg" "type = (int|long|long long)"
|
||||
gdb_test "ptype \$uintreg" "type = uint32_t"
|
||||
gdb_test "ptype \$vecreg" "type = int8_t __attribute__ \\(\\(vector_size\\(4\\)\\)\\)"
|
||||
|
@ -170,7 +166,11 @@ gdb_test "ptype \$structreg" \
|
|||
gdb_test "ptype \$structreg.v4" "type = int8_t __attribute__ \\(\\(vector_size\\(4\\)\\)\\)"
|
||||
gdb_test "ptype \$bitfields" \
|
||||
"type = struct struct2 {\r\n *uint64_t f1 : 35;\r\n *uint64_t f2 : 1;\r\n}"
|
||||
gdb_test "ptype \$flags" \
|
||||
"type = flag flags {\r\n *uint32_t X @0;\r\n *uint32_t Y @2;\r\n}"
|
||||
gdb_test "ptype \$mixed_flags" \
|
||||
"type = flag mixed_flags {\r\n *bool A @0;\r\n *uint32_t B @1;\r\n *bool C @2;\r\n *uint32_t D @3;\r\n *uint32_t @4-5;\r\n *uint32_t E @6-7;\r\n *enum {yes = 1, no = 0, maybe = 2, so} Z @8-9;\r\n}"
|
||||
|
||||
load_description "core-only.xml" ""
|
||||
load_description "core-only.xml" "" "test-regs.xml"
|
||||
# The extra register from the previous description should be gone.
|
||||
gdb_test "ptype \$extrareg" "type = void"
|
||||
|
|
|
@ -98,6 +98,10 @@ static void set_output_radix (char *, int, struct cmd_list_element *);
|
|||
|
||||
static void set_output_radix_1 (int, unsigned);
|
||||
|
||||
static void val_print_type_code_flags (struct type *type,
|
||||
const gdb_byte *valaddr,
|
||||
struct ui_file *stream);
|
||||
|
||||
void _initialize_valprint (void);
|
||||
|
||||
#define PRINT_MAX_DEFAULT 200 /* Start print_max off at this value. */
|
||||
|
@ -526,28 +530,17 @@ generic_val_print_ref (struct type *type, const gdb_byte *valaddr,
|
|||
}
|
||||
}
|
||||
|
||||
/* generic_val_print helper for TYPE_CODE_ENUM. */
|
||||
/* Helper function for generic_val_print_enum.
|
||||
This is also used to print enums in TYPE_CODE_FLAGS values. */
|
||||
|
||||
static void
|
||||
generic_val_print_enum (struct type *type, const gdb_byte *valaddr,
|
||||
int embedded_offset, struct ui_file *stream,
|
||||
const struct value *original_value,
|
||||
const struct value_print_options *options)
|
||||
generic_val_print_enum_1 (struct type *type, LONGEST val,
|
||||
struct ui_file *stream)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int len;
|
||||
LONGEST val;
|
||||
struct gdbarch *gdbarch = get_type_arch (type);
|
||||
int unit_size = gdbarch_addressable_memory_unit_size (gdbarch);
|
||||
|
||||
if (options->format)
|
||||
{
|
||||
val_print_scalar_formatted (type, valaddr, embedded_offset,
|
||||
original_value, options, 0, stream);
|
||||
return;
|
||||
}
|
||||
len = TYPE_NFIELDS (type);
|
||||
val = unpack_long (type, valaddr + embedded_offset * unit_size);
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
QUIT;
|
||||
|
@ -597,6 +590,29 @@ generic_val_print_enum (struct type *type, const gdb_byte *valaddr,
|
|||
print_longest (stream, 'd', 0, val);
|
||||
}
|
||||
|
||||
/* generic_val_print helper for TYPE_CODE_ENUM. */
|
||||
|
||||
static void
|
||||
generic_val_print_enum (struct type *type, const gdb_byte *valaddr,
|
||||
int embedded_offset, struct ui_file *stream,
|
||||
const struct value *original_value,
|
||||
const struct value_print_options *options)
|
||||
{
|
||||
LONGEST val;
|
||||
struct gdbarch *gdbarch = get_type_arch (type);
|
||||
int unit_size = gdbarch_addressable_memory_unit_size (gdbarch);
|
||||
|
||||
if (options->format)
|
||||
{
|
||||
val_print_scalar_formatted (type, valaddr, embedded_offset,
|
||||
original_value, options, 0, stream);
|
||||
return;
|
||||
}
|
||||
val = unpack_long (type, valaddr + embedded_offset * unit_size);
|
||||
|
||||
generic_val_print_enum_1 (type, val, stream);
|
||||
}
|
||||
|
||||
/* generic_val_print helper for TYPE_CODE_FLAGS. */
|
||||
|
||||
static void
|
||||
|
@ -1162,26 +1178,51 @@ val_print_type_code_int (struct type *type, const gdb_byte *valaddr,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
val_print_type_code_flags (struct type *type, const gdb_byte *valaddr,
|
||||
struct ui_file *stream)
|
||||
{
|
||||
ULONGEST val = unpack_long (type, valaddr);
|
||||
int bitpos, nfields = TYPE_NFIELDS (type);
|
||||
int field, nfields = TYPE_NFIELDS (type);
|
||||
struct gdbarch *gdbarch = get_type_arch (type);
|
||||
struct type *bool_type = builtin_type (gdbarch)->builtin_bool;
|
||||
|
||||
fputs_filtered ("[ ", stream);
|
||||
for (bitpos = 0; bitpos < nfields; bitpos++)
|
||||
fputs_filtered ("[", stream);
|
||||
for (field = 0; field < nfields; field++)
|
||||
{
|
||||
if (TYPE_FIELD_BITPOS (type, bitpos) != -1
|
||||
&& (val & ((ULONGEST)1 << bitpos)))
|
||||
if (TYPE_FIELD_NAME (type, field)[0] != '\0')
|
||||
{
|
||||
if (TYPE_FIELD_NAME (type, bitpos))
|
||||
fprintf_filtered (stream, "%s ", TYPE_FIELD_NAME (type, bitpos));
|
||||
struct type *field_type = TYPE_FIELD_TYPE (type, field);
|
||||
|
||||
if (field_type == bool_type
|
||||
/* We require boolean types here to be one bit wide. This is a
|
||||
problematic place to notify the user of an internal error
|
||||
though. Instead just fall through and print the field as an
|
||||
int. */
|
||||
&& TYPE_FIELD_BITSIZE (type, field) == 1)
|
||||
{
|
||||
if (val & ((ULONGEST)1 << TYPE_FIELD_BITPOS (type, field)))
|
||||
fprintf_filtered (stream, " %s",
|
||||
TYPE_FIELD_NAME (type, field));
|
||||
}
|
||||
else
|
||||
fprintf_filtered (stream, "#%d ", bitpos);
|
||||
{
|
||||
unsigned field_len = TYPE_FIELD_BITSIZE (type, field);
|
||||
ULONGEST field_val
|
||||
= val >> (TYPE_FIELD_BITPOS (type, field) - field_len + 1);
|
||||
|
||||
if (field_len < sizeof (ULONGEST) * TARGET_CHAR_BIT)
|
||||
field_val &= ((ULONGEST) 1 << field_len) - 1;
|
||||
fprintf_filtered (stream, " %s=",
|
||||
TYPE_FIELD_NAME (type, field));
|
||||
if (TYPE_CODE (field_type) == TYPE_CODE_ENUM)
|
||||
generic_val_print_enum_1 (field_type, field_val, stream);
|
||||
else
|
||||
print_longest (stream, 'd', 0, field_val);
|
||||
}
|
||||
}
|
||||
}
|
||||
fputs_filtered ("]", stream);
|
||||
fputs_filtered (" ]", stream);
|
||||
}
|
||||
|
||||
/* Print a scalar of data of type TYPE, pointed to in GDB by VALADDR,
|
||||
|
|
|
@ -124,10 +124,6 @@ extern void val_print_array_elements (struct type *, const gdb_byte *, int,
|
|||
extern void val_print_type_code_int (struct type *, const gdb_byte *,
|
||||
struct ui_file *);
|
||||
|
||||
extern void val_print_type_code_flags (struct type *type,
|
||||
const gdb_byte *valaddr,
|
||||
struct ui_file *stream);
|
||||
|
||||
extern void val_print_scalar_formatted (struct type *,
|
||||
const gdb_byte *, int,
|
||||
const struct value *,
|
||||
|
|
194
gdb/xml-tdesc.c
194
gdb/xml-tdesc.c
|
@ -91,12 +91,9 @@ struct tdesc_parsing_data
|
|||
/* The struct or union we are currently parsing, or last parsed. */
|
||||
struct tdesc_type *current_type;
|
||||
|
||||
/* The byte size of the current struct type, if specified. Zero
|
||||
if not specified. */
|
||||
/* The byte size of the current struct/flags type, if specified. Zero
|
||||
if not specified. Flags values must specify a size. */
|
||||
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. */
|
||||
|
@ -240,7 +237,6 @@ tdesc_start_union (struct gdb_xml_parser *parser,
|
|||
|
||||
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
|
||||
|
@ -259,7 +255,6 @@ tdesc_start_struct (struct gdb_xml_parser *parser,
|
|||
type = tdesc_create_struct (data->current_feature, id);
|
||||
data->current_type = type;
|
||||
data->current_type_size = 0;
|
||||
data->current_type_is_flags = 0;
|
||||
|
||||
attr = xml_find_attribute (attributes, "size");
|
||||
if (attr != NULL)
|
||||
|
@ -296,13 +291,35 @@ tdesc_start_flags (struct gdb_xml_parser *parser,
|
|||
}
|
||||
type = tdesc_create_flags (data->current_feature, id, size);
|
||||
|
||||
data->current_type = type;
|
||||
data->current_type_size = size;
|
||||
}
|
||||
|
||||
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 size = * (ULONGEST *)
|
||||
xml_find_attribute (attributes, "size")->value;
|
||||
struct tdesc_type *type;
|
||||
|
||||
if (size > MAX_FIELD_SIZE)
|
||||
{
|
||||
gdb_xml_error (parser,
|
||||
_("Enum size %s is larger than maximum (%d)"),
|
||||
pulongest (size), MAX_FIELD_SIZE);
|
||||
}
|
||||
type = tdesc_create_enum (data->current_feature, id, size);
|
||||
|
||||
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. */
|
||||
current struct, union or flags. */
|
||||
|
||||
static void
|
||||
tdesc_start_field (struct gdb_xml_parser *parser,
|
||||
|
@ -319,9 +336,15 @@ tdesc_start_field (struct gdb_xml_parser *parser,
|
|||
|
||||
attr = xml_find_attribute (attributes, "type");
|
||||
if (attr != NULL)
|
||||
field_type_id = (char *) attr->value;
|
||||
{
|
||||
field_type_id = (char *) 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)
|
||||
|
@ -355,18 +378,66 @@ tdesc_start_field (struct gdb_xml_parser *parser,
|
|||
else
|
||||
end = -1;
|
||||
|
||||
if (field_type_id != NULL)
|
||||
if (start != -1)
|
||||
{
|
||||
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)
|
||||
struct tdesc_type *t = data->current_type;
|
||||
|
||||
if (data->current_type_size == 0)
|
||||
gdb_xml_error (parser,
|
||||
_("Explicitly sized type can not "
|
||||
"contain non-bitfield \"%s\""),
|
||||
_("Bitfields must live in explicitly sized types"));
|
||||
|
||||
if (field_type_id != NULL
|
||||
&& strcmp (field_type_id, "bool") == 0
|
||||
&& !(start == end || end == -1))
|
||||
{
|
||||
gdb_xml_error (parser,
|
||||
_("Boolean fields must be one bit in size"));
|
||||
}
|
||||
|
||||
if (end >= 64)
|
||||
gdb_xml_error (parser,
|
||||
_("Bitfield \"%s\" goes past "
|
||||
"64 bits (unsupported)"),
|
||||
field_name);
|
||||
|
||||
if (end != -1)
|
||||
{
|
||||
/* 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"));
|
||||
}
|
||||
|
||||
if (end == -1)
|
||||
{
|
||||
if (field_type != NULL)
|
||||
tdesc_add_typed_bitfield (t, field_name, start, start, field_type);
|
||||
else
|
||||
tdesc_add_flag (t, start, field_name);
|
||||
}
|
||||
else if (field_type != NULL)
|
||||
tdesc_add_typed_bitfield (t, field_name, start, end, field_type);
|
||||
else
|
||||
tdesc_add_bitfield (t, field_name, start, end);
|
||||
}
|
||||
else if (start == -1 && end != -1)
|
||||
gdb_xml_error (parser, _("End specified but not start"));
|
||||
else if (field_type_id != NULL)
|
||||
{
|
||||
/* TDESC_TYPE_FLAGS values are explicitly sized, so the following test
|
||||
catches adding non-bitfield types to flags as well. */
|
||||
if (data->current_type_size != 0)
|
||||
gdb_xml_error (parser,
|
||||
_("Explicitly sized type cannot "
|
||||
"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\""),
|
||||
|
@ -374,46 +445,40 @@ tdesc_start_field (struct gdb_xml_parser *parser,
|
|||
|
||||
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 an <evalue> element. Attach the value to the
|
||||
current enum. */
|
||||
|
||||
static void
|
||||
tdesc_start_enum_value (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 = (struct tdesc_parsing_data *) user_data;
|
||||
struct gdb_xml_value *attr;
|
||||
char *field_name;
|
||||
ULONGEST ul_value;
|
||||
int value;
|
||||
|
||||
field_name = (char *) xml_find_attribute (attributes, "name")->value;
|
||||
|
||||
attr = xml_find_attribute (attributes, "value");
|
||||
ul_value = * (ULONGEST *) attr->value;
|
||||
if (ul_value > INT_MAX)
|
||||
{
|
||||
gdb_xml_error (parser,
|
||||
_("Enum value %s is larger than maximum (%d)"),
|
||||
pulongest (ul_value), INT_MAX);
|
||||
}
|
||||
value = ul_value;
|
||||
|
||||
tdesc_add_enum_value (data->current_type, value, field_name);
|
||||
}
|
||||
|
||||
/* Handle the start of a <vector> element. Initialize the type and
|
||||
record it with the current feature. */
|
||||
|
||||
|
@ -457,12 +522,24 @@ static const struct gdb_xml_attribute field_attributes[] = {
|
|||
{ NULL, GDB_XML_AF_NONE, NULL, NULL }
|
||||
};
|
||||
|
||||
static const struct gdb_xml_attribute enum_value_attributes[] = {
|
||||
{ "name", GDB_XML_AF_NONE, NULL, NULL },
|
||||
{ "value", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL },
|
||||
{ NULL, GDB_XML_AF_NONE, NULL, NULL }
|
||||
};
|
||||
|
||||
static const struct gdb_xml_element struct_union_children[] = {
|
||||
{ "field", field_attributes, NULL, GDB_XML_EF_REPEATABLE,
|
||||
tdesc_start_field, NULL },
|
||||
{ NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
|
||||
};
|
||||
|
||||
static const struct gdb_xml_element enum_children[] = {
|
||||
{ "evalue", enum_value_attributes, NULL, GDB_XML_EF_REPEATABLE,
|
||||
tdesc_start_enum_value, NULL },
|
||||
{ NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
|
||||
};
|
||||
|
||||
static const struct gdb_xml_attribute reg_attributes[] = {
|
||||
{ "name", GDB_XML_AF_NONE, NULL, NULL },
|
||||
{ "bitsize", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
|
||||
|
@ -486,6 +563,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 },
|
||||
|
@ -511,6 +594,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, enum_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 },
|
||||
|
|
Loading…
Reference in a new issue