1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2004 Marcel Moolenaar 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __FBSDID("$FreeBSD$"); 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/kdb.h> 35 #include <sys/kernel.h> 36 #include <sys/pcpu.h> 37 #include <sys/proc.h> 38 #include <sys/reboot.h> 39 #include <sys/sbuf.h> 40 41 #include <machine/gdb_machdep.h> 42 #include <machine/kdb.h> 43 44 #include <gdb/gdb.h> 45 #include <gdb/gdb_int.h> 46 47 SYSCTL_NODE(_debug, OID_AUTO, gdb, CTLFLAG_RW, 0, "GDB settings"); 48 49 static dbbe_init_f gdb_init; 50 static dbbe_trap_f gdb_trap; 51 52 KDB_BACKEND(gdb, gdb_init, NULL, NULL, gdb_trap); 53 54 static struct gdb_dbgport null_gdb_dbgport; 55 DATA_SET(gdb_dbgport_set, null_gdb_dbgport); 56 SET_DECLARE(gdb_dbgport_set, struct gdb_dbgport); 57 58 struct gdb_dbgport *gdb_cur = NULL; 59 int gdb_listening = 0; 60 61 static unsigned char gdb_bindata[64]; 62 63 #ifdef DDB 64 bool gdb_return_to_ddb = false; 65 #endif 66 67 static int 68 gdb_init(void) 69 { 70 struct gdb_dbgport *dp, **iter; 71 int cur_pri, pri; 72 73 gdb_cur = NULL; 74 cur_pri = -1; 75 SET_FOREACH(iter, gdb_dbgport_set) { 76 dp = *iter; 77 pri = (dp->gdb_probe != NULL) ? dp->gdb_probe() : -1; 78 dp->gdb_active = (pri >= 0) ? 0 : -1; 79 if (pri > cur_pri) { 80 cur_pri = pri; 81 gdb_cur = dp; 82 } 83 } 84 if (gdb_cur != NULL) { 85 printf("GDB: debug ports:"); 86 SET_FOREACH(iter, gdb_dbgport_set) { 87 dp = *iter; 88 if (dp->gdb_active == 0) 89 printf(" %s", dp->gdb_name); 90 } 91 printf("\n"); 92 } else 93 printf("GDB: no debug ports present\n"); 94 if (gdb_cur != NULL) { 95 gdb_cur->gdb_init(); 96 printf("GDB: current port: %s\n", gdb_cur->gdb_name); 97 } 98 if (gdb_cur != NULL) { 99 cur_pri = (boothowto & RB_GDB) ? 2 : 0; 100 gdb_consinit(); 101 } else 102 cur_pri = -1; 103 return (cur_pri); 104 } 105 106 static void 107 gdb_do_mem_search(void) 108 { 109 size_t patlen; 110 intmax_t addr, size; 111 const unsigned char *found; 112 113 if (gdb_rx_varhex(&addr) || gdb_rx_char() != ';' || 114 gdb_rx_varhex(&size) || gdb_rx_char() != ';' || 115 gdb_rx_bindata(gdb_bindata, sizeof(gdb_bindata), &patlen)) { 116 gdb_tx_err(EINVAL); 117 return; 118 } 119 if (gdb_search_mem((char *)(uintptr_t)addr, size, gdb_bindata, 120 patlen, &found)) { 121 if (found == 0ULL) 122 gdb_tx_begin('0'); 123 else { 124 gdb_tx_begin('1'); 125 gdb_tx_char(','); 126 gdb_tx_hex((intmax_t)(uintptr_t)found, 8); 127 } 128 gdb_tx_end(); 129 } else 130 gdb_tx_err(EIO); 131 } 132 133 static void 134 gdb_do_threadinfo(struct thread **thr_iter) 135 { 136 static struct thread * const done_sentinel = (void *)(uintptr_t)1; 137 static const size_t tidsz_hex = sizeof(lwpid_t) * 2; 138 size_t tds_sent; 139 140 if (*thr_iter == NULL) { 141 gdb_tx_err(ENXIO); 142 return; 143 } 144 145 if (*thr_iter == done_sentinel) { 146 gdb_tx_begin('l'); 147 *thr_iter = NULL; 148 goto sendit; 149 } 150 151 gdb_tx_begin('m'); 152 153 for (tds_sent = 0; 154 *thr_iter != NULL && gdb_txbuf_has_capacity(tidsz_hex + 1); 155 *thr_iter = kdb_thr_next(*thr_iter), tds_sent++) { 156 if (tds_sent > 0) 157 gdb_tx_char(','); 158 gdb_tx_varhex((*thr_iter)->td_tid); 159 } 160 161 /* 162 * Can't send EOF and "some" in same packet, so set a sentinel to send 163 * EOF when GDB asks us next. 164 */ 165 if (*thr_iter == NULL && tds_sent > 0) 166 *thr_iter = done_sentinel; 167 168 sendit: 169 gdb_tx_end(); 170 } 171 172 #define BIT(n) (1ull << (n)) 173 enum { 174 GDB_MULTIPROCESS, 175 GDB_SWBREAK, 176 GDB_HWBREAK, 177 GDB_QRELOCINSN, 178 GDB_FORK_EVENTS, 179 GDB_VFORK_EVENTS, 180 GDB_EXEC_EVENTS, 181 GDB_VCONT_SUPPORTED, 182 GDB_QTHREADEVENTS, 183 GDB_NO_RESUMED, 184 }; 185 static const char * const gdb_feature_names[] = { 186 [GDB_MULTIPROCESS] = "multiprocess", 187 [GDB_SWBREAK] = "swbreak", 188 [GDB_HWBREAK] = "hwbreak", 189 [GDB_QRELOCINSN] = "qRelocInsn", 190 [GDB_FORK_EVENTS] = "fork-events", 191 [GDB_VFORK_EVENTS] = "vfork-events", 192 [GDB_EXEC_EVENTS] = "exec-events", 193 [GDB_VCONT_SUPPORTED] = "vContSupported", 194 [GDB_QTHREADEVENTS] = "QThreadEvents", 195 [GDB_NO_RESUMED] = "no-resumed", 196 }; 197 static void 198 gdb_do_qsupported(uint32_t *feat) 199 { 200 char *tok, *delim, ok; 201 size_t i, toklen; 202 203 /* Parse supported host features */ 204 *feat = 0; 205 if (gdb_rx_char() != ':') 206 goto error; 207 208 while (gdb_rxsz > 0) { 209 tok = gdb_rxp; 210 delim = strchrnul(gdb_rxp, ';'); 211 toklen = (delim - tok); 212 213 gdb_rxp += toklen; 214 gdb_rxsz -= toklen; 215 if (*delim != '\0') { 216 *delim = '\0'; 217 gdb_rxp += 1; 218 gdb_rxsz -= 1; 219 } 220 221 if (toklen < 2) 222 goto error; 223 224 ok = tok[toklen - 1]; 225 if (ok != '-' && ok != '+') { 226 /* 227 * GDB only has one KV-pair feature, and we don't 228 * support it, so ignore and move on. 229 */ 230 if (strchr(tok, '=') != NULL) 231 continue; 232 /* Not a KV-pair, and not a +/- flag? Malformed. */ 233 goto error; 234 } 235 if (ok != '+') 236 continue; 237 tok[toklen - 1] = '\0'; 238 239 for (i = 0; i < nitems(gdb_feature_names); i++) 240 if (strcmp(gdb_feature_names[i], tok) == 0) 241 break; 242 243 if (i == nitems(gdb_feature_names)) { 244 /* Unknown GDB feature. */ 245 continue; 246 } 247 248 *feat |= BIT(i); 249 } 250 251 /* Send a supported feature list back */ 252 gdb_tx_begin(0); 253 254 gdb_tx_str("PacketSize"); 255 gdb_tx_char('='); 256 /* 257 * We don't buffer framing bytes, but we do need to retain a byte for a 258 * trailing nul. 259 */ 260 gdb_tx_varhex(GDB_BUFSZ + strlen("$#nn") - 1); 261 262 gdb_tx_str(";qXfer:threads:read+"); 263 264 /* 265 * Future consideration: 266 * - vCont 267 * - multiprocess 268 */ 269 gdb_tx_end(); 270 return; 271 272 error: 273 *feat = 0; 274 gdb_tx_err(EINVAL); 275 } 276 277 /* 278 * A qXfer_context provides a vaguely generic way to generate a multi-packet 279 * response on the fly, making some assumptions about the size of sbuf writes 280 * vs actual packet length constraints. A non-byzantine gdb host should allow 281 * hundreds of bytes per packet or more. 282 * 283 * Upper layers are considered responsible for escaping the four forbidden 284 * characters '# $ } *'. 285 */ 286 struct qXfer_context { 287 struct sbuf sb; 288 size_t last_offset; 289 bool flushed; 290 bool lastmessage; 291 char xfer_buf[GDB_BUFSZ]; 292 }; 293 294 static int 295 qXfer_drain(void *v, const char *buf, int len) 296 { 297 struct qXfer_context *qx; 298 299 if (len < 0) 300 return (-EINVAL); 301 302 qx = v; 303 if (qx->flushed) { 304 /* 305 * Overflow. We lost some message. Maybe the packet size is 306 * ridiculously small. 307 */ 308 printf("%s: Overflow in qXfer detected.\n", __func__); 309 return (-ENOBUFS); 310 } 311 312 qx->last_offset += len; 313 qx->flushed = true; 314 315 if (qx->lastmessage) 316 gdb_tx_begin('l'); 317 else 318 gdb_tx_begin('m'); 319 320 memcpy(gdb_txp, buf, len); 321 gdb_txp += len; 322 323 gdb_tx_end(); 324 return (len); 325 } 326 327 static int 328 init_qXfer_ctx(struct qXfer_context *qx, uintmax_t len) 329 { 330 331 /* Protocol (max) length field includes framing overhead. */ 332 if (len < sizeof("$m#nn")) 333 return (ENOSPC); 334 335 len -= 4; 336 len = ummin(len, GDB_BUFSZ - 1); 337 338 qx->last_offset = 0; 339 qx->flushed = false; 340 qx->lastmessage = false; 341 sbuf_new(&qx->sb, qx->xfer_buf, len, SBUF_FIXEDLEN); 342 sbuf_set_drain(&qx->sb, qXfer_drain, qx); 343 return (0); 344 } 345 346 /* 347 * dst must be 2x strlen(max_src) + 1. 348 * 349 * Squashes invalid XML characters down to _. Sorry. Then escapes for GDB. 350 */ 351 static void 352 qXfer_escape_xmlattr_str(char *dst, size_t dstlen, const char *src) 353 { 354 static const char *forbidden = "#$}*"; 355 356 size_t i; 357 char c; 358 359 for (i = 0; i < dstlen - 1 && *src != 0; src++, i++) { 360 c = *src; 361 /* XML attr filter */ 362 if (c < 32) 363 c = '_'; 364 /* We assume attributes will be "" quoted. */ 365 if (c == '<' || c == '&' || c == '"') 366 c = '_'; 367 368 /* GDB escape. */ 369 if (strchr(forbidden, c) != NULL) { 370 *dst++ = '}'; 371 c ^= 0x20; 372 } 373 *dst++ = c; 374 } 375 if (*src != 0) 376 printf("XXX%s: overflow; API misuse\n", __func__); 377 378 *dst = 0; 379 } 380 381 /* 382 * Dynamically generate qXfer:threads document, one packet at a time. 383 * 384 * The format is loosely described[0], although it does not seem that the 385 * <?xml?> mentioned on that page is required. 386 * 387 * [0]: https://sourceware.org/gdb/current/onlinedocs/gdb/Thread-List-Format.html 388 */ 389 static void 390 do_qXfer_threads_read(void) 391 { 392 /* Kludgy context */ 393 static struct { 394 struct qXfer_context qXfer; 395 /* Kludgy state machine */ 396 struct thread *iter; 397 enum { 398 XML_START_THREAD, /* '<thread' */ 399 XML_THREAD_ID, /* ' id="xxx"' */ 400 XML_THREAD_CORE, /* ' core="yyy"' */ 401 XML_THREAD_NAME, /* ' name="zzz"' */ 402 XML_THREAD_EXTRA, /* '> ...' */ 403 XML_END_THREAD, /* '</thread>' */ 404 XML_SENT_END_THREADS, /* '</threads>' */ 405 } next_step; 406 } ctx; 407 static char td_name_escape[MAXCOMLEN * 2 + 1]; 408 409 const char *name_src; 410 uintmax_t offset, len; 411 int error; 412 413 /* Annex part must be empty. */ 414 if (gdb_rx_char() != ':') 415 goto misformed_request; 416 417 if (gdb_rx_varhex(&offset) != 0 || 418 gdb_rx_char() != ',' || 419 gdb_rx_varhex(&len) != 0) 420 goto misformed_request; 421 422 /* 423 * Validate resume xfers. 424 */ 425 if (offset != 0) { 426 if (offset != ctx.qXfer.last_offset) { 427 printf("%s: Resumed offset %ju != expected %zu\n", 428 __func__, offset, ctx.qXfer.last_offset); 429 error = ESPIPE; 430 goto request_error; 431 } 432 ctx.qXfer.flushed = false; 433 } 434 435 if (offset == 0) { 436 ctx.iter = kdb_thr_first(); 437 ctx.next_step = XML_START_THREAD; 438 error = init_qXfer_ctx(&ctx.qXfer, len); 439 if (error != 0) 440 goto request_error; 441 442 sbuf_cat(&ctx.qXfer.sb, "<threads>"); 443 } 444 445 while (!ctx.qXfer.flushed && ctx.iter != NULL) { 446 switch (ctx.next_step) { 447 case XML_START_THREAD: 448 ctx.next_step = XML_THREAD_ID; 449 sbuf_cat(&ctx.qXfer.sb, "<thread"); 450 continue; 451 452 case XML_THREAD_ID: 453 ctx.next_step = XML_THREAD_CORE; 454 sbuf_printf(&ctx.qXfer.sb, " id=\"%jx\"", 455 (uintmax_t)ctx.iter->td_tid); 456 continue; 457 458 case XML_THREAD_CORE: 459 ctx.next_step = XML_THREAD_NAME; 460 if (ctx.iter->td_oncpu != NOCPU) { 461 sbuf_printf(&ctx.qXfer.sb, " core=\"%d\"", 462 ctx.iter->td_oncpu); 463 } 464 continue; 465 466 case XML_THREAD_NAME: 467 ctx.next_step = XML_THREAD_EXTRA; 468 469 if (ctx.iter->td_name[0] != 0) 470 name_src = ctx.iter->td_name; 471 else if (ctx.iter->td_proc != NULL && 472 ctx.iter->td_proc->p_comm[0] != 0) 473 name_src = ctx.iter->td_proc->p_comm; 474 else 475 continue; 476 477 qXfer_escape_xmlattr_str(td_name_escape, 478 sizeof(td_name_escape), name_src); 479 sbuf_printf(&ctx.qXfer.sb, " name=\"%s\"", 480 td_name_escape); 481 continue; 482 483 case XML_THREAD_EXTRA: 484 ctx.next_step = XML_END_THREAD; 485 486 sbuf_putc(&ctx.qXfer.sb, '>'); 487 488 if (ctx.iter->td_state == TDS_RUNNING) 489 sbuf_cat(&ctx.qXfer.sb, "Running"); 490 else if (ctx.iter->td_state == TDS_RUNQ) 491 sbuf_cat(&ctx.qXfer.sb, "RunQ"); 492 else if (ctx.iter->td_state == TDS_CAN_RUN) 493 sbuf_cat(&ctx.qXfer.sb, "CanRun"); 494 else if (TD_ON_LOCK(ctx.iter)) 495 sbuf_cat(&ctx.qXfer.sb, "Blocked"); 496 else if (TD_IS_SLEEPING(ctx.iter)) 497 sbuf_cat(&ctx.qXfer.sb, "Sleeping"); 498 else if (TD_IS_SWAPPED(ctx.iter)) 499 sbuf_cat(&ctx.qXfer.sb, "Swapped"); 500 else if (TD_AWAITING_INTR(ctx.iter)) 501 sbuf_cat(&ctx.qXfer.sb, "IthreadWait"); 502 else if (TD_IS_SUSPENDED(ctx.iter)) 503 sbuf_cat(&ctx.qXfer.sb, "Suspended"); 504 else 505 sbuf_cat(&ctx.qXfer.sb, "???"); 506 continue; 507 508 case XML_END_THREAD: 509 ctx.next_step = XML_START_THREAD; 510 sbuf_cat(&ctx.qXfer.sb, "</thread>"); 511 ctx.iter = kdb_thr_next(ctx.iter); 512 continue; 513 514 /* 515 * This one isn't part of the looping state machine, 516 * but GCC complains if you leave an enum value out of the 517 * select. 518 */ 519 case XML_SENT_END_THREADS: 520 /* NOTREACHED */ 521 break; 522 } 523 } 524 if (ctx.qXfer.flushed) 525 return; 526 527 if (ctx.next_step != XML_SENT_END_THREADS) { 528 ctx.next_step = XML_SENT_END_THREADS; 529 sbuf_cat(&ctx.qXfer.sb, "</threads>"); 530 } 531 if (ctx.qXfer.flushed) 532 return; 533 534 ctx.qXfer.lastmessage = true; 535 sbuf_finish(&ctx.qXfer.sb); 536 sbuf_delete(&ctx.qXfer.sb); 537 ctx.qXfer.last_offset = 0; 538 return; 539 540 misformed_request: 541 /* 542 * GDB "General-Query-Packets.html" qXfer-read anchor specifically 543 * documents an E00 code for malformed requests or invalid annex. 544 * Non-zero codes indicate invalid offset or "error reading the data." 545 */ 546 error = 0; 547 request_error: 548 gdb_tx_err(error); 549 return; 550 } 551 552 /* 553 * A set of standardized transfers from "special data areas." 554 * 555 * We've already matched on "qXfer:" and advanced the rx packet buffer past 556 * that bit. Parse out the rest of the packet and generate an appropriate 557 * response. 558 */ 559 static void 560 do_qXfer(void) 561 { 562 if (!gdb_rx_equal("threads:")) 563 goto unrecognized; 564 565 if (!gdb_rx_equal("read:")) 566 goto unrecognized; 567 568 do_qXfer_threads_read(); 569 return; 570 571 unrecognized: 572 gdb_tx_empty(); 573 return; 574 } 575 576 static void 577 gdb_handle_detach(void) 578 { 579 kdb_cpu_clear_singlestep(); 580 gdb_listening = 0; 581 582 if (gdb_cur->gdb_dbfeatures & GDB_DBGP_FEAT_WANTTERM) 583 gdb_cur->gdb_term(); 584 585 #ifdef DDB 586 if (!gdb_return_to_ddb) 587 return; 588 589 gdb_return_to_ddb = false; 590 591 if (kdb_dbbe_select("ddb") != 0) 592 printf("The ddb backend could not be selected.\n"); 593 #endif 594 } 595 596 static int 597 gdb_trap(int type, int code) 598 { 599 jmp_buf jb; 600 struct thread *thr_iter; 601 void *prev_jb; 602 uint32_t host_features; 603 604 prev_jb = kdb_jmpbuf(jb); 605 if (setjmp(jb) != 0) { 606 printf("%s bailing, hopefully back to ddb!\n", __func__); 607 gdb_listening = 0; 608 (void)kdb_jmpbuf(prev_jb); 609 return (1); 610 } 611 612 gdb_listening = 0; 613 /* 614 * Send a T packet. We currently do not support watchpoints (the 615 * awatch, rwatch or watch elements). 616 */ 617 gdb_tx_begin('T'); 618 gdb_tx_hex(gdb_cpu_signal(type, code), 2); 619 gdb_tx_varhex(GDB_REG_PC); 620 gdb_tx_char(':'); 621 gdb_tx_reg(GDB_REG_PC); 622 gdb_tx_char(';'); 623 gdb_tx_str("thread:"); 624 gdb_tx_varhex((long)kdb_thread->td_tid); 625 gdb_tx_char(';'); 626 gdb_tx_end(); /* XXX check error condition. */ 627 628 thr_iter = NULL; 629 while (gdb_rx_begin() == 0) { 630 /* printf("GDB: got '%s'\n", gdb_rxp); */ 631 switch (gdb_rx_char()) { 632 case '?': /* Last signal. */ 633 gdb_tx_begin('T'); 634 gdb_tx_hex(gdb_cpu_signal(type, code), 2); 635 gdb_tx_str("thread:"); 636 gdb_tx_varhex((long)kdb_thread->td_tid); 637 gdb_tx_char(';'); 638 gdb_tx_end(); 639 break; 640 case 'c': { /* Continue. */ 641 uintmax_t addr; 642 register_t pc; 643 if (!gdb_rx_varhex(&addr)) { 644 pc = addr; 645 gdb_cpu_setreg(GDB_REG_PC, &pc); 646 } 647 kdb_cpu_clear_singlestep(); 648 gdb_listening = 1; 649 return (1); 650 } 651 case 'C': { /* Continue with signal. */ 652 uintmax_t addr, sig; 653 register_t pc; 654 if (!gdb_rx_varhex(&sig) && gdb_rx_char() == ';' && 655 !gdb_rx_varhex(&addr)) { 656 pc = addr; 657 gdb_cpu_setreg(GDB_REG_PC, &pc); 658 } 659 kdb_cpu_clear_singlestep(); 660 gdb_listening = 1; 661 return (1); 662 } 663 case 'D': { /* Detach */ 664 gdb_tx_ok(); 665 gdb_handle_detach(); 666 return (1); 667 } 668 case 'g': { /* Read registers. */ 669 size_t r; 670 gdb_tx_begin(0); 671 for (r = 0; r < GDB_NREGS; r++) 672 gdb_tx_reg(r); 673 gdb_tx_end(); 674 break; 675 } 676 case 'G': /* Write registers. */ 677 gdb_tx_err(0); 678 break; 679 case 'H': { /* Set thread. */ 680 intmax_t tid; 681 struct thread *thr; 682 683 /* Ignore 'g' (general) or 'c' (continue) flag. */ 684 (void) gdb_rx_char(); 685 686 if (gdb_rx_varhex(&tid)) { 687 gdb_tx_err(EINVAL); 688 break; 689 } 690 if (tid > 0) { 691 thr = kdb_thr_lookup(tid); 692 if (thr == NULL) { 693 gdb_tx_err(ENOENT); 694 break; 695 } 696 kdb_thr_select(thr); 697 } 698 gdb_tx_ok(); 699 break; 700 } 701 case 'k': /* Kill request. */ 702 gdb_handle_detach(); 703 return (1); 704 case 'm': { /* Read memory. */ 705 uintmax_t addr, size; 706 if (gdb_rx_varhex(&addr) || gdb_rx_char() != ',' || 707 gdb_rx_varhex(&size)) { 708 gdb_tx_err(EINVAL); 709 break; 710 } 711 gdb_tx_begin(0); 712 if (gdb_tx_mem((char *)(uintptr_t)addr, size)) 713 gdb_tx_end(); 714 else 715 gdb_tx_err(EIO); 716 break; 717 } 718 case 'M': { /* Write memory. */ 719 uintmax_t addr, size; 720 if (gdb_rx_varhex(&addr) || gdb_rx_char() != ',' || 721 gdb_rx_varhex(&size) || gdb_rx_char() != ':') { 722 gdb_tx_err(EINVAL); 723 break; 724 } 725 if (gdb_rx_mem((char *)(uintptr_t)addr, size) == 0) 726 gdb_tx_err(EIO); 727 else 728 gdb_tx_ok(); 729 break; 730 } 731 case 'P': { /* Write register. */ 732 char *val; 733 uintmax_t reg; 734 val = gdb_rxp; 735 if (gdb_rx_varhex(®) || gdb_rx_char() != '=' || 736 !gdb_rx_mem(val, gdb_cpu_regsz(reg))) { 737 gdb_tx_err(EINVAL); 738 break; 739 } 740 gdb_cpu_setreg(reg, val); 741 gdb_tx_ok(); 742 break; 743 } 744 case 'q': /* General query. */ 745 if (gdb_rx_equal("C")) { 746 gdb_tx_begin('Q'); 747 gdb_tx_char('C'); 748 gdb_tx_varhex((long)kdb_thread->td_tid); 749 gdb_tx_end(); 750 } else if (gdb_rx_equal("Supported")) { 751 gdb_do_qsupported(&host_features); 752 } else if (gdb_rx_equal("fThreadInfo")) { 753 thr_iter = kdb_thr_first(); 754 gdb_do_threadinfo(&thr_iter); 755 } else if (gdb_rx_equal("sThreadInfo")) { 756 gdb_do_threadinfo(&thr_iter); 757 } else if (gdb_rx_equal("Xfer:")) { 758 do_qXfer(); 759 } else if (gdb_rx_equal("Search:memory:")) { 760 gdb_do_mem_search(); 761 } else if (!gdb_cpu_query()) 762 gdb_tx_empty(); 763 break; 764 case 's': { /* Step. */ 765 uintmax_t addr; 766 register_t pc; 767 if (!gdb_rx_varhex(&addr)) { 768 pc = addr; 769 gdb_cpu_setreg(GDB_REG_PC, &pc); 770 } 771 kdb_cpu_set_singlestep(); 772 gdb_listening = 1; 773 return (1); 774 } 775 case 'S': { /* Step with signal. */ 776 uintmax_t addr, sig; 777 register_t pc; 778 if (!gdb_rx_varhex(&sig) && gdb_rx_char() == ';' && 779 !gdb_rx_varhex(&addr)) { 780 pc = addr; 781 gdb_cpu_setreg(GDB_REG_PC, &pc); 782 } 783 kdb_cpu_set_singlestep(); 784 gdb_listening = 1; 785 return (1); 786 } 787 case 'T': { /* Thread alive. */ 788 intmax_t tid; 789 if (gdb_rx_varhex(&tid)) { 790 gdb_tx_err(EINVAL); 791 break; 792 } 793 if (kdb_thr_lookup(tid) != NULL) 794 gdb_tx_ok(); 795 else 796 gdb_tx_err(ENOENT); 797 break; 798 } 799 case EOF: 800 /* Empty command. Treat as unknown command. */ 801 /* FALLTHROUGH */ 802 default: 803 /* Unknown command. Send empty response. */ 804 gdb_tx_empty(); 805 break; 806 } 807 } 808 (void)kdb_jmpbuf(prev_jb); 809 return (0); 810 } 811