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 RTEMS_DEBUGGER_VERBOSE_LOCK 0
0028
0029 #include <errno.h>
0030 #include <inttypes.h>
0031 #include <stdlib.h>
0032 #include <unistd.h>
0033
0034 #include <rtems/bspIo.h>
0035 #include <rtems/score/smp.h>
0036
0037 #include <rtems/rtems-debugger.h>
0038 #include <rtems/debugger/rtems-debugger-server.h>
0039 #include <rtems/debugger/rtems-debugger-remote.h>
0040
0041 #include "rtems-debugger-target.h"
0042 #include "rtems-debugger-threads.h"
0043
0044
0045
0046
0047
0048
0049
0050
0051 typedef int (*rtems_debugger_command)(uint8_t* buffer, int size);
0052
0053 typedef struct rtems_debugger_packet
0054 {
0055 const char* const label;
0056 rtems_debugger_command command;
0057 } rtems_debugger_packet;
0058
0059
0060
0061
0062 static const char* const r_OK = "OK";
0063 static const char* const r_E01 = "E01";
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076 rtems_debugger_server* rtems_debugger;
0077
0078
0079
0080
0081
0082 RTEMS_INTERRUPT_LOCK_DEFINE(static, printk_lock, "printk_lock")
0083
0084 void
0085 rtems_debugger_printk_lock(rtems_interrupt_lock_context* lock_context)
0086 {
0087 rtems_interrupt_lock_acquire(&printk_lock, lock_context);
0088 }
0089
0090 void
0091 rtems_debugger_printk_unlock(rtems_interrupt_lock_context* lock_context)
0092 {
0093 rtems_interrupt_lock_release(&printk_lock, lock_context);
0094 }
0095
0096 int
0097 rtems_debugger_clean_printf(const char* format, ...)
0098 {
0099 rtems_interrupt_lock_context lock_context;
0100 int len;
0101 va_list ap;
0102 va_start(ap, format);
0103 rtems_debugger_printk_lock(&lock_context);
0104 len = vprintk(format, ap);
0105 rtems_debugger_printk_unlock(&lock_context);
0106 va_end(ap);
0107 return len;
0108 }
0109
0110 int
0111 rtems_debugger_printf(const char* format, ...)
0112 {
0113 rtems_interrupt_lock_context lock_context;
0114 int len;
0115 va_list ap;
0116 va_start(ap, format);
0117 rtems_debugger_printk_lock(&lock_context);
0118 printk("[CPU:%d] ", (int) _SMP_Get_current_processor ());
0119 len = vprintk(format, ap);
0120 rtems_debugger_printk_unlock(&lock_context);
0121 va_end(ap);
0122 return len;
0123 }
0124
0125 bool
0126 rtems_debugger_verbose(void)
0127 {
0128 return rtems_debugger_server_flag(RTEMS_DEBUGGER_FLAG_VERBOSE);
0129 }
0130
0131 static inline int
0132 hex_decode(uint8_t ch)
0133 {
0134 int i;
0135 if (ch >= '0' && ch <= '9')
0136 i = (int) (ch - '0');
0137 else if (ch >= 'a' && ch <= 'f')
0138 i = (int) (ch - 'a') + 10;
0139 else if (ch >= 'A' && ch <= 'F')
0140 i = (int) (ch - 'A') + 10;
0141 else
0142 i = -1;
0143 return i;
0144 }
0145
0146 static inline uint8_t
0147 hex_encode(int val)
0148 {
0149 return "0123456789abcdef"[val & 0xf];
0150 }
0151
0152 static inline uintptr_t
0153 hex_decode_addr(const uint8_t* data)
0154 {
0155 uintptr_t ui = 0;
0156 size_t i;
0157 if (data[0] == '-') {
0158 if (data[1] == '1')
0159 ui = (uintptr_t) -1;
0160 }
0161 else {
0162 for (i = 0; i < (sizeof(ui) * 2); ++i) {
0163 int v = hex_decode(data[i]);
0164 if (v < 0)
0165 break;
0166 ui = (ui << 4) | v;
0167 }
0168 }
0169 return ui;
0170 }
0171
0172 static inline DB_UINT
0173 hex_decode_uint(const uint8_t* data)
0174 {
0175 DB_UINT ui = 0;
0176 size_t i;
0177 if (data[0] == '-') {
0178 if (data[1] == '1')
0179 ui = (DB_UINT) -1;
0180 }
0181 else {
0182 for (i = 0; i < (sizeof(ui) * 2); ++i) {
0183 int v = hex_decode(data[i]);
0184 if (v < 0)
0185 break;
0186 ui = (ui << 4) | v;
0187 }
0188 }
0189 return ui;
0190 }
0191
0192 static inline int
0193 hex_decode_int(const uint8_t* data)
0194 {
0195 return (int) hex_decode_uint(data);
0196 }
0197
0198 static bool
0199 thread_id_decode(const char* data, DB_UINT* pid, DB_UINT* tid)
0200 {
0201 bool is_extended = false;
0202 if (*data == 'p') {
0203 is_extended = true;
0204 ++data;
0205 }
0206 *pid = *tid = hex_decode_uint((const uint8_t*) data);
0207 if (is_extended) {
0208 const char* stop = strchr(data, '.');
0209 if (stop != NULL) {
0210 *tid = hex_decode_uint((const uint8_t*) stop + 1);
0211 }
0212 }
0213 return is_extended;
0214 }
0215
0216 static inline bool
0217 check_pid(DB_UINT pid)
0218 {
0219 return pid == 0 || rtems_debugger->pid == (pid_t) pid;
0220 }
0221
0222 void
0223 rtems_debugger_lock(void)
0224 {
0225 _Mutex_recursive_Acquire(&rtems_debugger->lock);
0226 }
0227
0228 void
0229 rtems_debugger_unlock(void)
0230 {
0231 _Mutex_recursive_Release(&rtems_debugger->lock);
0232 }
0233
0234 static int
0235 rtems_debugger_lock_create(void)
0236 {
0237 _Mutex_recursive_Initialize_named(&rtems_debugger->lock, "DBlock");
0238 return 0;
0239 }
0240
0241 static int
0242 rtems_debugger_lock_destroy(void)
0243 {
0244 return 0;
0245 }
0246
0247 static int
0248 rtems_debugger_task_create(const char* name,
0249 rtems_task_priority priority,
0250 size_t stack_size,
0251 rtems_task_entry entry_point,
0252 rtems_task_argument argument,
0253 rtems_id* id)
0254 {
0255 rtems_name tname;
0256 rtems_status_code sc;
0257
0258 tname = rtems_build_name(name[0], name[1], name[2], name[3]);
0259
0260 sc = rtems_task_create (tname,
0261 priority,
0262 stack_size,
0263 RTEMS_PREEMPT | RTEMS_NO_ASR,
0264 RTEMS_LOCAL | RTEMS_FLOATING_POINT,
0265 id);
0266 if (sc != RTEMS_SUCCESSFUL) {
0267 *id = 0;
0268 rtems_debugger_printf("error: rtems-db: thread create: %s: %s\n",
0269 name, rtems_status_text(sc));
0270 errno = EIO;
0271 return -1;
0272 }
0273
0274 sc = rtems_task_start(*id, entry_point, argument);
0275 if (sc != RTEMS_SUCCESSFUL) {
0276 rtems_debugger_printf("error: rtems-db: thread start: %s: %s\n",
0277 name, rtems_status_text(sc));
0278 rtems_task_delete(*id);
0279 *id = 0;
0280 errno = EIO;
0281 return -1;
0282 }
0283
0284 return 0;
0285 }
0286
0287 static int
0288 rtems_debugger_task_destroy(const char* name,
0289 rtems_id id,
0290 volatile bool* finished,
0291 int timeout)
0292 {
0293 while (timeout) {
0294 bool has_finished;
0295
0296 rtems_debugger_lock();
0297 has_finished = *finished;
0298 rtems_debugger_unlock();
0299
0300 if (has_finished)
0301 break;
0302
0303 usleep(RTEMS_DEBUGGER_POLL_WAIT);
0304 if (timeout < RTEMS_DEBUGGER_POLL_WAIT)
0305 timeout = 0;
0306 else
0307 timeout -= RTEMS_DEBUGGER_POLL_WAIT;
0308 }
0309
0310 if (timeout == 0) {
0311 rtems_debugger_printf("rtems-db: %s not stopping, killing\n", name);
0312 rtems_task_delete(id);
0313 }
0314 return 0;
0315 }
0316
0317 bool
0318 rtems_debugger_server_running(void)
0319 {
0320 bool running;
0321 rtems_debugger_lock();
0322 running = rtems_debugger->server_running;
0323 rtems_debugger_unlock();
0324 return running;
0325 }
0326
0327 rtems_debugger_remote*
0328 rtems_debugger_remote_handle(void)
0329 {
0330 rtems_debugger_remote* remote;
0331 rtems_debugger_lock();
0332 remote = rtems_debugger->remote;
0333 rtems_debugger_unlock();
0334 return remote;
0335 }
0336
0337 bool
0338 rtems_debugger_connected(void)
0339 {
0340 bool isconnected = false;
0341 rtems_debugger_lock();
0342 if (rtems_debugger->remote != NULL)
0343 isconnected = rtems_debugger->remote->isconnected(rtems_debugger->remote);
0344 rtems_debugger_unlock();
0345 return isconnected;
0346 }
0347
0348 bool
0349 rtems_debugger_server_events_running(void)
0350 {
0351 return rtems_debugger->events_running;
0352 }
0353
0354 void
0355 rtems_debugger_server_events_signal(void)
0356 {
0357 _Condition_Signal(&rtems_debugger->server_cond);
0358 }
0359
0360 static void
0361 rtems_debugger_server_events_wait(void)
0362 {
0363 _Condition_Wait_recursive(&rtems_debugger->server_cond, &rtems_debugger->lock);
0364 }
0365
0366 static int
0367 rtems_debugger_remote_connect(void)
0368 {
0369 rtems_debugger_remote* remote = rtems_debugger_remote_handle();
0370 if (remote != NULL) {
0371 if (!remote->isconnected(remote))
0372 return remote->connect(remote);
0373 }
0374 errno = EIO;
0375 return -1;
0376 }
0377
0378 static int
0379 rtems_debugger_remote_disconnect(void)
0380 {
0381 rtems_debugger_remote* remote = rtems_debugger_remote_handle();
0382 if (remote != NULL) {
0383 if (remote->isconnected(remote))
0384 return remote->disconnect(remote);
0385 }
0386 errno = EIO;
0387 return -1;
0388 }
0389
0390 static int
0391 rtems_debugger_remote_receive(uint8_t* buffer, size_t size)
0392 {
0393 rtems_debugger_remote* remote = rtems_debugger_remote_handle();
0394 ssize_t len = remote->read(remote, buffer, size);
0395 if (len < 0 && errno != EAGAIN)
0396 rtems_debugger_printf("rtems-db: read: (%d) %s\n",
0397 errno, strerror(errno));
0398 return (int) len;
0399 }
0400
0401 static int
0402 rtems_debugger_remote_send(void)
0403 {
0404 const uint8_t* buffer = rtems_debugger->output;
0405 ssize_t size = rtems_debugger->output_level;
0406
0407 if (rtems_debugger->output_level > RTEMS_DEBUGGER_BUFFER_SIZE) {
0408 rtems_debugger_printf("rtems-db: write too big: %d\n",
0409 (int) rtems_debugger->output_level);
0410 return -1;
0411 }
0412
0413 if (rtems_debugger->remote_debug) {
0414 size_t i = 0;
0415 rtems_debugger_printf("rtems-db: put:%4zu: ", rtems_debugger->output_level);
0416 while (i < rtems_debugger->output_level)
0417 rtems_debugger_clean_printf("%c", (char) rtems_debugger->output[i++]);
0418 rtems_debugger_clean_printf("\n");
0419 }
0420
0421 while (size) {
0422 rtems_debugger_remote* remote = rtems_debugger_remote_handle();
0423 ssize_t w;
0424 if (remote == NULL) {
0425 errno = EIO;
0426 return -1;
0427 }
0428 w = remote->write(remote, buffer, size);
0429 if (w < 0 && errno != EINTR) {
0430 rtems_debugger_printf("rtems-db: write: (%d) %s\n",
0431 errno, strerror(errno));
0432 break;
0433 }
0434 else {
0435 size -= w;
0436 buffer += w;
0437 }
0438 }
0439
0440 return (int) rtems_debugger->output_level;
0441 }
0442
0443 static int
0444 rtems_debugger_remote_send_ack(void)
0445 {
0446 rtems_debugger->output[0] = '+';
0447 rtems_debugger->output_level = 1;
0448 return rtems_debugger_remote_send();
0449 }
0450
0451 static int
0452 rtems_debugger_remote_send_nack(void)
0453 {
0454 rtems_debugger->output[0] = '-';
0455 rtems_debugger->output_level = 1;
0456 return rtems_debugger_remote_send();
0457 }
0458
0459 static int
0460 rtems_debugger_remote_packet_in(void)
0461 {
0462 uint8_t buf[256];
0463 uint8_t state;
0464 int in = 0;
0465 uint8_t csum = 0;
0466 uint8_t rx_csum = 0;
0467 bool junk = false;
0468 bool escaped = false;
0469 bool remote_debug_header = true;
0470
0471
0472
0473
0474
0475
0476
0477
0478
0479
0480 state = 'H';
0481
0482 while (state != 'F') {
0483 int r;
0484 int i;
0485
0486 rtems_debugger_unlock();
0487
0488 r = rtems_debugger_remote_receive(buf, sizeof(buf));
0489
0490 rtems_debugger_lock();
0491
0492 if (r <= 0) {
0493
0494
0495
0496 if (r < 0 && errno == EAGAIN) {
0497 if (rtems_debugger->ack_pending) {
0498 rtems_debugger_remote_send();
0499 }
0500 continue;
0501 }
0502 if (r == 0)
0503 rtems_debugger_printf("rtems-db: remote disconnected\n");
0504 return -1;
0505 }
0506
0507 i = 0;
0508
0509 while (i < r) {
0510 uint8_t c = buf[i++];
0511
0512 if (rtems_debugger->remote_debug && remote_debug_header) {
0513 rtems_debugger_printf("rtems-db: get:%4d: ", r);
0514 remote_debug_header = false;
0515 }
0516
0517 if (rtems_debugger->remote_debug)
0518 rtems_debugger_clean_printf("%c", c);
0519
0520 switch (state) {
0521 case 'H':
0522 switch (c) {
0523 case '+':
0524 if (rtems_debugger->remote_debug) {
0525 rtems_debugger_clean_printf(" [[ACK%s]]\n",
0526 rtems_debugger->ack_pending ? "" : "?");
0527 remote_debug_header = true;
0528 }
0529 rtems_debugger->ack_pending = false;
0530 break;
0531 case '-':
0532 if (rtems_debugger->remote_debug) {
0533 rtems_debugger_clean_printf(" [[NACK]]\n");
0534 remote_debug_header = true;
0535 }
0536
0537
0538
0539 rtems_debugger_remote_send();
0540 break;
0541 case '$':
0542 state = 'P';
0543 csum = 0;
0544 in = 0;
0545 if (junk && rtems_debugger->remote_debug) {
0546 rtems_debugger_clean_printf("\b [[junk dropped]]\nrtems-db: get: : $");
0547 remote_debug_header = false;
0548 }
0549 break;
0550 case '\x3':
0551 if (rtems_debugger->remote_debug)
0552 rtems_debugger_clean_printf("^C [[BREAK]]\n");
0553 rtems_debugger->ack_pending = false;
0554 rtems_debugger->input[0] = '^';
0555 rtems_debugger->input[1] = 'C';
0556 rtems_debugger->input[2] = '\0';
0557 return 2;
0558 default:
0559 junk = true;
0560 break;
0561 }
0562 break;
0563 case 'P':
0564 if (c == '{' && !escaped) {
0565 escaped = true;
0566 }
0567 else if (c == '$' && !escaped) {
0568 csum = 0;
0569 in = 0;
0570 if (rtems_debugger->remote_debug) {
0571 rtems_debugger_clean_printf("\n");
0572 remote_debug_header = true;
0573 }
0574 }
0575 else if (c == '#' && !escaped) {
0576 rtems_debugger->input[in] = '\0';
0577 rx_csum = 0;
0578 state = '1';
0579 }
0580 else {
0581 if (in >= (RTEMS_DEBUGGER_BUFFER_SIZE - 1)) {
0582 rtems_debugger_printf("rtems-db: input buffer overflow\n");
0583 return -1;
0584 }
0585 csum += c;
0586 rtems_debugger->input[in++] = c;
0587 }
0588 break;
0589 case '1':
0590 rx_csum = (rx_csum << 4) | (uint8_t) hex_decode(c);
0591 state = '2';
0592 break;
0593 case '2':
0594 rx_csum = (rx_csum << 4) | (uint8_t) hex_decode(c);
0595 if (csum == rx_csum) {
0596 state = 'F';
0597 if (rtems_debugger->remote_debug)
0598 rtems_debugger_clean_printf("\n");
0599 rtems_debugger_remote_send_ack();
0600 }
0601 else {
0602 if (rtems_debugger->remote_debug) {
0603 rtems_debugger_clean_printf(" [[invalid checksum]]\n");
0604 remote_debug_header = true;
0605 rtems_debugger_remote_send_nack();
0606 }
0607 state = 'H';
0608 }
0609 break;
0610 case 'F':
0611 if (rtems_debugger->remote_debug)
0612 rtems_debugger_clean_printf(" [[extra data: 0x%02x]]", (int) c);
0613 break;
0614 default:
0615 rtems_debugger_printf("rtems-db: bad state\n");
0616 rtems_debugger_remote_send_nack();
0617 return -1;
0618 }
0619 }
0620 }
0621
0622 return in;
0623 }
0624
0625 static int
0626 rtems_debugger_remote_packet_in_hex(uint8_t* addr,
0627 const char* data,
0628 size_t size)
0629 {
0630 size_t i;
0631 for (i = 0; i < size; ++i) {
0632 *addr = (hex_decode(*data++) << 4);
0633 *addr++ |= hex_decode(*data++);
0634 }
0635 return 0;
0636 }
0637
0638 #if KEEP_INCASE
0639 static void
0640 remote_packet_out_rewind(size_t size)
0641 {
0642 size_t i = 0;
0643 while (rtems_debugger->output_level > 0 && i < size) {
0644 if (rtems_debugger->output_level > 1) {
0645 if (rtems_debugger->output[rtems_debugger->output_level - 1] == '}') {
0646 --rtems_debugger->output_level;
0647 }
0648 }
0649 --rtems_debugger->output_level;
0650 --i;
0651 }
0652 }
0653 #endif
0654
0655 static int
0656 remote_packet_out_append_buffer(const char* buffer, size_t size)
0657 {
0658 size_t ol = rtems_debugger->output_level;
0659 size_t i = 0;
0660 while (i < size) {
0661 char c = buffer[i++];
0662 if (c == '#' || c == '$') {
0663 if (rtems_debugger->output_level >= (RTEMS_DEBUGGER_BUFFER_SIZE - 1)) {
0664 rtems_debugger->output_level = ol;
0665 rtems_debugger_printf("rtems-db: output overflow\n");
0666 return -1;
0667 }
0668 rtems_debugger->output[rtems_debugger->output_level++] = '}';
0669 c ^= 0x20;
0670 }
0671 if (rtems_debugger->output_level >= (RTEMS_DEBUGGER_BUFFER_SIZE - 1)) {
0672 rtems_debugger->output_level = ol;
0673 rtems_debugger_printf("rtems-db: output overflow\n");
0674 return -1;
0675 }
0676 rtems_debugger->output[rtems_debugger->output_level++] = c;
0677 }
0678 return 0;
0679 }
0680
0681 static int
0682 remote_packet_out_append_hex(const uint8_t* data, size_t size)
0683 {
0684 size_t ol = rtems_debugger->output_level;
0685 size_t i = 0;
0686 while (i < size) {
0687 uint8_t byte = data[i++];
0688 if (rtems_debugger->output_level >= (RTEMS_DEBUGGER_BUFFER_SIZE - 2)) {
0689 rtems_debugger->output_level = ol;
0690 rtems_debugger_printf("rtems-db: output overflow\n");
0691 return -1;
0692 }
0693 rtems_debugger->output[rtems_debugger->output_level++] = hex_encode(byte >> 4);
0694 rtems_debugger->output[rtems_debugger->output_level++] = hex_encode(byte);
0695 }
0696 return 0;
0697 }
0698
0699 static int
0700 remote_packet_out_append_str(const char* str)
0701 {
0702 return remote_packet_out_append_buffer(str, strlen(str));
0703 }
0704
0705 static int
0706 remote_packet_out_append_vprintf(const char* fmt, va_list ap)
0707 {
0708 int len;
0709 char buffer[64];
0710 len = vsnprintf(buffer, sizeof(buffer), fmt, ap);
0711 return remote_packet_out_append_buffer(buffer, len);
0712 }
0713
0714 static int
0715 remote_packet_out_append(const char* fmt, ...)
0716 {
0717 va_list ap;
0718 int r;
0719 va_start(ap, fmt);
0720 r = remote_packet_out_append_vprintf(fmt, ap);
0721 va_end(ap);
0722 return r;
0723 }
0724
0725 static void
0726 remote_packet_out_reset(void)
0727 {
0728 rtems_debugger->output_level = 1;
0729 rtems_debugger->output[0] = '$';
0730 }
0731
0732 static int
0733 remote_packet_out_buffer(const char* buffer, size_t size)
0734 {
0735 remote_packet_out_reset();
0736 return remote_packet_out_append_buffer(buffer, size);
0737 }
0738
0739 static int
0740 remote_packet_out_str(const char* str)
0741 {
0742 remote_packet_out_reset();
0743 return remote_packet_out_append_buffer(str, strlen(str));
0744 }
0745
0746 static int
0747 remote_packet_out(const char* fmt, ...)
0748 {
0749 va_list ap;
0750 int r;
0751 va_start(ap, fmt);
0752 remote_packet_out_reset();
0753 r = remote_packet_out_append_vprintf(fmt, ap);
0754 va_end(ap);
0755 return r;
0756 }
0757
0758 static int
0759 remote_packet_out_send(void)
0760 {
0761 uint8_t csum = 0;
0762 size_t i = 1;
0763
0764 if (rtems_debugger->output_level >= (RTEMS_DEBUGGER_BUFFER_SIZE - 3)) {
0765 rtems_debugger_printf("rtems-db: output overflow\n");
0766 return -1;
0767 }
0768
0769 while (i < rtems_debugger->output_level) {
0770 csum += rtems_debugger->output[i++];
0771 }
0772
0773 rtems_debugger->output[rtems_debugger->output_level++] = '#';
0774 rtems_debugger->output[rtems_debugger->output_level++] = hex_encode((csum >> 4) & 0xf);
0775 rtems_debugger->output[rtems_debugger->output_level++] = hex_encode(csum & 0xf);
0776
0777 rtems_debugger->ack_pending = true;;
0778
0779 return rtems_debugger_remote_send();
0780 }
0781
0782 static int
0783 remote_packet_dispatch(const rtems_debugger_packet* packet,
0784 size_t packets,
0785 uint8_t* buffer,
0786 int size)
0787 {
0788 const rtems_debugger_packet* p;
0789 size_t i;
0790 int r = -1;
0791 for (i = 0, p = &packet[0]; i < packets; ++i, ++p) {
0792 if (strncmp(p->label,
0793 (const char*) &buffer[0],
0794 strlen(p->label)) == 0) {
0795 if (rtems_debugger_server_flag(RTEMS_DEBUGGER_FLAG_VERBOSE_CMDS))
0796 rtems_debugger_printf("rtems-db: cmd: %s [%d] '%s'\n",
0797 p->label, size, (const char*) buffer);
0798 r = p->command(buffer, size);
0799 break;
0800 }
0801 }
0802 if (r < 0) {
0803 remote_packet_out_buffer("", 0);
0804 remote_packet_out_send();
0805 }
0806 return 0;
0807 }
0808
0809 static int
0810 remote_detach(uint8_t* buffer, int size)
0811 {
0812 remote_packet_out_str(r_OK);
0813 remote_packet_out_send();
0814 rtems_debugger_remote_disconnect();
0815 return 0;
0816 }
0817
0818 static int
0819 remote_ut_features(uint8_t* buffer, int size)
0820 {
0821 return -1;
0822 }
0823
0824 static int
0825 remote_ut_osdata(uint8_t* buffer, int size)
0826 {
0827 return -1;
0828 }
0829
0830 static const rtems_debugger_packet uninterpreted_transfer[] = {
0831 { .label = "qXfer:features",
0832 .command = remote_ut_features },
0833 { .label = "qXfer:osdata",
0834 .command = remote_ut_osdata },
0835 };
0836
0837 #define REMOTE_UNINTERPRETED_TRANSFERS \
0838 RTEMS_DEBUGGER_NUMOF(uninterpreted_transfer)
0839
0840 static int
0841 remote_gq_uninterpreted_transfer(uint8_t* buffer, int size)
0842 {
0843 return remote_packet_dispatch(uninterpreted_transfer,
0844 REMOTE_UNINTERPRETED_TRANSFERS,
0845 buffer, size);
0846 }
0847
0848 static int
0849 remote_gq_thread_info_subsequent(uint8_t* buffer, int size)
0850 {
0851 rtems_debugger_threads* threads = rtems_debugger->threads;
0852 if (threads->next >= threads->current.level)
0853 remote_packet_out_str("l");
0854 else {
0855 rtems_debugger_thread* current;
0856 const char* format = "p%d.%08lx";
0857 current = rtems_debugger_thread_current(threads);
0858 remote_packet_out_str("m");
0859 while (threads->next < threads->current.level) {
0860 int r;
0861 r = remote_packet_out_append(format,
0862 rtems_debugger->pid,
0863 current[threads->next].id);
0864 if (r < 0)
0865 break;
0866 format = ",p%d.%08lx";
0867 ++threads->next;
0868 }
0869 }
0870 remote_packet_out_send();
0871 return 0;
0872 }
0873
0874 static int
0875 remote_gq_thread_info_first(uint8_t* buffer, int size)
0876 {
0877 rtems_debugger->threads->next = 0;
0878 return remote_gq_thread_info_subsequent(buffer, size);
0879 }
0880
0881 static int
0882 remote_gq_thread_extra_info(uint8_t* buffer, int size)
0883 {
0884 const char* comma;
0885 remote_packet_out_reset();
0886 comma = strchr((const char*) buffer, ',');
0887 if (comma != NULL) {
0888 DB_UINT pid = 0;
0889 DB_UINT tid = 0;
0890 bool extended;
0891 extended = thread_id_decode(comma + 1, &pid, &tid);
0892 if (extended || check_pid(pid)) {
0893 int r;
0894 r = rtems_debugger_thread_find_index(tid);
0895 if (r >= 0) {
0896 rtems_debugger_threads* threads = rtems_debugger->threads;
0897 rtems_debugger_thread* current;
0898 rtems_debugger_thread* thread;
0899 char buf[128];
0900 char str[32];
0901 size_t l;
0902 current = rtems_debugger_thread_current(threads);
0903 thread = ¤t[r];
0904 l = snprintf(buf, sizeof(buf),
0905 "%4s (%08" PRIx32 "), ", thread->name, thread->id);
0906 remote_packet_out_append_hex((const uint8_t*) buf, l);
0907 l = snprintf(buf, sizeof(buf),
0908 "priority(c:%3d r:%3d), ",
0909 rtems_debugger_thread_current_priority(thread),
0910 rtems_debugger_thread_real_priority(thread));
0911 remote_packet_out_append_hex((const uint8_t*) buf, l);
0912 l = snprintf(buf, sizeof(buf),
0913 "stack(s:%6lu a:%p), ",
0914 rtems_debugger_thread_stack_size(thread),
0915 rtems_debugger_thread_stack_area(thread));
0916 remote_packet_out_append_hex((const uint8_t*) buf, l);
0917 rtems_debugger_thread_state_str(thread, str, sizeof(str));
0918 l = snprintf(buf, sizeof(buf), "state(%s)", str);
0919 remote_packet_out_append_hex((const uint8_t*) buf, l);
0920 }
0921 }
0922 }
0923 remote_packet_out_send();
0924 return 0;
0925 }
0926
0927 static int
0928 remote_gq_supported(uint8_t* buffer, int size)
0929 {
0930 uint32_t capabilities = rtems_debugger_target_capabilities();
0931 const char* p;
0932 bool swbreak = false;
0933 bool hwbreak = false;
0934 bool vCont = false;
0935 bool no_resumed = false;
0936 bool multiprocess = false;
0937 remote_packet_out("qSupported:PacketSize=%d;QNonStop-",
0938 RTEMS_DEBUGGER_BUFFER_SIZE);
0939 p = strchr((const char*) buffer, ':');
0940 if (p != NULL)
0941 ++p;
0942 while (p != NULL && *p != '\0') {
0943 bool echo = false;
0944 char* sc;
0945 sc = strchr(p, ';');
0946 if (sc != NULL) {
0947 *sc++ = '\0';
0948 }
0949 if (strcmp(p, "swbreak+") == 0 &&
0950 !swbreak && (capabilities & RTEMS_DEBUGGER_TARGET_CAP_SWBREAK) != 0) {
0951 swbreak = true;
0952 echo = true;
0953 }
0954 if (strcmp(p, "hwbreak+") == 0 &&
0955 !hwbreak && (capabilities & RTEMS_DEBUGGER_TARGET_CAP_HWBREAK) != 0) {
0956 hwbreak = true;
0957 echo = true;
0958 }
0959 if (!vCont && strcmp(p, "vContSupported+") == 0) {
0960 rtems_debugger->flags |= RTEMS_DEBUGGER_FLAG_VCONT;
0961 vCont = true;
0962 echo = true;
0963 }
0964 if (!no_resumed && strcmp(p, "no-resumed+") == 0) {
0965 no_resumed = true;
0966 echo = true;
0967 }
0968 if (!multiprocess && strcmp(p, "multiprocess+") == 0) {
0969 rtems_debugger->flags |= RTEMS_DEBUGGER_FLAG_MULTIPROCESS;
0970 multiprocess = true;
0971 echo = true;
0972 }
0973
0974 if (echo) {
0975 remote_packet_out_append_str(";");
0976 remote_packet_out_append_str(p);
0977 }
0978 else if (strncmp(p, "xmlRegisters", sizeof("xmlRegisters") - 1) == 0) {
0979
0980 }
0981 else {
0982 remote_packet_out_append_str(";");
0983 remote_packet_out_append_buffer(p, strlen(p) - 1);
0984 remote_packet_out_append_str("-");
0985 }
0986 p = sc;
0987 }
0988 if (!swbreak && (capabilities & RTEMS_DEBUGGER_TARGET_CAP_SWBREAK) != 0) {
0989 remote_packet_out_append_str("swbreak+;");
0990 }
0991 if (!hwbreak && (capabilities & RTEMS_DEBUGGER_TARGET_CAP_HWBREAK) != 0) {
0992 remote_packet_out_append_str("hwbreak+;");
0993 }
0994 if (!vCont) {
0995 remote_packet_out_append_str("vContSupported+;");
0996 }
0997 if (!no_resumed) {
0998 remote_packet_out_append_str("no-resumed+;");
0999 }
1000 if (!multiprocess) {
1001 remote_packet_out_append_str("multiprocess+;");
1002 }
1003 remote_packet_out_send();
1004 return 0;
1005 }
1006
1007 static int
1008 remote_gq_attached(uint8_t* buffer, int size)
1009 {
1010 const char* response = "1";
1011 const char* colon = strchr((const char*) buffer, ':');
1012 if (colon != NULL) {
1013 DB_UINT pid = hex_decode_uint((const uint8_t*) colon + 1);
1014 if ((pid_t) pid != rtems_debugger->pid)
1015 response = r_E01;
1016 }
1017 remote_packet_out_str(response);
1018 remote_packet_out_send();
1019 return 0;
1020 }
1021
1022 static const rtems_debugger_packet general_query[] = {
1023 { .label = "qfThreadInfo",
1024 .command = remote_gq_thread_info_first },
1025 { .label = "qsThreadInfo",
1026 .command = remote_gq_thread_info_subsequent },
1027 { .label = "qThreadExtraInfo",
1028 .command = remote_gq_thread_extra_info },
1029 { .label = "qSupported",
1030 .command = remote_gq_supported },
1031 { .label = "qAttached",
1032 .command = remote_gq_attached },
1033 { .label = "qXfer",
1034 .command = remote_gq_uninterpreted_transfer },
1035 };
1036
1037 #define REMOTE_GENERAL_QUERIES RTEMS_DEBUGGER_NUMOF(general_query)
1038
1039 static int
1040 remote_general_query(uint8_t* buffer, int size)
1041 {
1042 return remote_packet_dispatch(general_query, REMOTE_GENERAL_QUERIES,
1043 buffer, size);
1044 }
1045
1046 static int
1047 remote_gs_non_stop(uint8_t* buffer, int size)
1048 {
1049 const char* response = r_E01;
1050 char* p = strchr((char*) buffer, ':');
1051 if (p != NULL) {
1052 ++p;
1053 response = r_OK;
1054 if (*p == '0') {
1055 rtems_debugger->flags &= ~RTEMS_DEBUGGER_FLAG_NON_STOP;
1056 }
1057 else if (*p == '1') {
1058 rtems_debugger->flags |= RTEMS_DEBUGGER_FLAG_NON_STOP;
1059 }
1060 else
1061 response = r_E01;
1062 }
1063 remote_packet_out_str(response);
1064 remote_packet_out_send();
1065 return 0;
1066 }
1067
1068 static const rtems_debugger_packet general_set[] = {
1069 { .label = "QNonStop",
1070 .command = remote_gs_non_stop },
1071 };
1072
1073 #define REMOTE_GENERAL_SETS RTEMS_DEBUGGER_NUMOF(general_set)
1074
1075 static int
1076 remote_general_set(uint8_t* buffer, int size)
1077 {
1078 return remote_packet_dispatch(general_set, REMOTE_GENERAL_SETS,
1079 buffer, size);
1080 }
1081
1082 static int
1083 remote_v_stopped(uint8_t* buffer, int size)
1084 {
1085 rtems_debugger_threads* threads = rtems_debugger->threads;
1086 if (threads->next >= threads->stopped.level)
1087 remote_packet_out_str(r_OK);
1088 else {
1089 rtems_id* stopped;
1090 remote_packet_out("T%02x", rtems_debugger->signal);
1091 stopped = rtems_debugger_thread_stopped(threads);
1092 while (threads->next < threads->stopped.level) {
1093 int r;
1094 r = remote_packet_out_append("thread:p%d.%08lx;",
1095 rtems_debugger->pid,
1096 stopped[threads->next]);
1097 if (r < 0)
1098 break;
1099 ++threads->next;
1100 }
1101 }
1102 remote_packet_out_send();
1103 return 0;
1104 }
1105
1106 static int
1107 remote_stop_reason(uint8_t* buffer, int size)
1108 {
1109 rtems_debugger->threads->next = 0;
1110 return remote_v_stopped(buffer, size);
1111 }
1112
1113 static int
1114 remote_v_continue(uint8_t* buffer, int size)
1115 {
1116 buffer += 5;
1117
1118 if (buffer[0] == '?') {
1119
1120
1121
1122
1123 remote_packet_out_str("vCont;c;C;s;r;");
1124 }
1125 else {
1126 const char* semi = (const char*) &buffer[0];
1127 bool resume = false;
1128 bool ok = true;
1129 while (ok && semi != NULL) {
1130 const char* colon = strchr(semi + 1, ':');
1131 const char action = *(semi + 1);
1132 DB_UINT pid = 0;
1133 DB_UINT tid = 0;
1134 bool extended;
1135 if (colon != NULL) {
1136 int r = -1;
1137 extended = thread_id_decode(colon + 1, &pid, &tid);
1138 if (extended || check_pid(pid)) {
1139 rtems_debugger_threads* threads = rtems_debugger->threads;
1140 rtems_debugger_thread* thread = NULL;
1141 int index = 0;
1142 if (tid != (DB_UINT) -1) {
1143 rtems_debugger_thread* current;
1144 current = rtems_debugger_thread_current(threads);
1145 index = rtems_debugger_thread_find_index(tid);
1146 if (index >= 0)
1147 thread = ¤t[index];
1148 }
1149 switch (action) {
1150 case 'c':
1151 case 'C':
1152 if (tid == (DB_UINT) -1) {
1153 r = rtems_debugger_thread_continue_all();
1154 }
1155 else if (thread != NULL) {
1156 r = rtems_debugger_thread_continue(thread);
1157 }
1158 if (r == 0)
1159 resume = true;
1160 break;
1161 case 'S':
1162 case 's':
1163 if (thread != NULL) {
1164 r = rtems_debugger_thread_step(thread);
1165 if (r == 0)
1166 resume = true;
1167 }
1168 break;
1169 case 'r':
1170
1171
1172
1173 if (thread != NULL) {
1174 const char* comma;
1175 comma = strchr(semi + 2, ',');
1176 if (comma != NULL) {
1177 DB_UINT start;
1178 DB_UINT end;
1179 start = hex_decode_uint((const uint8_t*) semi + 2);
1180 end = hex_decode_uint((const uint8_t*) comma + 1);
1181 r = rtems_debugger_thread_stepping(thread, start, end);
1182 if (r == 0)
1183 resume = true;
1184 }
1185 else {
1186 ok = false;
1187 }
1188 }
1189 break;
1190 default:
1191 rtems_debugger_printf("rtems-db: vCont: unkown action: %c\n", action);
1192 ok = false;
1193 break;
1194 }
1195 if (r < 0)
1196 ok = false;
1197 }
1198 }
1199 else {
1200 rtems_debugger_printf("rtems-db: vCont: no colon\n");
1201 ok = false;
1202 }
1203 semi = strchr(semi + 1, ';');
1204 }
1205
1206 if (ok)
1207 remote_packet_out_str(r_OK);
1208 else
1209 remote_packet_out_str(r_E01);
1210
1211 if (resume)
1212 rtems_debugger_thread_system_resume(false);
1213 }
1214
1215 remote_packet_out_send();
1216
1217 return 0;
1218 }
1219
1220 static int
1221 remote_v_kill(uint8_t* buffer, int size)
1222 {
1223 rtems_debugger->flags |= RTEMS_DEBUGGER_FLAG_RESET;
1224 return remote_detach(buffer, size);
1225 }
1226
1227 static const rtems_debugger_packet v_packets[] = {
1228 { .label = "vCont",
1229 .command = remote_v_continue },
1230 { .label = "vStopped",
1231 .command = remote_v_stopped },
1232 { .label = "vKill",
1233 .command = remote_v_kill },
1234 };
1235
1236 #define REMOTE_V_PACKETS RTEMS_DEBUGGER_NUMOF(v_packets)
1237
1238 static int
1239 remote_v_packets(uint8_t* buffer, int size)
1240 {
1241 return remote_packet_dispatch(v_packets, REMOTE_V_PACKETS,
1242 buffer, size);
1243 }
1244
1245 static int
1246 remote_thread_select(uint8_t* buffer, int size)
1247 {
1248 const char* response = r_OK;
1249 int* index = NULL;
1250
1251 if (buffer[1] == 'g')
1252 index = &rtems_debugger->threads->selector_gen;
1253 else if (buffer[1] == 'c')
1254 index = &rtems_debugger->threads->selector_cont;
1255 else
1256 response = r_E01;
1257
1258 if (index != NULL) {
1259 DB_UINT pid = 0;
1260 DB_UINT tid = 0;
1261 bool extended;
1262 extended = thread_id_decode((const char*) &buffer[2], &pid, &tid);
1263 if (extended && !check_pid(pid)) {
1264 response = r_E01;
1265 }
1266 else {
1267 if (tid == 0 || tid == (DB_UINT) -1)
1268 *index = (int) tid;
1269 else {
1270 int r;
1271 r = rtems_debugger_thread_find_index(tid);
1272 if (r < 0) {
1273 response = r_E01;
1274 *index = -1;
1275 }
1276 else
1277 *index = r;
1278 }
1279 }
1280 }
1281
1282 remote_packet_out_str(response);
1283 remote_packet_out_send();
1284 return 0;
1285 }
1286
1287 static int
1288 remote_thread_alive(uint8_t* buffer, int size)
1289 {
1290 const char* response = r_E01;
1291 DB_UINT pid = 0;
1292 DB_UINT tid = 0;
1293 bool extended;
1294 extended = thread_id_decode((const char*) &buffer[1], &pid, &tid);
1295 if (!extended || (extended && check_pid(pid))) {
1296 int r;
1297 r = rtems_debugger_thread_find_index(tid);
1298 if (r >= 0)
1299 response = r_OK;
1300 }
1301 remote_packet_out_str(response);
1302 remote_packet_out_send();
1303 return 0;
1304 }
1305
1306 static int
1307 remote_argc_argv(uint8_t* buffer, int size)
1308 {
1309 return -1;
1310 }
1311
1312 static int
1313 remote_continue_at(uint8_t* buffer, int size)
1314 {
1315 if (!rtems_debugger_server_flag(RTEMS_DEBUGGER_FLAG_VCONT)) {
1316 char* vCont_c = "vCont;c:p1.-1";
1317 return remote_v_continue((uint8_t*) vCont_c, strlen(vCont_c));
1318 }
1319 return -1;
1320 }
1321
1322 static int
1323 remote_read_general_regs(uint8_t* buffer, int size)
1324 {
1325 rtems_debugger_threads* threads = rtems_debugger->threads;
1326 bool ok = false;
1327 int r;
1328 if (threads->selector_gen >= 0 &&
1329 threads->selector_gen < (int) threads->current.level) {
1330 rtems_debugger_thread* current;
1331 rtems_debugger_thread* thread;
1332 current = rtems_debugger_thread_current(threads);
1333 thread = ¤t[threads->selector_gen];
1334 r = rtems_debugger_target_read_regs(thread);
1335 if (r >= 0) {
1336 remote_packet_out_reset();
1337 r = remote_packet_out_append_hex((const uint8_t*) &thread->registers[0],
1338 rtems_debugger_target_reg_table_size());
1339 if (r >= 0)
1340 ok = true;
1341 }
1342 }
1343 if (!ok)
1344 remote_packet_out_str(r_E01);
1345 remote_packet_out_send();
1346 return 0;
1347 }
1348
1349 static int
1350 remote_write_general_regs(uint8_t* buffer, int size)
1351 {
1352 rtems_debugger_threads* threads = rtems_debugger->threads;
1353 size_t reg_table_size = rtems_debugger_target_reg_table_size();
1354 bool ok = false;
1355 int r;
1356 if (threads->selector_gen >= 0 &&
1357 threads->selector_gen < (int) threads->current.level &&
1358 ((size - 1) / 2) == (int) reg_table_size) {
1359 rtems_debugger_thread* current;
1360 rtems_debugger_thread* thread;
1361 current = rtems_debugger_thread_current(threads);
1362 thread = ¤t[threads->selector_gen];
1363 r = rtems_debugger_target_read_regs(thread);
1364 if (r >= 0) {
1365 r = rtems_debugger_remote_packet_in_hex((uint8_t*) &thread->registers[0],
1366 (const char*) &buffer[1],
1367 reg_table_size);
1368 if (r >= 0) {
1369 thread->flags |= RTEMS_DEBUGGER_THREAD_FLAG_REG_DIRTY;
1370 ok = true;
1371 }
1372 }
1373 }
1374 if (!ok)
1375 remote_packet_out_str(r_E01);
1376 remote_packet_out_send();
1377 return 0;
1378 }
1379
1380 static int
1381 remote_read_reg(uint8_t* buffer, int size)
1382 {
1383 rtems_debugger_threads* threads = rtems_debugger->threads;
1384 bool ok = false;
1385 int r;
1386 if (threads->selector_gen >= 0
1387 && threads->selector_gen < (int) threads->current.level) {
1388 size_t reg = hex_decode_int(&buffer[1]);
1389 if (reg < rtems_debugger_target_reg_num()) {
1390 rtems_debugger_thread* current;
1391 rtems_debugger_thread* thread;
1392 current = rtems_debugger_thread_current(threads);
1393 thread = ¤t[threads->selector_gen];
1394 r = rtems_debugger_target_read_regs(thread);
1395 if (r >= 0) {
1396 const size_t reg_size = rtems_debugger_target_reg_size(reg);
1397 const size_t reg_offset = rtems_debugger_target_reg_offset(reg);
1398 const uint8_t* addr = &thread->registers[reg_offset];
1399 remote_packet_out_reset();
1400 r = remote_packet_out_append_hex(addr, reg_size);
1401 if (r >= 0)
1402 ok = true;
1403 }
1404 }
1405 }
1406 if (!ok)
1407 remote_packet_out_str(r_E01);
1408 remote_packet_out_send();
1409 return 0;
1410 }
1411
1412 static int
1413 remote_write_reg(uint8_t* buffer, int size)
1414 {
1415 rtems_debugger_threads* threads = rtems_debugger->threads;
1416 const char* response = r_E01;
1417 if (threads->selector_gen >= 0
1418 && threads->selector_gen < (int) threads->current.level) {
1419 const char* equals;
1420 equals = strchr((const char*) buffer, '=');
1421 if (equals != NULL) {
1422 size_t reg = hex_decode_int(&buffer[1]);
1423 if (reg < rtems_debugger_target_reg_num()) {
1424 rtems_debugger_thread* current;
1425 rtems_debugger_thread* thread;
1426 int r;
1427 current = rtems_debugger_thread_current(threads);
1428 thread = ¤t[threads->selector_gen];
1429 r = rtems_debugger_target_read_regs(thread);
1430 if (r >= 0) {
1431 const size_t reg_size = rtems_debugger_target_reg_size(reg);
1432 const size_t reg_offset = rtems_debugger_target_reg_offset(reg);
1433 uint8_t* addr = &thread->registers[reg_offset];
1434 r = rtems_debugger_remote_packet_in_hex(addr, equals + 1, reg_size);
1435 if (r == 0) {
1436 thread->flags |= RTEMS_DEBUGGER_THREAD_FLAG_REG_DIRTY;
1437 response = r_OK;
1438 }
1439 }
1440 }
1441 }
1442 }
1443 remote_packet_out_str(response);
1444 remote_packet_out_send();
1445 return 0;
1446 }
1447
1448 static int
1449 remote_read_memory(uint8_t* buffer, int size)
1450 {
1451 const char* comma;
1452 comma = strchr((const char*) buffer, ',');
1453 if (comma == NULL)
1454 remote_packet_out_str(r_E01);
1455 else {
1456 uintptr_t addr;
1457 DB_UINT length;
1458 int r;
1459 addr = hex_decode_addr(&buffer[1]);
1460 length = hex_decode_uint((const uint8_t*) comma + 1);
1461 remote_packet_out_reset();
1462 r = rtems_debugger_target_start_memory_access();
1463 if (r == 0) {
1464
1465
1466
1467 r = remote_packet_out_append_hex((const uint8_t*) addr, length);
1468 }
1469 rtems_debugger_target_end_memory_access();
1470 if (r < 0)
1471 remote_packet_out_str(r_E01);
1472 }
1473 remote_packet_out_send();
1474 return 0;
1475 }
1476
1477 static int
1478 remote_write_memory(uint8_t* buffer, int size)
1479 {
1480 const char* response = r_E01;
1481 const char* comma;
1482 const char* colon;
1483 comma = strchr((const char*) buffer, ',');
1484 colon = strchr((const char*) buffer, ':');
1485 if (comma != NULL && colon != NULL) {
1486 uintptr_t addr;
1487 DB_UINT length;
1488 int r;
1489 addr = hex_decode_addr(&buffer[1]);
1490 length = hex_decode_uint((const uint8_t*) comma + 1);
1491 r = rtems_debugger_target_start_memory_access();
1492 if (r == 0) {
1493 r = rtems_debugger_remote_packet_in_hex((uint8_t*) addr,
1494 colon + 1,
1495 length);
1496 }
1497 rtems_debugger_target_end_memory_access();
1498 if (r == 0)
1499 response = r_OK;
1500 }
1501 remote_packet_out_str(response);
1502 remote_packet_out_send();
1503 return 0;
1504 }
1505
1506 static int
1507 remote_single_step(uint8_t* buffer, int size)
1508 {
1509 if (!rtems_debugger_server_flag(RTEMS_DEBUGGER_FLAG_VCONT)) {
1510 rtems_debugger_threads* threads = rtems_debugger->threads;
1511 if (threads != NULL && rtems_debugger_thread_current(threads) != NULL) {
1512 rtems_debugger_thread* current;
1513 char vCont_s[32];
1514 current = rtems_debugger_thread_current(threads);
1515 snprintf(vCont_s, sizeof(vCont_s), "vCont;s:p1.%08" PRIx32 ";c:p1.-1",
1516 current[threads->selector_cont].id);
1517 return remote_v_continue((uint8_t*) vCont_s, strlen(vCont_s));
1518 }
1519 remote_packet_out_str(r_E01);
1520 remote_packet_out_send();
1521 return 0;
1522 }
1523 return -1;
1524 }
1525
1526 static int
1527 remote_breakpoints(bool insert, uint8_t* buffer, int size)
1528 {
1529 const char* comma1;
1530 int r = -1;
1531 comma1 = strchr((const char*) buffer, ',');
1532 if (comma1 != NULL) {
1533 const char* comma2;
1534 comma2 = strchr(comma1 + 1, ',');
1535 if (comma2 != NULL) {
1536 uint32_t capabilities;
1537 uintptr_t addr;
1538 DB_UINT kind;
1539 addr = hex_decode_addr((const uint8_t*) comma1 + 1);
1540 kind = hex_decode_uint((const uint8_t*) comma2 + 1);
1541 capabilities = rtems_debugger_target_capabilities();
1542 switch (buffer[1]) {
1543 case '0':
1544 if ((capabilities & RTEMS_DEBUGGER_TARGET_CAP_SWBREAK) != 0) {
1545 r = rtems_debugger_target_swbreak_control(insert, addr, kind);
1546 }
1547 break;
1548 case '1':
1549 case '2':
1550 case '3':
1551 case '4':
1552 if ((capabilities & RTEMS_DEBUGGER_TARGET_CAP_HWWATCH) != 0) {
1553 rtems_debugger_target_watchpoint type;
1554 switch (buffer[1]) {
1555 case '1':
1556 type = rtems_debugger_target_hw_execute;
1557 break;
1558 case '2':
1559 type = rtems_debugger_target_hw_write;
1560 break;
1561 case '3':
1562 type = rtems_debugger_target_hw_read;
1563 break;
1564 case '4':
1565 default:
1566 type = rtems_debugger_target_hw_read_write;
1567 break;
1568 }
1569 r = rtems_debugger_target_hwbreak_control(type, insert, addr, kind);
1570 }
1571 break;
1572 default:
1573 break;
1574 }
1575 }
1576 }
1577 remote_packet_out_str(r < 0 ? r_E01 : r_OK);
1578 remote_packet_out_send();
1579 return 0;
1580 }
1581
1582 static int
1583 remote_insert_breakpoint(uint8_t* buffer, int size)
1584 {
1585 return remote_breakpoints(true, buffer, size);
1586 }
1587
1588 static int
1589 remote_remove_breakpoint(uint8_t* buffer, int size)
1590 {
1591 return remote_breakpoints(false, buffer, size);
1592 }
1593
1594 static int
1595 remote_break(uint8_t* buffer, int size)
1596 {
1597 int r;
1598 r = rtems_debugger_thread_system_suspend();
1599 if (r < 0) {
1600 rtems_debugger_printf("error: rtems-db: suspend all on break\n");
1601 }
1602 return remote_stop_reason(buffer, size);
1603 }
1604
1605 static const rtems_debugger_packet packets[] = {
1606 { .label = "q",
1607 .command = remote_general_query },
1608 { .label = "Q",
1609 .command = remote_general_set },
1610 { .label = "v",
1611 .command = remote_v_packets },
1612 { .label = "H",
1613 .command = remote_thread_select },
1614 { .label = "T",
1615 .command = remote_thread_alive },
1616 { .label = "?",
1617 .command = remote_stop_reason },
1618 { .label = "A",
1619 .command = remote_argc_argv },
1620 { .label = "c",
1621 .command = remote_continue_at },
1622 { .label = "g",
1623 .command = remote_read_general_regs },
1624 { .label = "G",
1625 .command = remote_write_general_regs },
1626 { .label = "p",
1627 .command = remote_read_reg },
1628 { .label = "P",
1629 .command = remote_write_reg },
1630 { .label = "m",
1631 .command = remote_read_memory },
1632 { .label = "M",
1633 .command = remote_write_memory },
1634 { .label = "s",
1635 .command = remote_single_step },
1636 { .label = "Z",
1637 .command = remote_insert_breakpoint },
1638 { .label = "z",
1639 .command = remote_remove_breakpoint },
1640 { .label = "D",
1641 .command = remote_detach },
1642 { .label = "k",
1643 .command = remote_v_kill },
1644 { .label = "r",
1645 .command = remote_v_kill },
1646 { .label = "R",
1647 .command = remote_v_kill },
1648 { .label = "^C",
1649 .command = remote_break },
1650 };
1651
1652 #define REMOTE_PACKETS RTEMS_DEBUGGER_NUMOF(packets)
1653
1654 static int
1655 remote_packets(uint8_t* buffer, size_t size)
1656 {
1657 return remote_packet_dispatch(packets, REMOTE_PACKETS,
1658 buffer, size);
1659 }
1660
1661 static void
1662 rtems_debugger_events(rtems_task_argument arg)
1663 {
1664 int r = 0;
1665
1666 if (rtems_debugger_verbose())
1667 rtems_debugger_printf("rtems-db: events running\n");
1668
1669
1670
1671
1672 rtems_debugger_lock();
1673
1674 rtems_debugger_target_enable();
1675
1676 if (rtems_debugger_server_flag(RTEMS_DEBUGGER_FLAG_BREAK_WAITER)) {
1677 rtems_debugger->flags &= ~RTEMS_DEBUGGER_FLAG_BREAK_WAITER;
1678 r = rtems_debugger_thread_system_suspend();
1679 if (rtems_debugger_verbose())
1680 rtems_debugger_printf("rtems-db: break waiter\n");
1681 rtems_debugger_server_events_signal();
1682 if (rtems_debugger_verbose())
1683 rtems_debugger_printf("rtems-db: break waiter: signalled\n");
1684 }
1685
1686 if (r == 0) {
1687 while (rtems_debugger_server_events_running()) {
1688 rtems_debugger_server_events_wait();
1689 if (rtems_debugger_verbose())
1690 rtems_debugger_printf("rtems-db: event woken\n");
1691 if (!rtems_debugger_server_events_running())
1692 break;
1693 r = rtems_debugger_thread_system_suspend();
1694 if (r < 0)
1695 break;
1696 r = remote_stop_reason(NULL, 0);
1697 if (r < 0)
1698 break;
1699 }
1700 }
1701
1702 if (r < 0)
1703 rtems_debugger_printf("rtems-db: error in events\n");
1704
1705 rtems_debugger_target_disable();
1706
1707 rtems_debugger->events_running = false;
1708 rtems_debugger->events_finished = true;
1709
1710 rtems_debugger_unlock();
1711
1712 if (rtems_debugger_verbose())
1713 rtems_debugger_printf("rtems-db: events finishing\n");
1714
1715 rtems_task_exit();
1716 }
1717
1718 static int
1719 rtems_debugger_session(void)
1720 {
1721 int r;
1722 int rr;
1723
1724 if (rtems_debugger_verbose())
1725 rtems_debugger_printf("rtems-db: remote running\n");
1726
1727
1728
1729
1730 rtems_debugger_lock();
1731
1732 r = rtems_debugger_target_create();
1733 if (r < 0) {
1734 rtems_debugger_unlock();
1735 return r;
1736 }
1737
1738 r = rtems_debugger_thread_create();
1739 if (r < 0) {
1740 rtems_debugger_target_destroy();
1741 rtems_debugger_unlock();
1742 return r;
1743 }
1744
1745 rtems_debugger->events_running = true;
1746 rtems_debugger->events_finished = false;
1747
1748 r = rtems_debugger_task_create("DBSe",
1749 rtems_debugger->priority,
1750 RTEMS_DEBUGGER_STACKSIZE,
1751 rtems_debugger_events,
1752 0,
1753 &rtems_debugger->events_task);
1754 if (r < 0) {
1755 rtems_debugger_thread_destroy();
1756 rtems_debugger_target_destroy();
1757 rtems_debugger_unlock();
1758 return r;
1759 }
1760
1761 while (rtems_debugger_server_running() &&
1762 rtems_debugger_connected()) {
1763 r = rtems_debugger_remote_packet_in();
1764 if (r < 0)
1765 break;
1766 if (r > 0) {
1767 remote_packets(&rtems_debugger->input[0], r);
1768 }
1769 }
1770
1771 rtems_debugger->events_running = false;
1772 rtems_debugger_server_events_signal();
1773
1774 rtems_debugger_unlock();
1775
1776 rr = rtems_debugger_task_destroy("DBSe",
1777 rtems_debugger->events_task,
1778 &rtems_debugger->events_finished,
1779 RTEMS_DEBUGGER_TIMEOUT_STOP);
1780 if (rr < 0 && r == 0)
1781 r = rr;
1782
1783 rtems_debugger_lock();
1784
1785 rr = rtems_debugger_target_destroy();
1786 if (rr < 0 && r == 0)
1787 r = rr;
1788
1789 rr = rtems_debugger_thread_destroy();
1790 if (rr < 0 && r == 0)
1791 r = rr;
1792
1793 if (rtems_debugger_server_flag(RTEMS_DEBUGGER_FLAG_RESET)) {
1794 rtems_debugger_printf("rtems-db: shutdown\n");
1795
1796
1797
1798
1799
1800 sleep(2);
1801
1802
1803
1804
1805 rtems_fatal_error_occurred(1122);
1806 }
1807
1808 rtems_debugger->flags = 0;
1809 rtems_debugger->ack_pending = false;
1810
1811 rtems_debugger_unlock();
1812
1813 if (rtems_debugger_verbose())
1814 rtems_debugger_printf("rtems-db: remote finishing\n");
1815
1816 return r;
1817 }
1818
1819 static int
1820 rtems_debugger_create(const char* remote,
1821 const char* device,
1822 rtems_task_priority priority,
1823 int timeout,
1824 const rtems_printer* printer)
1825 {
1826 int r;
1827
1828 if (rtems_debugger != NULL) {
1829 rtems_printf(printer, "error: rtems-db: create: already active\n");
1830 errno = EEXIST;
1831 return -1;
1832 }
1833
1834 rtems_debugger = malloc(sizeof(rtems_debugger_server));
1835 if (rtems_debugger == NULL) {
1836 rtems_printf(printer, "error: rtems-db: create: no memory\n");
1837 errno = ENOMEM;
1838 return -1;
1839 }
1840
1841 memset(rtems_debugger, 0, sizeof(rtems_debugger_server));
1842
1843
1844
1845
1846 rtems_debugger->priority = priority;
1847 rtems_debugger->timeout = timeout;
1848 rtems_debugger->printer = *printer;
1849 rtems_debugger->pid = getpid();
1850 rtems_debugger->remote_debug = false;
1851
1852 rtems_chain_initialize_empty(&rtems_debugger->exception_threads);
1853
1854 rtems_debugger->remote = rtems_debugger_remote_find(remote);
1855 if (rtems_debugger->remote== NULL) {
1856 rtems_printf(printer, "error: rtems-db: remote not found: %s\n", remote);
1857 free(rtems_debugger);
1858 rtems_debugger = NULL;
1859 return -1;
1860 }
1861
1862 r = rtems_debugger->remote->begin(rtems_debugger->remote, device);
1863 if (r < 0) {
1864 rtems_printf(printer, "error: rtems-db: remote begin: %s: %s\n",
1865 rtems_debugger->remote->name, strerror(errno));
1866 free(rtems_debugger);
1867 rtems_debugger = NULL;
1868 return -1;
1869 }
1870
1871
1872
1873
1874 rtems_debugger->flags = 0;
1875 rtems_debugger->ack_pending = false;
1876
1877 r = rtems_debugger_lock_create();
1878 if (r < 0) {
1879 free(rtems_debugger);
1880 rtems_debugger = NULL;
1881 return -1;
1882 }
1883
1884 return 0;
1885 }
1886
1887 static int
1888 rtems_debugger_destroy(void)
1889 {
1890 int r;
1891 int rr;
1892
1893 rtems_debugger_lock();
1894 rtems_debugger->server_running = false;
1895 rtems_debugger_unlock();
1896
1897 r = rtems_debugger_remote_disconnect();
1898
1899 rr = rtems_debugger->remote->end(rtems_debugger->remote);
1900 if (rr < 0 && r == 0)
1901 r = rr;
1902
1903 rr = rtems_debugger_task_destroy("DBSs",
1904 rtems_debugger->server_task,
1905 &rtems_debugger->server_finished,
1906 RTEMS_DEBUGGER_TIMEOUT_STOP);
1907 if (rr < 0 && r == 0)
1908 r = rr;
1909
1910 rr = rtems_debugger_lock_destroy();
1911 if (rr < 0 && r == 0)
1912 r = rr;
1913
1914 free(rtems_debugger);
1915 rtems_debugger = NULL;
1916
1917 return r;
1918 }
1919
1920 static void
1921 rtems_debugger_main(rtems_task_argument arg)
1922 {
1923 int r;
1924
1925 rtems_debugger_lock();
1926 rtems_debugger->server_running = true;
1927 rtems_debugger->server_finished = false;
1928 rtems_debugger_unlock();
1929
1930 rtems_debugger_printf("rtems-db: remote running\n");
1931
1932 while (rtems_debugger_server_running()) {
1933 r = rtems_debugger_remote_connect();
1934 if (r < 0)
1935 break;
1936 rtems_debugger_session();
1937 rtems_debugger_remote_disconnect();
1938 }
1939
1940 rtems_debugger_printf("rtems-db: remote finishing\n");
1941
1942 rtems_debugger_lock();
1943 rtems_debugger->server_running = false;
1944 rtems_debugger->server_finished = true;
1945 rtems_debugger_unlock();
1946
1947 rtems_task_exit();
1948 }
1949
1950 int
1951 rtems_debugger_start(const char* remote,
1952 const char* device,
1953 int timeout,
1954 rtems_task_priority priority,
1955 const rtems_printer* printer)
1956 {
1957 int r;
1958
1959 r = rtems_debugger_create(remote, device, priority, timeout, printer);
1960 if (r < 0)
1961 return -1;
1962
1963 rtems_debugger_lock();
1964 rtems_debugger->server_running = false;
1965 rtems_debugger->server_finished = true;
1966 _Condition_Initialize_named(&rtems_debugger->server_cond, "DBserver");
1967 rtems_debugger_unlock();
1968
1969 r = rtems_debugger_task_create("DBSs",
1970 priority,
1971 RTEMS_DEBUGGER_STACKSIZE,
1972 rtems_debugger_main,
1973 0,
1974 &rtems_debugger->server_task);
1975 if (r < 0) {
1976 rtems_debugger_destroy();
1977 return -1;
1978 }
1979
1980 return 0;
1981 }
1982
1983 void
1984 rtems_debugger_server_crash(void)
1985 {
1986 rtems_debugger_lock();
1987 rtems_debugger->server_running = false;
1988 rtems_debugger_unlock();
1989 rtems_debugger->remote->end(rtems_debugger->remote);
1990 }
1991
1992 int
1993 rtems_debugger_break(bool wait)
1994 {
1995 int r = 0;
1996 if (!rtems_debugger_running()) {
1997 errno = EIO;
1998 r = -1;
1999 } else {
2000 rtems_debugger_lock();
2001 if (rtems_debugger_server_events_running()) {
2002 rtems_debugger_server_events_signal();
2003 } else if (
2004 wait && !rtems_debugger_server_flag(RTEMS_DEBUGGER_FLAG_BREAK_WAITER)) {
2005 rtems_debugger->flags |= RTEMS_DEBUGGER_FLAG_BREAK_WAITER;
2006 rtems_debugger_server_events_wait();
2007 } else {
2008 errno = EIO;
2009 r = -1;
2010 }
2011 rtems_debugger_unlock();
2012 }
2013 return r;
2014 }
2015
2016 int
2017 rtems_debugger_stop(void)
2018 {
2019 return rtems_debugger_destroy();
2020 }
2021
2022 bool
2023 rtems_debugger_running(void)
2024 {
2025 return rtems_debugger != NULL;
2026 }
2027
2028 void
2029 rtems_debugger_set_verbose(bool on)
2030 {
2031 if (rtems_debugger_running()) {
2032 if (on)
2033 rtems_debugger->flags |= RTEMS_DEBUGGER_FLAG_VERBOSE;
2034 else
2035 rtems_debugger->flags &= ~RTEMS_DEBUGGER_FLAG_VERBOSE;
2036 }
2037 }
2038
2039 int
2040 rtems_debugger_remote_debug(bool state)
2041 {
2042 if (rtems_debugger_running()) {
2043 rtems_debugger_lock();
2044 rtems_debugger->remote_debug = state;
2045 rtems_debugger_printf("rtems-db: remote-debug is %s\n",
2046 rtems_debugger->remote_debug ? "on" : "off");
2047 rtems_debugger_unlock();
2048 } else {
2049 rtems_debugger_printf("rtems-db: debug server not running\n");
2050 }
2051 return 0;
2052 }