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