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