[PATCH 2/6]: gdbserver use common tdesc functions

Alan Hayward
2018-01-16T09:52:15Z

This moves gdbserver over to using the common tdesc functions.
gdbserver now parses target descriptions using the same code
as gdb. These parsed structures are not (yet) used once parsed.

tdesc_feature and target_desc are no longer interchangeable in
gdbserver, and is now it's own structure. It does not share
code with gdb, as gdbsever has additional fields it still
requires - mainly the reg_defs and registers_size fields (as
used by regcache). These fields are now populated in
init_target_desc() from the common tdesc fields. A future patch
could change regcache to access the newer tdesc fields but that
is outside of the scope of this patch series.

Alan.

2018-01-16 Alan Hayward <alan.hayward@arm.com>

gdb/
* arch/tdesc.h: Allow code to compile for gdbserver.
* regformats/regdat.sh: Explicitly create a feature.

gdbserver/
* Makefile.in: Add the new common file.
* tdesc.c (tdesc_feature): Replaced by common version.
(void target_desc::~target_desc): Moved from .c file.
(void target_desc::accept): Blank function.
(bool target_desc::operator==): Moved from .c file.
(init_target_desc): Init reg_defs from parsed feature.
(tdesc_get_features_xml): features is now a vector.
(struct tdesc_type): Remove. Use common version.
(tdesc_create_feature): Create new structure.
(tdesc_create_flags): Remove. Use common version.
(tdesc_add_flag): Likewise.
(tdesc_named_type): Likewise.
(tdesc_create_union): Likewise.
(tdesc_create_struct): Likewise.
(type *tdesc_type_builtin::make_gdb_type): Blank stub.
(type *tdesc_type_vector::make_gdb_type): Likewise.
(tdesc_add_bitfield): Likewise.
(tdesc_add_field): Likewise.
* tdesc.h (struct target_desc): Update field types.

diff --git a/gdb/arch/tdesc.h b/gdb/arch/tdesc.h
index 22da5efa48f8cf5e94c33c9eed4739127467c356..633853447d98c952cfed462939b486afd2738742 100644
--- a/gdb/arch/tdesc.h
+++ b/gdb/arch/tdesc.h
@@ -33,8 +33,6 @@ struct tdesc_reg;
struct target_desc;
struct type;

-#ifndef GDBSERVER
-
/* The interface to visit different elements of target description. */

class tdesc_element_visitor
@@ -295,8 +293,6 @@ struct tdesc_arch_reg
struct type *type;
};

-#endif
-
/* Allocate a new target_desc. */
target_desc *allocate_target_description (void);

diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index 3ce086d70f23df445b174c49c489ec8415d7614a..8ae124875dd08f31e8424b18281cb1454ed40edb 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -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 \
diff --git a/gdb/gdbserver/tdesc.h b/gdb/gdbserver/tdesc.h
index 783500598b5599e51f8e768a876fdfe499cdf0ef..499ed0e4598ae812f2d1ceb1fa8e8f1f50c14fff 100644
--- a/gdb/gdbserver/tdesc.h
+++ b/gdb/gdbserver/tdesc.h
@@ -24,13 +24,9 @@
#include "regdef.h"
#include <vector>

-struct tdesc_feature
-{};
+/* A target description. */

-/* 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. */
@@ -52,70 +48,34 @@ struct target_desc : tdesc_feature
It can be NULL, then, its content is got from the following three
fields features, arch, and osabi in tdesc_get_features_xml. */
const char *xmltarget = NULL;
+#endif

/* XML features in this target description. */
- VEC (char_ptr) *features = NULL;
+ std::vector<tdesc_feature_up> features;

+#ifndef IN_PROCESS_AGENT
/* The value of <architecture> element in the XML, replying GDB. */
const char *arch = NULL;

/* The value of <osabi> element in the XML, replying GDB. */
const char *osabi = NULL;
+#endif

public:
target_desc ()
: registers_size (0)
{}

