aboutsummaryrefslogtreecommitdiff
path: root/sys/gdb
diff options
context:
space:
mode:
authorConrad Meyer <cem@FreeBSD.org>2019-08-22 00:19:41 +0000
committerConrad Meyer <cem@FreeBSD.org>2019-08-22 00:19:41 +0000
commitc4fbbfaa472bb4f102aaa41bfc0f3760ccbc9ef8 (patch)
tree6695c8f671f8915fae8049401bd7336c09a89a0c /sys/gdb
parent76c8c0902cbdc87d8059d2c9bef8be390c8180ff (diff)
downloadsrc-c4fbbfaa472bb4f102aaa41bfc0f3760ccbc9ef8.tar.gz
src-c4fbbfaa472bb4f102aaa41bfc0f3760ccbc9ef8.zip
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.
Notes
Notes: svn path=/head/; revision=351366
Diffstat (limited to 'sys/gdb')
-rw-r--r--sys/gdb/gdb_main.c107
1 files changed, 107 insertions, 0 deletions
diff --git a/sys/gdb/gdb_main.c b/sys/gdb/gdb_main.c
index ed1b8a245347..9fa0e2a4eb22 100644
--- a/sys/gdb/gdb_main.c
+++ b/sys/gdb/gdb_main.c
@@ -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);