[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 21/29] gdbstub: expose api to find registers
From: |
Alex Bennée |
Subject: |
[PATCH 21/29] gdbstub: expose api to find registers |
Date: |
Fri, 3 Nov 2023 19:59:48 +0000 |
Expose an internal API to QEMU to find groups of registers. It returns
a list containing the details required to called gdb_read_register().
Based-on: <20231025093128.33116-15-akihiko.odaki@daynix.com>
Cc: Akihiko Odaki <akihiko.odaki@daynix.com>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
vAJB:
This principle difference is the find registers is a single call which
can return a) multiple registers and b) is agnostic to the gdb
feature. This is because I haven't so far found any duplicate
registers in the system so I thing the regname by itself should be
enough. However I do expose the gdb feature name in case the caller
wants to do some additional filtering.
---
include/exec/gdbstub.h | 47 +++++++++++++++++++++++++++++++++
gdbstub/gdbstub.c | 59 +++++++++++++++++++++++++++++++++++++++++-
2 files changed, 105 insertions(+), 1 deletion(-)
diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h
index da9ddfe54c..b201eb4b84 100644
--- a/include/exec/gdbstub.h
+++ b/include/exec/gdbstub.h
@@ -111,6 +111,53 @@ void gdb_feature_builder_end(const GDBFeatureBuilder
*builder);
*/
const GDBFeature *gdb_find_static_feature(const char *xmlname);
+/**
+ * gdb_find_feature() - Find a feature associated with a CPU.
+ * @cpu: The CPU associated with the feature.
+ * @name: The feature's name.
+ *
+ * Return: The feature's number.
+ */
+int gdb_find_feature(CPUState *cpu, const char *name);
+
+/**
+ * gdb_find_feature_register() - Find a register associated with a CPU.
+ * @cpu: The CPU associated with the register.
+ * @feature: The feature's number returned by gdb_find_feature().
+ * @name: The register's name.
+ *
+ * Return: The register's number.
+ */
+int gdb_find_feature_register(CPUState *cpu, int feature, const char *name);
+
+/**
+ * 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_find_registers() - Return list of registers matching pattern
+ * @cpu: The CPU being searched
+ * @reg_pattern: the pattern being searched for
+ *
+ * Returns a GArray of GDBRegDesc, caller frees
+ */
+GArray *gdb_find_registers(CPUState *cpu, const char *reg_pattern);
+
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 7d7d887817..45882d1a6f 100644
--- a/gdbstub/gdbstub.c
+++ b/gdbstub/gdbstub.c
@@ -490,7 +490,64 @@ const GDBFeature *gdb_find_static_feature(const char
*xmlname)
g_assert_not_reached();
}
-static int gdb_read_register(CPUState *cpu, GByteArray *buf, int reg)
+int gdb_find_feature(CPUState *cpu, const char *name)
+{
+ GDBRegisterState *r;
+
+ for (guint i = 0; i < cpu->gdb_regs->len; i++) {
+ r = &g_array_index(cpu->gdb_regs, GDBRegisterState, i);
+ if (!strcmp(name, r->feature->name)) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+int gdb_find_feature_register(CPUState *cpu, int feature, const char *name)
+{
+ GDBRegisterState *r;
+
+ r = &g_array_index(cpu->gdb_regs, GDBRegisterState, feature);
+
+ for (int i = 0; i < r->feature->num_regs; i++) {
+ if (r->feature->regs[i] && !strcmp(name, r->feature->regs[i])) {
+ return r->base_reg + i;
+ }
+ }
+
+ return -1;
+}
+
+GArray *gdb_find_registers(CPUState *cpu, const char *reg_pattern)
+{
+ g_autoptr(GPatternSpec) pat = g_pattern_spec_new(reg_pattern);
+ 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 = &g_array_index(cpu->gdb_regs, GDBRegisterState,
f);
+ for (int i = 0; i < r->feature->num_regs; i++) {
+ const char *name = r->feature->regs[i];
+ if (name && g_pattern_match_string(pat, name)) {
+ 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
- Re: [PATCH 25/29] contrib/plugins: extend execlog to track register changes, (continued)
- [PATCH 28/29] plugins: disable lockstep plugin on windows, Alex Bennée, 2023/11/03
- [PATCH 19/29] hw/core/cpu: Remove gdb_get_dynamic_xml member, Alex Bennée, 2023/11/03
- [PATCH 29/29] plugins: allow plugins to be enabled on windows, Alex Bennée, 2023/11/03
- [PATCH 21/29] gdbstub: expose api to find registers,
Alex Bennée <=
- [PATCH 24/29] plugins: add an API to read registers, Alex Bennée, 2023/11/03
- [PATCH 27/29] plugins: make test/example plugins work on windows, Alex Bennée, 2023/11/03
- [PATCH 20/29] gdbstub: Add members to identify registers to GDBFeature, Alex Bennée, 2023/11/03
- [PATCH 18/29] gdbstub: Infer number of core registers from XML, Alex Bennée, 2023/11/03