Commit 7fa7ec98 authored by Friedemann Kleint's avatar Friedemann Kleint
Browse files

Debugger[New CDB]: Do not add begin twice for QList<Large>.

Factor out some utilities for hashes.
parent 6723f92a
......@@ -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);
......
......@@ -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,
......
......@@ -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;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment