⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 remote_gdb.cc

📁 M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作为模拟平台
💻 CC
📖 第 1 页 / 共 2 页
字号:
    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 + -