1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2004 Marcel Moolenaar 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 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. 16 * 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. 27 */ 28 29 #include <sys/param.h> 30 #include <sys/systm.h> 31 #include <sys/ctype.h> 32 #include <sys/kdb.h> 33 #include <sys/libkern.h> 34 #include <sys/ttydefaults.h> 35 36 #include <machine/gdb_machdep.h> 37 #include <machine/kdb.h> 38 39 #include <gdb/gdb.h> 40 #include <gdb/gdb_int.h> 41 42 static char gdb_rxbuf[GDB_BUFSZ]; 43 char *gdb_rxp = NULL; 44 size_t gdb_rxsz = 0; 45 46 /* 47 * The goal here is to allow in-place framing without making the math around 48 * 'gdb_txbuf' more complicated. A generous reading of union special rule for 49 * "common initial sequence" suggests this may be valid in standard C99 and 50 * later. 51 */ 52 static union { 53 struct _midbuf { 54 char mb_pad1; 55 char mb_buf[GDB_BUFSZ]; 56 char mb_pad2[4]; 57 } __packed txu_midbuf; 58 /* sizeof includes trailing nul byte and this is intentional. */ 59 char txu_fullbuf[GDB_BUFSZ + sizeof("$#..")]; 60 } gdb_tx_u; 61 #define gdb_txbuf gdb_tx_u.txu_midbuf.mb_buf 62 #define gdb_tx_fullbuf gdb_tx_u.txu_fullbuf 63 _Static_assert(sizeof(gdb_tx_u.txu_midbuf) == sizeof(gdb_tx_u.txu_fullbuf) && 64 offsetof(struct _midbuf, mb_buf) == 1, 65 "assertions necessary for correctness"); 66 char *gdb_txp = NULL; /* Used in inline functions. */ 67 68 #define C2N(c) (((c) < 'A') ? (c) - '0' : \ 69 10 + (((c) < 'a') ? (c) - 'A' : (c) - 'a')) 70 #define N2C(n) (((n) < 10) ? (n) + '0' : (n) + 'a' - 10) 71 72 /* 73 * Get a single character 74 */ 75 76 static int 77 gdb_getc(void) 78 { 79 int c; 80 81 do 82 c = gdb_cur->gdb_getc(); 83 while (c == -1); 84 85 if (c == CTRL('C')) { 86 printf("Received ^C; trying to switch back to ddb.\n"); 87 88 if (gdb_cur->gdb_dbfeatures & GDB_DBGP_FEAT_WANTTERM) 89 gdb_cur->gdb_term(); 90 91 if (kdb_dbbe_select("ddb") != 0) 92 printf("The ddb backend could not be selected.\n"); 93 else { 94 printf("using longjmp, hope it works!\n"); 95 kdb_reenter(); 96 } 97 } 98 return (c); 99 } 100 101 /* 102 * Functions to receive and extract from a packet. 103 */ 104 105 int 106 gdb_rx_begin(void) 107 { 108 int c, cksum; 109 110 gdb_rxp = NULL; 111 do { 112 /* 113 * Wait for the start character, ignore all others. 114 * XXX needs a timeout. 115 */ 116 while ((c = gdb_getc()) != '$') 117 ; 118 119 /* Read until a # or end of buffer is found. */ 120 cksum = 0; 121 gdb_rxsz = 0; 122 while (gdb_rxsz < sizeof(gdb_rxbuf) - 1) { 123 c = gdb_getc(); 124 if (c == '#') 125 break; 126 gdb_rxbuf[gdb_rxsz++] = c; 127 cksum += c; 128 } 129 gdb_rxbuf[gdb_rxsz] = 0; 130 cksum &= 0xff; 131 132 /* Bail out on a buffer overflow. */ 133 if (c != '#') { 134 gdb_nack(); 135 return (ENOSPC); 136 } 137 138 /* 139 * In Not-AckMode, we can assume reliable transport and neither 140 * need to verify checksums nor send Ack/Nack. 141 */ 142 if (!gdb_ackmode) 143 break; 144 145 c = gdb_getc(); 146 cksum -= (C2N(c) << 4) & 0xf0; 147 c = gdb_getc(); 148 cksum -= C2N(c) & 0x0f; 149 if (cksum == 0) { 150 gdb_ack(); 151 } else { 152 gdb_nack(); 153 printf("GDB: packet `%s' has invalid checksum\n", 154 gdb_rxbuf); 155 } 156 } while (cksum != 0); 157 158 gdb_rxp = gdb_rxbuf; 159 return (0); 160 } 161 162 int 163 gdb_rx_equal(const char *str) 164 { 165 int len; 166 167 len = strlen(str); 168 if (len > gdb_rxsz || strncmp(str, gdb_rxp, len) != 0) 169 return (0); 170 gdb_rxp += len; 171 gdb_rxsz -= len; 172 return (1); 173 } 174 175 int 176 gdb_rx_mem(unsigned char *addr, size_t size) 177 { 178 unsigned char *p; 179 void *prev; 180 void *wctx; 181 jmp_buf jb; 182 size_t cnt; 183 int ret; 184 unsigned char c; 185 186 if (size * 2 != gdb_rxsz) 187 return (-1); 188 189 wctx = gdb_begin_write(); 190 prev = kdb_jmpbuf(jb); 191 ret = setjmp(jb); 192 if (ret == 0) { 193 p = addr; 194 cnt = size; 195 while (cnt-- > 0) { 196 c = (C2N(gdb_rxp[0]) << 4) & 0xf0; 197 c |= C2N(gdb_rxp[1]) & 0x0f; 198 *p++ = c; 199 gdb_rxsz -= 2; 200 gdb_rxp += 2; 201 } 202 kdb_cpu_sync_icache(addr, size); 203 } 204 (void)kdb_jmpbuf(prev); 205 gdb_end_write(wctx); 206 return ((ret == 0) ? 1 : 0); 207 } 208 209 int 210 gdb_rx_varhex(uintmax_t *vp) 211 { 212 uintmax_t v; 213 int c, neg; 214 215 c = gdb_rx_char(); 216 neg = (c == '-') ? 1 : 0; 217 if (neg == 1) 218 c = gdb_rx_char(); 219 if (!isxdigit(c)) { 220 gdb_rxp -= ((c == -1) ? 0 : 1) + neg; 221 gdb_rxsz += ((c == -1) ? 0 : 1) + neg; 222 return (-1); 223 } 224 v = 0; 225 do { 226 v <<= 4; 227 v += C2N(c); 228 c = gdb_rx_char(); 229 } while (isxdigit(c)); 230 if (c != EOF) { 231 gdb_rxp--; 232 gdb_rxsz++; 233 } 234 *vp = (neg) ? -v : v; 235 return (0); 236 } 237 238 /* 239 * Function to build and send a package. 240 */ 241 242 void 243 gdb_tx_begin(char tp) 244 { 245 246 gdb_txp = gdb_txbuf; 247 if (tp != '\0') 248 gdb_tx_char(tp); 249 } 250 251 /* 252 * Take raw packet buffer and perform typical GDB packet framing, but not run- 253 * length encoding, before forwarding to driver ::gdb_sendpacket() routine. 254 */ 255 static void 256 gdb_tx_sendpacket(void) 257 { 258 size_t msglen, i; 259 unsigned char csum; 260 261 msglen = gdb_txp - gdb_txbuf; 262 263 /* Add GDB packet framing */ 264 gdb_tx_fullbuf[0] = '$'; 265 266 csum = 0; 267 for (i = 0; i < msglen; i++) 268 csum += (unsigned char)gdb_txbuf[i]; 269 snprintf(&gdb_tx_fullbuf[1 + msglen], 4, "#%02x", (unsigned)csum); 270 271 gdb_cur->gdb_sendpacket(gdb_tx_fullbuf, msglen + 4); 272 } 273 274 int 275 gdb_tx_end(void) 276 { 277 const char *p; 278 int runlen; 279 unsigned char c, cksum; 280 281 do { 282 if (gdb_cur->gdb_sendpacket != NULL) { 283 gdb_tx_sendpacket(); 284 goto getack; 285 } 286 287 gdb_cur->gdb_putc('$'); 288 289 cksum = 0; 290 p = gdb_txbuf; 291 while (p < gdb_txp) { 292 /* Send a character and start run-length encoding. */ 293 c = *p++; 294 gdb_cur->gdb_putc(c); 295 cksum += c; 296 runlen = 0; 297 /* Determine run-length and update checksum. */ 298 while (p < gdb_txp && *p == c) { 299 runlen++; 300 p++; 301 } 302 /* Emit the run-length encoded string. */ 303 while (runlen >= 97) { 304 gdb_cur->gdb_putc('*'); 305 cksum += '*'; 306 gdb_cur->gdb_putc(97+29); 307 cksum += 97+29; 308 runlen -= 97; 309 if (runlen > 0) { 310 gdb_cur->gdb_putc(c); 311 cksum += c; 312 runlen--; 313 } 314 } 315 /* Don't emit '$', '#', '+', '-' or a run length below 3. */ 316 while (runlen == 1 || runlen == 2 || 317 runlen + 29 == '$' || runlen + 29 == '#' || 318 runlen + 29 == '+' || runlen + 29 == '-') { 319 gdb_cur->gdb_putc(c); 320 cksum += c; 321 runlen--; 322 } 323 if (runlen == 0) 324 continue; 325 gdb_cur->gdb_putc('*'); 326 cksum += '*'; 327 gdb_cur->gdb_putc(runlen+29); 328 cksum += runlen+29; 329 } 330 331 gdb_cur->gdb_putc('#'); 332 c = cksum >> 4; 333 gdb_cur->gdb_putc(N2C(c)); 334 c = cksum & 0x0f; 335 gdb_cur->gdb_putc(N2C(c)); 336 337 getack: 338 /* 339 * In NoAckMode, it is assumed that the underlying transport is 340 * reliable and thus neither conservant sends acknowledgements; 341 * there is nothing to wait for here. 342 */ 343 if (!gdb_ackmode) 344 break; 345 346 c = gdb_getc(); 347 } while (c != '+'); 348 349 return (0); 350 } 351 352 int 353 gdb_tx_mem(const unsigned char *addr, size_t size) 354 { 355 void *prev; 356 jmp_buf jb; 357 int ret; 358 359 prev = kdb_jmpbuf(jb); 360 ret = setjmp(jb); 361 if (ret == 0) { 362 while (size-- > 0) { 363 *gdb_txp++ = N2C(*addr >> 4); 364 *gdb_txp++ = N2C(*addr & 0x0f); 365 addr++; 366 } 367 } 368 (void)kdb_jmpbuf(prev); 369 return ((ret == 0) ? 1 : 0); 370 } 371 372 void 373 gdb_tx_reg(int regnum) 374 { 375 unsigned char *regp; 376 size_t regsz; 377 378 regp = gdb_cpu_getreg(regnum, ®sz); 379 if (regp == NULL) { 380 /* Register unavailable. */ 381 while (regsz--) { 382 gdb_tx_char('x'); 383 gdb_tx_char('x'); 384 } 385 } else 386 gdb_tx_mem(regp, regsz); 387 } 388 389 bool 390 gdb_txbuf_has_capacity(size_t req) 391 { 392 return (((char *)gdb_txbuf + sizeof(gdb_txbuf) - gdb_txp) >= req); 393 } 394 395 /* Read binary data up until the end of the packet or until we have datalen decoded bytes */ 396 int 397 gdb_rx_bindata(unsigned char *data, size_t datalen, size_t *amt) 398 { 399 int c; 400 401 *amt = 0; 402 403 while (*amt < datalen) { 404 c = gdb_rx_char(); 405 if (c == EOF) 406 break; 407 /* Escaped character up next */ 408 if (c == '}') { 409 /* Malformed packet. */ 410 if ((c = gdb_rx_char()) == EOF) 411 return (1); 412 c ^= 0x20; 413 } 414 *(data++) = c & 0xff; 415 (*amt)++; 416 } 417 418 return (0); 419 } 420 421 int 422 gdb_search_mem(const unsigned char *addr, size_t size, const unsigned char *pat, size_t patlen, const unsigned char **found) 423 { 424 void *prev; 425 jmp_buf jb; 426 int ret; 427 428 prev = kdb_jmpbuf(jb); 429 ret = setjmp(jb); 430 if (ret == 0) 431 *found = memmem(addr, size, pat, patlen); 432 433 (void)kdb_jmpbuf(prev); 434 return ((ret == 0) ? 1 : 0); 435 } 436