Commit caa164a4 authored by Friedemann Kleint's avatar Friedemann Kleint

CDB: Use GdbMi parser for everything.

..preparing recursive dumpers. Add recursive parser to
watchutils.cpp Use insertBulkData() within CDB, add sizeof()
information for some Qt containers in order to be able to
dump QList<QList<KnownType> > .
parent de73a6d6
......@@ -37,6 +37,7 @@
#include <QtCore/QHash>
#include <QtCore/QLinkedList>
#include <QtCore/QList>
#include <QtCore/QQueue>
#include <QtCore/QLocale>
#include <QtCore/QMap>
#include <QtCore/QMetaEnum>
......@@ -3622,6 +3623,10 @@ static inline void dumpSizes(QDumper &d)
sizeMap.insert(sizeof(QStringList), NS"QStringList");
#ifndef QT_BOOTSTRAPPED
sizeMap.insert(sizeof(QObject), NS"QObject");
sizeMap.insert(sizeof(QList<int>), NS"QList<int>");
sizeMap.insert(sizeof(QLinkedList<int>), NS"QLinkedList<int>");
sizeMap.insert(sizeof(QVector<int>), NS"QVector<int>");
sizeMap.insert(sizeof(QQueue<int>), NS"QQueue<int>");
#endif
#if USE_QT_GUI
sizeMap.insert(sizeof(QWidget), NS"QWidget");
......
......@@ -28,6 +28,7 @@
**************************************************************************/
#include <QtCore/QStringList>
#include <QtCore/QLinkedList>
#include <QtCore/QVector>
#include <QtCore/QSharedPointer>
#include <QtCore/QTimer>
......@@ -138,6 +139,16 @@ static int dumpQIntList()
return 0;
}
static int dumpQIntLinkedList()
{
QLinkedList<int> test = QLinkedList<int>() << 1 << 2;
prepareInBuffer("QLinkedList", "local.qintlinkedlist", "local.qlinkedintlist", "int");
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(int), 0, 0, 0);
fputs(qDumpOutBuffer, stdout);
fputc('\n', stdout);
return 0;
}
static int dumpQIntVector()
{
QVector<int> test = QVector<int>() << 42 << 43;
......@@ -176,6 +187,20 @@ static int dumpQMapIntString()
return 0;
}
static int dumpQMapQStringString()
{
QMap<QString,QString> test;
QMapNode<QString,QString> mapNode;
const int valueOffset = (char*)&(mapNode.value) - (char*)&mapNode;
test.insert(QLatin1String("42s"), QLatin1String("fortytwo"));
test.insert(QLatin1String("423"), QLatin1String("fortytree"));
prepareInBuffer("QMap", "local.qmapqstringqstring", "local.qmapqstringqstring", "QString@QString");
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(QString), sizeof(QString), sizeof(mapNode), valueOffset);
fputs(qDumpOutBuffer, stdout);
fputc('\n', stdout);
return 0;
}
static int dumpQVariant()
{
QVariant test(QLatin1String("item"));
......@@ -417,9 +442,11 @@ static TypeDumpFunctionMap registerTypes()
rc.insert("QSharedPointer<QString>", dumpQSharedPointerQString);
rc.insert("QStringList", dumpQStringList);
rc.insert("QList<int>", dumpQIntList);
rc.insert("QLinkedList<int>", dumpQIntLinkedList);
rc.insert("QList<std::string>", dumpStdStringQList);
rc.insert("QVector<int>", dumpQIntVector);
rc.insert("QMap<int,QString>", dumpQMapIntString);
rc.insert("QMap<QString,QString>", dumpQMapQStringString);
rc.insert("QMap<int,int>", dumpQMapIntInt);
rc.insert("string", dumpStdString);
rc.insert("wstring", dumpStdWString);
......
......@@ -554,7 +554,7 @@ static inline QString msgNotHandled(const QString &type)
return QString::fromLatin1("The type '%1' is not handled.").arg(type);
}
CdbDumperHelper::DumpResult CdbDumperHelper::dumpType(const WatchData &wd, bool dumpChildren, int source,
CdbDumperHelper::DumpResult CdbDumperHelper::dumpType(const WatchData &wd, bool dumpChildren,
QList<WatchData> *result, QString *errorMessage)
{
// Check failure cache and supported types
......@@ -593,7 +593,7 @@ CdbDumperHelper::DumpResult CdbDumperHelper::dumpType(const WatchData &wd, bool
arg(wd.name, wd.exp, wd.type);
m_access->showDebuggerOutput(LogMisc, message);
const DumpExecuteResult der = executeDump(wd, td, dumpChildren, source, result, errorMessage);
const DumpExecuteResult der = executeDump(wd, td, dumpChildren, result, errorMessage);
if (der == DumpExecuteOk)
return DumpOk;
// Cache types that fail due to complicated template size expressions.
......@@ -610,7 +610,7 @@ CdbDumperHelper::DumpResult CdbDumperHelper::dumpType(const WatchData &wd, bool
CdbDumperHelper::DumpExecuteResult
CdbDumperHelper::executeDump(const WatchData &wd,
const QtDumperHelper::TypeData& td, bool dumpChildren, int source,
const QtDumperHelper::TypeData& td, bool dumpChildren,
QList<WatchData> *result, QString *errorMessage)
{
QByteArray inBuffer;
......@@ -658,12 +658,10 @@ CdbDumperHelper::DumpExecuteResult
}
if (!callDumper(callCmd, inBuffer, &outputData, true, errorMessage))
return DumpExecuteCallFailed;
QtDumperResult dumpResult;
if (!QtDumperHelper::parseValue(outputData, &dumpResult)) {
if (!QtDumperHelper::parseValue(outputData, result)) {
*errorMessage = QLatin1String("Parsing of value query output failed.");
return DumpExecuteCallFailed;
}
*result = dumpResult.toWatchData(source);
return DumpExecuteOk;
}
......
......@@ -89,7 +89,7 @@ public:
// Dump a WatchData item.
enum DumpResult { DumpNotHandled, DumpOk, DumpError };
DumpResult dumpType(const WatchData &d, bool dumpChildren, int source,
DumpResult dumpType(const WatchData &d, bool dumpChildren,
QList<WatchData> *result, QString *errorMessage);
inline CdbComInterfaces *comInterfaces() const { return m_cif; }
......@@ -113,7 +113,7 @@ private:
DumpComplexExpressionEncountered,
DumpExecuteCallFailed };
DumpExecuteResult executeDump(const WatchData &wd,
const QtDumperHelper::TypeData& td, bool dumpChildren, int source,
const QtDumperHelper::TypeData& td, bool dumpChildren,
QList<WatchData> *result, QString *errorMessage);
static bool writeToDebuggee(CIDebugDataSpaces *ds, const QByteArray &buffer, quint64 address, QString *errorMessage);
......
......@@ -156,7 +156,7 @@ bool WatchHandleDumperInserter::expandPointerToDumpable(const WatchData &wd, QSt
derefedWd.name = QString(QLatin1Char('*'));
derefedWd.iname = wd.iname + QLatin1String(".*");
derefedWd.source = OwnerDumper | CdbStackFrameContext::ChildrenKnownBit;
const CdbDumperHelper::DumpResult dr = m_dumper->dumpType(derefedWd, true, OwnerDumper, &m_dumperResult, errorMessage);
const CdbDumperHelper::DumpResult dr = m_dumper->dumpType(derefedWd, true, &m_dumperResult, errorMessage);
if (dr != CdbDumperHelper::DumpOk)
break;
// Insert the pointer item with 1 additional child + its dumper results
......@@ -166,8 +166,7 @@ bool WatchHandleDumperInserter::expandPointerToDumpable(const WatchData &wd, QSt
ptrWd.setHasChildren(true);
ptrWd.setChildrenUnneeded();
m_wh->insertData(ptrWd);
foreach(const WatchData &dwd, m_dumperResult)
m_wh->insertData(dwd);
m_wh->insertBulkData(m_dumperResult);
handled = true;
} while (false);
if (debugCDBWatchHandling)
......@@ -184,7 +183,8 @@ static inline void fixDumperResult(const WatchData &source,
const int size = result->size();
if (!size)
return;
// debugWatchDataList(*result, suppressGrandChildren ? ">fixDumperResult suppressGrandChildren" : ">fixDumperResult");
if (debugCDBWatchHandling)
debugWatchDataList(*result, suppressGrandChildren ? ">fixDumperResult suppressGrandChildren" : ">fixDumperResult");
WatchData &returned = result->front();
if (returned.iname != source.iname)
return;
......@@ -198,6 +198,10 @@ static inline void fixDumperResult(const WatchData &source,
returned.setValue(QCoreApplication::translate("CdbStackFrameContext", "<Unknown>"));
}
}
// Indicate owner and known children
returned.source = OwnerDumper;
if (returned.isChildrenKnown() && returned.isHasChildrenKnown() && returned.hasChildren)
returned.source |= CdbStackFrameContext::ChildrenKnownBit;
if (size == 1)
return;
// If the model queries the expanding item by pretending childrenNeeded=1,
......@@ -208,6 +212,10 @@ static inline void fixDumperResult(const WatchData &source,
QList<WatchData>::iterator it = result->begin();
for (++it; it != wend; ++it) {
WatchData &wd = *it;
// Indicate owner and known children
it->source = OwnerDumper;
if (it->isChildrenKnown() && it->isHasChildrenKnown() && it->hasChildren)
it->source |= CdbStackFrameContext::ChildrenKnownBit;
if (wd.addr.isEmpty() && wd.isSomethingNeeded()) {
wd.setHasChildren(false);
wd.setAllUnneeded();
......@@ -218,7 +226,8 @@ static inline void fixDumperResult(const WatchData &source,
wd.setHasChildren(false);
}
}
// debugWatchDataList(*result, "<fixDumperResult");
if (debugCDBWatchHandling)
debugWatchDataList(*result, "<fixDumperResult");
}
WatchHandleDumperInserter &WatchHandleDumperInserter::operator=(WatchData &wd)
......@@ -238,15 +247,14 @@ WatchHandleDumperInserter &WatchHandleDumperInserter::operator=(WatchData &wd)
return *this;
}
// Try library dumpers.
switch (m_dumper->dumpType(wd, true, OwnerDumper, &m_dumperResult, &errorMessage)) {
switch (m_dumper->dumpType(wd, true, &m_dumperResult, &errorMessage)) {
case CdbDumperHelper::DumpOk:
if (debugCDBWatchHandling)
qDebug() << "dumper triggered";
// Dumpers omit types for complicated templates
fixDumperResult(wd, &m_dumperResult, false);
// Discard the original item and insert the dumper results
foreach(const WatchData &dwd, m_dumperResult)
m_wh->insertData(dwd);
m_wh->insertBulkData(m_dumperResult);
// Nasty side effect: Modify owner for the ignore predicate
wd.source = OwnerDumper;
break;
......@@ -325,13 +333,12 @@ bool CdbStackFrameContext::completeData(const WatchData &incompleteLocal,
return true;
}
QList<WatchData> dumperResult;
const CdbDumperHelper::DumpResult dr = m_dumper->dumpType(incompleteLocal, true, OwnerDumper, &dumperResult, errorMessage);
const CdbDumperHelper::DumpResult dr = m_dumper->dumpType(incompleteLocal, true, &dumperResult, errorMessage);
if (dr == CdbDumperHelper::DumpOk) {
// Hack to stop endless model recursion
const bool suppressGrandChildren = !wh->isExpandedIName(incompleteLocal.iname);
fixDumperResult(incompleteLocal, &dumperResult, suppressGrandChildren);
foreach(const WatchData &dwd, dumperResult)
wh->insertData(dwd);
wh->insertBulkData(dumperResult);
} else {
const QString msg = QString::fromLatin1("Unable to further expand dumper watch data: '%1' (%2): %3/%4").arg(incompleteLocal.name, incompleteLocal.type).arg(int(dr)).arg(*errorMessage);
qWarning("%s", qPrintable(msg));
......@@ -372,7 +379,7 @@ bool CdbStackFrameContext::editorToolTip(const QString &iname,
// Check dumpers. Should actually be just one item.
if (m_useDumpers && m_dumper->state() != CdbDumperHelper::Disabled) {
QList<WatchData> result;
if (CdbDumperHelper::DumpOk == m_dumper->dumpType(wd, false, OwnerDumper, &result, errorMessage)) {
if (CdbDumperHelper::DumpOk == m_dumper->dumpType(wd, false, &result, errorMessage)) {
foreach (const WatchData &dwd, result) {
if (!value->isEmpty())
value->append(QLatin1Char('\n'));
......
......@@ -227,6 +227,8 @@ QString WatchData::toString() const
str << QLatin1Char('{');
if (!iname.isEmpty())
str << "iname=\"" << iname << doubleQuoteComma;
if (!name.isEmpty() && name != iname)
str << "name=\"" << name << doubleQuoteComma;
if (!addr.isEmpty())
str << "addr=\"" << addr << doubleQuoteComma;
if (!exp.isEmpty())
......
This diff is collapsed.
......@@ -90,49 +90,6 @@ QString cppExpressionAt(TextEditor::ITextEditor *editor, int pos,
// Decode string data as returned by the dumper helpers.
QString decodeData(const QByteArray &baIn, int encoding);
// Result of a dumper call.
struct QtDumperResult
{
struct Child {
Child();
int keyEncoded;
int valueEncoded;
int childCount;
bool valueEnabled;
QString name;
QString address;
QString exp;
QString type;
QString displayedType;
QByteArray key;
bool valueEncountered;
QByteArray value;
};
QtDumperResult();
void clear();
QList<WatchData> toWatchData(int source = 0) const;
QString iname;
QString address;
QString addressInfo; // "<synthetic>" or such, in the 2nd adress field.
QString type;
QString extra;
QString displayedType;
bool valueEncountered;
QByteArray value;
int valueEncoded;
bool valueEnabled;
int childCount;
bool internal;
QString childType;
int childChildCount;
QList <Child> children;
};
QDebug operator<<(QDebug in, const QtDumperResult &d);
/* Attempt to put common code of the dumper handling into a helper
* class.
* "Custom dumper" is a library compiled against the current
......@@ -210,7 +167,7 @@ public:
// Parse the value response (protocol 2) from debuggee buffer.
// 'data' excludes the leading indicator character.
static bool parseValue(const char *data, QtDumperResult *r);
static bool parseValue(const char *data, QList<WatchData> *l);
// What kind of debugger expressions are required to dump that type.
// A debugger with restricted expression syntax can handle
......@@ -245,7 +202,9 @@ private:
// They are not complete (std::allocator<X>).
enum SpecialSizeType { IntSize, PointerSize, StdAllocatorSize,
QSharedPointerSize, QSharedDataPointerSize,
QWeakPointerSize, QPointerSize, SpecialSizeCount };
QWeakPointerSize, QPointerSize,
QListSize, QLinkedListSize, QVectorSize, QQueueSize,
SpecialSizeCount };
// Resolve name to enumeration or SpecialSizeCount (invalid)
SpecialSizeType specialSizeType(const QString &t) const;
......@@ -263,6 +222,10 @@ private:
QString m_qSharedPointerPrefix;
QString m_qSharedDataPointerPrefix;
QString m_qWeakPointerPrefix;
QString m_qListPrefix;
QString m_qLinkedListPrefix;
QString m_qVectorPrefix;
QString m_qQueuePrefix;
};
QDebug operator<<(QDebug in, const QtDumperHelper::TypeData &d);
......
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