Compare commits

...

8 Commits

Author SHA1 Message Date
Alan Hayward
59c10f023a 8/8: Remove xml files from gdbserver 2018-01-24 12:14:04 +00:00
Alan Hayward
5db4be8573 7/8: Remove xml param 2018-01-24 12:14:04 +00:00
Alan Hayward
9374ab9e85 6/8 Add gdbserver xml prints 2018-01-24 12:14:03 +00:00
Alan Hayward
f736361e6d 5/8 Use tdesc types 2018-01-24 12:14:03 +00:00
Alan Hayward
c0c6b1a936 4/8 tab make_gdb_type 2018-01-24 12:14:03 +00:00
Alan Hayward
707bac6b4c 3/8 Use tdesc_feature 2018-01-24 12:14:02 +00:00
Alan Hayward
fff179643e [2/8] use reg_tdesc 2018-01-24 12:13:57 +00:00
Alan Hayward
75b9525ee2 [1/8] move gdbserver tdesc func to C file 2018-01-24 12:13:50 +00:00
32 changed files with 1136 additions and 932 deletions

View File

@@ -912,6 +912,7 @@ COMMON_SFILES = \
agent.c \
annotate.c \
arch-utils.c \
arch/tdesc.c \
auto-load.c \
auxv.c \
ax-gdb.c \

425
gdb/arch/tdesc.c Normal file
View File

