X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Ftarget-descriptions.c;h=16aaa64026bd255d7d7dcd63b3f15daa7738330a;hb=64c311498e46cef6b70aa88577e7d7c382e0f7cc;hp=024257b73400aff3f602fb64bd9a85b27ec69b60;hpb=58d6951de562a3ef2214927006541fc16f0e5bd0;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/target-descriptions.c b/gdb/target-descriptions.c index 024257b734..16aaa64026 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 Free Software Foundation, Inc. + Copyright (C) 2006-2012 Free Software Foundation, Inc. Contributed by CodeSourcery. @@ -29,6 +29,7 @@ #include "vec.h" #include "xml-support.h" #include "xml-tdesc.h" +#include "osabi.h" #include "gdb_assert.h" #include "gdb_obstack.h" @@ -89,9 +90,17 @@ typedef struct tdesc_type_field { char *name; struct tdesc_type *type; + 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); + typedef struct tdesc_type { /* The name of this type. */ @@ -116,10 +125,13 @@ typedef struct tdesc_type 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_UNION + TDESC_TYPE_STRUCT, + TDESC_TYPE_UNION, + TDESC_TYPE_FLAGS } kind; /* Kind-specific data. */ @@ -132,11 +144,19 @@ typedef struct tdesc_type int count; } v; - /* Union type. */ + /* Struct or union type. */ struct { VEC(tdesc_type_field) *fields; + LONGEST size; } u; + + /* Flags type. */ + struct + { + VEC(tdesc_type_flag) *flags; + LONGEST size; + } f; } u; } *tdesc_type_p; DEF_VEC_P(tdesc_type_p); @@ -158,6 +178,10 @@ typedef struct tdesc_feature } *tdesc_feature_p; DEF_VEC_P(tdesc_feature_p); +/* A compatible architecture from a target description. */ +typedef const struct bfd_arch_info *arch_p; +DEF_VEC_P(arch_p); + /* A target description. */ struct target_desc @@ -169,6 +193,9 @@ struct target_desc otherwise. */ enum gdb_osabi osabi; + /* The list of compatible architectures reported by the target. */ + VEC(arch_p) *compatible; + /* Any architecture-specific properties specified by the target. */ VEC(property_s) *properties; @@ -326,6 +353,28 @@ target_current_description (void) return NULL; } + +/* Return non-zero if this target description is compatible + with the given BFD architecture. */ + +int +tdesc_compatible_p (const struct target_desc *target_desc, + const struct bfd_arch_info *arch) +{ + const struct bfd_arch_info *compat; + int ix; + + for (ix = 0; VEC_iterate (arch_p, target_desc->compatible, ix, compat); + ix++) + { + if (compat == arch + || arch->compatible (arch, compat) + || compat->compatible (compat, arch)) + return 1; + } + + return 0; +} /* Direct accessors for target descriptions. */ @@ -431,7 +480,8 @@ static struct tdesc_type tdesc_predefined_types[] = { "data_ptr", TDESC_TYPE_DATA_PTR }, { "ieee_single", TDESC_TYPE_IEEE_SINGLE }, { "ieee_double", TDESC_TYPE_IEEE_DOUBLE }, - { "arm_fpa_ext", TDESC_TYPE_ARM_FPA_EXT } + { "arm_fpa_ext", TDESC_TYPE_ARM_FPA_EXT }, + { "i387_ext", TDESC_TYPE_I387_EXT } }; /* Return the type associated with ID in the context of FEATURE, or @@ -456,12 +506,38 @@ tdesc_named_type (const struct tdesc_feature *feature, const char *id) return NULL; } +/* Lookup type associated with ID. */ + +struct type * +tdesc_find_type (struct gdbarch *gdbarch, const char *id) +{ + struct tdesc_arch_reg *reg; + struct tdesc_arch_data *data; + int i, num_regs; + + data = gdbarch_data (gdbarch, tdesc_data); + num_regs = VEC_length (tdesc_arch_reg, data->arch_regs); + for (i = 0; i < num_regs; i++) + { + reg = VEC_index (tdesc_arch_reg, data->arch_regs, i); + if (reg->reg + && reg->reg->tdesc_type + && reg->type + && strcmp (id, reg->reg->tdesc_type->name) == 0) + return reg->type; + } + + return NULL; +} + /* Construct, if necessary, and return the GDB type implementing target type TDESC_TYPE for architecture GDBARCH. */ static struct type * tdesc_gdb_type (struct gdbarch *gdbarch, struct tdesc_type *tdesc_type) { + struct type *type; + switch (tdesc_type->kind) { /* Predefined types. */ @@ -501,6 +577,16 @@ tdesc_gdb_type (struct gdbarch *gdbarch, struct tdesc_type *tdesc_type) case TDESC_TYPE_DATA_PTR: return builtin_type (gdbarch)->builtin_data_ptr; + default: + break; + } + + type = tdesc_find_type (gdbarch, tdesc_type->name); + if (type) + return type; + + switch (tdesc_type->kind) + { case TDESC_TYPE_IEEE_SINGLE: return arch_float_type (gdbarch, -1, "builtin_type_ieee_single", floatformats_ieee_single); @@ -513,6 +599,10 @@ tdesc_gdb_type (struct gdbarch *gdbarch, struct tdesc_type *tdesc_type) return arch_float_type (gdbarch, -1, "builtin_type_arm_ext", floatformats_arm_ext); + case TDESC_TYPE_I387_EXT: + return arch_float_type (gdbarch, -1, "builtin_type_i387_ext", + floatformats_i387_ext); + /* Types defined by a target feature. */ case TDESC_TYPE_VECTOR: { @@ -525,6 +615,66 @@ tdesc_gdb_type (struct gdbarch *gdbarch, struct tdesc_type *tdesc_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)) + SET_FIELD_BITPOS (fld[0], total_size - f->start - bitsize); + else + SET_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: { struct type *type, *field_type; @@ -541,12 +691,30 @@ 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_flag *f; + int ix; + + type = arch_flags_type (gdbarch, 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 ? f->name : NULL); return type; } @@ -683,7 +851,6 @@ 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); @@ -697,6 +864,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; } @@ -716,6 +884,7 @@ 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); + gdb_assert (data->pseudo_register_name != NULL); return data->pseudo_register_name (gdbarch, regno); } @@ -734,6 +903,7 @@ 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); + gdb_assert (data->pseudo_register_type != NULL); return data->pseudo_register_type (gdbarch, regno); } @@ -777,7 +947,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 { @@ -871,6 +1041,7 @@ 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); + if (data->pseudo_register_reggroup_p != NULL) return data->pseudo_register_reggroup_p (gdbarch, regno, reggroup); /* Otherwise fall through to the default reggroup_p. */ @@ -922,7 +1093,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; @@ -1031,9 +1202,9 @@ tdesc_create_reg (struct tdesc_feature *feature, const char *name, static void tdesc_free_type (struct tdesc_type *type) { - switch (type->kind) { + case TDESC_TYPE_STRUCT: case TDESC_TYPE_UNION: { struct tdesc_type_field *f; @@ -1048,6 +1219,20 @@ 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; } @@ -1071,6 +1256,29 @@ 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 = 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 * tdesc_create_union (struct tdesc_feature *feature, const char *name) { @@ -1083,13 +1291,32 @@ 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, + 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 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; @@ -1097,6 +1324,37 @@ tdesc_add_field (struct tdesc_type *type, const char *field_name, 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 tdesc_free_feature (struct tdesc_feature *feature) { @@ -1156,6 +1414,8 @@ free_target_description (void *arg) } VEC_free (property_s, target_desc->properties); + VEC_free (arch_p, target_desc->compatible); + xfree (target_desc); } @@ -1165,6 +1425,30 @@ make_cleanup_free_target_description (struct target_desc *target_desc) return make_cleanup (free_target_description, target_desc); } +void +tdesc_add_compatible (struct target_desc *target_desc, + const struct bfd_arch_info *compatible) +{ + const struct bfd_arch_info *compat; + int ix; + + /* If this instance of GDB is compiled without BFD support for the + compatible architecture, simply ignore it -- we would not be able + to handle it anyway. */ + if (compatible == NULL) + return; + + for (ix = 0; VEC_iterate (arch_p, target_desc->compatible, ix, compat); + ix++) + if (compat == compatible) + internal_error (__FILE__, __LINE__, + _("Attempted to add duplicate " + "compatible architecture \"%s\""), + compatible->printable_name); + + VEC_safe_push (arch_p, target_desc->compatible, compatible); +} + void set_tdesc_property (struct target_desc *target_desc, const char *key, const char *value) @@ -1236,12 +1520,11 @@ show_tdesc_filename_cmd (struct ui_file *file, int from_tty, const char *value) { 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 @@ -1257,6 +1540,7 @@ static void maint_print_c_tdesc_cmd (char *args, int from_tty) { const struct target_desc *tdesc; + const struct bfd_arch_info *compatible; const char *filename, *inp; char *function, *outp; struct property *prop; @@ -1264,7 +1548,9 @@ 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; /* Use the global target-supplied description, not the current architecture's. This lets a GDB for one architecture generate C @@ -1292,6 +1578,7 @@ maint_print_c_tdesc_cmd (char *args, int from_tty) printf_unfiltered ("/* THIS FILE IS GENERATED. Original: %s */\n\n", filename); printf_unfiltered ("#include \"defs.h\"\n"); + printf_unfiltered ("#include \"osabi.h\"\n"); printf_unfiltered ("#include \"target-descriptions.h\"\n"); printf_unfiltered ("\n"); @@ -1302,7 +1589,39 @@ 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 + && 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) @@ -1313,6 +1632,25 @@ maint_print_c_tdesc_cmd (char *args, int from_tty) printf_unfiltered ("\n"); } + if (tdesc_osabi (tdesc) > GDB_OSABI_UNKNOWN + && tdesc_osabi (tdesc) < GDB_OSABI_INVALID) + { + printf_unfiltered + (" set_tdesc_osabi (result, osabi_from_tdesc_string (\"%s\"));\n", + gdbarch_osabi_name (tdesc_osabi (tdesc))); + printf_unfiltered ("\n"); + } + + for (ix = 0; VEC_iterate (arch_p, tdesc->compatible, ix, compatible); + ix++) + { + printf_unfiltered + (" tdesc_add_compatible (result, bfd_scan_arch (\"%s\"));\n", + compatible->printable_name); + } + if (ix) + printf_unfiltered ("\n"); + for (ix = 0; VEC_iterate (property_s, tdesc->properties, ix, prop); ix++) { @@ -1324,7 +1662,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; @@ -1357,6 +1696,18 @@ maint_print_c_tdesc_cmd (char *args, int from_tty) f->name); } break; + case TDESC_TYPE_FLAGS: + printf_unfiltered + (" field_type = tdesc_create_flags (feature, \"%s\", %d);\n", + type->name, (int) type->u.f.size); + for (ix3 = 0; + VEC_iterate (tdesc_type_flag, type->u.f.flags, ix3, + flag); + ix3++) + printf_unfiltered + (" tdesc_add_flag (field_type, %d, \"%s\");\n", + flag->start, flag->name); + break; default: error (_("C output is not supported type \"%s\"."), type->name); }