Signed-off-by: Richard Henderson <richard.hender...@linaro.org> --- target/arm/internals.h | 7 +++++-- target/arm/cpu.c | 38 ++++++++++++++++++++++++++++++++++++++ target/arm/cpu64.c | 25 +++++++++++++++++++++++++ target/arm/tcg/cpu-v7m.c | 2 ++ 4 files changed, 70 insertions(+), 2 deletions(-)
diff --git a/target/arm/internals.h b/target/arm/internals.h index dc53d86249..fe28937515 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -358,11 +358,14 @@ void init_cpreg_list(ARMCPU *cpu); void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu); void arm_translate_init(void); +#ifdef CONFIG_TCG void arm_restore_state_to_opc(CPUState *cs, const TranslationBlock *tb, const uint64_t *data); - -#ifdef CONFIG_TCG +bool arm_plugin_need_unwind_for_reg(CPUState *cs, int reg); +int arm_plugin_unwind_read_reg(CPUState *cs, GByteArray *buf, int reg, + const TranslationBlock *tb, + const uint64_t *data); void arm_cpu_synchronize_from_tb(CPUState *cs, const TranslationBlock *tb); bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request); #endif /* CONFIG_TCG */ diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 3cd4711064..e8ac3da351 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -29,6 +29,7 @@ #include "cpu.h" #ifdef CONFIG_TCG #include "hw/core/tcg-cpu-ops.h" +#include "gdbstub/helpers.h" #endif /* CONFIG_TCG */ #include "internals.h" #include "cpu-features.h" @@ -120,6 +121,41 @@ void arm_restore_state_to_opc(CPUState *cs, env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT; } } + +bool arm_plugin_need_unwind_for_reg(CPUState *cs, int reg) +{ + return reg == 15 || reg == 25; /* pc (r15) or cpsr */ +} + +int arm_plugin_unwind_read_reg(CPUState *cs, GByteArray *buf, int reg, + const TranslationBlock *tb, + const uint64_t *data) +{ + CPUARMState *env = cpu_env(cs); + uint32_t val, condexec; + + switch (reg) { + case 15: /* PC */ + val = data[0]; + if (tb_cflags(tb) & CF_PCREL) { + val |= env->regs[15] & TARGET_PAGE_MASK; + } + break; + case 25: /* CPSR, or XPSR for M-profile */ + if (arm_feature(env, ARM_FEATURE_M)) { + val = xpsr_read(env); + } else { + val = cpsr_read(env); + } + condexec = data[1] & 0xff; + val = (val & ~(3 << 25)) | ((condexec & 3) << 25); + val = (val & ~(0xfc << 8)) | ((condexec & 0xfc) << 8); + break; + default: + g_assert_not_reached(); + } + return gdb_get_reg32(buf, val); +} #endif /* CONFIG_TCG */ /* @@ -2657,6 +2693,8 @@ static const TCGCPUOps arm_tcg_ops = { .synchronize_from_tb = arm_cpu_synchronize_from_tb, .debug_excp_handler = arm_debug_excp_handler, .restore_state_to_opc = arm_restore_state_to_opc, + .plugin_need_unwind_for_reg = arm_plugin_need_unwind_for_reg, + .plugin_unwind_read_reg = arm_plugin_unwind_read_reg, #ifdef CONFIG_USER_ONLY .record_sigsegv = arm_cpu_record_sigsegv, diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c index 7ba80099af..1595be5d8f 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c @@ -33,6 +33,8 @@ #include "hw/qdev-properties.h" #ifdef CONFIG_TCG #include "hw/core/tcg-cpu-ops.h" +#include "exec/translation-block.h" +#include "gdbstub/helpers.h" #endif #include "internals.h" #include "cpu-features.h" @@ -797,11 +799,34 @@ static const gchar *aarch64_gdb_arch_name(CPUState *cs) } #ifdef CONFIG_TCG +static bool aarch64_plugin_need_unwind_for_reg(CPUState *cs, int reg) +{ + return reg == 32; /* pc */ +} + +static int aarch64_plugin_unwind_read_reg(CPUState *cs, GByteArray *buf, + int reg, const TranslationBlock *tb, + const uint64_t *data) +{ + CPUARMState *env = cpu_env(cs); + uint64_t val; + + assert(reg == 32); + + val = data[0]; + if (tb_cflags(tb) & CF_PCREL) { + val |= env->pc & TARGET_PAGE_MASK; + } + return gdb_get_reg64(buf, val); +} + static const TCGCPUOps aarch64_tcg_ops = { .initialize = arm_translate_init, .synchronize_from_tb = arm_cpu_synchronize_from_tb, .debug_excp_handler = arm_debug_excp_handler, .restore_state_to_opc = arm_restore_state_to_opc, + .plugin_need_unwind_for_reg = aarch64_plugin_need_unwind_for_reg, + .plugin_unwind_read_reg = aarch64_plugin_unwind_read_reg, #ifdef CONFIG_USER_ONLY .record_sigsegv = arm_cpu_record_sigsegv, diff --git a/target/arm/tcg/cpu-v7m.c b/target/arm/tcg/cpu-v7m.c index c059c681e9..47e44f70c7 100644 --- a/target/arm/tcg/cpu-v7m.c +++ b/target/arm/tcg/cpu-v7m.c @@ -237,6 +237,8 @@ static const TCGCPUOps arm_v7m_tcg_ops = { .synchronize_from_tb = arm_cpu_synchronize_from_tb, .debug_excp_handler = arm_debug_excp_handler, .restore_state_to_opc = arm_restore_state_to_opc, + .plugin_need_unwind_for_reg = arm_plugin_need_unwind_for_reg, + .plugin_unwind_read_reg = arm_plugin_unwind_read_reg, #ifdef CONFIG_USER_ONLY .record_sigsegv = arm_cpu_record_sigsegv, -- 2.34.1