From 7fa7ec98d37ca70356adb95f634a50875c7ad2de Mon Sep 17 00:00:00 2001 From: Friedemann Kleint <Friedemann.Kleint@nokia.com> Date: Wed, 15 Dec 2010 17:01:03 +0100 Subject: [PATCH] Debugger[New CDB]: Do not add begin twice for QList<Large>. Factor out some utilities for hashes. --- src/libs/qtcreatorcdbext/containers.cpp | 93 +++++++++++++------ src/libs/qtcreatorcdbext/knowntype.h | 5 +- src/libs/qtcreatorcdbext/symbolgroupvalue.cpp | 4 + 3 files changed, 74 insertions(+), 28 deletions(-) diff --git a/src/libs/qtcreatorcdbext/containers.cpp b/src/libs/qtcreatorcdbext/containers.cpp index bcb85082923..13d7b7b4526 100644 --- a/src/libs/qtcreatorcdbext/containers.cpp +++ b/src/libs/qtcreatorcdbext/containers.cpp @@ -36,15 +36,19 @@ typedef AbstractSymbolGroupNode::AbstractSymbolGroupNodePtrVector AbstractSymbolGroupNodePtrVector; -// Return size of container or -1 -int containerSize(KnownType kt, SymbolGroupNode *n, const SymbolGroupValueContext &ctx) +// Read a pointer array from debuggee memory (ULONG64/32 according pointer size) +static void *readPointerArray(ULONG64 address, unsigned count, const SymbolGroupValueContext &ctx) { - QTC_TRACE_IN - if ((kt & KT_ContainerType) == 0) - return -1; - const int ct = containerSize(kt, SymbolGroupValue(n, ctx)); - QTC_TRACE_OUT - return ct; + const unsigned pointerSize = SymbolGroupValue::pointerSize(); + const ULONG allocSize = pointerSize * count; + ULONG bytesRead = 0; + void *data = new unsigned char[allocSize]; + const HRESULT hr = ctx.dataspaces->ReadVirtual(address, data, allocSize, &bytesRead); + if (FAILED(hr) || bytesRead != allocSize) { + delete [] data; + return 0; + } + return data; } // Return size from an STL vector (last/first iterators). @@ -70,6 +74,17 @@ static inline int msvcStdVectorSize(const SymbolGroupValue &v) return -1; } +// Return size of container or -1 +int containerSize(KnownType kt, SymbolGroupNode *n, const SymbolGroupValueContext &ctx) +{ + QTC_TRACE_IN + if ((kt & KT_ContainerType) == 0) + return -1; + const int ct = containerSize(kt, SymbolGroupValue(n, ctx)); + QTC_TRACE_OUT + return ct; +} + // Determine size of containers int containerSize(KnownType kt, const SymbolGroupValue &v) { @@ -95,6 +110,10 @@ int containerSize(KnownType kt, const SymbolGroupValue &v) if (const SymbolGroupValue sizeV = v["d"]["size"]) return sizeV.intValue(); break; + case KT_QMultiHash: + if (const SymbolGroupValue qHash = v[unsigned(0)]) + return containerSize(KT_QHash, qHash); + break; case KT_QQueue: if (const SymbolGroupValue qList= v[unsigned(0)]) return containerSize(KT_QList, qList); @@ -202,9 +221,21 @@ 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. */ + template <class AddressFunc> AbstractSymbolGroupNodePtrVector arrayChildList(SymbolGroup *sg, AddressFunc addressFunc, const std::string &innerType, int count) @@ -215,12 +246,8 @@ AbstractSymbolGroupNodePtrVector arrayChildList(SymbolGroup *sg, AddressFunc add std::string errorMessage; rc.reserve(count); for (int i = 0; i < count; i++) { - std::ostringstream str; - str << "*(" << innerType; - if (!endsWith(innerType, '*')) - str << ' '; - str << "*)" << std::showbase << std::hex << addressFunc(); - if (SymbolGroupNode *child = sg->addSymbol(str.str(), std::string(), &errorMessage)) { + const std::string name = pointedToSymbolName(addressFunc(), innerType); + if (SymbolGroupNode *child = sg->addSymbol(name, std::string(), &errorMessage)) { rc.push_back(ReferenceSymbolGroupNode::createArrayNode(i, child)); } else { break; @@ -352,26 +379,30 @@ static inline AbstractSymbolGroupNodePtrVector } if (isLargeOrStatic) { // Retrieve the pointer array ourselves to avoid having to evaluate '*(class foo**)' - const ULONG allocSize = pointerSize * count; - ULONG bytesRead = 0; - void *data = new unsigned char[pointerSize * count]; - const HRESULT hr = v.context().dataspaces->ReadVirtual(arrayAddress + begin * pointerSize, data, allocSize, &bytesRead); - if (FAILED(hr) || bytesRead != allocSize) { + if (void *data = readPointerArray(arrayAddress, count, v.context())) { + // Generate sequence of addresses from pointer array + const AbstractSymbolGroupNodePtrVector rc = pointerSize == 8 ? + arrayChildList(v.node()->symbolGroup(), AddressArraySequence<ULONG64>(reinterpret_cast<const ULONG64 *>(data)), innerType, count) : + arrayChildList(v.node()->symbolGroup(), AddressArraySequence<ULONG32>(reinterpret_cast<const ULONG32 *>(data)), innerType, count); delete [] data; - return AbstractSymbolGroupNodePtrVector(); + return rc; } - // Generate sequence of addresses from pointer array - const AbstractSymbolGroupNodePtrVector rc = pointerSize == 8 ? - arrayChildList(v.node()->symbolGroup(), AddressArraySequence<ULONG64>(reinterpret_cast<const ULONG64 *>(data)), innerType, count) : - arrayChildList(v.node()->symbolGroup(), AddressArraySequence<ULONG32>(reinterpret_cast<const ULONG32 *>(data)), innerType, count); - delete [] data; - return rc; + return AbstractSymbolGroupNodePtrVector(); } return arrayChildList(v.node()->symbolGroup(), AddressSequence(arrayAddress, pointerSize), innerType, count); } +static inline AbstractSymbolGroupNodePtrVector + qHashChildList(const SymbolGroupValue &, int count) +{ + AbstractSymbolGroupNodePtrVector rc; + if (!count) + return rc; + return rc; +} + AbstractSymbolGroupNodePtrVector containerChildren(SymbolGroupNode *node, int type, int size, const SymbolGroupValueContext &ctx) { @@ -396,6 +427,16 @@ AbstractSymbolGroupNodePtrVector containerChildren(SymbolGroupNode *node, int ty if (const SymbolGroupValue qVector = SymbolGroupValue(node, ctx)[unsigned(0)]) return qVectorChildList(qVector.node(), size, ctx); break; + case KT_QHash: + return qHashChildList(SymbolGroupValue(node, ctx), size); + case KT_QMultiMap: + if (const SymbolGroupValue hash = SymbolGroupValue(node, ctx)[unsigned(0)]) + return qHashChildList(hash, size); + break; + case KT_QSet: + if (const SymbolGroupValue qHash = SymbolGroupValue(node, ctx)["q_hash"]) + return qHashChildList(qHash, size); + break; case KT_QStringList: if (const SymbolGroupValue qList = SymbolGroupValue(node, ctx)[unsigned(0)]) return qListChildList(qList, size); diff --git a/src/libs/qtcreatorcdbext/knowntype.h b/src/libs/qtcreatorcdbext/knowntype.h index f70dea00030..c8062fb46c8 100644 --- a/src/libs/qtcreatorcdbext/knowntype.h +++ b/src/libs/qtcreatorcdbext/knowntype.h @@ -138,8 +138,9 @@ enum KnownType KT_QQueue = KT_Qt_Type + KT_ContainerType + 6, KT_QSet = KT_Qt_Type + KT_ContainerType + 7, KT_QHash = KT_Qt_Type + KT_ContainerType + 8, - KT_QMap = KT_Qt_Type + KT_ContainerType + 9, - KT_QMultiMap = KT_Qt_Type + KT_ContainerType + 10, + KT_QMultiHash = KT_Qt_Type + KT_ContainerType + 9, + KT_QMap = KT_Qt_Type + KT_ContainerType + 10, + KT_QMultiMap = KT_Qt_Type + KT_ContainerType + 11, // STL KT_StdString = KT_STL_Type + 1, KT_StdWString = KT_STL_Type + 2, diff --git a/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp b/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp index c13f962c4bd..fdc9dceb30f 100644 --- a/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp +++ b/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp @@ -456,6 +456,10 @@ static KnownType knownTypeHelper(const std::string &type, std::string::size_type if (!type.compare(qPos, 9, "QMultiMap")) return KT_QMultiMap; break; + case 10: + if (!type.compare(qPos, 10, "QMultiHash")) + return KT_QMultiHash; + break; case 11: if (!type.compare(qPos, 11, "QLinkedList")) return KT_QLinkedList; -- GitLab