forked from qt-creator/qt-creator
Debugger[CDB]: Dump QByteArray as array of unsigned chars.
Fix assignment to reference nodes (QByteArray field elements).
This commit is contained in:
@@ -277,17 +277,6 @@ static inline AbstractSymbolGroupNodePtrVector qLinkedListChildList(SymbolGroupN
|
|||||||
return AbstractSymbolGroupNodePtrVector();
|
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:
|
/* Helper for array-type containers:
|
||||||
* Add a series of "*(innertype *)0x (address + n * size)" fake child symbols.
|
* Add a series of "*(innertype *)0x (address + n * size)" fake child symbols.
|
||||||
* for a function generating a sequence of addresses. */
|
* for a function generating a sequence of addresses. */
|
||||||
@@ -304,7 +293,7 @@ AbstractSymbolGroupNodePtrVector arrayChildList(SymbolGroup *sg, AddressFunc add
|
|||||||
std::string errorMessage;
|
std::string errorMessage;
|
||||||
rc.reserve(count);
|
rc.reserve(count);
|
||||||
for (int i = 0; i < count; i++) {
|
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)) {
|
if (SymbolGroupNode *child = sg->addSymbol(module, name, std::string(), &errorMessage)) {
|
||||||
rc.push_back(ReferenceSymbolGroupNode::createArrayNode(i, child));
|
rc.push_back(ReferenceSymbolGroupNode::createArrayNode(i, child));
|
||||||
} else {
|
} else {
|
||||||
@@ -393,7 +382,7 @@ AbstractSymbolGroupNodePtrVector
|
|||||||
block -= blockArraySize;
|
block -= blockArraySize;
|
||||||
const ULONG64 blockOffset = offset % dequeSize;
|
const ULONG64 blockOffset = offset % dequeSize;
|
||||||
const ULONG64 address = blockArray[block] + innerTypeSize * blockOffset;
|
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));
|
rc.push_back(ReferenceSymbolGroupNode::createArrayNode(i, n));
|
||||||
} else {
|
} else {
|
||||||
return AbstractSymbolGroupNodePtrVector();
|
return AbstractSymbolGroupNodePtrVector();
|
||||||
@@ -773,7 +762,7 @@ SymbolGroupValueVector hashBuckets(SymbolGroup *sg, const std::string &hashNodeT
|
|||||||
// empty array elements.
|
// empty array elements.
|
||||||
for (const AddressType *p = pointerArray; p < end; p++) {
|
for (const AddressType *p = pointerArray; p < end; p++) {
|
||||||
if (*p != ePtr) {
|
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)) {
|
if (SymbolGroupNode *child = sg->addSymbol(module, name, std::string(), &errorMessage)) {
|
||||||
rc.push_back(SymbolGroupValue(child, ctx));
|
rc.push_back(SymbolGroupValue(child, ctx));
|
||||||
} else {
|
} else {
|
||||||
@@ -1002,8 +991,8 @@ static inline AbstractSymbolGroupNodePtrVector
|
|||||||
if (!nodePtr)
|
if (!nodePtr)
|
||||||
return AbstractSymbolGroupNodePtrVector();
|
return AbstractSymbolGroupNodePtrVector();
|
||||||
const ULONG64 keyAddress = nodePtr - payLoad;
|
const ULONG64 keyAddress = nodePtr - payLoad;
|
||||||
const std::string keyExp = pointedToSymbolName(keyAddress, keyType);
|
const std::string keyExp = SymbolGroupValue::pointedToSymbolName(keyAddress, keyType);
|
||||||
const std::string valueExp = pointedToSymbolName(keyAddress + valueOffset, valueType);
|
const std::string valueExp = SymbolGroupValue::pointedToSymbolName(keyAddress + valueOffset, valueType);
|
||||||
if (SymbolGroupValue::verbose) {
|
if (SymbolGroupValue::verbose) {
|
||||||
DebugPrint() << '#' << i << '/' << count << ' ' << std::hex << ",node=0x" << nodePtr <<
|
DebugPrint() << '#' << i << '/' << count << ' ' << std::hex << ",node=0x" << nodePtr <<
|
||||||
',' <<keyExp << ',' << valueExp;
|
',' <<keyExp << ',' << valueExp;
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ enum KnownType
|
|||||||
KT_PointerType = KT_POD_Type + 7, // pointer to class or complex type
|
KT_PointerType = KT_POD_Type + 7, // pointer to class or complex type
|
||||||
// Types: Qt Basic
|
// Types: Qt Basic
|
||||||
KT_QChar = KT_Qt_Type + KT_Qt_MovableType + KT_HasSimpleDumper + 1,
|
KT_QChar = KT_Qt_Type + KT_Qt_MovableType + KT_HasSimpleDumper + 1,
|
||||||
KT_QByteArray = KT_Qt_Type + KT_Qt_MovableType + KT_HasSimpleDumper + 2,
|
KT_QByteArray = KT_Qt_Type + KT_Qt_MovableType + KT_HasComplexDumper + KT_HasSimpleDumper + 2,
|
||||||
KT_QString = KT_Qt_Type + KT_Qt_MovableType + KT_HasSimpleDumper + 3,
|
KT_QString = KT_Qt_Type + KT_Qt_MovableType + KT_HasSimpleDumper + 3,
|
||||||
KT_QColor = KT_Qt_Type + KT_HasSimpleDumper + 4,
|
KT_QColor = KT_Qt_Type + KT_HasSimpleDumper + 4,
|
||||||
KT_QFlags = KT_Qt_Type + KT_HasSimpleDumper + 5,
|
KT_QFlags = KT_Qt_Type + KT_HasSimpleDumper + 5,
|
||||||
|
|||||||
@@ -447,7 +447,7 @@ bool SymbolGroup::assign(const std::string &nodeName, const std::string &value,
|
|||||||
*errorMessage = msgAssignError(nodeName, value, "No such node");
|
*errorMessage = msgAssignError(nodeName, value, "No such node");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
SymbolGroupNode *node = aNode->asSymbolGroupNode();
|
SymbolGroupNode *node = aNode->resolveReference()->asSymbolGroupNode();
|
||||||
if (node == 0) {
|
if (node == 0) {
|
||||||
*errorMessage = msgAssignError(nodeName, value, "Invalid node type");
|
*errorMessage = msgAssignError(nodeName, value, "Invalid node type");
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -377,6 +377,17 @@ std::string SymbolGroupValue::moduleOfType(const std::string &type)
|
|||||||
return exclPos != std::string::npos ? type.substr(0, exclPos) : std::string();
|
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'.
|
/* 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
|
* as 'QtCored4![namespace::]qstrdup'. In the event someone really uses a different
|
||||||
* library prefix or namespaced Qt, this should be found.
|
* library prefix or namespaced Qt, this should be found.
|
||||||
@@ -1746,14 +1757,45 @@ unsigned dumpSimpleType(SymbolGroupNode *n, const SymbolGroupValueContext &ctx,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dump of QByteArray: Display as an array of unsigned chars.
|
||||||
|
static inline std::vector<AbstractSymbolGroupNode *>
|
||||||
|
complexDumpQByteArray(SymbolGroupNode *n, const SymbolGroupValueContext &ctx)
|
||||||
|
{
|
||||||
|
std::vector<AbstractSymbolGroupNode *> 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<AbstractSymbolGroupNode *>
|
std::vector<AbstractSymbolGroupNode *>
|
||||||
dumpComplexType(SymbolGroupNode *, int type, void *specialInfo,
|
dumpComplexType(SymbolGroupNode *n, int type, void *specialInfo,
|
||||||
const SymbolGroupValueContext &)
|
const SymbolGroupValueContext &ctx)
|
||||||
{
|
{
|
||||||
std::vector<AbstractSymbolGroupNode *> rc;
|
std::vector<AbstractSymbolGroupNode *> rc;
|
||||||
if (!(type & KT_HasComplexDumper))
|
if (!(type & KT_HasComplexDumper))
|
||||||
return rc;
|
return rc;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
case KT_QByteArray:
|
||||||
|
rc = complexDumpQByteArray(n, ctx);
|
||||||
|
break;
|
||||||
case KT_QWidget: // Special info by simple dumper is the QWidgetPrivate node
|
case KT_QWidget: // Special info by simple dumper is the QWidgetPrivate node
|
||||||
case KT_QObject: // Special info by simple dumper is the QObjectPrivate node
|
case KT_QObject: // Special info by simple dumper is the QObjectPrivate node
|
||||||
if (specialInfo) {
|
if (specialInfo) {
|
||||||
|
|||||||
@@ -124,6 +124,8 @@ public:
|
|||||||
static unsigned isPointerType(const std::string &);
|
static unsigned isPointerType(const std::string &);
|
||||||
// add pointer type 'Foo' -> 'Foo *', 'Foo *' -> 'Foo **'
|
// add pointer type 'Foo' -> 'Foo *', 'Foo *' -> 'Foo **'
|
||||||
static std::string pointerType(const std::string &type);
|
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')
|
// Resolve a type, that is, obtain its module name ('QString'->'QtCored4!QString')
|
||||||
// Some operations on types (like adding symbols may fail non-deterministically
|
// Some operations on types (like adding symbols may fail non-deterministically
|
||||||
// or be slow when the module specification is omitted).
|
// or be slow when the module specification is omitted).
|
||||||
|
|||||||
Reference in New Issue
Block a user