@@ -0,0 +1,425 @@
/* Target description support for GDB.
Copyright (C) 2017 Free Software Foundation, Inc.
This file is part of GDB.
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 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
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, see <http://www.gnu.org/licenses/>. */
#ifdef GDBSERVER
#include "server.h"
#else
#include "defs.h"
#endif
#include "tdesc.h"
tdesc_reg::tdesc_reg (struct tdesc_feature *feature, const std::string &name_,
int regnum, int save_restore_, const char *group_,
int bitsize_, const char *type_)
: name (name_), target_regnum (regnum),
save_restore (save_restore_),
group (group_ != NULL ? group_ : ""),
bitsize (bitsize_),
type (type_ != NULL ? type_ : "<unknown>")
{
/* 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 ());
}
/* Predefined types. */
static tdesc_type_builtin tdesc_predefined_types[] =
{
{ "bool", TDESC_TYPE_BOOL },
{ "int8", TDESC_TYPE_INT8 },
{ "int16", TDESC_TYPE_INT16 },
{ "int32", TDESC_TYPE_INT32 },
{ "int64", TDESC_TYPE_INT64 },
{ "int128", TDESC_TYPE_INT128 },
{ "uint8", TDESC_TYPE_UINT8 },
{ "uint16", TDESC_TYPE_UINT16 },
{ "uint32", TDESC_TYPE_UINT32 },
{ "uint64", TDESC_TYPE_UINT64 },
{ "uint128", TDESC_TYPE_UINT128 },
{ "code_ptr", TDESC_TYPE_CODE_PTR },
{ "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 },
{ "i387_ext", TDESC_TYPE_I387_EXT }
};
void tdesc_feature::accept (tdesc_element_visitor &v) const
{
v.visit_pre (this);
for (const tdesc_type_up &type : types)
type->accept (v);
for (const tdesc_reg_up &reg : registers)
reg->accept (v);
v.visit_post (this);
}
bool tdesc_feature::operator== (const tdesc_feature &other) const
{
if (name != other.name)
return false;
if (registers.size () != other.registers.size ())
return false;
for (int ix = 0; ix < registers.size (); ix++)
{
const tdesc_reg_up &reg1 = registers[ix];
const tdesc_reg_up &reg2 = other.registers[ix];
if (reg1 != reg2 && *reg1 != *reg2)
return false;
}
if (types.size () != other.types.size ())
return false;
for (int ix = 0; ix < types.size (); ix++)
{
const tdesc_type_up &type1 = types[ix];
const tdesc_type_up &type2 = other.types[ix];
if (type1 != type2 && *type1 != *type2)
return false;
}
return true;
}
/* Lookup a predefined type. */
static struct tdesc_type *
tdesc_predefined_type (enum tdesc_type_kind kind)
{
for (int 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");
}
/* See arch/tdesc.h. */
struct tdesc_type *
tdesc_named_type (const struct tdesc_feature *feature, const char *id)
{
/* First try target-defined types. */
for (const tdesc_type_up &type : feature->types)
if (type->name == id)
return type.get ();
/* Next try the predefined types. */
for (int ix = 0; ix < ARRAY_SIZE (tdesc_predefined_types); ix++)
if (tdesc_predefined_types[ix].name == id)
return &tdesc_predefined_types[ix];
return NULL;
}
/* See arch/tdesc.h. */
void
tdesc_create_reg (struct tdesc_feature *feature, const char *name,
int regnum, int save_restore, const char *group,
int bitsize, const char *type)
{
tdesc_reg *reg = new tdesc_reg (feature, name, regnum, save_restore,
group, bitsize, type);
feature->registers.emplace_back (reg);
}
/* See arch/tdesc.h. */
struct tdesc_type *
tdesc_create_vector (struct tdesc_feature *feature, const char *name,
struct tdesc_type *field_type, int count)
{
tdesc_type_vector *type = new tdesc_type_vector (name, field_type, count);
feature->types.emplace_back (type);
return type;
}
/* See arch/tdesc.h. */
tdesc_type_with_fields *
tdesc_create_struct (struct tdesc_feature *feature, const char *name)
{
tdesc_type_with_fields *type
= new tdesc_type_with_fields (name, TDESC_TYPE_STRUCT);
feature->types.emplace_back (type);
return type;
}
/* See arch/tdesc.h. */
void
tdesc_set_struct_size (tdesc_type_with_fields *type, int size)
{
gdb_assert (type->kind == TDESC_TYPE_STRUCT);
gdb_assert (size > 0);
type->size = size;
}
/* See arch/tdesc.h. */
tdesc_type_with_fields *
tdesc_create_union (struct tdesc_feature *feature, const char *name)
{
tdesc_type_with_fields *type
= new tdesc_type_with_fields (name, TDESC_TYPE_UNION);
feature->types.emplace_back (type);
return type;
}
/* See arch/tdesc.h. */
tdesc_type_with_fields *
tdesc_create_flags (struct tdesc_feature *feature, const char *name,
int size)
{
gdb_assert (size > 0);
tdesc_type_with_fields *type
= new tdesc_type_with_fields (name, TDESC_TYPE_FLAGS, size);
feature->types.emplace_back (type);
return type;
}
tdesc_type_with_fields *
tdesc_create_enum (struct tdesc_feature *feature, const char *name,
int size)
{
gdb_assert (size > 0);
tdesc_type_with_fields *type
= new tdesc_type_with_fields (name, TDESC_TYPE_ENUM, size);
feature->types.emplace_back (type);
return type;
}
/* See arch/tdesc.h. */
void
tdesc_add_field (tdesc_type_with_fields *type, const char *field_name,
struct tdesc_type *field_type)
{
gdb_assert (type->kind == TDESC_TYPE_UNION
|| type->kind == TDESC_TYPE_STRUCT);
/* Initialize start and end so we know this is not a bit-field
when we print-c-tdesc. */
type->fields.emplace_back (field_name, field_type, -1, -1);
}
void
tdesc_add_typed_bitfield (tdesc_type_with_fields *type, const char *field_name,
int start, int end, struct tdesc_type *field_type)
{
gdb_assert (type->kind == TDESC_TYPE_STRUCT
|| type->kind == TDESC_TYPE_FLAGS);
gdb_assert (start >= 0 && end >= start);
type->fields.emplace_back (field_name, field_type, start, end);
}
/* See arch/tdesc.h. */
void
tdesc_add_bitfield (tdesc_type_with_fields *type, const char *field_name,
int start, int end)
{
struct tdesc_type *field_type;
gdb_assert (start >= 0 && end >= start);
if (type->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);
}
/* See arch/tdesc.h. */
void
tdesc_add_flag (tdesc_type_with_fields *type, int start,
const char *flag_name)
{
gdb_assert (type->kind == TDESC_TYPE_FLAGS
|| type->kind == TDESC_TYPE_STRUCT);
type->fields.emplace_back (flag_name,
tdesc_predefined_type (TDESC_TYPE_BOOL),
start, start);
}
void
tdesc_add_enum_value (tdesc_type_with_fields *type, int value,
const char *name)
{
gdb_assert (type->kind == TDESC_TYPE_ENUM);
type->fields.emplace_back (name,
tdesc_predefined_type (TDESC_TYPE_INT32),
value, -1);
}
void print_xml_feature::visit_post (const target_desc *e)
{
*m_buffer += "</target>\n";
}
void print_xml_feature::visit_pre (const tdesc_feature *e)
{
*m_buffer += "<feature name=\"";
*m_buffer += e->name;
*m_buffer += "\">\n";
}
void print_xml_feature::visit_post (const tdesc_feature *e)
{
*m_buffer += "</feature>\n";
}
void print_xml_feature::visit (const tdesc_type_builtin *type)
{
error (_("xml output is not supported type \"%s\"."), type->name.c_str ());
}
void print_xml_feature::visit (const tdesc_type_vector *type)
{
*m_buffer += "<vector id=\"";
*m_buffer += type->name;
*m_buffer += "\" type=\"";
*m_buffer += type->element_type->name;
*m_buffer += "\" count=\"";
*m_buffer += std::to_string (type->count);
*m_buffer += "\"/>\n";
}
void print_xml_feature::visit (const tdesc_type_with_fields *type)
{
struct tdesc_type_field *f;
const static char *types[] = { "struct", "union", "flags", "enum" };
gdb_assert (type->kind >= TDESC_TYPE_STRUCT && type->kind <= TDESC_TYPE_ENUM);
*m_buffer += "<";
*m_buffer += types[type->kind - TDESC_TYPE_STRUCT];
switch (type->kind)
{
case TDESC_TYPE_STRUCT:
case TDESC_TYPE_FLAGS:
*m_buffer += " id=\"";
*m_buffer += type->name;
if (type->size > 0)
{
*m_buffer += "\" size=\"";
*m_buffer += std::to_string (type->size);
}
*m_buffer += "\">\n";
for (const tdesc_type_field &f : type->fields)
{
*m_buffer += " <field name=\"";
*m_buffer += f.name;
if (f.start == -1)
{
*m_buffer += "\" type=\"";
*m_buffer += f.type->name;
}
else
{
*m_buffer += "\" start=\"";
*m_buffer += std::to_string (f.start);
*m_buffer += "\" end=\"";
*m_buffer += std::to_string (f.end);
}
*m_buffer += "\"/>\n";
}
break;
case TDESC_TYPE_ENUM:
*m_buffer += " id=\"";
*m_buffer += type->name;
*m_buffer += "\">\n";
for (const tdesc_type_field &f : type->fields)
{
*m_buffer += " <field name=\"";
*m_buffer += f.name;
*m_buffer += "\" start=\"";
*m_buffer += std::to_string (f.start);
*m_buffer += "\"/>\n";
}
break;
case TDESC_TYPE_UNION:
*m_buffer += " id=\"";
*m_buffer += type->name;
*m_buffer += "\">\n";
for (const tdesc_type_field &f : type->fields)
{
*m_buffer += " <field name=\"";
*m_buffer += f.name;
*m_buffer += "\" type=\"";
*m_buffer += f.type->name;
*m_buffer += "\"/>\n";
}
break;
default:
error (_("xml output is not supported type \"%s\"."),
type->name.c_str ());
}
*m_buffer += "</";
*m_buffer += types[type->kind - TDESC_TYPE_STRUCT];
*m_buffer += ">\n";
}
void print_xml_feature::visit (const tdesc_reg *reg)
{
*m_buffer += "<reg name=\"";
*m_buffer += reg->name;
*m_buffer += "\" bitsize=\"";
*m_buffer += std::to_string (reg->bitsize);
*m_buffer += "\" type=\"";
*m_buffer += reg->type;
*m_buffer += "\" regnum=\"";
*m_buffer += std::to_string (reg->target_regnum);
if (reg->group.length () > 0)
{
*m_buffer += "\" group=\"";
*m_buffer += reg->group;
}
*m_buffer += "\"/>\n";
}

View File

@@ -18,6 +18,12 @@
#ifndef ARCH_TDESC_H
#define ARCH_TDESC_H 1
#ifdef GDBSERVER
#include "server.h"
#else
#include "defs.h"
#endif
struct tdesc_feature;
struct tdesc_type;
struct tdesc_type_builtin;
@@ -25,6 +31,274 @@ struct tdesc_type_vector;
struct tdesc_type_with_fields;
struct tdesc_reg;
struct target_desc;
struct type;
/* The interface to visit different elements of target description. */
class tdesc_element_visitor
{
public:
virtual void visit_pre (const target_desc *e) = 0;
virtual void visit_post (const target_desc *e) = 0;
virtual void visit_pre (const tdesc_feature *e) = 0;
virtual void visit_post (const tdesc_feature *e) = 0;
virtual void visit (const tdesc_type_builtin *e) = 0;
virtual void visit (const tdesc_type_vector *e) = 0;
virtual void visit (const tdesc_type_with_fields *e) = 0;
virtual void visit (const tdesc_reg *e) = 0;
};
class tdesc_element
{
public:
virtual void accept (tdesc_element_visitor &v) const = 0;
};
/* An individual register from a target description. */
struct tdesc_reg : tdesc_element
{
tdesc_reg (struct tdesc_feature *feature, const std::string &name_,
int regnum, int save_restore_, const char *group_,
int bitsize_, const char *type_);
virtual ~tdesc_reg () = default;
DISABLE_COPY_AND_ASSIGN (tdesc_reg);
/* The name of this register. In standard features, it may be
recognized by the architecture support code, or it may be purely
for the user. */
std::string name;
/* The register number used by this target to refer to this
register. This is used for remote p/P packets and to determine
the ordering of registers in the remote g/G packets. */
long target_regnum;
/* If this flag is set, GDB should save and restore this register
around calls to an inferior function. */
int save_restore;
/* The name of the register group containing this register, or empty
if the group should be automatically determined from the
register's type. If this is "general", "float", or "vector", the
corresponding "info" command should display this register's
value. It can be an arbitrary string, but should be limited to
alphanumeric characters and internal hyphens. Currently other
strings are ignored (treated as empty). */
std::string group;
/* The size of the register, in bits. */
int bitsize;
/* The type of the register. This string corresponds to either
a named type from the target description or a predefined
type from GDB. */
std::string type;
/* The target-described type corresponding to TYPE, if found. */
struct tdesc_type *tdesc_type;
void accept (tdesc_element_visitor &v) const override
{
v.visit (this);
}
bool operator== (const tdesc_reg &other) const
{
return (name == other.name
&& target_regnum == other.target_regnum
&& save_restore == other.save_restore
&& bitsize == other.bitsize
&& group == other.group
&& type == other.type);
}
bool operator!= (const tdesc_reg &other) const
{
return !(*this == other);
}
};
typedef std::unique_ptr<tdesc_reg> tdesc_reg_up;
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
};
struct tdesc_type : tdesc_element
{
tdesc_type (const std::string &name_, enum tdesc_type_kind kind_)
: name (name_), kind (kind_)
{}
virtual ~tdesc_type () = default;
DISABLE_COPY_AND_ASSIGN (tdesc_type);
/* The name of this type. */
std::string name;
/* Identify the kind of this type. */
enum tdesc_type_kind kind;
bool operator== (const tdesc_type &other) const
{
return name == other.name && kind == other.kind;
}
bool operator!= (const tdesc_type &other) const
{
return !(*this == other);
}
/* Construct, if necessary, and return the GDB type implementing this
target type for architecture GDBARCH. */
virtual type *make_gdb_type (struct gdbarch *gdbarch) const = 0;
};
typedef std::unique_ptr<tdesc_type> tdesc_type_up;
struct tdesc_type_builtin : tdesc_type
{
tdesc_type_builtin (const std::string &name, enum tdesc_type_kind kind)
: tdesc_type (name, kind)
{}
void accept (tdesc_element_visitor &v) const override
{
v.visit (this);
}
type *make_gdb_type (struct gdbarch *gdbarch) const override;
};
/* tdesc_type for vector types. */
struct tdesc_type_vector : tdesc_type
{
tdesc_type_vector (const std::string &name, tdesc_type *element_type_,
int count_)
: tdesc_type (name, TDESC_TYPE_VECTOR),
element_type (element_type_), count (count_)
{}
void accept (tdesc_element_visitor &v) const override
{
v.visit (this);
}
type *make_gdb_type (struct gdbarch *gdbarch) const override;
struct tdesc_type *element_type;
int count;
};
/* A named type from a target description. */
struct tdesc_type_field
{
tdesc_type_field (const std::string &name_, tdesc_type *type_,
int start_, int end_)
: name (name_), type (type_), start (start_), end (end_)
{}
std::string 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 for struct, union, flags, and enum types. */
struct tdesc_type_with_fields : tdesc_type
{
tdesc_type_with_fields (const std::string &name, tdesc_type_kind kind,
int size_ = 0)
: tdesc_type (name, kind), size (size_)
{}
void accept (tdesc_element_visitor &v) const override
{
v.visit (this);
}
type *make_gdb_type_struct (struct gdbarch *gdbarch) const;
type *make_gdb_type_union (struct gdbarch *gdbarch) const;
type *make_gdb_type_flags (struct gdbarch *gdbarch) const;
type *make_gdb_type_enum (struct gdbarch *gdbarch) const;
type *make_gdb_type (struct gdbarch *gdbarch) const override;
std::vector<tdesc_type_field> fields;
int size;
};
/* A feature from a target description. Each feature is a collection
of other elements, e.g. registers and types. */
struct tdesc_feature : tdesc_element
{
tdesc_feature (const std::string &name_)
: name (name_)
{}
virtual ~tdesc_feature () = default;
DISABLE_COPY_AND_ASSIGN (tdesc_feature);
/* The name of this feature. It may be recognized by the architecture
support code. */
std::string name;
/* The registers associated with this feature. */
std::vector<tdesc_reg_up> registers;
/* The types associated with this feature. */
std::vector<tdesc_type_up> types;
void accept (tdesc_element_visitor &v) const override;
bool operator== (const tdesc_feature &other) const;
bool operator!= (const tdesc_feature &other) const
{
return !(*this == other);
}
};
typedef std::unique_ptr<tdesc_feature> tdesc_feature_up;
/* Allocate a new target_desc. */
target_desc *allocate_target_description (void);
@@ -43,9 +317,7 @@ struct tdesc_type *tdesc_named_type (const struct tdesc_feature *feature,
/* Return the created feature named NAME in target description TDESC. */
struct tdesc_feature *tdesc_create_feature (struct target_desc *tdesc,
const char *name,
const char *xml = nullptr);
const char *name);
/* Return the created vector tdesc_type named NAME in FEATURE. */
struct tdesc_type *tdesc_create_vector (struct tdesc_feature *feature,
@@ -92,4 +364,33 @@ void tdesc_create_reg (struct tdesc_feature *feature, const char *name,
int regnum, int save_restore, const char *group,
int bitsize, const char *type);
/* Return the tdesc in string XML format. */
const char *tdesc_get_features_xml (target_desc *tdesc);
/* Print target description as xml. */
class print_xml_feature : public tdesc_element_visitor
{
public:
print_xml_feature (std::string *buffer_)
: m_buffer (buffer_)
{}
~print_xml_feature ()
{}
void visit_pre (const target_desc *e) override;
void visit_post (const target_desc *e) override;
void visit_pre (const tdesc_feature *e) override;
void visit_post (const tdesc_feature *e) override;
void visit (const tdesc_type_builtin *type) override;
void visit (const tdesc_type_vector *type) override;
void visit (const tdesc_type_with_fields *type) override;
void visit (const tdesc_reg *reg) override;
private:
std::string *m_buffer;
};
#endif /* ARCH_TDESC_H */

View File

@@ -8,7 +8,7 @@ create_feature_aarch64_core (struct target_desc *result, long regnum)
{
struct tdesc_feature *feature;
feature = tdesc_create_feature (result, "org.gnu.gdb.aarch64.core", "aarch64-core.xml");
feature = tdesc_create_feature (result, "org.gnu.gdb.aarch64.core");
tdesc_type_with_fields *type_with_fields;
type_with_fields = tdesc_create_flags (feature, "cpsr_flags", 4);
tdesc_add_flag (type_with_fields, 0, "SP");

View File

@@ -8,7 +8,7 @@ create_feature_aarch64_fpu (struct target_desc *result, long regnum)
{
struct tdesc_feature *feature;
feature = tdesc_create_feature (result, "org.gnu.gdb.aarch64.fpu", "aarch64-fpu.xml");
feature = tdesc_create_feature (result, "org.gnu.gdb.aarch64.fpu");
tdesc_type *element_type;
element_type = tdesc_named_type (feature, "ieee_double");
tdesc_create_vector (feature, "v2d", element_type, 2);

View File

@@ -8,7 +8,7 @@ create_feature_i386_32bit_avx (struct target_desc *result, long regnum)
{
struct tdesc_feature *feature;
feature = tdesc_create_feature (result, "org.gnu.gdb.i386.avx", "32bit-avx.xml");
feature = tdesc_create_feature (result, "org.gnu.gdb.i386.avx");
tdesc_create_reg (feature, "ymm0h", regnum++, 1, NULL, 128, "uint128");
tdesc_create_reg (feature, "ymm1h", regnum++, 1, NULL, 128, "uint128");
tdesc_create_reg (feature, "ymm2h", regnum++, 1, NULL, 128, "uint128");

View File

@@ -8,7 +8,7 @@ create_feature_i386_32bit_avx512 (struct target_desc *result, long regnum)
{
struct tdesc_feature *feature;
feature = tdesc_create_feature (result, "org.gnu.gdb.i386.avx512", "32bit-avx512.xml");
feature = tdesc_create_feature (result, "org.gnu.gdb.i386.avx512");
tdesc_type *element_type;
element_type = tdesc_named_type (feature, "uint128");
tdesc_create_vector (feature, "v2ui128", element_type, 2);

View File

@@ -8,7 +8,7 @@ create_feature_i386_32bit_core (struct target_desc *result, long regnum)
{
struct tdesc_feature *feature;
feature = tdesc_create_feature (result, "org.gnu.gdb.i386.core", "32bit-core.xml");
feature = tdesc_create_feature (result, "org.gnu.gdb.i386.core");
tdesc_type_with_fields *type_with_fields;
type_with_fields = tdesc_create_flags (feature, "i386_eflags", 4);
tdesc_add_flag (type_with_fields, 0, "CF");

View File

@@ -8,7 +8,7 @@ create_feature_i386_32bit_linux (struct target_desc *result, long regnum)
{
struct tdesc_feature *feature;
feature = tdesc_create_feature (result, "org.gnu.gdb.i386.linux", "32bit-linux.xml");
feature = tdesc_create_feature (result, "org.gnu.gdb.i386.linux");
regnum = 41;
tdesc_create_reg (feature, "orig_eax", regnum++, 1, NULL, 32, "int");
return regnum;

View File

@@ -8,7 +8,7 @@ create_feature_i386_32bit_mpx (struct target_desc *result, long regnum)
{
struct tdesc_feature *feature;
feature = tdesc_create_feature (result, "org.gnu.gdb.i386.mpx", "32bit-mpx.xml");
feature = tdesc_create_feature (result, "org.gnu.gdb.i386.mpx");
tdesc_type_with_fields *type_with_fields;
type_with_fields = tdesc_create_struct (feature, "br128");
tdesc_type *field_type;

View File

@@ -8,7 +8,7 @@ create_feature_i386_32bit_pkeys (struct target_desc *result, long regnum)
{
struct tdesc_feature *feature;
feature = tdesc_create_feature (result, "org.gnu.gdb.i386.pkeys", "32bit-pkeys.xml");
feature = tdesc_create_feature (result, "org.gnu.gdb.i386.pkeys");
tdesc_create_reg (feature, "pkru", regnum++, 1, NULL, 32, "uint32");
return regnum;
}

View File

@@ -8,7 +8,7 @@ create_feature_i386_32bit_sse (struct target_desc *result, long regnum)
{
struct tdesc_feature *feature;
feature = tdesc_create_feature (result, "org.gnu.gdb.i386.sse", "32bit-sse.xml");
feature = tdesc_create_feature (result, "org.gnu.gdb.i386.sse");
tdesc_type *element_type;
element_type = tdesc_named_type (feature, "ieee_single");
tdesc_create_vector (feature, "v4f", element_type, 4);

View File

@@ -8,7 +8,7 @@ create_feature_i386_64bit_avx (struct target_desc *result, long regnum)
{
struct tdesc_feature *feature;
feature = tdesc_create_feature (result, "org.gnu.gdb.i386.avx", "64bit-avx.xml");
feature = tdesc_create_feature (result, "org.gnu.gdb.i386.avx");
tdesc_create_reg (feature, "ymm0h", regnum++, 1, NULL, 128, "uint128");
tdesc_create_reg (feature, "ymm1h", regnum++, 1, NULL, 128, "uint128");
tdesc_create_reg (feature, "ymm2h", regnum++, 1, NULL, 128, "uint128");

View File

@@ -8,7 +8,7 @@ create_feature_i386_64bit_avx512 (struct target_desc *result, long regnum)
{
struct tdesc_feature *feature;
feature = tdesc_create_feature (result, "org.gnu.gdb.i386.avx512", "64bit-avx512.xml");
feature = tdesc_create_feature (result, "org.gnu.gdb.i386.avx512");
tdesc_type *element_type;
element_type = tdesc_named_type (feature, "ieee_single");
tdesc_create_vector (feature, "v4f", element_type, 4);

View File

@@ -8,7 +8,7 @@ create_feature_i386_64bit_core (struct target_desc *result, long regnum)
{
struct tdesc_feature *feature;
feature = tdesc_create_feature (result, "org.gnu.gdb.i386.core", "64bit-core.xml");
feature = tdesc_create_feature (result, "org.gnu.gdb.i386.core");
tdesc_type_with_fields *type_with_fields;
type_with_fields = tdesc_create_flags (feature, "i386_eflags", 4);
tdesc_add_flag (type_with_fields, 0, "CF");

View File

@@ -8,7 +8,7 @@ create_feature_i386_64bit_linux (struct target_desc *result, long regnum)
{
struct tdesc_feature *feature;
feature = tdesc_create_feature (result, "org.gnu.gdb.i386.linux", "64bit-linux.xml");
feature = tdesc_create_feature (result, "org.gnu.gdb.i386.linux");
regnum = 57;
tdesc_create_reg (feature, "orig_rax", regnum++, 1, NULL, 64, "int");
return regnum;

View File

@@ -8,7 +8,7 @@ create_feature_i386_64bit_mpx (struct target_desc *result, long regnum)
{
struct tdesc_feature *feature;
feature = tdesc_create_feature (result, "org.gnu.gdb.i386.mpx", "64bit-mpx.xml");
feature = tdesc_create_feature (result, "org.gnu.gdb.i386.mpx");
tdesc_type_with_fields *type_with_fields;
type_with_fields = tdesc_create_struct (feature, "br128");
tdesc_type *field_type;

View File

@@ -8,7 +8,7 @@ create_feature_i386_64bit_pkeys (struct target_desc *result, long regnum)
{
struct tdesc_feature *feature;
feature = tdesc_create_feature (result, "org.gnu.gdb.i386.pkeys", "64bit-pkeys.xml");
feature = tdesc_create_feature (result, "org.gnu.gdb.i386.pkeys");
tdesc_create_reg (feature, "pkru", regnum++, 1, NULL, 32, "uint32");
return regnum;
}

View File

@@ -8,7 +8,7 @@ create_feature_i386_64bit_segments (struct target_desc *result, long regnum)
{
struct tdesc_feature *feature;
feature = tdesc_create_feature (result, "org.gnu.gdb.i386.segments", "64bit-segments.xml");
feature = tdesc_create_feature (result, "org.gnu.gdb.i386.segments");
tdesc_create_reg (feature, "fs_base", regnum++, 1, NULL, 64, "int");
tdesc_create_reg (feature, "gs_base", regnum++, 1, NULL, 64, "int");
return regnum;

View File

@@ -8,7 +8,7 @@ create_feature_i386_64bit_sse (struct target_desc *result, long regnum)
{
struct tdesc_feature *feature;
feature = tdesc_create_feature (result, "org.gnu.gdb.i386.sse", "64bit-sse.xml");
feature = tdesc_create_feature (result, "org.gnu.gdb.i386.sse");
tdesc_type *element_type;
element_type = tdesc_named_type (feature, "ieee_single");
tdesc_create_vector (feature, "v4f", element_type, 4);

View File

@@ -8,7 +8,7 @@ create_feature_i386_x32_core (struct target_desc *result, long regnum)
{
struct tdesc_feature *feature;
feature = tdesc_create_feature (result, "org.gnu.gdb.i386.core", "x32-core.xml");
feature = tdesc_create_feature (result, "org.gnu.gdb.i386.core");
tdesc_type_with_fields *type_with_fields;
type_with_fields = tdesc_create_flags (feature, "i386_eflags", 4);
tdesc_add_flag (type_with_fields, 0, "CF");

View File

@@ -8,7 +8,7 @@ create_feature_tic6x_c6xp (struct target_desc *result, long regnum)
{
struct tdesc_feature *feature;
feature = tdesc_create_feature (result, "org.gnu.gdb.tic6x.c6xp", "tic6x-c6xp.xml");
feature = tdesc_create_feature (result, "org.gnu.gdb.tic6x.c6xp");
tdesc_create_reg (feature, "TSR", regnum++, 1, NULL, 32, "uint32");
tdesc_create_reg (feature, "ILC", regnum++, 1, NULL, 32, "uint32");
tdesc_create_reg (feature, "RILC", regnum++, 1, NULL, 32, "uint32");

View File

@@ -8,7 +8,7 @@ create_feature_tic6x_core (struct target_desc *result, long regnum)
{
struct tdesc_feature *feature;
feature = tdesc_create_feature (result, "org.gnu.gdb.tic6x.core", "tic6x-core.xml");
feature = tdesc_create_feature (result, "org.gnu.gdb.tic6x.core");
tdesc_create_reg (feature, "A0", regnum++, 1, NULL, 32, "uint32");
tdesc_create_reg (feature, "A1", regnum++, 1, NULL, 32, "uint32");
tdesc_create_reg (feature, "A2", regnum++, 1, NULL, 32, "uint32");

View File

@@ -8,7 +8,7 @@ create_feature_tic6x_gp (struct target_desc *result, long regnum)
{
struct tdesc_feature *feature;
feature = tdesc_create_feature (result, "org.gnu.gdb.tic6x.gp", "tic6x-gp.xml");
feature = tdesc_create_feature (result, "org.gnu.gdb.tic6x.gp");
tdesc_create_reg (feature, "A16", regnum++, 1, NULL, 32, "uint32");
tdesc_create_reg (feature, "A17", regnum++, 1, NULL, 32, "uint32");
tdesc_create_reg (feature, "A18", regnum++, 1, NULL, 32, "uint32");

View File

@@ -194,6 +194,7 @@ SFILES = \
$(srcdir)/arch/arm.c \
$(srcdir)/arch/arm-get-next-pcs.c \
$(srcdir)/arch/arm-linux.c \
$(srcdir)/../arch/tdesc.c \
$(srcdir)/common/btrace-common.c \
$(srcdir)/common/buffer.c \
$(srcdir)/common/cleanups.c \
@@ -232,6 +233,7 @@ TAGFILES = $(SOURCES) ${HFILES} ${ALLPARAM} ${POSSLIBS}
OBS = \
agent.o \
arch/tdesc.o \
ax.o \
btrace-common.o \
buffer.o \
@@ -391,6 +393,7 @@ gdbreplay$(EXEEXT): $(GDBREPLAY_OBS) $(LIBGNU) $(LIBIBERTY)
$(XM_CLIBS) $(LIBGNU) $(LIBIBERTY)
IPA_OBJS = \
arch/tdesc-ipa.o \
ax-ipa.o \
common-utils-ipa.o \
errors-ipa.o \

View File

@@ -34,14 +34,6 @@ fi
ipa_ppc_linux_regobj="powerpc-32l-ipa.o powerpc-altivec32l-ipa.o powerpc-cell32l-ipa.o powerpc-vsx32l-ipa.o powerpc-isa205-32l-ipa.o powerpc-isa205-altivec32l-ipa.o powerpc-isa205-vsx32l-ipa.o powerpc-e500l-ipa.o powerpc-64l-ipa.o powerpc-altivec64l-ipa.o powerpc-cell64l-ipa.o powerpc-vsx64l-ipa.o powerpc-isa205-64l-ipa.o powerpc-isa205-altivec64l-ipa.o powerpc-isa205-vsx64l-ipa.o"
srv_i386_32bit_xmlfiles="i386/32bit-core.xml i386/32bit-sse.xml i386/32bit-avx.xml i386/32bit-avx512.xml i386/32bit-mpx.xml i386/32bit-pkeys.xml"
srv_i386_64bit_xmlfiles="i386/64bit-core.xml i386/64bit-segments.xml i386/64bit-sse.xml i386/64bit-avx.xml i386/64bit-avx512.xml i386/x32-core.xml i386/64bit-mpx.xml i386/64bit-pkeys.xml"
srv_i386_xmlfiles="i386/i386.xml $srv_i386_32bit_xmlfiles"
srv_amd64_xmlfiles="i386/amd64.xml $srv_i386_64bit_xmlfiles"
srv_i386_linux_xmlfiles="i386/32bit-linux.xml $srv_i386_32bit_xmlfiles"
srv_amd64_linux_xmlfiles="i386/64bit-linux.xml $srv_i386_64bit_xmlfiles"
# Linux object files. This is so we don't have to repeat
# these files over and over again.
srv_linux_obj="linux-low.o linux-osdata.o linux-procfs.o linux-ptrace.o linux-waitpid.o linux-personality.o linux-namespaces.o fork-child.o fork-inferior.o"
@@ -63,11 +55,6 @@ case "${target}" in
srv_tgtobj="$srv_tgtobj arch/aarch64.o"
srv_tgtobj="$srv_tgtobj linux-aarch64-tdesc.o"
srv_tgtobj="${srv_tgtobj} $srv_linux_obj"
srv_xmlfiles="aarch64.xml"
srv_xmlfiles="${srv_xmlfiles} aarch64-core.xml"
srv_xmlfiles="${srv_xmlfiles} aarch64-fpu.xml"
srv_xmlfiles="${srv_xmlfiles} arm/arm-core.xml arm/arm-vfpv3.xml"
srv_xmlfiles="${srv_xmlfiles} arm/arm-with-neon.xml"
srv_linux_regsets=yes
srv_linux_thread_db=yes
ipa_obj="linux-aarch64-ipa.o"
@@ -83,14 +70,6 @@ case "${target}" in
srv_tgtobj="${srv_tgtobj} arch/arm.o"
srv_tgtobj="${srv_tgtobj} arch/arm-linux.o"
srv_tgtobj="${srv_tgtobj} arch/arm-get-next-pcs.o"
srv_xmlfiles="arm/arm-with-iwmmxt.xml"
srv_xmlfiles="${srv_xmlfiles} arm/arm-with-vfpv2.xml"
srv_xmlfiles="${srv_xmlfiles} arm/arm-with-vfpv3.xml"
srv_xmlfiles="${srv_xmlfiles} arm/arm-with-neon.xml"
srv_xmlfiles="${srv_xmlfiles} arm/arm-core.xml"
srv_xmlfiles="${srv_xmlfiles} arm/xscale-iwmmxt.xml"
srv_xmlfiles="${srv_xmlfiles} arm/arm-vfpv2.xml"
srv_xmlfiles="${srv_xmlfiles} arm/arm-vfpv3.xml"
srv_linux_usrregs=yes
srv_linux_regsets=yes
srv_linux_thread_db=yes
@@ -121,13 +100,10 @@ case "${target}" in
i[34567]86-*-cygwin*) srv_regobj=""
srv_tgtobj="x86-low.o x86-dregs.o win32-low.o win32-i386-low.o"
srv_tgtobj="${srv_tgtobj} arch/i386.o"
srv_xmlfiles="$srv_i386_xmlfiles"
;;
i[34567]86-*-linux*) srv_regobj="$srv_i386_linux_regobj"
srv_xmlfiles="$srv_i386_linux_xmlfiles"
if test "$gdb_cv_i386_is_x86_64" = yes ; then
srv_regobj="$srv_regobj $srv_amd64_linux_regobj"
srv_xmlfiles="${srv_xmlfiles} $srv_amd64_linux_xmlfiles"
srv_tgtobj="amd64-linux-siginfo.o"
fi
srv_tgtobj="${srv_tgtobj} arch/i386.o"
@@ -145,9 +121,6 @@ case "${target}" in
i[34567]86-*-lynxos*) srv_regobj=""
srv_tgtobj="lynx-low.o lynx-i386-low.o fork-child.o fork-inferior.o"
srv_tgtobj="${srv_tgtobj} arch/i386.o"
srv_xmlfiles="i386/i386.xml"
srv_xmlfiles="${srv_xmlfiles} i386/32bit-core.xml"
srv_xmlfiles="${srv_xmlfiles} i386/32bit-sse.xml"
srv_lynxos=yes
;;
i[34567]86-*-mingw32ce*)
@@ -155,7 +128,6 @@ case "${target}" in
srv_tgtobj="x86-low.o x86-dregs.o win32-low.o win32-i386-low.o"
srv_tgtobj="${srv_tgtobj} arch/i386.o"
srv_tgtobj="${srv_tgtobj} wincecompat.o"
srv_xmlfiles="$srv_i386_xmlfiles"
# hostio_last_error implementation is in win32-low.c
srv_hostio_err_objs=""
srv_mingw=yes
@@ -164,12 +136,10 @@ case "${target}" in
i[34567]86-*-mingw*) srv_regobj=""
srv_tgtobj="x86-low.o x86-dregs.o win32-low.o win32-i386-low.o"
srv_tgtobj="${srv_tgtobj} arch/i386.o"
srv_xmlfiles="$srv_i386_xmlfiles"
srv_mingw=yes
;;
i[34567]86-*-nto*) srv_regobj=""
srv_tgtobj="nto-low.o nto-x86-low.o arch/i386.o"
srv_xmlfiles="$srv_i386_xmlfiles"
srv_qnx="yes"
;;
ia64-*-linux*) srv_regobj=reg-ia64.o
@@ -370,9 +340,6 @@ case "${target}" in
else
srv_regobj=""
fi
srv_xmlfiles="${srv_xmlfiles} tic6x-core.xml"
srv_xmlfiles="${srv_xmlfiles} tic6x-gp.xml"
srv_xmlfiles="${srv_xmlfiles} tic6x-c6xp.xml"
srv_tgtobj="$srv_linux_obj linux-tic6x-low.o"
srv_tgtobj="${srv_tgtobj} arch/tic6x.o"
srv_linux_regsets=yes
@@ -386,7 +353,6 @@ case "${target}" in
srv_tgtobj="${srv_tgtobj} linux-btrace.o x86-linux.o"
srv_tgtobj="${srv_tgtobj} x86-linux-dregs.o"
srv_tgtobj="${srv_tgtobj} amd64-linux-siginfo.o"
srv_xmlfiles="$srv_i386_linux_xmlfiles $srv_amd64_linux_xmlfiles"
srv_linux_usrregs=yes # This is for i386 progs.
srv_linux_regsets=yes
srv_linux_thread_db=yes
@@ -397,13 +363,11 @@ case "${target}" in
x86_64-*-mingw*) srv_regobj=""
srv_tgtobj="x86-low.o x86-dregs.o i387-fp.o win32-low.o win32-i386-low.o"
srv_tgtobj="${srv_tgtobj} arch/amd64.o"
srv_xmlfiles="$srv_i386_xmlfiles $srv_amd64_xmlfiles"
srv_mingw=yes
;;
x86_64-*-cygwin*) srv_regobj=""
srv_tgtobj="x86-low.o x86-dregs.o i387-fp.o win32-low.o win32-i386-low.o"
srv_tgtobj="${srv_tgtobj} arch/amd64.o"
srv_xmlfiles="$srv_i386_xmlfiles"
;;
xtensa*-*-linux*) srv_regobj=reg-xtensa.o

View File

@@ -19,14 +19,85 @@
#include "tdesc.h"
#include "regdef.h"
#ifndef IN_PROCESS_AGENT
target_desc::~target_desc ()
{
for (reg *reg : reg_defs)
xfree (reg);
xfree ((char *) arch);
xfree ((char *) osabi);
}
bool target_desc::operator== (const target_desc &other) const
{
if (reg_defs.size () != other.reg_defs.size ())
return false;
for (int i = 0; i < reg_defs.size (); ++i)
{
struct reg *reg = reg_defs[i];
struct reg *reg2 = other.reg_defs[i];
if (reg != reg2 && *reg != *reg2)
return false;
}
/* Compare expedite_regs. */
int i = 0;
for (; expedite_regs[i] != NULL; i++)
{
if (strcmp (expedite_regs[i], other.expedite_regs[i]) != 0)
return false;
}
if (other.expedite_regs[i] != NULL)
return false;
return true;
}
#endif
void target_desc::accept (tdesc_element_visitor &v) const
{
#ifndef IN_PROCESS_AGENT
v.visit_pre (this);
for (const tdesc_feature_up &feature : features)
feature->accept (v);
v.visit_post (this);
#endif
}
void
init_target_desc (struct target_desc *tdesc)
{
int offset = 0;
for (reg *reg : tdesc->reg_defs)
/* Go through all the features and populate reg_defs. */
for (const tdesc_feature_up &feature : tdesc->features)
for (const tdesc_reg_up &treg : feature->registers)
{
/* Fill in any blank spaces. */
while (tdesc->reg_defs.size () < treg->target_regnum)
{
struct reg *reg = XCNEW (struct reg);
reg->name = "";
reg->size = 0;
reg->offset = offset;
tdesc->reg_defs.push_back (reg);
}
gdb_assert (treg->target_regnum == 0
|| treg->target_regnum == tdesc->reg_defs.size ());
struct reg *reg = XCNEW (struct reg);
reg->name = treg->name.c_str ();
reg->size = treg->bitsize;
reg->offset = offset;
tdesc->reg_defs.push_back (reg);
offset += reg->size;
}
@@ -91,37 +162,14 @@ tdesc_get_features_xml (target_desc *tdesc)
{
/* Either .xmltarget or .features is not NULL. */
gdb_assert (tdesc->xmltarget != NULL
|| (tdesc->features != NULL
|| (!tdesc->features.empty ()
&& tdesc->arch != NULL));
if (tdesc->xmltarget == NULL)
{
std::string buffer ("@<?xml version=\"1.0\"?>");
buffer += "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">";
buffer += "<target>";
buffer += "<architecture>";
buffer += tdesc->arch;
buffer += "</architecture>";
if (tdesc->osabi != nullptr)
{
buffer += "<osabi>";
buffer += tdesc->osabi;
buffer += "</osabi>";
}
char *xml;
for (int i = 0; VEC_iterate (char_ptr, tdesc->features, i, xml); i++)
{
buffer += "<xi:include href=\"";
buffer += xml;
buffer += "\"/>";
}
buffer += "</target>";
std::string buffer ("");
print_xml_feature v (&buffer);
tdesc->accept (v);
tdesc->xmltarget = xstrdup (buffer.c_str ());
}
@@ -129,113 +177,46 @@ tdesc_get_features_xml (target_desc *tdesc)
}
#endif
struct tdesc_type
{};
/* See arch/tdesc.h. */
struct tdesc_feature *
tdesc_create_feature (struct target_desc *tdesc, const char *name,
const char *xml)
tdesc_create_feature (struct target_desc *tdesc, const char *name)
{
struct tdesc_feature *new_feature = new tdesc_feature (name);
tdesc->features.emplace_back (new_feature);
return new_feature;
}
type *tdesc_type_builtin::make_gdb_type (struct gdbarch *gdbarch) const
{
error (_("Cannot create gdbtypes."));
}
type *tdesc_type_vector::make_gdb_type (struct gdbarch *gdbarch) const
{
error (_("Cannot create gdbtypes."));
}
type *tdesc_type_with_fields::make_gdb_type (struct gdbarch *gdbarch) const
{
error (_("Cannot create gdbtypes."));
}
void print_xml_feature::visit_pre (const target_desc *e)
{
#ifndef IN_PROCESS_AGENT
VEC_safe_push (char_ptr, tdesc->features, xstrdup (xml));
#endif
return tdesc;
}
*m_buffer += "@<?xml version=\"1.0\"?>\n";
*m_buffer += "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">\n";
*m_buffer += "<target>\n";
*m_buffer += "<architecture>";
*m_buffer += e->arch;
*m_buffer += "</architecture>\n";
/* See arch/tdesc.h. */
tdesc_type_with_fields *
tdesc_create_flags (struct tdesc_feature *feature, const char *name,
int size)
{
return NULL;
}
/* See arch/tdesc.h. */
void
tdesc_add_flag (tdesc_type_with_fields *type, int start,
const char *flag_name)
{}
/* See arch/tdesc.h. */
struct tdesc_type *
tdesc_named_type (const struct tdesc_feature *feature, const char *id)
{
return NULL;
}
/* See arch/tdesc.h. */
tdesc_type_with_fields *
tdesc_create_union (struct tdesc_feature *feature, const char *id)
{
return NULL;
}
/* See arch/tdesc.h. */
tdesc_type_with_fields *
tdesc_create_struct (struct tdesc_feature *feature, const char *id)
{
return NULL;
}
/* See arch/tdesc.h. */
void
tdesc_create_reg (struct tdesc_feature *feature, const char *name,
int regnum, int save_restore, const char *group,
int bitsize, const char *type)
{
struct target_desc *tdesc = (struct target_desc *) feature;
while (tdesc->reg_defs.size () < regnum)
if (e->osabi != nullptr)
{
struct reg *reg = XCNEW (struct reg);
reg->name = "";
reg->size = 0;
tdesc->reg_defs.push_back (reg);
*m_buffer += "<osabi>";
*m_buffer += e->osabi;
*m_buffer += "</osabi>\n";
}
#endif
}
gdb_assert (regnum == 0
|| regnum == tdesc->reg_defs.size ());
struct reg *reg = XCNEW (struct reg);
reg->name = name;
reg->size = bitsize;
tdesc->reg_defs.push_back (reg);
}
/* See arch/tdesc.h. */
struct tdesc_type *
tdesc_create_vector (struct tdesc_feature *feature, const char *name,
struct tdesc_type *field_type, int count)
{
return NULL;
}
void
tdesc_add_bitfield (tdesc_type_with_fields *type, const char *field_name,
int start, int end)
{}
/* See arch/tdesc.h. */
void
tdesc_add_field (tdesc_type_with_fields *type, const char *field_name,
struct tdesc_type *field_type)
{}
/* See arch/tdesc.h. */
void
tdesc_set_struct_size (tdesc_type_with_fields *type, int size)
{
}

View File

@@ -24,13 +24,10 @@
#include "regdef.h"
#include <vector>
struct tdesc_feature
{};
/* A target description. Inherit from tdesc_feature so that target_desc
can be used as tdesc_feature. */
struct target_desc : tdesc_feature
struct target_desc : tdesc_element
{
/* A vector of elements of register definitions that
describe the inferior's register set. */
@@ -39,6 +36,9 @@ struct target_desc : tdesc_feature
/* The register cache size, in bytes. */
int registers_size;
/* XML features in this target description. */
std::vector<tdesc_feature_up> features;
#ifndef IN_PROCESS_AGENT
/* An array of register names. These are the "expedite" registers:
registers whose values are sent along with stop replies. */
@@ -53,9 +53,6 @@ struct target_desc : tdesc_feature
fields features, arch, and osabi in tdesc_get_features_xml. */
const char *xmltarget = NULL;
/* XML features in this target description. */
VEC (char_ptr) *features = NULL;
/* The value of <architecture> element in the XML, replying GDB. */
const char *arch = NULL;
@@ -67,55 +64,18 @@ public:
: registers_size (0)
{}
~target_desc ()
{
int i;
~target_desc ();
for (reg *reg : reg_defs)
xfree (reg);
xfree ((char *) arch);
xfree ((char *) osabi);
char *f;
for (i = 0; VEC_iterate (char_ptr, features, i, f); i++)
xfree (f);
VEC_free (char_ptr, features);
}
bool operator== (const target_desc &other) const
{
if (reg_defs.size () != other.reg_defs.size ())
return false;
for (int i = 0; i < reg_defs.size (); ++i)
{
struct reg *reg = reg_defs[i];
struct reg *reg2 = other.reg_defs[i];
if (reg != reg2 && *reg != *reg2)
return false;
}
/* Compare expedite_regs. */
int i = 0;
for (; expedite_regs[i] != NULL; i++)
{
if (strcmp (expedite_regs[i], other.expedite_regs[i]) != 0)
return false;
}
if (other.expedite_regs[i] != NULL)
return false;
return true;
}
bool operator== (const target_desc &other) const;
bool operator!= (const target_desc &other) const
{
return !(*this == other);
}
#endif
void accept (tdesc_element_visitor &v) const;
};
/* Copy target description SRC to DEST. */

View File

@@ -131,7 +131,7 @@ do
echo "{"
echo " static struct target_desc tdesc_${name}_s;"
echo " struct target_desc *result = &tdesc_${name}_s;"
echo " struct tdesc_feature *feature = tdesc_create_feature (result, \"${name}\");"
continue
elif test "${type}" = "xmltarget"; then
xmltarget="${entry}"
@@ -149,7 +149,7 @@ do
echo "$0: $1 does not specify \`\`name''." 1>&2
exit 1
else
echo " tdesc_create_reg ((struct tdesc_feature *) result, \"${entry}\","
echo " tdesc_create_reg (feature, \"${entry}\","
echo " 0, 0, NULL, ${type}, NULL);"
offset=`expr ${offset} + ${type}`
@@ -180,7 +180,6 @@ echo
cat <<EOF
#ifndef IN_PROCESS_AGENT
result->expedite_regs = expedite_regs_${name};
result->xmltarget = xmltarget_${name};
#endif
init_target_desc (result);

View File

@@ -38,30 +38,6 @@
#include "completer.h"
#include "readline/tilde.h" /* tilde_expand */
/* The interface to visit different elements of target description. */
class tdesc_element_visitor
{
public:
virtual void visit_pre (const target_desc *e) = 0;
virtual void visit_post (const target_desc *e) = 0;
virtual void visit_pre (const tdesc_feature *e) = 0;
virtual void visit_post (const tdesc_feature *e) = 0;
virtual void visit (const tdesc_type_builtin *e) = 0;
virtual void visit (const tdesc_type_vector *e) = 0;
virtual void visit (const tdesc_type_with_fields *e) = 0;
virtual void visit (const tdesc_reg *e) = 0;
};
class tdesc_element
{
public:
virtual void accept (tdesc_element_visitor &v) const = 0;
};
/* Types. */
struct property
@@ -74,177 +50,10 @@ struct property
std::string value;
};
/* An individual register from a target description. */
struct tdesc_reg : tdesc_element
type *
tdesc_type_builtin::make_gdb_type (struct gdbarch *gdbarch) const
{
tdesc_reg (struct tdesc_feature *feature, const std::string &name_,
int regnum, int save_restore_, const char *group_,
int bitsize_, const char *type_)
: name (name_), target_regnum (regnum),
save_restore (save_restore_),
group (group_ != NULL ? group_ : ""),
bitsize (bitsize_),
type (type_ != NULL ? type_ : "<unknown>")
{
/* 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 ());
}
virtual ~tdesc_reg () = default;
DISABLE_COPY_AND_ASSIGN (tdesc_reg);
/* The name of this register. In standard features, it may be
recognized by the architecture support code, or it may be purely
for the user. */
std::string name;
/* The register number used by this target to refer to this
register. This is used for remote p/P packets and to determine
the ordering of registers in the remote g/G packets. */
long target_regnum;
/* If this flag is set, GDB should save and restore this register
around calls to an inferior function. */
int save_restore;
/* The name of the register group containing this register, or empty
if the group should be automatically determined from the register's
type. This is traditionally "general", "float", "vector" but can
also be an arbitrary string. If defined the corresponding "info"
command should display this register's value. The string should be
limited to alphanumeric characters and internal hyphens. */
std::string group;
/* The size of the register, in bits. */
int bitsize;
/* The type of the register. This string corresponds to either
a named type from the target description or a predefined
type from GDB. */
std::string type;
/* The target-described type corresponding to TYPE, if found. */
struct tdesc_type *tdesc_type;
void accept (tdesc_element_visitor &v) const override
{
v.visit (this);
}
bool operator== (const tdesc_reg &other) const
{
return (name == other.name
&& target_regnum == other.target_regnum
&& save_restore == other.save_restore
&& bitsize == other.bitsize
&& group == other.group
&& type == other.type);
}
bool operator!= (const tdesc_reg &other) const
{
return !(*this == other);
}
};
typedef std::unique_ptr<tdesc_reg> tdesc_reg_up;
/* A named type from a target description. */
struct tdesc_type_field
{
tdesc_type_field (const std::string &name_, tdesc_type *type_,
int start_, int end_)
: name (name_), type (type_), start (start_), end (end_)
{}
std::string 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;
};
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
};
struct tdesc_type : tdesc_element
{
tdesc_type (const std::string &name_, enum tdesc_type_kind kind_)
: name (name_), kind (kind_)
{}
virtual ~tdesc_type () = default;
DISABLE_COPY_AND_ASSIGN (tdesc_type);
/* The name of this type. */
std::string name;
/* Identify the kind of this type. */
enum tdesc_type_kind kind;
bool operator== (const tdesc_type &other) const
{
return name == other.name && kind == other.kind;
}
bool operator!= (const tdesc_type &other) const
{
return !(*this == other);
}
/* Construct, if necessary, and return the GDB type implementing this
target type for architecture GDBARCH. */
virtual type *make_gdb_type (struct gdbarch *gdbarch) const = 0;
};
typedef std::unique_ptr<tdesc_type> tdesc_type_up;
struct tdesc_type_builtin : tdesc_type
{
tdesc_type_builtin (const std::string &name, enum tdesc_type_kind kind)
: tdesc_type (name, kind)
{}
void accept (tdesc_element_visitor &v) const override
{
v.visit (this);
}
type *make_gdb_type (struct gdbarch *gdbarch) const override
{
switch (this->kind)
{
/* Predefined types. */
@@ -316,25 +125,11 @@ struct tdesc_type_builtin : tdesc_type
this->name.c_str (), this->kind);
return NULL;
}
};
}
/* tdesc_type for vector types. */
struct tdesc_type_vector : tdesc_type
type *
tdesc_type_vector::make_gdb_type (struct gdbarch *gdbarch) const
{
tdesc_type_vector (const std::string &name, tdesc_type *element_type_, int count_)
: tdesc_type (name, TDESC_TYPE_VECTOR),
element_type (element_type_), count (count_)
{}
void accept (tdesc_element_visitor &v) const override
{
v.visit (this);
}
type *make_gdb_type (struct gdbarch *gdbarch) const override
{
type *vector_gdb_type = tdesc_find_type (gdbarch, this->name.c_str ());
if (vector_gdb_type != NULL)
return vector_gdb_type;
@@ -344,28 +139,11 @@ struct tdesc_type_vector : tdesc_type
TYPE_NAME (vector_gdb_type) = xstrdup (this->name.c_str ());
return vector_gdb_type;
}
}
struct tdesc_type *element_type;
int count;
};
/* tdesc_type for struct, union, flags, and enum types. */
struct tdesc_type_with_fields : tdesc_type
type *
tdesc_type_with_fields::make_gdb_type_struct (struct gdbarch *gdbarch) const
{
tdesc_type_with_fields (const std::string &name, tdesc_type_kind kind,
int size_ = 0)
: tdesc_type (name, kind), size (size_)
{}
void accept (tdesc_element_visitor &v) const override
{
v.visit (this);
}
type *make_gdb_type_struct (struct gdbarch *gdbarch) const
{
type *struct_gdb_type = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT);
TYPE_NAME (struct_gdb_type) = xstrdup (this->name.c_str ());
TYPE_TAG_NAME (struct_gdb_type) = TYPE_NAME (struct_gdb_type);
@@ -420,10 +198,11 @@ struct tdesc_type_with_fields : tdesc_type
TYPE_LENGTH (struct_gdb_type) = this->size;
return struct_gdb_type;
}
}
type *make_gdb_type_union (struct gdbarch *gdbarch) const
{
type *
tdesc_type_with_fields::make_gdb_type_union (struct gdbarch *gdbarch) const
{
type *union_gdb_type = arch_composite_type (gdbarch, NULL, TYPE_CODE_UNION);
TYPE_NAME (union_gdb_type) = xstrdup (this->name.c_str ());
@@ -441,10 +220,11 @@ struct tdesc_type_with_fields : tdesc_type
}
return union_gdb_type;
}
}
type *make_gdb_type_flags (struct gdbarch *gdbarch) const
{
type *
tdesc_type_with_fields::make_gdb_type_flags (struct gdbarch *gdbarch) const
{
type *flags_gdb_type = arch_flags_type (gdbarch, this->name.c_str (),
this->size * TARGET_CHAR_BIT);
@@ -459,10 +239,11 @@ struct tdesc_type_with_fields : tdesc_type
}
return flags_gdb_type;
}
}
type *make_gdb_type_enum (struct gdbarch *gdbarch) const
{
type *
tdesc_type_with_fields::make_gdb_type_enum (struct gdbarch *gdbarch) const
{
type *enum_gdb_type = arch_type (gdbarch, TYPE_CODE_ENUM,
this->size * TARGET_CHAR_BIT,
this->name.c_str ());
@@ -479,10 +260,11 @@ struct tdesc_type_with_fields : tdesc_type
}
return enum_gdb_type;
}
}
type *make_gdb_type (struct gdbarch *gdbarch) const override
{
type *
tdesc_type_with_fields::make_gdb_type (struct gdbarch *gdbarch) const
{
type *gdb_type = tdesc_find_type (gdbarch, this->name.c_str ());
if (gdb_type != NULL)
return gdb_type;
@@ -504,87 +286,7 @@ struct tdesc_type_with_fields : tdesc_type
this->name.c_str (), this->kind);
return NULL;
}
std::vector<tdesc_type_field> fields;
int size;
};
/* A feature from a target description. Each feature is a collection
of other elements, e.g. registers and types. */
struct tdesc_feature : tdesc_element
{
tdesc_feature (const std::string &name_)
: name (name_)
{}
virtual ~tdesc_feature () = default;
DISABLE_COPY_AND_ASSIGN (tdesc_feature);
/* The name of this feature. It may be recognized by the architecture
support code. */
std::string name;
/* The registers associated with this feature. */
std::vector<tdesc_reg_up> registers;
/* The types associated with this feature. */
std::vector<tdesc_type_up> types;
void accept (tdesc_element_visitor &v) const override
{
v.visit_pre (this);
for (const tdesc_type_up &type : types)
type->accept (v);
for (const tdesc_reg_up &reg : registers)
reg->accept (v);
v.visit_post (this);
}
bool operator== (const tdesc_feature &other) const
{
if (name != other.name)
return false;
if (registers.size () != other.registers.size ())
return false;
for (int ix = 0; ix < registers.size (); ix++)
{
const tdesc_reg_up &reg1 = registers[ix];
const tdesc_reg_up &reg2 = other.registers[ix];
if (reg1 != reg2 && *reg1 != *reg2)
return false;
}
if (types.size () != other.types.size ())
return false;
for (int ix = 0; ix < types.size (); ix++)
{
const tdesc_type_up &type1 = types[ix];
const tdesc_type_up &type2 = other.types[ix];
if (type1 != type2 && *type1 != *type2)
return false;
}
return true;
}
bool operator!= (const tdesc_feature &other) const
{
return !(*this == other);
}
};
typedef std::unique_ptr<tdesc_feature> tdesc_feature_up;
}
/* A target description. */
@@ -614,6 +316,8 @@ struct target_desc : tdesc_element
/* The features associated with this target. */
std::vector<tdesc_feature_up> features;
char *xmltarget = nullptr;
void accept (tdesc_element_visitor &v) const override
{
v.visit_pre (this);
@@ -957,58 +661,6 @@ tdesc_feature_name (const struct tdesc_feature *feature)
return feature->name.c_str ();
}
/* Predefined types. */
static tdesc_type_builtin tdesc_predefined_types[] =
{
{ "bool", TDESC_TYPE_BOOL },
{ "int8", TDESC_TYPE_INT8 },
{ "int16", TDESC_TYPE_INT16 },
{ "int32", TDESC_TYPE_INT32 },
{ "int64", TDESC_TYPE_INT64 },
{ "int128", TDESC_TYPE_INT128 },
{ "uint8", TDESC_TYPE_UINT8 },
{ "uint16", TDESC_TYPE_UINT16 },
{ "uint32", TDESC_TYPE_UINT32 },
{ "uint64", TDESC_TYPE_UINT64 },
{ "uint128", TDESC_TYPE_UINT128 },
{ "code_ptr", TDESC_TYPE_CODE_PTR },
{ "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 },
{ "i387_ext", TDESC_TYPE_I387_EXT }
};
/* Lookup a predefined type. */
static struct tdesc_type *
tdesc_predefined_type (enum tdesc_type_kind kind)
{
for (int 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");
}
/* See arch/tdesc.h. */
struct tdesc_type *
tdesc_named_type (const struct tdesc_feature *feature, const char *id)
{
/* First try target-defined types. */
for (const tdesc_type_up &type : feature->types)
if (type->name == id)
return type.get ();
/* Next try the predefined types. */
for (int ix = 0; ix < ARRAY_SIZE (tdesc_predefined_types); ix++)
if (tdesc_predefined_types[ix].name == id)
return &tdesc_predefined_types[ix];
return NULL;
}
/* Lookup type associated with ID. */
struct type *
@@ -1440,167 +1092,11 @@ tdesc_use_registers (struct gdbarch *gdbarch,
tdesc_remote_register_number);
set_gdbarch_register_reggroup_p (gdbarch, tdesc_register_reggroup_p);
}
/* See arch/tdesc.h. */
void
tdesc_create_reg (struct tdesc_feature *feature, const char *name,
int regnum, int save_restore, const char *group,
int bitsize, const char *type)
{
tdesc_reg *reg = new tdesc_reg (feature, name, regnum, save_restore,
group, bitsize, type);
feature->registers.emplace_back (reg);
}
/* See arch/tdesc.h. */
struct tdesc_type *
tdesc_create_vector (struct tdesc_feature *feature, const char *name,
struct tdesc_type *field_type, int count)
{
tdesc_type_vector *type = new tdesc_type_vector (name, field_type, count);
feature->types.emplace_back (type);
return type;
}
/* See arch/tdesc.h. */
tdesc_type_with_fields *
tdesc_create_struct (struct tdesc_feature *feature, const char *name)
{
tdesc_type_with_fields *type
= new tdesc_type_with_fields (name, TDESC_TYPE_STRUCT);
feature->types.emplace_back (type);
return type;
}
/* See arch/tdesc.h. */
void
tdesc_set_struct_size (tdesc_type_with_fields *type, int size)
{
gdb_assert (type->kind == TDESC_TYPE_STRUCT);
gdb_assert (size > 0);
type->size = size;
}
/* See arch/tdesc.h. */
tdesc_type_with_fields *
tdesc_create_union (struct tdesc_feature *feature, const char *name)
{
tdesc_type_with_fields *type
= new tdesc_type_with_fields (name, TDESC_TYPE_UNION);
feature->types.emplace_back (type);
return type;
}
/* See arch/tdesc.h. */
tdesc_type_with_fields *
tdesc_create_flags (struct tdesc_feature *feature, const char *name,
int size)
{
gdb_assert (size > 0);
tdesc_type_with_fields *type
= new tdesc_type_with_fields (name, TDESC_TYPE_FLAGS, size);
feature->types.emplace_back (type);
return type;
}
tdesc_type_with_fields *
tdesc_create_enum (struct tdesc_feature *feature, const char *name,
int size)
{
gdb_assert (size > 0);
tdesc_type_with_fields *type
= new tdesc_type_with_fields (name, TDESC_TYPE_ENUM, size);
feature->types.emplace_back (type);
return type;
}
/* See arch/tdesc.h. */
void
tdesc_add_field (tdesc_type_with_fields *type, const char *field_name,
struct tdesc_type *field_type)
{
gdb_assert (type->kind == TDESC_TYPE_UNION
|| type->kind == TDESC_TYPE_STRUCT);
/* Initialize start and end so we know this is not a bit-field
when we print-c-tdesc. */
type->fields.emplace_back (field_name, field_type, -1, -1);
}
void
tdesc_add_typed_bitfield (tdesc_type_with_fields *type, const char *field_name,
int start, int end, struct tdesc_type *field_type)
{
gdb_assert (type->kind == TDESC_TYPE_STRUCT
|| type->kind == TDESC_TYPE_FLAGS);
gdb_assert (start >= 0 && end >= start);
type->fields.emplace_back (field_name, field_type, start, end);
}
/* See arch/tdesc.h. */
void
tdesc_add_bitfield (tdesc_type_with_fields *type, const char *field_name,
int start, int end)
{
struct tdesc_type *field_type;
gdb_assert (start >= 0 && end >= start);
if (type->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);
}
/* See arch/tdesc.h. */
void
tdesc_add_flag (tdesc_type_with_fields *type, int start,
const char *flag_name)
{
gdb_assert (type->kind == TDESC_TYPE_FLAGS
|| type->kind == TDESC_TYPE_STRUCT);
type->fields.emplace_back (flag_name,
tdesc_predefined_type (TDESC_TYPE_BOOL),
start, start);
}
void
tdesc_add_enum_value (tdesc_type_with_fields *type, int value,
const char *name)
{
gdb_assert (type->kind == TDESC_TYPE_ENUM);
type->fields.emplace_back (name,
tdesc_predefined_type (TDESC_TYPE_INT32),
value, -1);
}
/* See arch/tdesc.h. */
struct tdesc_feature *
tdesc_create_feature (struct target_desc *tdesc, const char *name,
const char *xml)
tdesc_create_feature (struct target_desc *tdesc, const char *name)
{
struct tdesc_feature *new_feature = new tdesc_feature (name);
@@ -2068,8 +1564,8 @@ public:
printf_unfiltered (" struct tdesc_feature *feature;\n");
printf_unfiltered
("\n feature = tdesc_create_feature (result, \"%s\", \"%s\");\n",
e->name.c_str (), lbasename (m_filename_after_features.c_str ()));
("\n feature = tdesc_create_feature (result, \"%s\");\n",
e->name.c_str ());
}
void visit_post (const tdesc_feature *e) override
@@ -2138,6 +1634,39 @@ private:
int m_next_regnum = 0;
};
void print_xml_feature::visit_pre (const target_desc *e)
{
*m_buffer += "<?xml version=\"1.0\"?>\n";
*m_buffer += "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">\n";
*m_buffer += "<target>\n";
*m_buffer += "<architecture>";
*m_buffer += tdesc_architecture (e)->printable_name;
*m_buffer += "</architecture>\n";
if (e->osabi != GDB_OSABI_UNKNOWN)
{
*m_buffer += "<osabi>";
*m_buffer += gdbarch_osabi_name (tdesc_osabi (e));
*m_buffer += "</osabi>\n";
}
}
/* Return a string which is of XML format, including XML target
description to be sent to GDB. */
const char *
tdesc_get_features_xml (target_desc *tdesc)
{
if (tdesc->xmltarget == nullptr)
{
std::string buffer ("");
print_xml_feature v (&buffer);
tdesc->accept (v);
tdesc->xmltarget = xstrdup (buffer.c_str ());
}
return tdesc->xmltarget;
}
static void
maint_print_c_tdesc_cmd (const char *args, int from_tty)
{
@@ -2231,7 +1760,34 @@ maintenance_check_xml_descriptions (const char *dir, int from_tty)
= file_read_description_xml (tdesc_xml.data ());
if (tdesc == NULL || *tdesc != *e.second)
{
printf_filtered ( _("Descriptions for %s do not match\n"), e.first);
failed++;
continue;
}
/* Convert both descriptions to xml, and then back again. Confirm all
descriptions are identical. */
const char *xml = tdesc_get_features_xml ((target_desc *) tdesc);
const char *xml2 = tdesc_get_features_xml ((target_desc *) e.second);
const target_desc *t_trans = target_read_description_xml_string (xml);
const target_desc *t_trans2 = target_read_description_xml_string (xml2);
if (t_trans == NULL || t_trans2 == NULL)
{
printf_filtered (
_("Could not convert descriptions for %s back to xml (%p %p)\n"),
e.first, t_trans, t_trans2);
failed++;
}
else if (*tdesc != *t_trans || *tdesc != *t_trans2)
{
printf_filtered
(_("Translated descriptions for %s do not match (%d %d)\n"),
e.first, *tdesc == *t_trans, *tdesc == *t_trans2);
failed++;
}
}
printf_filtered (_("Tested %lu XML files, %d failed\n"),
(long) selftests::xml_tdesc.size (), failed);

View File

@@ -752,3 +752,12 @@ target_fetch_description_xml (struct target_ops *ops)
return output;
#endif
}
/* Take an xml string, parse it, and return the parsed description. Does not
handle a string containing includes. */
const struct target_desc *
target_read_description_xml_string (const char *xml_str)
{
return tdesc_parse_xml (xml_str, nullptr, nullptr);
}

View File

@@ -44,5 +44,10 @@ const struct target_desc *target_read_description_xml (struct target_ops *);
otherwise. */
gdb::optional<std::string> target_fetch_description_xml (target_ops *ops);
/* Take an xml string, parse it, and return the parsed description. Does not
handle a string containing includes. */
const struct target_desc *target_read_description_xml_string (const char *);
#endif /* XML_TDESC_H */