1fa521b03SWarner Losh /*- 2497b6b2aSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 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/cdefs.h> 3072d44f31SMarcel Moolenaar __FBSDID("$FreeBSD$"); 3172d44f31SMarcel Moolenaar 3272d44f31SMarcel Moolenaar #include <sys/param.h> 3372d44f31SMarcel Moolenaar #include <sys/systm.h> 3472d44f31SMarcel Moolenaar #include <sys/ctype.h> 3572d44f31SMarcel Moolenaar #include <sys/kdb.h> 3627ecc2adSBenno Rice #include <sys/libkern.h> 373a5d3671SMatthew D Fleming #include <sys/ttydefaults.h> 3872d44f31SMarcel Moolenaar 3972d44f31SMarcel Moolenaar #include <machine/gdb_machdep.h> 4001bd17ccSMarcel Moolenaar #include <machine/kdb.h> 4172d44f31SMarcel Moolenaar 4272d44f31SMarcel Moolenaar #include <gdb/gdb.h> 4372d44f31SMarcel Moolenaar #include <gdb/gdb_int.h> 4472d44f31SMarcel Moolenaar 4572d44f31SMarcel Moolenaar static char gdb_rxbuf[GDB_BUFSZ]; 4672d44f31SMarcel Moolenaar char *gdb_rxp = NULL; 4772d44f31SMarcel Moolenaar size_t gdb_rxsz = 0; 48dda17b36SConrad Meyer 49dda17b36SConrad Meyer /* 50dda17b36SConrad Meyer * The goal here is to allow in-place framing without making the math around 51dda17b36SConrad Meyer * 'gdb_txbuf' more complicated. A generous reading of union special rule for 52dda17b36SConrad Meyer * "common initial sequence" suggests this may be valid in standard C99 and 53dda17b36SConrad Meyer * later. 54dda17b36SConrad Meyer */ 55dda17b36SConrad Meyer static union { 56dda17b36SConrad Meyer struct _midbuf { 57dda17b36SConrad Meyer char mb_pad1; 58dda17b36SConrad Meyer char mb_buf[GDB_BUFSZ]; 59dda17b36SConrad Meyer char mb_pad2[4]; 60dda17b36SConrad Meyer } __packed txu_midbuf; 61dda17b36SConrad Meyer /* sizeof includes trailing nul byte and this is intentional. */ 62dda17b36SConrad Meyer char txu_fullbuf[GDB_BUFSZ + sizeof("$#..")]; 63dda17b36SConrad Meyer } gdb_tx_u; 64dda17b36SConrad Meyer #define gdb_txbuf gdb_tx_u.txu_midbuf.mb_buf 65dda17b36SConrad Meyer #define gdb_tx_fullbuf gdb_tx_u.txu_fullbuf 66dda17b36SConrad Meyer _Static_assert(sizeof(gdb_tx_u.txu_midbuf) == sizeof(gdb_tx_u.txu_fullbuf) && 67dda17b36SConrad Meyer offsetof(struct _midbuf, mb_buf) == 1, 68dda17b36SConrad Meyer "assertions necessary for correctness"); 6972d44f31SMarcel Moolenaar char *gdb_txp = NULL; /* Used in inline functions. */ 7072d44f31SMarcel Moolenaar 7172d44f31SMarcel Moolenaar #define C2N(c) (((c) < 'A') ? (c) - '0' : \ 7272d44f31SMarcel Moolenaar 10 + (((c) < 'a') ? (c) - 'A' : (c) - 'a')) 7372d44f31SMarcel Moolenaar #define N2C(n) (((n) < 10) ? (n) + '0' : (n) + 'a' - 10) 7472d44f31SMarcel Moolenaar 7572d44f31SMarcel Moolenaar /* 76f346afc4SPoul-Henning Kamp * Get a single character 77f346afc4SPoul-Henning Kamp */ 78f346afc4SPoul-Henning Kamp 79f346afc4SPoul-Henning Kamp static int 80f346afc4SPoul-Henning Kamp gdb_getc(void) 81f346afc4SPoul-Henning Kamp { 82f346afc4SPoul-Henning Kamp int c; 83f346afc4SPoul-Henning Kamp 84f346afc4SPoul-Henning Kamp do 85f346afc4SPoul-Henning Kamp c = gdb_cur->gdb_getc(); 86f346afc4SPoul-Henning Kamp while (c == -1); 873a5d3671SMatthew D Fleming 883a5d3671SMatthew D Fleming if (c == CTRL('C')) { 893a5d3671SMatthew D Fleming printf("Received ^C; trying to switch back to ddb.\n"); 903a5d3671SMatthew D Fleming 91dda17b36SConrad Meyer if (gdb_cur->gdb_dbfeatures & GDB_DBGP_FEAT_WANTTERM) 92dda17b36SConrad Meyer gdb_cur->gdb_term(); 93dda17b36SConrad Meyer 943a5d3671SMatthew D Fleming if (kdb_dbbe_select("ddb") != 0) 953a5d3671SMatthew D Fleming printf("The ddb backend could not be selected.\n"); 963a5d3671SMatthew D Fleming else { 973a5d3671SMatthew D Fleming printf("using longjmp, hope it works!\n"); 983a5d3671SMatthew D Fleming kdb_reenter(); 993a5d3671SMatthew D Fleming } 1003a5d3671SMatthew D Fleming } 101f346afc4SPoul-Henning Kamp return (c); 102f346afc4SPoul-Henning Kamp } 103f346afc4SPoul-Henning Kamp 104f346afc4SPoul-Henning Kamp /* 10572d44f31SMarcel Moolenaar * Functions to receive and extract from a packet. 10672d44f31SMarcel Moolenaar */ 10772d44f31SMarcel Moolenaar 10872d44f31SMarcel Moolenaar int 10972d44f31SMarcel Moolenaar gdb_rx_begin(void) 11072d44f31SMarcel Moolenaar { 11172d44f31SMarcel Moolenaar int c, cksum; 11272d44f31SMarcel Moolenaar 11372d44f31SMarcel Moolenaar gdb_rxp = NULL; 11472d44f31SMarcel Moolenaar do { 11572d44f31SMarcel Moolenaar /* 11672d44f31SMarcel Moolenaar * Wait for the start character, ignore all others. 11772d44f31SMarcel Moolenaar * XXX needs a timeout. 11872d44f31SMarcel Moolenaar */ 119f346afc4SPoul-Henning Kamp while ((c = gdb_getc()) != '$') 12072d44f31SMarcel Moolenaar ; 12172d44f31SMarcel Moolenaar 12272d44f31SMarcel Moolenaar /* Read until a # or end of buffer is found. */ 12372d44f31SMarcel Moolenaar cksum = 0; 12472d44f31SMarcel Moolenaar gdb_rxsz = 0; 12572d44f31SMarcel Moolenaar while (gdb_rxsz < sizeof(gdb_rxbuf) - 1) { 126f346afc4SPoul-Henning Kamp c = gdb_getc(); 12772d44f31SMarcel Moolenaar if (c == '#') 12872d44f31SMarcel Moolenaar break; 12972d44f31SMarcel Moolenaar gdb_rxbuf[gdb_rxsz++] = c; 13072d44f31SMarcel Moolenaar cksum += c; 13172d44f31SMarcel Moolenaar } 13272d44f31SMarcel Moolenaar gdb_rxbuf[gdb_rxsz] = 0; 13372d44f31SMarcel Moolenaar cksum &= 0xff; 13472d44f31SMarcel Moolenaar 13572d44f31SMarcel Moolenaar /* Bail out on a buffer overflow. */ 13672d44f31SMarcel Moolenaar if (c != '#') { 1376310546dSConrad Meyer gdb_nack(); 13872d44f31SMarcel Moolenaar return (ENOSPC); 13972d44f31SMarcel Moolenaar } 14072d44f31SMarcel Moolenaar 1416310546dSConrad Meyer /* 1426310546dSConrad Meyer * In Not-AckMode, we can assume reliable transport and neither 1436310546dSConrad Meyer * need to verify checksums nor send Ack/Nack. 1446310546dSConrad Meyer */ 1456310546dSConrad Meyer if (!gdb_ackmode) 1466310546dSConrad Meyer break; 1476310546dSConrad Meyer 148f346afc4SPoul-Henning Kamp c = gdb_getc(); 14972d44f31SMarcel Moolenaar cksum -= (C2N(c) << 4) & 0xf0; 150f346afc4SPoul-Henning Kamp c = gdb_getc(); 15172d44f31SMarcel Moolenaar cksum -= C2N(c) & 0x0f; 1526310546dSConrad Meyer if (cksum == 0) { 1536310546dSConrad Meyer gdb_ack(); 1546310546dSConrad Meyer } else { 1556310546dSConrad Meyer gdb_nack(); 15672d44f31SMarcel Moolenaar printf("GDB: packet `%s' has invalid checksum\n", 15772d44f31SMarcel Moolenaar gdb_rxbuf); 1586310546dSConrad Meyer } 15972d44f31SMarcel Moolenaar } while (cksum != 0); 16072d44f31SMarcel Moolenaar 16172d44f31SMarcel Moolenaar gdb_rxp = gdb_rxbuf; 16272d44f31SMarcel Moolenaar return (0); 16372d44f31SMarcel Moolenaar } 16472d44f31SMarcel Moolenaar 16572d44f31SMarcel Moolenaar int 16672d44f31SMarcel Moolenaar gdb_rx_equal(const char *str) 16772d44f31SMarcel Moolenaar { 16872d44f31SMarcel Moolenaar int len; 16972d44f31SMarcel Moolenaar 17072d44f31SMarcel Moolenaar len = strlen(str); 17172d44f31SMarcel Moolenaar if (len > gdb_rxsz || strncmp(str, gdb_rxp, len) != 0) 17272d44f31SMarcel Moolenaar return (0); 17372d44f31SMarcel Moolenaar gdb_rxp += len; 17472d44f31SMarcel Moolenaar gdb_rxsz -= len; 17572d44f31SMarcel Moolenaar return (1); 17672d44f31SMarcel Moolenaar } 17772d44f31SMarcel Moolenaar 17872d44f31SMarcel Moolenaar int 17972d44f31SMarcel Moolenaar gdb_rx_mem(unsigned char *addr, size_t size) 18072d44f31SMarcel Moolenaar { 18101bd17ccSMarcel Moolenaar unsigned char *p; 18272d44f31SMarcel Moolenaar void *prev; 183beb24065SJonathan T. Looney void *wctx; 18472d44f31SMarcel Moolenaar jmp_buf jb; 18501bd17ccSMarcel Moolenaar size_t cnt; 18672d44f31SMarcel Moolenaar int ret; 18772d44f31SMarcel Moolenaar unsigned char c; 18872d44f31SMarcel Moolenaar 18972d44f31SMarcel Moolenaar if (size * 2 != gdb_rxsz) 19072d44f31SMarcel Moolenaar return (-1); 19172d44f31SMarcel Moolenaar 192beb24065SJonathan T. Looney wctx = gdb_begin_write(); 19372d44f31SMarcel Moolenaar prev = kdb_jmpbuf(jb); 19472d44f31SMarcel Moolenaar ret = setjmp(jb); 19572d44f31SMarcel Moolenaar if (ret == 0) { 19601bd17ccSMarcel Moolenaar p = addr; 19701bd17ccSMarcel Moolenaar cnt = size; 19801bd17ccSMarcel Moolenaar while (cnt-- > 0) { 19972d44f31SMarcel Moolenaar c = (C2N(gdb_rxp[0]) << 4) & 0xf0; 20072d44f31SMarcel Moolenaar c |= C2N(gdb_rxp[1]) & 0x0f; 20101bd17ccSMarcel Moolenaar *p++ = c; 20272d44f31SMarcel Moolenaar gdb_rxsz -= 2; 20372d44f31SMarcel Moolenaar gdb_rxp += 2; 20472d44f31SMarcel Moolenaar } 20501bd17ccSMarcel Moolenaar kdb_cpu_sync_icache(addr, size); 20672d44f31SMarcel Moolenaar } 20772d44f31SMarcel Moolenaar (void)kdb_jmpbuf(prev); 208beb24065SJonathan T. Looney gdb_end_write(wctx); 20972d44f31SMarcel Moolenaar return ((ret == 0) ? 1 : 0); 21072d44f31SMarcel Moolenaar } 21172d44f31SMarcel Moolenaar 21272d44f31SMarcel Moolenaar int 21372d44f31SMarcel Moolenaar gdb_rx_varhex(uintmax_t *vp) 21472d44f31SMarcel Moolenaar { 21572d44f31SMarcel Moolenaar uintmax_t v; 21672d44f31SMarcel Moolenaar int c, neg; 21772d44f31SMarcel Moolenaar 21872d44f31SMarcel Moolenaar c = gdb_rx_char(); 21972d44f31SMarcel Moolenaar neg = (c == '-') ? 1 : 0; 22072d44f31SMarcel Moolenaar if (neg == 1) 22172d44f31SMarcel Moolenaar c = gdb_rx_char(); 22272d44f31SMarcel Moolenaar if (!isxdigit(c)) { 22372d44f31SMarcel Moolenaar gdb_rxp -= ((c == -1) ? 0 : 1) + neg; 22472d44f31SMarcel Moolenaar gdb_rxsz += ((c == -1) ? 0 : 1) + neg; 22572d44f31SMarcel Moolenaar return (-1); 22672d44f31SMarcel Moolenaar } 22772d44f31SMarcel Moolenaar v = 0; 22872d44f31SMarcel Moolenaar do { 22972d44f31SMarcel Moolenaar v <<= 4; 23072d44f31SMarcel Moolenaar v += C2N(c); 23172d44f31SMarcel Moolenaar c = gdb_rx_char(); 23272d44f31SMarcel Moolenaar } while (isxdigit(c)); 2335df6fa43SConrad Meyer if (c != EOF) { 23472d44f31SMarcel Moolenaar gdb_rxp--; 23572d44f31SMarcel Moolenaar gdb_rxsz++; 23672d44f31SMarcel Moolenaar } 23772d44f31SMarcel Moolenaar *vp = (neg) ? -v : v; 23872d44f31SMarcel Moolenaar return (0); 23972d44f31SMarcel Moolenaar } 24072d44f31SMarcel Moolenaar 24172d44f31SMarcel Moolenaar /* 24272d44f31SMarcel Moolenaar * Function to build and send a package. 24372d44f31SMarcel Moolenaar */ 24472d44f31SMarcel Moolenaar 24572d44f31SMarcel Moolenaar void 24672d44f31SMarcel Moolenaar gdb_tx_begin(char tp) 24772d44f31SMarcel Moolenaar { 24872d44f31SMarcel Moolenaar 24972d44f31SMarcel Moolenaar gdb_txp = gdb_txbuf; 25072d44f31SMarcel Moolenaar if (tp != '\0') 25172d44f31SMarcel Moolenaar gdb_tx_char(tp); 25272d44f31SMarcel Moolenaar } 25372d44f31SMarcel Moolenaar 254dda17b36SConrad Meyer /* 255dda17b36SConrad Meyer * Take raw packet buffer and perform typical GDB packet framing, but not run- 256dda17b36SConrad Meyer * length encoding, before forwarding to driver ::gdb_sendpacket() routine. 257dda17b36SConrad Meyer */ 258dda17b36SConrad Meyer static void 259dda17b36SConrad Meyer gdb_tx_sendpacket(void) 260dda17b36SConrad Meyer { 261dda17b36SConrad Meyer size_t msglen, i; 262dda17b36SConrad Meyer unsigned char csum; 263dda17b36SConrad Meyer 264dda17b36SConrad Meyer msglen = gdb_txp - gdb_txbuf; 265dda17b36SConrad Meyer 266dda17b36SConrad Meyer /* Add GDB packet framing */ 267dda17b36SConrad Meyer gdb_tx_fullbuf[0] = '$'; 268dda17b36SConrad Meyer 269dda17b36SConrad Meyer csum = 0; 270dda17b36SConrad Meyer for (i = 0; i < msglen; i++) 271dda17b36SConrad Meyer csum += (unsigned char)gdb_txbuf[i]; 272dda17b36SConrad Meyer snprintf(&gdb_tx_fullbuf[1 + msglen], 4, "#%02x", (unsigned)csum); 273dda17b36SConrad Meyer 274dda17b36SConrad Meyer gdb_cur->gdb_sendpacket(gdb_tx_fullbuf, msglen + 4); 275dda17b36SConrad Meyer } 276dda17b36SConrad Meyer 27772d44f31SMarcel Moolenaar int 27872d44f31SMarcel Moolenaar gdb_tx_end(void) 27972d44f31SMarcel Moolenaar { 28072d44f31SMarcel Moolenaar const char *p; 28172d44f31SMarcel Moolenaar int runlen; 28272d44f31SMarcel Moolenaar unsigned char c, cksum; 28372d44f31SMarcel Moolenaar 28472d44f31SMarcel Moolenaar do { 285dda17b36SConrad Meyer if (gdb_cur->gdb_sendpacket != NULL) { 286dda17b36SConrad Meyer gdb_tx_sendpacket(); 287dda17b36SConrad Meyer goto getack; 288dda17b36SConrad Meyer } 289dda17b36SConrad Meyer 29072d44f31SMarcel Moolenaar gdb_cur->gdb_putc('$'); 29172d44f31SMarcel Moolenaar 29272d44f31SMarcel Moolenaar cksum = 0; 29372d44f31SMarcel Moolenaar p = gdb_txbuf; 29472d44f31SMarcel Moolenaar while (p < gdb_txp) { 29572d44f31SMarcel Moolenaar /* Send a character and start run-length encoding. */ 29672d44f31SMarcel Moolenaar c = *p++; 29772d44f31SMarcel Moolenaar gdb_cur->gdb_putc(c); 29872d44f31SMarcel Moolenaar cksum += c; 29972d44f31SMarcel Moolenaar runlen = 0; 30072d44f31SMarcel Moolenaar /* Determine run-length and update checksum. */ 30172d44f31SMarcel Moolenaar while (p < gdb_txp && *p == c) { 30272d44f31SMarcel Moolenaar runlen++; 30372d44f31SMarcel Moolenaar p++; 30472d44f31SMarcel Moolenaar } 30572d44f31SMarcel Moolenaar /* Emit the run-length encoded string. */ 30672d44f31SMarcel Moolenaar while (runlen >= 97) { 30772d44f31SMarcel Moolenaar gdb_cur->gdb_putc('*'); 30872d44f31SMarcel Moolenaar cksum += '*'; 30972d44f31SMarcel Moolenaar gdb_cur->gdb_putc(97+29); 31072d44f31SMarcel Moolenaar cksum += 97+29; 31172d44f31SMarcel Moolenaar runlen -= 97; 31272d44f31SMarcel Moolenaar if (runlen > 0) { 31372d44f31SMarcel Moolenaar gdb_cur->gdb_putc(c); 31472d44f31SMarcel Moolenaar cksum += c; 31572d44f31SMarcel Moolenaar runlen--; 31672d44f31SMarcel Moolenaar } 31772d44f31SMarcel Moolenaar } 318*028a372fSMichał Górny /* Don't emit '$', '#', '+', '-' or a run length below 3. */ 319*028a372fSMichał Górny while (runlen == 1 || runlen == 2 || 320*028a372fSMichał Górny runlen + 29 == '$' || runlen + 29 == '#' || 321*028a372fSMichał Górny runlen + 29 == '+' || runlen + 29 == '-') { 32272d44f31SMarcel Moolenaar gdb_cur->gdb_putc(c); 32372d44f31SMarcel Moolenaar cksum += c; 32472d44f31SMarcel Moolenaar runlen--; 32572d44f31SMarcel Moolenaar } 32672d44f31SMarcel Moolenaar if (runlen == 0) 32772d44f31SMarcel Moolenaar continue; 32872d44f31SMarcel Moolenaar gdb_cur->gdb_putc('*'); 32972d44f31SMarcel Moolenaar cksum += '*'; 33072d44f31SMarcel Moolenaar gdb_cur->gdb_putc(runlen+29); 33172d44f31SMarcel Moolenaar cksum += runlen+29; 33272d44f31SMarcel Moolenaar } 33372d44f31SMarcel Moolenaar 33472d44f31SMarcel Moolenaar gdb_cur->gdb_putc('#'); 33572d44f31SMarcel Moolenaar c = cksum >> 4; 33672d44f31SMarcel Moolenaar gdb_cur->gdb_putc(N2C(c)); 33772d44f31SMarcel Moolenaar c = cksum & 0x0f; 33872d44f31SMarcel Moolenaar gdb_cur->gdb_putc(N2C(c)); 33972d44f31SMarcel Moolenaar 340dda17b36SConrad Meyer getack: 3416310546dSConrad Meyer /* 3426310546dSConrad Meyer * In NoAckMode, it is assumed that the underlying transport is 3436310546dSConrad Meyer * reliable and thus neither conservant sends acknowledgements; 3446310546dSConrad Meyer * there is nothing to wait for here. 3456310546dSConrad Meyer */ 3466310546dSConrad Meyer if (!gdb_ackmode) 3476310546dSConrad Meyer break; 3486310546dSConrad Meyer 349f346afc4SPoul-Henning Kamp c = gdb_getc(); 35072d44f31SMarcel Moolenaar } while (c != '+'); 35172d44f31SMarcel Moolenaar 35272d44f31SMarcel Moolenaar return (0); 35372d44f31SMarcel Moolenaar } 35472d44f31SMarcel Moolenaar 35572d44f31SMarcel Moolenaar int 35672d44f31SMarcel Moolenaar gdb_tx_mem(const unsigned char *addr, size_t size) 35772d44f31SMarcel Moolenaar { 35872d44f31SMarcel Moolenaar void *prev; 35972d44f31SMarcel Moolenaar jmp_buf jb; 36072d44f31SMarcel Moolenaar int ret; 36172d44f31SMarcel Moolenaar 36272d44f31SMarcel Moolenaar prev = kdb_jmpbuf(jb); 36372d44f31SMarcel Moolenaar ret = setjmp(jb); 36472d44f31SMarcel Moolenaar if (ret == 0) { 36572d44f31SMarcel Moolenaar while (size-- > 0) { 36672d44f31SMarcel Moolenaar *gdb_txp++ = N2C(*addr >> 4); 36772d44f31SMarcel Moolenaar *gdb_txp++ = N2C(*addr & 0x0f); 36872d44f31SMarcel Moolenaar addr++; 36972d44f31SMarcel Moolenaar } 37072d44f31SMarcel Moolenaar } 37172d44f31SMarcel Moolenaar (void)kdb_jmpbuf(prev); 37272d44f31SMarcel Moolenaar return ((ret == 0) ? 1 : 0); 37372d44f31SMarcel Moolenaar } 37472d44f31SMarcel Moolenaar 37572d44f31SMarcel Moolenaar void 37672d44f31SMarcel Moolenaar gdb_tx_reg(int regnum) 37772d44f31SMarcel Moolenaar { 37872d44f31SMarcel Moolenaar unsigned char *regp; 37972d44f31SMarcel Moolenaar size_t regsz; 38072d44f31SMarcel Moolenaar 38172d44f31SMarcel Moolenaar regp = gdb_cpu_getreg(regnum, ®sz); 38272d44f31SMarcel Moolenaar if (regp == NULL) { 38372d44f31SMarcel Moolenaar /* Register unavailable. */ 38472d44f31SMarcel Moolenaar while (regsz--) { 38572d44f31SMarcel Moolenaar gdb_tx_char('x'); 38672d44f31SMarcel Moolenaar gdb_tx_char('x'); 38772d44f31SMarcel Moolenaar } 38872d44f31SMarcel Moolenaar } else 38972d44f31SMarcel Moolenaar gdb_tx_mem(regp, regsz); 39072d44f31SMarcel Moolenaar } 39127ecc2adSBenno Rice 392130ef1adSConrad Meyer bool 393130ef1adSConrad Meyer gdb_txbuf_has_capacity(size_t req) 394130ef1adSConrad Meyer { 395130ef1adSConrad Meyer return (((char *)gdb_txbuf + sizeof(gdb_txbuf) - gdb_txp) >= req); 396130ef1adSConrad Meyer } 397130ef1adSConrad Meyer 39827ecc2adSBenno Rice /* Read binary data up until the end of the packet or until we have datalen decoded bytes */ 39927ecc2adSBenno Rice int 40027ecc2adSBenno Rice gdb_rx_bindata(unsigned char *data, size_t datalen, size_t *amt) 40127ecc2adSBenno Rice { 40227ecc2adSBenno Rice int c; 40327ecc2adSBenno Rice 40427ecc2adSBenno Rice *amt = 0; 40527ecc2adSBenno Rice 40627ecc2adSBenno Rice while (*amt < datalen) { 40727ecc2adSBenno Rice c = gdb_rx_char(); 4085df6fa43SConrad Meyer if (c == EOF) 40927ecc2adSBenno Rice break; 41027ecc2adSBenno Rice /* Escaped character up next */ 41127ecc2adSBenno Rice if (c == '}') { 4125df6fa43SConrad Meyer /* Malformed packet. */ 4135df6fa43SConrad Meyer if ((c = gdb_rx_char()) == EOF) 41427ecc2adSBenno Rice return (1); 41527ecc2adSBenno Rice c ^= 0x20; 41627ecc2adSBenno Rice } 41727ecc2adSBenno Rice *(data++) = c & 0xff; 41827ecc2adSBenno Rice (*amt)++; 41927ecc2adSBenno Rice } 42027ecc2adSBenno Rice 42127ecc2adSBenno Rice return (0); 42227ecc2adSBenno Rice } 42327ecc2adSBenno Rice 42427ecc2adSBenno Rice int 42527ecc2adSBenno Rice gdb_search_mem(const unsigned char *addr, size_t size, const unsigned char *pat, size_t patlen, const unsigned char **found) 42627ecc2adSBenno Rice { 42727ecc2adSBenno Rice void *prev; 42827ecc2adSBenno Rice jmp_buf jb; 42927ecc2adSBenno Rice int ret; 43027ecc2adSBenno Rice 43127ecc2adSBenno Rice prev = kdb_jmpbuf(jb); 43227ecc2adSBenno Rice ret = setjmp(jb); 43327ecc2adSBenno Rice if (ret == 0) 43427ecc2adSBenno Rice *found = memmem(addr, size, pat, patlen); 43527ecc2adSBenno Rice 43627ecc2adSBenno Rice (void)kdb_jmpbuf(prev); 43727ecc2adSBenno Rice return ((ret == 0) ? 1 : 0); 43827ecc2adSBenno Rice } 439