From 587a2c3a2a2634af31849c715d5086dfae16cc59 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 10 May 2011 18:58:06 +0200 Subject: [PATCH] debugger: enable modification of std::string and QString --- share/qtcreator/gdbmacros/dumper.py | 44 ++++++++++++++++++- share/qtcreator/gdbmacros/gdbmacros.py | 19 ++++++++ src/plugins/debugger/gdb/gdbengine.cpp | 27 +++++++----- src/plugins/debugger/gdb/gdbmi.cpp | 10 +++++ src/plugins/debugger/gdb/gdbmi.h | 1 + src/plugins/debugger/watchutils.cpp | 5 +-- .../gdbdebugger/simple/simple_gdbtest_app.cpp | 3 ++ 7 files changed, 95 insertions(+), 14 deletions(-) diff --git a/share/qtcreator/gdbmacros/dumper.py b/share/qtcreator/gdbmacros/dumper.py index d1f1927520b..7982bf2c159 100644 --- a/share/qtcreator/gdbmacros/dumper.py +++ b/share/qtcreator/gdbmacros/dumper.py @@ -1015,6 +1015,9 @@ qqFormats = {} # This is a cache of all known dumpers. qqDumpers = {} +# This is a cache of all dumpers that support writing. +qqEditable = {} + # This is a cache of the namespace of the currently used Qt version. # FIXME: This is not available on 'bbsetup' time, only at 'bb' time. @@ -1049,16 +1052,55 @@ def bbsetup(): except: pass qqFormats[name] = formats + elif key.startswith("qedit__"): + name = key[7:] + try: + qqEditable[name] = value + except: + pass result = "dumpers=[" #qqNs = qtNamespace() # This is too early for key, value in qqFormats.items(): - result += '{type="%s",formats="%s"},' % (key, value) + if qqEditable.has_key(key): + result += '{type="%s",formats="%s",editable="true"},' % (key, value) + else: + result += '{type="%s",formats="%s"},' % (key, value) result += ']' #result += ',namespace="%s"' % qqNs result += ',hasInferiorThreadList="%s"' % int(hasInferiorThreadList()) return result +####################################################################### +# +# Edit Command +# +####################################################################### + +def bbedit(args): + (type, expr, value) = args.split(" ") + type = base64.b64decode(type) + ns = qtNamespace() + type = type[len(ns):] + type = type.replace("::", "__") + expr = base64.b64decode(expr) + value = base64.b64decode(value) + if qqEditable.has_key(type): + qqEditable[type](expr, value) + warn("EDIT: %s %s %s: " % (type, expr, value)) + +class EditCommand(gdb.Command): + """QtCreator Data Edit Support""" + + def __init__(self): + super(EditCommand, self).__init__("bbedit", gdb.COMMAND_OBSCURE) + + def invoke(self, args, from_tty): + bbedit(args) + +EditCommand() + + ####################################################################### # # FrameCommand diff --git a/share/qtcreator/gdbmacros/gdbmacros.py b/share/qtcreator/gdbmacros/gdbmacros.py index c106c6fce01..0928841d293 100644 --- a/share/qtcreator/gdbmacros/gdbmacros.py +++ b/share/qtcreator/gdbmacros/gdbmacros.py @@ -1354,6 +1354,18 @@ def qdump__QStandardItem(d, item): d.putPlainChildren(item) +def qedit__QString(expr, value): + cmd = "call (%s).resize(%d)" % (expr, len(value)) + gdb.execute(cmd) + d = gdb.parse_and_eval(expr)["d"]["data"] + cmd = "set {short[%d]}%s={" % (len(value), long(d)) + for i in range(len(value)): + if i != 0: + cmd += ',' + cmd += str(ord(value[i])) + cmd += '}' + gdb.execute(cmd) + def qform__QString(): return "Inline,Separate Window" @@ -1925,6 +1937,13 @@ def qdump__std__vector(d, item): p += 1 +def qedit__std__string(expr, value): + cmd = "print (%s).assign(\"%s\")" % (expr, value) + gdb.execute(cmd) + +def qedit__string(expr, value): + qdump__std__string(expr, value) + def qdump__string(d, item): qdump__std__string(d, item) diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 75ecfd4c40c..2549bc87d47 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -2199,11 +2199,9 @@ void GdbEngine::updateBreakpointDataFromOutput(BreakpointId id, const GdbMi &bkp // is called . //qDebug() << "ADDR: " << child.data() << (child.data() == ""); if (child.data().startsWith("0x")) { - response.address = child.data().mid(2).toULongLong(0, 16); + response.address = child.toAddress(); } else { response.extra = child.data(); - if (child.data() == "") - response.multiple = true; } } else if (child.hasName("file")) { file = child.data(); @@ -2320,7 +2318,7 @@ void GdbEngine::handleWatchInsert(const GdbResponse &response) // Mac yields: //>32^done,wpt={number="4",exp="*4355182176"} bresponse.number = wpt.findChild("number").data().toInt(); - bresponse.address = wpt.findChild("exp").data().toULongLong(0, 0); + bresponse.address = wpt.findChild("exp").toAddress(); handler->setResponse(id, bresponse); QTC_ASSERT(!handler->needsChange(id), /**/); handler->notifyBreakpointInsertOk(id); @@ -3147,7 +3145,7 @@ StackFrame GdbEngine::parseStackFrame(const GdbMi &frameMi, int level) frame.function = _(frameMi.findChild("func").data()); frame.from = _(frameMi.findChild("from").data()); frame.line = frameMi.findChild("line").data().toInt(); - frame.address = frameMi.findChild("addr").data().toULongLong(0, 16); + frame.address = frameMi.findChild("addr").toAddress(); frame.usable = QFileInfo(frame.file).isReadable(); return frame; } @@ -3902,13 +3900,22 @@ void GdbEngine::insertData(const WatchData &data0) watchHandler()->insertData(data); } -void GdbEngine::assignValueInDebugger(const WatchData *, +void GdbEngine::assignValueInDebugger(const WatchData *data, const QString &expression, const QVariant &value) { - postCommand("-var-delete assign"); - postCommand("-var-create assign * " + expression.toLatin1()); - postCommand("-var-assign assign " + GdbMi::escapeCString(value.toString().toLatin1()), - Discardable, CB(handleVarAssign)); + if (hasPython()) { + QByteArray cmd = "bbedit " + + data->type.toBase64() + ' ' + + expression.toUtf8().toBase64() + ' ' + + value.toString().toUtf8().toBase64(); + postCommand(cmd, Discardable, CB(handleVarAssign)); + } else { + postCommand("-var-delete assign"); + postCommand("-var-create assign * " + expression.toLatin1()); + postCommand("-var-assign assign " + + GdbMi::escapeCString(value.toString().toLatin1()), + Discardable, CB(handleVarAssign)); + } } void GdbEngine::watchPoint(const QPoint &pnt) diff --git a/src/plugins/debugger/gdb/gdbmi.cpp b/src/plugins/debugger/gdb/gdbmi.cpp index 0f43488103f..e93533e1566 100644 --- a/src/plugins/debugger/gdb/gdbmi.cpp +++ b/src/plugins/debugger/gdb/gdbmi.cpp @@ -373,6 +373,16 @@ GdbMi GdbMi::findChild(const char *name) const return GdbMi(); } +qulonglong GdbMi::toAddress() const +{ + QByteArray ba = m_data; + if (ba.endsWith('L')) + ba.chop(1); + if (ba.startsWith('*') || ba.startsWith('@')) + ba = ba.mid(1); + return ba.toULongLong(0, 16); +} + ////////////////////////////////////////////////////////////////////////////////// // // GdbResponse diff --git a/src/plugins/debugger/gdb/gdbmi.h b/src/plugins/debugger/gdb/gdbmi.h index 73afa0b9e29..09cc4cc98a9 100644 --- a/src/plugins/debugger/gdb/gdbmi.h +++ b/src/plugins/debugger/gdb/gdbmi.h @@ -127,6 +127,7 @@ public: GdbMi findChild(const char *name) const; QByteArray toString(bool multiline = false, int indent = 0) const; + qulonglong toAddress() const; void fromString(const QByteArray &str); void fromStringMultiple(const QByteArray &str); void setStreamOutput(const QByteArray &name, const QByteArray &content); diff --git a/src/plugins/debugger/watchutils.cpp b/src/plugins/debugger/watchutils.cpp index ffada28f063..ed59a6979e7 100644 --- a/src/plugins/debugger/watchutils.cpp +++ b/src/plugins/debugger/watchutils.cpp @@ -752,9 +752,8 @@ void setWatchDataAddress(WatchData &data, const GdbMi &addressMi, const GdbMi &o data.dumperFlags = addressBA; return; } - const quint64 address = addressBA.toULongLong(0, 16); - const quint64 origAddress = origAddressMi.isValid() ? - origAddressMi.data().toULongLong(0, 16) : quint64(0); + const quint64 address = addressMi.toAddress(); + const quint64 origAddress = origAddressMi.toAddress(); setWatchDataAddress(data, address, origAddress); } diff --git a/tests/manual/gdbdebugger/simple/simple_gdbtest_app.cpp b/tests/manual/gdbdebugger/simple/simple_gdbtest_app.cpp index efa787494f6..ffa0836ac83 100644 --- a/tests/manual/gdbdebugger/simple/simple_gdbtest_app.cpp +++ b/tests/manual/gdbdebugger/simple/simple_gdbtest_app.cpp @@ -2564,6 +2564,9 @@ int main(int argc, char *argv[]) { int *x = new int(32); Q_UNUSED(x); + std::string s; + s = "hallo"; + s += "hallo"; testQXmlAttributes(); testQRegExp(); testInlineBreakpoints();