X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Ftarget-descriptions.c;h=c1eec14542eb416771768e1e8ab2e312b5521492;hb=727fc41e077139570ea8b8ddfd6c546b2a55627c;hp=6df4547e8bf7d8fa5e8a3ff90ba3015f4170aa26;hpb=f8b73d13b7ca749dee450b60e4e401b4c096bed6;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/target-descriptions.c b/gdb/target-descriptions.c index 6df4547e8b..c1eec14542 100644 --- a/gdb/target-descriptions.c +++ b/gdb/target-descriptions.c @@ -1,6 +1,6 @@ /* Target description support for GDB. - Copyright (C) 2006, 2007 Free Software Foundation, Inc. + Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc. Contributed by CodeSourcery. @@ -8,7 +8,7 @@ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -17,9 +17,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. */ + along with this program. If not, see . */ #include "defs.h" #include "arch-utils.h" @@ -185,7 +183,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 (current_gdbarch) == NULL); + gdb_assert (gdbarch_target_desc (target_gdbarch) == NULL); /* First try to fetch an XML description from the user-specified file. */ @@ -218,7 +216,7 @@ target_find_description (void) { struct tdesc_arch_data *data; - data = gdbarch_data (current_gdbarch, tdesc_data); + data = gdbarch_data (target_gdbarch, tdesc_data); if (tdesc_has_registers (current_target_desc) && data->registers == NULL) warning (_("Target-supplied registers are not supported " @@ -341,6 +339,30 @@ tdesc_feature_name (const struct tdesc_feature *feature) return feature->name; } +/* Predefined types. Note that none of these types depend on the + current architecture; some of the builtin_type_foo variables are + swapped based on the architecture. */ +static struct +{ + const char *name; + struct type **type; +} tdesc_predefined_types[] = + { + { "int8", &builtin_type_int8 }, + { "int16", &builtin_type_int16 }, + { "int32", &builtin_type_int32 }, + { "int64", &builtin_type_int64 }, + { "int128", &builtin_type_int128 }, + { "uint8", &builtin_type_uint8 }, + { "uint16", &builtin_type_uint16 }, + { "uint32", &builtin_type_uint32 }, + { "uint64", &builtin_type_uint64 }, + { "uint128", &builtin_type_uint128 }, + { "ieee_single", &builtin_type_ieee_single }, + { "ieee_double", &builtin_type_ieee_double }, + { "arm_fpa_ext", &builtin_type_arm_ext } + }; + /* Return the type associated with ID in the context of FEATURE, or NULL if none. */ @@ -355,41 +377,10 @@ tdesc_named_type (const struct tdesc_feature *feature, const char *id) if (strcmp (TYPE_NAME (gdb_type), id) == 0) return gdb_type; - /* Next try some predefined types. Note that none of these types - depend on the current architecture; some of the builtin_type_foo - variables are swapped based on the architecture. */ - if (strcmp (id, "int8") == 0) - return builtin_type_int8; - - if (strcmp (id, "int16") == 0) - return builtin_type_int16; - - if (strcmp (id, "int32") == 0) - return builtin_type_int32; - - if (strcmp (id, "int64") == 0) - return builtin_type_int64; - - if (strcmp (id, "uint8") == 0) - return builtin_type_uint8; - - if (strcmp (id, "uint16") == 0) - return builtin_type_uint16; - - if (strcmp (id, "uint32") == 0) - return builtin_type_uint32; - - if (strcmp (id, "uint64") == 0) - return builtin_type_uint64; - - if (strcmp (id, "ieee_single") == 0) - return builtin_type_ieee_single; - - if (strcmp (id, "ieee_double") == 0) - return builtin_type_ieee_double; - - if (strcmp (id, "arm_fpa_ext") == 0) - return builtin_type_arm_ext; + /* Next try the predefined types. */ + for (ix = 0; ix < ARRAY_SIZE (tdesc_predefined_types); ix++) + if (strcmp (tdesc_predefined_types[ix].name, id) == 0) + return *tdesc_predefined_types[ix].type; return NULL; } @@ -432,10 +423,9 @@ tdesc_data_cleanup (void *data_untyped) /* Search FEATURE for a register named NAME. */ -int -tdesc_numbered_register (const struct tdesc_feature *feature, - struct tdesc_arch_data *data, - int regno, const char *name) +static struct tdesc_reg * +tdesc_find_register_early (const struct tdesc_feature *feature, + const char *name) { int ixr; struct tdesc_reg *reg; @@ -444,18 +434,32 @@ tdesc_numbered_register (const struct tdesc_feature *feature, VEC_iterate (tdesc_reg_p, feature->registers, ixr, reg); ixr++) if (strcasecmp (reg->name, name) == 0) - { - /* Make sure the vector includes a REGNO'th element. */ - while (regno >= VEC_length (tdesc_reg_p, data->registers)) - VEC_safe_push (tdesc_reg_p, data->registers, NULL); - VEC_replace (tdesc_reg_p, data->registers, regno, reg); - return 1; - } + return reg; - return 0; + return NULL; +} + +/* Search FEATURE for a register named NAME. Assign REGNO to it. */ + +int +tdesc_numbered_register (const struct tdesc_feature *feature, + struct tdesc_arch_data *data, + int regno, const char *name) +{ + struct tdesc_reg *reg = tdesc_find_register_early (feature, name); + + if (reg == NULL) + return 0; + + /* Make sure the vector includes a REGNO'th element. */ + while (regno >= VEC_length (tdesc_reg_p, data->registers)) + VEC_safe_push (tdesc_reg_p, data->registers, NULL); + VEC_replace (tdesc_reg_p, data->registers, regno, reg); + return 1; } -/* Search FEATURE for a register whose name is in NAMES. */ +/* Search FEATURE for a register whose name is in NAMES and assign + REGNO to it. */ int tdesc_numbered_register_choices (const struct tdesc_feature *feature, @@ -471,6 +475,19 @@ tdesc_numbered_register_choices (const struct tdesc_feature *feature, return 0; } +/* Search FEATURE for a register named NAME, and return its size in + bits. The register must exist. */ + +int +tdesc_register_size (const struct tdesc_feature *feature, + const char *name) +{ + struct tdesc_reg *reg = tdesc_find_register_early (feature, name); + + gdb_assert (reg != NULL); + return reg->bitsize; +} + /* Look up a register by its GDB internal register number. */ static struct tdesc_reg * @@ -490,21 +507,20 @@ tdesc_find_register (struct gdbarch *gdbarch, int regno) from an architecture-provided pseudo_register_name method. */ const char * -tdesc_register_name (int regno) +tdesc_register_name (struct gdbarch *gdbarch, int regno) { - struct tdesc_reg *reg = tdesc_find_register (current_gdbarch, regno); - int num_regs = gdbarch_num_regs (current_gdbarch); - int num_pseudo_regs = gdbarch_num_pseudo_regs (current_gdbarch); + struct tdesc_reg *reg = tdesc_find_register (gdbarch, regno); + int num_regs = gdbarch_num_regs (gdbarch); + int num_pseudo_regs = gdbarch_num_pseudo_regs (gdbarch); if (reg != NULL) return reg->name; if (regno >= num_regs && regno < num_regs + num_pseudo_regs) { - struct tdesc_arch_data *data = gdbarch_data (current_gdbarch, - tdesc_data); + struct tdesc_arch_data *data = gdbarch_data (gdbarch, tdesc_data); gdb_assert (data->pseudo_register_name != NULL); - return data->pseudo_register_name (regno); + return data->pseudo_register_name (gdbarch, regno); } return ""; @@ -536,32 +552,32 @@ tdesc_register_type (struct gdbarch *gdbarch, int regno) if (strcmp (reg->type, "float") == 0) { if (reg->bitsize == gdbarch_float_bit (gdbarch)) - return builtin_type_float; + return builtin_type (gdbarch)->builtin_float; else if (reg->bitsize == gdbarch_double_bit (gdbarch)) - return builtin_type_double; + return builtin_type (gdbarch)->builtin_double; else if (reg->bitsize == gdbarch_long_double_bit (gdbarch)) - return builtin_type_long_double; + return builtin_type (gdbarch)->builtin_long_double; } else if (strcmp (reg->type, "int") == 0) { if (reg->bitsize == gdbarch_long_bit (gdbarch)) - return builtin_type_long; + return builtin_type (gdbarch)->builtin_long; else if (reg->bitsize == TARGET_CHAR_BIT) - return builtin_type_char; + return builtin_type (gdbarch)->builtin_char; else if (reg->bitsize == gdbarch_short_bit (gdbarch)) - return builtin_type_short; + return builtin_type (gdbarch)->builtin_short; else if (reg->bitsize == gdbarch_int_bit (gdbarch)) - return builtin_type_int; + return builtin_type (gdbarch)->builtin_int; else if (reg->bitsize == gdbarch_long_long_bit (gdbarch)) - return builtin_type_long_long; + return builtin_type (gdbarch)->builtin_long_long; else if (reg->bitsize == gdbarch_ptr_bit (gdbarch)) /* A bit desperate by this point... */ - return builtin_type_void_data_ptr; + return builtin_type (gdbarch)->builtin_data_ptr; } else if (strcmp (reg->type, "code_ptr") == 0) - return builtin_type_void_func_ptr; + return builtin_type (gdbarch)->builtin_func_ptr; else if (strcmp (reg->type, "data_ptr") == 0) - return builtin_type_void_data_ptr; + return builtin_type (gdbarch)->builtin_data_ptr; else internal_error (__FILE__, __LINE__, "Register \"%s\" has an unknown type \"%s\"", @@ -569,7 +585,7 @@ tdesc_register_type (struct gdbarch *gdbarch, int regno) warning (_("Register \"%s\" has an unsupported size (%d bits)"), reg->name, reg->bitsize); - return builtin_type_long; + return builtin_type (gdbarch)->builtin_long; } static int @@ -693,18 +709,16 @@ set_tdesc_pseudo_register_reggroup_p void tdesc_use_registers (struct gdbarch *gdbarch, + const struct target_desc *target_desc, struct tdesc_arch_data *early_data) { int num_regs = gdbarch_num_regs (gdbarch); int i, ixf, ixr; - const struct target_desc *target_desc; struct tdesc_feature *feature; struct tdesc_reg *reg; struct tdesc_arch_data *data; htab_t reg_hash; - target_desc = gdbarch_target_desc (gdbarch); - /* We can't use the description for registers if it doesn't describe any. This function should only be called after validating registers, so the caller should know that registers are @@ -792,7 +806,7 @@ tdesc_create_reg (struct tdesc_feature *feature, const char *name, reg->save_restore = save_restore; reg->group = group ? xstrdup (group) : NULL; reg->bitsize = bitsize; - reg->type = type ? xstrdup (type) : NULL; + reg->type = type ? xstrdup (type) : xstrdup (""); /* If the register's type is target-defined, look it up now. We may not have easy access to the containing feature when we want it later. */ @@ -962,6 +976,158 @@ unset_tdesc_filename_cmd (char *args, int from_tty) target_find_description (); } +static const char * +tdesc_type_id (struct type *type) +{ + int ix; + + for (ix = 0; ix < ARRAY_SIZE (tdesc_predefined_types); ix++) + if (TYPE_MAIN_TYPE (*tdesc_predefined_types[ix].type) + == TYPE_MAIN_TYPE (type)) + return tdesc_predefined_types[ix].name; + + return TYPE_NAME (type); +} + +static void +maint_print_c_tdesc_cmd (char *args, int from_tty) +{ + const struct target_desc *tdesc; + const char *filename, *inp; + char *function, *outp; + struct property *prop; + struct tdesc_feature *feature; + struct tdesc_reg *reg; + struct type *type; + int ix, ix2, ix3; + + /* Use the global target-supplied description, not the current + architecture's. This lets a GDB for one architecture generate C + for another architecture's description, even though the gdbarch + initialization code will reject the new description. */ + tdesc = current_target_desc; + if (tdesc == NULL) + error (_("There is no target description to print.")); + + if (target_description_filename == NULL) + error (_("The current target description did not come from an XML file.")); + + filename = lbasename (target_description_filename); + function = alloca (strlen (filename) + 1); + for (inp = filename, outp = function; *inp != '\0'; inp++) + if (*inp == '.') + break; + else if (*inp == '-') + *outp++ = '_'; + else + *outp++ = *inp; + *outp = '\0'; + + /* Standard boilerplate. */ + printf_unfiltered ("/* THIS FILE IS GENERATED. Original: %s */\n\n", + filename); + printf_unfiltered ("#include \"defs.h\"\n"); + printf_unfiltered ("#include \"gdbtypes.h\"\n"); + printf_unfiltered ("#include \"target-descriptions.h\"\n"); + printf_unfiltered ("\n"); + + printf_unfiltered ("struct target_desc *tdesc_%s;\n", function); + printf_unfiltered ("static void\n"); + printf_unfiltered ("initialize_tdesc_%s (void)\n", function); + printf_unfiltered ("{\n"); + printf_unfiltered + (" struct target_desc *result = allocate_target_description ();\n"); + printf_unfiltered (" struct tdesc_feature *feature;\n"); + printf_unfiltered (" struct type *field_type, *type;\n"); + printf_unfiltered ("\n"); + + if (tdesc_architecture (tdesc) != NULL) + { + printf_unfiltered + (" set_tdesc_architecture (result, bfd_scan_arch (\"%s\"));\n", + tdesc_architecture (tdesc)->printable_name); + printf_unfiltered ("\n"); + } + + for (ix = 0; VEC_iterate (property_s, tdesc->properties, ix, prop); + ix++) + { + printf_unfiltered (" set_tdesc_property (result, \"%s\", \"%s\");\n", + prop->key, prop->value); + } + + for (ix = 0; + VEC_iterate (tdesc_feature_p, tdesc->features, ix, feature); + ix++) + { + printf_unfiltered (" feature = tdesc_create_feature (result, \"%s\");\n", + feature->name); + + for (ix2 = 0; + VEC_iterate (type_p, feature->types, ix2, type); + ix2++) + { + switch (TYPE_CODE (type)) + { + case TYPE_CODE_ARRAY: + printf_unfiltered + (" field_type = tdesc_named_type (feature, \"%s\");\n", + tdesc_type_id (TYPE_TARGET_TYPE (type))); + printf_unfiltered + (" type = init_vector_type (field_type, %d);\n", + TYPE_LENGTH (type) / TYPE_LENGTH (TYPE_TARGET_TYPE (type))); + printf_unfiltered + (" TYPE_NAME (type) = xstrdup (\"%s\");\n", TYPE_NAME (type)); + break; + case TYPE_CODE_UNION: + printf_unfiltered + (" type = init_composite_type (NULL, TYPE_CODE_UNION);\n"); + printf_unfiltered + (" TYPE_NAME (type) = xstrdup (\"%s\");\n", TYPE_NAME (type)); + for (ix3 = 0; ix3 < TYPE_NFIELDS (type); ix3++) + { + printf_unfiltered + (" field_type = tdesc_named_type (feature, \"%s\");\n", + tdesc_type_id (TYPE_FIELD_TYPE (type, ix3))); + printf_unfiltered + (" append_composite_type_field (type, " + "xstrdup (\"%s\"), field_type);\n", + TYPE_FIELD_NAME (type, ix3)); + } + if (TYPE_VECTOR (type)) + printf_unfiltered + (" TYPE_VECTOR (type) = 1;\n"); + break; + default: + error (_("C output is not supported type \"%s\"."), TYPE_NAME (type)); + } + printf_unfiltered (" tdesc_record_type (feature, type);\n"); + printf_unfiltered ("\n"); + } + + for (ix2 = 0; + VEC_iterate (tdesc_reg_p, feature->registers, ix2, reg); + ix2++) + { + printf_unfiltered (" tdesc_create_reg (feature, \"%s\", %ld, %d, ", + reg->name, reg->target_regnum, reg->save_restore); + if (reg->group) + printf_unfiltered ("\"%s\", ", reg->group); + else + printf_unfiltered ("NULL, "); + printf_unfiltered ("%d, \"%s\");\n", reg->bitsize, reg->type); + } + + printf_unfiltered ("\n"); + } + + printf_unfiltered (" tdesc_%s = result;\n", function); + printf_unfiltered ("}\n"); +} + +/* Provide a prototype to silence -Wmissing-prototypes. */ +extern initialize_file_ftype _initialize_target_descriptions; + void _initialize_target_descriptions (void) { @@ -995,4 +1161,8 @@ file instead of querying the remote target."), Unset the file to read for an XML target description. When unset,\n\ GDB will read the description from the target."), &tdesc_unset_cmdlist); + + add_cmd ("c-tdesc", class_maintenance, maint_print_c_tdesc_cmd, _("\ +Print the current target description as a C source file."), + &maintenanceprintlist); }