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./Fixed conflicts in 2.0 Acked-by: hjk
This commit is contained in:
@@ -1516,12 +1516,26 @@ void CdbDebugEnginePrivate::updateModules()
|
|||||||
|
|
||||||
static const char *dumperPrefixC = "dumper";
|
static const char *dumperPrefixC = "dumper";
|
||||||
|
|
||||||
void CdbDebugEnginePrivate::handleModuleLoad(const QString &name)
|
void CdbDebugEnginePrivate::handleModuleLoad(quint64 offset, const QString &name)
|
||||||
{
|
{
|
||||||
if (debugCDB>2)
|
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);
|
m_dumper->moduleLoadHook(name, m_hDebuggeeProcess);
|
||||||
updateModules();
|
}
|
||||||
|
|
||||||
|
void CdbDebugEnginePrivate::handleModuleUnload(const QString &imageName)
|
||||||
|
{
|
||||||
|
manager()->modulesHandler()->removeModule(imageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CdbDebugEnginePrivate::handleBreakpointEvent(PDEBUG_BREAKPOINT2 pBP)
|
void CdbDebugEnginePrivate::handleBreakpointEvent(PDEBUG_BREAKPOINT2 pBP)
|
||||||
|
|||||||
@@ -87,7 +87,8 @@ public:
|
|||||||
void handleBreakpointEvent(PDEBUG_BREAKPOINT2 pBP);
|
void handleBreakpointEvent(PDEBUG_BREAKPOINT2 pBP);
|
||||||
void cleanStackTrace();
|
void cleanStackTrace();
|
||||||
void clearForRun();
|
void clearForRun();
|
||||||
void handleModuleLoad(const QString &);
|
void handleModuleLoad(quint64 offset, const QString &);
|
||||||
|
void handleModuleUnload(const QString &name);
|
||||||
CdbSymbolGroupContext *getSymbolGroupContext(int frameIndex, QString *errorMessage) const;
|
CdbSymbolGroupContext *getSymbolGroupContext(int frameIndex, QString *errorMessage) const;
|
||||||
void clearDisplay();
|
void clearDisplay();
|
||||||
|
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ STDMETHODIMP CdbDebugEventCallback::LoadModule(
|
|||||||
if (debugCDB > 1)
|
if (debugCDB > 1)
|
||||||
qDebug() << Q_FUNC_INFO << ModuleName;
|
qDebug() << Q_FUNC_INFO << ModuleName;
|
||||||
handleModuleLoad();
|
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;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,6 +188,7 @@ STDMETHODIMP CdbDebugEventCallback::UnloadModule(
|
|||||||
Q_UNUSED(BaseOffset)
|
Q_UNUSED(BaseOffset)
|
||||||
if (debugCDB > 1)
|
if (debugCDB > 1)
|
||||||
qDebug() << Q_FUNC_INFO << ImageBaseName;
|
qDebug() << Q_FUNC_INFO << ImageBaseName;
|
||||||
|
m_pEngine->m_d->handleModuleUnload(QString::fromUtf16(reinterpret_cast<const ushort *>(ImageBaseName)));
|
||||||
handleModuleUnload();
|
handleModuleUnload();
|
||||||
m_pEngine->m_d->updateModules();
|
m_pEngine->m_d->updateModules();
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|||||||
@@ -63,6 +63,51 @@ bool getModuleNameList(CIDebugSymbols *syms, QStringList *modules, QString *erro
|
|||||||
return true;
|
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)
|
bool getModuleList(CIDebugSymbols *syms, QList<Module> *modules, QString *errorMessage)
|
||||||
{
|
{
|
||||||
ULONG count;
|
ULONG count;
|
||||||
@@ -79,22 +124,13 @@ bool getModuleList(CIDebugSymbols *syms, QList<Module> *modules, QString *errorM
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// fill array
|
// fill array
|
||||||
const QString hexPrefix = QLatin1String("0x");
|
|
||||||
WCHAR wszBuf[MAX_PATH];
|
|
||||||
for (ULONG m = 0; m < count; m++) {
|
for (ULONG m = 0; m < count; m++) {
|
||||||
const DEBUG_MODULE_PARAMETERS &p = parameters.at(m);
|
const DEBUG_MODULE_PARAMETERS &p = parameters.at(m);
|
||||||
if (p.Base != DEBUG_INVALID_OFFSET) { // Partial results?
|
if (p.Base != DEBUG_INVALID_OFFSET) { // Partial results?
|
||||||
Module module;
|
Module module;
|
||||||
module.symbolsRead = (p.Flags & DEBUG_MODULE_USER_MODE)
|
getBasicModuleParameters(p, &module);
|
||||||
&& (p.SymbolType != DEBUG_SYMTYPE_NONE);
|
if (!getModuleName(syms, m, &(module.moduleName), errorMessage))
|
||||||
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);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
module.moduleName = QString::fromUtf16(reinterpret_cast<const ushort *>(wszBuf));
|
|
||||||
modules->push_back(module);
|
modules->push_back(module);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ class Symbol;
|
|||||||
|
|
||||||
bool getModuleList(CIDebugSymbols *syms, QList<Module> *modules, QString *errorMessage);
|
bool getModuleList(CIDebugSymbols *syms, QList<Module> *modules, QString *errorMessage);
|
||||||
bool getModuleNameList(CIDebugSymbols *syms, QStringList *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.
|
// Search symbols matching a pattern. Does not filter on module names.
|
||||||
bool searchSymbols(CIDebugSymbols *syms, const QString &pattern,
|
bool searchSymbols(CIDebugSymbols *syms, const QString &pattern,
|
||||||
QStringList *matches, QString *errorMessage);
|
QStringList *matches, QString *errorMessage);
|
||||||
|
|||||||
@@ -56,9 +56,7 @@ class Debugger::Internal::ModulesModel : public QAbstractItemModel
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ModulesModel(ModulesHandler *parent)
|
explicit ModulesModel(ModulesHandler *parent);
|
||||||
: QAbstractItemModel(parent)
|
|
||||||
{}
|
|
||||||
|
|
||||||
// QAbstractItemModel
|
// QAbstractItemModel
|
||||||
int columnCount(const QModelIndex &parent) const
|
int columnCount(const QModelIndex &parent) const
|
||||||
@@ -72,13 +70,27 @@ public:
|
|||||||
QVariant data(const QModelIndex &index, int role) const;
|
QVariant data(const QModelIndex &index, int role) const;
|
||||||
bool setData(const QModelIndex &index, const QVariant &value, int role);
|
bool setData(const QModelIndex &index, const QVariant &value, int role);
|
||||||
|
|
||||||
void clearModel() { if (!m_modules.isEmpty()) { m_modules.clear(); update(); } }
|
void clearModel();
|
||||||
void update() { reset(); }
|
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;
|
QList<Module> m_modules;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ModulesModel::ModulesModel(ModulesHandler *parent) :
|
||||||
|
QAbstractItemModel(parent),
|
||||||
|
m_yes(tr("yes")), m_no(tr("no"))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
QVariant ModulesModel::headerData(int section,
|
QVariant ModulesModel::headerData(int section,
|
||||||
Qt::Orientation orientation, int role) const
|
Qt::Orientation orientation, int role) const
|
||||||
{
|
{
|
||||||
@@ -112,7 +124,7 @@ QVariant ModulesModel::data(const QModelIndex &index, int role) const
|
|||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if (role == Qt::DisplayRole)
|
if (role == Qt::DisplayRole)
|
||||||
return module.symbolsRead ? "yes" : "no";
|
return module.symbolsRead ? m_yes : m_no;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
if (role == Qt::DisplayRole)
|
if (role == Qt::DisplayRole)
|
||||||
@@ -131,6 +143,45 @@ bool ModulesModel::setData(const QModelIndex &index, const QVariant &value, int
|
|||||||
return QAbstractItemModel::setData(index, value, role);
|
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();
|
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)
|
void ModulesHandler::setModules(const QList<Module> &modules)
|
||||||
{
|
{
|
||||||
m_model->m_modules = modules;
|
m_model->setModules(modules);
|
||||||
m_model->update();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<Module> ModulesHandler::modules() const
|
QList<Module> ModulesHandler::modules() const
|
||||||
{
|
{
|
||||||
return m_model->m_modules;
|
return m_model->modules();
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "moduleshandler.moc"
|
#include "moduleshandler.moc"
|
||||||
|
|||||||
@@ -100,6 +100,9 @@ public:
|
|||||||
QAbstractItemModel *model() const;
|
QAbstractItemModel *model() const;
|
||||||
|
|
||||||
void setModules(const QList<Module> &modules);
|
void setModules(const QList<Module> &modules);
|
||||||
|
void addModule(const Module &module);
|
||||||
|
void removeModule(const QString &moduleName);
|
||||||
|
|
||||||
QList<Module> modules() const;
|
QList<Module> modules() const;
|
||||||
void removeAll();
|
void removeAll();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user