void GdbDebugger::handleResultStackListFrame(const GdbResponse &response, QMap<QString,QVariant> &map) { //10000015^done,stack=[frame={level="0",addr="0x0040113f",func="main.main",file="F:/hg/debug_test/hello/main.go",fullname="F:/hg/debug_test/hello/main.go",line="36"},frame={level="1",addr="0x00401f8a",func="runtime.mainstart",file="386/asm.s",fullname="c:/go/src/pkg/runtime/386/asm.s",line="96"},frame={level="2",addr="0x0040bcfe",func="runtime.initdone",file="/go/src/pkg/runtime/proc.c",fullname="c:/go/src/pkg/runtime/proc.c",line="242"},frame={level="3",addr="0x00000000",func="??"}] m_framesModel->removeRows(0,m_framesModel->rowCount()); if (response.resultClass != GdbResultDone) { return; } GdbMiValue stack = response.data.findChild("stack"); if (stack.isList()) { for (int i = 0; i < stack.childCount(); i++) { GdbMiValue child = stack.childAt(i); if (child.isValid() && child.name() == "frame") { QString level = child.findChild("level").data(); QString addr = child.findChild("addr").data(); QString func = child.findChild("func").data(); QString file = child.findChild("file").data(); QString line = child.findChild("line").data(); m_framesModel->appendRow(QList<QStandardItem*>() << new QStandardItem(level) << new QStandardItem(addr) << new QStandardItem(func) << new QStandardItem(file) << new QStandardItem(line) ); } } } }
void GdbDebugger::handleLibrary(const GdbMiValue &result) { QString id = result.findChild("id").data(); QString thread_group = result.findChild("thread-group").data(); m_libraryModel->appendRow(QList<QStandardItem*>() << new QStandardItem(id) << new QStandardItem(thread_group) ); }
void GdbDebugger::handleResultStackListVariables(const GdbResponse &response, QMap<QString,QVariant> &map) { //10000014^done,variables=[{name="v"},{name="x"},{name="pt"},{name="str"},{name="sum1"},{name="y"}] if (response.resultClass != GdbResultDone) { return; } GdbMiValue vars = response.data.findChild("variables"); if (vars.isList()) { foreach (const GdbMiValue &child, vars.m_children) { if (child.isValid()) { QString var = child.findChild("name").data(); if (!m_varNameMap.contains(var)) { createWatch(var,true,false); } } } }
void GdbDebugger::handleStopped(const GdbMiValue &result) { QByteArray reason = result.findChild("reason").data(); m_handleState.setReason(reason); m_handleState.setStopped(true); if (reason.startsWith("exited")) { m_handleState.setExited(true); m_handleState.setReason(reason); return; } GdbMiValue frame = result.findChild("frame"); if (frame.isValid()) { QString fullname = frame.findChild("fullname").data(); QString file = frame.findChild("file").data(); QString line = frame.findChild("line").data(); if (!fullname.isEmpty()) { emit setCurrentLine(fullname,line.toInt()-1); } else if (!file.isEmpty()) { //fix go build bug, not find fullname //file="C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist308287094/go/src/pkg/fmt/print.go" int i = file.indexOf("/go/src/pkg"); if (i > 0) { QString fullname = LiteApi::getGoroot(m_liteApp)+file.right(file.length()-i-3); emit setCurrentLine(fullname,line.toInt()-1); } } } }
static void GdbMiValueToItem(QStandardItem *item, const GdbMiValue &value) { switch (value.type()) { case GdbMiValue::Invalid: item->appendRow(new QStandardItem("Invalid")); break; case GdbMiValue::Const: if (value.name().isEmpty()) { item->appendRow(new QStandardItem(QString(value.data()))); } else { item->appendRow(new QStandardItem(QString(value.name()+"="+value.data()))); } break; case GdbMiValue::List: { QStandardItem *in = new QStandardItem(QString(value.name())); item->appendRow(in); for (int i = 0; i < value.childCount(); i++) { QStandardItem *iv = new QStandardItem(QString("[%1]").arg(i)); in->appendRow(iv); GdbMiValueToItem(iv,value.childAt(i)); } break; } case GdbMiValue::Tuple: { QStandardItem *iv = item; if (!value.name().isEmpty()) { iv = new QStandardItem(QString(value.name())); item->appendRow(iv); } foreach (const GdbMiValue &v, value.children()) { GdbMiValueToItem(iv,v); } break; } } }
void GdbDebugger::handleResponse(const QByteArray &buff) { if (buff.isEmpty() || buff == "(gdb) ") return; const char *from = buff.constData(); const char *to = from + buff.size(); const char *inner; int token = -1; // Token is a sequence of numbers. for (inner = from; inner != to; ++inner) if (*inner < '0' || *inner > '9') break; if (from != inner) { token = QByteArray(from, inner - from).toInt(); from = inner; } // Next char decides kind of response. const char c = *from++; switch (c) { case '*': case '+': case '=': { QByteArray asyncClass; for (; from != to; ++from) { const char c = *from; if (!isNameChar(c)) break; asyncClass += *from; } GdbMiValue result; while (from != to) { GdbMiValue data; if (*from != ',') { // happens on archer where we get // 23^running <NL> *running,thread-id="all" <NL> (gdb) result.m_type = GdbMiValue::Tuple; break; } ++from; // skip ',' data.parseResultOrValue(from, to); if (data.isValid()) { //qDebug() << "parsed result:" << data.toString(); result.m_children += data; result.m_type = GdbMiValue::Tuple; } } handleAsyncClass(asyncClass,result); break; } case '~': handleConsoleStream(GdbMiValue::parseCString(from, to)); break; case '@': handleTargetStream(GdbMiValue::parseCString(from, to)); break; case '&': handleLogStream(GdbMiValue::parseCString(from, to)); break; case '^': { GdbResponse response; response.token = token; for (inner = from; inner != to; ++inner) if (*inner < 'a' || *inner > 'z') break; QByteArray resultClass = QByteArray::fromRawData(from, inner - from); if (resultClass == "done") { response.resultClass = GdbResultDone; } else if (resultClass == "running") { response.resultClass = GdbResultRunning; } else if (resultClass == "connected") { response.resultClass = GdbResultConnected; } else if (resultClass == "error") { response.resultClass = GdbResultError; } else if (resultClass == "exit") { response.resultClass = GdbResultExit; } else { response.resultClass = GdbResultUnknown; } from = inner; if (from != to) { if (*from == ',') { ++from; response.data.parseTuple_helper(from, to); response.data.m_type = GdbMiValue::Tuple; response.data.m_name = "data"; } else { // Archer has this. response.data.m_type = GdbMiValue::Tuple; response.data.m_name = "data"; } } if (m_tokenCookieMap.contains(token)) { response.cookie = m_tokenCookieMap.take(token); } handleResultRecord(response); break; } default: { from--; QByteArray out(from,to-from); out.append("\n"); emit debugLog(LiteApi::DebugApplationLog,QString::fromUtf8(out)); break; } } }