2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2004 Marcel Moolenaar
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/ctype.h>
36 #include <sys/libkern.h>
37 #include <sys/ttydefaults.h>
39 #include <machine/gdb_machdep.h>
40 #include <machine/kdb.h>
43 #include <gdb/gdb_int.h>
45 static char gdb_rxbuf[GDB_BUFSZ];
48 static char gdb_txbuf[GDB_BUFSZ];
49 char *gdb_txp = NULL; /* Used in inline functions. */
51 #define C2N(c) (((c) < 'A') ? (c) - '0' : \
52 10 + (((c) < 'a') ? (c) - 'A' : (c) - 'a'))
53 #define N2C(n) (((n) < 10) ? (n) + '0' : (n) + 'a' - 10)
56 * Get a single character
65 c = gdb_cur->gdb_getc();
69 printf("Received ^C; trying to switch back to ddb.\n");
71 if (kdb_dbbe_select("ddb") != 0)
72 printf("The ddb backend could not be selected.\n");
74 printf("using longjmp, hope it works!\n");
82 * Functions to receive and extract from a packet.
93 * Wait for the start character, ignore all others.
94 * XXX needs a timeout.
96 while ((c = gdb_getc()) != '$')
99 /* Read until a # or end of buffer is found. */
102 while (gdb_rxsz < sizeof(gdb_rxbuf) - 1) {
106 gdb_rxbuf[gdb_rxsz++] = c;
109 gdb_rxbuf[gdb_rxsz] = 0;
112 /* Bail out on a buffer overflow. */
114 gdb_cur->gdb_putc('-');
119 cksum -= (C2N(c) << 4) & 0xf0;
121 cksum -= C2N(c) & 0x0f;
122 gdb_cur->gdb_putc((cksum == 0) ? '+' : '-');
124 printf("GDB: packet `%s' has invalid checksum\n",
126 } while (cksum != 0);
133 gdb_rx_equal(const char *str)
138 if (len > gdb_rxsz || strncmp(str, gdb_rxp, len) != 0)
146 gdb_rx_mem(unsigned char *addr, size_t size)
156 if (size * 2 != gdb_rxsz)
159 wctx = gdb_begin_write();
160 prev = kdb_jmpbuf(jb);
166 c = (C2N(gdb_rxp[0]) << 4) & 0xf0;
167 c |= C2N(gdb_rxp[1]) & 0x0f;
172 kdb_cpu_sync_icache(addr, size);
174 (void)kdb_jmpbuf(prev);
176 return ((ret == 0) ? 1 : 0);
180 gdb_rx_varhex(uintmax_t *vp)
186 neg = (c == '-') ? 1 : 0;
190 gdb_rxp -= ((c == -1) ? 0 : 1) + neg;
191 gdb_rxsz += ((c == -1) ? 0 : 1) + neg;
199 } while (isxdigit(c));
204 *vp = (neg) ? -v : v;
209 * Function to build and send a package.
213 gdb_tx_begin(char tp)
226 unsigned char c, cksum;
229 gdb_cur->gdb_putc('$');
233 while (p < gdb_txp) {
234 /* Send a character and start run-length encoding. */
236 gdb_cur->gdb_putc(c);
239 /* Determine run-length and update checksum. */
240 while (p < gdb_txp && *p == c) {
244 /* Emit the run-length encoded string. */
245 while (runlen >= 97) {
246 gdb_cur->gdb_putc('*');
248 gdb_cur->gdb_putc(97+29);
252 gdb_cur->gdb_putc(c);
258 gdb_cur->gdb_putc(c);
264 /* Don't emit '$', '#', '+' or '-'. */
266 gdb_cur->gdb_putc(c);
270 if (runlen == 6 || runlen == 14 || runlen == 16) {
271 gdb_cur->gdb_putc(c);
275 gdb_cur->gdb_putc('*');
277 gdb_cur->gdb_putc(runlen+29);
281 gdb_cur->gdb_putc('#');
283 gdb_cur->gdb_putc(N2C(c));
285 gdb_cur->gdb_putc(N2C(c));
294 gdb_tx_mem(const unsigned char *addr, size_t size)
300 prev = kdb_jmpbuf(jb);
304 *gdb_txp++ = N2C(*addr >> 4);
305 *gdb_txp++ = N2C(*addr & 0x0f);
309 (void)kdb_jmpbuf(prev);
310 return ((ret == 0) ? 1 : 0);
314 gdb_tx_reg(int regnum)
319 regp = gdb_cpu_getreg(regnum, ®sz);
321 /* Register unavailable. */
327 gdb_tx_mem(regp, regsz);
330 /* Read binary data up until the end of the packet or until we have datalen decoded bytes */
332 gdb_rx_bindata(unsigned char *data, size_t datalen, size_t *amt)
338 while (*amt < datalen) {
343 /* Escaped character up next */
345 /* Truncated packet? Bail out */
346 if ((c = gdb_rx_char()) == -1)
350 *(data++) = c & 0xff;
358 gdb_search_mem(const unsigned char *addr, size_t size, const unsigned char *pat, size_t patlen, const unsigned char **found)
364 prev = kdb_jmpbuf(jb);
367 *found = memmem(addr, size, pat, patlen);
369 (void)kdb_jmpbuf(prev);
370 return ((ret == 0) ? 1 : 0);