forked from Imagelibrary/rtems
libdebugger: Use an offset table to format GDB g packets.
Adding support for a register offset table lets FPU registers be supported if added to the backend. Closes #3733.
This commit is contained in:
@@ -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.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -176,6 +176,11 @@ extern void rtems_debugger_unlock(void);
|
|||||||
*/
|
*/
|
||||||
extern bool rtems_debugger_server_running(void);
|
extern bool rtems_debugger_server_running(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signel a server crash.
|
||||||
|
*/
|
||||||
|
extern void rtems_debugger_server_crash(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the remote handle from the debugger.
|
* Get the remote handle from the debugger.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -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.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -116,18 +116,13 @@
|
|||||||
#define RTEMS_DEBUGGER_NUMREGS 26
|
#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.
|
* Debugger registers layout. See arm-core.xml in GDB source.
|
||||||
*/
|
|
||||||
#define RTEMS_DEBUGGER_NUMREGBYTES \
|
|
||||||
(RTEMS_DEBUGGER_NUMREGS * RTEMS_DEBUGGER_REGBYTES)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Debugger registers layout.
|
|
||||||
*/
|
*/
|
||||||
#define REG_R0 0
|
#define REG_R0 0
|
||||||
#define REG_R1 1
|
#define REG_R1 1
|
||||||
@@ -145,8 +140,60 @@
|
|||||||
#define REG_SP 13
|
#define REG_SP 13
|
||||||
#define REG_LR 14
|
#define REG_LR 14
|
||||||
#define REG_PC 15
|
#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
|
#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.
|
* The various status registers.
|
||||||
*/
|
*/
|
||||||
@@ -235,8 +282,13 @@ target_printk(const char* format, ...)
|
|||||||
rtems_debugger_printk_unlock(&lock_context);
|
rtems_debugger_printk_unlock(&lock_context);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
#define target_printk(_fmt, ...)
|
||||||
|
#define mode_labels(_m) NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
static const char*
|
static const char*
|
||||||
mode_label(int mode)
|
arm_mode_label(int mode)
|
||||||
{
|
{
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case 0x10:
|
case 0x10:
|
||||||
@@ -260,10 +312,6 @@ mode_label(int mode)
|
|||||||
}
|
}
|
||||||
return "---";
|
return "---";
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
#define target_printk(_fmt, ...)
|
|
||||||
#define mode_labels(_m) NULL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CP register access.
|
* CP register access.
|
||||||
@@ -577,7 +625,7 @@ rtems_debugger_target_configure(rtems_debugger_target* target)
|
|||||||
{
|
{
|
||||||
target->capabilities = (RTEMS_DEBUGGER_TARGET_CAP_SWBREAK);
|
target->capabilities = (RTEMS_DEBUGGER_TARGET_CAP_SWBREAK);
|
||||||
target->reg_num = RTEMS_DEBUGGER_NUMREGS;
|
target->reg_num = RTEMS_DEBUGGER_NUMREGS;
|
||||||
target->reg_size = sizeof(uint32_t);
|
target->reg_offset = arm_reg_offsets;
|
||||||
target->breakpoint = &breakpoint[0];
|
target->breakpoint = &breakpoint[0];
|
||||||
target->breakpoint_size = sizeof(breakpoint);
|
target->breakpoint_size = sizeof(breakpoint);
|
||||||
return arm_debug_probe(target);
|
return arm_debug_probe(target);
|
||||||
@@ -590,7 +638,7 @@ target_exception(CPU_Exception_frame* frame)
|
|||||||
uint32_t ifsr = arm_cp15_get_instruction_fault_status();
|
uint32_t ifsr = arm_cp15_get_instruction_fault_status();
|
||||||
#endif
|
#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,
|
(uint32_t) frame,
|
||||||
rtems_debugger_target_exception_to_signal(frame),
|
rtems_debugger_target_exception_to_signal(frame),
|
||||||
frame->vector, ifsr, (intptr_t) frame->register_pc);
|
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 & (1 << 5)) != 0 ? 'T' : '-',
|
||||||
((FRAME_SR >> (25 - 5)) & (0x3 << 5)) | ((FRAME_SR >> 10) & 0x1f),
|
((FRAME_SR >> (25 - 5)) & (0x3 << 5)) | ((FRAME_SR >> 10) & 0x1f),
|
||||||
(FRAME_SR >> 16) & 0xf,
|
(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();
|
arm_debug_break_clear();
|
||||||
|
|
||||||
@@ -652,7 +700,7 @@ target_exception(CPU_Exception_frame* frame)
|
|||||||
break;
|
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);
|
(uint32_t) frame, (intptr_t) frame->register_pc, FRAME_SR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -986,6 +1034,34 @@ rtems_debugger_target_set_vectors(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#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
|
int
|
||||||
rtems_debugger_target_enable(void)
|
rtems_debugger_target_enable(void)
|
||||||
{
|
{
|
||||||
@@ -1028,11 +1104,14 @@ rtems_debugger_target_read_regs(rtems_debugger_thread* thread)
|
|||||||
if (!rtems_debugger_thread_flag(thread,
|
if (!rtems_debugger_thread_flag(thread,
|
||||||
RTEMS_DEBUGGER_THREAD_FLAG_REG_VALID)) {
|
RTEMS_DEBUGGER_THREAD_FLAG_REG_VALID)) {
|
||||||
static const uint32_t good_address = (uint32_t) &good_address;
|
static const uint32_t good_address = (uint32_t) &good_address;
|
||||||
uint32_t* regs = &thread->registers[0];
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < RTEMS_DEBUGGER_NUMREGS; ++i)
|
memset(&thread->registers[0], 0, RTEMS_DEBUGGER_NUMREGBYTES);
|
||||||
regs[i] = (uint32_t) &good_address;
|
|
||||||
|
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) {
|
if (thread->frame) {
|
||||||
CPU_Exception_frame* frame = 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;
|
thread->flags = ~RTEMS_DEBUGGER_THREAD_FLAG_INTS_DISABLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
regs[REG_R0] = frame->register_r0;
|
rtems_debugger_set_int_reg(thread, REG_R0, frame->register_r0);
|
||||||
regs[REG_R1] = frame->register_r1;
|
rtems_debugger_set_int_reg(thread, REG_R1, frame->register_r1);
|
||||||
regs[REG_R2] = frame->register_r2;
|
rtems_debugger_set_int_reg(thread, REG_R2, frame->register_r2);
|
||||||
regs[REG_R3] = frame->register_r3;
|
rtems_debugger_set_int_reg(thread, REG_R3, frame->register_r3);
|
||||||
regs[REG_R4] = frame->register_r4;
|
rtems_debugger_set_int_reg(thread, REG_R4, frame->register_r4);
|
||||||
regs[REG_R5] = frame->register_r5;
|
rtems_debugger_set_int_reg(thread, REG_R5, frame->register_r5);
|
||||||
regs[REG_R6] = frame->register_r6;
|
rtems_debugger_set_int_reg(thread, REG_R6, frame->register_r6);
|
||||||
regs[REG_R7] = frame->register_r7;
|
rtems_debugger_set_int_reg(thread, REG_R7, frame->register_r7);
|
||||||
regs[REG_R8] = frame->register_r8;
|
rtems_debugger_set_int_reg(thread, REG_R8, frame->register_r8);
|
||||||
regs[REG_R9] = frame->register_r9;
|
rtems_debugger_set_int_reg(thread, REG_R9, frame->register_r9);
|
||||||
regs[REG_R10] = frame->register_r10;
|
rtems_debugger_set_int_reg(thread, REG_R10, frame->register_r10);
|
||||||
regs[REG_R11] = frame->register_r11;
|
rtems_debugger_set_int_reg(thread, REG_R11, frame->register_r11);
|
||||||
regs[REG_R12] = frame->register_r12;
|
rtems_debugger_set_int_reg(thread, REG_R12, frame->register_r12);
|
||||||
regs[REG_SP] = frame->register_sp;
|
rtems_debugger_set_int_reg(thread, REG_SP, frame->register_sp);
|
||||||
regs[REG_LR] = (uint32_t) frame->register_lr;
|
rtems_debugger_set_int_reg(thread, REG_LR, (uint32_t) frame->register_lr);
|
||||||
regs[REG_PC] = (uint32_t) frame->register_pc;
|
rtems_debugger_set_int_reg(thread, REG_PC, (uint32_t) frame->register_pc);
|
||||||
regs[REG_CPSR] = FRAME_SR;
|
rtems_debugger_set_int_reg(thread, REG_CPSR, FRAME_SR);
|
||||||
/*
|
/*
|
||||||
* Get the signal from the frame.
|
* Get the signal from the frame.
|
||||||
*/
|
*/
|
||||||
@@ -1074,29 +1153,29 @@ rtems_debugger_target_read_regs(rtems_debugger_thread* thread)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
#if defined(ARM_MULTILIB_ARCH_V4)
|
#if defined(ARM_MULTILIB_ARCH_V4)
|
||||||
regs[REG_R4] = thread->tcb->Registers.register_r4;
|
rtems_debugger_set_int_reg(thread, REG_R4, thread->tcb->Registers.register_r4);
|
||||||
regs[REG_R5] = thread->tcb->Registers.register_r5;
|
rtems_debugger_set_int_reg(thread, REG_R5, thread->tcb->Registers.register_r5);
|
||||||
regs[REG_R6] = thread->tcb->Registers.register_r6;
|
rtems_debugger_set_int_reg(thread, REG_R6, thread->tcb->Registers.register_r6);
|
||||||
regs[REG_R7] = thread->tcb->Registers.register_r7;
|
rtems_debugger_set_int_reg(thread, REG_R7, thread->tcb->Registers.register_r7);
|
||||||
regs[REG_R8] = thread->tcb->Registers.register_r8;
|
rtems_debugger_set_int_reg(thread, REG_R8, thread->tcb->Registers.register_r8);
|
||||||
regs[REG_R9] = thread->tcb->Registers.register_r9;
|
rtems_debugger_set_int_reg(thread, REG_R9, thread->tcb->Registers.register_r9);
|
||||||
regs[REG_R10] = thread->tcb->Registers.register_r10;
|
rtems_debugger_set_int_reg(thread, REG_R10, thread->tcb->Registers.register_r10);
|
||||||
regs[REG_R11] = thread->tcb->Registers.register_fp;
|
rtems_debugger_set_int_reg(thread, REG_R11, thread->tcb->Registers.register_fp);
|
||||||
regs[REG_LR] = (intptr_t) thread->tcb->Registers.register_lr;
|
rtems_debugger_set_int_reg(thread, REG_LR, (intptr_t) thread->tcb->Registers.register_lr);
|
||||||
regs[REG_PC] = (intptr_t) thread->tcb->Registers.register_lr;
|
rtems_debugger_set_int_reg(thread, 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_SP, (intptr_t) thread->tcb->Registers.register_sp);
|
||||||
#elif defined(ARM_MULTILIB_ARCH_V7M)
|
#elif defined(ARM_MULTILIB_ARCH_V7M)
|
||||||
regs[REG_R4] = thread->tcb->Registers.register_r4;
|
rtems_debugger_set_int_reg(thread, REG_R4, thread->tcb->Registers.register_r4);
|
||||||
regs[REG_R5] = thread->tcb->Registers.register_r5;
|
rtems_debugger_set_int_reg(thread, REG_R5, thread->tcb->Registers.register_r5);
|
||||||
regs[REG_R6] = thread->tcb->Registers.register_r6;
|
rtems_debugger_set_int_reg(thread, REG_R6, thread->tcb->Registers.register_r6);
|
||||||
regs[REG_R7] = thread->tcb->Registers.register_r7;
|
rtems_debugger_set_int_reg(thread, REG_R7, thread->tcb->Registers.register_r7);
|
||||||
regs[REG_R8] = thread->tcb->Registers.register_r8;
|
rtems_debugger_set_int_reg(thread, REG_R8, thread->tcb->Registers.register_r8);
|
||||||
regs[REG_R9] = thread->tcb->Registers.register_r9;
|
rtems_debugger_set_int_reg(thread, REG_R9, thread->tcb->Registers.register_r9);
|
||||||
regs[REG_R10] = thread->tcb->Registers.register_r10;
|
rtems_debugger_set_int_reg(thread, REG_R10, thread->tcb->Registers.register_r10);
|
||||||
regs[REG_R11] = thread->tcb->Registers.register_r11;
|
rtems_debugger_set_int_reg(thread, REG_R11, thread->tcb->Registers.register_r11);
|
||||||
regs[REG_LR] = (intptr_t) thread->tcb->Registers.register_lr;
|
rtems_debugger_set_int_reg(thread, REG_LR, (intptr_t) thread->tcb->Registers.register_lr);
|
||||||
regs[REG_PC] = (intptr_t) thread->tcb->Registers.register_lr;
|
rtems_debugger_set_int_reg(thread, 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_SP, (intptr_t) thread->tcb->Registers.register_sp);
|
||||||
#endif
|
#endif
|
||||||
/*
|
/*
|
||||||
* Blocked threads have no signal.
|
* Blocked threads have no signal.
|
||||||
@@ -1116,8 +1195,6 @@ rtems_debugger_target_write_regs(rtems_debugger_thread* thread)
|
|||||||
{
|
{
|
||||||
if (rtems_debugger_thread_flag(thread,
|
if (rtems_debugger_thread_flag(thread,
|
||||||
RTEMS_DEBUGGER_THREAD_FLAG_REG_DIRTY)) {
|
RTEMS_DEBUGGER_THREAD_FLAG_REG_DIRTY)) {
|
||||||
uint32_t* regs = &thread->registers[0];
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Only write to debugger controlled exception threads. Do not touch the
|
* Only write to debugger controlled exception threads. Do not touch the
|
||||||
* registers for threads blocked in the context switcher.
|
* 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,
|
if (rtems_debugger_thread_flag(thread,
|
||||||
RTEMS_DEBUGGER_THREAD_FLAG_EXCEPTION)) {
|
RTEMS_DEBUGGER_THREAD_FLAG_EXCEPTION)) {
|
||||||
CPU_Exception_frame* frame = thread->frame;
|
CPU_Exception_frame* frame = thread->frame;
|
||||||
frame->register_r0 = regs[REG_R0];
|
frame->register_r0 = rtems_debugger_get_int_reg(thread, REG_R0);
|
||||||
frame->register_r1 = regs[REG_R1];
|
frame->register_r1 = rtems_debugger_get_int_reg(thread, REG_R1);
|
||||||
frame->register_r2 = regs[REG_R2];
|
frame->register_r2 = rtems_debugger_get_int_reg(thread, REG_R2);
|
||||||
frame->register_r3 = regs[REG_R3];
|
frame->register_r3 = rtems_debugger_get_int_reg(thread, REG_R3);
|
||||||
frame->register_r4 = regs[REG_R4];
|
frame->register_r4 = rtems_debugger_get_int_reg(thread, REG_R4);
|
||||||
frame->register_r5 = regs[REG_R5];
|
frame->register_r5 = rtems_debugger_get_int_reg(thread, REG_R5);
|
||||||
frame->register_r6 = regs[REG_R6];
|
frame->register_r6 = rtems_debugger_get_int_reg(thread, REG_R6);
|
||||||
frame->register_r7 = regs[REG_R7];
|
frame->register_r7 = rtems_debugger_get_int_reg(thread, REG_R7);
|
||||||
frame->register_r8 = regs[REG_R8];
|
frame->register_r8 = rtems_debugger_get_int_reg(thread, REG_R8);
|
||||||
frame->register_r9 = regs[REG_R9];
|
frame->register_r9 = rtems_debugger_get_int_reg(thread, REG_R9);
|
||||||
frame->register_r10 = regs[REG_R10];
|
frame->register_r10 = rtems_debugger_get_int_reg(thread, REG_R10);
|
||||||
frame->register_r11 = regs[REG_R11];
|
frame->register_r11 = rtems_debugger_get_int_reg(thread, REG_R11);
|
||||||
frame->register_r12 = regs[REG_R12];
|
frame->register_r12 = rtems_debugger_get_int_reg(thread, REG_R12);
|
||||||
frame->register_sp = regs[REG_SP];
|
frame->register_sp = rtems_debugger_get_int_reg(thread, REG_SP);
|
||||||
frame->register_lr = (void*) regs[REG_LR];
|
frame->register_lr = (void*) rtems_debugger_get_int_reg(thread, REG_LR);
|
||||||
frame->register_pc = (void*) regs[REG_PC];
|
frame->register_pc = (void*) rtems_debugger_get_int_reg(thread, REG_PC);
|
||||||
FRAME_SR = regs[REG_CPSR];
|
FRAME_SR = rtems_debugger_get_int_reg(thread, REG_CPSR);
|
||||||
}
|
}
|
||||||
thread->flags &= ~RTEMS_DEBUGGER_THREAD_FLAG_REG_DIRTY;
|
thread->flags &= ~RTEMS_DEBUGGER_THREAD_FLAG_REG_DIRTY;
|
||||||
}
|
}
|
||||||
@@ -1154,8 +1231,7 @@ rtems_debugger_target_reg_pc(rtems_debugger_thread* thread)
|
|||||||
int r;
|
int r;
|
||||||
r = rtems_debugger_target_read_regs(thread);
|
r = rtems_debugger_target_read_regs(thread);
|
||||||
if (r >= 0) {
|
if (r >= 0) {
|
||||||
uint32_t* regs = &thread->registers[0];
|
return rtems_debugger_get_int_reg(thread, REG_PC);
|
||||||
return regs[REG_PC];
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1172,8 +1248,7 @@ rtems_debugger_target_reg_sp(rtems_debugger_thread* thread)
|
|||||||
int r;
|
int r;
|
||||||
r = rtems_debugger_target_read_regs(thread);
|
r = rtems_debugger_target_read_regs(thread);
|
||||||
if (r >= 0) {
|
if (r >= 0) {
|
||||||
uint32_t* regs = &thread->registers[0];
|
return rtems_debugger_get_int_reg(thread, REG_SP);
|
||||||
return regs[REG_SP];
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1293,6 +1368,44 @@ rtems_debugger_target_exception_to_signal(CPU_Exception_frame* frame)
|
|||||||
return sig;
|
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
|
int
|
||||||
rtems_debugger_target_hwbreak_insert(void)
|
rtems_debugger_target_hwbreak_insert(void)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -53,13 +53,7 @@
|
|||||||
/*
|
/*
|
||||||
* Number of bytes per register.
|
* Number of bytes per register.
|
||||||
*/
|
*/
|
||||||
#define RTEMS_DEBUGGER_REGBYTES 4
|
#define RTEMS_DEBUGGER_REG_BYTES 4
|
||||||
|
|
||||||
/*
|
|
||||||
* Number of bytes of registers.
|
|
||||||
*/
|
|
||||||
#define RTEMS_DEBUGGER_NUMREGBYTES \
|
|
||||||
(RTEMS_DEBUGGER_NUMREGS * RTEMS_DEBUGGER_REGBYTES)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Debugger registers layout.
|
* Debugger registers layout.
|
||||||
@@ -83,6 +77,39 @@
|
|||||||
#define REG_FS 14
|
#define REG_FS 14
|
||||||
#define REG_GS 15
|
#define REG_GS 15
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 i386_reg_offsets[RTEMS_DEBUGGER_NUMREGS + 1] =
|
||||||
|
{
|
||||||
|
0, /* REG_EAX 4 uint32_t */
|
||||||
|
4, /* REG_ECX 4 uint32_t */
|
||||||
|
8, /* REG_EDX 4 uint32_t */
|
||||||
|
12, /* REG_EBX 4 uint32_t */
|
||||||
|
16, /* REG_ESP 4 uint32_t */
|
||||||
|
20, /* REG_EBP 4 uint32_t */
|
||||||
|
24, /* REG_ESI 4 uint32_t */
|
||||||
|
28, /* REG_EDI 4 uint32_t */
|
||||||
|
32, /* REG_EIP 4 *1 */
|
||||||
|
36, /* REG_EFLAGS 4 uint32_t */
|
||||||
|
40, /* REG_CS 4 uint32_t */
|
||||||
|
44, /* REG_SS 4 uint32_t */
|
||||||
|
48, /* REG_DS 4 uint32_t */
|
||||||
|
52, /* REG_ES 4 uint32_t */
|
||||||
|
56, /* REG_FS 4 uint32_t */
|
||||||
|
60, /* REG_GS 4 uint32_t */
|
||||||
|
64 /* total size */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Number of bytes of registers.
|
||||||
|
*/
|
||||||
|
#define RTEMS_DEBUGGER_NUMREGBYTES i386_reg_offsets[RTEMS_DEBUGGER_NUMREGS]
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The int 3 opcode.
|
* The int 3 opcode.
|
||||||
*/
|
*/
|
||||||
@@ -96,14 +123,34 @@ static const uint8_t breakpoint[1] = { TARGET_BKPT };
|
|||||||
#define GET_REG(_r, _v) asm volatile("pushl %%" #_r "; popl %0" : "=rm" (_v))
|
#define GET_REG(_r, _v) asm volatile("pushl %%" #_r "; popl %0" : "=rm" (_v))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get a copy of a segment register.
|
* A function to get a segment register.
|
||||||
*/
|
*/
|
||||||
#define GET_SEG_REG(_r, _v) \
|
static inline uint32_t
|
||||||
do { \
|
get_seg_reg(size_t reg)
|
||||||
int _i; \
|
{
|
||||||
GET_REG(_r, _i); \
|
int v = 0;
|
||||||
_v = _i & 0xffff; \
|
switch (reg) {
|
||||||
} while (0)
|
case REG_CS:
|
||||||
|
GET_REG(CS, v);
|
||||||
|
break;
|
||||||
|
case REG_SS:
|
||||||
|
GET_REG(SS, v);
|
||||||
|
break;
|
||||||
|
case REG_DS:
|
||||||
|
GET_REG(DS, v);
|
||||||
|
break;
|
||||||
|
case REG_ES:
|
||||||
|
GET_REG(ES, v);
|
||||||
|
break;
|
||||||
|
case REG_FS:
|
||||||
|
GET_REG(FS, v);
|
||||||
|
break;
|
||||||
|
case REG_GS:
|
||||||
|
GET_REG(GS, v);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return v & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Target lock.
|
* Target lock.
|
||||||
@@ -149,7 +196,7 @@ rtems_debugger_target_configure(rtems_debugger_target* target)
|
|||||||
{
|
{
|
||||||
target->capabilities = (RTEMS_DEBUGGER_TARGET_CAP_SWBREAK);
|
target->capabilities = (RTEMS_DEBUGGER_TARGET_CAP_SWBREAK);
|
||||||
target->reg_num = RTEMS_DEBUGGER_NUMREGS;
|
target->reg_num = RTEMS_DEBUGGER_NUMREGS;
|
||||||
target->reg_size = sizeof(uint32_t);
|
target->reg_offset = i386_reg_offsets;
|
||||||
target->breakpoint = &breakpoint[0];
|
target->breakpoint = &breakpoint[0];
|
||||||
target->breakpoint_size = sizeof(breakpoint);
|
target->breakpoint_size = sizeof(breakpoint);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -158,7 +205,7 @@ rtems_debugger_target_configure(rtems_debugger_target* target)
|
|||||||
static void
|
static void
|
||||||
target_exception(CPU_Exception_frame* frame)
|
target_exception(CPU_Exception_frame* frame)
|
||||||
{
|
{
|
||||||
target_printk("[} frame = %08lx sig=%d (%lx)\n",
|
target_printk("[} frame = %08" PRIx32 " sig=%d (%" PRIx32 ")\n",
|
||||||
(uint32_t) frame,
|
(uint32_t) frame,
|
||||||
rtems_debugger_target_exception_to_signal(frame),
|
rtems_debugger_target_exception_to_signal(frame),
|
||||||
frame->idtIndex);
|
frame->idtIndex);
|
||||||
@@ -185,6 +232,34 @@ target_exception(CPU_Exception_frame* frame)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
rtems_debugger_is_int_reg(size_t reg)
|
||||||
|
{
|
||||||
|
const size_t size = i386_reg_offsets[reg + 1] - i386_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 = i386_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 = i386_reg_offsets[reg];
|
||||||
|
uint32_t value;
|
||||||
|
memcpy(&value, &thread->registers[offset], sizeof(uint32_t));
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
rtems_debugger_target_enable(void)
|
rtems_debugger_target_enable(void)
|
||||||
{
|
{
|
||||||
@@ -214,25 +289,27 @@ rtems_debugger_target_read_regs(rtems_debugger_thread* thread)
|
|||||||
{
|
{
|
||||||
if (!rtems_debugger_thread_flag(thread,
|
if (!rtems_debugger_thread_flag(thread,
|
||||||
RTEMS_DEBUGGER_THREAD_FLAG_REG_VALID)) {
|
RTEMS_DEBUGGER_THREAD_FLAG_REG_VALID)) {
|
||||||
uint32_t* regs = &thread->registers[0];
|
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
for (i = 0; i < rtems_debugger_target_reg_num(); ++i)
|
for (i = 0; i < rtems_debugger_target_reg_num(); ++i) {
|
||||||
regs[i] = 0xdeaddead;
|
if (rtems_debugger_is_int_reg(i))
|
||||||
|
rtems_debugger_set_int_reg(thread, i, 0xdeaddead);
|
||||||
|
}
|
||||||
|
|
||||||
if (thread->frame) {
|
if (thread->frame) {
|
||||||
CPU_Exception_frame* frame = thread->frame;
|
CPU_Exception_frame* frame = thread->frame;
|
||||||
regs[REG_EAX] = frame->eax;
|
|
||||||
regs[REG_ECX] = frame->ecx;
|
rtems_debugger_set_int_reg(thread, REG_EAX, frame->eax);
|
||||||
regs[REG_EDX] = frame->edx;
|
rtems_debugger_set_int_reg(thread, REG_ECX, frame->ecx);
|
||||||
regs[REG_EBX] = frame->ebx;
|
rtems_debugger_set_int_reg(thread, REG_EDX, frame->edx);
|
||||||
regs[REG_ESP] = frame->esp0;
|
rtems_debugger_set_int_reg(thread, REG_EBX, frame->ebx);
|
||||||
regs[REG_EBP] = frame->ebp;
|
rtems_debugger_set_int_reg(thread, REG_ESP, frame->esp0);
|
||||||
regs[REG_ESI] = frame->esi;
|
rtems_debugger_set_int_reg(thread, REG_EBP, frame->ebp);
|
||||||
regs[REG_EDI] = frame->edi;
|
rtems_debugger_set_int_reg(thread, REG_ESI, frame->esi);
|
||||||
regs[REG_EIP] = frame->eip;
|
rtems_debugger_set_int_reg(thread, REG_EDI, frame->edi);
|
||||||
regs[REG_EFLAGS] = frame->eflags;
|
rtems_debugger_set_int_reg(thread, REG_EIP, frame->eip);
|
||||||
regs[REG_CS] = frame->cs;
|
rtems_debugger_set_int_reg(thread, REG_EFLAGS, frame->eflags);
|
||||||
|
rtems_debugger_set_int_reg(thread, REG_CS, frame->cs);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the signal from the frame.
|
* Get the signal from the frame.
|
||||||
@@ -240,16 +317,16 @@ rtems_debugger_target_read_regs(rtems_debugger_thread* thread)
|
|||||||
thread->signal = rtems_debugger_target_exception_to_signal(frame);
|
thread->signal = rtems_debugger_target_exception_to_signal(frame);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
regs[REG_EBX] = thread->tcb->Registers.ebx;
|
rtems_debugger_set_int_reg(thread, REG_EBX, thread->tcb->Registers.ebx);
|
||||||
regs[REG_ESI] = thread->tcb->Registers.esi;
|
rtems_debugger_set_int_reg(thread, REG_ESI, thread->tcb->Registers.esi);
|
||||||
regs[REG_EDI] = thread->tcb->Registers.edi;
|
rtems_debugger_set_int_reg(thread, REG_EDI, thread->tcb->Registers.edi);
|
||||||
regs[REG_EFLAGS] = thread->tcb->Registers.eflags;
|
rtems_debugger_set_int_reg(thread, REG_EFLAGS, thread->tcb->Registers.eflags);
|
||||||
regs[REG_ESP] = (intptr_t) thread->tcb->Registers.esp;
|
rtems_debugger_set_int_reg(thread, REG_ESP, (intptr_t) thread->tcb->Registers.esp);
|
||||||
regs[REG_EBP] = (intptr_t) thread->tcb->Registers.ebp;
|
rtems_debugger_set_int_reg(thread, REG_EBP, (intptr_t) thread->tcb->Registers.ebp);
|
||||||
regs[REG_EIP] = *((DB_UINT*) thread->tcb->Registers.esp);
|
rtems_debugger_set_int_reg(thread, REG_EIP, *((DB_UINT*) thread->tcb->Registers.esp));
|
||||||
regs[REG_EAX] = (intptr_t) thread;
|
rtems_debugger_set_int_reg(thread, REG_EAX, (intptr_t) thread);
|
||||||
|
|
||||||
GET_SEG_REG(CS, regs[REG_CS]);
|
rtems_debugger_set_int_reg(thread, REG_CS, get_seg_reg(REG_CS));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Blocked threads have no signal.
|
* Blocked threads have no signal.
|
||||||
@@ -257,11 +334,11 @@ rtems_debugger_target_read_regs(rtems_debugger_thread* thread)
|
|||||||
thread->signal = 0;
|
thread->signal = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
GET_SEG_REG(SS, regs[REG_SS]);
|
rtems_debugger_set_int_reg(thread, REG_SS, get_seg_reg(REG_SS));
|
||||||
GET_SEG_REG(DS, regs[REG_DS]);
|
rtems_debugger_set_int_reg(thread, REG_DS, get_seg_reg(REG_DS));
|
||||||
GET_SEG_REG(ES, regs[REG_ES]);
|
rtems_debugger_set_int_reg(thread, REG_ES, get_seg_reg(REG_ES));
|
||||||
GET_SEG_REG(FS, regs[REG_FS]);
|
rtems_debugger_set_int_reg(thread, REG_FS, get_seg_reg(REG_FS));
|
||||||
GET_SEG_REG(GS, regs[REG_GS]);
|
rtems_debugger_set_int_reg(thread, REG_GS, get_seg_reg(REG_GS));
|
||||||
|
|
||||||
thread->flags |= RTEMS_DEBUGGER_THREAD_FLAG_REG_VALID;
|
thread->flags |= RTEMS_DEBUGGER_THREAD_FLAG_REG_VALID;
|
||||||
thread->flags &= ~RTEMS_DEBUGGER_THREAD_FLAG_REG_DIRTY;
|
thread->flags &= ~RTEMS_DEBUGGER_THREAD_FLAG_REG_DIRTY;
|
||||||
@@ -275,8 +352,6 @@ rtems_debugger_target_write_regs(rtems_debugger_thread* thread)
|
|||||||
{
|
{
|
||||||
if (rtems_debugger_thread_flag(thread,
|
if (rtems_debugger_thread_flag(thread,
|
||||||
RTEMS_DEBUGGER_THREAD_FLAG_REG_DIRTY)) {
|
RTEMS_DEBUGGER_THREAD_FLAG_REG_DIRTY)) {
|
||||||
uint32_t* regs = &thread->registers[0];
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Only write to debugger controlled threads. Do not touch the registers
|
* Only write to debugger controlled threads. Do not touch the registers
|
||||||
* for threads blocked in the context switcher.
|
* for threads blocked in the context switcher.
|
||||||
@@ -284,17 +359,17 @@ rtems_debugger_target_write_regs(rtems_debugger_thread* thread)
|
|||||||
if (rtems_debugger_thread_flag(thread,
|
if (rtems_debugger_thread_flag(thread,
|
||||||
RTEMS_DEBUGGER_THREAD_FLAG_EXCEPTION)) {
|
RTEMS_DEBUGGER_THREAD_FLAG_EXCEPTION)) {
|
||||||
CPU_Exception_frame* frame = thread->frame;
|
CPU_Exception_frame* frame = thread->frame;
|
||||||
frame->eax = regs[REG_EAX];
|
frame->eax = rtems_debugger_get_int_reg(thread, REG_EAX);
|
||||||
frame->ecx = regs[REG_ECX];
|
frame->ecx = rtems_debugger_get_int_reg(thread, REG_ECX);
|
||||||
frame->edx = regs[REG_EDX];
|
frame->edx = rtems_debugger_get_int_reg(thread, REG_EDX);
|
||||||
frame->ebx = regs[REG_EBX];
|
frame->ebx = rtems_debugger_get_int_reg(thread, REG_EBX);
|
||||||
frame->esp0 = regs[REG_ESP];
|
frame->esp0 = rtems_debugger_get_int_reg(thread, REG_ESP);
|
||||||
frame->ebp = regs[REG_EBP];
|
frame->ebp = rtems_debugger_get_int_reg(thread, REG_EBP);
|
||||||
frame->esi = regs[REG_ESI];
|
frame->esi = rtems_debugger_get_int_reg(thread, REG_ESI);
|
||||||
frame->edi = regs[REG_EDI];
|
frame->edi = rtems_debugger_get_int_reg(thread, REG_EDI);
|
||||||
frame->eip = regs[REG_EIP];
|
frame->eip = rtems_debugger_get_int_reg(thread, REG_EIP);
|
||||||
frame->eflags = regs[REG_EFLAGS];
|
frame->eflags = rtems_debugger_get_int_reg(thread, REG_EFLAGS);
|
||||||
frame->cs = regs[REG_CS];
|
frame->cs = rtems_debugger_get_int_reg(thread, REG_CS);
|
||||||
}
|
}
|
||||||
thread->flags &= ~RTEMS_DEBUGGER_THREAD_FLAG_REG_DIRTY;
|
thread->flags &= ~RTEMS_DEBUGGER_THREAD_FLAG_REG_DIRTY;
|
||||||
}
|
}
|
||||||
@@ -307,8 +382,7 @@ rtems_debugger_target_reg_pc(rtems_debugger_thread* thread)
|
|||||||
int r;
|
int r;
|
||||||
r = rtems_debugger_target_read_regs(thread);
|
r = rtems_debugger_target_read_regs(thread);
|
||||||
if (r >= 0) {
|
if (r >= 0) {
|
||||||
uint32_t* regs = &thread->registers[0];
|
return rtems_debugger_get_int_reg(thread, REG_EIP);
|
||||||
return regs[REG_EIP];
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -325,8 +399,7 @@ rtems_debugger_target_reg_sp(rtems_debugger_thread* thread)
|
|||||||
int r;
|
int r;
|
||||||
r = rtems_debugger_target_read_regs(thread);
|
r = rtems_debugger_target_read_regs(thread);
|
||||||
if (r >= 0) {
|
if (r >= 0) {
|
||||||
uint32_t* regs = &thread->registers[0];
|
return rtems_debugger_get_int_reg(thread, REG_ESP);
|
||||||
return regs[REG_ESP];
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -400,6 +473,18 @@ rtems_debugger_target_exception_to_signal(CPU_Exception_frame* frame)
|
|||||||
return sig;
|
return sig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rtems_debugger_target_exception_print(CPU_Exception_frame* frame)
|
||||||
|
{
|
||||||
|
rtems_debugger_printf(" EAX = %" PRIx32 " EBX = %" PRIx32 \
|
||||||
|
" ECX = %" PRIx32 " EDX = %" PRIx32 "\n",
|
||||||
|
frame->eax, frame->ebx, frame->ecx, frame->edx);
|
||||||
|
rtems_debugger_printf(" ESI = %" PRIx32 " EDI = %" PRIx32 \
|
||||||
|
" EBP = %" PRIx32 " ESP = %" PRIx32 "\n",
|
||||||
|
frame->esi, frame->edi, frame->ebp, frame->esp0);
|
||||||
|
rtems_debugger_printf(" EIP = %" PRIx32"\n", frame->eip);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
rtems_debugger_target_hwbreak_insert(void)
|
rtems_debugger_target_hwbreak_insert(void)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -25,9 +25,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define RTEMS_DEBUGGER_VERBOSE_LOCK 0
|
#define RTEMS_DEBUGGER_VERBOSE_LOCK 0
|
||||||
#define RTEMS_DEBUGGER_PRINT_PRINTK 1
|
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <inttypes.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
@@ -84,9 +84,7 @@ rtems_debugger_server* rtems_debugger;
|
|||||||
* Print lock ot make the prints sequential. This is to debug the debugger in
|
* Print lock ot make the prints sequential. This is to debug the debugger in
|
||||||
* SMP.
|
* SMP.
|
||||||
*/
|
*/
|
||||||
#if RTEMS_DEBUGGER_PRINT_PRINTK
|
|
||||||
RTEMS_INTERRUPT_LOCK_DEFINE(static, printk_lock, "printk_lock")
|
RTEMS_INTERRUPT_LOCK_DEFINE(static, printk_lock, "printk_lock")
|
||||||
#endif
|
|
||||||
|
|
||||||
void
|
void
|
||||||
rtems_debugger_printk_lock(rtems_interrupt_lock_context* lock_context)
|
rtems_debugger_printk_lock(rtems_interrupt_lock_context* lock_context)
|
||||||
@@ -103,17 +101,13 @@ rtems_debugger_printk_unlock(rtems_interrupt_lock_context* lock_context)
|
|||||||
int
|
int
|
||||||
rtems_debugger_clean_printf(const char* format, ...)
|
rtems_debugger_clean_printf(const char* format, ...)
|
||||||
{
|
{
|
||||||
|
rtems_interrupt_lock_context lock_context;
|
||||||
int len;
|
int len;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
if (RTEMS_DEBUGGER_PRINT_PRINTK) {
|
|
||||||
rtems_interrupt_lock_context lock_context;
|
|
||||||
rtems_debugger_printk_lock(&lock_context);
|
rtems_debugger_printk_lock(&lock_context);
|
||||||
len = vprintk(format, ap);
|
len = vprintk(format, ap);
|
||||||
rtems_debugger_printk_unlock(&lock_context);
|
rtems_debugger_printk_unlock(&lock_context);
|
||||||
}
|
|
||||||
else
|
|
||||||
len = rtems_vprintf(&rtems_debugger->printer, format, ap);
|
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
@@ -121,18 +115,14 @@ rtems_debugger_clean_printf(const char* format, ...)
|
|||||||
int
|
int
|
||||||
rtems_debugger_printf(const char* format, ...)
|
rtems_debugger_printf(const char* format, ...)
|
||||||
{
|
{
|
||||||
|
rtems_interrupt_lock_context lock_context;
|
||||||
int len;
|
int len;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
if (RTEMS_DEBUGGER_PRINT_PRINTK) {
|
|
||||||
rtems_interrupt_lock_context lock_context;
|
|
||||||
rtems_debugger_printk_lock(&lock_context);
|
rtems_debugger_printk_lock(&lock_context);
|
||||||
printk("[CPU:%d] ", (int) _SMP_Get_current_processor ());
|
printk("[CPU:%d] ", (int) _SMP_Get_current_processor ());
|
||||||
len = vprintk(format, ap);
|
len = vprintk(format, ap);
|
||||||
rtems_debugger_printk_unlock(&lock_context);
|
rtems_debugger_printk_unlock(&lock_context);
|
||||||
}
|
|
||||||
else
|
|
||||||
len = rtems_vprintf(&rtems_debugger->printer, format, ap);
|
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
@@ -897,7 +887,7 @@ remote_gq_thread_extra_info(uint8_t* buffer, int size)
|
|||||||
current = rtems_debugger_thread_current(threads);
|
current = rtems_debugger_thread_current(threads);
|
||||||
thread = ¤t[r];
|
thread = ¤t[r];
|
||||||
l = snprintf(buf, sizeof(buf),
|
l = snprintf(buf, sizeof(buf),
|
||||||
"%4s (%08lx), ", thread->name, thread->id);
|
"%4s (%08" PRIx32 "), ", thread->name, thread->id);
|
||||||
remote_packet_out_append_hex((const uint8_t*) buf, l);
|
remote_packet_out_append_hex((const uint8_t*) buf, l);
|
||||||
l = snprintf(buf, sizeof(buf),
|
l = snprintf(buf, sizeof(buf),
|
||||||
"priority(c:%3d r:%3d), ",
|
"priority(c:%3d r:%3d), ",
|
||||||
@@ -1330,7 +1320,7 @@ remote_read_general_regs(uint8_t* buffer, int size)
|
|||||||
if (r >= 0) {
|
if (r >= 0) {
|
||||||
remote_packet_out_reset();
|
remote_packet_out_reset();
|
||||||
r = remote_packet_out_append_hex((const uint8_t*) &thread->registers[0],
|
r = remote_packet_out_append_hex((const uint8_t*) &thread->registers[0],
|
||||||
rtems_debugger_target_reg_size());
|
rtems_debugger_target_reg_table_size());
|
||||||
if (r >= 0)
|
if (r >= 0)
|
||||||
ok = true;
|
ok = true;
|
||||||
}
|
}
|
||||||
@@ -1345,12 +1335,12 @@ static int
|
|||||||
remote_write_general_regs(uint8_t* buffer, int size)
|
remote_write_general_regs(uint8_t* buffer, int size)
|
||||||
{
|
{
|
||||||
rtems_debugger_threads* threads = rtems_debugger->threads;
|
rtems_debugger_threads* threads = rtems_debugger->threads;
|
||||||
size_t reg_size = rtems_debugger_target_reg_size();
|
size_t reg_table_size = rtems_debugger_target_reg_table_size();
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
int r;
|
int r;
|
||||||
if (threads->selector_gen >= 0 &&
|
if (threads->selector_gen >= 0 &&
|
||||||
threads->selector_gen < (int) threads->current.level &&
|
threads->selector_gen < (int) threads->current.level &&
|
||||||
((size - 1) / 2) == (int) reg_size) {
|
((size - 1) / 2) == (int) reg_table_size) {
|
||||||
rtems_debugger_thread* current;
|
rtems_debugger_thread* current;
|
||||||
rtems_debugger_thread* thread;
|
rtems_debugger_thread* thread;
|
||||||
current = rtems_debugger_thread_current(threads);
|
current = rtems_debugger_thread_current(threads);
|
||||||
@@ -1359,7 +1349,7 @@ remote_write_general_regs(uint8_t* buffer, int size)
|
|||||||
if (r >= 0) {
|
if (r >= 0) {
|
||||||
r = rtems_debugger_remote_packet_in_hex((uint8_t*) &thread->registers[0],
|
r = rtems_debugger_remote_packet_in_hex((uint8_t*) &thread->registers[0],
|
||||||
(const char*) &buffer[1],
|
(const char*) &buffer[1],
|
||||||
reg_size);
|
reg_table_size);
|
||||||
if (r >= 0) {
|
if (r >= 0) {
|
||||||
thread->flags |= RTEMS_DEBUGGER_THREAD_FLAG_REG_DIRTY;
|
thread->flags |= RTEMS_DEBUGGER_THREAD_FLAG_REG_DIRTY;
|
||||||
ok = true;
|
ok = true;
|
||||||
@@ -1388,9 +1378,11 @@ remote_read_reg(uint8_t* buffer, int size)
|
|||||||
thread = ¤t[threads->selector_gen];
|
thread = ¤t[threads->selector_gen];
|
||||||
r = rtems_debugger_target_read_regs(thread);
|
r = rtems_debugger_target_read_regs(thread);
|
||||||
if (r >= 0) {
|
if (r >= 0) {
|
||||||
const uint8_t* addr = (const uint8_t*) &thread->registers[reg];
|
const size_t reg_size = rtems_debugger_target_reg_size(reg);
|
||||||
|
const size_t reg_offset = rtems_debugger_target_reg_offset(reg);
|
||||||
|
const uint8_t* addr = &thread->registers[reg_offset];
|
||||||
remote_packet_out_reset();
|
remote_packet_out_reset();
|
||||||
r = remote_packet_out_append_hex(addr, sizeof(thread->registers[0]));
|
r = remote_packet_out_append_hex(addr, reg_size);
|
||||||
if (r >= 0)
|
if (r >= 0)
|
||||||
ok = true;
|
ok = true;
|
||||||
}
|
}
|
||||||
@@ -1421,10 +1413,10 @@ remote_write_reg(uint8_t* buffer, int size)
|
|||||||
thread = ¤t[threads->selector_gen];
|
thread = ¤t[threads->selector_gen];
|
||||||
r = rtems_debugger_target_read_regs(thread);
|
r = rtems_debugger_target_read_regs(thread);
|
||||||
if (r >= 0) {
|
if (r >= 0) {
|
||||||
uint8_t* addr = (uint8_t*) &thread->registers[reg];
|
const size_t reg_size = rtems_debugger_target_reg_size(reg);
|
||||||
r = rtems_debugger_remote_packet_in_hex(addr,
|
const size_t reg_offset = rtems_debugger_target_reg_offset(reg);
|
||||||
equals + 1,
|
uint8_t* addr = &thread->registers[reg_offset];
|
||||||
sizeof(thread->registers[reg]));
|
r = rtems_debugger_remote_packet_in_hex(addr, equals + 1, reg_size);
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
thread->flags |= RTEMS_DEBUGGER_THREAD_FLAG_REG_DIRTY;
|
thread->flags |= RTEMS_DEBUGGER_THREAD_FLAG_REG_DIRTY;
|
||||||
response = r_OK;
|
response = r_OK;
|
||||||
@@ -1505,7 +1497,7 @@ remote_single_step(uint8_t* buffer, int size)
|
|||||||
rtems_debugger_thread* current;
|
rtems_debugger_thread* current;
|
||||||
char vCont_s[32];
|
char vCont_s[32];
|
||||||
current = rtems_debugger_thread_current(threads);
|
current = rtems_debugger_thread_current(threads);
|
||||||
snprintf(vCont_s, sizeof(vCont_s), "vCont;s:p1.%08lx;c:p1.-1",
|
snprintf(vCont_s, sizeof(vCont_s), "vCont;s:p1.%08" PRIx32 ";c:p1.-1",
|
||||||
current[threads->selector_cont].id);
|
current[threads->selector_cont].id);
|
||||||
return remote_v_continue((uint8_t*) vCont_s, strlen(vCont_s));
|
return remote_v_continue((uint8_t*) vCont_s, strlen(vCont_s));
|
||||||
}
|
}
|
||||||
@@ -1668,6 +1660,8 @@ rtems_debugger_events(rtems_task_argument arg)
|
|||||||
|
|
||||||
while (rtems_debugger_server_events_running()) {
|
while (rtems_debugger_server_events_running()) {
|
||||||
rtems_debugger_server_events_wait();
|
rtems_debugger_server_events_wait();
|
||||||
|
if (rtems_debugger_verbose())
|
||||||
|
rtems_debugger_printf("rtems-db: event woken\n");
|
||||||
if (!rtems_debugger_server_events_running())
|
if (!rtems_debugger_server_events_running())
|
||||||
break;
|
break;
|
||||||
r = rtems_debugger_thread_system_suspend();
|
r = rtems_debugger_thread_system_suspend();
|
||||||
@@ -1949,6 +1943,15 @@ rtems_debugger_start(const char* remote,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rtems_debugger_server_crash(void)
|
||||||
|
{
|
||||||
|
rtems_debugger_lock();
|
||||||
|
rtems_debugger->server_running = false;
|
||||||
|
rtems_debugger_unlock();
|
||||||
|
rtems_debugger->remote->end(rtems_debugger->remote);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
rtems_debugger_stop(void)
|
rtems_debugger_stop(void)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -134,16 +134,36 @@ rtems_debugger_target_capabilities(void)
|
|||||||
size_t
|
size_t
|
||||||
rtems_debugger_target_reg_num(void)
|
rtems_debugger_target_reg_num(void)
|
||||||
{
|
{
|
||||||
if (rtems_debugger->target != NULL)
|
rtems_debugger_target* target = rtems_debugger->target;
|
||||||
return rtems_debugger->target->reg_num;
|
if (target != NULL)
|
||||||
|
return target->reg_num;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
rtems_debugger_target_reg_size(void)
|
rtems_debugger_target_reg_size(size_t reg)
|
||||||
{
|
{
|
||||||
if (rtems_debugger->target != NULL)
|
rtems_debugger_target* target = rtems_debugger->target;
|
||||||
return rtems_debugger->target->reg_num * rtems_debugger->target->reg_size;
|
if (target != NULL && reg < target->reg_num)
|
||||||
|
return target->reg_offset[reg + 1] - target->reg_offset[reg];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
rtems_debugger_target_reg_offset(size_t reg)
|
||||||
|
{
|
||||||
|
rtems_debugger_target* target = rtems_debugger->target;
|
||||||
|
if (target != NULL && reg < target->reg_num)
|
||||||
|
return target->reg_offset[reg];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
rtems_debugger_target_reg_table_size(void)
|
||||||
|
{
|
||||||
|
rtems_debugger_target* target = rtems_debugger->target;
|
||||||
|
if (target != NULL)
|
||||||
|
return target->reg_offset[target->reg_num];
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,17 +325,23 @@ rtems_debugger_target_exception(CPU_Exception_frame* frame)
|
|||||||
rtems_debugger_lock();
|
rtems_debugger_lock();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the thread is the debugger recover.
|
* If the thread is in the debugger recover. If the access is from gdb
|
||||||
|
* continue else shutdown and let the user know.
|
||||||
*/
|
*/
|
||||||
if (tid == rtems_debugger->server_task) {
|
if (tid == rtems_debugger->server_task ||
|
||||||
if (rtems_debugger->target->memory_access) {
|
tid == rtems_debugger->events_task) {
|
||||||
target_printk("[} server access fault\n");
|
bool memory_access = rtems_debugger_target_is_memory_access();
|
||||||
rtems_debugger->target->memory_access = true;
|
|
||||||
rtems_debugger_unlock();
|
rtems_debugger_unlock();
|
||||||
|
/*
|
||||||
|
* Has GDB has asked us to write to an address?
|
||||||
|
*/
|
||||||
|
if (memory_access) {
|
||||||
|
target_printk("[} server fault: memory access\n");
|
||||||
longjmp(rtems_debugger->target->access_return, -1);
|
longjmp(rtems_debugger->target->access_return, -1);
|
||||||
}
|
}
|
||||||
target_printk("[} server exception\n");
|
rtems_debugger_printf("rtems-db: server exception (report)\n");
|
||||||
rtems_debugger_unlock();
|
rtems_debugger_target_exception_print(frame);
|
||||||
|
rtems_debugger_server_crash();
|
||||||
return rtems_debugger_target_exc_cascade;
|
return rtems_debugger_target_exc_cascade;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -332,7 +358,7 @@ rtems_debugger_target_exception(CPU_Exception_frame* frame)
|
|||||||
* the contents of the instruction, step then return the
|
* the contents of the instruction, step then return the
|
||||||
* swbreak's contents.
|
* swbreak's contents.
|
||||||
*/
|
*/
|
||||||
target_printk("[} tid:%08lx: excluded\n", tid);
|
target_printk("[} tid:%08" PRIx32 ": excluded\n", tid);
|
||||||
rtems_debugger_unlock();
|
rtems_debugger_unlock();
|
||||||
return rtems_debugger_target_exc_cascade;
|
return rtems_debugger_target_exc_cascade;
|
||||||
}
|
}
|
||||||
@@ -346,12 +372,12 @@ rtems_debugger_target_exception(CPU_Exception_frame* frame)
|
|||||||
if (stepper != NULL) {
|
if (stepper != NULL) {
|
||||||
stepper->thread->frame = frame;
|
stepper->thread->frame = frame;
|
||||||
rtems_debugger_target_thread_stepping(stepper->thread);
|
rtems_debugger_target_thread_stepping(stepper->thread);
|
||||||
target_printk("[} tid:%08lx: stepping\n", tid);
|
target_printk("[} tid:%08" PRIx32 ": stepping\n", tid);
|
||||||
rtems_debugger_unlock();
|
rtems_debugger_unlock();
|
||||||
return rtems_debugger_target_exc_step;
|
return rtems_debugger_target_exc_step;
|
||||||
}
|
}
|
||||||
|
|
||||||
target_printk("[} tid:%08lx: suspending\n", tid);
|
target_printk("[} tid:%08" PRIx32 ": suspending\n", tid);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialise the target exception data and queue ready for the debugger
|
* Initialise the target exception data and queue ready for the debugger
|
||||||
@@ -381,12 +407,12 @@ rtems_debugger_target_exception(CPU_Exception_frame* frame)
|
|||||||
*/
|
*/
|
||||||
rtems_debugger_unlock();
|
rtems_debugger_unlock();
|
||||||
|
|
||||||
target_printk("[} tid:%08lx: resuming\n", tid);
|
target_printk("[} tid:%08" PRIx32 ": resuming\n", tid);
|
||||||
|
|
||||||
return rtems_debugger_target_exc_consumed;
|
return rtems_debugger_target_exc_consumed;
|
||||||
}
|
}
|
||||||
|
|
||||||
target_printk("[} cascade, in interrupt\n");
|
rtems_debugger_printf("rtems-db: exception in an interrupt, cascading\n");
|
||||||
|
|
||||||
return rtems_debugger_target_exc_cascade;
|
return rtems_debugger_target_exc_cascade;
|
||||||
}
|
}
|
||||||
@@ -439,3 +465,9 @@ rtems_debugger_target_end_memory_access(void)
|
|||||||
{
|
{
|
||||||
rtems_debugger->target->memory_access = false;
|
rtems_debugger->target->memory_access = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
rtems_debugger_target_is_memory_access(void)
|
||||||
|
{
|
||||||
|
return rtems_debugger->target->memory_access;
|
||||||
|
}
|
||||||
|
|||||||
@@ -85,11 +85,15 @@ typedef struct rtems_debugger_target_swbreak {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The target data.
|
* The target data.
|
||||||
|
*
|
||||||
|
* reg_offset: Table of size_t offset of a register in the register
|
||||||
|
* table. The table has one more entry than reg_num where
|
||||||
|
* the last entry is the size of the register table.
|
||||||
*/
|
*/
|
||||||
typedef struct rtems_debugger_target {
|
typedef struct rtems_debugger_target {
|
||||||
int capabilities; /*<< The capabilities to report. */
|
int capabilities; /*<< The capabilities to report. */
|
||||||
size_t reg_num; /*<< The number of registers. */
|
size_t reg_num; /*<< The number of registers. */
|
||||||
size_t reg_size; /*<< The size of a register. */
|
const size_t* reg_offset; /*<< The reg offsettable, len = reg_num + 1. */
|
||||||
const uint8_t* breakpoint; /*<< The breakpoint instruction(s). */
|
const uint8_t* breakpoint; /*<< The breakpoint instruction(s). */
|
||||||
size_t breakpoint_size; /*<< The breakpoint size. */
|
size_t breakpoint_size; /*<< The breakpoint size. */
|
||||||
rtems_debugger_block swbreaks; /*<< The software breakpoint block. */
|
rtems_debugger_block swbreaks; /*<< The software breakpoint block. */
|
||||||
@@ -133,9 +137,19 @@ extern uint32_t rtems_debugger_target_capabilities(void);
|
|||||||
extern size_t rtems_debugger_target_reg_num(void);
|
extern size_t rtems_debugger_target_reg_num(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the size of the regisers in bytes.
|
* Return the offset of a register in the register table.
|
||||||
*/
|
*/
|
||||||
extern size_t rtems_debugger_target_reg_size(void);
|
extern size_t rtems_debugger_target_reg_size(size_t reg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the offset of a register in the register table.
|
||||||
|
*/
|
||||||
|
extern size_t rtems_debugger_target_reg_offset(size_t reg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the size of register table.
|
||||||
|
*/
|
||||||
|
extern size_t rtems_debugger_target_reg_table_size(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read the regosters.
|
* Read the regosters.
|
||||||
@@ -177,6 +191,11 @@ extern int rtems_debugger_target_thread_stepping(rtems_debugger_thread* thread);
|
|||||||
*/
|
*/
|
||||||
extern int rtems_debugger_target_exception_to_signal(CPU_Exception_frame* frame);
|
extern int rtems_debugger_target_exception_to_signal(CPU_Exception_frame* frame);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print the target exception registers.
|
||||||
|
*/
|
||||||
|
extern void rtems_debugger_target_exception_print(CPU_Exception_frame* frame);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Software breakpoints. These are also referred to as memory breakpoints.
|
* Software breakpoints. These are also referred to as memory breakpoints.
|
||||||
*/
|
*/
|
||||||
@@ -245,6 +264,11 @@ extern int rtems_debugger_target_start_memory_access(void);
|
|||||||
*/
|
*/
|
||||||
extern void rtems_debugger_target_end_memory_access(void);
|
extern void rtems_debugger_target_end_memory_access(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is this a target memory access?
|
||||||
|
*/
|
||||||
|
extern bool rtems_debugger_target_is_memory_access(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <inttypes.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
@@ -85,7 +86,7 @@ rtems_debugger_thread_create(void)
|
|||||||
|
|
||||||
r = rtems_debugger_block_create(&threads->registers,
|
r = rtems_debugger_block_create(&threads->registers,
|
||||||
RTEMS_DEBUGGER_THREAD_BLOCK_SIZE,
|
RTEMS_DEBUGGER_THREAD_BLOCK_SIZE,
|
||||||
rtems_debugger_target_reg_size());
|
rtems_debugger_target_reg_table_size());
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
rtems_debugger_thread_free(threads);
|
rtems_debugger_thread_free(threads);
|
||||||
free(threads);
|
free(threads);
|
||||||
@@ -209,7 +210,7 @@ snapshot_thread(rtems_tcb* tcb, void* arg)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
rtems_debugger_thread* current;
|
rtems_debugger_thread* current;
|
||||||
DB_UINT* registers;
|
uint8_t* registers;
|
||||||
rtems_debugger_thread* thread;
|
rtems_debugger_thread* thread;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@@ -229,7 +230,7 @@ snapshot_thread(rtems_tcb* tcb, void* arg)
|
|||||||
|
|
||||||
thread = ¤t[threads->current.level++];
|
thread = ¤t[threads->current.level++];
|
||||||
thread->registers =
|
thread->registers =
|
||||||
®isters[threads->registers.level++ * rtems_debugger_target_reg_num()];
|
®isters[threads->registers.level++ * rtems_debugger_target_reg_table_size()];
|
||||||
|
|
||||||
thread->tcb = tcb;
|
thread->tcb = tcb;
|
||||||
thread->id = id;
|
thread->id = id;
|
||||||
@@ -262,7 +263,7 @@ snapshot_thread(rtems_tcb* tcb, void* arg)
|
|||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
sc = rtems_task_suspend(id);
|
sc = rtems_task_suspend(id);
|
||||||
if (sc != RTEMS_SUCCESSFUL && sc != RTEMS_ALREADY_SUSPENDED) {
|
if (sc != RTEMS_SUCCESSFUL && sc != RTEMS_ALREADY_SUSPENDED) {
|
||||||
rtems_debugger_printf("error: rtems-db: thread: suspend: %08lx: %s\n",
|
rtems_debugger_printf("error: rtems-db: thread: suspend: %08" PRIx32 ": %s\n",
|
||||||
id, rtems_status_text(sc));
|
id, rtems_status_text(sc));
|
||||||
r = -1;
|
r = -1;
|
||||||
}
|
}
|
||||||
@@ -274,7 +275,7 @@ snapshot_thread(rtems_tcb* tcb, void* arg)
|
|||||||
rtems_debugger_target_read_regs(thread);
|
rtems_debugger_target_read_regs(thread);
|
||||||
|
|
||||||
if (rtems_debugger_server_flag(RTEMS_DEBUGGER_FLAG_VERBOSE))
|
if (rtems_debugger_server_flag(RTEMS_DEBUGGER_FLAG_VERBOSE))
|
||||||
rtems_debugger_printf("rtems-db: sys: thd: %08lx: signal: %d\n",
|
rtems_debugger_printf("rtems-db: sys: thd: %08" PRIx32 ": signal: %d\n",
|
||||||
id, thread->signal);
|
id, thread->signal);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -380,7 +381,7 @@ rtems_debugger_thread_system_resume(bool detaching)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (rtems_debugger_verbose())
|
if (rtems_debugger_verbose())
|
||||||
rtems_debugger_printf("rtems-db: sys: : resume: 0x%08lx\n",
|
rtems_debugger_printf("rtems-db: sys: : resume: 0x%08" PRIx32 "\n",
|
||||||
thread->id);
|
thread->id);
|
||||||
if (rtems_debugger_thread_flag(thread,
|
if (rtems_debugger_thread_flag(thread,
|
||||||
RTEMS_DEBUGGER_THREAD_FLAG_EXCEPTION)) {
|
RTEMS_DEBUGGER_THREAD_FLAG_EXCEPTION)) {
|
||||||
@@ -388,7 +389,7 @@ rtems_debugger_thread_system_resume(bool detaching)
|
|||||||
} else {
|
} else {
|
||||||
sc = rtems_task_resume(thread->id);
|
sc = rtems_task_resume(thread->id);
|
||||||
if (sc != RTEMS_SUCCESSFUL) {
|
if (sc != RTEMS_SUCCESSFUL) {
|
||||||
rtems_debugger_printf("error: rtems-db: thread: resume: %08lx: %s\n",
|
rtems_debugger_printf("error: rtems-db: thread: resume: %08" PRIx32 ": %s\n",
|
||||||
thread->id, rtems_status_text(sc));
|
thread->id, rtems_status_text(sc));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ typedef struct rtems_debugger_thread
|
|||||||
Thread_Control* tcb;
|
Thread_Control* tcb;
|
||||||
rtems_id id;
|
rtems_id id;
|
||||||
int cpu;
|
int cpu;
|
||||||
DB_UINT* registers;
|
uint8_t* registers;
|
||||||
int signal;
|
int signal;
|
||||||
void* frame;
|
void* frame;
|
||||||
} rtems_debugger_thread;
|
} rtems_debugger_thread;
|
||||||
@@ -234,7 +234,7 @@ rtems_debugger_thread_current(rtems_debugger_threads* threads)
|
|||||||
/**
|
/**
|
||||||
* Get the registers.
|
* Get the registers.
|
||||||
*/
|
*/
|
||||||
static inline DB_UINT*
|
static inline uint8_t*
|
||||||
rtems_debugger_thread_registers(rtems_debugger_threads* threads)
|
rtems_debugger_thread_registers(rtems_debugger_threads* threads)
|
||||||
{
|
{
|
||||||
return threads->registers.block;
|
return threads->registers.block;
|
||||||
|
|||||||
Reference in New Issue
Block a user