diff options
author | benno <benno@FreeBSD.org> | 2014-09-05 16:40:47 +0000 |
---|---|---|
committer | benno <benno@FreeBSD.org> | 2014-09-05 16:40:47 +0000 |
commit | b46fbbac90c150e0c7ed397aee01711a8e2b6461 (patch) | |
tree | 9c65549c84dd3404b6d357698cfa4a416e414b44 /sys/gdb | |
parent | ca6e87735466b49e624fca023d7c8aade7025e62 (diff) | |
download | FreeBSD-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.h | 3 | ||||
-rw-r--r-- | sys/gdb/gdb_main.c | 24 | ||||
-rw-r--r-- | sys/gdb/gdb_packet.c | 44 |
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); +} |