📄 remote_gdb.cc
字号:
return true;}PCEventQueue *BaseRemoteGDB::getPcEventQueue(){ return &system->pcEventQueue;}BaseRemoteGDB::HardBreakpoint::HardBreakpoint(BaseRemoteGDB *_gdb, Addr pc) : PCEvent(_gdb->getPcEventQueue(), "HardBreakpoint Event", pc), gdb(_gdb), refcount(0){ DPRINTF(GDBMisc, "creating hardware breakpoint at %#x\n", evpc);}voidBaseRemoteGDB::HardBreakpoint::process(ThreadContext *tc){ DPRINTF(GDBMisc, "handling hardware breakpoint at %#x\n", pc()); if (tc == gdb->context) gdb->trap(SIGTRAP);}boolBaseRemoteGDB::insertSoftBreak(Addr addr, size_t len){ if (len != sizeof(TheISA::MachInst)) panic("invalid length\n"); return insertHardBreak(addr, len);}boolBaseRemoteGDB::removeSoftBreak(Addr addr, size_t len){ if (len != sizeof(MachInst)) panic("invalid length\n"); return removeHardBreak(addr, len);}boolBaseRemoteGDB::insertHardBreak(Addr addr, size_t len){ if (len != sizeof(MachInst)) panic("invalid length\n"); DPRINTF(GDBMisc, "inserting hardware breakpoint at %#x\n", addr); HardBreakpoint *&bkpt = hardBreakMap[addr]; if (bkpt == 0) bkpt = new HardBreakpoint(this, addr); bkpt->refcount++; return true;}boolBaseRemoteGDB::removeHardBreak(Addr addr, size_t len){ if (len != sizeof(MachInst)) panic("invalid length\n"); DPRINTF(GDBMisc, "removing hardware breakpoint at %#x\n", addr); break_iter_t i = hardBreakMap.find(addr); if (i == hardBreakMap.end()) return false; HardBreakpoint *hbp = (*i).second; if (--hbp->refcount == 0) { delete hbp; hardBreakMap.erase(i); } return true;}voidBaseRemoteGDB::setTempBreakpoint(Addr bkpt){ DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n", bkpt); insertHardBreak(bkpt, sizeof(TheISA::MachInst));}voidBaseRemoteGDB::clearTempBreakpoint(Addr &bkpt){ DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n", bkpt); removeHardBreak(bkpt, sizeof(TheISA::MachInst)); bkpt = 0;}const char *BaseRemoteGDB::break_type(char c){ switch(c) { case '0': return "software breakpoint"; case '1': return "hardware breakpoint"; case '2': return "write watchpoint"; case '3': return "read watchpoint"; case '4': return "access watchpoint"; default: return "unknown breakpoint/watchpoint"; }}// This function does all command processing for interfacing to a// remote gdb. Note that the error codes are ignored by gdb at// present, but might eventually become meaningful. (XXX) It might// makes sense to use POSIX errno values, because that is what the// gdb/remote.c functions want to return.boolBaseRemoteGDB::trap(int type){ uint64_t val; size_t datalen, len; char data[GDBPacketBufLen + 1]; char *buffer; int bufferSize; const char *p; char command, subcmd; string var; bool ret; if (!attached) return false; bufferSize = gdbregs.bytes() * 2 + 256; buffer = (char*)malloc(bufferSize); DPRINTF(GDBMisc, "trap: PC=%#x NPC=%#x\n", context->readPC(), context->readNextPC()); clearSingleStep(); /* * The first entry to this function is normally through * a breakpoint trap in kgdb_connect(), in which case we * must advance past the breakpoint because gdb will not. * * On the first entry here, we expect that gdb is not yet * listening to us, so just enter the interaction loop. * After the debugger is "active" (connected) it will be * waiting for a "signaled" message from us. */ if (!active) active = true; else // Tell remote host that an exception has occurred. snprintf((char *)buffer, bufferSize, "S%02x", type); send(buffer); // Stick frame regs into our reg cache. getregs(); for (;;) { datalen = recv(data, sizeof(data)); data[sizeof(data) - 1] = 0; // Sentinel command = data[0]; subcmd = 0; p = data + 1; switch (command) { case GDBSignal: // if this command came from a running gdb, answer it -- // the other guy has no way of knowing if we're in or out // of this loop when he issues a "remote-signal". snprintf((char *)buffer, bufferSize, "S%02x", type); send(buffer); continue; case GDBRegR: if (2 * gdbregs.bytes() > bufferSize) panic("buffer too small"); mem2hex(buffer, gdbregs.regs, gdbregs.bytes()); send(buffer); continue; case GDBRegW: p = hex2mem(gdbregs.regs, p, gdbregs.bytes()); if (p == NULL || *p != '\0') send("E01"); else { setregs(); send("OK"); } continue;#if 0 case GDBSetReg: val = hex2i(&p); if (*p++ != '=') { send("E01"); continue; } if (val < 0 && val >= KGDB_NUMREGS) { send("E01"); continue; } gdbregs.regs[val] = hex2i(&p); setregs(); send("OK"); continue;#endif case GDBMemR: val = hex2i(&p); if (*p++ != ',') { send("E02"); continue; } len = hex2i(&p); if (*p != '\0') { send("E03"); continue; } if (len > bufferSize) { send("E04"); continue; } if (!acc(val, len)) { send("E05"); continue; } if (read(val, (size_t)len, (char *)buffer)) { // variable length array would be nice, but C++ doesn't // officially support those... char *temp = new char[2*len+1]; mem2hex(temp, buffer, len); send(temp); delete [] temp; } else { send("E05"); } continue; case GDBMemW: val = hex2i(&p); if (*p++ != ',') { send("E06"); continue; } len = hex2i(&p); if (*p++ != ':') { send("E07"); continue; } if (len > datalen - (p - data)) { send("E08"); continue; } p = hex2mem(buffer, p, bufferSize); if (p == NULL) { send("E09"); continue; } if (!acc(val, len)) { send("E0A"); continue; } if (write(val, (size_t)len, (char *)buffer)) send("OK"); else send("E0B"); continue; case GDBSetThread: subcmd = *p++; val = hex2i(&p); if (val == 0) send("OK"); else send("E01"); continue; case GDBDetach: case GDBKill: active = false; clearSingleStep(); detach(); goto out; case GDBAsyncCont: subcmd = hex2i(&p); if (*p++ == ';') { val = hex2i(&p); context->setPC(val); context->setNextPC(val + sizeof(MachInst)); } clearSingleStep(); goto out; case GDBCont: if (p - data < datalen) { val = hex2i(&p); context->setPC(val); context->setNextPC(val + sizeof(MachInst)); } clearSingleStep(); goto out; case GDBAsyncStep: subcmd = hex2i(&p); if (*p++ == ';') { val = hex2i(&p); context->setPC(val); context->setNextPC(val + sizeof(MachInst)); } setSingleStep(); goto out; case GDBStep: if (p - data < datalen) { val = hex2i(&p); context->setPC(val); context->setNextPC(val + sizeof(MachInst)); } setSingleStep(); goto out; case GDBClrHwBkpt: subcmd = *p++; if (*p++ != ',') send("E0D"); val = hex2i(&p); if (*p++ != ',') send("E0D"); len = hex2i(&p); DPRINTF(GDBMisc, "clear %s, addr=%#x, len=%d\n", break_type(subcmd), val, len); ret = false; switch (subcmd) { case '0': // software breakpoint ret = removeSoftBreak(val, len); break; case '1': // hardware breakpoint ret = removeHardBreak(val, len); break; case '2': // write watchpoint case '3': // read watchpoint case '4': // access watchpoint default: // unknown send(""); break; } send(ret ? "OK" : "E0C"); continue; case GDBSetHwBkpt: subcmd = *p++; if (*p++ != ',') send("E0D"); val = hex2i(&p); if (*p++ != ',') send("E0D"); len = hex2i(&p); DPRINTF(GDBMisc, "set %s, addr=%#x, len=%d\n", break_type(subcmd), val, len); ret = false; switch (subcmd) { case '0': // software breakpoint ret = insertSoftBreak(val, len); break; case '1': // hardware breakpoint ret = insertHardBreak(val, len); break; case '2': // write watchpoint case '3': // read watchpoint case '4': // access watchpoint default: // unknown send(""); break; } send(ret ? "OK" : "E0C"); continue; case GDBQueryVar: var = string(p, datalen - 1); if (var == "C") send("QC0"); else send(""); continue; case GDBSetBaud: case GDBSetBreak: case GDBDebug: case GDBCycleStep: case GDBSigCycleStep: case GDBReadReg: case GDBSetVar: case GDBReset: case GDBThreadAlive: case GDBTargetExit: case GDBBinaryDload: // Unsupported command DPRINTF(GDBMisc, "Unsupported command: %s\n", gdb_command(command)); DDUMP(GDBMisc, (uint8_t *)data, datalen); send(""); continue; default: // Unknown command. DPRINTF(GDBMisc, "Unknown command: %c(%#x)\n", command, command); send(""); continue; } } out: free(buffer); return true;}// Convert a hex digit into an integer.// This returns -1 if the argument passed is no valid hex digit.intBaseRemoteGDB::digit2i(char c){ if (c >= '0' && c <= '9') return (c - '0'); else if (c >= 'a' && c <= 'f') return (c - 'a' + 10); else if (c >= 'A' && c <= 'F') return (c - 'A' + 10); else return (-1);}// Convert the low 4 bits of an integer into an hex digit.charBaseRemoteGDB::i2digit(int n){ return ("0123456789abcdef"[n & 0x0f]);}// Convert a byte array into an hex string.voidBaseRemoteGDB::mem2hex(void *vdst, const void *vsrc, int len){ char *dst = (char *)vdst; const char *src = (const char *)vsrc; while (len--) { *dst++ = i2digit(*src >> 4); *dst++ = i2digit(*src++); } *dst = '\0';}// Convert an hex string into a byte array.// This returns a pointer to the character following the last valid// hex digit. If the string ends in the middle of a byte, NULL is// returned.const char *BaseRemoteGDB::hex2mem(void *vdst, const char *src, int maxlen){ char *dst = (char *)vdst; int msb, lsb; while (*src && maxlen--) { msb = digit2i(*src++); if (msb < 0) return (src - 1); lsb = digit2i(*src++); if (lsb < 0) return (NULL); *dst++ = (msb << 4) | lsb; } return (src);}// Convert an hex string into an integer.// This returns a pointer to the character following the last valid// hex digit.AddrBaseRemoteGDB::hex2i(const char **srcp){ const char *src = *srcp; Addr r = 0; int nibble; while ((nibble = digit2i(*src)) >= 0) { r *= 16; r += nibble; src++; } *srcp = src; return (r);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -