diff options
author | Chris Johns <chrisj@rtems.org> | 2019-04-08 13:17:08 +1000 |
---|---|---|
committer | Chris Johns <chrisj@rtems.org> | 2019-04-09 15:02:24 +1000 |
commit | 2c09b71faf4c476cf76476dc5926f0095eb6fdcd (patch) | |
tree | 00e4102eb5282055c568e2a8e0a96f4d7c170065 /cpukit/libdebugger/rtems-debugger-i386.c | |
parent | doxygen: Update _Objects_Build_name() (diff) | |
download | rtems-2c09b71faf4c476cf76476dc5926f0095eb6fdcd.tar.bz2 |
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.
Diffstat (limited to 'cpukit/libdebugger/rtems-debugger-i386.c')
-rw-r--r-- | cpukit/libdebugger/rtems-debugger-i386.c | 209 |
1 files changed, 147 insertions, 62 deletions
diff --git a/cpukit/libdebugger/rtems-debugger-i386.c b/cpukit/libdebugger/rtems-debugger-i386.c index 9da6031574..a2396e5f30 100644 --- a/cpukit/libdebugger/rtems-debugger-i386.c +++ b/cpukit/libdebugger/rtems-debugger-i386.c @@ -53,13 +53,7 @@ /* * Number of bytes per register. */ -#define RTEMS_DEBUGGER_REGBYTES 4 - -/* - * Number of bytes of registers. - */ -#define RTEMS_DEBUGGER_NUMREGBYTES \ - (RTEMS_DEBUGGER_NUMREGS * RTEMS_DEBUGGER_REGBYTES) +#define RTEMS_DEBUGGER_REG_BYTES 4 /* * Debugger registers layout. @@ -84,6 +78,39 @@ #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. */ #define TARGET_BKPT 0xcc @@ -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)) /* - * Get a copy of a segment register. + * A function to get a segment register. */ -#define GET_SEG_REG(_r, _v) \ - do { \ - int _i; \ - GET_REG(_r, _i); \ - _v = _i & 0xffff; \ - } while (0) +static inline uint32_t +get_seg_reg(size_t reg) +{ + int v = 0; + switch (reg) { + 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. @@ -149,7 +196,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 = i386_reg_offsets; target->breakpoint = &breakpoint[0]; target->breakpoint_size = sizeof(breakpoint); return 0; @@ -158,7 +205,7 @@ rtems_debugger_target_configure(rtems_debugger_target* target) static void 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, rtems_debugger_target_exception_to_signal(frame), 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 rtems_debugger_target_enable(void) { @@ -214,25 +289,27 @@ rtems_debugger_target_read_regs(rtems_debugger_thread* thread) { if (!rtems_debugger_thread_flag(thread, 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) - regs[i] = 0xdeaddead; + for (i = 0; i < rtems_debugger_target_reg_num(); ++i) { + if (rtems_debugger_is_int_reg(i)) + rtems_debugger_set_int_reg(thread, i, 0xdeaddead); + } if (thread->frame) { CPU_Exception_frame* frame = thread->frame; - regs[REG_EAX] = frame->eax; - regs[REG_ECX] = frame->ecx; - regs[REG_EDX] = frame->edx; - regs[REG_EBX] = frame->ebx; - regs[REG_ESP] = frame->esp0; - regs[REG_EBP] = frame->ebp; - regs[REG_ESI] = frame->esi; - regs[REG_EDI] = frame->edi; - regs[REG_EIP] = frame->eip; - regs[REG_EFLAGS] = frame->eflags; - regs[REG_CS] = frame->cs; + + rtems_debugger_set_int_reg(thread, REG_EAX, frame->eax); + rtems_debugger_set_int_reg(thread, REG_ECX, frame->ecx); + rtems_debugger_set_int_reg(thread, REG_EDX, frame->edx); + rtems_debugger_set_int_reg(thread, REG_EBX, frame->ebx); + rtems_debugger_set_int_reg(thread, REG_ESP, frame->esp0); + rtems_debugger_set_int_reg(thread, REG_EBP, frame->ebp); + rtems_debugger_set_int_reg(thread, REG_ESI, frame->esi); + rtems_debugger_set_int_reg(thread, REG_EDI, frame->edi); + rtems_debugger_set_int_reg(thread, REG_EIP, frame->eip); + 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. @@ -240,16 +317,16 @@ rtems_debugger_target_read_regs(rtems_debugger_thread* thread) thread->signal = rtems_debugger_target_exception_to_signal(frame); } else { - regs[REG_EBX] = thread->tcb->Registers.ebx; - regs[REG_ESI] = thread->tcb->Registers.esi; - regs[REG_EDI] = thread->tcb->Registers.edi; - regs[REG_EFLAGS] = thread->tcb->Registers.eflags; - regs[REG_ESP] = (intptr_t) thread->tcb->Registers.esp; - regs[REG_EBP] = (intptr_t) thread->tcb->Registers.ebp; - regs[REG_EIP] = *((DB_UINT*) thread->tcb->Registers.esp); - regs[REG_EAX] = (intptr_t) thread; + rtems_debugger_set_int_reg(thread, REG_EBX, thread->tcb->Registers.ebx); + rtems_debugger_set_int_reg(thread, REG_ESI, thread->tcb->Registers.esi); + rtems_debugger_set_int_reg(thread, REG_EDI, thread->tcb->Registers.edi); + rtems_debugger_set_int_reg(thread, REG_EFLAGS, thread->tcb->Registers.eflags); + rtems_debugger_set_int_reg(thread, REG_ESP, (intptr_t) thread->tcb->Registers.esp); + rtems_debugger_set_int_reg(thread, REG_EBP, (intptr_t) thread->tcb->Registers.ebp); + rtems_debugger_set_int_reg(thread, REG_EIP, *((DB_UINT*) thread->tcb->Registers.esp)); + 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. @@ -257,11 +334,11 @@ rtems_debugger_target_read_regs(rtems_debugger_thread* thread) thread->signal = 0; } - GET_SEG_REG(SS, regs[REG_SS]); - GET_SEG_REG(DS, regs[REG_DS]); - GET_SEG_REG(ES, regs[REG_ES]); - GET_SEG_REG(FS, regs[REG_FS]); - GET_SEG_REG(GS, regs[REG_GS]); + rtems_debugger_set_int_reg(thread, REG_SS, get_seg_reg(REG_SS)); + rtems_debugger_set_int_reg(thread, REG_DS, get_seg_reg(REG_DS)); + rtems_debugger_set_int_reg(thread, REG_ES, get_seg_reg(REG_ES)); + rtems_debugger_set_int_reg(thread, REG_FS, get_seg_reg(REG_FS)); + 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_DIRTY; @@ -275,8 +352,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 threads. Do not touch the registers * 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, RTEMS_DEBUGGER_THREAD_FLAG_EXCEPTION)) { CPU_Exception_frame* frame = thread->frame; - frame->eax = regs[REG_EAX]; - frame->ecx = regs[REG_ECX]; - frame->edx = regs[REG_EDX]; - frame->ebx = regs[REG_EBX]; - frame->esp0 = regs[REG_ESP]; - frame->ebp = regs[REG_EBP]; - frame->esi = regs[REG_ESI]; - frame->edi = regs[REG_EDI]; - frame->eip = regs[REG_EIP]; - frame->eflags = regs[REG_EFLAGS]; - frame->cs = regs[REG_CS]; + frame->eax = rtems_debugger_get_int_reg(thread, REG_EAX); + frame->ecx = rtems_debugger_get_int_reg(thread, REG_ECX); + frame->edx = rtems_debugger_get_int_reg(thread, REG_EDX); + frame->ebx = rtems_debugger_get_int_reg(thread, REG_EBX); + frame->esp0 = rtems_debugger_get_int_reg(thread, REG_ESP); + frame->ebp = rtems_debugger_get_int_reg(thread, REG_EBP); + frame->esi = rtems_debugger_get_int_reg(thread, REG_ESI); + frame->edi = rtems_debugger_get_int_reg(thread, REG_EDI); + frame->eip = rtems_debugger_get_int_reg(thread, REG_EIP); + frame->eflags = rtems_debugger_get_int_reg(thread, REG_EFLAGS); + frame->cs = rtems_debugger_get_int_reg(thread, REG_CS); } thread->flags &= ~RTEMS_DEBUGGER_THREAD_FLAG_REG_DIRTY; } @@ -307,8 +382,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_EIP]; + return rtems_debugger_get_int_reg(thread, REG_EIP); } return 0; } @@ -325,8 +399,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_ESP]; + return rtems_debugger_get_int_reg(thread, REG_ESP); } return 0; } @@ -400,6 +473,18 @@ 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(" 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 rtems_debugger_target_hwbreak_insert(void) { |