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
This commit is contained in:
Benno Rice 2014-09-05 16:40:47 +00:00
parent a5f9f526bd
commit 27ecc2adbc
6 changed files with 136 additions and 1 deletions

View File

@ -3176,8 +3176,9 @@ libkern/inet_pton.c standard
libkern/jenkins_hash.c standard
libkern/mcount.c optional profiling-routine
libkern/memcchr.c standard
libkern/memchr.c optional fdt
libkern/memchr.c optional fdt | gdb
libkern/memcmp.c standard
libkern/memmem.c optional gdb
libkern/qsort.c standard
libkern/qsort_r.c standard
libkern/random.c standard

View File

@ -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)

View File

@ -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;

View File

@ -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);
}

62
sys/libkern/memmem.c Normal file
View File

@ -0,0 +1,62 @@
/*-
* Copyright (c) 2005 Pascal Gloor <pascal.gloor@spale.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/libkern.h>
#include <sys/param.h>
void *
memmem(const void *l, size_t l_len, const void *s, size_t s_len)
{
register char *cur, *last;
const char *cl = (const char *)l;
const char *cs = (const char *)s;
/* we need something to compare */
if (l_len == 0 || s_len == 0)
return NULL;
/* "s" must be smaller or equal to "l" */
if (l_len < s_len)
return NULL;
/* special case where s_len == 1 */
if (s_len == 1)
return memchr(l, (int)*cs, l_len);
/* the last position where its possible to find "s" in "l" */
last = (char *)cl + l_len - s_len;
for (cur = (char *)cl; cur <= last; cur++)
if (cur[0] == cs[0] && memcmp(cur, cs, s_len) == 0)
return cur;
return NULL;
}

View File

@ -103,6 +103,7 @@ int locc(int, char *, u_int);
void *memchr(const void *s, int c, size_t n);
void *memcchr(const void *s, int c, size_t n);
int memcmp(const void *b1, const void *b2, size_t len);
void *memmem(const void *l, size_t l_len, const void *s, size_t s_len);
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
void qsort_r(void *base, size_t nmemb, size_t size, void *thunk,