- ~target_desc ()
- {
- int i;
-
- for (reg *reg : reg_defs)
- xfree (reg);
+ ~target_desc ();

- xfree ((char *) arch);
- xfree ((char *) osabi);
+ void accept (tdesc_element_visitor &v) const override;

- 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
};

/* Copy target description SRC to DEST. */
diff --git a/gdb/gdbserver/tdesc.c b/gdb/gdbserver/tdesc.c
index c39b5e7d27e879c5d3fb49b6e04d1eb6128f8eef..a96b3f07e7aff81f32a160d6498c8012d18bd0c7 100644
--- a/gdb/gdbserver/tdesc.c
+++ b/gdb/gdbserver/tdesc.c
@@ -19,16 +19,78 @@
#include "tdesc.h"
#include "regdef.h"

+target_desc::~target_desc ()
+{
+ for (reg *reg : reg_defs)
+ xfree (reg);
+
+#ifndef IN_PROCESS_AGENT
+ xfree ((char *) arch);
+ xfree ((char *) osabi);
+#endif
+}
+
+void target_desc::accept (tdesc_element_visitor &v) const
+{}
+
+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;
+ }
+
+#ifndef IN_PROCESS_AGENT
+ /* 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;
+#endif
+
+ return true;
+}
+
void
init_target_desc (struct target_desc *tdesc)
{
int offset = 0;

- for (reg *reg : tdesc->reg_defs)
- {
- reg->offset = offset;
- offset += reg->size;
- }
+ /* 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;
+ }

tdesc->registers_size = offset / 8;

@@ -91,7 +153,7 @@ 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)
@@ -111,12 +173,10 @@ tdesc_get_features_xml (target_desc *tdesc)
buffer += "</osabi>";
}

- char *xml;
-
- for (int i = 0; VEC_iterate (char_ptr, tdesc->features, i, xml); i++)
+ for (const tdesc_feature_up &feature : tdesc->features)
{
buffer += "<xi:include href=\"";
- buffer += xml;
+ buffer += feature->name;
buffer += "\"/>";
}

@@ -129,113 +189,28 @@ 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)
{
-#ifndef IN_PROCESS_AGENT
- VEC_safe_push (char_ptr, tdesc->features, xstrdup (xml));
-#endif
- return tdesc;
-}
-
-/* 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;
+ struct tdesc_feature *new_feature = new tdesc_feature (name);
+ tdesc->features.emplace_back (new_feature);
+ return new_feature;
}

-/* See arch/tdesc.h. */
-
-tdesc_type_with_fields *
-tdesc_create_union (struct tdesc_feature *feature, const char *id)
+type *tdesc_type_builtin::make_gdb_type (struct gdbarch *gdbarch) const
{
- 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)
- {
- struct reg *reg = XCNEW (struct reg);
-
- reg->name = "";
- reg->size = 0;
- tdesc->reg_defs.push_back (reg);
- }
-
- 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);
+ error (_("Cannot create gdbtypes."));
}

-/* See arch/tdesc.h. */
-
-struct tdesc_type *
-tdesc_create_vector (struct tdesc_feature *feature, const char *name,
- struct tdesc_type *field_type, int count)
+type *tdesc_type_vector::make_gdb_type (struct gdbarch *gdbarch) const
{
- return NULL;
+ error (_("Cannot create gdbtypes."));
}

-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)
+type *tdesc_type_with_fields::make_gdb_type (struct gdbarch *gdbarch) const
{
-}
+ error (_("Cannot create gdbtypes."));
+}
\ No newline at end of file
diff --git a/gdb/regformats/regdat.sh b/gdb/regformats/regdat.sh
index ce1627120d9439082709c82c5804724f39477eb1..8c6e191596350fb4e983f8736985d9832f41e2d3 100755
--- a/gdb/regformats/regdat.sh
+++ b/gdb/regformats/regdat.sh
@@ -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}`