summaryrefslogtreecommitdiffstats
path: root/cpukit/libdebugger/rtems-debugger-arm.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/libdebugger/rtems-debugger-arm.c')
-rw-r--r--cpukit/libdebugger/rtems-debugger-arm.c281
1 files changed, 197 insertions, 84 deletions
diff --git a/cpukit/libdebugger/rtems-debugger-arm.c b/cpukit/libdebugger/rtems-debugger-arm.c
index 722dd54924..c71af42a02 100644
--- a/cpukit/libdebugger/rtems-debugger-arm.c
+++ b/cpukit/libdebugger/rtems-debugger-arm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017 Chris Johns <chrisj@rtems.org>.
+ * Copyright (c) 2016-2019 Chris Johns <chrisj@rtems.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -116,18 +116,13 @@
#define RTEMS_DEBUGGER_NUMREGS 26
/*
- * Number of bytes per register.
+ * Number of bytes per type of register.
*/
-#define RTEMS_DEBUGGER_REGBYTES 4
+#define RTEMS_DEBUGGER_REG_BYTES 4
+#define RTEMS_DEBUGGER_FP_REG_BYTES 12
/*
- * Number of bytes of registers.
- */
-#define RTEMS_DEBUGGER_NUMREGBYTES \
- (RTEMS_DEBUGGER_NUMREGS * RTEMS_DEBUGGER_REGBYTES)
-
-/*
- * Debugger registers layout.
+ * Debugger registers layout. See arm-core.xml in GDB source.
*/
#define REG_R0 0
#define REG_R1 1
@@ -145,9 +140,61 @@
#define REG_SP 13
#define REG_LR 14
#define REG_PC 15
+#define REG_F0 16
+#define REG_F1 17
+#define REG_F2 18
+#define REG_F3 19
+#define REG_F4 20
+#define REG_F5 21
+#define REG_F6 22
+#define REG_F7 23
+#define REG_FPS 24
#define REG_CPSR 25
/**
+ * Register offset table with the total as the last entry.
+ *
+ * Check this table in gdb with the command:
+ *
+ * maint print registers
+ */
+static const size_t arm_reg_offsets[RTEMS_DEBUGGER_NUMREGS + 1] =
+{
+ 0, /* REG_R0 4 uint32_t */
+ 4, /* REG_R1 4 uint32_t */
+ 8, /* REG_R2 4 uint32_t */
+ 12, /* REG_R3 4 uint32_t */
+ 16, /* REG_R4 4 uint32_t */
+ 20, /* REG_R5 4 uint32_t */
+ 24, /* REG_R6 4 uint32_t */
+ 28, /* REG_R7 4 uint32_t */
+ 32, /* REG_R8 4 uint32_t */
+ 36, /* REG_R9 4 uint32_t */
+ 40, /* REG_R10 4 uint32_t */
+ 44, /* REG_R11 4 uint32_t */
+ 48, /* REG_R12 4 uint32_t */
+ 52, /* REG_SP 4 *1 */
+ 56, /* REG_LR 4 uint32_t */
+ 60, /* REG_PC 4 *1 */
+ 64, /* REG_F0 12 _arm_ext */
+ 76, /* REG_F1 12 _arm_ext */
+ 88, /* REG_F2 12 _arm_ext */
+ 100, /* REG_F3 12 _arm_ext */
+ 112, /* REG_F4 12 _arm_ext */
+ 124, /* REG_F5 12 _arm_ext */
+ 136, /* REG_F6 12 _arm_ext */
+ 148, /* REG_F7 12 _arm_ext */
+ 160, /* REG_FPS 4 uint32_t */
+ 164, /* REG_CPSR 4 uint32_t */
+ 168 /* total size */
+};
+
+/*
+ * Number of bytes of registers.
+ */
+#define RTEMS_DEBUGGER_NUMREGBYTES arm_reg_offsets[RTEMS_DEBUGGER_NUMREGS]
+
+/**
* The various status registers.
*/
#if defined(ARM_MULTILIB_ARCH_V4)
@@ -235,8 +282,13 @@ target_printk(const char* format, ...)
rtems_debugger_printk_unlock(&lock_context);
va_end(ap);
}
+#else
+#define target_printk(_fmt, ...)
+#define mode_labels(_m) NULL
+#endif
+
static const char*
-mode_label(int mode)
+arm_mode_label(int mode)
{
switch (mode) {
case 0x10:
@@ -260,10 +312,6 @@ mode_label(int mode)
}
return "---";
}
-#else
-#define target_printk(_fmt, ...)
-#define mode_labels(_m) NULL
-#endif
/*
* CP register access.
@@ -577,7 +625,7 @@ rtems_debugger_target_configure(rtems_debugger_target* target)
{
target->capabilities = (RTEMS_DEBUGGER_TARGET_CAP_SWBREAK);
target->reg_num = RTEMS_DEBUGGER_NUMREGS;
- target->reg_size = sizeof(uint32_t);
+ target->reg_offset = arm_reg_offsets;
target->breakpoint = &breakpoint[0];
target->breakpoint_size = sizeof(breakpoint);
return arm_debug_probe(target);
@@ -590,7 +638,7 @@ target_exception(CPU_Exception_frame* frame)
uint32_t ifsr = arm_cp15_get_instruction_fault_status();
#endif
- target_printk("[} frame = %08lx sig=%d vector=%x ifsr=%08lx pra=%08x\n",
+ target_printk("[} frame = %08" PRIx32 " sig=%d vector=%x ifsr=%08" PRIx32 " pra=%08x\n",
(uint32_t) frame,
rtems_debugger_target_exception_to_signal(frame),
frame->vector, ifsr, (intptr_t) frame->register_pc);
@@ -632,7 +680,7 @@ target_exception(CPU_Exception_frame* frame)
(FRAME_SR & (1 << 5)) != 0 ? 'T' : '-',
((FRAME_SR >> (25 - 5)) & (0x3 << 5)) | ((FRAME_SR >> 10) & 0x1f),
(FRAME_SR >> 16) & 0xf,
- FRAME_SR & 0x1f, mode_label(FRAME_SR & 0x1f));
+ FRAME_SR & 0x1f, arm_mode_label(FRAME_SR & 0x1f));
arm_debug_break_clear();
@@ -652,7 +700,7 @@ target_exception(CPU_Exception_frame* frame)
break;
}
- target_printk("[} resuming frame = %08lx PC = %08" PRIxPTR " CPSR = %08" PRIx32 "\n",
+ target_printk("[} resuming frame = %08" PRIx32 " PC = %08" PRIxPTR " CPSR = %08" PRIx32 "\n",
(uint32_t) frame, (intptr_t) frame->register_pc, FRAME_SR);
}
@@ -986,6 +1034,34 @@ rtems_debugger_target_set_vectors(void)
}
#endif
+static bool
+rtems_debugger_is_int_reg(size_t reg)
+{
+ const size_t size = arm_reg_offsets[reg + 1] - arm_reg_offsets[reg];
+ return size == RTEMS_DEBUGGER_REG_BYTES;
+}
+
+static void
+rtems_debugger_set_int_reg(rtems_debugger_thread* thread,
+ size_t reg,
+ const uint32_t value)
+{
+ const size_t offset = arm_reg_offsets[reg];
+ /*
+ * Use memcpy to avoid alignment issues.
+ */
+ memcpy(&thread->registers[offset], &value, sizeof(uint32_t));
+}
+
+static const uint32_t
+rtems_debugger_get_int_reg(rtems_debugger_thread* thread, size_t reg)
+{
+ const size_t offset = arm_reg_offsets[reg];
+ uint32_t value;
+ memcpy(&value, &thread->registers[offset], sizeof(uint32_t));
+ return value;
+}
+
int
rtems_debugger_target_enable(void)
{
@@ -1028,11 +1104,14 @@ rtems_debugger_target_read_regs(rtems_debugger_thread* thread)
if (!rtems_debugger_thread_flag(thread,
RTEMS_DEBUGGER_THREAD_FLAG_REG_VALID)) {
static const uint32_t good_address = (uint32_t) &good_address;
- uint32_t* regs = &thread->registers[0];
int i;
- for (i = 0; i < RTEMS_DEBUGGER_NUMREGS; ++i)
- regs[i] = (uint32_t) &good_address;
+ memset(&thread->registers[0], 0, RTEMS_DEBUGGER_NUMREGBYTES);
+
+ for (i = 0; i < RTEMS_DEBUGGER_NUMREGS; ++i) {
+ if (rtems_debugger_is_int_reg(i))
+ rtems_debugger_set_int_reg(thread, i, (uint32_t) &good_address);
+ }
if (thread->frame) {
CPU_Exception_frame* frame = thread->frame;
@@ -1050,23 +1129,23 @@ rtems_debugger_target_read_regs(rtems_debugger_thread* thread)
thread->flags = ~RTEMS_DEBUGGER_THREAD_FLAG_INTS_DISABLED;
}
- regs[REG_R0] = frame->register_r0;
- regs[REG_R1] = frame->register_r1;
- regs[REG_R2] = frame->register_r2;
- regs[REG_R3] = frame->register_r3;
- regs[REG_R4] = frame->register_r4;
- regs[REG_R5] = frame->register_r5;
- regs[REG_R6] = frame->register_r6;
- regs[REG_R7] = frame->register_r7;
- regs[REG_R8] = frame->register_r8;
- regs[REG_R9] = frame->register_r9;
- regs[REG_R10] = frame->register_r10;
- regs[REG_R11] = frame->register_r11;
- regs[REG_R12] = frame->register_r12;
- regs[REG_SP] = frame->register_sp;
- regs[REG_LR] = (uint32_t) frame->register_lr;
- regs[REG_PC] = (uint32_t) frame->register_pc;
- regs[REG_CPSR] = FRAME_SR;
+ rtems_debugger_set_int_reg(thread, REG_R0, frame->register_r0);
+ rtems_debugger_set_int_reg(thread, REG_R1, frame->register_r1);
+ rtems_debugger_set_int_reg(thread, REG_R2, frame->register_r2);
+ rtems_debugger_set_int_reg(thread, REG_R3, frame->register_r3);
+ rtems_debugger_set_int_reg(thread, REG_R4, frame->register_r4);
+ rtems_debugger_set_int_reg(thread, REG_R5, frame->register_r5);
+ rtems_debugger_set_int_reg(thread, REG_R6, frame->register_r6);
+ rtems_debugger_set_int_reg(thread, REG_R7, frame->register_r7);
+ rtems_debugger_set_int_reg(thread, REG_R8, frame->register_r8);
+ rtems_debugger_set_int_reg(thread, REG_R9, frame->register_r9);
+ rtems_debugger_set_int_reg(thread, REG_R10, frame->register_r10);
+ rtems_debugger_set_int_reg(thread, REG_R11, frame->register_r11);
+ rtems_debugger_set_int_reg(thread, REG_R12, frame->register_r12);
+ rtems_debugger_set_int_reg(thread, REG_SP, frame->register_sp);
+ rtems_debugger_set_int_reg(thread, REG_LR, (uint32_t) frame->register_lr);
+ rtems_debugger_set_int_reg(thread, REG_PC, (uint32_t) frame->register_pc);
+ rtems_debugger_set_int_reg(thread, REG_CPSR, FRAME_SR);
/*
* Get the signal from the frame.
*/
@@ -1074,29 +1153,29 @@ rtems_debugger_target_read_regs(rtems_debugger_thread* thread)
}
else {
#if defined(ARM_MULTILIB_ARCH_V4)
- regs[REG_R4] = thread->tcb->Registers.register_r4;
- regs[REG_R5] = thread->tcb->Registers.register_r5;
- regs[REG_R6] = thread->tcb->Registers.register_r6;
- regs[REG_R7] = thread->tcb->Registers.register_r7;
- regs[REG_R8] = thread->tcb->Registers.register_r8;
- regs[REG_R9] = thread->tcb->Registers.register_r9;
- regs[REG_R10] = thread->tcb->Registers.register_r10;
- regs[REG_R11] = thread->tcb->Registers.register_fp;
- regs[REG_LR] = (intptr_t) thread->tcb->Registers.register_lr;
- regs[REG_PC] = (intptr_t) thread->tcb->Registers.register_lr;
- regs[REG_SP] = (intptr_t) thread->tcb->Registers.register_sp;
+ rtems_debugger_set_int_reg(thread, REG_R4, thread->tcb->Registers.register_r4);
+ rtems_debugger_set_int_reg(thread, REG_R5, thread->tcb->Registers.register_r5);
+ rtems_debugger_set_int_reg(thread, REG_R6, thread->tcb->Registers.register_r6);
+ rtems_debugger_set_int_reg(thread, REG_R7, thread->tcb->Registers.register_r7);
+ rtems_debugger_set_int_reg(thread, REG_R8, thread->tcb->Registers.register_r8);
+ rtems_debugger_set_int_reg(thread, REG_R9, thread->tcb->Registers.register_r9);
+ rtems_debugger_set_int_reg(thread, REG_R10, thread->tcb->Registers.register_r10);
+ rtems_debugger_set_int_reg(thread, REG_R11, thread->tcb->Registers.register_fp);
+ rtems_debugger_set_int_reg(thread, REG_LR, (intptr_t) thread->tcb->Registers.register_lr);
+ rtems_debugger_set_int_reg(thread, REG_PC, (intptr_t) thread->tcb->Registers.register_lr);
+ rtems_debugger_set_int_reg(thread, REG_SP, (intptr_t) thread->tcb->Registers.register_sp);
#elif defined(ARM_MULTILIB_ARCH_V7M)
- regs[REG_R4] = thread->tcb->Registers.register_r4;
- regs[REG_R5] = thread->tcb->Registers.register_r5;
- regs[REG_R6] = thread->tcb->Registers.register_r6;
- regs[REG_R7] = thread->tcb->Registers.register_r7;
- regs[REG_R8] = thread->tcb->Registers.register_r8;
- regs[REG_R9] = thread->tcb->Registers.register_r9;
- regs[REG_R10] = thread->tcb->Registers.register_r10;
- regs[REG_R11] = thread->tcb->Registers.register_r11;
- regs[REG_LR] = (intptr_t) thread->tcb->Registers.register_lr;
- regs[REG_PC] = (intptr_t) thread->tcb->Registers.register_lr;
- regs[REG_SP] = (intptr_t) thread->tcb->Registers.register_sp;
+ rtems_debugger_set_int_reg(thread, REG_R4, thread->tcb->Registers.register_r4);
+ rtems_debugger_set_int_reg(thread, REG_R5, thread->tcb->Registers.register_r5);
+ rtems_debugger_set_int_reg(thread, REG_R6, thread->tcb->Registers.register_r6);
+ rtems_debugger_set_int_reg(thread, REG_R7, thread->tcb->Registers.register_r7);
+ rtems_debugger_set_int_reg(thread, REG_R8, thread->tcb->Registers.register_r8);
+ rtems_debugger_set_int_reg(thread, REG_R9, thread->tcb->Registers.register_r9);
+ rtems_debugger_set_int_reg(thread, REG_R10, thread->tcb->Registers.register_r10);
+ rtems_debugger_set_int_reg(thread, REG_R11, thread->tcb->Registers.register_r11);
+ rtems_debugger_set_int_reg(thread, REG_LR, (intptr_t) thread->tcb->Registers.register_lr);
+ rtems_debugger_set_int_reg(thread, REG_PC, (intptr_t) thread->tcb->Registers.register_lr);
+ rtems_debugger_set_int_reg(thread, REG_SP, (intptr_t) thread->tcb->Registers.register_sp);
#endif
/*
* Blocked threads have no signal.
@@ -1116,8 +1195,6 @@ rtems_debugger_target_write_regs(rtems_debugger_thread* thread)
{
if (rtems_debugger_thread_flag(thread,
RTEMS_DEBUGGER_THREAD_FLAG_REG_DIRTY)) {
- uint32_t* regs = &thread->registers[0];
-
/*
* Only write to debugger controlled exception threads. Do not touch the
* registers for threads blocked in the context switcher.
@@ -1125,23 +1202,23 @@ rtems_debugger_target_write_regs(rtems_debugger_thread* thread)
if (rtems_debugger_thread_flag(thread,
RTEMS_DEBUGGER_THREAD_FLAG_EXCEPTION)) {
CPU_Exception_frame* frame = thread->frame;
- frame->register_r0 = regs[REG_R0];
- frame->register_r1 = regs[REG_R1];
- frame->register_r2 = regs[REG_R2];
- frame->register_r3 = regs[REG_R3];
- frame->register_r4 = regs[REG_R4];
- frame->register_r5 = regs[REG_R5];
- frame->register_r6 = regs[REG_R6];
- frame->register_r7 = regs[REG_R7];
- frame->register_r8 = regs[REG_R8];
- frame->register_r9 = regs[REG_R9];
- frame->register_r10 = regs[REG_R10];
- frame->register_r11 = regs[REG_R11];
- frame->register_r12 = regs[REG_R12];
- frame->register_sp = regs[REG_SP];
- frame->register_lr = (void*) regs[REG_LR];
- frame->register_pc = (void*) regs[REG_PC];
- FRAME_SR = regs[REG_CPSR];
+ frame->register_r0 = rtems_debugger_get_int_reg(thread, REG_R0);
+ frame->register_r1 = rtems_debugger_get_int_reg(thread, REG_R1);
+ frame->register_r2 = rtems_debugger_get_int_reg(thread, REG_R2);
+ frame->register_r3 = rtems_debugger_get_int_reg(thread, REG_R3);
+ frame->register_r4 = rtems_debugger_get_int_reg(thread, REG_R4);
+ frame->register_r5 = rtems_debugger_get_int_reg(thread, REG_R5);
+ frame->register_r6 = rtems_debugger_get_int_reg(thread, REG_R6);
+ frame->register_r7 = rtems_debugger_get_int_reg(thread, REG_R7);
+ frame->register_r8 = rtems_debugger_get_int_reg(thread, REG_R8);
+ frame->register_r9 = rtems_debugger_get_int_reg(thread, REG_R9);
+ frame->register_r10 = rtems_debugger_get_int_reg(thread, REG_R10);
+ frame->register_r11 = rtems_debugger_get_int_reg(thread, REG_R11);
+ frame->register_r12 = rtems_debugger_get_int_reg(thread, REG_R12);
+ frame->register_sp = rtems_debugger_get_int_reg(thread, REG_SP);
+ frame->register_lr = (void*) rtems_debugger_get_int_reg(thread, REG_LR);
+ frame->register_pc = (void*) rtems_debugger_get_int_reg(thread, REG_PC);
+ FRAME_SR = rtems_debugger_get_int_reg(thread, REG_CPSR);
}
thread->flags &= ~RTEMS_DEBUGGER_THREAD_FLAG_REG_DIRTY;
}
@@ -1154,8 +1231,7 @@ rtems_debugger_target_reg_pc(rtems_debugger_thread* thread)
int r;
r = rtems_debugger_target_read_regs(thread);
if (r >= 0) {
- uint32_t* regs = &thread->registers[0];
- return regs[REG_PC];
+ return rtems_debugger_get_int_reg(thread, REG_PC);
}
return 0;
}
@@ -1172,8 +1248,7 @@ rtems_debugger_target_reg_sp(rtems_debugger_thread* thread)
int r;
r = rtems_debugger_target_read_regs(thread);
if (r >= 0) {
- uint32_t* regs = &thread->registers[0];
- return regs[REG_SP];
+ return rtems_debugger_get_int_reg(thread, REG_SP);
}
return 0;
}
@@ -1293,6 +1368,44 @@ rtems_debugger_target_exception_to_signal(CPU_Exception_frame* frame)
return sig;
}
+void
+rtems_debugger_target_exception_print(CPU_Exception_frame* frame)
+{
+ rtems_debugger_printf(" R0 = %08" PRIx32 " R1 = %08" PRIx32 \
+ " R2 = %08" PRIx32 " R3 = %08" PRIx32 "\n",
+ frame->register_r0, frame->register_r1,
+ frame->register_r2, frame->register_r3);
+ rtems_debugger_printf(" R4 = %08" PRIx32 " R5 = %08" PRIx32 \
+ " R6 = %08" PRIx32 " R7 = %08" PRIx32 "\n",
+ frame->register_r4, frame->register_r5,
+ frame->register_r6, frame->register_r7);
+ rtems_debugger_printf(" R8 = %08" PRIx32 " R9 = %08" PRIx32 \
+ " R10 = %08" PRIx32 " R11 = %08" PRIx32 "\n",
+ frame->register_r8, frame->register_r9,
+ frame->register_r10, frame->register_r11);
+ rtems_debugger_printf(" R12 = %08" PRIx32 " SP = %08" PRIx32 \
+ " LR = %08" PRIxPTR " PC = %08" PRIxPTR "\n", \
+ frame->register_r12, frame->register_sp,
+ (intptr_t) frame->register_lr, (intptr_t) frame->register_pc);
+ rtems_debugger_printf(" CPSR = %08" PRIx32 " %c%c%c%c%c%c%c%c%c%c%c" \
+ " GE:%" PRIx32 " IT:%02" PRIx32 " M:%" PRIx32 " %s\n",
+ FRAME_SR,
+ (FRAME_SR & (1 << 31)) != 0 ? 'N' : '-',
+ (FRAME_SR & (1 << 30)) != 0 ? 'Z' : '-',
+ (FRAME_SR & (1 << 29)) != 0 ? 'C' : '-',
+ (FRAME_SR & (1 << 28)) != 0 ? 'V' : '-',
+ (FRAME_SR & (1 << 27)) != 0 ? 'Q' : '-',
+ (FRAME_SR & (1 << 24)) != 0 ? 'J' : '-',
+ (FRAME_SR & (1 << 9)) != 0 ? 'E' : '-',
+ (FRAME_SR & (1 << 8)) != 0 ? 'A' : '-',
+ (FRAME_SR & (1 << 7)) != 0 ? 'I' : '-',
+ (FRAME_SR & (1 << 6)) != 0 ? 'F' : '-',
+ (FRAME_SR & (1 << 5)) != 0 ? 'T' : '-',
+ ((FRAME_SR >> (25 - 5)) & (0x3 << 5)) | ((FRAME_SR >> 10) & 0x1f),
+ (FRAME_SR >> 16) & 0xf,
+ FRAME_SR & 0x1f, arm_mode_label(FRAME_SR & 0x1f));
+}
+
int
rtems_debugger_target_hwbreak_insert(void)
{