From 7f90f2942a6b712f2ddfb4b00aafb65508ac7d5f Mon Sep 17 00:00:00 2001 From: Friedemann Kleint <Friedemann.Kleint@nokia.com> Date: Wed, 19 May 2010 15:14:15 +0200 Subject: [PATCH] Debugger: Add incremental API for modules. And use it from CDB's module load/unload callbacks instead of re-setting all modules. Some cleanup./Fixed conflicts in 2.0 Acked-by: hjk --- src/plugins/debugger/cdb/cdbdebugengine.cpp | 20 ++++- src/plugins/debugger/cdb/cdbdebugengine_p.h | 3 +- .../debugger/cdb/cdbdebugeventcallback.cpp | 3 +- src/plugins/debugger/cdb/cdbmodules.cpp | 58 +++++++++++--- src/plugins/debugger/cdb/cdbmodules.h | 2 + src/plugins/debugger/moduleshandler.cpp | 79 ++++++++++++++++--- src/plugins/debugger/moduleshandler.h | 3 + 7 files changed, 142 insertions(+), 26 deletions(-) diff --git a/src/plugins/debugger/cdb/cdbdebugengine.cpp b/src/plugins/debugger/cdb/cdbdebugengine.cpp index afc938f2f65..30b8514a13c 100644 --- a/src/plugins/debugger/cdb/cdbdebugengine.cpp +++ b/src/plugins/debugger/cdb/cdbdebugengine.cpp @@ -1516,12 +1516,26 @@ void CdbDebugEnginePrivate::updateModules() static const char *dumperPrefixC = "dumper"; -void CdbDebugEnginePrivate::handleModuleLoad(const QString &name) +void CdbDebugEnginePrivate::handleModuleLoad(quint64 offset, const QString &name) { if (debugCDB>2) - qDebug() << Q_FUNC_INFO << "\n " << name; + qDebug() << Q_FUNC_INFO << "\n " << offset << name; + Module module; + // Determine module parameters by offset. The callback has almost all the + // parameters we need with the exception of 'symbolsRead'. Retrieve the + // parameters by offset as to avoid a hack like 'check last module'. + QString errorMessage; + if (getModuleByOffset(interfaces().debugSymbols, offset, &module, &errorMessage)) { + manager()->modulesHandler()->addModule(module); + } else { + m_engine->warning(errorMessage); + } m_dumper->moduleLoadHook(name, m_hDebuggeeProcess); - updateModules(); +} + +void CdbDebugEnginePrivate::handleModuleUnload(const QString &imageName) +{ + manager()->modulesHandler()->removeModule(imageName); } void CdbDebugEnginePrivate::handleBreakpointEvent(PDEBUG_BREAKPOINT2 pBP) diff --git a/src/plugins/debugger/cdb/cdbdebugengine_p.h b/src/plugins/debugger/cdb/cdbdebugengine_p.h index 4c1b8442e4e..b8e4fe0abf5 100644 --- a/src/plugins/debugger/cdb/cdbdebugengine_p.h +++ b/src/plugins/debugger/cdb/cdbdebugengine_p.h @@ -87,7 +87,8 @@ public: void handleBreakpointEvent(PDEBUG_BREAKPOINT2 pBP); void cleanStackTrace(); void clearForRun(); - void handleModuleLoad(const QString &); + void handleModuleLoad(quint64 offset, const QString &); + void handleModuleUnload(const QString &name); CdbSymbolGroupContext *getSymbolGroupContext(int frameIndex, QString *errorMessage) const; void clearDisplay(); diff --git a/src/plugins/debugger/cdb/cdbdebugeventcallback.cpp b/src/plugins/debugger/cdb/cdbdebugeventcallback.cpp index 833bdb2d258..23d4b0f992e 100644 --- a/src/plugins/debugger/cdb/cdbdebugeventcallback.cpp +++ b/src/plugins/debugger/cdb/cdbdebugeventcallback.cpp @@ -174,7 +174,7 @@ STDMETHODIMP CdbDebugEventCallback::LoadModule( if (debugCDB > 1) qDebug() << Q_FUNC_INFO << ModuleName; handleModuleLoad(); - m_pEngine->m_d->handleModuleLoad(QString::fromUtf16(reinterpret_cast<const ushort *>(ModuleName))); + m_pEngine->m_d->handleModuleLoad(BaseOffset, QString::fromUtf16(reinterpret_cast<const ushort *>(ModuleName))); return S_OK; } @@ -188,6 +188,7 @@ STDMETHODIMP CdbDebugEventCallback::UnloadModule( Q_UNUSED(BaseOffset) if (debugCDB > 1) qDebug() << Q_FUNC_INFO << ImageBaseName; + m_pEngine->m_d->handleModuleUnload(QString::fromUtf16(reinterpret_cast<const ushort *>(ImageBaseName))); handleModuleUnload(); m_pEngine->m_d->updateModules(); return S_OK; diff --git a/src/plugins/debugger/cdb/cdbmodules.cpp b/src/plugins/debugger/cdb/cdbmodules.cpp index 439c87b14a9..eaad0eaf730 100644 --- a/src/plugins/debugger/cdb/cdbmodules.cpp +++ b/src/plugins/debugger/cdb/cdbmodules.cpp @@ -63,6 +63,51 @@ bool getModuleNameList(CIDebugSymbols *syms, QStringList *modules, QString *erro return true; } +// Get basic module parameters from struct (except name) +static inline void getBasicModuleParameters(const DEBUG_MODULE_PARAMETERS &p, + Module *module) +{ + const QString hexPrefix = QLatin1String("0x"); + module->symbolsRead = (p.Flags & DEBUG_MODULE_USER_MODE) + && (p.SymbolType != DEBUG_SYMTYPE_NONE); + module->startAddress = hexPrefix + QString::number(p.Base, 16); + module->endAddress = hexPrefix + QString::number((p.Base + p.Size), 16); +} + +// Get module name by index +static inline bool getModuleName(CIDebugSymbols *syms, ULONG index, QString *n, QString *errorMessage) +{ + WCHAR wszBuf[MAX_PATH]; + const HRESULT hr = syms->GetModuleNameStringWide(DEBUG_MODNAME_IMAGE, index, 0, wszBuf, MAX_PATH - 1, 0); + if (FAILED(hr) && hr != E_INVALIDARG) { + *errorMessage= CdbCore::msgComFailed("GetModuleNameStringWide", hr); + return false; + } + *n = QString::fromUtf16(reinterpret_cast<const ushort *>(wszBuf)); + return true; +} + +bool getModuleByOffset(CIDebugSymbols *syms, quint64 offset, + Module *module, QString *errorMessage) +{ + // Find by base address and set parameters + ULONG index; + HRESULT hr = syms->GetModuleByOffset(offset, 0, &index, 0); + if (FAILED(hr)) { + *errorMessage= CdbCore::msgComFailed("GetModuleByOffset", hr); + return false; + } + DEBUG_MODULE_PARAMETERS parameters; + memset(¶meters, 0, sizeof(DEBUG_MODULE_PARAMETERS)); + hr = syms->GetModuleParameters(1, 0, 0u, ¶meters); + if (FAILED(hr)) { + *errorMessage= CdbCore::msgComFailed("GetModuleParameters", hr); + return false; + } + getBasicModuleParameters(parameters, module); + return getModuleName(syms, index, &(module->moduleName), errorMessage); +} + bool getModuleList(CIDebugSymbols *syms, QList<Module> *modules, QString *errorMessage) { ULONG count; @@ -79,22 +124,13 @@ bool getModuleList(CIDebugSymbols *syms, QList<Module> *modules, QString *errorM return false; } // fill array - const QString hexPrefix = QLatin1String("0x"); - WCHAR wszBuf[MAX_PATH]; for (ULONG m = 0; m < count; m++) { const DEBUG_MODULE_PARAMETERS &p = parameters.at(m); if (p.Base != DEBUG_INVALID_OFFSET) { // Partial results? Module module; - module.symbolsRead = (p.Flags & DEBUG_MODULE_USER_MODE) - && (p.SymbolType != DEBUG_SYMTYPE_NONE); - module.startAddress = hexPrefix + QString::number(p.Base, 16); - module.endAddress = hexPrefix + QString::number((p.Base + p.Size), 16); - hr = syms->GetModuleNameStringWide(DEBUG_MODNAME_IMAGE, m, 0, wszBuf, MAX_PATH - 1, 0); - if (FAILED(hr) && hr != E_INVALIDARG) { - *errorMessage= CdbCore::msgComFailed("GetModuleNameStringWide", hr); + getBasicModuleParameters(p, &module); + if (!getModuleName(syms, m, &(module.moduleName), errorMessage)) return false; - } - module.moduleName = QString::fromUtf16(reinterpret_cast<const ushort *>(wszBuf)); modules->push_back(module); } } diff --git a/src/plugins/debugger/cdb/cdbmodules.h b/src/plugins/debugger/cdb/cdbmodules.h index 768e9b495d4..792ba526fac 100644 --- a/src/plugins/debugger/cdb/cdbmodules.h +++ b/src/plugins/debugger/cdb/cdbmodules.h @@ -42,6 +42,8 @@ class Symbol; bool getModuleList(CIDebugSymbols *syms, QList<Module> *modules, QString *errorMessage); bool getModuleNameList(CIDebugSymbols *syms, QStringList *modules, QString *errorMessage); +bool getModuleByOffset(CIDebugSymbols *syms, quint64 offset, Module *module, QString *errorMessage); + // Search symbols matching a pattern. Does not filter on module names. bool searchSymbols(CIDebugSymbols *syms, const QString &pattern, QStringList *matches, QString *errorMessage); diff --git a/src/plugins/debugger/moduleshandler.cpp b/src/plugins/debugger/moduleshandler.cpp index dc7c1ac0c75..d92ae7660db 100644 --- a/src/plugins/debugger/moduleshandler.cpp +++ b/src/plugins/debugger/moduleshandler.cpp @@ -56,9 +56,7 @@ class Debugger::Internal::ModulesModel : public QAbstractItemModel Q_OBJECT public: - ModulesModel(ModulesHandler *parent) - : QAbstractItemModel(parent) - {} + explicit ModulesModel(ModulesHandler *parent); // QAbstractItemModel int columnCount(const QModelIndex &parent) const @@ -72,13 +70,27 @@ public: QVariant data(const QModelIndex &index, int role) const; bool setData(const QModelIndex &index, const QVariant &value, int role); - void clearModel() { if (!m_modules.isEmpty()) { m_modules.clear(); update(); } } - void update() { reset(); } + void clearModel(); + void addModule(const Module &m); + void removeModule(const QString &moduleName); + void setModules(const QList<Module> &m); -public: + const QList<Module> &modules() const { return m_modules; } + +private: + int indexOfModule(const QString &name) const; + + const QVariant m_yes; + const QVariant m_no; QList<Module> m_modules; }; +ModulesModel::ModulesModel(ModulesHandler *parent) : + QAbstractItemModel(parent), + m_yes(tr("yes")), m_no(tr("no")) +{ +} + QVariant ModulesModel::headerData(int section, Qt::Orientation orientation, int role) const { @@ -112,7 +124,7 @@ QVariant ModulesModel::data(const QModelIndex &index, int role) const break; case 1: if (role == Qt::DisplayRole) - return module.symbolsRead ? "yes" : "no"; + return module.symbolsRead ? m_yes : m_no; break; case 2: if (role == Qt::DisplayRole) @@ -131,6 +143,45 @@ bool ModulesModel::setData(const QModelIndex &index, const QVariant &value, int return QAbstractItemModel::setData(index, value, role); } +void ModulesModel::addModule(const Module &m) +{ + beginInsertRows(QModelIndex(), m_modules.size(), m_modules.size()); + m_modules.push_back(m); + endInsertRows(); +} + +void ModulesModel::setModules(const QList<Module> &m) +{ + m_modules = m; + reset(); +} + +void ModulesModel::clearModel() +{ + if (!m_modules.isEmpty()) { + m_modules.clear(); + reset(); + } +} + +int ModulesModel::indexOfModule(const QString &name) const +{ + // Recent modules are more likely to be unloaded first. + for (int i = m_modules.size() - 1; i >= 0; i--) + if (m_modules.at(i).moduleName == name) + return i; + return -1; +} + +void ModulesModel::removeModule(const QString &moduleName) +{ + const int index = indexOfModule(moduleName); + QTC_ASSERT(index != -1, return); + + beginRemoveRows(QModelIndex(), index, index); + m_modules.removeAt(index); + endRemoveRows(); +} ////////////////////////////////////////////////////////////////// // @@ -155,16 +206,24 @@ void ModulesHandler::removeAll() m_model->clearModel(); } +void ModulesHandler::addModule(const Module &module) +{ + m_model->addModule(module); +} + +void ModulesHandler::removeModule(const QString &moduleName) +{ + m_model->removeModule(moduleName); +} void ModulesHandler::setModules(const QList<Module> &modules) { - m_model->m_modules = modules; - m_model->update(); + m_model->setModules(modules); } QList<Module> ModulesHandler::modules() const { - return m_model->m_modules; + return m_model->modules(); } #include "moduleshandler.moc" diff --git a/src/plugins/debugger/moduleshandler.h b/src/plugins/debugger/moduleshandler.h index 249d6ca242e..c0f8d19f736 100644 --- a/src/plugins/debugger/moduleshandler.h +++ b/src/plugins/debugger/moduleshandler.h @@ -100,6 +100,9 @@ public: QAbstractItemModel *model() const; void setModules(const QList<Module> &modules); + void addModule(const Module &module); + void removeModule(const QString &moduleName); + QList<Module> modules() const; void removeAll(); -- GitLab