qemu/target/arm/gdbstub.c
<<
>>
Prefs
   1/*
   2 * ARM gdb server stub
   3 *
   4 * Copyright (c) 2003-2005 Fabrice Bellard
   5 * Copyright (c) 2013 SUSE LINUX Products GmbH
   6 *
   7 * This library is free software; you can redistribute it and/or
   8 * modify it under the terms of the GNU Lesser General Public
   9 * License as published by the Free Software Foundation; either
  10 * version 2 of the License, or (at your option) any later version.
  11 *
  12 * This library is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15 * Lesser General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU Lesser General Public
  18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  19 */
  20#include "qemu/osdep.h"
  21#include "cpu.h"
  22#include "exec/gdbstub.h"
  23
  24typedef struct RegisterSysregXmlParam {
  25    CPUState *cs;
  26    GString *s;
  27} RegisterSysregXmlParam;
  28
  29/* Old gdb always expect FPA registers.  Newer (xml-aware) gdb only expect
  30   whatever the target description contains.  Due to a historical mishap
  31   the FPA registers appear in between core integer regs and the CPSR.
  32   We hack round this by giving the FPA regs zero size when talking to a
  33   newer gdb.  */
  34
  35int arm_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
  36{
  37    ARMCPU *cpu = ARM_CPU(cs);
  38    CPUARMState *env = &cpu->env;
  39
  40    if (n < 16) {
  41        /* Core integer register.  */
  42        return gdb_get_reg32(mem_buf, env->regs[n]);
  43    }
  44    if (n < 24) {
  45        /* FPA registers.  */
  46        if (gdb_has_xml) {
  47            return 0;
  48        }
  49        memset(mem_buf, 0, 12);
  50        return 12;
  51    }
  52    switch (n) {
  53    case 24:
  54        /* FPA status register.  */
  55        if (gdb_has_xml) {
  56            return 0;
  57        }
  58        return gdb_get_reg32(mem_buf, 0);
  59    case 25:
  60        /* CPSR */
  61        return gdb_get_reg32(mem_buf, cpsr_read(env));
  62    }
  63    /* Unknown register.  */
  64    return 0;
  65}
  66
  67int arm_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
  68{
  69    ARMCPU *cpu = ARM_CPU(cs);
  70    CPUARMState *env = &cpu->env;
  71    uint32_t tmp;
  72
  73    tmp = ldl_p(mem_buf);
  74
  75    /* Mask out low bit of PC to workaround gdb bugs.  This will probably
  76       cause problems if we ever implement the Jazelle DBX extensions.  */
  77    if (n == 15) {
  78        tmp &= ~1;
  79    }
  80
  81    if (n < 16) {
  82        /* Core integer register.  */
  83        env->regs[n] = tmp;
  84        return 4;
  85    }
  86    if (n < 24) { /* 16-23 */
  87        /* FPA registers (ignored).  */
  88        if (gdb_has_xml) {
  89            return 0;
  90        }
  91        return 12;
  92    }
  93    switch (n) {
  94    case 24:
  95        /* FPA status register (ignored).  */
  96        if (gdb_has_xml) {
  97            return 0;
  98        }
  99        return 4;
 100    case 25:
 101        /* CPSR */
 102        cpsr_write(env, tmp, 0xffffffff, CPSRWriteByGDBStub);
 103        return 4;
 104    }
 105    /* Unknown register.  */
 106    return 0;
 107}
 108
 109static void arm_gen_one_xml_reg_tag(GString *s, DynamicGDBXMLInfo *dyn_xml,
 110                                    ARMCPRegInfo *ri, uint32_t ri_key,
 111                                    int bitsize)
 112{
 113    g_string_append_printf(s, "<reg name=\"%s\"", ri->name);
 114    g_string_append_printf(s, " bitsize=\"%d\"", bitsize);
 115    g_string_append_printf(s, " group=\"cp_regs\"/>");
 116    dyn_xml->num_cpregs++;
 117    dyn_xml->cpregs_keys[dyn_xml->num_cpregs - 1] = ri_key;
 118}
 119
 120static void arm_register_sysreg_for_xml(gpointer key, gpointer value,
 121                                        gpointer p)
 122{
 123    uint32_t ri_key = *(uint32_t *)key;
 124    ARMCPRegInfo *ri = value;
 125    RegisterSysregXmlParam *param = (RegisterSysregXmlParam *)p;
 126    GString *s = param->s;
 127    ARMCPU *cpu = ARM_CPU(param->cs);
 128    CPUARMState *env = &cpu->env;
 129    DynamicGDBXMLInfo *dyn_xml = &cpu->dyn_xml;
 130
 131    if (!(ri->type & (ARM_CP_NO_RAW | ARM_CP_NO_GDB))) {
 132        if (arm_feature(env, ARM_FEATURE_AARCH64)) {
 133            if (ri->state == ARM_CP_STATE_AA64) {
 134                arm_gen_one_xml_reg_tag(s , dyn_xml, ri, ri_key, 64);
 135            }
 136        } else {
 137            if (ri->state == ARM_CP_STATE_AA32) {
 138                if (!arm_feature(env, ARM_FEATURE_EL3) &&
 139                    (ri->secure & ARM_CP_SECSTATE_S)) {
 140                    return;
 141                }
 142                if (ri->type & ARM_CP_64BIT) {
 143                    arm_gen_one_xml_reg_tag(s , dyn_xml, ri, ri_key, 64);
 144                } else {
 145                    arm_gen_one_xml_reg_tag(s , dyn_xml, ri, ri_key, 32);
 146                }
 147            }
 148        }
 149    }
 150}
 151
 152int arm_gen_dynamic_xml(CPUState *cs)
 153{
 154    ARMCPU *cpu = ARM_CPU(cs);
 155    GString *s = g_string_new(NULL);
 156    RegisterSysregXmlParam param = {cs, s};
 157
 158    cpu->dyn_xml.num_cpregs = 0;
 159    cpu->dyn_xml.cpregs_keys = g_new(uint32_t, g_hash_table_size(cpu->cp_regs));
 160    g_string_printf(s, "<?xml version=\"1.0\"?>");
 161    g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
 162    g_string_append_printf(s, "<feature name=\"org.qemu.gdb.arm.sys.regs\">");
 163    g_hash_table_foreach(cpu->cp_regs, arm_register_sysreg_for_xml, &param);
 164    g_string_append_printf(s, "</feature>");
 165    cpu->dyn_xml.desc = g_string_free(s, false);
 166    return cpu->dyn_xml.num_cpregs;
 167}
 168
 169const char *arm_gdb_get_dynamic_xml(CPUState *cs, const char *xmlname)
 170{
 171    ARMCPU *cpu = ARM_CPU(cs);
 172
 173    if (strcmp(xmlname, "system-registers.xml") == 0) {
 174        return cpu->dyn_xml.desc;
 175    }
 176    return NULL;
 177}
 178