xref: /freebsd/sys/gdb/gdb_main.c (revision 036d2e814bf0f5d88ffb4b24c159320894541757)
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(&reg) || 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