diff --git a/share/qtcreator/gdbmacros/gdbmacros.cpp b/share/qtcreator/gdbmacros/gdbmacros.cpp index 7c766dff31ec64c8d9b1b834ddf26fa5f596fc6e..029de5f6a6c1c38703cb883a5b3d99c27005730f 100644 --- a/share/qtcreator/gdbmacros/gdbmacros.cpp +++ b/share/qtcreator/gdbmacros/gdbmacros.cpp @@ -56,6 +56,7 @@ int qtGhVersion = QT_VERSION; #ifdef QT_GUI_LIB +# include <QtGui/QWidget> # include <QtGui/QPixmap> # include <QtGui/QImage> #endif @@ -2685,7 +2686,25 @@ void *qDumpObjectData440( "\"" << ((QT_VERSION >> 16) & 255) << "\"," "\"" << ((QT_VERSION >> 8) & 255) << "\"," "\"" << ((QT_VERSION) & 255) << "\"]"; - d << ",namespace=\""NS"\""; + d << ",namespace=\""NS"\","; +// Dump out size information + d << "sizes={"; + d << "int=\"" << sizeof(int) << "\"," + << "char*=\"" << sizeof(char*) << "\"," + << ""NS"QString=\"" << sizeof(QString) << "\"," + << ""NS"QStringList=\"" << sizeof(QStringList) << "\"," + << ""NS"QObject=\"" << sizeof(QObject) << "\"," +#ifdef QT_GUI_LIB + << ""NS"QWidget=\"" << sizeof(QWidget)<< "\"," +#endif +#ifdef Q_OS_WIN + << "string=\"" << sizeof(std::string) << "\"," + << "wstring=\"" << sizeof(std::wstring) << "\"," +#endif + << "std::string=\"" << sizeof(std::string) << "\"," + << "std::wstring=\"" << sizeof(std::wstring) << "\"," + << "std::allocator=\"" << sizeof(std::allocator<int>) + << "\"}"; d.disarm(); } diff --git a/src/plugins/debugger/cdb/cdbdumperhelper.cpp b/src/plugins/debugger/cdb/cdbdumperhelper.cpp index 1357eb99d6f6abeba672e0ac3780f243b3932779..3f4ffdab8fd98e8df8241c96408d194109c22fcd 100644 --- a/src/plugins/debugger/cdb/cdbdumperhelper.cpp +++ b/src/plugins/debugger/cdb/cdbdumperhelper.cpp @@ -181,7 +181,6 @@ void CdbDumperHelper::reset(const QString &library, bool enabled) m_helper.clear(); m_inBufferAddress = m_outBufferAddress = 0; m_inBufferSize = m_outBufferSize = 0; - m_typeSizeCache.clear(); m_failedTypes.clear(); clearBuffer(); } @@ -405,7 +404,9 @@ CdbDumperHelper::DumpResult CdbDumperHelper::dumpType(const WatchData &wd, bool // Check failure cache and supported types if (m_failedTypes.contains(wd.type)) return DumpNotHandled; - const QtDumperHelper::TypeData td = m_helper.typeData(wd.type); + const QtDumperHelper::TypeData td = m_helper.typeData(wd.type); + if (loadDebug) + qDebug() << wd.type << td; if (td.type == QtDumperHelper::UnknownType) return DumpNotHandled; @@ -448,10 +449,11 @@ CdbDumperHelper::DumpExecuteResult int size; ep.truncate(ep.lastIndexOf(QLatin1Char(')'))); ep.remove(0, ep.indexOf(QLatin1Char('(')) + 1); - if (!getTypeSize(ep, &size, errorMessage)) - return DumpExecuteSizeFailed; + const bool sizeOk = getTypeSize(ep, &size, errorMessage); if (loadDebug) - qDebug() << "Size" << size << ep; + qDebug() << "Size" << sizeOk << size << ep; + if (!sizeOk) + return DumpExecuteSizeFailed; ep = QString::number(size); } } @@ -461,7 +463,7 @@ CdbDumperHelper::DumpExecuteResult << "(2,0," << wd.addr << ',' << (dumpChildren ? 1 : 0) << ',' << extraParameters.join(QString(QLatin1Char(','))) << ')'; if (loadDebug) - qDebug() << "Query: " << wd.toString() << "\nwith: " << callCmd; + qDebug() << "Query: " << wd.toString() << "\nwith: " << callCmd << '\n'; const char *outputData; if (!callDumper(callCmd, inBuffer, &outputData, errorMessage)) return DumpExecuteCallFailed; @@ -486,11 +488,6 @@ bool CdbDumperHelper::getTypeSize(const QString &typeNameIn, int *size, QString if (loadDebug > 1) qDebug() << Q_FUNC_INFO << typeNameIn; // Look up cache - const TypeSizeCache::const_iterator it = m_typeSizeCache.constFind(typeNameIn); - if (it != m_typeSizeCache.constEnd()) { - *size = it.value(); - return true; - } QString typeName = typeNameIn; simplifySizeExpression(&typeName); // "std::" types sometimes only work without namespace. @@ -511,8 +508,9 @@ bool CdbDumperHelper::getTypeSize(const QString &typeNameIn, int *size, QString break; success = true; } while (false); + // Cache in dumper helper if (success) - m_typeSizeCache.insert(typeName, *size); + m_helper.addSize(typeName, *size); return success; } diff --git a/src/plugins/debugger/cdb/cdbdumperhelper.h b/src/plugins/debugger/cdb/cdbdumperhelper.h index 2f576b196ef978ce5447b81db71e71c0db162bd8..b9ec2bccccbbf8248a94e833bc5a30b3b9e8cf18 100644 --- a/src/plugins/debugger/cdb/cdbdumperhelper.h +++ b/src/plugins/debugger/cdb/cdbdumperhelper.h @@ -119,8 +119,6 @@ private: unsigned long m_outBufferSize; char *m_buffer; - typedef QMap<QString, int> TypeSizeCache; - TypeSizeCache m_typeSizeCache; QStringList m_failedTypes; QtDumperHelper m_helper; diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp index da1fead265e2435cbd72cd65d9e1d2be6c436fc0..04966d4023daa58e959e19a8ef47d8249c5bc136 100644 --- a/src/plugins/debugger/gdbengine.cpp +++ b/src/plugins/debugger/gdbengine.cpp @@ -3061,8 +3061,6 @@ void GdbEngine::runDebuggingHelper(const WatchData &data0, bool dumpChildren) <<',' << addr << ',' << (dumpChildren ? "1" : "0") << ',' << extraArgs.join(QString(QLatin1Char(','))) << ')'; - qDebug() << "CMD: " << cmd; - QVariant var; var.setValue(data); sendSynchronizedCommand(cmd, WatchDebuggingHelperValue1, var); @@ -3344,7 +3342,7 @@ void GdbEngine::handleQueryDebuggingHelper(const GdbResultRecord &record) q->showStatusMessage(tr("%1 custom dumpers found.") .arg(m_dumperHelper.typeCount())); } - qDebug() << m_dumperHelper.toString(true); + //qDebug() << m_dumperHelper.toString(true); //qDebug() << "DATA DUMPERS AVAILABLE" << m_availableSimpleDebuggingHelpers; } diff --git a/src/plugins/debugger/watchutils.cpp b/src/plugins/debugger/watchutils.cpp index c1150c2ad8f15598a3180500263bf8307d0b1066..c77fc0a5b39ecb030f35dff62ee2c28b30211233 100644 --- a/src/plugins/debugger/watchutils.cpp +++ b/src/plugins/debugger/watchutils.cpp @@ -470,6 +470,10 @@ void QtDumperHelper::TypeData::clear() // ----------------- QtDumperHelper QtDumperHelper::QtDumperHelper() : + m_stdAllocatorPrefix(QLatin1String("std::allocator")), + m_intSize(0), + m_pointerSize(0), + m_stdAllocatorSize(0), m_qtVersion(0) { } @@ -479,6 +483,10 @@ void QtDumperHelper::clear() m_nameTypeMap.clear(); m_qtVersion = 0; m_qtNamespace.clear(); + m_sizeCache.clear(); + m_intSize = 0; + m_pointerSize = 0; + m_stdAllocatorSize = 0; } static inline void formatQtVersion(int v, QTextStream &str) @@ -498,6 +506,12 @@ QString QtDumperHelper::toString(bool debug) const for (NameTypeMap::const_iterator it = m_nameTypeMap.constBegin(); it != cend; ++it) { str <<",[" << it.key() << ',' << it.value() << ']'; } + str << "Sizes: intsize=" << m_intSize << " pointer size=" << m_pointerSize + << " allocatorsize=" << m_stdAllocatorSize; + const SizeCache::const_iterator scend = m_sizeCache.constEnd(); + for (SizeCache::const_iterator it = m_sizeCache.constBegin(); it != scend; ++it) { + str << ' ' << it.key() << '=' << it.value(); + } return rc; } const QString nameSpace = m_qtNamespace.isEmpty() ? QCoreApplication::translate("QtDumperHelper", "<none>") : m_qtNamespace; @@ -824,6 +838,7 @@ bool DumperParser::handleValue(const char *k, int size) class QueryDumperParser : public DumperParser { public: + typedef QPair<QString, int> SizeEntry; explicit QueryDumperParser(const char *s); struct Data { @@ -831,20 +846,23 @@ public: QString qtNameSpace; QString qtVersion; QStringList types; + QList<SizeEntry> sizes; }; inline Data data() const { return m_data; } protected: virtual bool handleKeyword(const char *k, int size); - virtual bool handleListStart(); + virtual bool handleListStart(); virtual bool handleListEnd(); + virtual bool handleHashEnd(); virtual bool handleValue(const char *k, int size); private: - enum Mode { None, ExpectingDumpers, ExpectingVersion, ExpectingNameSpace }; + enum Mode { None, ExpectingDumpers, ExpectingVersion, ExpectingNameSpace, ExpectingSizes }; Mode m_mode; Data m_data; + QString m_lastSizeType; }; QueryDumperParser::QueryDumperParser(const char *s) : @@ -854,7 +872,11 @@ QueryDumperParser::QueryDumperParser(const char *s) : } bool QueryDumperParser::handleKeyword(const char *k, int size) -{ +{ + if (m_mode == ExpectingSizes) { + m_lastSizeType = QString::fromLatin1(k, size); + return true; + } if (!qstrncmp(k, "dumpers", size)) { m_mode = ExpectingDumpers; return true; @@ -867,6 +889,10 @@ bool QueryDumperParser::handleKeyword(const char *k, int size) m_mode = ExpectingNameSpace; return true; } + if (!qstrncmp(k, "sizes", size)) { + m_mode = ExpectingSizes; + return true; + } qWarning("%s Unexpected keyword %s.\n", Q_FUNC_INFO, QByteArray(k, size).constData()); return false; } @@ -882,15 +908,21 @@ bool QueryDumperParser::handleListEnd() 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: + case None: return false; - case ExpectingDumpers: + case ExpectingDumpers: m_data.types.push_back(QString::fromLatin1(k, size)); break; - case ExpectingNameSpace: + case ExpectingNameSpace: m_data.qtNameSpace = QString::fromLatin1(k, size); break; case ExpectingVersion: // ["4","1","5"] @@ -898,6 +930,9 @@ bool QueryDumperParser::handleValue(const char *k, int size) 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; } return true; } @@ -905,7 +940,6 @@ bool QueryDumperParser::handleValue(const char *k, int size) // parse a query bool QtDumperHelper::parseQuery(const char *data, Debugger debugger) { - QueryDumperParser parser(data); if (!parser.run()) return false; @@ -913,9 +947,39 @@ bool QtDumperHelper::parseQuery(const char *data, Debugger debugger) m_qtNamespace = parser.data().qtNameSpace; setQtVersion(parser.data().qtVersion); parseQueryTypes(parser.data().types, debugger); + foreach (const QueryDumperParser::SizeEntry &se, parser.data().sizes) + addSize(se.first, se.second); return true; } +void QtDumperHelper::addSize(const QString &name, int size) +{ + // Special interest cases + do { + if (name == QLatin1String("char*")) { + m_pointerSize = size; + break; + } + if (name == QLatin1String("int")) { + m_intSize = size; + break; + } + if (name.startsWith(m_stdAllocatorPrefix)) { + m_stdAllocatorSize = size; + break; + } + if (name == QLatin1String("std::string")) { + m_sizeCache.insert(QLatin1String("std::basic_string<char,std::char_traits<char>,std::allocator<char>>"), size); + break; + } + if (name == QLatin1String("std::wstring")) { + m_sizeCache.insert(QLatin1String("std::basic_string<unsigned short,std::char_traits<unsignedshort>,std::allocator<unsignedshort> >"), size); + break; + } + } while (false); + m_sizeCache.insert(name, size); +} + QtDumperHelper::Type QtDumperHelper::type(const QString &typeName) const { const QtDumperHelper::TypeData td = typeData(typeName); @@ -941,9 +1005,26 @@ QtDumperHelper::TypeData QtDumperHelper::typeData(const QString &typeName) const return td; } +// Format an expression to have the debugger query the +// size. Use size cache if possible +QString QtDumperHelper::evaluationSizeofTypeExpression(const QString &typeName, + Debugger /* debugger */) const +{ + // Look up fixed types + if (m_pointerSize && isPointerType(typeName)) + return QString::number(m_pointerSize); + if (m_stdAllocatorSize && typeName.startsWith(m_stdAllocatorPrefix)) + return QString::number(m_stdAllocatorSize); + const SizeCache::const_iterator sit = m_sizeCache.constFind(typeName); + if (sit != m_sizeCache.constEnd()) + return QString::number(sit.value()); + // Finally have the debugger evaluate + return sizeofTypeExpression(typeName); +} + void QtDumperHelper::evaluationParameters(const WatchData &data, const TypeData &td, - Debugger /* debugger */, + Debugger debugger, QByteArray *inBuffer, QStringList *extraArgsIn) const { @@ -970,7 +1051,7 @@ void QtDumperHelper::evaluationParameters(const WatchData &data, // gives already most information the dumpers need const int count = qMin(int(maxExtraArgCount), inners.size()); for (int i = 0; i < count; i++) - extraArgs.push_back(sizeofTypeExpression(inners.at(i))); + extraArgs.push_back(evaluationSizeofTypeExpression(inners.at(i), debugger)); } int extraArgCount = extraArgs.size(); // Pad with zeros @@ -1019,14 +1100,14 @@ void QtDumperHelper::evaluationParameters(const WatchData &data, } //qDebug() << "OUTERTYPE: " << outertype << " NODETYPE: " << nodetype // << "QT VERSION" << m_qtVersion << ((4 << 16) + (5 << 8) + 0); - extraArgs[2] = sizeofTypeExpression(nodetype); + extraArgs[2] = evaluationSizeofTypeExpression(nodetype, debugger); extraArgs[3] = QLatin1String("(size_t)&(('"); extraArgs[3] += nodetype; extraArgs[3] += QLatin1String("'*)0)->value"); } break; case QMapNodeType: - extraArgs[2] = sizeofTypeExpression(data.type); + extraArgs[2] = evaluationSizeofTypeExpression(data.type, debugger); extraArgs[3] = QLatin1String("(size_t)&(('"); extraArgs[3] += data.type; extraArgs[3] += QLatin1String("'*)0)->value"); @@ -1036,7 +1117,7 @@ void QtDumperHelper::evaluationParameters(const WatchData &data, if (inners.at(0) == QLatin1String("bool")) { outertype = QLatin1String("std::vector::bool"); } else { - //extraArgs[extraArgCount++] = sizeofTypeExpression(data.type); + //extraArgs[extraArgCount++] = evaluationSizeofTypeExpression(data.type, debugger); //extraArgs[extraArgCount++] = "(size_t)&(('" + data.type + "'*)0)->value"; } break; @@ -1260,5 +1341,14 @@ bool QtDumperHelper::parseValue(const char *data, QtDumperResult *r) return true; } +QDebug operator<<(QDebug in, const QtDumperHelper::TypeData &d) +{ + QDebug nsp = in.nospace(); + nsp << " type=" << d.type << " tpl=" << d.isTemplate; + if (d.isTemplate) + nsp << d.tmplate << '<' << d.inner << '>'; + return in; +} + } } diff --git a/src/plugins/debugger/watchutils.h b/src/plugins/debugger/watchutils.h index 2fd9a802465d7f26349f450cce223e66200da23f..e316973ca13f0a5c07e955cec53cbbf6796ece76 100644 --- a/src/plugins/debugger/watchutils.h +++ b/src/plugins/debugger/watchutils.h @@ -181,17 +181,28 @@ public: QString toString(bool debug = false) const; -private: + void addSize(const QString &name, int size); + +private: typedef QMap<QString, Type> NameTypeMap; + typedef QMap<QString, int> SizeCache; // Look up a simple (namespace) type static Type specialType(QString s); + QString evaluationSizeofTypeExpression(const QString &typeName, Debugger d) const; + + const QString m_stdAllocatorPrefix; NameTypeMap m_nameTypeMap; + SizeCache m_sizeCache; + int m_intSize; + int m_pointerSize; + int m_stdAllocatorSize; int m_qtVersion; QString m_qtNamespace; }; +QDebug operator<<(QDebug in, const QtDumperHelper::TypeData &d); } // namespace Internal } // namespace Debugger