svn commit: r351366 - head/sys/gdb

Conrad Meyer cem at FreeBSD.org
Thu Aug 22 00:19:41 UTC 2019


Author: cem
Date: Thu Aug 22 00:19:41 2019
New Revision: 351366
URL: https://svnweb.freebsd.org/changeset/base/351366

Log:
  gdb(4): Add basic 'qSupported' support
  
  This is where the host GDB tells us what features it supports, and we
  respond with the list we support.  For now, just report PacketSize.

Modified:
  head/sys/gdb/gdb_main.c

Modified: head/sys/gdb/gdb_main.c
==============================================================================
--- head/sys/gdb/gdb_main.c	Thu Aug 22 00:19:14 2019	(r351365)
+++ head/sys/gdb/gdb_main.c	Thu Aug 22 00:19:41 2019	(r351366)
@@ -162,12 +162,117 @@ sendit:
 	gdb_tx_end();
 }
 
+#define	BIT(n)	(1ull << (n))
+enum {
+	GDB_MULTIPROCESS,
+	GDB_SWBREAK,
+	GDB_HWBREAK,
+	GDB_QRELOCINSN,
+	GDB_FORK_EVENTS,
+	GDB_VFORK_EVENTS,
+	GDB_EXEC_EVENTS,
+	GDB_VCONT_SUPPORTED,
+	GDB_QTHREADEVENTS,
+	GDB_NO_RESUMED,
+};
+static const char * const gdb_feature_names[] = {
+	[GDB_MULTIPROCESS] = "multiprocess",
+	[GDB_SWBREAK] = "swbreak",
+	[GDB_HWBREAK] = "hwbreak",
+	[GDB_QRELOCINSN] = "qRelocInsn",
+	[GDB_FORK_EVENTS] = "fork-events",
+	[GDB_VFORK_EVENTS] = "vfork-events",
+	[GDB_EXEC_EVENTS] = "exec-events",
+	[GDB_VCONT_SUPPORTED] = "vContSupported",
+	[GDB_QTHREADEVENTS] = "QThreadEvents",
+	[GDB_NO_RESUMED] = "no-resumed",
+};
+static void
+gdb_do_qsupported(uint32_t *feat)
+{
+	char *tok, *delim, ok;
+	size_t i, toklen;
+
+	/* Parse supported host features */
+	*feat = 0;
+	if (gdb_rx_char() != ':')
+		goto error;
+
+	while (gdb_rxsz > 0) {
+		tok = gdb_rxp;
+		delim = strchrnul(gdb_rxp, ';');
+		toklen = (delim - tok);
+
+		gdb_rxp += toklen;
+		gdb_rxsz -= toklen;
+		if (*delim != '\0') {
+			*delim = '\0';
+			gdb_rxp += 1;
+			gdb_rxsz -= 1;
+		}
+
+		if (toklen < 2)
+			goto error;
+
+		ok = tok[toklen - 1];
+		if (ok != '-' && ok != '+') {
+			/*
+			 * GDB only has one KV-pair feature, and we don't
+			 * support it, so ignore and move on.
+			 */
+			if (strchr(tok, '=') != NULL)
+				continue;
+			/* Not a KV-pair, and not a +/- flag?  Malformed. */
+			goto error;
+		}
+		if (ok != '+')
+			continue;
+		tok[toklen - 1] = '\0';
+
+		for (i = 0; i < nitems(gdb_feature_names); i++)
+			if (strcmp(gdb_feature_names[i], tok) == 0)
+				break;
+
+		if (i == nitems(gdb_feature_names)) {
+			/* Unknown GDB feature. */
+			continue;
+		}
+
+		*feat |= BIT(i);
+	}
+
+	/* Send a supported feature list back */
+	gdb_tx_begin(0);
+
+	gdb_tx_str("PacketSize");
+	gdb_tx_char('=');
+	/*
+	 * We don't buffer framing bytes, but we do need to retain a byte for a
+	 * trailing nul.
+	 */
+	gdb_tx_varhex(GDB_BUFSZ + strlen("$#nn") - 1);
+
+	/*
+	 * Future consideration:
+	 *   - vCont
+	 *   - multiprocess
+	 *   - qXfer:threads:read
+	 */
+	gdb_tx_end();
+	return;
+
+error:
+	*feat = 0;
+	gdb_tx_err(EINVAL);
+}
+
 static int
 gdb_trap(int type, int code)
 {
 	jmp_buf jb;
 	struct thread *thr_iter;
 	void *prev_jb;
+	uint32_t host_features;
 
 	prev_jb = kdb_jmpbuf(jb);
 	if (setjmp(jb) != 0) {
@@ -313,6 +418,8 @@ gdb_trap(int type, int code)
 				gdb_tx_char('C');
 				gdb_tx_varhex((long)kdb_thread->td_tid);
 				gdb_tx_end();
+			} else if (gdb_rx_equal("Supported")) {
+				gdb_do_qsupported(&host_features);
 			} else if (gdb_rx_equal("fThreadInfo")) {
 				thr_iter = kdb_thr_first();
 				gdb_do_threadinfo(&thr_iter);


More information about the svn-src-all mailing list