aboutsummaryrefslogtreecommitdiff
path: root/target/arm/gdbstub.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/arm/gdbstub.c')
-rw-r--r--target/arm/gdbstub.c76
1 files changed, 76 insertions, 0 deletions
diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
index 04c1208..e80cfb4 100644
--- a/target/arm/gdbstub.c
+++ b/target/arm/gdbstub.c
@@ -22,6 +22,11 @@
#include "cpu.h"
#include "exec/gdbstub.h"
+typedef struct RegisterSysregXmlParam {
+ CPUState *cs;
+ GString *s;
+} RegisterSysregXmlParam;
+
/* Old gdb always expect FPA registers. Newer (xml-aware) gdb only expect
whatever the target description contains. Due to a historical mishap
the FPA registers appear in between core integer regs and the CPSR.
@@ -101,3 +106,74 @@ int arm_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
/* Unknown register. */
return 0;
}
+
+static void arm_gen_one_xml_reg_tag(GString *s, DynamicGDBXMLInfo *dyn_xml,
+ ARMCPRegInfo *ri, uint32_t ri_key,
+ int bitsize)
+{
+ g_string_append_printf(s, "<reg name=\"%s\"", ri->name);
+ g_string_append_printf(s, " bitsize=\"%d\"", bitsize);
+ g_string_append_printf(s, " group=\"cp_regs\"/>");
+ dyn_xml->num_cpregs++;
+ dyn_xml->cpregs_keys[dyn_xml->num_cpregs - 1] = ri_key;
+}
+
+static void arm_register_sysreg_for_xml(gpointer key, gpointer value,
+ gpointer p)
+{
+ uint32_t ri_key = *(uint32_t *)key;
+ ARMCPRegInfo *ri = value;
+ RegisterSysregXmlParam *param = (RegisterSysregXmlParam *)p;
+ GString *s = param->s;
+ ARMCPU *cpu = ARM_CPU(param->cs);
+ CPUARMState *env = &cpu->env;
+ DynamicGDBXMLInfo *dyn_xml = &cpu->dyn_xml;
+
+ if (!(ri->type & (ARM_CP_NO_RAW | ARM_CP_NO_GDB))) {
+ if (arm_feature(env, ARM_FEATURE_AARCH64)) {
+ if (ri->state == ARM_CP_STATE_AA64) {
+ arm_gen_one_xml_reg_tag(s , dyn_xml, ri, ri_key, 64);
+ }
+ } else {
+ if (ri->state == ARM_CP_STATE_AA32) {
+ if (!arm_feature(env, ARM_FEATURE_EL3) &&
+ (ri->secure & ARM_CP_SECSTATE_S)) {
+ return;
+ }
+ if (ri->type & ARM_CP_64BIT) {
+ arm_gen_one_xml_reg_tag(s , dyn_xml, ri, ri_key, 64);
+ } else {
+ arm_gen_one_xml_reg_tag(s , dyn_xml, ri, ri_key, 32);
+ }
+ }
+ }
+ }
+}
+
+int arm_gen_dynamic_xml(CPUState *cs)
+{
+ ARMCPU *cpu = ARM_CPU(cs);
+ GString *s = g_string_new(NULL);
+ RegisterSysregXmlParam param = {cs, s};
+
+ cpu->dyn_xml.num_cpregs = 0;
+ cpu->dyn_xml.cpregs_keys = g_malloc(sizeof(uint32_t *) *
+ g_hash_table_size(cpu->cp_regs));
+ g_string_printf(s, "<?xml version=\"1.0\"?>");
+ g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
+ g_string_append_printf(s, "<feature name=\"org.qemu.gdb.arm.sys.regs\">");
+ g_hash_table_foreach(cpu->cp_regs, arm_register_sysreg_for_xml, &param);
+ g_string_append_printf(s, "</feature>");
+ cpu->dyn_xml.desc = g_string_free(s, false);
+ return cpu->dyn_xml.num_cpregs;
+}
+
+const char *arm_gdb_get_dynamic_xml(CPUState *cs, const char *xmlname)
+{
+ ARMCPU *cpu = ARM_CPU(cs);
+
+ if (strcmp(xmlname, "system-registers.xml") == 0) {
+ return cpu->dyn_xml.desc;
+ }
+ return NULL;
+}