Author: benno
Date: Fri Sep  5 16:40:47 2014
New Revision: 271173
URL: http://svnweb.freebsd.org/changeset/base/271173

Log:
  Add support for gdb's memory searching capabilities to our in-kernel gdb
  server.
  
  Submitted by: Daniel O'Connor <daniel.ocon...@isilon.com>
  Reviewed by:  jhb
  Sponsored by: EMC Isilon Storage Division

Added:
  head/sys/libkern/memmem.c   (contents, props changed)
Modified:
  head/sys/conf/files
  head/sys/gdb/gdb_int.h
  head/sys/gdb/gdb_main.c
  head/sys/gdb/gdb_packet.c
  head/sys/sys/libkern.h

Modified: head/sys/conf/files
==============================================================================
--- head/sys/conf/files Fri Sep  5 15:45:20 2014        (r271172)
+++ head/sys/conf/files Fri Sep  5 16:40:47 2014        (r271173)
@@ -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

Modified: head/sys/gdb/gdb_int.h
==============================================================================
--- head/sys/gdb/gdb_int.h      Fri Sep  5 15:45:20 2014        (r271172)
+++ head/sys/gdb/gdb_int.h      Fri Sep  5 16:40:47 2014        (r271173)
@@ -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)

Modified: head/sys/gdb/gdb_main.c
==============================================================================
--- head/sys/gdb/gdb_main.c     Fri Sep  5 15:45:20 2014        (r271172)
+++ head/sys/gdb/gdb_main.c     Fri Sep  5 16:40:47 2014        (r271173)
@@ -53,6 +53,8 @@ SET_DECLARE(gdb_dbgport_set, struct gdb_
 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;

Modified: head/sys/gdb/gdb_packet.c
==============================================================================
--- head/sys/gdb/gdb_packet.c   Fri Sep  5 15:45:20 2014        (r271172)
+++ head/sys/gdb/gdb_packet.c   Fri Sep  5 16:40:47 2014        (r271173)
@@ -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);
+}

Added: head/sys/libkern/memmem.c
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/libkern/memmem.c   Fri Sep  5 16:40:47 2014        (r271173)
@@ -0,0 +1,62 @@
+/*-
+ * Copyright (c) 2005 Pascal Gloor <pascal.gl...@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;
+}

Modified: head/sys/sys/libkern.h
==============================================================================
--- head/sys/sys/libkern.h      Fri Sep  5 15:45:20 2014        (r271172)
+++ head/sys/sys/libkern.h      Fri Sep  5 16:40:47 2014        (r271173)
@@ -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,
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to