forked from qt-creator/qt-creator
Debugger: Add incremental API for modules.
And use it from CDB's module load/unload callbacks instead of re-setting all modules. Some cleanup. Acked-by: hjk
This commit is contained in:
@@ -1558,12 +1558,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)
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
{
|
||||
@@ -117,7 +129,7 @@ QVariant ModulesModel::data(const QModelIndex &index, int role) const
|
||||
break;
|
||||
case 2:
|
||||
if (role == Qt::DisplayRole)
|
||||
return module.symbolsRead ? "yes" : "no";
|
||||
return module.symbolsRead ? m_yes : m_no;
|
||||
break;
|
||||
case 3:
|
||||
if (role == Qt::DisplayRole)
|
||||
@@ -136,6 +148,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();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@@ -160,16 +211,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"
|
||||
|
||||
@@ -101,6 +101,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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user