1 1.31 riastrad /* $NetBSD: kgdb_stub.c,v 1.31 2022/10/26 23:26:57 riastradh Exp $ */ 2 1.1 gwr 3 1.1 gwr /* 4 1.1 gwr * Copyright (c) 1990, 1993 5 1.1 gwr * The Regents of the University of California. All rights reserved. 6 1.1 gwr * 7 1.1 gwr * This software was developed by the Computer Systems Engineering group 8 1.1 gwr * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 9 1.1 gwr * contributed to Berkeley. 10 1.1 gwr * 11 1.1 gwr * All advertising materials mentioning features or use of this software 12 1.1 gwr * must display the following acknowledgement: 13 1.1 gwr * This product includes software developed by the University of 14 1.1 gwr * California, Lawrence Berkeley Laboratories. 15 1.1 gwr * 16 1.1 gwr * Redistribution and use in source and binary forms, with or without 17 1.1 gwr * modification, are permitted provided that the following conditions 18 1.1 gwr * are met: 19 1.1 gwr * 1. Redistributions of source code must retain the above copyright 20 1.1 gwr * notice, this list of conditions and the following disclaimer. 21 1.1 gwr * 2. Redistributions in binary form must reproduce the above copyright 22 1.1 gwr * notice, this list of conditions and the following disclaimer in the 23 1.1 gwr * documentation and/or other materials provided with the distribution. 24 1.15 agc * 3. Neither the name of the University nor the names of its contributors 25 1.1 gwr * may be used to endorse or promote products derived from this software 26 1.1 gwr * without specific prior written permission. 27 1.1 gwr * 28 1.1 gwr * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 1.1 gwr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 1.1 gwr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 1.1 gwr * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 1.1 gwr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 1.1 gwr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 1.1 gwr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 1.1 gwr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 1.1 gwr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 1.1 gwr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 1.1 gwr * SUCH DAMAGE. 39 1.1 gwr * 40 1.1 gwr * @(#)kgdb_stub.c 8.4 (Berkeley) 1/12/94 41 1.1 gwr */ 42 1.1 gwr 43 1.1 gwr /* 44 1.16 wiz * "Stub" to allow remote CPU to debug over a serial line using gdb. 45 1.1 gwr */ 46 1.10 lukem 47 1.10 lukem #include <sys/cdefs.h> 48 1.31 riastrad __KERNEL_RCSID(0, "$NetBSD: kgdb_stub.c,v 1.31 2022/10/26 23:26:57 riastradh Exp $"); 49 1.11 lukem 50 1.25 matt #include "opt_ddb.h" 51 1.11 lukem #include "opt_kgdb.h" 52 1.1 gwr 53 1.1 gwr #include <sys/param.h> 54 1.1 gwr #include <sys/systm.h> 55 1.1 gwr #include <sys/kgdb.h> 56 1.1 gwr 57 1.13 thorpej #undef DEBUG_KGDB 58 1.13 thorpej 59 1.13 thorpej #ifdef DEBUG_KGDB 60 1.13 thorpej #define DPRINTF(x) printf x 61 1.13 thorpej #else 62 1.13 thorpej #define DPRINTF(x) 63 1.13 thorpej #endif 64 1.1 gwr 65 1.1 gwr /* XXX: Maybe these should be in the MD files? */ 66 1.11 lukem #ifndef KGDB_DEV 67 1.11 lukem #define KGDB_DEV NODEV 68 1.1 gwr #endif 69 1.11 lukem #ifndef KGDB_DEVRATE 70 1.11 lukem #define KGDB_DEVRATE 19200 71 1.1 gwr #endif 72 1.1 gwr 73 1.23 cegger dev_t kgdb_dev = KGDB_DEV; /* remote debugging device (NODEV if none) */ 74 1.11 lukem int kgdb_rate = KGDB_DEVRATE; /* remote debugging baud rate */ 75 1.1 gwr int kgdb_active = 0; /* remote debugging active if != 0 */ 76 1.1 gwr int kgdb_debug_init = 0; /* != 0 waits for remote at system init */ 77 1.1 gwr int kgdb_debug_panic = 0; /* != 0 waits for remote on panic */ 78 1.1 gwr label_t *kgdb_recover = 0; 79 1.1 gwr 80 1.17 junyoung static int (*kgdb_getc)(void *); 81 1.17 junyoung static void (*kgdb_putc)(void *, int); 82 1.1 gwr static void *kgdb_ioarg; 83 1.1 gwr 84 1.12 dbj /* KGDB_BUFLEN must be at least (2*KGDB_NUMREGS*sizeof(kgdb_reg_t)+1) */ 85 1.1 gwr static u_char buffer[KGDB_BUFLEN]; 86 1.1 gwr static kgdb_reg_t gdb_regs[KGDB_NUMREGS]; 87 1.1 gwr 88 1.29 christos #define GETC() kgdb_waitc(kgdb_ioarg) 89 1.29 christos #define PUTC(c) (*kgdb_putc)(kgdb_ioarg, c) 90 1.29 christos 91 1.29 christos static int 92 1.29 christos kgdb_waitc(void *arg) 93 1.29 christos { 94 1.29 christos int c; 95 1.29 christos while ((c = (*kgdb_getc)(arg)) == -1) 96 1.29 christos continue; 97 1.29 christos return c; 98 1.29 christos } 99 1.1 gwr 100 1.1 gwr /* 101 1.7 jeffs * db_trap_callback can be hooked by MD port code to handle special 102 1.7 jeffs * cases such as disabling hardware watchdogs while in kgdb. Name 103 1.7 jeffs * is shared with DDB. 104 1.7 jeffs */ 105 1.25 matt #ifdef DDB 106 1.31 riastrad #include <ddb/db_extern.h> 107 1.25 matt #else 108 1.7 jeffs void (*db_trap_callback)(int); 109 1.25 matt #endif 110 1.7 jeffs 111 1.24 dyoung void kgdb_voidop(void); 112 1.24 dyoung 113 1.24 dyoung __weak_alias(kgdb_entry_notice, kgdb_voidop); 114 1.24 dyoung 115 1.24 dyoung void 116 1.24 dyoung kgdb_voidop(void) 117 1.24 dyoung { 118 1.24 dyoung return; 119 1.24 dyoung } 120 1.24 dyoung 121 1.7 jeffs /* 122 1.1 gwr * This little routine exists simply so that bcopy() can be debugged. 123 1.1 gwr */ 124 1.1 gwr static void 125 1.22 thorpej kgdb_copy(void *vsrc, void *vdst, int len) 126 1.1 gwr { 127 1.1 gwr char *src = vsrc; 128 1.1 gwr char *dst = vdst; 129 1.1 gwr 130 1.1 gwr while (--len >= 0) 131 1.1 gwr *dst++ = *src++; 132 1.1 gwr } 133 1.1 gwr 134 1.1 gwr #if 0 135 1.1 gwr /* ditto for bzero */ 136 1.1 gwr static void 137 1.22 thorpej kgdb_zero(void *vptr, int len) 138 1.1 gwr { 139 1.1 gwr char *ptr = vptr; 140 1.1 gwr 141 1.1 gwr while (--len >= 0) 142 1.1 gwr *ptr++ = (char) 0; 143 1.1 gwr } 144 1.1 gwr #endif 145 1.1 gwr 146 1.1 gwr /* 147 1.1 gwr * Convert a hex digit into an integer. 148 1.1 gwr * This returns -1 if the argument passed is no 149 1.1 gwr * valid hex digit. 150 1.1 gwr */ 151 1.1 gwr static int 152 1.22 thorpej digit2i(u_char c) 153 1.1 gwr { 154 1.1 gwr if (c >= '0' && c <= '9') 155 1.6 scottr return (c - '0'); 156 1.1 gwr else if (c >= 'a' && c <= 'f') 157 1.19 perry return (c - 'a' + 10); 158 1.1 gwr else if (c >= 'A' && c <= 'F') 159 1.1 gwr 160 1.19 perry return (c - 'A' + 10); 161 1.1 gwr else 162 1.6 scottr return (-1); 163 1.1 gwr } 164 1.1 gwr 165 1.1 gwr /* 166 1.1 gwr * Convert the low 4 bits of an integer into 167 1.30 skrll * a hex digit. 168 1.1 gwr */ 169 1.1 gwr static u_char 170 1.22 thorpej i2digit(int n) 171 1.1 gwr { 172 1.20 christos return (hexdigits[n & 0x0f]); 173 1.1 gwr } 174 1.1 gwr 175 1.1 gwr /* 176 1.30 skrll * Convert a byte array into a hex string. 177 1.1 gwr */ 178 1.1 gwr static void 179 1.22 thorpej mem2hex(void *vdst, void *vsrc, int len) 180 1.1 gwr { 181 1.1 gwr u_char *dst = vdst; 182 1.1 gwr u_char *src = vsrc; 183 1.1 gwr 184 1.1 gwr while (len--) { 185 1.1 gwr *dst++ = i2digit(*src >> 4); 186 1.1 gwr *dst++ = i2digit(*src++); 187 1.1 gwr } 188 1.1 gwr *dst = '\0'; 189 1.1 gwr } 190 1.1 gwr 191 1.1 gwr /* 192 1.30 skrll * Convert a hex string into a byte array. 193 1.1 gwr * This returns a pointer to the character following 194 1.1 gwr * the last valid hex digit. If the string ends in 195 1.1 gwr * the middle of a byte, NULL is returned. 196 1.1 gwr */ 197 1.1 gwr static u_char * 198 1.22 thorpej hex2mem(void *vdst, u_char *src, int maxlen) 199 1.1 gwr { 200 1.1 gwr u_char *dst = vdst; 201 1.1 gwr int msb, lsb; 202 1.1 gwr 203 1.1 gwr while (*src && maxlen--) { 204 1.1 gwr msb = digit2i(*src++); 205 1.1 gwr if (msb < 0) 206 1.6 scottr return (src - 1); 207 1.1 gwr lsb = digit2i(*src++); 208 1.1 gwr if (lsb < 0) 209 1.6 scottr return (NULL); 210 1.1 gwr *dst++ = (msb << 4) | lsb; 211 1.1 gwr } 212 1.6 scottr return (src); 213 1.1 gwr } 214 1.1 gwr 215 1.1 gwr /* 216 1.30 skrll * Convert a hex string into an integer. 217 1.1 gwr * This returns a pointer to the character following 218 1.1 gwr * the last valid hex digit. 219 1.19 perry */ 220 1.5 eeh static vaddr_t 221 1.22 thorpej hex2i(u_char **srcp) 222 1.1 gwr { 223 1.1 gwr char *src = *srcp; 224 1.5 eeh vaddr_t r = 0; 225 1.1 gwr int nibble; 226 1.1 gwr 227 1.1 gwr while ((nibble = digit2i(*src)) >= 0) { 228 1.1 gwr r *= 16; 229 1.1 gwr r += nibble; 230 1.1 gwr src++; 231 1.1 gwr } 232 1.1 gwr *srcp = src; 233 1.6 scottr return (r); 234 1.1 gwr } 235 1.1 gwr 236 1.1 gwr /* 237 1.1 gwr * Send a packet. 238 1.1 gwr */ 239 1.1 gwr static void 240 1.22 thorpej kgdb_send(const u_char *bp) 241 1.1 gwr { 242 1.21 christos const u_char *p; 243 1.1 gwr u_char csum, c; 244 1.1 gwr 245 1.13 thorpej DPRINTF(("kgdb_send: %s\n", bp)); 246 1.1 gwr do { 247 1.1 gwr p = bp; 248 1.1 gwr PUTC(KGDB_START); 249 1.1 gwr for (csum = 0; (c = *p); p++) { 250 1.1 gwr PUTC(c); 251 1.1 gwr csum += c; 252 1.1 gwr } 253 1.1 gwr PUTC(KGDB_END); 254 1.1 gwr PUTC(i2digit(csum >> 4)); 255 1.1 gwr PUTC(i2digit(csum)); 256 1.1 gwr } while ((c = GETC() & 0x7f) == KGDB_BADP); 257 1.1 gwr } 258 1.1 gwr 259 1.1 gwr /* 260 1.1 gwr * Receive a packet. 261 1.1 gwr */ 262 1.1 gwr static int 263 1.22 thorpej kgdb_recv(u_char *bp, int maxlen) 264 1.1 gwr { 265 1.1 gwr u_char *p; 266 1.13 thorpej int c, csum, tmpcsum; 267 1.1 gwr int len; 268 1.1 gwr 269 1.13 thorpej DPRINTF(("kgdb_recv: ")); 270 1.1 gwr do { 271 1.1 gwr p = bp; 272 1.1 gwr csum = len = 0; 273 1.1 gwr while ((c = GETC()) != KGDB_START) 274 1.13 thorpej DPRINTF(("%c",c)); 275 1.13 thorpej DPRINTF(("%c Start ",c)); 276 1.1 gwr 277 1.1 gwr while ((c = GETC()) != KGDB_END && len < maxlen) { 278 1.13 thorpej DPRINTF(("%c",c)); 279 1.1 gwr c &= 0x7f; 280 1.1 gwr csum += c; 281 1.1 gwr *p++ = c; 282 1.1 gwr len++; 283 1.1 gwr } 284 1.1 gwr csum &= 0xff; 285 1.1 gwr *p = '\0'; 286 1.13 thorpej DPRINTF(("%c End ", c)); 287 1.1 gwr 288 1.1 gwr if (len >= maxlen) { 289 1.13 thorpej DPRINTF(("Long- ")); 290 1.1 gwr PUTC(KGDB_BADP); 291 1.1 gwr continue; 292 1.1 gwr } 293 1.13 thorpej tmpcsum = csum; 294 1.1 gwr 295 1.13 thorpej c = GETC(); 296 1.13 thorpej DPRINTF(("%c",c)); 297 1.13 thorpej csum -= digit2i(c) * 16; 298 1.13 thorpej c = GETC(); 299 1.13 thorpej DPRINTF(("%c",c)); 300 1.13 thorpej csum -= digit2i(c); 301 1.1 gwr 302 1.1 gwr if (csum == 0) { 303 1.13 thorpej DPRINTF(("Good+ ")); 304 1.1 gwr PUTC(KGDB_GOODP); 305 1.1 gwr /* Sequence present? */ 306 1.1 gwr if (bp[2] == ':') { 307 1.13 thorpej DPRINTF(("Seq %c%c ", bp[0], bp[1])); 308 1.1 gwr PUTC(bp[0]); 309 1.1 gwr PUTC(bp[1]); 310 1.1 gwr len -= 3; 311 1.1 gwr kgdb_copy(bp + 3, bp, len); 312 1.1 gwr } 313 1.1 gwr break; 314 1.1 gwr } 315 1.13 thorpej DPRINTF((" Bad(wanted %x, off by %d)- ", tmpcsum, csum)); 316 1.27 christos __USE(tmpcsum); 317 1.1 gwr PUTC(KGDB_BADP); 318 1.1 gwr } while (1); 319 1.13 thorpej DPRINTF(("kgdb_recv: %s\n", bp)); 320 1.6 scottr return (len); 321 1.1 gwr } 322 1.1 gwr 323 1.1 gwr /* 324 1.6 scottr * This is called by the appropriate tty driver. 325 1.1 gwr */ 326 1.1 gwr void 327 1.22 thorpej kgdb_attach(int (*getfn)(void *), void (*putfn)(void *, int), void *ioarg) 328 1.1 gwr { 329 1.1 gwr kgdb_getc = getfn; 330 1.1 gwr kgdb_putc = putfn; 331 1.1 gwr kgdb_ioarg = ioarg; 332 1.1 gwr } 333 1.1 gwr 334 1.1 gwr /* 335 1.6 scottr * This function does all command processing for interfacing to 336 1.1 gwr * a remote gdb. Note that the error codes are ignored by gdb 337 1.1 gwr * at present, but might eventually become meaningful. (XXX) 338 1.1 gwr * It might makes sense to use POSIX errno values, because 339 1.1 gwr * that is what the gdb/remote.c functions want to return. 340 1.1 gwr */ 341 1.1 gwr int 342 1.22 thorpej kgdb_trap(int type, db_regs_t *regs) 343 1.1 gwr { 344 1.1 gwr label_t jmpbuf; 345 1.5 eeh vaddr_t addr; 346 1.1 gwr size_t len; 347 1.1 gwr u_char *p; 348 1.1 gwr 349 1.24 dyoung kgdb_entry_notice(type, regs); 350 1.24 dyoung 351 1.23 cegger if (kgdb_dev == NODEV || kgdb_getc == NULL) { 352 1.1 gwr /* not debugging */ 353 1.1 gwr return (0); 354 1.1 gwr } 355 1.8 wdk 356 1.8 wdk db_clear_single_step(regs); 357 1.1 gwr 358 1.26 skrll if (db_trap_callback) 359 1.26 skrll db_trap_callback(1); 360 1.7 jeffs 361 1.1 gwr /* Detect and recover from unexpected traps. */ 362 1.1 gwr if (kgdb_recover != 0) { 363 1.1 gwr printf("kgdb: caught trap 0x%x at %p\n", 364 1.1 gwr type, (void*)PC_REGS(regs)); 365 1.1 gwr kgdb_send("E0E"); /* 14==EFAULT */ 366 1.1 gwr longjmp(kgdb_recover); 367 1.1 gwr } 368 1.1 gwr 369 1.1 gwr /* 370 1.2 gwr * The first entry to this function is normally through 371 1.2 gwr * a breakpoint trap in kgdb_connect(), in which case we 372 1.2 gwr * must advance past the breakpoint because gdb will not. 373 1.2 gwr * 374 1.2 gwr * Machines vary as to where they leave the PC after a 375 1.2 gwr * breakpoint trap. Those that leave the PC set to the 376 1.2 gwr * address of the trap instruction (i.e. pc532) will not 377 1.2 gwr * define FIXUP_PC_AFTER_BREAK(), and therefore will just 378 1.2 gwr * advance the PC. On machines that leave the PC set to 379 1.2 gwr * the instruction after the trap, FIXUP_PC_AFTER_BREAK 380 1.2 gwr * will be defined to back-up the PC, so that after the 381 1.2 gwr * "first-time" part of the if statement below has run, 382 1.2 gwr * the PC will be the same as it was on entry. 383 1.2 gwr * 384 1.1 gwr * On the first entry here, we expect that gdb is not yet 385 1.1 gwr * listening to us, so just enter the interaction loop. 386 1.2 gwr * After the debugger is "active" (connected) it will be 387 1.1 gwr * waiting for a "signaled" message from us. 388 1.1 gwr */ 389 1.1 gwr if (kgdb_active == 0) { 390 1.1 gwr if (!IS_BREAKPOINT_TRAP(type, 0)) { 391 1.1 gwr /* No debugger active -- let trap handle this. */ 392 1.26 skrll if (db_trap_callback) 393 1.26 skrll db_trap_callback(0); 394 1.1 gwr return (0); 395 1.1 gwr } 396 1.2 gwr /* Make the PC point at the breakpoint... */ 397 1.2 gwr #ifdef FIXUP_PC_AFTER_BREAK 398 1.2 gwr FIXUP_PC_AFTER_BREAK(regs); 399 1.2 gwr #endif 400 1.2 gwr /* ... and then advance past it. */ 401 1.4 pk #ifdef PC_ADVANCE 402 1.4 pk PC_ADVANCE(regs); 403 1.4 pk #else 404 1.2 gwr PC_REGS(regs) += BKPT_SIZE; 405 1.4 pk #endif 406 1.1 gwr kgdb_active = 1; 407 1.1 gwr } else { 408 1.9 wiz /* Tell remote host that an exception has occurred. */ 409 1.18 itojun snprintf(buffer, sizeof(buffer), "S%02x", kgdb_signal(type)); 410 1.1 gwr kgdb_send(buffer); 411 1.1 gwr } 412 1.1 gwr 413 1.1 gwr /* Stick frame regs into our reg cache. */ 414 1.1 gwr kgdb_getregs(regs, gdb_regs); 415 1.1 gwr 416 1.1 gwr /* 417 1.1 gwr * Interact with gdb until it lets us go. 418 1.1 gwr * If we cause a trap, resume here. 419 1.1 gwr */ 420 1.6 scottr (void)setjmp((kgdb_recover = &jmpbuf)); 421 1.1 gwr for (;;) { 422 1.1 gwr kgdb_recv(buffer, sizeof(buffer)); 423 1.1 gwr switch (buffer[0]) { 424 1.1 gwr 425 1.1 gwr default: 426 1.1 gwr /* Unknown command. */ 427 1.1 gwr kgdb_send(""); 428 1.1 gwr continue; 429 1.1 gwr 430 1.1 gwr case KGDB_SIGNAL: 431 1.1 gwr /* 432 1.1 gwr * if this command came from a running gdb, 433 1.1 gwr * answer it -- the other guy has no way of 434 1.1 gwr * knowing if we're in or out of this loop 435 1.1 gwr * when he issues a "remote-signal". 436 1.1 gwr */ 437 1.18 itojun snprintf(buffer, sizeof(buffer), "S%02x", 438 1.18 itojun kgdb_signal(type)); 439 1.1 gwr kgdb_send(buffer); 440 1.1 gwr continue; 441 1.1 gwr 442 1.1 gwr case KGDB_REG_R: 443 1.1 gwr mem2hex(buffer, gdb_regs, sizeof(gdb_regs)); 444 1.1 gwr kgdb_send(buffer); 445 1.1 gwr continue; 446 1.1 gwr 447 1.1 gwr case KGDB_REG_W: 448 1.1 gwr p = hex2mem(gdb_regs, buffer + 1, sizeof(gdb_regs)); 449 1.1 gwr if (p == NULL || *p != '\0') 450 1.1 gwr kgdb_send("E01"); 451 1.1 gwr else { 452 1.1 gwr kgdb_setregs(regs, gdb_regs); 453 1.1 gwr kgdb_send("OK"); 454 1.1 gwr } 455 1.1 gwr continue; 456 1.1 gwr 457 1.1 gwr case KGDB_MEM_R: 458 1.1 gwr p = buffer + 1; 459 1.1 gwr addr = hex2i(&p); 460 1.1 gwr if (*p++ != ',') { 461 1.1 gwr kgdb_send("E02"); 462 1.1 gwr continue; 463 1.1 gwr } 464 1.1 gwr len = hex2i(&p); 465 1.1 gwr if (*p != '\0') { 466 1.1 gwr kgdb_send("E03"); 467 1.1 gwr continue; 468 1.1 gwr } 469 1.1 gwr if (len > sizeof(buffer) / 2) { 470 1.1 gwr kgdb_send("E04"); 471 1.1 gwr continue; 472 1.1 gwr } 473 1.1 gwr if (kgdb_acc(addr, len) == 0) { 474 1.1 gwr kgdb_send("E05"); 475 1.1 gwr continue; 476 1.1 gwr } 477 1.28 christos char *ptr = (char *)buffer + sizeof(buffer) / 2; 478 1.28 christos db_read_bytes(addr, len, ptr); 479 1.28 christos mem2hex(buffer, ptr, len); 480 1.1 gwr kgdb_send(buffer); 481 1.1 gwr continue; 482 1.1 gwr 483 1.1 gwr case KGDB_MEM_W: 484 1.1 gwr p = buffer + 1; 485 1.1 gwr addr = hex2i(&p); 486 1.1 gwr if (*p++ != ',') { 487 1.1 gwr kgdb_send("E06"); 488 1.1 gwr continue; 489 1.1 gwr } 490 1.1 gwr len = hex2i(&p); 491 1.1 gwr if (*p++ != ':') { 492 1.1 gwr kgdb_send("E07"); 493 1.1 gwr continue; 494 1.1 gwr } 495 1.1 gwr if (len > (sizeof(buffer) - (p - buffer))) { 496 1.1 gwr kgdb_send("E08"); 497 1.1 gwr continue; 498 1.1 gwr } 499 1.1 gwr p = hex2mem(buffer, p, sizeof(buffer)); 500 1.1 gwr if (p == NULL) { 501 1.1 gwr kgdb_send("E09"); 502 1.1 gwr continue; 503 1.1 gwr } 504 1.1 gwr if (kgdb_acc(addr, len) == 0) { 505 1.1 gwr kgdb_send("E0A"); 506 1.1 gwr continue; 507 1.1 gwr } 508 1.28 christos db_write_bytes(addr, len, (char *)buffer); 509 1.1 gwr kgdb_send("OK"); 510 1.1 gwr continue; 511 1.1 gwr 512 1.12 dbj case KGDB_DETACH: 513 1.1 gwr case KGDB_KILL: 514 1.1 gwr kgdb_active = 0; 515 1.1 gwr printf("kgdb detached\n"); 516 1.1 gwr db_clear_single_step(regs); 517 1.12 dbj kgdb_send("OK"); 518 1.1 gwr goto out; 519 1.1 gwr 520 1.1 gwr case KGDB_CONT: 521 1.1 gwr if (buffer[1]) { 522 1.1 gwr p = buffer + 1; 523 1.1 gwr addr = hex2i(&p); 524 1.1 gwr if (*p) { 525 1.1 gwr kgdb_send("E0B"); 526 1.1 gwr continue; 527 1.1 gwr } 528 1.1 gwr PC_REGS(regs) = addr; 529 1.14 dbj DPRINTF(("kgdb: continuing at %08lx\n", addr)); 530 1.13 thorpej 531 1.13 thorpej } else { 532 1.13 thorpej DPRINTF(( 533 1.13 thorpej "kgdb: continuing at old address %08lx\n", 534 1.14 dbj (vaddr_t)PC_REGS(regs))); 535 1.1 gwr } 536 1.13 thorpej 537 1.1 gwr db_clear_single_step(regs); 538 1.1 gwr goto out; 539 1.1 gwr 540 1.1 gwr case KGDB_STEP: 541 1.1 gwr if (buffer[1]) { 542 1.1 gwr p = buffer + 1; 543 1.1 gwr addr = hex2i(&p); 544 1.1 gwr if (*p) { 545 1.1 gwr kgdb_send("E0B"); 546 1.1 gwr continue; 547 1.1 gwr } 548 1.1 gwr PC_REGS(regs) = addr; 549 1.1 gwr } 550 1.1 gwr db_set_single_step(regs); 551 1.1 gwr goto out; 552 1.1 gwr } 553 1.1 gwr } 554 1.1 gwr out: 555 1.26 skrll if (db_trap_callback) 556 1.26 skrll db_trap_callback(0); 557 1.1 gwr kgdb_recover = 0; 558 1.1 gwr return (1); 559 1.1 gwr } 560 1.24 dyoung 561 1.24 dyoung int 562 1.24 dyoung kgdb_disconnected(void) 563 1.24 dyoung { 564 1.24 dyoung return 1; 565 1.24 dyoung } 566