aarch64: enable aarch32 debugging with arm gdb 21/3821/4
authorMatthias Welwarsky <matthias.welwarsky@sysgo.com>
Thu, 20 Oct 2016 13:36:19 +0000 (15:36 +0200)
committerMatthias Welwarsky <matthias.welwarsky@sysgo.com>
Fri, 10 Feb 2017 13:18:35 +0000 (14:18 +0100)
When a PE is in Aarch32 state and gdb asks for a target description,
provide a register view compatible with the "org.gnu.gdb.arm.core"
feature. Only current-mode registers are exported, banked registers are
not visible.

Change-Id: I99a85d94831cf597fe8cff6a0a1818ce0a33613b
Signed-off-by: Matthias Welwarsky <matthias.welwarsky@sysgo.com>
src/target/aarch64.c
src/target/armv8.c

index 947c1ecfff9e6a3065b7e6c8d13b50a5082c2f12..d7d557dd179095ed4ae5e63cf95780f5efe303a6 100644 (file)
@@ -590,6 +590,7 @@ static int aarch64_internal_restart(struct target *target, bool slave_pe)
 
        /* registers are now invalid */
        register_cache_invalidate(arm->core_cache);
+       register_cache_invalidate(arm->core_cache->next);
 
        return ERROR_OK;
 }
index 089982e91f28ccc211515dc9b3aefaaabb87ecc0..a2a099d66434f2467dc8e6b7988a60db1b79dcbe 100644 (file)
@@ -1012,12 +1012,39 @@ static const struct {
        { ARMV8_SPSR_EL3, "SPSR_EL3", 32, ARMV8_64_EL3H, REG_TYPE_UINT32, "banked", "net.sourceforge.openocd.banked" },
 };
 
