diff --git a/share/qtcreator/gdbmacros/dumper.py b/share/qtcreator/gdbmacros/dumper.py index b2029125cbc..0565159b6de 100644 --- a/share/qtcreator/gdbmacros/dumper.py +++ b/share/qtcreator/gdbmacros/dumper.py @@ -103,6 +103,13 @@ def hasInferiorThreadList(): typeCache = {} +class TypeInfo: + def __init__(self, type): + self.size = type.sizeof + self.reported = False + +typeInfoCache = {} + def lookupType(typestring): type = typeCache.get(typestring) #warn("LOOKUP 1: %s -> %s" % (typestring, type)) @@ -331,8 +338,13 @@ class SubItem: #warn("TYPE VALUE: %s" % self.d.currentValue) type = stripClassTag(str(self.d.currentType)) #warn("TYPE: '%s' DEFAULT: '%s'" % (type, self.d.currentChildType)) + if len(type) > 0 and type != self.d.currentChildType: self.d.put('type="%s",' % type) # str(type.unqualified()) ? + if not type in typeInfoCache: + typeObj = lookupType(type) + if not typeObj is None: + typeInfoCache[type] = TypeInfo(typeObj) if not self.d.currentValueEncoding is None: self.d.put('valueencoded="%d",' % self.d.currentValueEncoding) if not self.d.currentValue is None: @@ -1082,7 +1094,14 @@ class FrameCommand(gdb.Command): FrameCommand() def bb(args): - return 'data=[' + Dumper(args).output + ']' + output = 'data=[' + Dumper(args).output + '],typeinfo=[' + for typeName, typeInfo in typeInfoCache.iteritems(): + if not typeInfo.reported: + output += '{name="' + base64.b64encode(typeName) + output += '",size="' + str(typeInfo.size) + '"},' + typeInfo.reported = True + output += ']'; + return output ####################################################################### diff --git a/src/plugins/debugger/gdb/classicgdbengine.cpp b/src/plugins/debugger/gdb/classicgdbengine.cpp index 4004d7b5c52..a20221217f2 100644 --- a/src/plugins/debugger/gdb/classicgdbengine.cpp +++ b/src/plugins/debugger/gdb/classicgdbengine.cpp @@ -1367,7 +1367,7 @@ void GdbEngine::handleVarListChildrenHelperClassic(const GdbMi &item, data.variable = name; setWatchDataType(data, item.findChild("type")); setWatchDataValue(data, item); - setWatchDataAddress(data, item.findChild("addr")); + setWatchDataAddress(data, item.findChild("addr"), GdbMi()); data.setHasChildren(false); insertData(data); } else if (parent.iname.endsWith('.')) { @@ -1391,7 +1391,7 @@ void GdbEngine::handleVarListChildrenHelperClassic(const GdbMi &item, data.sortId = sortId; setWatchDataType(data, item.findChild("type")); setWatchDataValue(data, item); - setWatchDataAddress(data, item.findChild("addr")); + setWatchDataAddress(data, item.findChild("addr"), GdbMi()); setWatchDataChildCount(data, item.findChild("numchild")); if (!watchHandler()->isExpandedIName(data.iname)) data.setChildrenUnneeded(); diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h index 3480b163a2e..ff372289f5f 100644 --- a/src/plugins/debugger/gdb/gdbengine.h +++ b/src/plugins/debugger/gdb/gdbengine.h @@ -660,6 +660,14 @@ private: ////////// View & Data Stuff ////////// void handleStackListArgumentsClassic(const GdbResponse &response); QSet m_processedNames; + struct TypeInfo + { + TypeInfo(uint s = 0) : size(s) {} + + uint size; + }; + + QHash m_typeInfoCache; // // Dumper Management diff --git a/src/plugins/debugger/gdb/pythongdbengine.cpp b/src/plugins/debugger/gdb/pythongdbengine.cpp index 72b535d8a17..af971fad121 100644 --- a/src/plugins/debugger/gdb/pythongdbengine.cpp +++ b/src/plugins/debugger/gdb/pythongdbengine.cpp @@ -158,6 +158,22 @@ void GdbEngine::handleStackFramePython(const GdbResponse &response) } parseWatchData(watchHandler()->expandedINames(), dummy, child, &list); } + const GdbMi typeInfo = all.findChild("typeinfo"); + if (typeInfo.type() == GdbMi::List) { + foreach (const GdbMi &s, typeInfo.children()) { + const GdbMi name = s.findChild("name"); + const GdbMi size = s.findChild("size"); + if (name.isValid() && size.isValid()) + m_typeInfoCache.insert(QByteArray::fromBase64(name.data()), + TypeInfo(size.data().toUInt())); + } + } + for (int i = 0; i != list.size(); ++i) { + const TypeInfo ti = m_typeInfoCache.value(list.at(i).type); + if (ti.size) + list[i].size = ti.size; + } + watchHandler()->insertBulkData(list); //PENDING_DEBUG("AFTER handleStackFrame()"); diff --git a/src/plugins/debugger/watchdata.cpp b/src/plugins/debugger/watchdata.cpp index 81b7e0d49e6..d27f40ef3c3 100644 --- a/src/plugins/debugger/watchdata.cpp +++ b/src/plugins/debugger/watchdata.cpp @@ -125,7 +125,7 @@ WatchData::WatchData() : state(InitialState), editformat(0), address(0), - origAddress(0), + referencingAddress(0), size(0), bitpos(0), bitsize(0), @@ -305,9 +305,9 @@ QString WatchData::toString() const str << "addr=\"0x" << address << doubleQuoteComma; str.setIntegerBase(10); } - if (origAddress) { + if (referencingAddress) { str.setIntegerBase(16); - str << "origaddr=\"0x" << origAddress << doubleQuoteComma; + str << "referencingaddr=\"0x" << referencingAddress << doubleQuoteComma; str.setIntegerBase(10); } if (!exp.isEmpty()) @@ -373,9 +373,9 @@ QString WatchData::toToolTip() const formatToolTipRow(str, tr("Value"), val); formatToolTipRow(str, tr("Object Address"), QString::fromAscii(hexAddress())); - if (origAddress) - formatToolTipRow(str, tr("Original Address"), - QString::fromAscii(hexOrigAddress())); + if (referencingAddress) + formatToolTipRow(str, tr("Referencing Address"), + QString::fromAscii(hexReferencingAddress())); if (size) formatToolTipRow(str, tr("Size"), QString::number(size)); @@ -419,9 +419,9 @@ QByteArray WatchData::hexAddress() const return address ? (QByteArray("0x") + QByteArray::number(address, 16)) : QByteArray(); } -QByteArray WatchData::hexOrigAddress() const +QByteArray WatchData::hexReferencingAddress() const { - return origAddress ? (QByteArray("0x") + QByteArray::number(origAddress, 16)) : QByteArray(); + return referencingAddress ? (QByteArray("0x") + QByteArray::number(referencingAddress, 16)) : QByteArray(); } } // namespace Internal diff --git a/src/plugins/debugger/watchdata.h b/src/plugins/debugger/watchdata.h index d8e835fffb5..3fba8f40de2 100644 --- a/src/plugins/debugger/watchdata.h +++ b/src/plugins/debugger/watchdata.h @@ -113,7 +113,7 @@ public: quint64 coreAddress() const; QByteArray hexAddress() const; - QByteArray hexOrigAddress() const; + QByteArray hexReferencingAddress() const; public: quint64 id; // Token for the engine for internal mapping @@ -129,7 +129,7 @@ public: QByteArray type; // Type for further processing QString displayedType;// Displayed type (optional) quint64 address; // Displayed address - quint64 origAddress; // Original address for dereferenced pointers + quint64 referencingAddress; // Address of the pointer referencing this item (gdb auto-deref) uint size; // Size uint bitpos; // Position within bit fields uint bitsize; // Size in case of bit fields diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp index fd7bd5afbb6..fa41c2e4701 100644 --- a/src/plugins/debugger/watchhandler.cpp +++ b/src/plugins/debugger/watchhandler.cpp @@ -641,9 +641,9 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const case 1: result = removeInitialNamespace(truncateValue( formattedValue(data, itemFormat(data))), ns); - if (data.origAddress) { + if (data.referencingAddress) { result += QLatin1String(" @"); - result += QString::fromLatin1(data.hexOrigAddress()); + result += QString::fromLatin1(data.hexAddress()); } break; case 2: @@ -696,7 +696,7 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const return m_handler->m_expandedINames.contains(data.iname); case LocalsTypeFormatListRole: { - if (data.origAddress || data.type.endsWith('*')) + if (data.referencingAddress || data.type.endsWith('*')) return QStringList() << tr("Raw pointer") << tr("Latin1 string") diff --git a/src/plugins/debugger/watchutils.cpp b/src/plugins/debugger/watchutils.cpp index 5c74fa2c5bb..fe9b889d4b9 100644 --- a/src/plugins/debugger/watchutils.cpp +++ b/src/plugins/debugger/watchutils.cpp @@ -732,26 +732,31 @@ static void setWatchDataExpression(WatchData &data, const GdbMi &mi) data.exp = mi.data(); } -static void setWatchDataAddressHelper(WatchData &data, const QByteArray &addr) +static void setWatchDataAddress(WatchData &data, quint64 address , quint64 origAddress = 0) { - if (addr.startsWith("0x")) { // Item model dumpers pull tricks - data.setHexAddress(addr); + if (origAddress) { // Gdb dumpers reports the dereferenced address as origAddress + data.address = origAddress; + data.referencingAddress = address; } else { - data.dumperFlags = addr; + data.address = address; } if (data.exp.isEmpty() && !data.dumperFlags.startsWith('$')) data.exp = "*(" + gdbQuoteTypes(data.type) + "*)" +data.hexAddress(); } -void setWatchDataAddress(WatchData &data, const GdbMi &mi) +void setWatchDataAddress(WatchData &data, const GdbMi &addressMi, const GdbMi &origAddressMi) { - if (mi.isValid()) - setWatchDataAddressHelper(data, mi.data()); -} - -static void setWatchDataOrigAddress(WatchData &data, const GdbMi &mi) -{ - data.origAddress = mi.data().toULongLong(0, 16); + if (!addressMi.isValid()) + return; + const QByteArray addressBA = addressMi.data(); + if (!addressBA.startsWith("0x")) { // Item model dumpers pull tricks. + data.dumperFlags = addressBA; + return; + } + const quint64 address = addressBA.toULongLong(0, 16); + const quint64 origAddress = origAddressMi.isValid() ? + origAddressMi.data().toULongLong(0, 16) : quint64(0); + setWatchDataAddress(data, address, origAddress); } static void setWatchDataSize(WatchData &data, const GdbMi &mi) @@ -811,8 +816,7 @@ void parseWatchData(const QSet &expandedINames, data.bitsize = mi.data().toInt(); setWatchDataValue(data, item); - setWatchDataAddress(data, item.findChild("addr")); - setWatchDataOrigAddress(data, item.findChild("origaddr")); + setWatchDataAddress(data, item.findChild("addr"), item.findChild("origaddr")); setWatchDataSize(data, item.findChild("size")); setWatchDataExpression(data, item.findChild("exp")); setWatchDataValueEnabled(data, item.findChild("valueenabled")); @@ -851,8 +855,7 @@ void parseWatchData(const QSet &expandedINames, if (!data1.name.isEmpty() && data1.name.at(0).isDigit()) data1.name = _c('[') + data1.name + _c(']'); if (addressStep) { - const QByteArray addr = "0x" + QByteArray::number(addressBase, 16); - setWatchDataAddressHelper(data1, addr); + setWatchDataAddress(data1, addressBase); addressBase += addressStep; } QByteArray key = child.findChild("key").data(); diff --git a/src/plugins/debugger/watchutils.h b/src/plugins/debugger/watchutils.h index 4e59fcc5e40..0182bbbd4c2 100644 --- a/src/plugins/debugger/watchutils.h +++ b/src/plugins/debugger/watchutils.h @@ -119,7 +119,7 @@ void setWatchDataValueToolTip(WatchData &data, const GdbMi &mi, int encoding); void setWatchDataChildCount(WatchData &data, const GdbMi &mi); void setWatchDataValueEnabled(WatchData &data, const GdbMi &mi); -void setWatchDataAddress(WatchData &data, const GdbMi &mi); +void setWatchDataAddress(WatchData &data, const GdbMi &addressMi, const GdbMi &origAddressMi); void setWatchDataType(WatchData &data, const GdbMi &mi); void setWatchDataDisplayedType(WatchData &data, const GdbMi &mi);