Commit 1fad39c9 authored by Friedemann Kleint's avatar Friedemann Kleint

CDB: Fix dumper regression

- Do not deref d-ptr when checking on QVariants of PODS
- Make type/value fixing of dumper results more fine-grained
- Allow children in expandPtrToDumpage (QWidget-Pointers)
- Fix broken size cache (queuePrefix was empty)
- Compile
parent 0cc5f14f
......@@ -1177,7 +1177,7 @@ static void qDumpQAbstractItemModel(QDumper &d)
static void qDumpQByteArray(QDumper &d)
{
qCheckAccess(deref(d.data));
qCheckAccess(deref(d.data)); // is the d-ptr de-referenceable and valid
const QByteArray &ba = *reinterpret_cast<const QByteArray *>(d.data);
if (!ba.isEmpty()) {
......@@ -1461,7 +1461,7 @@ int hashOffset(bool optimizedIntKey, bool forKey, unsigned keySize, unsigned val
static void qDumpQHash(QDumper &d)
{
qCheckAccess(deref(d.data));
qCheckAccess(deref(d.data)); // is the d-ptr de-referenceable and valid
const char *keyType = d.templateParameters[0];
const char *valueType = d.templateParameters[1];
......@@ -1569,7 +1569,7 @@ static void qDumpQHashNode(QDumper &d)
#if USE_QT_GUI
static void qDumpQImage(QDumper &d)
{
qCheckAccess(deref(d.data));
qCheckAccess(deref(d.data)); // is the d-ptr de-referenceable and valid
const QImage &im = *reinterpret_cast<const QImage *>(d.data);
d.beginItem("value");
d.put("(").put(im.width()).put("x").put(im.height()).put(")");
......@@ -1611,7 +1611,7 @@ static void qDumpQImageData(QDumper &d)
static void qDumpQList(QDumper &d)
{
qCheckAccess(deref(d.data));
qCheckAccess(deref(d.data)); // is the d-ptr de-referenceable and valid
// This uses the knowledge that QList<T> has only a single member
// of type union { QListData p; QListData::Data *d; };
......@@ -1691,7 +1691,7 @@ static void qDumpQList(QDumper &d)
static void qDumpQLinkedList(QDumper &d)
{
qCheckAccess(deref(d.data));
qCheckAccess(deref(d.data)); // is the d-ptr de-referenceable and valid
// This uses the knowledge that QLinkedList<T> has only a single member
// of type union { QLinkedListData *d; QLinkedListNode<T> *e; };
const QLinkedListData *ldata =
......@@ -1817,7 +1817,7 @@ static void qDumpQMapNode(QDumper &d)
static void qDumpQMap(QDumper &d)
{
qCheckAccess(deref(d.data));
qCheckAccess(deref(d.data)); // is the d-ptr de-referenceable and valid
QMapData *h = *reinterpret_cast<QMapData *const*>(d.data);
const char *keyType = d.templateParameters[0];
const char *valueType = d.templateParameters[1];
......@@ -1956,7 +1956,7 @@ static void qDumpQModelIndex(QDumper &d)
static void qDumpQObject(QDumper &d)
{
qCheckAccess(deref(d.data));
qCheckAccess(deref(d.data)); // is the d-ptr de-referenceable and valid
const QObject *ob = reinterpret_cast<const QObject *>(d.data);
const QMetaObject *mo = ob->metaObject();
d.putItem("value", ob->objectName());
......@@ -2206,7 +2206,7 @@ static void qDumpQVariant(QDumper &d, const QVariant *v)
static inline void qDumpQVariant(QDumper &d)
{
qCheckAccess(deref(d.data));
qCheckAccess(d.data);
qDumpQVariant(d, reinterpret_cast<const QVariant *>(d.data));
}
......@@ -2832,7 +2832,7 @@ static void qDumpQSharedPointer(QDumper &d)
static void qDumpQString(QDumper &d)
{
//qCheckAccess(deref(d.data));
//qCheckAccess(deref(d.data)); // is the d-ptr de-referenceable and valid
const QString &str = *reinterpret_cast<const QString *>(d.data);
const int size = str.size();
......@@ -2857,7 +2857,7 @@ static void qDumpQString(QDumper &d)
static void qDumpQStringList(QDumper &d)
{
qCheckAccess(deref(d.data));
qCheckAccess(deref(d.data)); // is the d-ptr de-referenceable and valid
const QStringList &list = *reinterpret_cast<const QStringList *>(d.data);
int n = list.size();
if (n < 0)
......@@ -2906,7 +2906,7 @@ static void qDumpQTextCodec(QDumper &d)
static void qDumpQVector(QDumper &d)
{
qCheckAccess(deref(d.data));
qCheckAccess(deref(d.data)); // is the d-ptr de-referenceable and valid
QVectorTypedData<int> *dummy = 0;
const unsigned typeddatasize = (char*)(&dummy->array) - (char*)dummy;
......@@ -3810,7 +3810,11 @@ void *qDumpObjectData440(
d.exp = inbuffer; while (*inbuffer) ++inbuffer; ++inbuffer;
d.innerType = inbuffer; while (*inbuffer) ++inbuffer; ++inbuffer;
d.iname = inbuffer; while (*inbuffer) ++inbuffer; ++inbuffer;
#if 0
qDebug() << "data=" << d.data << "dumpChildren=" << d.dumpChildren
<< " extra=" << d.extraInt[0] << d.extraInt[1] << d.extraInt[2] << d.extraInt[3]
<< d.outerType << d.iname << d.exp << d.iname;
#endif
handleProtocolVersion2and3(d);
}
......
......@@ -227,7 +227,17 @@ static int dumpQMapQStringString()
static int dumpQVariant()
{
QVariant test(QLatin1String("item"));
QVariant test = QLatin1String("item");
prepareInBuffer("QVariant", "local.qvariant", "local.qvariant", "");
qDumpObjectData440(2, 42, testAddress(&test), 1, 0, 0,0 ,0);
fputs(qDumpOutBuffer, stdout);
fputs("\n\n", stdout);
test = QVariant(int(42));
prepareInBuffer("QVariant", "local.qvariant", "local.qvariant", "");
qDumpObjectData440(2, 42, testAddress(&test), 1, 0, 0,0 ,0);
fputs(qDumpOutBuffer, stdout);
fputs("\n\n", stdout);
test = QVariant(double(3.141));
prepareInBuffer("QVariant", "local.qvariant", "local.qvariant", "");
qDumpObjectData440(2, 42, testAddress(&test), 1, 0, 0,0 ,0);
fputs(qDumpOutBuffer, stdout);
......
......@@ -128,21 +128,29 @@ WatchHandleDumperInserter::WatchHandleDumperInserter(WatchHandler *wh,
Q_ASSERT(m_hexNullPattern.isValid());
}
// Prevent recursion of the model by setting value and type
static inline void fixDumperValueAndType(WatchData *wd, const WatchData *source = 0)
{
static const QString unknown = QCoreApplication::translate("CdbStackFrameContext", "<Unknown>");
if (wd->isTypeNeeded() || wd->type.isEmpty()) {
wd->setType(source ? source->type : unknown);
static inline bool fixDumperType(WatchData *wd, const WatchData *source = 0)
{
const bool missing = wd->isTypeNeeded() || wd->type.isEmpty();
if (missing) {
static const QString unknownType = QCoreApplication::translate("CdbStackFrameContext", "<Unknown Type>");
wd->setType(source ? source->type : unknownType);
}
if (wd->isValueNeeded()) {
return missing;
}
static inline bool fixDumperValue(WatchData *wd, const WatchData *source = 0)
{
const bool missing = wd->isValueNeeded();
if (missing) {
if (source && source->isValueKnown()) {
wd->setValue(source->value);
} else {
wd->setValue(unknown);
static const QString unknownValue = QCoreApplication::translate("CdbStackFrameContext", "<Unknown Value>");
wd->setValue(unknownValue);
}
}
return missing;
}
// When querying an item, the queried item is sometimes returned in incomplete form.
......@@ -160,7 +168,8 @@ static inline void fixDumperResult(const WatchData &source,
WatchData &returned = result->front();
if (returned.iname != source.iname)
return;
fixDumperValueAndType(&returned, &source);
fixDumperType(&returned, &source);
fixDumperValue(&returned, &source);
// Indicate owner and known children
returned.source = OwnerDumper;
if (returned.isChildrenKnown() && returned.isHasChildrenKnown() && returned.hasChildren)
......@@ -179,7 +188,9 @@ static inline void fixDumperResult(const WatchData &source,
it->source = OwnerDumper;
if (it->isChildrenKnown() && it->isHasChildrenKnown() && it->hasChildren)
it->source |= CdbStackFrameContext::ChildrenKnownBit;
if (wd.addr.isEmpty() && wd.isSomethingNeeded()) {
// Cannot dump items with missing addresses or missing types
const bool typeFixed = fixDumperType(&wd); // Order of evaluation!
if ((wd.addr.isEmpty() && wd.isSomethingNeeded()) || typeFixed) {
wd.setHasChildren(false);
wd.setAllUnneeded();
} else {
......@@ -188,8 +199,6 @@ static inline void fixDumperResult(const WatchData &source,
if (suppressGrandChildren && (wd.isChildrenNeeded() || wd.isHasChildrenNeeded()))
wd.setHasChildren(false);
}
// <Out of scope value> have sometimes missing types. Kill recursion
fixDumperValueAndType(&wd);
}
if (debugCDBWatchHandling)
debugWatchDataList(*result, "<fixDumperResult");
......@@ -226,7 +235,7 @@ bool WatchHandleDumperInserter::expandPointerToDumpable(const WatchData &wd, QSt
const CdbDumperHelper::DumpResult dr = m_dumper->dumpType(derefedWd, true, &m_dumperResult, errorMessage);
if (dr != CdbDumperHelper::DumpOk)
break;
fixDumperResult(derefedWd, &m_dumperResult, true);
fixDumperResult(derefedWd, &m_dumperResult, false);
// Insert the pointer item with 1 additional child + its dumper results
// Note: formal arguments might already be expanded in the symbol group.
WatchData ptrWd = wd;
......
......@@ -86,7 +86,8 @@ bool CdbStackTraceContext::init(unsigned long frameCount, QString * /*errorMessa
// Convert the DEBUG_STACK_FRAMEs to our StackFrame structure and populate the frames
WCHAR wszBuf[MAX_PATH];
for (ULONG i=0; i < frameCount; ++i) {
StackFrame frame(i);
StackFrame frame;
frame.level = i;
const ULONG64 instructionOffset = m_cdbFrames[i].InstructionOffset;
if (i == 0)
m_instructionOffset = instructionOffset;
......
......@@ -560,7 +560,7 @@ QString QtDumperHelper::toString(bool debug) const
str << "\nSize cache: ";
const SizeCache::const_iterator scend = m_sizeCache.constEnd();
for (SizeCache::const_iterator it = m_sizeCache.constBegin(); it != scend; ++it) {
str << ' ' << it.key() << '=' << it.value();
str << ' ' << it.key() << '=' << it.value() << '\n';
}
str << "\nExpression cache: (" << m_expressionCache.size() << ")\n";
const QMap<QString, QString>::const_iterator excend = m_expressionCache.constEnd();
......@@ -888,6 +888,7 @@ void QtDumperHelper::setQClassPrefixes(const QString &qNamespace)
m_qListPrefix = qClassName(qNamespace, "QList");
m_qLinkedListPrefix = qClassName(qNamespace, "QLinkedList");
m_qVectorPrefix = qClassName(qNamespace, "QVector");
m_qQueuePrefix = qClassName(qNamespace, "QQueue");
}
static inline double getDumperVersion(const GdbMi &contents)
......
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