-#define ARMV8_NUM_REGS ARRAY_SIZE(armv8_regs)
+static const struct {
+       unsigned id;
+       const char *name;
+       unsigned bits;
+       enum arm_mode mode;
+       enum reg_type type;
+       const char *group;
+       const char *feature;
+} armv8_regs32[] = {
+       { ARMV8_R0,  "r0",  32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+       { ARMV8_R1,  "r1",  32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+       { ARMV8_R2,  "r2",  32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+       { ARMV8_R3,  "r3",  32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+       { ARMV8_R4,  "r4",  32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+       { ARMV8_R5,  "r5",  32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+       { ARMV8_R6,  "r6",  32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+       { ARMV8_R7,  "r7",  32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+       { ARMV8_R8,  "r8",  32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+       { ARMV8_R9,  "r9",  32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+       { ARMV8_R10, "r10", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+       { ARMV8_R11, "r11", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+       { ARMV8_R12, "r12", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+       { ARMV8_R13, "sp", 32, ARM_MODE_ANY, REG_TYPE_DATA_PTR, "general", "org.gnu.gdb.arm.core" },
+       { ARMV8_R14, "lr",  32, ARM_MODE_ANY, REG_TYPE_CODE_PTR, "general", "org.gnu.gdb.arm.core" },
+       { ARMV8_PC, "pc",   32, ARM_MODE_ANY, REG_TYPE_CODE_PTR, "general", "org.gnu.gdb.arm.core" },
+       { ARMV8_xPSR, "cpsr", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+};
 
+#define ARMV8_NUM_REGS ARRAY_SIZE(armv8_regs)
+#define ARMV8_NUM_REGS32 ARRAY_SIZE(armv8_regs32)
 
 static int armv8_get_core_reg(struct reg *reg)
 {
-       int retval;
        struct arm_reg *armv8_reg = reg->arch_info;
        struct target *target = armv8_reg->target;
        struct arm *arm = target_to_arm(target);
@@ -1025,9 +1052,7 @@ static int armv8_get_core_reg(struct reg *reg)
        if (target->state != TARGET_HALTED)
                return ERROR_TARGET_NOT_HALTED;
 
-       retval = arm->read_core_reg(target, reg, armv8_reg->num, arm->core_mode);
-
-       return retval;
+       return arm->read_core_reg(target, reg, armv8_reg->num, arm->core_mode);
 }
 
 static int armv8_set_core_reg(struct reg *reg, uint8_t *buf)
@@ -1057,25 +1082,83 @@ static const struct reg_arch_type armv8_reg_type = {
        .set = armv8_set_core_reg,
 };
 
+static int armv8_get_core_reg32(struct reg *reg)
+{
+       struct arm_reg *armv8_reg = reg->arch_info;
+       struct target *target = armv8_reg->target;
+       struct arm *arm = target_to_arm(target);
+       struct reg_cache *cache = arm->core_cache;
+       struct reg *reg64;
+       int retval;
+
+       LOG_DEBUG("reg.name:%s number:%i arm.num:%i value:0x%08" PRIx64,
+                       reg->name, reg->number, armv8_reg->num, buf_get_u64(reg->value, 0, 32));
+
+       /* get the corresponding Aarch64 register */
+       reg64 = cache->reg_list + armv8_reg->num;
+       if (reg64->valid) {
+               reg->valid = true;
+               return ERROR_OK;
+       }
+
+       retval = arm->read_core_reg(target, reg, armv8_reg->num, arm->core_mode);
+       if (retval == ERROR_OK)
+               reg->valid = reg64->valid;
+
+       return retval;
+}
+
+static int armv8_set_core_reg32(struct reg *reg, uint8_t *buf)
+{
+       struct arm_reg *armv8_reg = reg->arch_info;
+       struct target *target = armv8_reg->target;
+       struct arm *arm = target_to_arm(target);
+       struct reg_cache *cache = arm->core_cache;
+       struct reg *reg64 = cache->reg_list + armv8_reg->num;
+       uint32_t value = buf_get_u32(buf, 0, 32);
+
+       if (target->state != TARGET_HALTED)
+               return ERROR_TARGET_NOT_HALTED;
+
+       if (reg64 == arm->cpsr) {
+               armv8_set_cpsr(arm, value);
+       } else {
+               buf_set_u32(reg->value, 0, 32, value);
+               reg->valid = 1;
+               reg64->valid = 1;
+       }
+
+       reg64->dirty = 1;
+
+       return ERROR_OK;
+}
+
+static const struct reg_arch_type armv8_reg32_type = {
+       .get = armv8_get_core_reg32,
+       .set = armv8_set_core_reg32,
+};
+
 /** Builds cache of architecturally defined registers.  */
 struct reg_cache *armv8_build_reg_cache(struct target *target)
 {
        struct armv8_common *armv8 = target_to_armv8(target);
        struct arm *arm = &armv8->arm;
        int num_regs = ARMV8_NUM_REGS;
+       int num_regs32 = ARMV8_NUM_REGS32;
        struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
        struct reg_cache *cache = malloc(sizeof(struct reg_cache));
+       struct reg_cache *cache32 = malloc(sizeof(struct reg_cache));
        struct reg *reg_list = calloc(num_regs, sizeof(struct reg));
+       struct reg *reg_list32 = calloc(num_regs32, sizeof(struct reg));
        struct arm_reg *arch_info = calloc(num_regs, sizeof(struct arm_reg));
        struct reg_feature *feature;
        int i;
 
        /* Build the process context cache */
-       cache->name = "arm v8 registers";
-       cache->next = NULL;
+       cache->name = "Aarch64 registers";
+       cache->next = cache32;
        cache->reg_list = reg_list;
        cache->num_regs = num_regs;
-       (*cache_p) = cache;
 
        for (i = 0; i < num_regs; i++) {
                arch_info[i].num = armv8_regs[i].id;
@@ -1086,8 +1169,6 @@ struct reg_cache *armv8_build_reg_cache(struct target *target)
                reg_list[i].name = armv8_regs[i].name;
                reg_list[i].size = armv8_regs[i].bits;
                reg_list[i].value = calloc(1, 8);
-               reg_list[i].dirty = 0;
-               reg_list[i].valid = 0;
                reg_list[i].type = &armv8_reg_type;
                reg_list[i].arch_info = &arch_info[i];
 
@@ -1114,6 +1195,38 @@ struct reg_cache *armv8_build_reg_cache(struct target *target)
        arm->pc = reg_list + ARMV8_PC;
        arm->core_cache = cache;
 
+       /* shadow cache for ARM mode registers */
+       cache32->name = "Aarch32 registers";
+       cache32->next = NULL;
+       cache32->reg_list = reg_list32;
+       cache32->num_regs = num_regs32;
+
+       for (i = 0; i < num_regs32; i++) {
+               reg_list32[i].name = armv8_regs32[i].name;
+               reg_list32[i].size = armv8_regs32[i].bits;
+               reg_list32[i].value = &arch_info[armv8_regs32[i].id].value[0];
+               reg_list32[i].type = &armv8_reg32_type;
+               reg_list32[i].arch_info = &arch_info[armv8_regs32[i].id];
+               reg_list32[i].group = armv8_regs32[i].group;
+               reg_list32[i].number = i;
+               reg_list32[i].exist = true;
+               reg_list32[i].caller_save = true;
+
+               feature = calloc(1, sizeof(struct reg_feature));
+               if (feature) {
+                       feature->name = armv8_regs32[i].feature;
+                       reg_list32[i].feature = feature;
+               } else
+                       LOG_ERROR("unable to allocate feature list");
+
+               reg_list32[i].reg_data_type = calloc(1, sizeof(struct reg_data_type));
+               if (reg_list32[i].reg_data_type)
+                       reg_list32[i].reg_data_type->type = armv8_regs32[i].type;
+               else
+                       LOG_ERROR("unable to allocate reg type list");
+       }
+
+       (*cache_p) = cache;
        return cache;
 }
 
@@ -1143,27 +1256,50 @@ int armv8_get_gdb_reg_list(struct target *target,
        struct arm *arm = target_to_arm(target);
        int i;
 
-       switch (reg_class) {
-       case REG_CLASS_GENERAL:
-               *reg_list_size = ARMV8_ELR_EL1;
-               *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
+       if (arm->core_state == ARM_STATE_AARCH64) {
 
-               for (i = 0; i < *reg_list_size; i++)
-                               (*reg_list)[i] = armv8_reg_current(arm, i);
+               LOG_DEBUG("Creating Aarch64 register list");
 
-               return ERROR_OK;
-       case REG_CLASS_ALL:
-               *reg_list_size = ARMV8_LAST_REG;
-               *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
+               switch (reg_class) {
+               case REG_CLASS_GENERAL:
+                       *reg_list_size = ARMV8_ELR_EL1;
+                       *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
 
-               for (i = 0; i < *reg_list_size; i++)
-                               (*reg_list)[i] = armv8_reg_current(arm, i);
+                       for (i = 0; i < *reg_list_size; i++)
+                                       (*reg_list)[i] = armv8_reg_current(arm, i);
+                       return ERROR_OK;
 
-               return ERROR_OK;
+               case REG_CLASS_ALL:
+                       *reg_list_size = ARMV8_LAST_REG;
+                       *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
 
-       default:
-               LOG_ERROR("not a valid register class type in query.");
-               return ERROR_FAIL;
-               break;
+                       for (i = 0; i < *reg_list_size; i++)
+                                       (*reg_list)[i] = armv8_reg_current(arm, i);
+
+                       return ERROR_OK;
+
+               default:
+                       LOG_ERROR("not a valid register class type in query.");
+                       return ERROR_FAIL;
+               }
+       } else {
+               struct reg_cache *cache32 = arm->core_cache->next;
+
+               LOG_DEBUG("Creating Aarch32 register list");
+
+               switch (reg_class) {
+               case REG_CLASS_GENERAL:
+               case REG_CLASS_ALL:
+                       *reg_list_size = cache32->num_regs;
+                       *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
+
+                       for (i = 0; i < *reg_list_size; i++)
+                               (*reg_list)[i] = cache32->reg_list + i;
+
+                       return ERROR_OK;
+               default:
+                       LOG_ERROR("not a valid register class type in query.");
+                       return ERROR_FAIL;
+               }
        }
 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)