forked from qt-creator/qt-creator
Debugger: Use Gdbmi parser in CDB for parsing of protocol 1
Change dumper protocol 1 output not to contain type names as hash keys (might contain blanks), use lists instead. Start fixing autotests for 4.6.
This commit is contained in:
@@ -3572,15 +3572,15 @@ template <class Key, class Value>
|
||||
{
|
||||
QMapNode<Key, Value> *mn = 0;
|
||||
const int valueOffset = (char *)&(mn->value) - (char*)mn;
|
||||
d.put("(size_t)&(('"NS"QMapNode<");
|
||||
d.put("[\"(size_t)&(('"NS"QMapNode<");
|
||||
d.put(keyType);
|
||||
d.put(',');
|
||||
d.put(valueType);
|
||||
if (valueType[qstrlen(valueType) - 1] == '>')
|
||||
d.put(' ');
|
||||
d.put(">'*)0)->value=\"");
|
||||
d.put(">'*)0)->value\",\"");
|
||||
d.put(valueOffset);
|
||||
d.put('"');
|
||||
d.put("\"]");
|
||||
return d;
|
||||
}
|
||||
|
||||
@@ -3595,20 +3595,82 @@ template <class Key, class Value>
|
||||
{
|
||||
std::pair<Key, Value> *p = 0;
|
||||
const int valueOffset = (char *)&(p->second) - (char*)p;
|
||||
d.put("(size_t)&(('std::pair<");
|
||||
d.put("[\"(size_t)&(('std::pair<");
|
||||
d.put(keyType);
|
||||
d.put(" const ,");
|
||||
d.put(valueType);
|
||||
if (valueType[qstrlen(valueType) - 1] == '>')
|
||||
d.put(' ');
|
||||
d.put(">'*)0)->second=\"");
|
||||
d.put(">'*)0)->second\",\"");
|
||||
d.put(valueOffset);
|
||||
d.put('"');
|
||||
d.put("\"]");
|
||||
return d;
|
||||
}
|
||||
|
||||
#endif // Q_CC_MSVC
|
||||
|
||||
// Dump out sizes for CDB
|
||||
static inline void dumpSizes(QDumper &d)
|
||||
{
|
||||
// Sort by sizes
|
||||
typedef QMultiMap<size_t, const char *> SizeMap;
|
||||
SizeMap sizeMap;
|
||||
|
||||
sizeMap.insert(sizeof(int), "int");
|
||||
sizeMap.insert(sizeof(char*), "char*");
|
||||
sizeMap.insert(sizeof(QString), NS"QString");
|
||||
sizeMap.insert(sizeof(QStringList), NS"QStringList");
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
sizeMap.insert(sizeof(QObject), NS"QObject");
|
||||
#endif
|
||||
#if USE_QT_GUI
|
||||
sizeMap.insert(sizeof(QWidget), NS"QWidget");
|
||||
#endif
|
||||
#ifdef Q_OS_WIN
|
||||
sizeMap.insert(sizeof(std::string), "string");
|
||||
sizeMap.insert(sizeof(std::wstring), "wstring");
|
||||
#endif
|
||||
sizeMap.insert(sizeof(std::string), "std::string");
|
||||
sizeMap.insert(sizeof(std::wstring), "std::wstring");
|
||||
sizeMap.insert(sizeof(std::allocator<int>), "std::allocator");
|
||||
sizeMap.insert(sizeof(std::char_traits<char>), "std::char_traits<char>");
|
||||
sizeMap.insert(sizeof(std::char_traits<unsigned short>), "std::char_traits<unsigned short>");
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
#if QT_VERSION >= 0x040500
|
||||
sizeMap.insert(sizeof(QSharedPointer<int>), NS"QSharedPointer");
|
||||
sizeMap.insert(sizeof(QSharedDataPointer<QSharedData>), NS"QSharedDataPointer");
|
||||
sizeMap.insert(sizeof(QWeakPointer<int>), NS"QWeakPointer");
|
||||
#endif
|
||||
#endif // QT_BOOTSTRAPPED
|
||||
sizeMap.insert(sizeof(QPointer<QObject>), "QPointer");
|
||||
// Common map node types
|
||||
sizeMap.insert(sizeof(QMapNode<int,int >), NS"QMapNode<int,int>");
|
||||
sizeMap.insert(sizeof(QMapNode<int, QString>), NS"QMapNode<int,"NS"QString>");
|
||||
sizeMap.insert(sizeof(QMapNode<int, QVariant>), NS"QMapNode<int,"NS"QVariant>");
|
||||
sizeMap.insert(sizeof(QMapNode<QString, int>), NS"QMapNode<"NS"QString,int>");
|
||||
sizeMap.insert(sizeof(QMapNode<QString, QString>), NS"QMapNode<"NS"QString,"NS"QString>");
|
||||
sizeMap.insert(sizeof(QMapNode<QString, QVariant>), NS"QMapNode<"NS"QString,"NS"QVariant>");
|
||||
// Dump as lists of types preceded by size
|
||||
size_t lastSize = 0;
|
||||
d.put("sizes=[");
|
||||
const SizeMap::const_iterator cend = sizeMap.constEnd();
|
||||
for (SizeMap::const_iterator it = sizeMap.constBegin(); it != cend; ++it) {
|
||||
// new size list
|
||||
if (it.key() != lastSize) {
|
||||
if (lastSize)
|
||||
d.put("],");
|
||||
d.put("[\"");
|
||||
d.put(it.key());
|
||||
lastSize = it.key();
|
||||
d.put('"');
|
||||
}
|
||||
d.put(",\"");
|
||||
d.put(it.value());
|
||||
d.put('"');
|
||||
}
|
||||
d.put("]]");
|
||||
}
|
||||
|
||||
extern "C" Q_DECL_EXPORT
|
||||
void *qDumpObjectData440(
|
||||
int protocolVersion,
|
||||
@@ -3702,45 +3764,10 @@ void *qDumpObjectData440(
|
||||
d.put(",namespace=\""NS"\",");
|
||||
d.put("dumperversion=\"1.3\",");
|
||||
// Dump out size information
|
||||
d.put("sizes={");
|
||||
d.put("int=\"").put(sizeof(int)).put("\",")
|
||||
.put("char*=\"").put(sizeof(char*)).put("\",")
|
||||
.put(""NS"QString=\"").put(sizeof(QString)).put("\",")
|
||||
.put(""NS"QStringList=\"").put(sizeof(QStringList)).put("\",")
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
.put(""NS"QObject=\"").put(sizeof(QObject)).put("\",")
|
||||
#endif
|
||||
#if USE_QT_GUI
|
||||
.put(""NS"QWidget=\"").put(sizeof(QWidget)).put("\",")
|
||||
#endif
|
||||
#ifdef Q_OS_WIN
|
||||
.put("string=\"").put(sizeof(std::string)).put("\",")
|
||||
.put("wstring=\"").put(sizeof(std::wstring)).put("\",")
|
||||
#endif
|
||||
.put("std::string=\"").put(sizeof(std::string)).put("\",")
|
||||
.put("std::wstring=\"").put(sizeof(std::wstring)).put("\",")
|
||||
.put("std::allocator=\"").put(sizeof(std::allocator<int>)).put("\",")
|
||||
.put("std::char_traits<char>=\"").put(sizeof(std::char_traits<char>)).put("\",")
|
||||
.put("std::char_traits<unsigned short>=\"").put(sizeof(std::char_traits<unsigned short>)).put("\",")
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
#if QT_VERSION >= 0x040500
|
||||
.put(NS"QSharedPointer=\"").put(sizeof(QSharedPointer<int>)).put("\",")
|
||||
.put(NS"QSharedDataPointer=\"").put(sizeof(QSharedDataPointer<QSharedData>)).put("\",")
|
||||
.put(NS"QWeakPointer=\"").put(sizeof(QWeakPointer<int>)).put("\",")
|
||||
#endif
|
||||
#endif // QT_BOOTSTRAPPED
|
||||
.put("QPointer=\"").put(sizeof(QPointer<QObject>)).put("\",")
|
||||
// Common map node types
|
||||
.put(NS"QMapNode<int,int>=\"").put(sizeof(QMapNode<int,int >)).put("\",")
|
||||
.put(NS"QMapNode<int,"NS"QString>=\"").put(sizeof(QMapNode<int, QString>)).put("\",")
|
||||
.put(NS"QMapNode<int,"NS"QVariant>=\"").put(sizeof(QMapNode<int, QVariant>)).put("\",")
|
||||
.put(NS"QMapNode<"NS"QString,int>=\"").put(sizeof(QMapNode<QString, int>)).put("\",")
|
||||
.put(NS"QMapNode<"NS"QString,"NS"QString>=\"").put(sizeof(QMapNode<QString, QString>)).put("\",")
|
||||
.put(NS"QMapNode<"NS"QString,"NS"QVariant>=\"").put(sizeof(QMapNode<QString, QVariant>))
|
||||
.put("\"}");
|
||||
dumpSizes(d);
|
||||
// Write out common expression values for CDB
|
||||
#ifdef Q_CC_MSVC
|
||||
d.put(",expressions={");
|
||||
d.put(",expressions=[");
|
||||
putQMapNodeOffsetExpression<int,int>("int", "int", d).put(',');
|
||||
putQMapNodeOffsetExpression<int,QString>("int", NS"QString", d).put(',');
|
||||
putQMapNodeOffsetExpression<int,QVariant>("int", NS"QVariant", d).put(',');
|
||||
@@ -3754,11 +3781,11 @@ void *qDumpObjectData440(
|
||||
putStdPairValueOffsetExpression<QString,int>(NS"QString", "int", d).put(',');
|
||||
putStdPairValueOffsetExpression<std::string,std::string>(stdStringTypeC, stdStringTypeC, d).put(',');
|
||||
putStdPairValueOffsetExpression<int,std::string>("int", stdStringTypeC, d).put(',');
|
||||
putStdPairValueOffsetExpression<std::string,int>(stdStringTypeC, "int", d.put(','));
|
||||
putStdPairValueOffsetExpression<std::string,int>(stdStringTypeC, "int", d).put(',');
|
||||
putStdPairValueOffsetExpression<std::wstring,std::wstring>(stdWideStringTypeUShortC, stdWideStringTypeUShortC, d).put(',');
|
||||
putStdPairValueOffsetExpression<int,std::wstring>("int", stdWideStringTypeUShortC, d).put(',');
|
||||
putStdPairValueOffsetExpression<std::wstring,int>(stdWideStringTypeUShortC, "int", d);
|
||||
d.put('}');
|
||||
d.put(']');
|
||||
#endif // Q_CC_MSVC
|
||||
d.disarm();
|
||||
}
|
||||
|
@@ -152,8 +152,6 @@ public:
|
||||
QList<QObject *> pendingChildInsertedEvents;
|
||||
QList<QPointer<QObject> > eventFilters;
|
||||
void *currentChildBeingDeleted;
|
||||
void *declarativeData;
|
||||
void *objectGuards;
|
||||
QAtomicPointer<void> sharedRefcount;
|
||||
int *deleteWatch;
|
||||
#endif
|
||||
|
@@ -3305,36 +3305,12 @@ static void parseSizeCache(const GdbMi &contents, QtDumperHelper *dumperHelper)
|
||||
void GdbEngine::handleQueryDebuggingHelper(const GdbResultRecord &record, const QVariant &)
|
||||
{
|
||||
const double dumperVersionRequired = 1.0;
|
||||
m_dumperHelper.clear();
|
||||
//qDebug() << "DATA DUMPER TRIAL:" << record.toString();
|
||||
|
||||
GdbMi contents;
|
||||
QTC_ASSERT(parseConsoleStream(record, &contents), /**/);
|
||||
GdbMi simple = contents.findChild("dumpers");
|
||||
|
||||
m_dumperHelper.setQtNamespace(_(contents.findChild("namespace").data()));
|
||||
GdbMi qtversion = contents.findChild("qtversion");
|
||||
int qtv = 0;
|
||||
if (qtversion.children().size() == 3) {
|
||||
qtv = (qtversion.childAt(0).data().toInt() << 16)
|
||||
+ (qtversion.childAt(1).data().toInt() << 8)
|
||||
+ qtversion.childAt(2).data().toInt();
|
||||
//qDebug() << "FOUND QT VERSION:" << qtversion.toString() << m_qtVersion;
|
||||
}
|
||||
m_dumperHelper.setQtVersion(qtv);
|
||||
//qDebug() << "CONTENTS:" << contents.toString();
|
||||
//qDebug() << "SIMPLE DUMPERS:" << simple.toString();
|
||||
|
||||
QStringList availableSimpleDebuggingHelpers;
|
||||
foreach (const GdbMi &item, simple.children())
|
||||
availableSimpleDebuggingHelpers.append(_(item.data()));
|
||||
m_dumperHelper.parseQueryTypes(availableSimpleDebuggingHelpers, QtDumperHelper::GdbDebugger);
|
||||
|
||||
if (availableSimpleDebuggingHelpers.isEmpty()) {
|
||||
if (!m_dumperInjectionLoad) // Retry if thread has not terminated yet.
|
||||
m_debuggingHelperState = DebuggingHelperUnavailable;
|
||||
showStatusMessage(tr("Debugging helpers not found."));
|
||||
} else {
|
||||
const bool ok = m_dumperHelper.parseQuery(contents, QtDumperHelper::GdbDebugger) && m_dumperHelper.typeCount();
|
||||
if (ok) {
|
||||
// Get version and sizes from dumpers. Expression cache
|
||||
// currently causes errors.
|
||||
const double dumperVersion = getDumperVersion(contents);
|
||||
@@ -3347,6 +3323,10 @@ void GdbEngine::handleQueryDebuggingHelper(const GdbResultRecord &record, const
|
||||
m_debuggingHelperState = DebuggingHelperAvailable;
|
||||
const QString successMsg = tr("Dumper version %1, %n custom dumpers found.", 0, m_dumperHelper.typeCount()).arg(dumperVersion);
|
||||
showStatusMessage(successMsg);
|
||||
} else {
|
||||
if (!m_dumperInjectionLoad) // Retry if thread has not terminated yet.
|
||||
m_debuggingHelperState = DebuggingHelperUnavailable;
|
||||
showStatusMessage(tr("Debugging helpers not found."));
|
||||
}
|
||||
//qDebug() << m_dumperHelper.toString(true);
|
||||
//qDebug() << m_availableSimpleDebuggingHelpers << "DATA DUMPERS AVAILABLE";
|
||||
|
@@ -29,6 +29,7 @@
|
||||
|
||||
#include "watchutils.h"
|
||||
#include "watchhandler.h"
|
||||
#include "gdb/gdbmi.h"
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <texteditor/basetexteditor.h>
|
||||
@@ -725,6 +726,10 @@ QString QtDumperHelper::toString(bool debug) const
|
||||
for (SizeCache::const_iterator it = m_sizeCache.constBegin(); it != scend; ++it) {
|
||||
str << ' ' << it.key() << '=' << it.value();
|
||||
}
|
||||
str << "\nExpression cache: (" << m_expressionCache.size() << ")\n";
|
||||
const QMap<QString, QString>::const_iterator excend = m_expressionCache.constEnd();
|
||||
for (QMap<QString, QString>::const_iterator it = m_expressionCache.constBegin(); it != excend; ++it)
|
||||
str << " " << it.key() << ' ' << it.value() << '\n';
|
||||
return rc;
|
||||
}
|
||||
const QString nameSpace = m_qtNamespace.isEmpty() ? QCoreApplication::translate("QtDumperHelper", "<none>") : m_qtNamespace;
|
||||
@@ -749,11 +754,6 @@ QString QtDumperHelper::qtNamespace() const
|
||||
return m_qtNamespace;
|
||||
}
|
||||
|
||||
void QtDumperHelper::setQtNamespace(const QString &qtNamespace)
|
||||
{
|
||||
m_qtNamespace = qtNamespace;
|
||||
}
|
||||
|
||||
int QtDumperHelper::typeCount() const
|
||||
{
|
||||
return m_nameTypeMap.size();
|
||||
@@ -842,23 +842,6 @@ QString QtDumperHelper::qtVersionString() const
|
||||
return rc;
|
||||
}
|
||||
|
||||
void QtDumperHelper::setQtVersion(int v)
|
||||
{
|
||||
m_qtVersion = v;
|
||||
}
|
||||
|
||||
void QtDumperHelper::setQtVersion(const QString &v)
|
||||
{
|
||||
m_qtVersion = 0;
|
||||
const QStringList vl = v.split(QLatin1Char('.'));
|
||||
if (vl.size() == 3) {
|
||||
const int major = vl.at(0).toInt();
|
||||
const int minor = vl.at(1).toInt();
|
||||
const int patch = vl.at(2).toInt();
|
||||
m_qtVersion = (major << 16) | (minor << 8) | patch;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse a list of types.
|
||||
void QtDumperHelper::parseQueryTypes(const QStringList &l, Debugger debugger)
|
||||
{
|
||||
@@ -1049,134 +1032,6 @@ bool DumperParser::handleValue(const char *k, int size)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Parse 'query' (1) protocol response of the custom dumpers:
|
||||
* "'dumpers=["QByteArray","QDateTime",..."std::basic_string",],
|
||||
* qtversion=["4","5","1"],namespace="""' */
|
||||
|
||||
class QueryDumperParser : public DumperParser {
|
||||
public:
|
||||
typedef QPair<QString, int> SizeEntry;
|
||||
explicit QueryDumperParser(const char *s);
|
||||
|
||||
struct Data {
|
||||
QString qtNameSpace;
|
||||
QString qtVersion;
|
||||
QString dumperVersion;
|
||||
QStringList types;
|
||||
QList<SizeEntry> sizes;
|
||||
QMap<QString, QString> expressionCache;
|
||||
};
|
||||
|
||||
inline Data data() const { return m_data; }
|
||||
|
||||
protected:
|
||||
virtual bool handleKeyword(const char *k, int size);
|
||||
virtual bool handleListStart();
|
||||
virtual bool handleListEnd();
|
||||
virtual bool handleHashEnd();
|
||||
virtual bool handleValue(const char *k, int size);
|
||||
|
||||
private:
|
||||
enum Mode { None, ExpectingDumpers, ExpectingQtVersion, ExpectingDumperVersion,
|
||||
ExpectingNameSpace, ExpectingSizes, ExpectingExpressionCache };
|
||||
Mode m_mode;
|
||||
Data m_data;
|
||||
QString m_lastSizeType;
|
||||
QString m_lastExpression;
|
||||
};
|
||||
|
||||
QueryDumperParser::QueryDumperParser(const char *s) :
|
||||
DumperParser(s),
|
||||
m_mode(None)
|
||||
{
|
||||
}
|
||||
|
||||
bool QueryDumperParser::handleKeyword(const char *k, int size)
|
||||
{
|
||||
switch (m_mode) {
|
||||
case ExpectingSizes:
|
||||
m_lastSizeType = QString::fromLatin1(k, size);
|
||||
return true;
|
||||
case ExpectingExpressionCache:
|
||||
m_lastExpression = QString::fromLatin1(k, size);
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!qstrncmp(k, "dumpers", size)) {
|
||||
m_mode = ExpectingDumpers;
|
||||
return true;
|
||||
}
|
||||
if (!qstrncmp(k, "qtversion", size)) {
|
||||
m_mode = ExpectingQtVersion;
|
||||
return true;
|
||||
}
|
||||
if (!qstrncmp(k, "dumperversion", size)) {
|
||||
m_mode = ExpectingDumperVersion;
|
||||
return true;
|
||||
}
|
||||
if (!qstrncmp(k, "namespace", size)) {
|
||||
m_mode = ExpectingNameSpace;
|
||||
return true;
|
||||
}
|
||||
if (!qstrncmp(k, "sizes", size)) {
|
||||
m_mode = ExpectingSizes;
|
||||
return true;
|
||||
}
|
||||
if (!qstrncmp(k, "expressions", size)) {
|
||||
m_mode = ExpectingExpressionCache;
|
||||
return true;
|
||||
}
|
||||
qWarning("%s Unexpected keyword %s.\n", Q_FUNC_INFO, QByteArray(k, size).constData());
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QueryDumperParser::handleListStart()
|
||||
{
|
||||
return m_mode == ExpectingDumpers || m_mode == ExpectingQtVersion;
|
||||
}
|
||||
|
||||
bool QueryDumperParser::handleListEnd()
|
||||
{
|
||||
m_mode = None;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QueryDumperParser::handleHashEnd()
|
||||
{
|
||||
m_mode = None; // Size hash
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QueryDumperParser::handleValue(const char *k, int size)
|
||||
{
|
||||
switch (m_mode) {
|
||||
case None:
|
||||
return false;
|
||||
case ExpectingDumpers:
|
||||
m_data.types.push_back(QString::fromLatin1(k, size));
|
||||
break;
|
||||
case ExpectingNameSpace:
|
||||
m_data.qtNameSpace = QString::fromLatin1(k, size);
|
||||
break;
|
||||
case ExpectingDumperVersion:
|
||||
m_data.dumperVersion = QString::fromLatin1(k, size);
|
||||
break;
|
||||
case ExpectingQtVersion: // ["4","1","5"]
|
||||
if (!m_data.qtVersion.isEmpty())
|
||||
m_data.qtVersion += QLatin1Char('.');
|
||||
m_data.qtVersion += QString::fromLatin1(k, size);
|
||||
break;
|
||||
case ExpectingSizes:
|
||||
m_data.sizes.push_back(SizeEntry(m_lastSizeType, QString::fromLatin1(k, size).toInt()));
|
||||
break;
|
||||
case ExpectingExpressionCache:
|
||||
m_data.expressionCache.insert(m_lastExpression, QString::fromLatin1(k, size));
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline QString qClassName(const QString &qtNamespace, const char *className)
|
||||
{
|
||||
if (qtNamespace.isEmpty())
|
||||
@@ -1196,34 +1051,68 @@ void QtDumperHelper::setQClassPrefixes(const QString &qNamespace)
|
||||
m_qWeakPointerPrefix = qClassName(qNamespace, "QWeakPointer");
|
||||
}
|
||||
|
||||
// parse a query
|
||||
bool QtDumperHelper::parseQuery(const char *data, Debugger debugger)
|
||||
static inline double getDumperVersion(const GdbMi &contents)
|
||||
{
|
||||
QueryDumperParser parser(data);
|
||||
if (!parser.run())
|
||||
return false;
|
||||
clear();
|
||||
m_qtNamespace = parser.data().qtNameSpace;
|
||||
setQtVersion(parser.data().qtVersion);
|
||||
setQClassPrefixes(m_qtNamespace);
|
||||
parseQueryTypes(parser.data().types, debugger);
|
||||
foreach (const QueryDumperParser::SizeEntry &se, parser.data().sizes)
|
||||
addSize(se.first, se.second);
|
||||
m_expressionCache = parser.data().expressionCache;
|
||||
// Version
|
||||
if (!parser.data().dumperVersion.isEmpty()) {
|
||||
double dumperVersion;
|
||||
const GdbMi dumperVersionG = contents.findChild("dumperversion");
|
||||
if (dumperVersionG.type() != GdbMi::Invalid) {
|
||||
bool ok;
|
||||
dumperVersion = parser.data().dumperVersion.toDouble(&ok);
|
||||
const double v = QString::fromAscii(dumperVersionG.data()).toDouble(&ok);
|
||||
if (ok)
|
||||
m_dumperVersion = dumperVersion;
|
||||
return v;
|
||||
}
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
bool QtDumperHelper::parseQuery(const GdbMi &contents, Debugger debugger)
|
||||
{
|
||||
clear();
|
||||
if (debug > 1)
|
||||
qDebug() << "parseQuery" << contents.toString(true, 2);
|
||||
|
||||
// Common info, dumper version, etc
|
||||
m_qtNamespace = QLatin1String(contents.findChild("namespace").data());
|
||||
int qtv = 0;
|
||||
const GdbMi qtversion = contents.findChild("qtversion");
|
||||
if (qtversion.children().size() == 3) {
|
||||
qtv = (qtversion.childAt(0).data().toInt() << 16)
|
||||
+ (qtversion.childAt(1).data().toInt() << 8)
|
||||
+ qtversion.childAt(2).data().toInt();
|
||||
}
|
||||
m_qtVersion = qtv;
|
||||
// Get list of helpers
|
||||
QStringList availableSimpleDebuggingHelpers;
|
||||
foreach (const GdbMi &item, contents.findChild("dumpers").children())
|
||||
availableSimpleDebuggingHelpers.append(QLatin1String(item.data()));
|
||||
parseQueryTypes(availableSimpleDebuggingHelpers, debugger);
|
||||
m_dumperVersion = getDumperVersion(contents);
|
||||
// Parse sizes
|
||||
foreach (const GdbMi &sizesList, contents.findChild("sizes").children()) {
|
||||
const int childCount = sizesList.childCount();
|
||||
if (childCount > 1) {
|
||||
const int size = sizesList.childAt(0).data().toInt();
|
||||
for (int c = 1; c < childCount; c++)
|
||||
addSize(QLatin1String(sizesList.childAt(c).data()), size);
|
||||
}
|
||||
}
|
||||
// Parse expressions
|
||||
foreach (const GdbMi &exprList, contents.findChild("expressions").children())
|
||||
if (exprList.childCount() == 2)
|
||||
m_expressionCache.insert(QLatin1String(exprList.childAt(0).data()),
|
||||
QLatin1String(exprList.childAt(1).data()));
|
||||
return true;
|
||||
}
|
||||
|
||||
void QtDumperHelper::addExpression(const QString &expression, const QString &value)
|
||||
// parse a query
|
||||
bool QtDumperHelper::parseQuery(const char *data, Debugger debugger)
|
||||
{
|
||||
m_expressionCache.insert(expression, value);
|
||||
QByteArray fullData = data;
|
||||
fullData.insert(0, '{');
|
||||
fullData.append(data);
|
||||
fullData.append('}');
|
||||
GdbMi root(fullData);
|
||||
if (!root.isValid())
|
||||
return false;
|
||||
return parseQuery(root, debugger);
|
||||
}
|
||||
|
||||
void QtDumperHelper::addSize(const QString &name, int size)
|
||||
|
@@ -49,6 +49,7 @@ namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class WatchData;
|
||||
class GdbMi;
|
||||
|
||||
QString dotEscape(QString str);
|
||||
QString currentTime();
|
||||
@@ -181,7 +182,6 @@ public:
|
||||
void clear();
|
||||
|
||||
double dumperVersion() const { return m_dumperVersion; }
|
||||
void setDumperVersion(double v) { m_dumperVersion = v; }
|
||||
|
||||
int typeCount() const;
|
||||
// Look up a simple, non-template type
|
||||
@@ -192,17 +192,14 @@ public:
|
||||
|
||||
int qtVersion() const;
|
||||
QString qtVersionString() const;
|
||||
void setQtVersion(int v);
|
||||
void setQtVersion(const QString &v);
|
||||
|
||||
QString qtNamespace() const;
|
||||
void setQtNamespace(const QString &qtNamespace);
|
||||
|
||||
// Complete parse of "query" (protocol 1) response from debuggee buffer.
|
||||
// 'data' excludes the leading indicator character.
|
||||
bool parseQuery(const char *data, Debugger debugger);
|
||||
// Set up from pre-parsed type list
|
||||
void parseQueryTypes(const QStringList &l, Debugger debugger);
|
||||
bool parseQuery(const GdbMi &data, Debugger debugger);
|
||||
// Sizes can be added as the debugger determines them
|
||||
void addSize(const QString &name, int size);
|
||||
|
||||
// Determine the parameters required for an "evaluate" (protocol 2) call
|
||||
void evaluationParameters(const WatchData &data,
|
||||
@@ -228,9 +225,6 @@ public:
|
||||
|
||||
QString toString(bool debug = false) const;
|
||||
|
||||
// Helpers for debuggers that use a different dumper parser.
|
||||
void addSize(const QString &name, int size);
|
||||
void addExpression(const QString &expression, const QString &value);
|
||||
|
||||
static QString msgDumperOutdated(double requiredVersion, double currentVersion);
|
||||
|
||||
@@ -241,6 +235,7 @@ private:
|
||||
// Look up a simple (namespace) type
|
||||
static Type specialType(QString s);
|
||||
QString evaluationSizeofTypeExpression(const QString &typeName, Debugger d) const;
|
||||
void parseQueryTypes(const QStringList &l, Debugger debugger);
|
||||
|
||||
NameTypeMap m_nameTypeMap;
|
||||
SizeCache m_sizeCache;
|
||||
|
@@ -1501,7 +1501,7 @@ template <typename K, typename V>
|
||||
append(" isSimpleValue: ").append(N(simpleVal)).
|
||||
append(" keyOffset: ").append(N(transKeyOffset)).append(" valueOffset: ").
|
||||
append(N(transValOffset)).append(" mapnodesize: ").
|
||||
append(N(nodeSize)).append("',children=[");
|
||||
append(N(qulonglong(nodeSize))).append("',children=["); // 64bit Linux hack
|
||||
typedef typename QMap<K, V>::iterator mapIter;
|
||||
for (mapIter it = map.begin(); it != map.end(); ++it) {
|
||||
if (it != map.begin())
|
||||
@@ -2368,7 +2368,9 @@ void tst_Debugger::initTestCase()
|
||||
d.weakref = d.strongref = 0; // That's what the destructor expects.
|
||||
QVERIFY(sizeof(int) == sizeof(d.weakref));
|
||||
QVERIFY(sizeof(int) == sizeof(d.strongref));
|
||||
QVERIFY(sizeof(QObjectPrivate) == sizeof(ObjectPrivate));
|
||||
const size_t qObjectPrivateSize = sizeof(QObjectPrivate);
|
||||
const size_t objectPrivateSize = sizeof(ObjectPrivate);
|
||||
QVERIFY2(qObjectPrivateSize == objectPrivateSize, QString::fromLatin1("QObjectPrivate=%1 ObjectPrivate=%2").arg(qObjectPrivateSize).arg(objectPrivateSize).toLatin1().constData());
|
||||
VERIFY_OFFSETOF(threadData);
|
||||
VERIFY_OFFSETOF(extraData);
|
||||
VERIFY_OFFSETOF(objectName);
|
||||
@@ -2379,11 +2381,12 @@ void tst_Debugger::initTestCase()
|
||||
VERIFY_OFFSETOF(currentChildBeingDeleted);
|
||||
VERIFY_OFFSETOF(connectedSignals);
|
||||
VERIFY_OFFSETOF(deleteWatch);
|
||||
#ifdef QT3_SUPPORT
|
||||
#if QT_VERSION < 0x040600
|
||||
VERIFY_OFFSETOF(pendingChildInsertedEvents);
|
||||
#else
|
||||
VERIFY_OFFSETOF(declarativeData);
|
||||
VERIFY_OFFSETOF(objectGuards);
|
||||
#endif
|
||||
#endif
|
||||
#if QT_VERSION >= 0x040600
|
||||
VERIFY_OFFSETOF(sharedRefcount);
|
||||
#endif
|
||||
}
|
||||
|
Reference in New Issue
Block a user