gdbstub: Introduce GDBFeatureBuilder

GDBFeatureBuilder unifies the logic to generate dynamic GDBFeature.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20231025093128.33116-4-akihiko.odaki@daynix.com>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Message-Id: <20231106185112.2755262-11-alex.bennee@linaro.org>
This commit is contained in:
Akihiko Odaki 2023-11-06 18:51:00 +00:00 committed by Alex Bennée
parent 1218b68ea6
commit e84f45243f
2 changed files with 115 additions and 0 deletions

View File

@ -422,6 +422,71 @@ static const char *get_feature_xml(const char *p, const char **newp,
return NULL; return NULL;
} }
void gdb_feature_builder_init(GDBFeatureBuilder *builder, GDBFeature *feature,
const char *name, const char *xmlname,
int base_reg)
{
char *header = g_markup_printf_escaped(
"<?xml version=\"1.0\"?>"
"<!DOCTYPE feature SYSTEM \"gdb-target.dtd\">"
"<feature name=\"%s\">",
name);
builder->feature = feature;
builder->xml = g_ptr_array_new();
g_ptr_array_add(builder->xml, header);
builder->base_reg = base_reg;
feature->xmlname = xmlname;
feature->num_regs = 0;
}
void gdb_feature_builder_append_tag(const GDBFeatureBuilder *builder,
const char *format, ...)
{
va_list ap;
va_start(ap, format);
g_ptr_array_add(builder->xml, g_markup_vprintf_escaped(format, ap));
va_end(ap);
}
void gdb_feature_builder_append_reg(const GDBFeatureBuilder *builder,
const char *name,
int bitsize,
int regnum,
const char *type,
const char *group)
{
if (builder->feature->num_regs < regnum) {
builder->feature->num_regs = regnum;
}
if (group) {
gdb_feature_builder_append_tag(
builder,
"<reg name=\"%s\" bitsize=\"%d\" regnum=\"%d\" type=\"%s\" group=\"%s\"/>",
name, bitsize, builder->base_reg + regnum, type, group);
} else {
gdb_feature_builder_append_tag(
builder,
"<reg name=\"%s\" bitsize=\"%d\" regnum=\"%d\" type=\"%s\"/>",
name, bitsize, builder->base_reg + regnum, type);
}
}
void gdb_feature_builder_end(const GDBFeatureBuilder *builder)
{
g_ptr_array_add(builder->xml, (void *)"</feature>");
g_ptr_array_add(builder->xml, NULL);
builder->feature->xml = g_strjoinv(NULL, (void *)builder->xml->pdata);
for (guint i = 0; i < builder->xml->len - 2; i++) {
g_free(g_ptr_array_index(builder->xml, i));
}
g_ptr_array_free(builder->xml, TRUE);
}
const GDBFeature *gdb_find_static_feature(const char *xmlname) const GDBFeature *gdb_find_static_feature(const char *xmlname)
{ {
const GDBFeature *feature; const GDBFeature *feature;

View File

@ -16,6 +16,12 @@ typedef struct GDBFeature {
int num_regs; int num_regs;
} GDBFeature; } GDBFeature;
typedef struct GDBFeatureBuilder {
GDBFeature *feature;
GPtrArray *xml;
int base_reg;
} GDBFeatureBuilder;
/* Get or set a register. Returns the size of the register. */ /* Get or set a register. Returns the size of the register. */
typedef int (*gdb_get_reg_cb)(CPUArchState *env, GByteArray *buf, int reg); typedef int (*gdb_get_reg_cb)(CPUArchState *env, GByteArray *buf, int reg);
@ -44,6 +50,50 @@ void gdb_register_coprocessor(CPUState *cpu,
*/ */
int gdbserver_start(const char *port_or_device); int gdbserver_start(const char *port_or_device);
/**
* gdb_feature_builder_init() - Initialize GDBFeatureBuilder.
* @builder: The builder to be initialized.
* @feature: The feature to be filled.
* @name: The name of the feature.
* @xmlname: The name of the XML.
* @base_reg: The base number of the register ID.
*/
void gdb_feature_builder_init(GDBFeatureBuilder *builder, GDBFeature *feature,
const char *name, const char *xmlname,
int base_reg);
/**
* gdb_feature_builder_append_tag() - Append a tag.
* @builder: The builder.
* @format: The format of the tag.
* @...: The values to be formatted.
*/
void G_GNUC_PRINTF(2, 3)
gdb_feature_builder_append_tag(const GDBFeatureBuilder *builder,
const char *format, ...);
/**
* gdb_feature_builder_append_reg() - Append a register.
* @builder: The builder.
* @name: The register's name; it must be unique within a CPU.
* @bitsize: The register's size, in bits.
* @regnum: The offset of the register's number in the feature.
* @type: The type of the register.
* @group: The register group to which this register belongs; it can be NULL.
*/
void gdb_feature_builder_append_reg(const GDBFeatureBuilder *builder,
const char *name,
int bitsize,
int regnum,
const char *type,
const char *group);
/**
* gdb_feature_builder_end() - End building GDBFeature.
* @builder: The builder.
*/
void gdb_feature_builder_end(const GDBFeatureBuilder *builder);
/** /**
* gdb_find_static_feature() - Find a static feature. * gdb_find_static_feature() - Find a static feature.
* @xmlname: The name of the XML. * @xmlname: The name of the XML.