remote_gdb.cc revision 56
1/* $Id$ */ 2/* 3 * Copyright (c) 1990, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * This software was developed by the Computer Systems Engineering group 7 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 8 * contributed to Berkeley. 9 * 10 * All advertising materials mentioning features or use of this software 11 * must display the following acknowledgement: 12 * This product includes software developed by the University of 13 * California, Lawrence Berkeley Laboratories. 14 * 15 * Redistribution and use in source and binary forms, with or without 16 * modification, are permitted provided that the following conditions 17 * are met: 18 * 1. Redistributions of source code must retain the above copyright 19 * notice, this list of conditions and the following disclaimer. 20 * 2. Redistributions in binary form must reproduce the above copyright 21 * notice, this list of conditions and the following disclaimer in the 22 * documentation and/or other materials provided with the distribution. 23 * 3. All advertising materials mentioning features or use of this software 24 * must display the following acknowledgement: 25 * This product includes software developed by the University of 26 * California, Berkeley and its contributors. 27 * 4. Neither the name of the University nor the names of its contributors 28 * may be used to endorse or promote products derived from this software 29 * without specific prior written permission. 30 * 31 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 32 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 33 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 34 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 35 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 39 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 40 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 41 * SUCH DAMAGE. 42 * 43 * @(#)kgdb_stub.c 8.4 (Berkeley) 1/12/94 44 */ 45 46/*- 47 * Copyright (c) 2001 The NetBSD Foundation, Inc. 48 * All rights reserved. 49 * 50 * This code is derived from software contributed to The NetBSD Foundation 51 * by Jason R. Thorpe. 52 * 53 * Redistribution and use in source and binary forms, with or without 54 * modification, are permitted provided that the following conditions 55 * are met: 56 * 1. Redistributions of source code must retain the above copyright 57 * notice, this list of conditions and the following disclaimer. 58 * 2. Redistributions in binary form must reproduce the above copyright 59 * notice, this list of conditions and the following disclaimer in the 60 * documentation and/or other materials provided with the distribution. 61 * 3. All advertising materials mentioning features or use of this software 62 * must display the following acknowledgement: 63 * This product includes software developed by the NetBSD 64 * Foundation, Inc. and its contributors. 65 * 4. Neither the name of The NetBSD Foundation nor the names of its 66 * contributors may be used to endorse or promote products derived 67 * from this software without specific prior written permission. 68 * 69 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 70 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 71 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 72 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 73 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 74 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 75 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 76 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 77 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 78 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 79 * POSSIBILITY OF SUCH DAMAGE. 80 */ 81 82/* 83 * $NetBSD: kgdb_stub.c,v 1.8 2001/07/07 22:58:00 wdk Exp $ 84 * 85 * Taken from NetBSD 86 * 87 * "Stub" to allow remote cpu to debug over a serial line using gdb. 88 */ 89 90#include <sys/signal.h> 91 92#include <unistd.h> 93 94#include <string> 95 96#include "cpu/exec_context.hh" 97#include "base/intmath.hh" 98#include "base/kgdb.h" 99 100#include "mem/functional_mem/physical_memory.hh" 101#include "base/remote_gdb.hh" 102#include "base/socket.hh" 103#include "base/trace.hh" 104#include "targetarch/vtophys.hh" 105#include "sim/system.hh" 106#include "cpu/static_inst.hh" 107 108using namespace std; 109 110#ifdef DEBUG 111RemoteGDB *theDebugger = NULL; 112 113void 114debugger() 115{ 116 if (theDebugger) 117 theDebugger->trap(ALPHA_KENTRY_IF); 118} 119#endif 120 121/////////////////////////////////////////////////////////// 122// 123// 124// 125 126GDBListener::Event::Event(GDBListener *l, int fd, int e) 127 : PollEvent(fd, e), listener(l) 128{} 129 130void 131GDBListener::Event::process(int revent) 132{ 133 listener->accept(); 134} 135 136GDBListener::GDBListener(RemoteGDB *g, int p) 137 : event(NULL), gdb(g), port(p) 138{} 139 140GDBListener::~GDBListener() 141{ 142 if (event) 143 delete event; 144} 145 146void 147GDBListener::listen() 148{ 149 while (!listener.listen(port, true)) { 150 DPRINTF(RGDB, "GDBListener(listen): Can't bind port %d\n", port); 151 port++; 152 } 153 154 cerr << "Listening for remote gdb connection on port " << port << endl; 155 event = new Event(this, listener.getfd(), POLLIN); 156 pollQueue.schedule(event); 157} 158 159void 160GDBListener::accept() 161{ 162 if (!listener.islistening()) 163 panic("GDBListener(accept): cannot accept a connection if we're not listening!"); 164 165 int sfd = listener.accept(true); 166 167 if (sfd != -1) { 168 if (gdb->isattached()) 169 close(sfd); 170 else 171 gdb->attach(sfd); 172 } 173} 174 175/////////////////////////////////////////////////////////// 176// 177// 178// 179int digit2i(char); 180char i2digit(int); 181void mem2hex(void *, const void *, int); 182const char *hex2mem(void *, const char *, int); 183Addr hex2i(const char **); 184 185RemoteGDB::Event::Event(RemoteGDB *g, int fd, int e) 186 : PollEvent(fd, e), gdb(g) 187{} 188 189void 190RemoteGDB::Event::process(int revent) 191{ gdb->trap(ALPHA_KENTRY_IF); } 192 193RemoteGDB::RemoteGDB(System *_system, ExecContext *c) 194 : event(NULL), fd(-1), active(false), attached(false), 195 system(_system), pmem(_system->physmem), context(c) 196{ 197#ifdef DEBUG 198 theDebugger = this; 199#endif 200 memset(gdbregs, 0, sizeof(gdbregs)); 201} 202 203RemoteGDB::~RemoteGDB() 204{ 205 if (event) 206 delete event; 207} 208 209bool 210RemoteGDB::isattached() 211{ return attached; } 212 213void 214RemoteGDB::attach(int f) 215{ 216 fd = f; 217 218 event = new Event(this, fd, POLLIN); 219 pollQueue.schedule(event); 220 221 attached = true; 222 DPRINTFN("remote gdb attached\n"); 223} 224 225void 226RemoteGDB::detach() 227{ 228 attached = false; 229 close(fd); 230 fd = -1; 231 232 pollQueue.remove(event); 233 DPRINTFN("remote gdb detached\n"); 234} 235 236const char * 237gdb_command(char cmd) 238{ 239 switch (cmd) { 240 case KGDB_SIGNAL: return "KGDB_SIGNAL"; 241 case KGDB_SET_BAUD: return "KGDB_SET_BAUD"; 242 case KGDB_SET_BREAK: return "KGDB_SET_BREAK"; 243 case KGDB_CONT: return "KGDB_CONT"; 244 case KGDB_ASYNC_CONT: return "KGDB_ASYNC_CONT"; 245 case KGDB_DEBUG: return "KGDB_DEBUG"; 246 case KGDB_DETACH: return "KGDB_DETACH"; 247 case KGDB_REG_R: return "KGDB_REG_R"; 248 case KGDB_REG_W: return "KGDB_REG_W"; 249 case KGDB_SET_THREAD: return "KGDB_SET_THREAD"; 250 case KGDB_CYCLE_STEP: return "KGDB_CYCLE_STEP"; 251 case KGDB_SIG_CYCLE_STEP: return "KGDB_SIG_CYCLE_STEP"; 252 case KGDB_KILL: return "KGDB_KILL"; 253 case KGDB_MEM_W: return "KGDB_MEM_W"; 254 case KGDB_MEM_R: return "KGDB_MEM_R"; 255 case KGDB_SET_REG: return "KGDB_SET_REG"; 256 case KGDB_READ_REG: return "KGDB_READ_REG"; 257 case KGDB_QUERY_VAR: return "KGDB_QUERY_VAR"; 258 case KGDB_SET_VAR: return "KGDB_SET_VAR"; 259 case KGDB_RESET: return "KGDB_RESET"; 260 case KGDB_STEP: return "KGDB_STEP"; 261 case KGDB_ASYNC_STEP: return "KGDB_ASYNC_STEP"; 262 case KGDB_THREAD_ALIVE: return "KGDB_THREAD_ALIVE"; 263 case KGDB_TARGET_EXIT: return "KGDB_TARGET_EXIT"; 264 case KGDB_BINARY_DLOAD: return "KGDB_BINARY_DLOAD"; 265 case KGDB_CLR_HW_BKPT: return "KGDB_CLR_HW_BKPT"; 266 case KGDB_SET_HW_BKPT: return "KGDB_SET_HW_BKPT"; 267 case KGDB_START: return "KGDB_START"; 268 case KGDB_END: return "KGDB_END"; 269 case KGDB_GOODP: return "KGDB_GOODP"; 270 case KGDB_BADP: return "KGDB_BADP"; 271 default: return "KGDB_UNKNOWN"; 272 } 273} 274 275/////////////////////////////////////////////////////////// 276// RemoteGDB::acc 277// 278// Determine if the mapping at va..(va+len) is valid. 279// 280bool 281RemoteGDB::acc(Addr va, size_t len) 282{ 283 Addr last_va; 284 Addr pte; 285 286 va = alpha_trunc_page(va); 287 last_va = alpha_round_page(va + len); 288 289 do { 290 if (va < ALPHA_K0SEG_BASE) { 291 DPRINTF(RGDB, "RGDB(acc): Mapping is invalid %#x < K0SEG\n", va); 292 return false; 293 } 294 295 if (va < ALPHA_K1SEG_BASE) { 296 if (va < (ALPHA_K0SEG_BASE + pmem->getSize())) { 297 DPRINTF(RGDB, "RGDB(acc): Mapping is valid K0SEG <= " 298 "%#x < K0SEG + size\n", va); 299 return true; 300 } else { 301 DPRINTF(RGDB, "RGDB(acc): Mapping is invalid %#x < K0SEG\n", 302 va); 303 return false; 304 } 305 } 306 307 Addr ptbr = context->regs.ipr[AlphaISA::IPR_PALtemp20]; 308 pte = kernel_pte_lookup(pmem, ptbr, va); 309 if (!pte || !entry_valid(pmem->phys_read_qword(pte))) { 310 DPRINTF(RGDB, "RGDB(acc): %#x pte is invalid\n", va); 311 return false; 312 } 313 va += ALPHA_PGBYTES; 314 } while (va < last_va); 315 316 DPRINTF(RGDB, "RGDB(acc): %#x mapping is valid\n", va); 317 return true; 318} 319 320/////////////////////////////////////////////////////////// 321// RemoteGDB::signal 322// 323// Translate a trap number into a Unix-compatible signal number. 324// (GDB only understands Unix signal numbers.) 325// 326int 327RemoteGDB::signal(int type) 328{ 329 switch (type) { 330 case ALPHA_KENTRY_UNA: 331 return (SIGBUS); 332 333 case ALPHA_KENTRY_ARITH: 334 return (SIGFPE); 335 336 case ALPHA_KENTRY_IF: 337 return (SIGILL); 338 339 case ALPHA_KENTRY_MM: 340 return (SIGSEGV); 341 342 default: 343 panic("unknown signal type"); 344 return 0; 345 } 346} 347 348/////////////////////////////////////////////////////////// 349// RemoteGDB::getregs 350// 351// Translate the kernel debugger register format into 352// the GDB register format. 353void 354RemoteGDB::getregs() 355{ 356 memset(gdbregs, 0, sizeof(gdbregs)); 357 memcpy(&gdbregs[KGDB_REG_V0], context->regs.intRegFile, 32 * sizeof(uint64_t)); 358#ifdef KGDB_FP_REGS 359 memcpy(&gdbregs[KGDB_REG_F0], context->regs.floatRegFile.q, 360 32 * sizeof(uint64_t)); 361#endif 362 gdbregs[KGDB_REG_PC] = context->regs.pc; 363} 364 365/////////////////////////////////////////////////////////// 366// RemoteGDB::setregs 367// 368// Translate the GDB register format into the kernel 369// debugger register format. 370// 371void 372RemoteGDB::setregs() 373{ 374 memcpy(context->regs.intRegFile, &gdbregs[KGDB_REG_V0], 32 * sizeof(uint64_t)); 375#ifdef KGDB_FP_REGS 376 memcpy(context->regs.floatRegFile.q, &gdbregs[KGDB_REG_F0], 377 32 * sizeof(uint64_t)); 378#endif 379 context->regs.pc = gdbregs[KGDB_REG_PC]; 380} 381 382void 383RemoteGDB::setTempBreakpoint(TempBreakpoint &bkpt, Addr addr) 384{ 385 DPRINTF(RGDB, "RGDB(setTempBreakpoint): addr=%#x\n", addr); 386 387 bkpt.address = addr; 388 insertHardBreak(addr, 4); 389} 390 391void 392RemoteGDB::clearTempBreakpoint(TempBreakpoint &bkpt) 393{ 394 DPRINTF(RGDB, "RGDB(setTempBreakpoint): addr=%#x\n", 395 bkpt.address); 396 397 398 removeHardBreak(bkpt.address, 4); 399 bkpt.address = 0; 400} 401 402void 403RemoteGDB::clearSingleStep() 404{ 405 DPRINTF(RGDB, "clearSingleStep bt_addr=%#x nt_addr=%#x\n", 406 takenBkpt.address, notTakenBkpt.address); 407 408 if (takenBkpt.address != 0) 409 clearTempBreakpoint(takenBkpt); 410 411 if (notTakenBkpt.address != 0) 412 clearTempBreakpoint(notTakenBkpt); 413} 414 415void 416RemoteGDB::setSingleStep() 417{ 418 Addr pc = context->regs.pc; 419 Addr npc, bpc; 420 bool set_bt = false; 421 422 npc = pc + sizeof(MachInst); 423 424 // User was stopped at pc, e.g. the instruction at pc was not 425 // executed. 426 MachInst inst = read<MachInst>(pc); 427 StaticInstPtr<TheISA> si(inst); 428 if (si->hasBranchTarget(pc, context, bpc)) { 429 // Don't bother setting a breakpoint on the taken branch if it 430 // is the same as the next pc 431 if (bpc != npc) 432 set_bt = true; 433 } 434 435 DPRINTF(RGDB, "setSingleStep bt_addr=%#x nt_addr=%#x\n", 436 takenBkpt.address, notTakenBkpt.address); 437 438 setTempBreakpoint(notTakenBkpt, npc); 439 440 if (set_bt) 441 setTempBreakpoint(takenBkpt, bpc); 442} 443 444///////////////////////// 445// 446// 447 448uint8_t 449RemoteGDB::getbyte() 450{ 451 uint8_t b; 452 ::read(fd, &b, 1); 453 return b; 454} 455 456void 457RemoteGDB::putbyte(uint8_t b) 458{ 459 ::write(fd, &b, 1); 460} 461 462// Send a packet to gdb 463void 464RemoteGDB::send(const char *bp) 465{ 466 const char *p; 467 uint8_t csum, c; 468 469// DPRINTF(RGDB, "RGDB(send): %s\n", bp); 470 471 do { 472 p = bp; 473 putbyte(KGDB_START); 474 for (csum = 0; (c = *p); p++) { 475 putbyte(c); 476 csum += c; 477 } 478 putbyte(KGDB_END); 479 putbyte(i2digit(csum >> 4)); 480 putbyte(i2digit(csum)); 481 } while ((c = getbyte() & 0x7f) == KGDB_BADP); 482} 483 484// Receive a packet from gdb 485int 486RemoteGDB::recv(char *bp, int maxlen) 487{ 488 char *p; 489 int c, csum; 490 int len; 491 492 do { 493 p = bp; 494 csum = len = 0; 495 while ((c = getbyte()) != KGDB_START) 496 ; 497 498 while ((c = getbyte()) != KGDB_END && len < maxlen) { 499 c &= 0x7f; 500 csum += c; 501 *p++ = c; 502 len++; 503 } 504 csum &= 0xff; 505 *p = '\0'; 506 507 if (len >= maxlen) { 508 putbyte(KGDB_BADP); 509 continue; 510 } 511 512 csum -= digit2i(getbyte()) * 16; 513 csum -= digit2i(getbyte()); 514 515 if (csum == 0) { 516 putbyte(KGDB_GOODP); 517 // Sequence present? 518 if (bp[2] == ':') { 519 putbyte(bp[0]); 520 putbyte(bp[1]); 521 len -= 3; 522 bcopy(bp + 3, bp, len); 523 } 524 break; 525 } 526 putbyte(KGDB_BADP); 527 } while (1); 528 529// DPRINTF(RGDB, "RGDB(recv): %s: %s\n", gdb_command(*bp), bp); 530 531 return (len); 532} 533 534// Read bytes from kernel address space for debugger. 535bool 536RemoteGDB::read(Addr vaddr, size_t size, char *data) 537{ 538 static Addr lastaddr = 0; 539 static size_t lastsize = 0; 540 541 uint8_t *maddr; 542 543 if (vaddr < 10) { 544 DPRINTF(RGDB, "\nRGDB(read): reading memory location zero!\n"); 545 vaddr = lastaddr + lastsize; 546 } 547 548 DPRINTF(RGDB, "RGDB(read): addr=%#x, size=%d", vaddr, size); 549#if TRACING_ON 550 char *d = data; 551 size_t s = size; 552#endif 553 554 lastaddr = vaddr; 555 lastsize = size; 556 557 size_t count = min((Addr)size, 558 VMPageSize - (vaddr & (VMPageSize - 1))); 559 560 maddr = vtomem(context, vaddr, count); 561 memcpy(data, maddr, count); 562 563 vaddr += count; 564 data += count; 565 size -= count; 566 567 while (size >= VMPageSize) { 568 maddr = vtomem(context, vaddr, count); 569 memcpy(data, maddr, VMPageSize); 570 571 vaddr += VMPageSize; 572 data += VMPageSize; 573 size -= VMPageSize; 574 } 575 576 if (size > 0) { 577 maddr = vtomem(context, vaddr, count); 578 memcpy(data, maddr, size); 579 } 580 581#if TRACING_ON 582 if (DTRACE(RGDB)) { 583 char buf[1024]; 584 mem2hex(buf, d, s); 585 cprintf(": %s\n", buf); 586 } 587#endif 588 589 return true; 590} 591 592// Write bytes to kernel address space for debugger. 593bool 594RemoteGDB::write(Addr vaddr, size_t size, const char *data) 595{ 596 static Addr lastaddr = 0; 597 static size_t lastsize = 0; 598 599 uint8_t *maddr; 600 601 if (vaddr < 10) { 602 DPRINTF(RGDB, "RGDB(write): writing memory location zero!\n"); 603 vaddr = lastaddr + lastsize; 604 } 605 606 if (DTRACE(RGDB)) { 607 char buf[1024]; 608 mem2hex(buf, data, size); 609 cprintf("RGDB(write): addr=%#x, size=%d: %s\n", vaddr, size, buf); 610 } 611 612 lastaddr = vaddr; 613 lastsize = size; 614 615 size_t count = min((Addr)size, 616 VMPageSize - (vaddr & (VMPageSize - 1))); 617 618 maddr = vtomem(context, vaddr, count); 619 memcpy(maddr, data, count); 620 621 vaddr += count; 622 data += count; 623 size -= count; 624 625 while (size >= VMPageSize) { 626 maddr = vtomem(context, vaddr, count); 627 memcpy(maddr, data, VMPageSize); 628 629 vaddr += VMPageSize; 630 data += VMPageSize; 631 size -= VMPageSize; 632 } 633 634 if (size > 0) { 635 maddr = vtomem(context, vaddr, count); 636 memcpy(maddr, data, size); 637 } 638 639#ifdef IMB 640 alpha_pal_imb(); 641#endif 642 643 return true; 644} 645 646 647PCEventQueue *RemoteGDB::getPcEventQueue() 648{ 649 return &system->pcEventQueue; 650} 651 652 653RemoteGDB::HardBreakpoint::HardBreakpoint(RemoteGDB *_gdb, Addr pc) 654 : PCEvent(_gdb->getPcEventQueue(), "HardBreakpoint Event", pc), 655 gdb(_gdb), refcount(0) 656{ 657 DPRINTF(RGDB, "creating hardware breakpoint at %#x\n", evpc); 658 schedule(); 659} 660 661void 662RemoteGDB::HardBreakpoint::process(ExecContext *xc) 663{ 664 DPRINTF(RGDB, "handling hardware breakpoint at %#x\n", pc()); 665 666 if (xc == gdb->context) 667 gdb->trap(ALPHA_KENTRY_IF); 668} 669 670bool 671RemoteGDB::insertSoftBreak(Addr addr, size_t len) 672{ 673 if (len != sizeof(MachInst)) 674 panic("invalid length\n"); 675 676 return insertHardBreak(addr, len); 677} 678 679bool 680RemoteGDB::removeSoftBreak(Addr addr, size_t len) 681{ 682 if (len != sizeof(MachInst)) 683 panic("invalid length\n"); 684 685 return removeHardBreak(addr, len); 686} 687 688bool 689RemoteGDB::insertHardBreak(Addr addr, size_t len) 690{ 691 if (len != sizeof(MachInst)) 692 panic("invalid length\n"); 693 694 DPRINTF(RGDB, "inserting hardware breakpoint at %#x\n", addr); 695 696 HardBreakpoint *&bkpt = hardBreakMap[addr]; 697 if (bkpt == 0) 698 bkpt = new HardBreakpoint(this, addr); 699 700 bkpt->refcount++; 701 702 return true; 703 704#if 0 705 break_iter_t i = hardBreakMap.find(addr); 706 if (i == hardBreakMap.end()) { 707 HardBreakpoint *bkpt = new HardBreakpoint(this, addr); 708 hardBreakMap[addr] = bkpt; 709 i = hardBreakMap.insert(make_pair(addr, bkpt)); 710 if (i == hardBreakMap.end()) 711 return false; 712 } 713 714 (*i).second->refcount++; 715#endif 716} 717 718bool 719RemoteGDB::removeHardBreak(Addr addr, size_t len) 720{ 721 if (len != sizeof(MachInst)) 722 panic("invalid length\n"); 723 724 DPRINTF(RGDB, "removing hardware breakpoint at %#x\n", addr); 725 726 break_iter_t i = hardBreakMap.find(addr); 727 if (i == hardBreakMap.end()) 728 return false; 729 730 HardBreakpoint *hbp = (*i).second; 731 if (--hbp->refcount == 0) { 732 delete hbp; 733 hardBreakMap.erase(i); 734 } 735 736 return true; 737} 738 739const char * 740break_type(char c) 741{ 742 switch(c) { 743 case '0': return "software breakpoint"; 744 case '1': return "hardware breakpoint"; 745 case '2': return "write watchpoint"; 746 case '3': return "read watchpoint"; 747 case '4': return "access watchpoint"; 748 default: return "unknown breakpoint/watchpoint"; 749 } 750} 751 752// This function does all command processing for interfacing to a 753// remote gdb. Note that the error codes are ignored by gdb at 754// present, but might eventually become meaningful. (XXX) It might 755// makes sense to use POSIX errno values, because that is what the 756// gdb/remote.c functions want to return. 757bool 758RemoteGDB::trap(int type) 759{ 760 uint64_t val; 761 size_t datalen, len; 762 char data[KGDB_BUFLEN + 1]; 763 char buffer[sizeof(gdbregs) * 2 + 256]; 764 char temp[KGDB_BUFLEN]; 765 const char *p; 766 char command, subcmd; 767 string var; 768 bool ret; 769 770 if (!attached) 771 return false; 772 773 DPRINTF(RGDB, "RGDB(trap): PC=%#x NPC=%#x\n", 774 context->regs.pc, context->regs.npc); 775 776 clearSingleStep(); 777 778 /* 779 * The first entry to this function is normally through 780 * a breakpoint trap in kgdb_connect(), in which case we 781 * must advance past the breakpoint because gdb will not. 782 * 783 * On the first entry here, we expect that gdb is not yet 784 * listening to us, so just enter the interaction loop. 785 * After the debugger is "active" (connected) it will be 786 * waiting for a "signaled" message from us. 787 */ 788 if (!active) { 789 if (!IS_BREAKPOINT_TRAP(type, 0)) { 790 // No debugger active -- let trap handle this. 791 return false; 792 } 793 active = true; 794 } else { 795 // Tell remote host that an exception has occurred. 796 sprintf((char *)buffer, "S%02x", signal(type)); 797 send(buffer); 798 } 799 800 // Stick frame regs into our reg cache. 801 getregs(); 802 803 for (;;) { 804 datalen = recv(data, sizeof(data)); 805 data[sizeof(data) - 1] = 0; // Sentinel 806 command = data[0]; 807 subcmd = 0; 808 p = data + 1; 809 switch (command) { 810 811 case KGDB_SIGNAL: 812 // if this command came from a running gdb, answer it -- 813 // the other guy has no way of knowing if we're in or out 814 // of this loop when he issues a "remote-signal". 815 sprintf((char *)buffer, "S%02x", signal(type)); 816 send(buffer); 817 continue; 818 819 case KGDB_REG_R: 820 if (2 * sizeof(gdbregs) > sizeof(buffer)) 821 panic("buffer too small"); 822 823 mem2hex(buffer, gdbregs, sizeof(gdbregs)); 824 send(buffer); 825 continue; 826 827 case KGDB_REG_W: 828 p = hex2mem(gdbregs, p, sizeof(gdbregs)); 829 if (p == NULL || *p != '\0') 830 send("E01"); 831 else { 832 setregs(); 833 send("OK"); 834 } 835 continue; 836 837#if 0 838 case KGDB_SET_REG: 839 val = hex2i(&p); 840 if (*p++ != '=') { 841 send("E01"); 842 continue; 843 } 844 if (val < 0 && val >= KGDB_NUMREGS) { 845 send("E01"); 846 continue; 847 } 848 849 gdbregs[val] = hex2i(&p); 850 setregs(); 851 send("OK"); 852 853 continue; 854#endif 855 856 case KGDB_MEM_R: 857 val = hex2i(&p); 858 if (*p++ != ',') { 859 send("E02"); 860 continue; 861 } 862 len = hex2i(&p); 863 if (*p != '\0') { 864 send("E03"); 865 continue; 866 } 867 if (len > sizeof(buffer)) { 868 send("E04"); 869 continue; 870 } 871 if (!acc(val, len)) { 872 send("E05"); 873 continue; 874 } 875 876 if (read(val, (size_t)len, (char *)buffer)) { 877 mem2hex(temp, buffer, len); 878 send(temp); 879 } else { 880 send("E05"); 881 } 882 continue; 883 884 case KGDB_MEM_W: 885 val = hex2i(&p); 886 if (*p++ != ',') { 887 send("E06"); 888 continue; 889 } 890 len = hex2i(&p); 891 if (*p++ != ':') { 892 send("E07"); 893 continue; 894 } 895 if (len > datalen - (p - data)) { 896 send("E08"); 897 continue; 898 } 899 p = hex2mem(buffer, p, sizeof(buffer)); 900 if (p == NULL) { 901 send("E09"); 902 continue; 903 } 904 if (!acc(val, len)) { 905 send("E0A"); 906 continue; 907 } 908 if (write(val, (size_t)len, (char *)buffer)) 909 send("OK"); 910 else 911 send("E0B"); 912 continue; 913 914 case KGDB_SET_THREAD: 915 subcmd = *p++; 916 val = hex2i(&p); 917 if (val == 0) 918 send("OK"); 919 else 920 send("E01"); 921 continue; 922 923 case KGDB_DETACH: 924 case KGDB_KILL: 925 active = false; 926 clearSingleStep(); 927 detach(); 928 goto out; 929 930 case KGDB_ASYNC_CONT: 931 subcmd = hex2i(&p); 932 if (*p++ == ';') { 933 val = hex2i(&p); 934 context->regs.pc = val; 935 context->regs.npc = val + sizeof(MachInst); 936 } 937 clearSingleStep(); 938 goto out; 939 940 case KGDB_CONT: 941 if (p - data < datalen) { 942 val = hex2i(&p); 943 context->regs.pc = val; 944 context->regs.npc = val + sizeof(MachInst); 945 } 946 clearSingleStep(); 947 goto out; 948 949 case KGDB_ASYNC_STEP: 950 subcmd = hex2i(&p); 951 if (*p++ == ';') { 952 val = hex2i(&p); 953 context->regs.pc = val; 954 context->regs.npc = val + sizeof(MachInst); 955 } 956 setSingleStep(); 957 goto out; 958 959 case KGDB_STEP: 960 if (p - data < datalen) { 961 val = hex2i(&p); 962 context->regs.pc = val; 963 context->regs.npc = val + sizeof(MachInst); 964 } 965 setSingleStep(); 966 goto out; 967 968 case KGDB_CLR_HW_BKPT: 969 subcmd = *p++; 970 if (*p++ != ',') send("E0D"); 971 val = hex2i(&p); 972 if (*p++ != ',') send("E0D"); 973 len = hex2i(&p); 974 975 DPRINTF(RGDB, "kgdb: clear %s, addr=%#x, len=%d\n", 976 break_type(subcmd), val, len); 977 978 ret = false; 979 980 switch (subcmd) { 981 case '0': // software breakpoint 982 ret = removeSoftBreak(val, len); 983 break; 984 985 case '1': // hardware breakpoint 986 ret = removeHardBreak(val, len); 987 break; 988 989 case '2': // write watchpoint 990 case '3': // read watchpoint 991 case '4': // access watchpoint 992 default: // unknown 993 send(""); 994 break; 995 } 996 997 send(ret ? "OK" : "E0C"); 998 continue; 999 1000 case KGDB_SET_HW_BKPT: 1001 subcmd = *p++; 1002 if (*p++ != ',') send("E0D"); 1003 val = hex2i(&p); 1004 if (*p++ != ',') send("E0D"); 1005 len = hex2i(&p); 1006 1007 DPRINTF(RGDB, "kgdb: set %s, addr=%#x, len=%d\n", 1008 break_type(subcmd), val, len); 1009 1010 ret = false; 1011 1012 switch (subcmd) { 1013 case '0': // software breakpoint 1014 ret = insertSoftBreak(val, len); 1015 break; 1016 1017 case '1': // hardware breakpoint 1018 ret = insertHardBreak(val, len); 1019 break; 1020 1021 case '2': // write watchpoint 1022 case '3': // read watchpoint 1023 case '4': // access watchpoint 1024 default: // unknown 1025 send(""); 1026 break; 1027 } 1028 1029 send(ret ? "OK" : "E0C"); 1030 continue; 1031 1032 case KGDB_QUERY_VAR: 1033 var = string(p, datalen - 1); 1034 if (var == "C") 1035 send("QC0"); 1036 else 1037 send(""); 1038 continue; 1039 1040 case KGDB_SET_BAUD: 1041 case KGDB_SET_BREAK: 1042 case KGDB_DEBUG: 1043 case KGDB_CYCLE_STEP: 1044 case KGDB_SIG_CYCLE_STEP: 1045 case KGDB_READ_REG: 1046 case KGDB_SET_VAR: 1047 case KGDB_RESET: 1048 case KGDB_THREAD_ALIVE: 1049 case KGDB_TARGET_EXIT: 1050 case KGDB_BINARY_DLOAD: 1051 // Unsupported command 1052 DPRINTF(RGDB, "kgdb: Unsupported command: %s\n", 1053 gdb_command(command)); 1054 DDUMP(RGDB, (uint8_t *)data, datalen); 1055 send(""); 1056 continue; 1057 1058 default: 1059 // Unknown command. 1060 DPRINTF(RGDB, "kgdb: Unknown command: %c(%#x)\n", 1061 command, command); 1062 send(""); 1063 continue; 1064 1065 1066 } 1067 } 1068 1069 out: 1070 return true; 1071} 1072 1073// Convert a hex digit into an integer. 1074// This returns -1 if the argument passed is no valid hex digit. 1075int 1076digit2i(char c) 1077{ 1078 if (c >= '0' && c <= '9') 1079 return (c - '0'); 1080 else if (c >= 'a' && c <= 'f') 1081 return (c - 'a' + 10); 1082 else if (c >= 'A' && c <= 'F') 1083 1084 return (c - 'A' + 10); 1085 else 1086 return (-1); 1087} 1088 1089// Convert the low 4 bits of an integer into an hex digit. 1090char 1091i2digit(int n) 1092{ 1093 return ("0123456789abcdef"[n & 0x0f]); 1094} 1095 1096// Convert a byte array into an hex string. 1097void 1098mem2hex(void *vdst, const void *vsrc, int len) 1099{ 1100 char *dst = (char *)vdst; 1101 const char *src = (const char *)vsrc; 1102 1103 while (len--) { 1104 *dst++ = i2digit(*src >> 4); 1105 *dst++ = i2digit(*src++); 1106 } 1107 *dst = '\0'; 1108} 1109 1110// Convert an hex string into a byte array. 1111// This returns a pointer to the character following the last valid 1112// hex digit. If the string ends in the middle of a byte, NULL is 1113// returned. 1114const char * 1115hex2mem(void *vdst, const char *src, int maxlen) 1116{ 1117 char *dst = (char *)vdst; 1118 int msb, lsb; 1119 1120 while (*src && maxlen--) { 1121 msb = digit2i(*src++); 1122 if (msb < 0) 1123 return (src - 1); 1124 lsb = digit2i(*src++); 1125 if (lsb < 0) 1126 return (NULL); 1127 *dst++ = (msb << 4) | lsb; 1128 } 1129 return (src); 1130} 1131 1132// Convert an hex string into an integer. 1133// This returns a pointer to the character following the last valid 1134// hex digit. 1135Addr 1136hex2i(const char **srcp) 1137{ 1138 const char *src = *srcp; 1139 Addr r = 0; 1140 int nibble; 1141 1142 while ((nibble = digit2i(*src)) >= 0) { 1143 r *= 16; 1144 r += nibble; 1145 src++; 1146 } 1147 *srcp = src; 1148 return (r); 1149} 1150 1151