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