forked from qt-creator/qt-creator
Make the "Show symbols" option of the module window work on Windows.
Introduce API to debug engines and debugger manager to do this. Reviewed-by: hjk <qtc-commiter@nokia.com>
This commit is contained in:
@@ -31,6 +31,8 @@
|
||||
#include "moduleshandler.h"
|
||||
#include "cdbdebugengine_p.h"
|
||||
|
||||
#include <QtCore/QFileInfo>
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
@@ -82,11 +84,13 @@ bool searchSymbols(IDebugSymbols3 *syms, const QString &pattern,
|
||||
QStringList *matches, QString *errorMessage)
|
||||
{
|
||||
matches->clear();
|
||||
ULONG64 handle;
|
||||
// E_NOINTERFACE means "no match"
|
||||
ULONG64 handle = 0;
|
||||
// E_NOINTERFACE means "no match". Apparently, it does not always
|
||||
// set handle.
|
||||
HRESULT hr = syms->StartSymbolMatchWide(pattern.utf16(), &handle);
|
||||
if (hr == E_NOINTERFACE) {
|
||||
syms->EndSymbolMatch(handle);
|
||||
if (handle)
|
||||
syms->EndSymbolMatch(handle);
|
||||
return true;
|
||||
}
|
||||
if (FAILED(hr)) {
|
||||
@@ -133,5 +137,27 @@ ResolveSymbolResult resolveSymbol(IDebugSymbols3 *syms, QString *symbol,
|
||||
return ResolveSymbolOk;
|
||||
}
|
||||
|
||||
// List symbols of a module
|
||||
bool getModuleSymbols(IDebugSymbols3 *syms, const QString &moduleName,
|
||||
QList<Symbol> *symbols, QString *errorMessage)
|
||||
{
|
||||
// Search all symbols and retrieve addresses
|
||||
symbols->clear();
|
||||
QStringList matches;
|
||||
const QString pattern = QFileInfo(moduleName).baseName() + QLatin1String("!*");
|
||||
if (!searchSymbols(syms, pattern, &matches, errorMessage))
|
||||
return false;
|
||||
const QString hexPrefix = QLatin1String("0x");
|
||||
foreach (const QString &name, matches) {
|
||||
Symbol symbol;
|
||||
symbol.name = name;
|
||||
ULONG64 offset = 0;
|
||||
if (SUCCEEDED(syms->GetOffsetByNameWide(name.utf16(), &offset)))
|
||||
symbol.address = hexPrefix + QString::number(offset, 16);
|
||||
symbols->push_back(symbol);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -40,6 +40,7 @@ namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class Module;
|
||||
class Symbol;
|
||||
|
||||
bool getModuleList(IDebugSymbols3 *syms, QList<Module> *modules, QString *errorMessage);
|
||||
// Search symbols matching a pattern
|
||||
@@ -54,6 +55,10 @@ enum ResolveSymbolResult { ResolveSymbolOk, ResolveSymbolAmbiguous,
|
||||
|
||||
ResolveSymbolResult resolveSymbol(IDebugSymbols3 *syms, QString *symbol, QString *errorMessage);
|
||||
|
||||
// List symbols of a module
|
||||
bool getModuleSymbols(IDebugSymbols3 *syms, const QString &moduleName,
|
||||
QList<Symbol> *symbols, QString *errorMessage);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -175,7 +175,7 @@ void DebuggerManager::init()
|
||||
m_statusLabel = new QLabel;
|
||||
m_breakWindow = new BreakWindow;
|
||||
m_disassemblerWindow = new DisassemblerWindow;
|
||||
m_modulesWindow = new ModulesWindow;
|
||||
m_modulesWindow = new ModulesWindow(this);
|
||||
m_outputWindow = new DebuggerOutputWindow;
|
||||
m_registerWindow = new RegisterWindow;
|
||||
m_stackWindow = new StackWindow;
|
||||
@@ -998,6 +998,12 @@ void DebuggerManager::loadSymbols(const QString &module)
|
||||
m_engine->loadSymbols(module);
|
||||
}
|
||||
|
||||
QList<Symbol> DebuggerManager::moduleSymbols(const QString &moduleName)
|
||||
{
|
||||
QTC_ASSERT(m_engine, return QList<Symbol>());
|
||||
return m_engine->moduleSymbols(moduleName);
|
||||
}
|
||||
|
||||
void DebuggerManager::stepExec()
|
||||
{
|
||||
QTC_ASSERT(m_engine, return);
|
||||
|
@@ -65,7 +65,7 @@ class WatchHandler;
|
||||
class SourceFilesWindow;
|
||||
class WatchData;
|
||||
class BreakpointData;
|
||||
|
||||
class Symbol;
|
||||
|
||||
// Note: the Debugger process itself is referred to as 'Debugger',
|
||||
// whereas the debugged process is referred to as 'Inferior' or 'Debuggee'.
|
||||
@@ -309,6 +309,8 @@ public:
|
||||
int status() const { return m_status; }
|
||||
DebuggerStartMode startMode() const { return m_startMode; }
|
||||
|
||||
QList<Symbol> moduleSymbols(const QString &moduleName);
|
||||
|
||||
signals:
|
||||
void debuggingFinished();
|
||||
void inferiorPidChanged(qint64 pid);
|
||||
|
@@ -2389,6 +2389,40 @@ void GdbEngine::loadAllSymbols()
|
||||
reloadModules();
|
||||
}
|
||||
|
||||
QList<Symbol> GdbEngine::moduleSymbols(const QString &moduleName)
|
||||
{
|
||||
QList<Symbol> rc;
|
||||
bool success = false;
|
||||
QString errorMessage;
|
||||
do {
|
||||
const QString nmBinary = QLatin1String("nm");
|
||||
QProcess proc;
|
||||
proc.start(nmBinary, QStringList() << QLatin1String("-D") << moduleName);
|
||||
if (!proc.waitForFinished()) {
|
||||
errorMessage = tr("Unable to run '%1': %2").arg(nmBinary, proc.errorString());
|
||||
break;
|
||||
}
|
||||
const QString contents = QString::fromLocal8Bit(proc.readAllStandardOutput());
|
||||
const QRegExp re(QLatin1String("([0-9a-f]+)?\\s+([^\\s]+)\\s+([^\\s]+)"));
|
||||
Q_ASSERT(re.isValid());
|
||||
foreach (const QString &line, contents.split(QLatin1Char('\n'))) {
|
||||
if (re.indexIn(line) != -1) {
|
||||
Symbol symbol;
|
||||
symbol.address = re.cap(1);
|
||||
symbol.state = re.cap(2);
|
||||
symbol.name = re.cap(3);
|
||||
rc.push_back(symbol);
|
||||
} else {
|
||||
qWarning("moduleSymbols: unhandled: %s", qPrintable(line));
|
||||
}
|
||||
}
|
||||
success = true;
|
||||
} while (false);
|
||||
if (!success)
|
||||
qWarning("moduleSymbols: %s\n", qPrintable(errorMessage));
|
||||
return rc;
|
||||
}
|
||||
|
||||
void GdbEngine::reloadModules()
|
||||
{
|
||||
sendCommand("info shared", ModulesList, QVariant());
|
||||
|
@@ -129,6 +129,7 @@ private:
|
||||
|
||||
void loadSymbols(const QString &moduleName);
|
||||
void loadAllSymbols();
|
||||
virtual QList<Symbol> moduleSymbols(const QString &moduleName);
|
||||
|
||||
Q_SLOT void setDebugDebuggingHelpers(const QVariant &on);
|
||||
Q_SLOT void setUseDebuggingHelpers(const QVariant &on);
|
||||
|
@@ -31,6 +31,7 @@
|
||||
#define DEBUGGER_IDEBUGGERENGINE_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QList>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QPoint;
|
||||
@@ -40,6 +41,8 @@ QT_END_NAMESPACE
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class Symbol;
|
||||
|
||||
class IDebuggerEngine : public QObject
|
||||
{
|
||||
public:
|
||||
@@ -79,6 +82,7 @@ public:
|
||||
virtual void reloadModules() = 0;
|
||||
virtual void loadSymbols(const QString &moduleName) = 0;
|
||||
virtual void loadAllSymbols() = 0;
|
||||
virtual QList<Symbol> moduleSymbols(const QString &moduleName) = 0;
|
||||
|
||||
virtual void reloadRegisters() = 0;
|
||||
|
||||
|
@@ -51,6 +51,19 @@ enum ModulesModelRoles
|
||||
LoadAllSymbolsRole
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Symbol
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
class Symbol
|
||||
{
|
||||
public:
|
||||
QString address;
|
||||
QString state;
|
||||
QString name;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
@@ -29,6 +29,7 @@
|
||||
|
||||
#include "moduleswindow.h"
|
||||
#include "moduleshandler.h" // for model roles
|
||||
#include "debuggermanager.h"
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QProcess>
|
||||
@@ -40,7 +41,7 @@
|
||||
#include <QtGui/QResizeEvent>
|
||||
#include <QtGui/QToolButton>
|
||||
#include <QtGui/QTreeWidget>
|
||||
|
||||
#include <QtGui/QApplication>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@@ -48,10 +49,14 @@
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
using Debugger::Internal::ModulesWindow;
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
ModulesWindow::ModulesWindow(QWidget *parent)
|
||||
: QTreeView(parent), m_alwaysResizeColumnsToContents(false)
|
||||
ModulesWindow::ModulesWindow(DebuggerManager *debuggerManager,
|
||||
QWidget *parent) :
|
||||
QTreeView(parent),
|
||||
m_alwaysResizeColumnsToContents(false),
|
||||
m_debuggerManager(debuggerManager)
|
||||
{
|
||||
setWindowTitle(tr("Modules"));
|
||||
setSortingEnabled(true);
|
||||
@@ -88,9 +93,12 @@ void ModulesWindow::resizeEvent(QResizeEvent *event)
|
||||
|
||||
void ModulesWindow::contextMenuEvent(QContextMenuEvent *ev)
|
||||
{
|
||||
QString name;
|
||||
QModelIndex index = indexAt(ev->pos());
|
||||
index = index.sibling(index.row(), 0);
|
||||
QString name = model()->data(index).toString();
|
||||
if (index.isValid())
|
||||
index = index.sibling(index.row(), 0);
|
||||
if (index.isValid())
|
||||
name = model()->data(index).toString();
|
||||
|
||||
QMenu menu;
|
||||
QAction *act0 = new QAction(tr("Update module list"), &menu);
|
||||
@@ -116,9 +124,6 @@ void ModulesWindow::contextMenuEvent(QContextMenuEvent *ev)
|
||||
act5->setDisabled(name.isEmpty());
|
||||
act6->setDisabled(name.isEmpty());
|
||||
act7->setDisabled(name.isEmpty());
|
||||
#ifndef Q_OS_LINUX
|
||||
act7->setDisabled(true);
|
||||
#endif
|
||||
|
||||
menu.addAction(act0);
|
||||
menu.addAction(act4);
|
||||
@@ -178,28 +183,26 @@ void ModulesWindow::showSymbols(const QString &name)
|
||||
{
|
||||
if (name.isEmpty())
|
||||
return;
|
||||
QProcess proc;
|
||||
proc.start("nm", QStringList() << "-D" << name);
|
||||
proc.waitForFinished();
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
const QList<Symbol> symbols = m_debuggerManager->moduleSymbols(name);
|
||||
QApplication::restoreOverrideCursor();
|
||||
if (symbols.empty())
|
||||
return;
|
||||
QTreeWidget *w = new QTreeWidget;
|
||||
w->setColumnCount(3);
|
||||
w->setRootIsDecorated(false);
|
||||
w->setAlternatingRowColors(true);
|
||||
//w->header()->hide();
|
||||
w->setHeaderLabels(QStringList() << tr("Address") << tr("Code") << tr("Symbol"));
|
||||
w->setWindowTitle(tr("Symbols in \"%1\"").arg(name));
|
||||
QString contents = QString::fromLocal8Bit(proc.readAllStandardOutput());
|
||||
QRegExp re("([0-9a-f]+)?\\s+([^\\s]+)\\s+([^\\s]+)");
|
||||
foreach (QString line, contents.split('\n')) {
|
||||
if (re.indexIn(line) != -1) {
|
||||
QTreeWidgetItem *it = new QTreeWidgetItem;
|
||||
it->setData(0, Qt::DisplayRole, re.cap(1));
|
||||
it->setData(1, Qt::DisplayRole, re.cap(2));
|
||||
it->setData(2, Qt::DisplayRole, re.cap(3));
|
||||
w->addTopLevelItem(it);
|
||||
} else {
|
||||
qDebug() << "UNHANDLED LINE" << line;
|
||||
}
|
||||
foreach (const Symbol &s, symbols) {
|
||||
QTreeWidgetItem *it = new QTreeWidgetItem;
|
||||
it->setData(0, Qt::DisplayRole, s.address);
|
||||
it->setData(1, Qt::DisplayRole, s.state);
|
||||
it->setData(2, Qt::DisplayRole, s.name);
|
||||
w->addTopLevelItem(it);
|
||||
}
|
||||
emit newDockRequested(w);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -35,12 +35,14 @@
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class DebuggerManager;
|
||||
|
||||
class ModulesWindow : public QTreeView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ModulesWindow(QWidget *parent = 0);
|
||||
explicit ModulesWindow(DebuggerManager *debuggerManager, QWidget *parent = 0);
|
||||
|
||||
signals:
|
||||
void reloadModulesRequested();
|
||||
@@ -62,6 +64,7 @@ private:
|
||||
void setModel(QAbstractItemModel *model);
|
||||
|
||||
bool m_alwaysResizeColumnsToContents;
|
||||
DebuggerManager *m_debuggerManager;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -38,6 +38,7 @@
|
||||
#include "registerhandler.h"
|
||||
#include "stackhandler.h"
|
||||
#include "watchhandler.h"
|
||||
#include "moduleshandler.h"
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
@@ -405,6 +406,10 @@ void ScriptEngine::reloadModules()
|
||||
{
|
||||
}
|
||||
|
||||
QList<Symbol> ScriptEngine::moduleSymbols(const QString & /*moduleName*/)
|
||||
{
|
||||
return QList<Symbol>();
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
@@ -102,6 +102,7 @@ private:
|
||||
|
||||
void loadSymbols(const QString &moduleName);
|
||||
void loadAllSymbols();
|
||||
virtual QList<Symbol> moduleSymbols(const QString &moduleName);
|
||||
void reloadDisassembler();
|
||||
void reloadModules();
|
||||
void reloadRegisters() {}
|
||||
|
Reference in New Issue
Block a user