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