X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Ftarget-descriptions.c;h=9a7e2ddfbd632f4e55f8c8834576dd89ad9c82ee;hb=94de2a2c57b7f6b2870f72ecdcacc6d909c6421a;hp=9856d6f76cafeb2b199e3c02a3761cb6b41c1a52;hpb=9fd3625f79a17480dd4017136edf4f9a21e834df;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/target-descriptions.c b/gdb/target-descriptions.c index 9856d6f76c..9a7e2ddfbd 100644 --- a/gdb/target-descriptions.c +++ b/gdb/target-descriptions.c @@ -1,6 +1,6 @@ /* Target description support for GDB. - Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2006-2017 Free Software Foundation, Inc. Contributed by CodeSourcery. @@ -31,9 +31,9 @@ #include "xml-tdesc.h" #include "osabi.h" -#include "gdb_assert.h" #include "gdb_obstack.h" #include "hashtab.h" +#include "inferior.h" /* Types. */ @@ -90,41 +90,51 @@ 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); +enum tdesc_type_kind +{ + /* Predefined types. */ + TDESC_TYPE_BOOL, + TDESC_TYPE_INT8, + TDESC_TYPE_INT16, + TDESC_TYPE_INT32, + TDESC_TYPE_INT64, + TDESC_TYPE_INT128, + TDESC_TYPE_UINT8, + TDESC_TYPE_UINT16, + TDESC_TYPE_UINT32, + TDESC_TYPE_UINT64, + TDESC_TYPE_UINT128, + TDESC_TYPE_CODE_PTR, + TDESC_TYPE_DATA_PTR, + TDESC_TYPE_IEEE_SINGLE, + TDESC_TYPE_IEEE_DOUBLE, + TDESC_TYPE_ARM_FPA_EXT, + TDESC_TYPE_I387_EXT, + + /* Types defined by a target feature. */ + TDESC_TYPE_VECTOR, + TDESC_TYPE_STRUCT, + TDESC_TYPE_UNION, + TDESC_TYPE_FLAGS, + TDESC_TYPE_ENUM +}; + typedef struct tdesc_type { - /* The name of this type. */ - char *name; + /* The name of this type. If this type is a built-in type, this is + a pointer to a constant string. Otherwise, it's a + malloc-allocated string (and thus must be freed). */ + const char *name; /* Identify the kind of this type. */ - enum - { - /* Predefined types. */ - TDESC_TYPE_INT8, - TDESC_TYPE_INT16, - TDESC_TYPE_INT32, - TDESC_TYPE_INT64, - TDESC_TYPE_INT128, - TDESC_TYPE_UINT8, - TDESC_TYPE_UINT16, - TDESC_TYPE_UINT32, - TDESC_TYPE_UINT64, - TDESC_TYPE_UINT128, - TDESC_TYPE_CODE_PTR, - TDESC_TYPE_DATA_PTR, - TDESC_TYPE_IEEE_SINGLE, - TDESC_TYPE_IEEE_DOUBLE, - TDESC_TYPE_ARM_FPA_EXT, - TDESC_TYPE_I387_EXT, - TDESC_TYPE_I386_EFLAGS, - TDESC_TYPE_I386_MXCSR, - - /* Types defined by a target feature. */ - TDESC_TYPE_VECTOR, - TDESC_TYPE_UNION - } kind; + enum tdesc_type_kind kind; /* Kind-specific data. */ union @@ -136,10 +146,11 @@ typedef struct tdesc_type int count; } v; - /* Union type. */ + /* Struct, union, flags, or enum type. */ struct { VEC(tdesc_type_field) *fields; + int size; } u; } u; } *tdesc_type_p; @@ -215,34 +226,92 @@ struct tdesc_arch_data gdbarch_register_reggroup_p_ftype *pseudo_register_reggroup_p; }; -/* Global state. These variables are associated with the current - target; if GDB adds support for multiple simultaneous targets, then - these variables should become target-specific data. */ +/* Info about an inferior's target description. There's one of these + for each inferior. */ -/* A flag indicating that a description has already been fetched from - the current target, so it should not be queried again. */ +struct target_desc_info +{ + /* A flag indicating that a description has already been fetched + from the target, so it should not be queried again. */ -static int target_desc_fetched; + int fetched; -/* The description fetched from the current target, or NULL if the - current target did not supply any description. Only valid when - target_desc_fetched is set. Only the description initialization - code should access this; normally, the description should be - accessed through the gdbarch object. */ + /* The description fetched from the target, or NULL if the target + did not supply any description. Only valid when + target_desc_fetched is set. Only the description initialization + code should access this; normally, the description should be + accessed through the gdbarch object. */ -static const struct target_desc *current_target_desc; + const struct target_desc *tdesc; -/* Other global variables. */ + /* The filename to read a target description from, as set by "set + tdesc filename ..." */ -/* The filename to read a target description from. */ + char *filename; +}; -static char *target_description_filename; +/* Get the inferior INF's target description info, allocating one on + the stop if necessary. */ + +static struct target_desc_info * +get_tdesc_info (struct inferior *inf) +{ + if (inf->tdesc_info == NULL) + inf->tdesc_info = XCNEW (struct target_desc_info); + return inf->tdesc_info; +} /* A handle for architecture-specific data associated with the target description (see struct tdesc_arch_data). */ static struct gdbarch_data *tdesc_data; +/* See target-descriptions.h. */ + +int +target_desc_info_from_user_p (struct target_desc_info *info) +{ + return info != NULL && info->filename != NULL; +} + +/* See target-descriptions.h. */ + +void +copy_inferior_target_desc_info (struct inferior *destinf, struct inferior *srcinf) +{ + struct target_desc_info *src = get_tdesc_info (srcinf); + struct target_desc_info *dest = get_tdesc_info (destinf); + + dest->fetched = src->fetched; + dest->tdesc = src->tdesc; + dest->filename = src->filename != NULL ? xstrdup (src->filename) : NULL; +} + +/* See target-descriptions.h. */ + +void +target_desc_info_free (struct target_desc_info *tdesc_info) +{ + if (tdesc_info != NULL) + { + xfree (tdesc_info->filename); + xfree (tdesc_info); + } +} + +/* Convenience helper macros. */ + +#define target_desc_fetched \ + get_tdesc_info (current_inferior ())->fetched +#define current_target_desc \ + get_tdesc_info (current_inferior ())->tdesc +#define target_description_filename \ + get_tdesc_info (current_inferior ())->filename + +/* The string manipulated by the "set tdesc filename ..." command. */ + +static char *tdesc_filename_cmd_string; + /* Fetch the current target's description, and switch the current architecture to one which incorporates that description. */ @@ -259,7 +328,7 @@ target_find_description (void) /* The current architecture should not have any target description specified. It should have been cleared, e.g. when we disconnected from the previous target. */ - gdb_assert (gdbarch_target_desc (target_gdbarch) == NULL); + gdb_assert (gdbarch_target_desc (target_gdbarch ()) == NULL); /* First try to fetch an XML description from the user-specified file. */ @@ -292,7 +361,8 @@ target_find_description (void) { struct tdesc_arch_data *data; - data = gdbarch_data (target_gdbarch, tdesc_data); + data = ((struct tdesc_arch_data *) + gdbarch_data (target_gdbarch (), tdesc_data)); if (tdesc_has_registers (current_target_desc) && data->arch_regs == NULL) warning (_("Target-supplied registers are not supported " @@ -450,6 +520,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 }, @@ -465,11 +536,24 @@ static struct tdesc_type tdesc_predefined_types[] = { "ieee_single", TDESC_TYPE_IEEE_SINGLE }, { "ieee_double", TDESC_TYPE_IEEE_DOUBLE }, { "arm_fpa_ext", TDESC_TYPE_ARM_FPA_EXT }, - { "i387_ext", TDESC_TYPE_I387_EXT }, - { "i386_eflags", TDESC_TYPE_I386_EFLAGS }, - { "i386_mxcsr", TDESC_TYPE_I386_MXCSR } + { "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. */ @@ -501,7 +585,7 @@ tdesc_find_type (struct gdbarch *gdbarch, const char *id) struct tdesc_arch_data *data; int i, num_regs; - data = gdbarch_data (gdbarch, tdesc_data); + data = (struct tdesc_arch_data *) gdbarch_data (gdbarch, tdesc_data); num_regs = VEC_length (tdesc_arch_reg, data->arch_regs); for (i = 0; i < num_regs; i++) { @@ -527,6 +611,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; @@ -589,66 +676,77 @@ tdesc_gdb_type (struct gdbarch *gdbarch, struct tdesc_type *tdesc_type) return arch_float_type (gdbarch, -1, "builtin_type_i387_ext", floatformats_i387_ext); - case TDESC_TYPE_I386_EFLAGS: + /* Types defined by a target feature. */ + case TDESC_TYPE_VECTOR: { - struct type *type; - - type = arch_flags_type (gdbarch, "builtin_type_i386_eflags", 4); - append_flags_type_flag (type, 0, "CF"); - append_flags_type_flag (type, 1, NULL); - append_flags_type_flag (type, 2, "PF"); - append_flags_type_flag (type, 4, "AF"); - append_flags_type_flag (type, 6, "ZF"); - append_flags_type_flag (type, 7, "SF"); - append_flags_type_flag (type, 8, "TF"); - append_flags_type_flag (type, 9, "IF"); - append_flags_type_flag (type, 10, "DF"); - append_flags_type_flag (type, 11, "OF"); - append_flags_type_flag (type, 14, "NT"); - append_flags_type_flag (type, 16, "RF"); - append_flags_type_flag (type, 17, "VM"); - append_flags_type_flag (type, 18, "AC"); - append_flags_type_flag (type, 19, "VIF"); - append_flags_type_flag (type, 20, "VIP"); - append_flags_type_flag (type, 21, "ID"); - - return type; - } - break; + struct type *type, *field_type; - case TDESC_TYPE_I386_MXCSR: - { - struct type *type; - - type = arch_flags_type (gdbarch, "builtin_type_i386_mxcsr", 4); - append_flags_type_flag (type, 0, "IE"); - append_flags_type_flag (type, 1, "DE"); - append_flags_type_flag (type, 2, "ZE"); - append_flags_type_flag (type, 3, "OE"); - append_flags_type_flag (type, 4, "UE"); - append_flags_type_flag (type, 5, "PE"); - append_flags_type_flag (type, 6, "DAZ"); - append_flags_type_flag (type, 7, "IM"); - append_flags_type_flag (type, 8, "DM"); - append_flags_type_flag (type, 9, "ZM"); - append_flags_type_flag (type, 10, "OM"); - append_flags_type_flag (type, 11, "UM"); - append_flags_type_flag (type, 12, "PM"); - append_flags_type_flag (type, 15, "FZ"); + field_type = tdesc_gdb_type (gdbarch, tdesc_type->u.v.type); + type = init_vector_type (field_type, tdesc_type->u.v.count); + TYPE_NAME (type) = xstrdup (tdesc_type->name); return type; } - break; - /* Types defined by a target feature. */ - case TDESC_TYPE_VECTOR: + case TDESC_TYPE_STRUCT: { struct type *type, *field_type; + struct tdesc_type_field *f; + int ix; - field_type = tdesc_gdb_type (gdbarch, tdesc_type->u.v.type); - type = init_vector_type (field_type, tdesc_type->u.v.count); + 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->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. */ + gdb_assert (tdesc_type->u.u.size != 0); + 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; + + 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)) + SET_FIELD_BITPOS (fld[0], total_size - f->start - bitsize); + else + SET_FIELD_BITPOS (fld[0], f->start); + FIELD_BITSIZE (fld[0]) = bitsize; + } + 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); + } + } + + if (tdesc_type->u.u.size != 0) + TYPE_LENGTH (type) = tdesc_type->u.u.size; return type; } @@ -668,12 +766,56 @@ tdesc_gdb_type (struct gdbarch *gdbarch, struct tdesc_type *tdesc_type) field_type = tdesc_gdb_type (gdbarch, f->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 vector types to show up automatically in "info vector". */ if (TYPE_VECTOR (field_type)) TYPE_VECTOR (type) = 1; } + return type; + } + + case TDESC_TYPE_FLAGS: + { + struct tdesc_type_field *f; + int ix; + + type = arch_flags_type (gdbarch, tdesc_type->name, + tdesc_type->u.u.size); + for (ix = 0; + VEC_iterate (tdesc_type_field, tdesc_type->u.u.fields, ix, f); + ix++) + { + 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; } @@ -704,7 +846,7 @@ tdesc_data_init (struct obstack *obstack) struct tdesc_arch_data * tdesc_data_alloc (void) { - return XZALLOC (struct tdesc_arch_data); + return XCNEW (struct tdesc_arch_data); } /* Free something allocated by tdesc_data_alloc, if it is not going @@ -714,7 +856,7 @@ tdesc_data_alloc (void) void tdesc_data_cleanup (void *data_untyped) { - struct tdesc_arch_data *data = data_untyped; + struct tdesc_arch_data *data = (struct tdesc_arch_data *) data_untyped; VEC_free (tdesc_arch_reg, data->arch_regs); xfree (data); @@ -810,10 +952,9 @@ tdesc_register_size (const struct tdesc_feature *feature, static struct tdesc_arch_reg * tdesc_find_arch_register (struct gdbarch *gdbarch, int regno) { - struct tdesc_arch_reg *reg; struct tdesc_arch_data *data; - data = gdbarch_data (gdbarch, tdesc_data); + data = (struct tdesc_arch_data *) gdbarch_data (gdbarch, tdesc_data); if (regno < VEC_length (tdesc_arch_reg, data->arch_regs)) return VEC_index (tdesc_arch_reg, data->arch_regs, regno); else @@ -824,6 +965,7 @@ static struct tdesc_reg * tdesc_find_register (struct gdbarch *gdbarch, int regno) { struct tdesc_arch_reg *reg = tdesc_find_arch_register (gdbarch, regno); + return reg? reg->reg : NULL; } @@ -842,7 +984,9 @@ tdesc_register_name (struct gdbarch *gdbarch, int regno) if (regno >= num_regs && regno < num_regs + num_pseudo_regs) { - struct tdesc_arch_data *data = gdbarch_data (gdbarch, tdesc_data); + struct tdesc_arch_data *data + = (struct tdesc_arch_data *) gdbarch_data (gdbarch, tdesc_data); + gdb_assert (data->pseudo_register_name != NULL); return data->pseudo_register_name (gdbarch, regno); } @@ -860,7 +1004,9 @@ tdesc_register_type (struct gdbarch *gdbarch, int regno) if (reg == NULL && regno >= num_regs && regno < num_regs + num_pseudo_regs) { - struct tdesc_arch_data *data = gdbarch_data (gdbarch, tdesc_data); + struct tdesc_arch_data *data + = (struct tdesc_arch_data *) gdbarch_data (gdbarch, tdesc_data); + gdb_assert (data->pseudo_register_type != NULL); return data->pseudo_register_type (gdbarch, regno); } @@ -904,7 +1050,7 @@ tdesc_register_type (struct gdbarch *gdbarch, int regno) else if (reg->bitsize == gdbarch_long_long_bit (gdbarch)) arch_reg->type = builtin_type (gdbarch)->builtin_long_long; else if (reg->bitsize == gdbarch_ptr_bit (gdbarch)) - /* A bit desperate by this point... */ + /* A bit desperate by this point... */ arch_reg->type = builtin_type (gdbarch)->builtin_data_ptr; else { @@ -997,7 +1143,9 @@ tdesc_register_reggroup_p (struct gdbarch *gdbarch, int regno, if (regno >= num_regs && regno < num_regs + num_pseudo_regs) { - struct tdesc_arch_data *data = gdbarch_data (gdbarch, tdesc_data); + struct tdesc_arch_data *data + = (struct tdesc_arch_data *) gdbarch_data (gdbarch, tdesc_data); + if (data->pseudo_register_reggroup_p != NULL) return data->pseudo_register_reggroup_p (gdbarch, regno, reggroup); /* Otherwise fall through to the default reggroup_p. */ @@ -1017,7 +1165,8 @@ void set_tdesc_pseudo_register_name (struct gdbarch *gdbarch, gdbarch_register_name_ftype *pseudo_name) { - struct tdesc_arch_data *data = gdbarch_data (gdbarch, tdesc_data); + struct tdesc_arch_data *data + = (struct tdesc_arch_data *) gdbarch_data (gdbarch, tdesc_data); data->pseudo_register_name = pseudo_name; } @@ -1026,7 +1175,8 @@ void set_tdesc_pseudo_register_type (struct gdbarch *gdbarch, gdbarch_register_type_ftype *pseudo_type) { - struct tdesc_arch_data *data = gdbarch_data (gdbarch, tdesc_data); + struct tdesc_arch_data *data + = (struct tdesc_arch_data *) gdbarch_data (gdbarch, tdesc_data); data->pseudo_register_type = pseudo_type; } @@ -1036,7 +1186,8 @@ set_tdesc_pseudo_register_reggroup_p (struct gdbarch *gdbarch, gdbarch_register_reggroup_p_ftype *pseudo_reggroup_p) { - struct tdesc_arch_data *data = gdbarch_data (gdbarch, tdesc_data); + struct tdesc_arch_data *data + = (struct tdesc_arch_data *) gdbarch_data (gdbarch, tdesc_data); data->pseudo_register_reggroup_p = pseudo_reggroup_p; } @@ -1049,7 +1200,7 @@ tdesc_use_registers (struct gdbarch *gdbarch, struct tdesc_arch_data *early_data) { int num_regs = gdbarch_num_regs (gdbarch); - int i, ixf, ixr; + int ixf, ixr; struct tdesc_feature *feature; struct tdesc_reg *reg; struct tdesc_arch_data *data; @@ -1062,7 +1213,7 @@ tdesc_use_registers (struct gdbarch *gdbarch, included. */ gdb_assert (tdesc_has_registers (target_desc)); - data = gdbarch_data (gdbarch, tdesc_data); + data = (struct tdesc_arch_data *) gdbarch_data (gdbarch, tdesc_data); data->arch_regs = early_data->arch_regs; xfree (early_data); @@ -1139,7 +1290,7 @@ tdesc_create_reg (struct tdesc_feature *feature, const char *name, int regnum, int save_restore, const char *group, int bitsize, const char *type) { - struct tdesc_reg *reg = XZALLOC (struct tdesc_reg); + struct tdesc_reg *reg = XCNEW (struct tdesc_reg); reg->name = xstrdup (name); reg->target_regnum = regnum; @@ -1155,13 +1306,20 @@ 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) { - switch (type->kind) { + case TDESC_TYPE_STRUCT: case TDESC_TYPE_UNION: + case TDESC_TYPE_FLAGS: + case TDESC_TYPE_ENUM: { struct tdesc_type_field *f; int ix; @@ -1179,7 +1337,7 @@ tdesc_free_type (struct tdesc_type *type) break; } - xfree (type->name); + xfree ((char *) type->name); xfree (type); } @@ -1187,7 +1345,7 @@ struct tdesc_type * tdesc_create_vector (struct tdesc_feature *feature, const char *name, struct tdesc_type *field_type, int count) { - struct tdesc_type *type = XZALLOC (struct tdesc_type); + struct tdesc_type *type = XCNEW (struct tdesc_type); type->name = xstrdup (name); type->kind = TDESC_TYPE_VECTOR; @@ -1198,10 +1356,34 @@ tdesc_create_vector (struct tdesc_feature *feature, const char *name, return type; } +struct tdesc_type * +tdesc_create_struct (struct tdesc_feature *feature, const char *name) +{ + struct tdesc_type *type = XCNEW (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, int size) +{ + gdb_assert (type->kind == TDESC_TYPE_STRUCT); + gdb_assert (size > 0); + type->u.u.size = size; +} + struct tdesc_type * tdesc_create_union (struct tdesc_feature *feature, const char *name) { - struct tdesc_type *type = XZALLOC (struct tdesc_type); + struct tdesc_type *type = XCNEW (struct tdesc_type); type->name = xstrdup (name); type->kind = TDESC_TYPE_UNION; @@ -1210,20 +1392,135 @@ tdesc_create_union (struct tdesc_feature *feature, const char *name) return type; } +struct tdesc_type * +tdesc_create_flags (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_FLAGS; + type->u.u.size = size; + + VEC_safe_push (tdesc_type_p, feature->types, type); + return type; +} + +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, struct tdesc_type *field_type) { 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.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 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_type; + + gdb_assert (start >= 0 && end >= start); + + if (type->u.u.size > 4) + field_type = tdesc_predefined_type (TDESC_TYPE_UINT64); + else + field_type = tdesc_predefined_type (TDESC_TYPE_UINT32); + + 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_field f = { 0 }; + + 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_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 tdesc_free_feature (struct tdesc_feature *feature) { @@ -1246,7 +1543,7 @@ tdesc_free_feature (struct tdesc_feature *feature) struct tdesc_feature * tdesc_create_feature (struct target_desc *tdesc, const char *name) { - struct tdesc_feature *new_feature = XZALLOC (struct tdesc_feature); + struct tdesc_feature *new_feature = XCNEW (struct tdesc_feature); new_feature->name = xstrdup (name); @@ -1257,13 +1554,13 @@ tdesc_create_feature (struct target_desc *tdesc, const char *name) struct target_desc * allocate_target_description (void) { - return XZALLOC (struct target_desc); + return XCNEW (struct target_desc); } static void free_target_description (void *arg) { - struct target_desc *target_desc = arg; + struct target_desc *target_desc = (struct target_desc *) arg; struct tdesc_feature *feature; struct property *prop; int ix; @@ -1360,7 +1657,7 @@ static struct cmd_list_element *tdesc_unset_cmdlist; static void set_tdesc_cmd (char *args, int from_tty) { - help_list (tdesc_set_cmdlist, "set tdesc ", -1, gdb_stdout); + help_list (tdesc_set_cmdlist, "set tdesc ", all_commands, gdb_stdout); } static void @@ -1372,13 +1669,16 @@ show_tdesc_cmd (char *args, int from_tty) static void unset_tdesc_cmd (char *args, int from_tty) { - help_list (tdesc_unset_cmdlist, "unset tdesc ", -1, gdb_stdout); + help_list (tdesc_unset_cmdlist, "unset tdesc ", all_commands, gdb_stdout); } static void set_tdesc_filename_cmd (char *args, int from_tty, struct cmd_list_element *c) { + xfree (target_description_filename); + target_description_filename = xstrdup (tdesc_filename_cmd_string); + target_clear_description (); target_find_description (); } @@ -1388,13 +1688,14 @@ show_tdesc_filename_cmd (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { + value = target_description_filename; + if (value != NULL && *value != '\0') - printf_filtered (_("\ -The target description will be read from \"%s\".\n"), + printf_filtered (_("The target description will be read from \"%s\".\n"), value); else - printf_filtered (_("\ -The target description will be read from the target.\n")); + printf_filtered (_("The target description will be " + "read from the target.\n")); } static void @@ -1419,6 +1720,7 @@ maint_print_c_tdesc_cmd (char *args, int from_tty) struct tdesc_type *type; struct tdesc_type_field *f; int ix, ix2, ix3; + int printed_field_type = 0; /* Use the global target-supplied description, not the current architecture's. This lets a GDB for one architecture generate C @@ -1432,7 +1734,7 @@ maint_print_c_tdesc_cmd (char *args, int from_tty) error (_("The current target description did not come from an XML file.")); filename = lbasename (target_description_filename); - function = alloca (strlen (filename) + 1); + function = (char *) alloca (strlen (filename) + 1); for (inp = filename, outp = function; *inp != '\0'; inp++) if (*inp == '.') break; @@ -1443,8 +1745,10 @@ maint_print_c_tdesc_cmd (char *args, int from_tty) *outp = '\0'; /* Standard boilerplate. */ - printf_unfiltered ("/* THIS FILE IS GENERATED. Original: %s */\n\n", - filename); + printf_unfiltered ("/* THIS FILE IS GENERATED. " + "-*- buffer-read-only: t -*- vi" + ":set ro:\n"); + printf_unfiltered (" Original: %s */\n\n", filename); printf_unfiltered ("#include \"defs.h\"\n"); printf_unfiltered ("#include \"osabi.h\"\n"); printf_unfiltered ("#include \"target-descriptions.h\"\n"); @@ -1457,7 +1761,42 @@ maint_print_c_tdesc_cmd (char *args, int from_tty) printf_unfiltered (" struct target_desc *result = allocate_target_description ();\n"); printf_unfiltered (" struct tdesc_feature *feature;\n"); - printf_unfiltered (" struct tdesc_type *field_type, *type;\n"); + + /* Now we do some "filtering" in order to know which variables to + declare. This is needed because otherwise we would declare unused + variables `field_type' and `type'. */ + for (ix = 0; + VEC_iterate (tdesc_feature_p, tdesc->features, ix, feature); + ix++) + { + int printed_desc_type = 0; + + for (ix2 = 0; + VEC_iterate (tdesc_type_p, feature->types, ix2, type); + ix2++) + { + if (!printed_field_type) + { + printf_unfiltered (" struct tdesc_type *field_type;\n"); + printed_field_type = 1; + } + + 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; + break; + } + } + + if (printed_desc_type) + break; + } + printf_unfiltered ("\n"); if (tdesc_architecture (tdesc) != NULL) @@ -1498,7 +1837,8 @@ maint_print_c_tdesc_cmd (char *args, int from_tty) VEC_iterate (tdesc_feature_p, tdesc->features, ix, feature); ix++) { - printf_unfiltered (" feature = tdesc_create_feature (result, \"%s\");\n", + printf_unfiltered (" \ +feature = tdesc_create_feature (result, \"%s\");\n", feature->name); for (ix2 = 0; @@ -1515,6 +1855,80 @@ maint_print_c_tdesc_cmd (char *args, int from_tty) (" tdesc_create_vector (feature, \"%s\", field_type, %d);\n", type->name, type->u.v.count); break; + case TDESC_TYPE_STRUCT: + 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++) + { + 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", + type_name); + printf_unfiltered + (" tdesc_add_field (type, \"%s\", field_type);\n", + f->name); + } + } + break; case TDESC_TYPE_UNION: printf_unfiltered (" type = tdesc_create_union (feature, \"%s\");\n", @@ -1531,6 +1945,17 @@ maint_print_c_tdesc_cmd (char *args, int from_tty) f->name); } break; + case TDESC_TYPE_ENUM: + printf_unfiltered + (" type = tdesc_create_enum (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++) + printf_unfiltered + (" tdesc_add_enum_value (type, %d, \"%s\");\n", + f->start, f->name); + break; default: error (_("C output is not supported type \"%s\"."), type->name); } @@ -1579,7 +2004,7 @@ Unset target description specific variables."), 0 /* allow-unknown */, &unsetlist); add_setshow_filename_cmd ("filename", class_obscure, - &target_description_filename, + &tdesc_filename_cmd_string, _("\ Set the file to read for an XML target description"), _("\ Show the file to read for an XML target description"), _("\