File indexing completed on 2025-05-11 08:24:15
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027 #define TARGET_DEBUG 1
0028
0029 #ifdef HAVE_CONFIG_H
0030 #include "config.h"
0031 #endif
0032
0033 #include <errno.h>
0034 #include <inttypes.h>
0035 #include <stdlib.h>
0036
0037 #include <rtems.h>
0038 #include <rtems/score/threadimpl.h>
0039
0040 #include "rtems-debugger-target.h"
0041 #include "rtems-debugger-threads.h"
0042
0043
0044
0045
0046 #define RTEMS_DEBUGGER_HWBREAK_NUM 4
0047
0048
0049
0050
0051 #define RTEMS_DEBUGGER_NUMREGS 16
0052
0053
0054
0055
0056 #define RTEMS_DEBUGGER_REG_BYTES 4
0057
0058
0059
0060
0061 #define REG_EAX 0
0062 #define REG_ECX 1
0063 #define REG_EDX 2
0064 #define REG_EBX 3
0065 #define REG_ESP 4
0066 #define REG_EBP 5
0067 #define REG_ESI 6
0068 #define REG_EDI 7
0069 #define REG_PC 8
0070 #define REG_EIP REG_PC
0071 #define REG_PS 9
0072 #define REG_EFLAGS REG_PS
0073 #define REG_CS 10
0074 #define REG_SS 11
0075 #define REG_DS 12
0076 #define REG_ES 13
0077 #define REG_FS 14
0078 #define REG_GS 15
0079
0080
0081
0082
0083
0084
0085
0086
0087 static const size_t i386_reg_offsets[RTEMS_DEBUGGER_NUMREGS + 1] =
0088 {
0089 0,
0090 4,
0091 8,
0092 12,
0093 16,
0094 20,
0095 24,
0096 28,
0097 32,
0098 36,
0099 40,
0100 44,
0101 48,
0102 52,
0103 56,
0104 60,
0105 64
0106 };
0107
0108
0109
0110
0111 #define RTEMS_DEBUGGER_NUMREGBYTES i386_reg_offsets[RTEMS_DEBUGGER_NUMREGS]
0112
0113
0114
0115
0116 #define TARGET_BKPT 0xcc
0117
0118 static const uint8_t breakpoint[1] = { TARGET_BKPT };
0119
0120
0121
0122
0123 #define GET_REG(_r, _v) asm volatile("pushl %%" #_r "; popl %0" : "=rm" (_v))
0124
0125
0126
0127
0128 static inline uint32_t
0129 get_seg_reg(size_t reg)
0130 {
0131 int v = 0;
0132 switch (reg) {
0133 case REG_CS:
0134 GET_REG(CS, v);
0135 break;
0136 case REG_SS:
0137 GET_REG(SS, v);
0138 break;
0139 case REG_DS:
0140 GET_REG(DS, v);
0141 break;
0142 case REG_ES:
0143 GET_REG(ES, v);
0144 break;
0145 case REG_FS:
0146 GET_REG(FS, v);
0147 break;
0148 case REG_GS:
0149 GET_REG(GS, v);
0150 break;
0151 }
0152 return v & 0xffff;
0153 }
0154
0155
0156
0157
0158 RTEMS_INTERRUPT_LOCK_DEFINE(static, target_lock, "target_lock")
0159
0160
0161
0162
0163 static void (*orig_currentExcHandler)(CPU_Exception_frame* frame);
0164
0165 #if TARGET_DEBUG
0166 #include <rtems/bspIo.h>
0167 static void target_printk(const char* format, ...) RTEMS_PRINTFLIKE(1, 2);
0168 static void
0169 target_printk(const char* format, ...)
0170 {
0171 va_list ap;
0172 va_start(ap, format);
0173 vprintk(format, ap);
0174 va_end(ap);
0175 }
0176 #else
0177 #define target_printk(_fmt, ...)
0178 #endif
0179
0180 #if TODO
0181
0182
0183
0184 static const char* const target_xml =
0185 "<?xml version=\"1.0\"> \
0186 <!DOCTYPE target SYSTEM \"gdb-target.dtd\"> \
0187 <target version=\"1.0\"> \
0188 <architecture>i386</architecture> \
0189 <xi:include href=\"32bit-core.xml\"/> \
0190 <xi:include href=\"32bit-sse.xml\"/> \
0191 </target>";
0192 #endif
0193
0194 int
0195 rtems_debugger_target_configure(rtems_debugger_target* target)
0196 {
0197 target->capabilities = (RTEMS_DEBUGGER_TARGET_CAP_SWBREAK);
0198 target->reg_num = RTEMS_DEBUGGER_NUMREGS;
0199 target->reg_offset = i386_reg_offsets;
0200 target->breakpoint = &breakpoint[0];
0201 target->breakpoint_size = sizeof(breakpoint);
0202 return 0;
0203 }
0204
0205 static void
0206 target_exception(CPU_Exception_frame* frame)
0207 {
0208 target_printk("[} frame = %08" PRIx32 " sig=%d (%" PRIx32 ")\n",
0209 (uint32_t) frame,
0210 rtems_debugger_target_exception_to_signal(frame),
0211 frame->idtIndex);
0212 target_printk("[} EAX = %" PRIx32 " EBX = %" PRIx32 \
0213 " ECX = %" PRIx32 " EDX = %" PRIx32 "\n",
0214 frame->eax, frame->ebx, frame->ecx, frame->edx);
0215 target_printk("[} ESI = %" PRIx32 " EDI = %" PRIx32 \
0216 " EBP = %" PRIx32 " ESP = %" PRIx32 "\n",
0217 frame->esi, frame->edi, frame->ebp, frame->esp0);
0218 target_printk("[} EIP = %" PRIx32"\n", frame->eip);
0219
0220 frame->eflags &= ~EFLAGS_TRAP;
0221
0222 switch (rtems_debugger_target_exception(frame)) {
0223 case rtems_debugger_target_exc_consumed:
0224 default:
0225 break;
0226 case rtems_debugger_target_exc_step:
0227 frame->eflags |= EFLAGS_TRAP;
0228 break;
0229 case rtems_debugger_target_exc_cascade:
0230 orig_currentExcHandler(frame);
0231 break;
0232 }
0233 }
0234
0235 static bool
0236 rtems_debugger_is_int_reg(size_t reg)
0237 {
0238 const size_t size = i386_reg_offsets[reg + 1] - i386_reg_offsets[reg];
0239 return size == RTEMS_DEBUGGER_REG_BYTES;
0240 }
0241
0242 static void
0243 rtems_debugger_set_int_reg(rtems_debugger_thread* thread,
0244 size_t reg,
0245 const uint32_t value)
0246 {
0247 const size_t offset = i386_reg_offsets[reg];
0248
0249
0250
0251 memcpy(&thread->registers[offset], &value, sizeof(uint32_t));
0252 }
0253
0254 static const uint32_t
0255 rtems_debugger_get_int_reg(rtems_debugger_thread* thread, size_t reg)
0256 {
0257 const size_t offset = i386_reg_offsets[reg];
0258 uint32_t value;
0259 memcpy(&value, &thread->registers[offset], sizeof(uint32_t));
0260 return value;
0261 }
0262
0263 int
0264 rtems_debugger_target_enable(void)
0265 {
0266 rtems_interrupt_lock_context lock_context;
0267 rtems_interrupt_lock_acquire(&target_lock, &lock_context);
0268 if (orig_currentExcHandler == NULL) {
0269 orig_currentExcHandler = _currentExcHandler;
0270 _currentExcHandler = target_exception;
0271 }
0272 rtems_interrupt_lock_release(&target_lock, &lock_context);
0273 return 0;
0274 }
0275
0276 int
0277 rtems_debugger_target_disable(void)
0278 {
0279 rtems_interrupt_lock_context lock_context;
0280 rtems_interrupt_lock_acquire(&target_lock, &lock_context);
0281 if (orig_currentExcHandler != NULL)
0282 _currentExcHandler = orig_currentExcHandler;
0283 rtems_interrupt_lock_release(&target_lock, &lock_context);
0284 return 0;
0285 }
0286
0287 int
0288 rtems_debugger_target_read_regs(rtems_debugger_thread* thread)
0289 {
0290 if (!rtems_debugger_thread_flag(thread,
0291 RTEMS_DEBUGGER_THREAD_FLAG_REG_VALID)) {
0292 size_t i;
0293
0294 for (i = 0; i < rtems_debugger_target_reg_num(); ++i) {
0295 if (rtems_debugger_is_int_reg(i))
0296 rtems_debugger_set_int_reg(thread, i, 0xdeaddead);
0297 }
0298
0299 if (thread->frame) {
0300 CPU_Exception_frame* frame = thread->frame;
0301
0302 rtems_debugger_set_int_reg(thread, REG_EAX, frame->eax);
0303 rtems_debugger_set_int_reg(thread, REG_ECX, frame->ecx);
0304 rtems_debugger_set_int_reg(thread, REG_EDX, frame->edx);
0305 rtems_debugger_set_int_reg(thread, REG_EBX, frame->ebx);
0306 rtems_debugger_set_int_reg(thread, REG_ESP, frame->esp0);
0307 rtems_debugger_set_int_reg(thread, REG_EBP, frame->ebp);
0308 rtems_debugger_set_int_reg(thread, REG_ESI, frame->esi);
0309 rtems_debugger_set_int_reg(thread, REG_EDI, frame->edi);
0310 rtems_debugger_set_int_reg(thread, REG_EIP, frame->eip);
0311 rtems_debugger_set_int_reg(thread, REG_EFLAGS, frame->eflags);
0312 rtems_debugger_set_int_reg(thread, REG_CS, frame->cs);
0313
0314
0315
0316
0317 thread->signal = rtems_debugger_target_exception_to_signal(frame);
0318 }
0319 else {
0320 rtems_debugger_set_int_reg(thread, REG_EBX, thread->tcb->Registers.ebx);
0321 rtems_debugger_set_int_reg(thread, REG_ESI, thread->tcb->Registers.esi);
0322 rtems_debugger_set_int_reg(thread, REG_EDI, thread->tcb->Registers.edi);
0323 rtems_debugger_set_int_reg(thread, REG_EFLAGS, thread->tcb->Registers.eflags);
0324 rtems_debugger_set_int_reg(thread, REG_ESP, (intptr_t) thread->tcb->Registers.esp);
0325 rtems_debugger_set_int_reg(thread, REG_EBP, (intptr_t) thread->tcb->Registers.ebp);
0326 rtems_debugger_set_int_reg(thread, REG_EIP, *((DB_UINT*) thread->tcb->Registers.esp));
0327 rtems_debugger_set_int_reg(thread, REG_EAX, (intptr_t) thread);
0328
0329 rtems_debugger_set_int_reg(thread, REG_CS, get_seg_reg(REG_CS));
0330
0331
0332
0333
0334 thread->signal = 0;
0335 }
0336
0337 rtems_debugger_set_int_reg(thread, REG_SS, get_seg_reg(REG_SS));
0338 rtems_debugger_set_int_reg(thread, REG_DS, get_seg_reg(REG_DS));
0339 rtems_debugger_set_int_reg(thread, REG_ES, get_seg_reg(REG_ES));
0340 rtems_debugger_set_int_reg(thread, REG_FS, get_seg_reg(REG_FS));
0341 rtems_debugger_set_int_reg(thread, REG_GS, get_seg_reg(REG_GS));
0342
0343 thread->flags |= RTEMS_DEBUGGER_THREAD_FLAG_REG_VALID;
0344 thread->flags &= ~RTEMS_DEBUGGER_THREAD_FLAG_REG_DIRTY;
0345 }
0346
0347 return 0;
0348 }
0349
0350 int
0351 rtems_debugger_target_write_regs(rtems_debugger_thread* thread)
0352 {
0353 if (rtems_debugger_thread_flag(thread,
0354 RTEMS_DEBUGGER_THREAD_FLAG_REG_DIRTY)) {
0355
0356
0357
0358
0359 if (rtems_debugger_thread_flag(thread,
0360 RTEMS_DEBUGGER_THREAD_FLAG_EXCEPTION)) {
0361 CPU_Exception_frame* frame = thread->frame;
0362 frame->eax = rtems_debugger_get_int_reg(thread, REG_EAX);
0363 frame->ecx = rtems_debugger_get_int_reg(thread, REG_ECX);
0364 frame->edx = rtems_debugger_get_int_reg(thread, REG_EDX);
0365 frame->ebx = rtems_debugger_get_int_reg(thread, REG_EBX);
0366 frame->esp0 = rtems_debugger_get_int_reg(thread, REG_ESP);
0367 frame->ebp = rtems_debugger_get_int_reg(thread, REG_EBP);
0368 frame->esi = rtems_debugger_get_int_reg(thread, REG_ESI);
0369 frame->edi = rtems_debugger_get_int_reg(thread, REG_EDI);
0370 frame->eip = rtems_debugger_get_int_reg(thread, REG_EIP);
0371 frame->eflags = rtems_debugger_get_int_reg(thread, REG_EFLAGS);
0372 frame->cs = rtems_debugger_get_int_reg(thread, REG_CS);
0373 }
0374 thread->flags &= ~RTEMS_DEBUGGER_THREAD_FLAG_REG_DIRTY;
0375 }
0376 return 0;
0377 }
0378
0379 uintptr_t
0380 rtems_debugger_target_reg_pc(rtems_debugger_thread* thread)
0381 {
0382 int r;
0383 r = rtems_debugger_target_read_regs(thread);
0384 if (r >= 0) {
0385 return rtems_debugger_get_int_reg(thread, REG_EIP);
0386 }
0387 return 0;
0388 }
0389
0390 uintptr_t
0391 rtems_debugger_target_frame_pc(CPU_Exception_frame* frame)
0392 {
0393 return (uintptr_t) frame->eip;
0394 }
0395
0396 uintptr_t
0397 rtems_debugger_target_reg_sp(rtems_debugger_thread* thread)
0398 {
0399 int r;
0400 r = rtems_debugger_target_read_regs(thread);
0401 if (r >= 0) {
0402 return rtems_debugger_get_int_reg(thread, REG_ESP);
0403 }
0404 return 0;
0405 }
0406
0407 uintptr_t
0408 rtems_debugger_target_tcb_sp(rtems_debugger_thread* thread)
0409 {
0410 return (DB_UINT) thread->tcb->Registers.esp;
0411 }
0412
0413 int
0414 rtems_debugger_target_thread_stepping(rtems_debugger_thread* thread)
0415 {
0416 if (rtems_debugger_thread_flag(thread,
0417 (RTEMS_DEBUGGER_THREAD_FLAG_STEP |
0418 RTEMS_DEBUGGER_THREAD_FLAG_STEPPING))) {
0419 CPU_Exception_frame* frame = thread->frame;
0420
0421
0422
0423
0424 if ((frame->eflags & EFLAGS_INTR_ENABLE) == 0)
0425 thread->flags |= RTEMS_DEBUGGER_THREAD_FLAG_INTS_DISABLED;
0426 else
0427 frame->eflags &= ~EFLAGS_INTR_ENABLE;
0428 frame->eflags |= EFLAGS_TRAP;
0429 }
0430 return 0;
0431 }
0432
0433 int
0434 rtems_debugger_target_exception_to_signal(CPU_Exception_frame* frame)
0435 {
0436 int sig = RTEMS_DEBUGGER_SIGNAL_HUP;
0437 switch (frame->idtIndex) {
0438 case 1:
0439 case 3:
0440 sig = RTEMS_DEBUGGER_SIGNAL_TRAP;
0441 break;
0442 case 4:
0443 case 5:
0444 sig = RTEMS_DEBUGGER_SIGNAL_URG;
0445 break;
0446 case 6:
0447 sig = RTEMS_DEBUGGER_SIGNAL_ILL;
0448 break;
0449 case 8:
0450 case 16:
0451 sig = RTEMS_DEBUGGER_SIGNAL_EMT;
0452 break;
0453 case 0:
0454 case 7:
0455 sig = RTEMS_DEBUGGER_SIGNAL_FPE;
0456 break;
0457 case 9:
0458 case 10:
0459 case 11:
0460 case 12:
0461 case 13:
0462 case 14:
0463 case 17:
0464 sig = RTEMS_DEBUGGER_SIGNAL_SEGV;
0465 break;
0466 case 2:
0467 case 18:
0468 sig = RTEMS_DEBUGGER_SIGNAL_BUS;
0469 break;
0470 default:
0471 break;
0472 }
0473 return sig;
0474 }
0475
0476 void
0477 rtems_debugger_target_exception_print(CPU_Exception_frame* frame)
0478 {
0479 rtems_debugger_printf(" EAX = %" PRIx32 " EBX = %" PRIx32 \
0480 " ECX = %" PRIx32 " EDX = %" PRIx32 "\n",
0481 frame->eax, frame->ebx, frame->ecx, frame->edx);
0482 rtems_debugger_printf(" ESI = %" PRIx32 " EDI = %" PRIx32 \
0483 " EBP = %" PRIx32 " ESP = %" PRIx32 "\n",
0484 frame->esi, frame->edi, frame->ebp, frame->esp0);
0485 rtems_debugger_printf(" EIP = %" PRIx32"\n", frame->eip);
0486 }
0487
0488 int
0489 rtems_debugger_target_hwbreak_insert(void)
0490 {
0491
0492
0493
0494 return 0;
0495 }
0496
0497 int
0498 rtems_debugger_target_hwbreak_remove(void)
0499 {
0500 return 0;
0501 }
0502
0503 int
0504 rtems_debugger_target_hwbreak_control(rtems_debugger_target_watchpoint wp,
0505 bool insert,
0506 uintptr_t addr,
0507 DB_UINT kind)
0508 {
0509
0510
0511
0512 return 0;
0513 }
0514
0515 int
0516 rtems_debugger_target_cache_sync(rtems_debugger_target_swbreak* swbreak)
0517 {
0518
0519
0520
0521 return 0;
0522 }