From: Thiago Jung Bauermann Date: Mon, 14 Apr 2025 22:40:23 +0000 (-0300) Subject: Beginning of support for target description parameters X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=991fa8fdf4f78f5dd091adab4eb0864fe49ab2d3;p=thirdparty%2Fbinutils-gdb.git Beginning of support for target description parameters With this commit, it's possible to reference to a parameter in a bitsize attribute in a or element. It's not possible yet to declare parameters in a feature, nor to create a a functioning target description with them yet. The parameter is stored in a dynamic_prop and used to define a dynamic range for an array. GDB can't yet resolve the dynamic type. --- diff --git a/gdb/features/gdb-target.dtd b/gdb/features/gdb-target.dtd index 2ecc41eb1fa..f619573f241 100644 --- a/gdb/features/gdb-target.dtd +++ b/gdb/features/gdb-target.dtd @@ -38,7 +38,8 @@ + count CDATA #IMPLIED + bitsize CDATA #IMPLIED> *parameter + = new std::pair; + // FIXME: Is the lifetime of the following strings longer than of this + // object? + parameter->first = parameter_feature; + parameter->second = length_parameter; + high.set_tdesc_parameter (parameter); + + return create_range_type (alloc, index_type, &low, &high, 0); +} + /* Predicate tests whether BOUNDS are static. Returns 1 if all bounds values are static, otherwise returns 0. */ @@ -1410,6 +1436,24 @@ lookup_array_range_type (struct type *element_type, return create_array_type (alloc, element_type, range_type); } +/* Create type for array ranges where the low bound is 0 and the high bound is + calculated from the array length found in the given target description + parameter. */ + +static struct type * +lookup_array_range_type (struct type *element_type, + const char *parameter_feature, + const char *length_parameter) +{ + type_allocator alloc (element_type); + struct type *index_type, *range_type; + + index_type = builtin_type (element_type->arch ())->builtin_unsigned_int; + range_type = create_dynamic_range_type (alloc, index_type, parameter_feature, + length_parameter); + return create_array_type (alloc, element_type, range_type); +} + /* See gdbtypes.h. */ struct type * @@ -1498,6 +1542,20 @@ init_vector_type (struct type *elt_type, int n) return array_type; } +/* Create vector type of elements of type ELT_TYPE, where its total length is + given by the given target description parameter. */ + +struct type * +init_vector_type (struct type *elt_type, const char *parameter_feature, + const char *length_parameter) +{ + struct type *array_type = lookup_array_range_type (elt_type, + parameter_feature, + length_parameter); + make_vector_type (array_type); + return array_type; +} + /* Internal routine called by TYPE_SELF_TYPE to return the type that TYPE belongs to. In c++ this is the class of "this", but TYPE_THIS_TYPE is too confusing. "self" is a common enough replacement for "this". diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index 5ee9deb07ad..98732614d36 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -266,6 +266,7 @@ enum dynamic_prop_kind PROP_TYPE, /* Type. */ PROP_VARIABLE_NAME, /* Variable name. */ PROP_OPTIMIZED_OUT, /* Optimized out. */ + PROP_TDESC_PARAMETER, /* Parameter from target description. */ }; union dynamic_prop_data @@ -297,6 +298,10 @@ union dynamic_prop_data this property. */ const char *variable_name; + + /* The first element is the feature name and the second is the parameter + name. */ + std::pair *tdesc_parameter; }; /* * Used to store a dynamic property. */ @@ -412,6 +417,18 @@ struct dynamic_prop m_data.variable_name = name; } + std::pair tdesc_parameter () const + { + gdb_assert (m_kind == PROP_TDESC_PARAMETER); + return *m_data.tdesc_parameter; + } + + void set_tdesc_parameter (std::pair *parameter) + { + m_kind = PROP_TDESC_PARAMETER; + m_data.tdesc_parameter = parameter; + } + /* Determine which field of the union dynamic_prop.data is used. */ enum dynamic_prop_kind m_kind; @@ -2421,6 +2438,9 @@ extern void append_flags_type_flag (struct type *type, int bitpos, extern void make_vector_type (struct type *array_type); extern struct type *init_vector_type (struct type *elt_type, int n); +extern struct type *init_vector_type (struct type *elt_type, + const char *parameter_feature, + const char *length_parameter); extern struct type *lookup_reference_type (struct type *, enum type_code); extern struct type *lookup_lvalue_reference_type (struct type *); diff --git a/gdb/target-descriptions.c b/gdb/target-descriptions.c index 8042d25d893..aa0017a252f 100644 --- a/gdb/target-descriptions.c +++ b/gdb/target-descriptions.c @@ -160,7 +160,13 @@ make_gdb_type (struct gdbarch *gdbarch, struct tdesc_type *ttype) return; type *element_gdb_type = make_gdb_type (m_gdbarch, e->element_type); - m_type = init_vector_type (element_gdb_type, e->count); + if (e->bitsize_parameter.length () == 0) + m_type = init_vector_type (element_gdb_type, e->count); + else + // FIXME: Is the lifetime of feature and tdesc_parameter correct? + // Probably not. e->name is duplicated below. + m_type = init_vector_type (element_gdb_type, e->feature.c_str (), + e->bitsize_parameter.c_str ()); m_type->set_name (xstrdup (e->name.c_str ())); return; } @@ -1361,9 +1367,14 @@ public: gdb_printf (" element_type = tdesc_named_type (feature, \"%s\");\n", type->element_type->name.c_str ()); - gdb_printf - (" tdesc_create_vector (feature, \"%s\", element_type, %d);\n", - type->name.c_str (), type->count); + if (type->bitsize_parameter.length () != 0) + gdb_printf + (" tdesc_create_vector (feature, \"%s\", element_type, \"%s\");\n", + type->name.c_str (), type->bitsize_parameter.c_str ()); + else + gdb_printf + (" tdesc_create_vector (feature, \"%s\", element_type, %d);\n", + type->name.c_str (), type->count); gdb_printf ("\n"); } @@ -1483,7 +1494,11 @@ public: gdb_printf ("\"%s\", ", reg->group.c_str ()); else gdb_printf ("NULL, "); - gdb_printf ("%d, \"%s\");\n", reg->bitsize, reg->type.c_str ()); + if (reg->bitsize_parameter.length () != 0) + gdb_printf ("\"%s\", \"%s\");\n", reg->bitsize_parameter.c_str (), + reg->type.c_str ()); + else + gdb_printf ("%d, \"%s\");\n", reg->bitsize, reg->type.c_str ()); } protected: @@ -1626,7 +1641,11 @@ public: gdb_printf ("\"%s\", ", reg->group.c_str ()); else gdb_printf ("NULL, "); - gdb_printf ("%d, \"%s\");\n", reg->bitsize, reg->type.c_str ()); + if (reg->bitsize_parameter.length () != 0) + gdb_printf ("\"%s\", \"%s\");\n", reg->bitsize_parameter.c_str (), + reg->type.c_str ()); + else + gdb_printf ("%d, \"%s\");\n", reg->bitsize, reg->type.c_str ()); m_next_regnum++; } diff --git a/gdb/xml-tdesc.c b/gdb/xml-tdesc.c index 6c095afa699..64aef110e7e 100644 --- a/gdb/xml-tdesc.c +++ b/gdb/xml-tdesc.c @@ -176,14 +176,14 @@ tdesc_start_reg (struct gdb_xml_parser *parser, { struct tdesc_parsing_data *data = (struct tdesc_parsing_data *) user_data; int ix = 0; - char *name, *group; + char *name, *group, *bitsize_attr; const char *type; - int bitsize, regnum, save_restore; + int regnum, save_restore; int length = attributes.size (); name = (char *) attributes[ix++].value.get (); - bitsize = * (ULONGEST *) attributes[ix++].value.get (); + bitsize_attr = (char *) attributes[ix++].value.get (); if (ix < length && strcmp (attributes[ix].name, "regnum") == 0) regnum = * (ULONGEST *) attributes[ix++].value.get (); @@ -211,8 +211,19 @@ tdesc_start_reg (struct gdb_xml_parser *parser, gdb_xml_error (parser, _("Register \"%s\" has unknown type \"%s\""), name, type); - tdesc_create_reg (data->current_feature, name, regnum, save_restore, group, - bitsize, type); + if (bitsize_attr[0] == '$') + { + // FIXME: Check whether the bitsize parameter is valid. + tdesc_create_reg (data->current_feature, name, regnum, save_restore, + group, &bitsize_attr[1], type); + } + else + { + int bitsize = (int) gdb_xml_parse_ulongest (parser, bitsize_attr); + + tdesc_create_reg (data->current_feature, name, regnum, save_restore, + group, bitsize, type); + } data->next_regnum = regnum + 1; } @@ -476,25 +487,38 @@ tdesc_start_vector (struct gdb_xml_parser *parser, struct tdesc_parsing_data *data = (struct tdesc_parsing_data *) user_data; struct tdesc_type *field_type; char *id, *field_type_id; - ULONGEST count; id = (char *) attributes[0].value.get (); field_type_id = (char *) attributes[1].value.get (); - count = * (ULONGEST *) attributes[2].value.get (); - - if (count > MAX_VECTOR_SIZE) - { - gdb_xml_error (parser, - _("Vector size %s is larger than maximum (%d)"), - pulongest (count), MAX_VECTOR_SIZE); - } field_type = tdesc_named_type (data->current_feature, field_type_id); if (field_type == NULL) gdb_xml_error (parser, _("Vector \"%s\" references undefined type \"%s\""), id, field_type_id); - tdesc_create_vector (data->current_feature, id, field_type, count); + if (!strcmp (attributes[2].name, "count")) + { + ULONGEST count = * (ULONGEST *) attributes[2].value.get (); + + if (count > MAX_VECTOR_SIZE) + gdb_xml_error (parser, _ ("Vector size %s is larger than maximum (%d)"), + pulongest (count), MAX_VECTOR_SIZE); + + tdesc_create_vector (data->current_feature, id, field_type, count); + } + else if (!strcmp (attributes[2].name, "bitsize")) + { + char *bitsize = (char *) attributes[2].value.get (); + + if (bitsize[0] != '$') + gdb_xml_error (parser, _ ("Vector bitsize \"%s\" isn't a parameter"), + bitsize); + + // FIXME: Check whether the parameter exists. + tdesc_create_vector (data->current_feature, id, field_type, &bitsize[1]); + } + else + gdb_xml_error (parser, _ ("Vector doesn't have count nor size attribute")); } /* The elements and attributes of an XML target description. */ @@ -527,7 +551,7 @@ static const struct gdb_xml_element enum_children[] = { 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 }, + { "bitsize", GDB_XML_AF_NONE, NULL, NULL }, { "regnum", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL }, { "type", GDB_XML_AF_OPTIONAL, NULL, NULL }, { "group", GDB_XML_AF_OPTIONAL, NULL, NULL }, @@ -557,7 +581,8 @@ static const struct gdb_xml_attribute enum_attributes[] = { static const struct gdb_xml_attribute vector_attributes[] = { { "id", GDB_XML_AF_NONE, NULL, NULL }, { "type", GDB_XML_AF_NONE, NULL, NULL }, - { "count", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL }, + { "count", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL }, + { "bitsize", GDB_XML_AF_OPTIONAL, NULL, NULL }, { NULL, GDB_XML_AF_NONE, NULL, NULL } }; diff --git a/gdbsupport/tdesc.cc b/gdbsupport/tdesc.cc index ed92c864732..186354aef85 100644 --- a/gdbsupport/tdesc.cc +++ b/gdbsupport/tdesc.cc @@ -33,6 +33,22 @@ tdesc_reg::tdesc_reg (struct tdesc_feature *feature, const std::string &name_, tdesc_type = tdesc_named_type (feature, type.c_str ()); } +tdesc_reg::tdesc_reg (struct tdesc_feature *feature_, const std::string &name_, + int regnum, int save_restore_, const char *group_, + const std::string &bitsize_parameter_, const char *type_) + : name (name_), target_regnum (regnum), + save_restore (save_restore_), + group (group_ != NULL ? group_ : ""), + bitsize (TDESC_REG_VARIABLE_SIZE), + bitsize_parameter (bitsize_parameter_), + type (type_ != NULL ? type_ : "") +{ + /* 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. */ + tdesc_type = tdesc_named_type (feature_, type.c_str ()); + feature = feature_->name; +} + /* Predefined types. */ static tdesc_type_builtin tdesc_predefined_types[] = { @@ -147,6 +163,19 @@ tdesc_create_reg (struct tdesc_feature *feature, const char *name, /* See gdbsupport/tdesc.h. */ +void +tdesc_create_reg (struct tdesc_feature *feature, const char *name, + int regnum, int save_restore, const char *group, + const char *bitsize_parameter, const char *type) +{ + tdesc_reg *reg = new tdesc_reg (feature, name, regnum, save_restore, + group, bitsize_parameter, type); + + feature->registers.emplace_back (reg); +} + +/* See gdbsupport/tdesc.h. */ + struct tdesc_type * tdesc_create_vector (struct tdesc_feature *feature, const char *name, struct tdesc_type *field_type, int count) @@ -159,6 +188,21 @@ tdesc_create_vector (struct tdesc_feature *feature, const char *name, /* See gdbsupport/tdesc.h. */ +struct tdesc_type * +tdesc_create_vector (struct tdesc_feature *feature, const char *name, + struct tdesc_type *field_type, + const char *bitsize_parameter) +{ + tdesc_type_vector *type = new tdesc_type_vector (name, field_type, + feature->name, + bitsize_parameter); + feature->types.emplace_back (type); + + return type; +} + +/* See gdbsupport/tdesc.h. */ + tdesc_type_with_fields * tdesc_create_struct (struct tdesc_feature *feature, const char *name) { @@ -311,8 +355,12 @@ void print_xml_feature::visit (const tdesc_type_builtin *t) void print_xml_feature::visit (const tdesc_type_vector *t) { - add_line ("", - t->name.c_str (), t->element_type->name.c_str (), t->count); + if (t->bitsize_parameter.length () != 0) + add_line ("", t->name.c_str (), + t->element_type->name.c_str (), t->bitsize_parameter.c_str ()); + else + add_line ("", t->name.c_str (), + t->element_type->name.c_str (), t->count); } void print_xml_feature::visit (const tdesc_type_with_fields *t) @@ -381,10 +429,16 @@ void print_xml_feature::visit (const tdesc_reg *r) { std::string tmp; - string_appendf (tmp, - "name.c_str (), r->bitsize, r->type.c_str (), - r->target_regnum); + if (r->bitsize_parameter.length () != 0) + string_appendf (tmp, + "name.c_str (), r->bitsize_parameter.c_str(), + r->type.c_str (), r->target_regnum); + else + string_appendf (tmp, + "name.c_str (), r->bitsize, r->type.c_str (), + r->target_regnum); if (r->group.length () > 0) string_appendf (tmp, " group=\"%s\"", r->group.c_str ()); diff --git a/gdbsupport/tdesc.h b/gdbsupport/tdesc.h index 6bf66ad3dcd..4ecee683e09 100644 --- a/gdbsupport/tdesc.h +++ b/gdbsupport/tdesc.h @@ -64,6 +64,11 @@ public: virtual void accept (tdesc_element_visitor &v) const = 0; }; +/* Used in vector type element count or register bitsize to indicate that the + corresponding value is derived from a target description parameter. */ + +#define TDESC_REG_VARIABLE_SIZE -1 + /* An individual register from a target description. */ struct tdesc_reg : tdesc_element @@ -72,6 +77,10 @@ struct tdesc_reg : tdesc_element int regnum, int save_restore_, const char *group_, int bitsize_, const char *type_); + tdesc_reg (struct tdesc_feature *feature, const std::string &name_, + int regnum, int save_restore_, const char *group_, + const std::string &bitsize_parameter_, const char *type_); + virtual ~tdesc_reg () = default; DISABLE_COPY_AND_ASSIGN (tdesc_reg); @@ -99,9 +108,12 @@ struct tdesc_reg : tdesc_element strings are ignored (treated as empty). */ std::string group; - /* The size of the register, in bits. */ + /* The size of the register, in bits. + Ignored if BITSIZE_PARAMETER isn't empty. */ int bitsize; + std::string feature, bitsize_parameter; + /* The type of the register. This string corresponds to either a named type from the target description or a predefined type from GDB. */ @@ -236,13 +248,26 @@ struct tdesc_type_vector : tdesc_type element_type (element_type_), count (count_) {} + tdesc_type_vector (const std::string &name, tdesc_type *element_type_, + const std::string &feature_, + const std::string &bitsize_parameter_) + : tdesc_type (name, TDESC_TYPE_VECTOR), element_type (element_type_), + count (TDESC_REG_VARIABLE_SIZE), feature (feature_), + bitsize_parameter (bitsize_parameter_) + {} + void accept (tdesc_element_visitor &v) const override { v.visit (this); } struct tdesc_type *element_type; + + /* Ignored if BITSIZE_PARAMETER isn't empty. */ int count; + + /* Target description parameter providing total vector size. */ + std::string feature, bitsize_parameter; }; /* A named type from a target description. */ @@ -362,6 +387,13 @@ struct tdesc_type *tdesc_create_vector (struct tdesc_feature *feature, struct tdesc_type *field_type, int count); +/* Return the created vector tdesc_type named NAME in FEATURE, + with number of elements derived by the given BITSIZE_PARAMETER. */ +struct tdesc_type *tdesc_create_vector (struct tdesc_feature *feature, + const char *name, + struct tdesc_type *field_type, + const char *bitsize_parameter); + /* Return the created struct tdesc_type named NAME in FEATURE. */ tdesc_type_with_fields *tdesc_create_struct (struct tdesc_feature *feature, const char *name); @@ -417,6 +449,12 @@ void tdesc_create_reg (struct tdesc_feature *feature, const char *name, int regnum, int save_restore, const char *group, int bitsize, const char *type); +/* Create a register in feature FEATURE with size given by + BITSIZE_PARAMETER. */ +void tdesc_create_reg (struct tdesc_feature *feature, const char *name, + int regnum, int save_restore, const char *group, + const char *bitsize_parameter, const char *type); + /* Return the tdesc in string XML format. */ const char *tdesc_get_features_xml (const target_desc *tdesc);