diff --git a/src/libs/qtcreatorcdbext/containers.cpp b/src/libs/qtcreatorcdbext/containers.cpp index b3d5088cc51..268ea03e997 100644 --- a/src/libs/qtcreatorcdbext/containers.cpp +++ b/src/libs/qtcreatorcdbext/containers.cpp @@ -277,17 +277,6 @@ static inline AbstractSymbolGroupNodePtrVector qLinkedListChildList(SymbolGroupN return AbstractSymbolGroupNodePtrVector(); } -// Symbol Name/(Expression) of a pointed-to instance ('Foo' at 0x10') ==> '*(Foo *)0x10' -static inline std::string pointedToSymbolName(ULONG64 address, const std::string &type) -{ - std::ostringstream str; - str << "*(" << type; - if (!endsWith(type, '*')) - str << ' '; - str << "*)" << std::showbase << std::hex << address; - return str.str(); -} - /* Helper for array-type containers: * Add a series of "*(innertype *)0x (address + n * size)" fake child symbols. * for a function generating a sequence of addresses. */ @@ -304,7 +293,7 @@ AbstractSymbolGroupNodePtrVector arrayChildList(SymbolGroup *sg, AddressFunc add std::string errorMessage; rc.reserve(count); for (int i = 0; i < count; i++) { - const std::string name = pointedToSymbolName(addressFunc(), innerType); + const std::string name = SymbolGroupValue::pointedToSymbolName(addressFunc(), innerType); if (SymbolGroupNode *child = sg->addSymbol(module, name, std::string(), &errorMessage)) { rc.push_back(ReferenceSymbolGroupNode::createArrayNode(i, child)); } else { @@ -393,7 +382,7 @@ AbstractSymbolGroupNodePtrVector block -= blockArraySize; const ULONG64 blockOffset = offset % dequeSize; const ULONG64 address = blockArray[block] + innerTypeSize * blockOffset; - if (SymbolGroupNode *n = sg->addSymbol(module, pointedToSymbolName(address, innerType), std::string(), &errorMessage)) { + if (SymbolGroupNode *n = sg->addSymbol(module, SymbolGroupValue::pointedToSymbolName(address, innerType), std::string(), &errorMessage)) { rc.push_back(ReferenceSymbolGroupNode::createArrayNode(i, n)); } else { return AbstractSymbolGroupNodePtrVector(); @@ -773,7 +762,7 @@ SymbolGroupValueVector hashBuckets(SymbolGroup *sg, const std::string &hashNodeT // empty array elements. for (const AddressType *p = pointerArray; p < end; p++) { if (*p != ePtr) { - const std::string name = pointedToSymbolName(*p, hashNodeType); + const std::string name = SymbolGroupValue::pointedToSymbolName(*p, hashNodeType); if (SymbolGroupNode *child = sg->addSymbol(module, name, std::string(), &errorMessage)) { rc.push_back(SymbolGroupValue(child, ctx)); } else { @@ -1002,8 +991,8 @@ static inline AbstractSymbolGroupNodePtrVector if (!nodePtr) return AbstractSymbolGroupNodePtrVector(); const ULONG64 keyAddress = nodePtr - payLoad; - const std::string keyExp = pointedToSymbolName(keyAddress, keyType); - const std::string valueExp = pointedToSymbolName(keyAddress + valueOffset, valueType); + const std::string keyExp = SymbolGroupValue::pointedToSymbolName(keyAddress, keyType); + const std::string valueExp = SymbolGroupValue::pointedToSymbolName(keyAddress + valueOffset, valueType); if (SymbolGroupValue::verbose) { DebugPrint() << '#' << i << '/' << count << ' ' << std::hex << ",node=0x" << nodePtr << ',' <asSymbolGroupNode(); + SymbolGroupNode *node = aNode->resolveReference()->asSymbolGroupNode(); if (node == 0) { *errorMessage = msgAssignError(nodeName, value, "Invalid node type"); return false; diff --git a/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp b/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp index 1bcd596ff3d..19c5b40e663 100644 --- a/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp +++ b/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp @@ -377,6 +377,17 @@ std::string SymbolGroupValue::moduleOfType(const std::string &type) return exclPos != std::string::npos ? type.substr(0, exclPos) : std::string(); } +// Symbol Name/(Expression) of a pointed-to instance ('Foo' at 0x10') ==> '*(Foo *)0x10' +std::string SymbolGroupValue::pointedToSymbolName(ULONG64 address, const std::string &type) +{ + std::ostringstream str; + str << "*(" << type; + if (!endsWith(type, '*')) + str << ' '; + str << "*)" << std::showbase << std::hex << address; + return str.str(); +} + /* QtInfo helper: Determine the full name of a Qt Symbol like 'qstrdup' in 'QtCored4'. * as 'QtCored4![namespace::]qstrdup'. In the event someone really uses a different * library prefix or namespaced Qt, this should be found. @@ -1746,14 +1757,45 @@ unsigned dumpSimpleType(SymbolGroupNode *n, const SymbolGroupValueContext &ctx, return rc; } +// Dump of QByteArray: Display as an array of unsigned chars. +static inline std::vector + complexDumpQByteArray(SymbolGroupNode *n, const SymbolGroupValueContext &ctx) +{ + std::vector rc; + const SymbolGroupValue ba(n, ctx); + int size = ba["d"]["size"].intValue(); + ULONG64 address = ba["d"]["data"].pointerValue(); + if (size <= 0 || !address) + return rc; + if (size > 200) + size = 200; + rc.reserve(size); + const std::string charType = "unsigned char"; + std::string errorMessage; + SymbolGroup *sg = n->symbolGroup(); + for (int i = 0; i < size; i++, address++) { + SymbolGroupNode *en = sg->addSymbol(std::string(), SymbolGroupValue::pointedToSymbolName(address, charType), + std::string(), &errorMessage); + if (!en) { + rc.clear(); + return rc; + } + rc.push_back(ReferenceSymbolGroupNode::createArrayNode(i, en)); + } + return rc; +} + std::vector - dumpComplexType(SymbolGroupNode *, int type, void *specialInfo, - const SymbolGroupValueContext &) + dumpComplexType(SymbolGroupNode *n, int type, void *specialInfo, + const SymbolGroupValueContext &ctx) { std::vector rc; if (!(type & KT_HasComplexDumper)) return rc; switch (type) { + case KT_QByteArray: + rc = complexDumpQByteArray(n, ctx); + break; case KT_QWidget: // Special info by simple dumper is the QWidgetPrivate node case KT_QObject: // Special info by simple dumper is the QObjectPrivate node if (specialInfo) { diff --git a/src/libs/qtcreatorcdbext/symbolgroupvalue.h b/src/libs/qtcreatorcdbext/symbolgroupvalue.h index 3375f3e6b78..610a95a8005 100644 --- a/src/libs/qtcreatorcdbext/symbolgroupvalue.h +++ b/src/libs/qtcreatorcdbext/symbolgroupvalue.h @@ -124,6 +124,8 @@ public: static unsigned isPointerType(const std::string &); // add pointer type 'Foo' -> 'Foo *', 'Foo *' -> 'Foo **' static std::string pointerType(const std::string &type); + // Symbol Name/(Expression) of a pointed-to instance ('Foo' at 0x10') ==> '*(Foo *)0x10' + static std::string pointedToSymbolName(ULONG64 address, const std::string &type); // Resolve a type, that is, obtain its module name ('QString'->'QtCored4!QString') // Some operations on types (like adding symbols may fail non-deterministically // or be slow when the module specification is omitted).