Re: [PATCH v4 21/29] gdbstub: expose api to find registers
On 2024/02/27 23:43, Alex Bennée wrote: Expose an internal API to QEMU to return all the registers for a vCPU. The list containing the details required to called gdb_read_register(). Based-on: <20231025093128.33116-15-akihiko.od...@daynix.com> Cc: Akihiko Odaki Message-Id: <20240103173349.398526-38-alex.ben...@linaro.org> Signed-off-by: Alex Bennée Reviewed-by: Akihiko Odaki --- v3 - rm unused api functions left over --- include/exec/gdbstub.h | 28 gdbstub/gdbstub.c | 27 ++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h index da9ddfe54c5..eb14b91139b 100644 --- a/include/exec/gdbstub.h +++ b/include/exec/gdbstub.h @@ -111,6 +111,34 @@ void gdb_feature_builder_end(const GDBFeatureBuilder *builder); */ const GDBFeature *gdb_find_static_feature(const char *xmlname); +/** + * gdb_read_register() - Read a register associated with a CPU. + * @cpu: The CPU associated with the register. + * @buf: The buffer that the read register will be appended to. + * @reg: The register's number returned by gdb_find_feature_register(). + * + * Return: The number of read bytes. + */ +int gdb_read_register(CPUState *cpu, GByteArray *buf, int reg); + +/** + * typedef GDBRegDesc - a register description from gdbstub + */ +typedef struct { +int gdb_reg; +const char *name; +const char *feature_name; +} GDBRegDesc; + +/** + * gdb_get_register_list() - Return list of all registers for CPU + * @cpu: The CPU being searched + * + * Returns a GArray of GDBRegDesc, caller frees array but not the + * const strings. + */ +GArray *gdb_get_register_list(CPUState *cpu); + void gdb_set_stop_cpu(CPUState *cpu); /* in gdbstub-xml.c, generated by scripts/feature_to_c.py */ diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c index a55b5e6581a..2909bc8c69f 100644 --- a/gdbstub/gdbstub.c +++ b/gdbstub/gdbstub.c @@ -490,7 +490,32 @@ const GDBFeature *gdb_find_static_feature(const char *xmlname) g_assert_not_reached(); } -static int gdb_read_register(CPUState *cpu, GByteArray *buf, int reg) +GArray *gdb_get_register_list(CPUState *cpu) +{ +GArray *results = g_array_new(true, true, sizeof(GDBRegDesc)); + +/* registers are only available once the CPU is initialised */ +if (!cpu->gdb_regs) { +return results; +} + +for (int f = 0; f < cpu->gdb_regs->len; f++) { +GDBRegisterState *r = _array_index(cpu->gdb_regs, GDBRegisterState, f); +for (int i = 0; i < r->feature->num_regs; i++) { +const char *name = r->feature->regs[i]; +GDBRegDesc desc = { +r->base_reg + i, +name, +r->feature->name +}; +g_array_append_val(results, desc); +} +} + +return results; +} + +int gdb_read_register(CPUState *cpu, GByteArray *buf, int reg) { CPUClass *cc = CPU_GET_CLASS(cpu); GDBRegisterState *r;
[PATCH v4 21/29] gdbstub: expose api to find registers
Expose an internal API to QEMU to return all the registers for a vCPU. The list containing the details required to called gdb_read_register(). Based-on: <20231025093128.33116-15-akihiko.od...@daynix.com> Cc: Akihiko Odaki Message-Id: <20240103173349.398526-38-alex.ben...@linaro.org> Signed-off-by: Alex Bennée --- v3 - rm unused api functions left over --- include/exec/gdbstub.h | 28 gdbstub/gdbstub.c | 27 ++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h index da9ddfe54c5..eb14b91139b 100644 --- a/include/exec/gdbstub.h +++ b/include/exec/gdbstub.h @@ -111,6 +111,34 @@ void gdb_feature_builder_end(const GDBFeatureBuilder *builder); */ const GDBFeature *gdb_find_static_feature(const char *xmlname); +/** + * gdb_read_register() - Read a register associated with a CPU. + * @cpu: The CPU associated with the register. + * @buf: The buffer that the read register will be appended to. + * @reg: The register's number returned by gdb_find_feature_register(). + * + * Return: The number of read bytes. + */ +int gdb_read_register(CPUState *cpu, GByteArray *buf, int reg); + +/** + * typedef GDBRegDesc - a register description from gdbstub + */ +typedef struct { +int gdb_reg; +const char *name; +const char *feature_name; +} GDBRegDesc; + +/** + * gdb_get_register_list() - Return list of all registers for CPU + * @cpu: The CPU being searched + * + * Returns a GArray of GDBRegDesc, caller frees array but not the + * const strings. + */ +GArray *gdb_get_register_list(CPUState *cpu); + void gdb_set_stop_cpu(CPUState *cpu); /* in gdbstub-xml.c, generated by scripts/feature_to_c.py */ diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c index a55b5e6581a..2909bc8c69f 100644 --- a/gdbstub/gdbstub.c +++ b/gdbstub/gdbstub.c @@ -490,7 +490,32 @@ const GDBFeature *gdb_find_static_feature(const char *xmlname) g_assert_not_reached(); } -static int gdb_read_register(CPUState *cpu, GByteArray *buf, int reg) +GArray *gdb_get_register_list(CPUState *cpu) +{ +GArray *results = g_array_new(true, true, sizeof(GDBRegDesc)); + +/* registers are only available once the CPU is initialised */ +if (!cpu->gdb_regs) { +return results; +} + +for (int f = 0; f < cpu->gdb_regs->len; f++) { +GDBRegisterState *r = _array_index(cpu->gdb_regs, GDBRegisterState, f); +for (int i = 0; i < r->feature->num_regs; i++) { +const char *name = r->feature->regs[i]; +GDBRegDesc desc = { +r->base_reg + i, +name, +r->feature->name +}; +g_array_append_val(results, desc); +} +} + +return results; +} + +int gdb_read_register(CPUState *cpu, GByteArray *buf, int reg) { CPUClass *cc = CPU_GET_CLASS(cpu); GDBRegisterState *r; -- 2.39.2