summaryrefslogtreecommitdiffstats
path: root/sys/gdb
diff options
context:
space:
mode:
authorbenno <benno@FreeBSD.org>2014-09-05 16:40:47 +0000
committerbenno <benno@FreeBSD.org>2014-09-05 16:40:47 +0000
commitb46fbbac90c150e0c7ed397aee01711a8e2b6461 (patch)
tree9c65549c84dd3404b6d357698cfa4a416e414b44 /sys/gdb
parentca6e87735466b49e624fca023d7c8aade7025e62 (diff)
downloadFreeBSD-src-b46fbbac90c150e0c7ed397aee01711a8e2b6461.zip
FreeBSD-src-b46fbbac90c150e0c7ed397aee01711a8e2b6461.tar.gz
Add support for gdb's memory searching capabilities to our in-kernel gdb
server. Submitted by: Daniel O'Connor <daniel.oconnor@isilon.com> Reviewed by: jhb Sponsored by: EMC Isilon Storage Division
Diffstat (limited to 'sys/gdb')
-rw-r--r--sys/gdb/gdb_int.h3
-rw-r--r--sys/gdb/gdb_main.c24
-rw-r--r--sys/gdb/gdb_packet.c44
3 files changed, 71 insertions, 0 deletions
diff --git a/sys/gdb/gdb_int.h b/sys/gdb/gdb_int.h
index d06943a..aa89402 100644
--- a/sys/gdb/gdb_int.h
+++ b/sys/gdb/gdb_int.h
@@ -60,6 +60,9 @@ void gdb_tx_begin(char);
int gdb_tx_end(void);
int gdb_tx_mem(const unsigned char *, size_t);
void gdb_tx_reg(int);
+int gdb_rx_bindata(unsigned char *data, size_t datalen, size_t *amt);
+int gdb_search_mem(const unsigned char *addr, size_t size,
+ const unsigned char *pat, size_t patlen, const unsigned char **found);
static __inline void
gdb_tx_char(char c)
diff --git a/sys/gdb/gdb_main.c b/sys/gdb/gdb_main.c
index 4ed3272..f8f3836 100644
--- a/sys/gdb/gdb_main.c
+++ b/sys/gdb/gdb_main.c
@@ -53,6 +53,8 @@ SET_DECLARE(gdb_dbgport_set, struct gdb_dbgport);
struct gdb_dbgport *gdb_cur = NULL;
int gdb_listening = 0;
+static unsigned char gdb_bindata[64];
+
static int
gdb_init(void)
{
@@ -254,6 +256,28 @@ gdb_trap(int type, int code)
gdb_tx_begin('l');
gdb_tx_end();
}
+ } else if (gdb_rx_equal("Search:memory:")) {
+ size_t patlen;
+ intmax_t addr, size;
+ const unsigned char *found;
+ if (gdb_rx_varhex(&addr) || gdb_rx_char() != ';' ||
+ gdb_rx_varhex(&size) || gdb_rx_char() != ';' ||
+ gdb_rx_bindata(gdb_bindata, sizeof(gdb_bindata), &patlen)) {
+ gdb_tx_err(EINVAL);
+ break;
+ }
+ if (gdb_search_mem((char *)(uintptr_t)addr, size, gdb_bindata, patlen, &found)) {
+ if (found == 0ULL)
+ gdb_tx_begin('0');
+ else {
+ gdb_tx_begin('1');
+ gdb_tx_char(',');
+ gdb_tx_hex((intmax_t)(uintptr_t)found, 8);
+ }
+ gdb_tx_end();
+ } else
+ gdb_tx_err(EIO);
+ break;
} else if (!gdb_cpu_query())
gdb_tx_empty();
break;
diff --git a/sys/gdb/gdb_packet.c b/sys/gdb/gdb_packet.c
index a62cc8d..73ee74f 100644
--- a/sys/gdb/gdb_packet.c
+++ b/sys/gdb/gdb_packet.c
@@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/ctype.h>
#include <sys/kdb.h>
+#include <sys/libkern.h>
#include <sys/ttydefaults.h>
#include <machine/gdb_machdep.h>
@@ -320,3 +321,46 @@ gdb_tx_reg(int regnum)
} else
gdb_tx_mem(regp, regsz);
}
+
+/* Read binary data up until the end of the packet or until we have datalen decoded bytes */
+int
+gdb_rx_bindata(unsigned char *data, size_t datalen, size_t *amt)
+{
+ int c;
+
+ *amt = 0;
+
+ while (*amt < datalen) {
+ c = gdb_rx_char();
+ /* End of packet? */
+ if (c == -1)
+ break;
+ /* Escaped character up next */
+ if (c == '}') {
+ /* Truncated packet? Bail out */
+ if ((c = gdb_rx_char()) == -1)
+ return (1);
+ c ^= 0x20;
+ }
+ *(data++) = c & 0xff;
+ (*amt)++;
+ }
+
+ return (0);
+}
+
+int
+gdb_search_mem(const unsigned char *addr, size_t size, const unsigned char *pat, size_t patlen, const unsigned char **found)
+{
+ void *prev;
+ jmp_buf jb;
+ int ret;
+
+ prev = kdb_jmpbuf(jb);
+ ret = setjmp(jb);
+ if (ret == 0)
+ *found = memmem(addr, size, pat, patlen);
+
+ (void)kdb_jmpbuf(prev);
+ return ((ret == 0) ? 1 : 0);
+}
OpenPOWER on IntegriCloud