1fa521b03SWarner Losh /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
3497b6b2aSPedro F. Giffuni *
472d44f31SMarcel Moolenaar * Copyright (c) 2004 Marcel Moolenaar
572d44f31SMarcel Moolenaar * All rights reserved.
672d44f31SMarcel Moolenaar *
772d44f31SMarcel Moolenaar * Redistribution and use in source and binary forms, with or without
872d44f31SMarcel Moolenaar * modification, are permitted provided that the following conditions
972d44f31SMarcel Moolenaar * are met:
1072d44f31SMarcel Moolenaar *
1172d44f31SMarcel Moolenaar * 1. Redistributions of source code must retain the above copyright
1272d44f31SMarcel Moolenaar * notice, this list of conditions and the following disclaimer.
1372d44f31SMarcel Moolenaar * 2. Redistributions in binary form must reproduce the above copyright
1472d44f31SMarcel Moolenaar * notice, this list of conditions and the following disclaimer in the
1572d44f31SMarcel Moolenaar * documentation and/or other materials provided with the distribution.
1672d44f31SMarcel Moolenaar *
1772d44f31SMarcel Moolenaar * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1872d44f31SMarcel Moolenaar * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1972d44f31SMarcel Moolenaar * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2072d44f31SMarcel Moolenaar * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2172d44f31SMarcel Moolenaar * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2272d44f31SMarcel Moolenaar * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2372d44f31SMarcel Moolenaar * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2472d44f31SMarcel Moolenaar * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2572d44f31SMarcel Moolenaar * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2672d44f31SMarcel Moolenaar * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2772d44f31SMarcel Moolenaar */
2872d44f31SMarcel Moolenaar
2972d44f31SMarcel Moolenaar #include <sys/param.h>
3072d44f31SMarcel Moolenaar #include <sys/systm.h>
3172d44f31SMarcel Moolenaar #include <sys/ctype.h>
3272d44f31SMarcel Moolenaar #include <sys/kdb.h>
3327ecc2adSBenno Rice #include <sys/libkern.h>
343a5d3671SMatthew D Fleming #include <sys/ttydefaults.h>
3572d44f31SMarcel Moolenaar
3672d44f31SMarcel Moolenaar #include <machine/gdb_machdep.h>
3701bd17ccSMarcel Moolenaar #include <machine/kdb.h>
3872d44f31SMarcel Moolenaar
3972d44f31SMarcel Moolenaar #include <gdb/gdb.h>
4072d44f31SMarcel Moolenaar #include <gdb/gdb_int.h>
4172d44f31SMarcel Moolenaar
4272d44f31SMarcel Moolenaar static char gdb_rxbuf[GDB_BUFSZ];
4372d44f31SMarcel Moolenaar char *gdb_rxp = NULL;
4472d44f31SMarcel Moolenaar size_t gdb_rxsz = 0;
45dda17b36SConrad Meyer
46dda17b36SConrad Meyer /*
47dda17b36SConrad Meyer * The goal here is to allow in-place framing without making the math around
48dda17b36SConrad Meyer * 'gdb_txbuf' more complicated. A generous reading of union special rule for
49dda17b36SConrad Meyer * "common initial sequence" suggests this may be valid in standard C99 and
50dda17b36SConrad Meyer * later.
51dda17b36SConrad Meyer */
52dda17b36SConrad Meyer static union {
53dda17b36SConrad Meyer struct _midbuf {
54dda17b36SConrad Meyer char mb_pad1;
55dda17b36SConrad Meyer char mb_buf[GDB_BUFSZ];
56dda17b36SConrad Meyer char mb_pad2[4];
57dda17b36SConrad Meyer } __packed txu_midbuf;
58dda17b36SConrad Meyer /* sizeof includes trailing nul byte and this is intentional. */
59dda17b36SConrad Meyer char txu_fullbuf[GDB_BUFSZ + sizeof("$#..")];
60dda17b36SConrad Meyer } gdb_tx_u;
61dda17b36SConrad Meyer #define gdb_txbuf gdb_tx_u.txu_midbuf.mb_buf
62dda17b36SConrad Meyer #define gdb_tx_fullbuf gdb_tx_u.txu_fullbuf
63dda17b36SConrad Meyer _Static_assert(sizeof(gdb_tx_u.txu_midbuf) == sizeof(gdb_tx_u.txu_fullbuf) &&
64dda17b36SConrad Meyer offsetof(struct _midbuf, mb_buf) == 1,
65dda17b36SConrad Meyer "assertions necessary for correctness");
6672d44f31SMarcel Moolenaar char *gdb_txp = NULL; /* Used in inline functions. */
6772d44f31SMarcel Moolenaar
6872d44f31SMarcel Moolenaar #define C2N(c) (((c) < 'A') ? (c) - '0' : \
6972d44f31SMarcel Moolenaar 10 + (((c) < 'a') ? (c) - 'A' : (c) - 'a'))
7072d44f31SMarcel Moolenaar #define N2C(n) (((n) < 10) ? (n) + '0' : (n) + 'a' - 10)
7172d44f31SMarcel Moolenaar
7272d44f31SMarcel Moolenaar /*
73f346afc4SPoul-Henning Kamp * Get a single character
74f346afc4SPoul-Henning Kamp */
75f346afc4SPoul-Henning Kamp
76f346afc4SPoul-Henning Kamp static int
gdb_getc(void)77f346afc4SPoul-Henning Kamp gdb_getc(void)
78f346afc4SPoul-Henning Kamp {
79f346afc4SPoul-Henning Kamp int c;
80f346afc4SPoul-Henning Kamp
81f346afc4SPoul-Henning Kamp do
82f346afc4SPoul-Henning Kamp c = gdb_cur->gdb_getc();
83f346afc4SPoul-Henning Kamp while (c == -1);
843a5d3671SMatthew D Fleming
853a5d3671SMatthew D Fleming if (c == CTRL('C')) {
863a5d3671SMatthew D Fleming printf("Received ^C; trying to switch back to ddb.\n");
873a5d3671SMatthew D Fleming
88dda17b36SConrad Meyer if (gdb_cur->gdb_dbfeatures & GDB_DBGP_FEAT_WANTTERM)
89dda17b36SConrad Meyer gdb_cur->gdb_term();
90dda17b36SConrad Meyer
913a5d3671SMatthew D Fleming if (kdb_dbbe_select("ddb") != 0)
923a5d3671SMatthew D Fleming printf("The ddb backend could not be selected.\n");
933a5d3671SMatthew D Fleming else {
943a5d3671SMatthew D Fleming printf("using longjmp, hope it works!\n");
953a5d3671SMatthew D Fleming kdb_reenter();
963a5d3671SMatthew D Fleming }
973a5d3671SMatthew D Fleming }
98f346afc4SPoul-Henning Kamp return (c);
99f346afc4SPoul-Henning Kamp }
100f346afc4SPoul-Henning Kamp
101f346afc4SPoul-Henning Kamp /*
10272d44f31SMarcel Moolenaar * Functions to receive and extract from a packet.
10372d44f31SMarcel Moolenaar */
10472d44f31SMarcel Moolenaar
10572d44f31SMarcel Moolenaar int
gdb_rx_begin(void)10672d44f31SMarcel Moolenaar gdb_rx_begin(void)
10772d44f31SMarcel Moolenaar {
10872d44f31SMarcel Moolenaar int c, cksum;
10972d44f31SMarcel Moolenaar
11072d44f31SMarcel Moolenaar gdb_rxp = NULL;
11172d44f31SMarcel Moolenaar do {
11272d44f31SMarcel Moolenaar /*
11372d44f31SMarcel Moolenaar * Wait for the start character, ignore all others.
11472d44f31SMarcel Moolenaar * XXX needs a timeout.
11572d44f31SMarcel Moolenaar */
116f346afc4SPoul-Henning Kamp while ((c = gdb_getc()) != '$')
11772d44f31SMarcel Moolenaar ;
11872d44f31SMarcel Moolenaar
11972d44f31SMarcel Moolenaar /* Read until a # or end of buffer is found. */
12072d44f31SMarcel Moolenaar cksum = 0;
12172d44f31SMarcel Moolenaar gdb_rxsz = 0;
12272d44f31SMarcel Moolenaar while (gdb_rxsz < sizeof(gdb_rxbuf) - 1) {
123f346afc4SPoul-Henning Kamp c = gdb_getc();
12472d44f31SMarcel Moolenaar if (c == '#')
12572d44f31SMarcel Moolenaar break;
12672d44f31SMarcel Moolenaar gdb_rxbuf[gdb_rxsz++] = c;
12772d44f31SMarcel Moolenaar cksum += c;
12872d44f31SMarcel Moolenaar }
12972d44f31SMarcel Moolenaar gdb_rxbuf[gdb_rxsz] = 0;
13072d44f31SMarcel Moolenaar cksum &= 0xff;
13172d44f31SMarcel Moolenaar
13272d44f31SMarcel Moolenaar /* Bail out on a buffer overflow. */
13372d44f31SMarcel Moolenaar if (c != '#') {
1346310546dSConrad Meyer gdb_nack();
13572d44f31SMarcel Moolenaar return (ENOSPC);
13672d44f31SMarcel Moolenaar }
13772d44f31SMarcel Moolenaar
1386310546dSConrad Meyer /*
1396310546dSConrad Meyer * In Not-AckMode, we can assume reliable transport and neither
1406310546dSConrad Meyer * need to verify checksums nor send Ack/Nack.
1416310546dSConrad Meyer */
1426310546dSConrad Meyer if (!gdb_ackmode)
1436310546dSConrad Meyer break;
1446310546dSConrad Meyer
145f346afc4SPoul-Henning Kamp c = gdb_getc();
14672d44f31SMarcel Moolenaar cksum -= (C2N(c) << 4) & 0xf0;
147f346afc4SPoul-Henning Kamp c = gdb_getc();
14872d44f31SMarcel Moolenaar cksum -= C2N(c) & 0x0f;
1496310546dSConrad Meyer if (cksum == 0) {
1506310546dSConrad Meyer gdb_ack();
1516310546dSConrad Meyer } else {
1526310546dSConrad Meyer gdb_nack();
15372d44f31SMarcel Moolenaar printf("GDB: packet `%s' has invalid checksum\n",
15472d44f31SMarcel Moolenaar gdb_rxbuf);
1556310546dSConrad Meyer }
15672d44f31SMarcel Moolenaar } while (cksum != 0);
15772d44f31SMarcel Moolenaar
15872d44f31SMarcel Moolenaar gdb_rxp = gdb_rxbuf;
15972d44f31SMarcel Moolenaar return (0);
16072d44f31SMarcel Moolenaar }
16172d44f31SMarcel Moolenaar
16272d44f31SMarcel Moolenaar int
gdb_rx_equal(const char * str)16372d44f31SMarcel Moolenaar gdb_rx_equal(const char *str)
16472d44f31SMarcel Moolenaar {
16572d44f31SMarcel Moolenaar int len;
16672d44f31SMarcel Moolenaar
16772d44f31SMarcel Moolenaar len = strlen(str);
16872d44f31SMarcel Moolenaar if (len > gdb_rxsz || strncmp(str, gdb_rxp, len) != 0)
16972d44f31SMarcel Moolenaar return (0);
17072d44f31SMarcel Moolenaar gdb_rxp += len;
17172d44f31SMarcel Moolenaar gdb_rxsz -= len;
17272d44f31SMarcel Moolenaar return (1);
17372d44f31SMarcel Moolenaar }
17472d44f31SMarcel Moolenaar
17572d44f31SMarcel Moolenaar int
gdb_rx_mem(unsigned char * addr,size_t size)17672d44f31SMarcel Moolenaar gdb_rx_mem(unsigned char *addr, size_t size)
17772d44f31SMarcel Moolenaar {
17801bd17ccSMarcel Moolenaar unsigned char *p;
17972d44f31SMarcel Moolenaar void *prev;
180beb24065SJonathan T. Looney void *wctx;
18172d44f31SMarcel Moolenaar jmp_buf jb;
18201bd17ccSMarcel Moolenaar size_t cnt;
18372d44f31SMarcel Moolenaar int ret;
18472d44f31SMarcel Moolenaar unsigned char c;
18572d44f31SMarcel Moolenaar
18672d44f31SMarcel Moolenaar if (size * 2 != gdb_rxsz)
18772d44f31SMarcel Moolenaar return (-1);
18872d44f31SMarcel Moolenaar
189beb24065SJonathan T. Looney wctx = gdb_begin_write();
19072d44f31SMarcel Moolenaar prev = kdb_jmpbuf(jb);
19172d44f31SMarcel Moolenaar ret = setjmp(jb);
19272d44f31SMarcel Moolenaar if (ret == 0) {
19301bd17ccSMarcel Moolenaar p = addr;
19401bd17ccSMarcel Moolenaar cnt = size;
19501bd17ccSMarcel Moolenaar while (cnt-- > 0) {
19672d44f31SMarcel Moolenaar c = (C2N(gdb_rxp[0]) << 4) & 0xf0;
19772d44f31SMarcel Moolenaar c |= C2N(gdb_rxp[1]) & 0x0f;
19801bd17ccSMarcel Moolenaar *p++ = c;
19972d44f31SMarcel Moolenaar gdb_rxsz -= 2;
20072d44f31SMarcel Moolenaar gdb_rxp += 2;
20172d44f31SMarcel Moolenaar }
20201bd17ccSMarcel Moolenaar kdb_cpu_sync_icache(addr, size);
20372d44f31SMarcel Moolenaar }
20472d44f31SMarcel Moolenaar (void)kdb_jmpbuf(prev);
205beb24065SJonathan T. Looney gdb_end_write(wctx);
20672d44f31SMarcel Moolenaar return ((ret == 0) ? 1 : 0);
20772d44f31SMarcel Moolenaar }
20872d44f31SMarcel Moolenaar
20972d44f31SMarcel Moolenaar int
gdb_rx_varhex(uintmax_t * vp)21072d44f31SMarcel Moolenaar gdb_rx_varhex(uintmax_t *vp)
21172d44f31SMarcel Moolenaar {
21272d44f31SMarcel Moolenaar uintmax_t v;
21372d44f31SMarcel Moolenaar int c, neg;
21472d44f31SMarcel Moolenaar
21572d44f31SMarcel Moolenaar c = gdb_rx_char();
21672d44f31SMarcel Moolenaar neg = (c == '-') ? 1 : 0;
21772d44f31SMarcel Moolenaar if (neg == 1)
21872d44f31SMarcel Moolenaar c = gdb_rx_char();
21972d44f31SMarcel Moolenaar if (!isxdigit(c)) {
22072d44f31SMarcel Moolenaar gdb_rxp -= ((c == -1) ? 0 : 1) + neg;
22172d44f31SMarcel Moolenaar gdb_rxsz += ((c == -1) ? 0 : 1) + neg;
22272d44f31SMarcel Moolenaar return (-1);
22372d44f31SMarcel Moolenaar }
22472d44f31SMarcel Moolenaar v = 0;
22572d44f31SMarcel Moolenaar do {
22672d44f31SMarcel Moolenaar v <<= 4;
22772d44f31SMarcel Moolenaar v += C2N(c);
22872d44f31SMarcel Moolenaar c = gdb_rx_char();
22972d44f31SMarcel Moolenaar } while (isxdigit(c));
2305df6fa43SConrad Meyer if (c != EOF) {
23172d44f31SMarcel Moolenaar gdb_rxp--;
23272d44f31SMarcel Moolenaar gdb_rxsz++;
23372d44f31SMarcel Moolenaar }
23472d44f31SMarcel Moolenaar *vp = (neg) ? -v : v;
23572d44f31SMarcel Moolenaar return (0);
23672d44f31SMarcel Moolenaar }
23772d44f31SMarcel Moolenaar
23872d44f31SMarcel Moolenaar /*
23972d44f31SMarcel Moolenaar * Function to build and send a package.
24072d44f31SMarcel Moolenaar */
24172d44f31SMarcel Moolenaar
24272d44f31SMarcel Moolenaar void
gdb_tx_begin(char tp)24372d44f31SMarcel Moolenaar gdb_tx_begin(char tp)
24472d44f31SMarcel Moolenaar {
24572d44f31SMarcel Moolenaar
24672d44f31SMarcel Moolenaar gdb_txp = gdb_txbuf;
24772d44f31SMarcel Moolenaar if (tp != '\0')
24872d44f31SMarcel Moolenaar gdb_tx_char(tp);
24972d44f31SMarcel Moolenaar }
25072d44f31SMarcel Moolenaar
251dda17b36SConrad Meyer /*
252dda17b36SConrad Meyer * Take raw packet buffer and perform typical GDB packet framing, but not run-
253dda17b36SConrad Meyer * length encoding, before forwarding to driver ::gdb_sendpacket() routine.
254dda17b36SConrad Meyer */
255dda17b36SConrad Meyer static void
gdb_tx_sendpacket(void)256dda17b36SConrad Meyer gdb_tx_sendpacket(void)
257dda17b36SConrad Meyer {
258dda17b36SConrad Meyer size_t msglen, i;
259dda17b36SConrad Meyer unsigned char csum;
260dda17b36SConrad Meyer
261dda17b36SConrad Meyer msglen = gdb_txp - gdb_txbuf;
262dda17b36SConrad Meyer
263dda17b36SConrad Meyer /* Add GDB packet framing */
264dda17b36SConrad Meyer gdb_tx_fullbuf[0] = '$';
265dda17b36SConrad Meyer
266dda17b36SConrad Meyer csum = 0;
267dda17b36SConrad Meyer for (i = 0; i < msglen; i++)
268dda17b36SConrad Meyer csum += (unsigned char)gdb_txbuf[i];
269dda17b36SConrad Meyer snprintf(&gdb_tx_fullbuf[1 + msglen], 4, "#%02x", (unsigned)csum);
270dda17b36SConrad Meyer
271dda17b36SConrad Meyer gdb_cur->gdb_sendpacket(gdb_tx_fullbuf, msglen + 4);
272dda17b36SConrad Meyer }
273dda17b36SConrad Meyer
27472d44f31SMarcel Moolenaar int
gdb_tx_end(void)27572d44f31SMarcel Moolenaar gdb_tx_end(void)
27672d44f31SMarcel Moolenaar {
27772d44f31SMarcel Moolenaar const char *p;
27872d44f31SMarcel Moolenaar int runlen;
27972d44f31SMarcel Moolenaar unsigned char c, cksum;
28072d44f31SMarcel Moolenaar
28172d44f31SMarcel Moolenaar do {
282dda17b36SConrad Meyer if (gdb_cur->gdb_sendpacket != NULL) {
283dda17b36SConrad Meyer gdb_tx_sendpacket();
284dda17b36SConrad Meyer goto getack;
285dda17b36SConrad Meyer }
286dda17b36SConrad Meyer
28772d44f31SMarcel Moolenaar gdb_cur->gdb_putc('$');
28872d44f31SMarcel Moolenaar
28972d44f31SMarcel Moolenaar cksum = 0;
29072d44f31SMarcel Moolenaar p = gdb_txbuf;
29172d44f31SMarcel Moolenaar while (p < gdb_txp) {
29272d44f31SMarcel Moolenaar /* Send a character and start run-length encoding. */
29372d44f31SMarcel Moolenaar c = *p++;
29472d44f31SMarcel Moolenaar gdb_cur->gdb_putc(c);
29572d44f31SMarcel Moolenaar cksum += c;
29672d44f31SMarcel Moolenaar runlen = 0;
29772d44f31SMarcel Moolenaar /* Determine run-length and update checksum. */
29872d44f31SMarcel Moolenaar while (p < gdb_txp && *p == c) {
29972d44f31SMarcel Moolenaar runlen++;
30072d44f31SMarcel Moolenaar p++;
30172d44f31SMarcel Moolenaar }
30272d44f31SMarcel Moolenaar /* Emit the run-length encoded string. */
30372d44f31SMarcel Moolenaar while (runlen >= 97) {
30472d44f31SMarcel Moolenaar gdb_cur->gdb_putc('*');
30572d44f31SMarcel Moolenaar cksum += '*';
30672d44f31SMarcel Moolenaar gdb_cur->gdb_putc(97+29);
30772d44f31SMarcel Moolenaar cksum += 97+29;
30872d44f31SMarcel Moolenaar runlen -= 97;
30972d44f31SMarcel Moolenaar if (runlen > 0) {
31072d44f31SMarcel Moolenaar gdb_cur->gdb_putc(c);
31172d44f31SMarcel Moolenaar cksum += c;
31272d44f31SMarcel Moolenaar runlen--;
31372d44f31SMarcel Moolenaar }
31472d44f31SMarcel Moolenaar }
315028a372fSMichał Górny /* Don't emit '$', '#', '+', '-' or a run length below 3. */
316028a372fSMichał Górny while (runlen == 1 || runlen == 2 ||
317028a372fSMichał Górny runlen + 29 == '$' || runlen + 29 == '#' ||
318028a372fSMichał Górny runlen + 29 == '+' || runlen + 29 == '-') {
31972d44f31SMarcel Moolenaar gdb_cur->gdb_putc(c);
32072d44f31SMarcel Moolenaar cksum += c;
32172d44f31SMarcel Moolenaar runlen--;
32272d44f31SMarcel Moolenaar }
32372d44f31SMarcel Moolenaar if (runlen == 0)
32472d44f31SMarcel Moolenaar continue;
32572d44f31SMarcel Moolenaar gdb_cur->gdb_putc('*');
32672d44f31SMarcel Moolenaar cksum += '*';
32772d44f31SMarcel Moolenaar gdb_cur->gdb_putc(runlen+29);
32872d44f31SMarcel Moolenaar cksum += runlen+29;
32972d44f31SMarcel Moolenaar }
33072d44f31SMarcel Moolenaar
33172d44f31SMarcel Moolenaar gdb_cur->gdb_putc('#');
33272d44f31SMarcel Moolenaar c = cksum >> 4;
33372d44f31SMarcel Moolenaar gdb_cur->gdb_putc(N2C(c));
33472d44f31SMarcel Moolenaar c = cksum & 0x0f;
33572d44f31SMarcel Moolenaar gdb_cur->gdb_putc(N2C(c));
33672d44f31SMarcel Moolenaar
337dda17b36SConrad Meyer getack:
3386310546dSConrad Meyer /*
3396310546dSConrad Meyer * In NoAckMode, it is assumed that the underlying transport is
3406310546dSConrad Meyer * reliable and thus neither conservant sends acknowledgements;
3416310546dSConrad Meyer * there is nothing to wait for here.
3426310546dSConrad Meyer */
3436310546dSConrad Meyer if (!gdb_ackmode)
3446310546dSConrad Meyer break;
3456310546dSConrad Meyer
346f346afc4SPoul-Henning Kamp c = gdb_getc();
34772d44f31SMarcel Moolenaar } while (c != '+');
34872d44f31SMarcel Moolenaar
34972d44f31SMarcel Moolenaar return (0);
35072d44f31SMarcel Moolenaar }
35172d44f31SMarcel Moolenaar
35272d44f31SMarcel Moolenaar int
gdb_tx_mem(const unsigned char * addr,size_t size)35372d44f31SMarcel Moolenaar gdb_tx_mem(const unsigned char *addr, size_t size)
35472d44f31SMarcel Moolenaar {
35572d44f31SMarcel Moolenaar void *prev;
35672d44f31SMarcel Moolenaar jmp_buf jb;
35772d44f31SMarcel Moolenaar int ret;
35872d44f31SMarcel Moolenaar
35972d44f31SMarcel Moolenaar prev = kdb_jmpbuf(jb);
36072d44f31SMarcel Moolenaar ret = setjmp(jb);
36172d44f31SMarcel Moolenaar if (ret == 0) {
36272d44f31SMarcel Moolenaar while (size-- > 0) {
36372d44f31SMarcel Moolenaar *gdb_txp++ = N2C(*addr >> 4);
36472d44f31SMarcel Moolenaar *gdb_txp++ = N2C(*addr & 0x0f);
36572d44f31SMarcel Moolenaar addr++;
36672d44f31SMarcel Moolenaar }
36772d44f31SMarcel Moolenaar }
36872d44f31SMarcel Moolenaar (void)kdb_jmpbuf(prev);
36972d44f31SMarcel Moolenaar return ((ret == 0) ? 1 : 0);
37072d44f31SMarcel Moolenaar }
37172d44f31SMarcel Moolenaar
37272d44f31SMarcel Moolenaar void
gdb_tx_reg(int regnum)37372d44f31SMarcel Moolenaar gdb_tx_reg(int regnum)
37472d44f31SMarcel Moolenaar {
37572d44f31SMarcel Moolenaar unsigned char *regp;
37672d44f31SMarcel Moolenaar size_t regsz;
37772d44f31SMarcel Moolenaar
37872d44f31SMarcel Moolenaar regp = gdb_cpu_getreg(regnum, ®sz);
37972d44f31SMarcel Moolenaar if (regp == NULL) {
38072d44f31SMarcel Moolenaar /* Register unavailable. */
38172d44f31SMarcel Moolenaar while (regsz--) {
38272d44f31SMarcel Moolenaar gdb_tx_char('x');
38372d44f31SMarcel Moolenaar gdb_tx_char('x');
38472d44f31SMarcel Moolenaar }
38572d44f31SMarcel Moolenaar } else
38672d44f31SMarcel Moolenaar gdb_tx_mem(regp, regsz);
38772d44f31SMarcel Moolenaar }
38827ecc2adSBenno Rice
389130ef1adSConrad Meyer bool
gdb_txbuf_has_capacity(size_t req)390130ef1adSConrad Meyer gdb_txbuf_has_capacity(size_t req)
391130ef1adSConrad Meyer {
392130ef1adSConrad Meyer return (((char *)gdb_txbuf + sizeof(gdb_txbuf) - gdb_txp) >= req);
393130ef1adSConrad Meyer }
394130ef1adSConrad Meyer
39527ecc2adSBenno Rice /* Read binary data up until the end of the packet or until we have datalen decoded bytes */
39627ecc2adSBenno Rice int
gdb_rx_bindata(unsigned char * data,size_t datalen,size_t * amt)39727ecc2adSBenno Rice gdb_rx_bindata(unsigned char *data, size_t datalen, size_t *amt)
39827ecc2adSBenno Rice {
39927ecc2adSBenno Rice int c;
40027ecc2adSBenno Rice
40127ecc2adSBenno Rice *amt = 0;
40227ecc2adSBenno Rice
40327ecc2adSBenno Rice while (*amt < datalen) {
40427ecc2adSBenno Rice c = gdb_rx_char();
4055df6fa43SConrad Meyer if (c == EOF)
40627ecc2adSBenno Rice break;
40727ecc2adSBenno Rice /* Escaped character up next */
40827ecc2adSBenno Rice if (c == '}') {
4095df6fa43SConrad Meyer /* Malformed packet. */
4105df6fa43SConrad Meyer if ((c = gdb_rx_char()) == EOF)
41127ecc2adSBenno Rice return (1);
41227ecc2adSBenno Rice c ^= 0x20;
41327ecc2adSBenno Rice }
41427ecc2adSBenno Rice *(data++) = c & 0xff;
41527ecc2adSBenno Rice (*amt)++;
41627ecc2adSBenno Rice }
41727ecc2adSBenno Rice
41827ecc2adSBenno Rice return (0);
41927ecc2adSBenno Rice }
42027ecc2adSBenno Rice
42127ecc2adSBenno Rice int
gdb_search_mem(const unsigned char * addr,size_t size,const unsigned char * pat,size_t patlen,const unsigned char ** found)42227ecc2adSBenno Rice gdb_search_mem(const unsigned char *addr, size_t size, const unsigned char *pat, size_t patlen, const unsigned char **found)
42327ecc2adSBenno Rice {
42427ecc2adSBenno Rice void *prev;
42527ecc2adSBenno Rice jmp_buf jb;
42627ecc2adSBenno Rice int ret;
42727ecc2adSBenno Rice
42827ecc2adSBenno Rice prev = kdb_jmpbuf(jb);
42927ecc2adSBenno Rice ret = setjmp(jb);
43027ecc2adSBenno Rice if (ret == 0)
43127ecc2adSBenno Rice *found = memmem(addr, size, pat, patlen);
43227ecc2adSBenno Rice
43327ecc2adSBenno Rice (void)kdb_jmpbuf(prev);
43427ecc2adSBenno Rice return ((ret == 0) ? 1 : 0);
43527ecc2adSBenno Rice }
436