Commit 7d8d5167 authored by hjk's avatar hjk

debugger: polish module symbols

parent a9f825fc
......@@ -1399,7 +1399,7 @@ void CdbEngine::loadAllSymbols()
void CdbEngine::requestModuleSymbols(const QString &moduleName)
{
QList<Symbol> rc;
Symbols rc;
QString errorMessage;
bool success = false;
do {
......@@ -1413,7 +1413,7 @@ void CdbEngine::requestModuleSymbols(const QString &moduleName)
} while (false);
if (!success)
warning(errorMessage);
showModuleSymbols(moduleName, rc);
debuggerCore()->showModuleSymbols(moduleName, rc);
}
void CdbEngine::reloadRegisters()
......
......@@ -113,7 +113,7 @@ bool getModuleByOffset(CIDebugSymbols *syms, quint64 offset,
return getModuleName(syms, index, &(module->moduleName), errorMessage);
}
bool getModuleList(CIDebugSymbols *syms, QList<Module> *modules, QString *errorMessage)
bool getModuleList(CIDebugSymbols *syms, Modules *modules, QString *errorMessage)
{
ULONG count;
modules->clear();
......@@ -261,7 +261,7 @@ ResolveSymbolResult resolveSymbol(CIDebugSymbols *syms, const QString &pattern,
// List symbols of a module
bool getModuleSymbols(CIDebugSymbols *syms, const QString &moduleName,
QList<Symbol> *symbols, QString *errorMessage)
Symbols *symbols, QString *errorMessage)
{
// Search all symbols and retrieve addresses
symbols->clear();
......
......@@ -31,6 +31,7 @@
#define CDBMODULES_H
#include <QtCore/QStringList>
#include <QtCore/QVector>
#include "cdbcom.h"
......@@ -39,8 +40,10 @@ namespace Internal {
class Module;
class Symbol;
typedef QVector<Module> Modules;
typedef QVector<Symbol> Symbols;
bool getModuleList(CIDebugSymbols *syms, QList<Module> *modules, QString *errorMessage);
bool getModuleList(CIDebugSymbols *syms, Modules *modules, QString *errorMessage);
bool getModuleNameList(CIDebugSymbols *syms, QStringList *modules, QString *errorMessage);
bool getModuleByOffset(CIDebugSymbols *syms, quint64 offset, Module *module, QString *errorMessage);
......@@ -62,7 +65,7 @@ ResolveSymbolResult resolveSymbol(CIDebugSymbols *syms, const QString &pattern,
// List symbols of a module
bool getModuleSymbols(CIDebugSymbols *syms, const QString &moduleName,
QList<Symbol> *symbols, QString *errorMessage);
Symbols *symbols, QString *errorMessage);
} // namespace Internal
} // namespace Debugger
......
......@@ -314,6 +314,7 @@ void DisassemblerViewAgent::setFrame(const StackFrame &frame,
{
d->frame = frame;
d->tryMixed = tryMixed;
d->setMarker = setMarker;
if (isMixed()) {
QHash<QString, DisassemblerLines>::ConstIterator it =
d->cache.find(frameKey(frame));
......
......@@ -158,7 +158,8 @@ enum DebuggerCapabilities
ReturnFromFunctionCapability = 0x400,
CreateFullBacktraceCapability = 0x800,
AddWatcherCapability = 0x1000,
WatchpointCapability = 0x2000
WatchpointCapability = 0x2000,
ShowModuleSymbolsCapability = 0x4000,
};
enum LogChannel
......
......@@ -35,6 +35,7 @@
#include <QtCore/QObject>
#include <QtCore/QMultiMap>
#include <QtCore/QVector>
QT_BEGIN_NAMESPACE
class QIcon;
......@@ -60,6 +61,7 @@ namespace Internal {
class BreakHandler;
class SnapshotHandler;
class Symbol;
// This is the "internal" interface of the debugger plugin that's
// used by debugger views and debugger engines. The interface is
......@@ -104,7 +106,6 @@ public:
virtual void writeSettings() const = 0;
virtual bool isReverseDebugging() const = 0;
virtual void createNewDock(QWidget *widget) = 0;
virtual void runControlStarted(DebuggerRunControl *runControl) = 0;
virtual void runControlFinished(DebuggerRunControl *runControl) = 0;
virtual void displayDebugger(DebuggerEngine *engine, bool updateEngine) = 0;
......@@ -114,6 +115,8 @@ public:
virtual bool initialize(const QStringList &arguments, QString *errorMessage) = 0;
virtual QWidget *mainWindow() const = 0;
virtual QString gdbBinaryForToolChain(int toolChain) const = 0;
virtual void showModuleSymbols(const QString &moduleName,
const QVector<Symbol> &symbols);
virtual Utils::SavedAction *action(int code) const = 0;
virtual bool boolSetting(int code) const = 0;
......
......@@ -63,9 +63,6 @@
#include <QtCore/QTimer>
#include <QtCore/QFutureInterface>
#include <QtGui/QStandardItemModel>
#include <QtGui/QAction>
#include <QtGui/QTreeWidget>
#include <QtGui/QMessageBox>
using namespace Core;
......@@ -301,26 +298,6 @@ void DebuggerEngine::removeTooltip()
hideDebuggerToolTip();
}
void DebuggerEngine::showModuleSymbols
(const QString &moduleName, const Symbols &symbols)
{
QTreeWidget *w = new QTreeWidget;
w->setColumnCount(3);
w->setRootIsDecorated(false);
w->setAlternatingRowColors(true);
w->setSortingEnabled(true);
w->setHeaderLabels(QStringList() << tr("Symbol") << tr("Address") << tr("Code"));
w->setWindowTitle(tr("Symbols in \"%1\"").arg(moduleName));
foreach (const Symbol &s, symbols) {
QTreeWidgetItem *it = new QTreeWidgetItem;
it->setData(0, Qt::DisplayRole, s.name);
it->setData(1, Qt::DisplayRole, s.address);
it->setData(2, Qt::DisplayRole, s.state);
w->addTopLevelItem(it);
}
debuggerCore()->createNewDock(w);
}
void DebuggerEngine::frameUp()
{
int currentIndex = stackHandler()->currentIndex();
......
......@@ -247,7 +247,6 @@ public:
void handleStartFailed();
bool debuggerActionsEnabled() const;
static bool debuggerActionsEnabled(DebuggerState state);
void showModuleSymbols(const QString &moduleName, const Internal::Symbols &symbols);
void breakByFunction(const QString &functionName);
void breakByFunctionMain();
......@@ -332,15 +331,18 @@ protected:
protected:
DebuggerRunControl *runControl() const;
static QString msgWatchpointTriggered(BreakpointId id, int number, quint64 address);
static QString msgWatchpointTriggered(BreakpointId id, int number, quint64 address,
const QString &threadId);
static QString msgBreakpointTriggered(BreakpointId id, int number, const QString &threadId);
static QString msgWatchpointTriggered(BreakpointId id,
int number, quint64 address);
static QString msgWatchpointTriggered(BreakpointId id,
int number, quint64 address, const QString &threadId);
static QString msgBreakpointTriggered(BreakpointId id,
int number, const QString &threadId);
static QString msgStopped(const QString &reason = QString());
static QString msgStoppedBySignal(const QString &meaning, const QString &name);
static QString msgStoppedByException(const QString &description, const QString &threadId);
static QString msgStoppedByException(const QString &description,
const QString &threadId);
static QString msgInterrupted();
void showStoppedBySignalMessageBox(QString meaning, QString name);
void showStoppedBySignalMessageBox(const QString meaning, QString name);
void showStoppedByExceptionMessageBox(const QString &description);
private:
......@@ -349,7 +351,6 @@ private:
void setState(DebuggerState state, bool forced = false);
void setSlaveEngine(bool value);
friend class DebuggerEnginePrivate;
DebuggerEnginePrivate *d;
};
......
......@@ -117,6 +117,7 @@
#include <QtGui/QTextBlock>
#include <QtGui/QTextCursor>
#include <QtGui/QToolButton>
#include <QtGui/QTreeWidget>
#include <climits>
......@@ -848,7 +849,7 @@ static bool isDebuggable(IEditor *editor)
///////////////////////////////////////////////////////////////////////
//
// DebuggerPluginPrivate
// Debugger Actions
//
///////////////////////////////////////////////////////////////////////
......@@ -1284,6 +1285,8 @@ public slots:
bool boolSetting(int code) const;
QString stringSetting(int code) const;
void showModuleSymbols(const QString &moduleName, const Symbols &symbols);
public:
DebuggerState m_state;
DebuggerUISwitcher *m_uiSwitcher;
......@@ -3324,9 +3327,36 @@ QString DebuggerPluginPrivate::stringSetting(int code) const
return m_debuggerSettings->item(code)->value().toString();
}
void DebuggerPluginPrivate::showModuleSymbols(const QString &moduleName,
const Symbols &symbols)
{
QTreeWidget *w = new QTreeWidget;
w->setColumnCount(5);
w->setRootIsDecorated(false);
w->setAlternatingRowColors(true);
w->setSortingEnabled(true);
QStringList header;
header.append(tr("Symbol"));
header.append(tr("Address"));
header.append(tr("Code"));
header.append(tr("Section"));
header.append(tr("Name"));
w->setHeaderLabels(header);
w->setWindowTitle(tr("Symbols in \"%1\"").arg(moduleName));
foreach (const Symbol &s, symbols) {
QTreeWidgetItem *it = new QTreeWidgetItem;
it->setData(0, Qt::DisplayRole, s.name);
it->setData(1, Qt::DisplayRole, s.address);
it->setData(2, Qt::DisplayRole, s.state);
it->setData(3, Qt::DisplayRole, s.section);
it->setData(4, Qt::DisplayRole, s.demangled);
w->addTopLevelItem(it);
}
createNewDock(w);
}
} // namespace Internal
using namespace Debugger::Internal;
///////////////////////////////////////////////////////////////////////
//
......@@ -3334,6 +3364,8 @@ using namespace Debugger::Internal;
//
///////////////////////////////////////////////////////////////////////
using namespace Debugger::Internal;
DebuggerPlugin::DebuggerPlugin()
{
theDebuggerCore = new DebuggerPluginPrivate(this);
......
......@@ -1777,14 +1777,19 @@ void GdbEngine::setupEngine()
unsigned GdbEngine::debuggerCapabilities() const
{
unsigned caps = ReverseSteppingCapability
| AutoDerefPointersCapability | DisassemblerCapability
| RegisterCapability | ShowMemoryCapability
| JumpToLineCapability | ReloadModuleCapability
| ReloadModuleSymbolsCapability | BreakOnThrowAndCatchCapability
| AutoDerefPointersCapability
| DisassemblerCapability
| RegisterCapability
| ShowMemoryCapability
| JumpToLineCapability
| ReloadModuleCapability
| ReloadModuleSymbolsCapability
| BreakOnThrowAndCatchCapability
| ReturnFromFunctionCapability
| CreateFullBacktraceCapability
| WatchpointCapability
| AddWatcherCapability;
| AddWatcherCapability
| ShowModuleSymbolsCapability;
if (startParameters().startMode == AttachCore)
return caps;
......@@ -2723,36 +2728,76 @@ void GdbEngine::loadAllSymbols()
void GdbEngine::requestModuleSymbols(const QString &moduleName)
{
QList<Symbol> rc;
bool success = false;
QString errorMessage;
do {
const QString nmBinary = _("nm");
QProcess proc;
proc.start(nmBinary, QStringList() << _("-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(_("([0-9a-f]+)?\\s+([^\\s]+)\\s+([^\\s]+)"));
Q_ASSERT(re.isValid());
foreach (const QString &line, contents.split(_c('\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);
QTemporaryFile tf(QDir::tempPath() + _("/gdbsymbols"));
if (!tf.open())
return;
QString fileName = tf.fileName();
tf.close();
postCommand("maint print msymbols " + fileName.toLocal8Bit()
+ " " + moduleName.toLocal8Bit(),
NeedsStop, CB(handleShowModuleSymbols),
QVariant(moduleName + QLatin1Char('@') + fileName));
}
void GdbEngine::handleShowModuleSymbols(const GdbResponse &response)
{
const QString cookie = response.cookie.toString();
const QString moduleName = cookie.section(QLatin1Char('@'), 0, 0);
const QString fileName = cookie.section(QLatin1Char('@'), 1, 1);
if (response.resultClass == GdbResultDone) {
Symbols rc;
QFile file(fileName);
file.open(QIODevice::ReadOnly);
// Object file /opt/dev/qt/lib/libQtNetworkMyns.so.4:
// [ 0] A 0x16bd64 _DYNAMIC moc_qudpsocket.cpp
// [12] S 0xe94680 _ZN4myns5QFileC1Ev section .plt myns::QFile::QFile()
foreach (const QByteArray &line, file.readAll().split('\n')) {
if (line.isEmpty())
continue;
if (!line.at(0) == '[')
continue;
int posCode = line.indexOf(']') + 2;
int posAddress = line.indexOf("0x", posCode);
if (posAddress == -1)
continue;
int posName = line.indexOf(" ", posAddress);
int lenAddress = posName - posAddress - 1;
int posSection = line.indexOf(" section ");
int lenName = 0;
int lenSection = 0;
int posDemangled = 0;
if (posSection == -1) {
lenName = line.size() - posName;
posDemangled = posName;
} else {
qWarning("moduleSymbols: unhandled: %s", qPrintable(line));
lenName = posSection - posName;
posSection += 10;
posDemangled = line.indexOf(' ', posSection + 1);
if (posDemangled == -1) {
lenSection = line.size() - posSection;
} else {
lenSection = posDemangled - posSection;
posDemangled += 1;
}
}
int lenDemangled = 0;
if (posDemangled != -1)
lenDemangled = line.size() - posDemangled;
Symbol symbol;
symbol.state = _(line.mid(posCode, 1));
symbol.address = _(line.mid(posAddress, lenAddress));
symbol.name = _(line.mid(posName, lenName));
symbol.section = _(line.mid(posSection, lenSection));
symbol.demangled = _(line.mid(posDemangled, lenDemangled));
rc.push_back(symbol);
}
success = true;
} while (false);
if (!success)
qWarning("moduleSymbols: %s\n", qPrintable(errorMessage));
showModuleSymbols(moduleName, rc);
file.close();
file.remove();
debuggerCore()->showModuleSymbols(moduleName, rc);
} else {
showMessageBox(QMessageBox::Critical, tr("Cannot Read Symbols"),
tr("Cannot read symbols for module \"%1\".").arg(fileName));
}
}
void GdbEngine::reloadModules()
......@@ -2773,7 +2818,7 @@ void GdbEngine::reloadModulesInternal()
void GdbEngine::handleModulesList(const GdbResponse &response)
{
QList<Module> modules;
Modules modules;
if (response.resultClass == GdbResultDone) {
// That's console-based output, likely Linux or Windows,
// but we can avoid the #ifdef here.
......
......@@ -374,6 +374,7 @@ private: ////////// View & Data Stuff //////////
void examineModules();
void reloadModulesInternal();
void handleModulesList(const GdbResponse &response);
void handleShowModuleSymbols(const GdbResponse &response);
bool m_modulesListOutdated;
......
......@@ -148,7 +148,7 @@ void ModulesModel::removeModule(const QString &moduleName)
const int index = indexOfModule(moduleName);
QTC_ASSERT(index != -1, return);
beginRemoveRows(QModelIndex(), index, index);
m_modules.removeAt(index);
m_modules.remove(index);
endRemoveRows();
}
......
......@@ -30,7 +30,7 @@
#ifndef DEBUGGER_MODULESHANDLER_H
#define DEBUGGER_MODULESHANDLER_H
#include <QtCore/QList>
#include <QtCore/QVector>
#include <QtCore/QObject>
#include <QtGui/QSortFilterProxyModel>
......@@ -54,9 +54,11 @@ public:
QString address;
QString state;
QString name;
QString section;
QString demangled;
};
typedef QList<Symbol> Symbols;
typedef QVector<Symbol> Symbols;
//////////////////////////////////////////////////////////////////
//
......@@ -88,7 +90,7 @@ public:
QString endAddress;
};
typedef QList<Module> Modules;
typedef QVector<Module> Modules;
//////////////////////////////////////////////////////////////////
......
......@@ -95,9 +95,9 @@ void ModulesWindow::contextMenuEvent(QContextMenuEvent *ev)
actUpdateModuleList
->setEnabled(enabled && (capabilities & ReloadModuleCapability));
QAction *actShowSourceFiles
QAction *actShowModuleSources
= new QAction(tr("Show Source Files for Module \"%1\"").arg(name), &menu);
actShowSourceFiles
actShowModuleSources
->setEnabled(enabled && (capabilities & ReloadModuleCapability));
QAction *actLoadSymbolsForAllModules
......@@ -112,14 +112,14 @@ void ModulesWindow::contextMenuEvent(QContextMenuEvent *ev)
QAction *actLoadSymbolsForModule = 0;
QAction *actEditFile = 0;
QAction *actShowSymbols = 0;
QAction *actShowModuleSymbols = 0;
if (name.isEmpty()) {
actLoadSymbolsForModule = new QAction(tr("Load Symbols for Module"), &menu);
actLoadSymbolsForModule->setEnabled(false);
actEditFile = new QAction(tr("Edit File"), &menu);
actEditFile->setEnabled(false);
actShowSymbols = new QAction(tr("Show Symbols"), &menu);
actShowSymbols->setEnabled(false);
actShowModuleSymbols = new QAction(tr("Show Symbols"), &menu);
actShowModuleSymbols->setEnabled(false);
} else {
actLoadSymbolsForModule
= new QAction(tr("Load Symbols for Module \"%1\"").arg(name), &menu);
......@@ -127,17 +127,19 @@ void ModulesWindow::contextMenuEvent(QContextMenuEvent *ev)
->setEnabled(capabilities & ReloadModuleSymbolsCapability);
actEditFile
= new QAction(tr("Edit File \"%1\"").arg(name), &menu);
actShowSymbols
actShowModuleSymbols
= new QAction(tr("Show Symbols in File \"%1\"").arg(name), &menu);
actShowModuleSymbols
->setEnabled(capabilities & ShowModuleSymbolsCapability);
}
menu.addAction(actUpdateModuleList);
//menu.addAction(actShowSourceFiles); // FIXME
//menu.addAction(actShowModuleSources); // FIXME
menu.addAction(actLoadSymbolsForAllModules);
menu.addAction(actExamineAllModules);
menu.addAction(actLoadSymbolsForModule);
menu.addAction(actEditFile);
//menu.addAction(actShowSymbols); // FIXME
menu.addAction(actShowModuleSymbols);
menu.addSeparator();
QAction *actAdjustColumnWidths =
menu.addAction(tr("Adjust Column Widths to Contents"));
......@@ -150,25 +152,24 @@ void ModulesWindow::contextMenuEvent(QContextMenuEvent *ev)
QAction *act = menu.exec(ev->globalPos());
if (act == actUpdateModuleList) {
if (act == actUpdateModuleList)
engine->reloadModules();
} else if (act == actAdjustColumnWidths) {
resizeColumnsToContents();
} else if (act == actAlwaysAdjustColumnWidth) {
setAlwaysResizeColumnsToContents(!m_alwaysResizeColumnsToContents);
//} else if (act == actShowSourceFiles) {
// emit displaySourceRequested(name);
} else if (act == actLoadSymbolsForAllModules) {
engine->loadAllSymbols();
} else if (act == actExamineAllModules) {
engine->examineModules();
} else if (act == actLoadSymbolsForModule) {
engine->loadSymbols(name);
} else if (act == actEditFile) {
debuggerCore()->gotoLocation(name);
} else if (act == actShowSymbols) {
// FIXME setModelData(RequestModuleSymbolsRole, name);
}
else if (act == actAdjustColumnWidths)
resizeColumnsToContents();
else if (act == actAlwaysAdjustColumnWidth)
setAlwaysResizeColumnsToContents(!m_alwaysResizeColumnsToContents);
else if (act == actShowModuleSources)
engine->loadSymbols(name);
else if (act == actLoadSymbolsForAllModules)
engine->loadAllSymbols();
else if (act == actExamineAllModules)
engine->examineModules();
else if (act == actLoadSymbolsForModule)
engine->loadSymbols(name);
else if (act == actEditFile)
debuggerCore()->gotoLocation(name);
else if (act == actShowModuleSymbols)
engine->requestModuleSymbols(name);
}
void ModulesWindow::resizeColumnsToContents()
......
......@@ -436,7 +436,7 @@ void PdbEngine::handleListSymbols(const PdbResponse &response)
symbol.name = _(item.findChild("name").data());
symbols.append(symbol);
}
showModuleSymbols(moduleName, symbols);
debuggerCore()->showModuleSymbols(moduleName, symbols);
}
//////////////////////////////////////////////////////////////////////
......
......@@ -385,7 +385,7 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
}
} else {
actSetWatchpointAtVariableAddress =
new QAction(tr("At Watchpoint"), &menu);
new QAction(tr("Add Watchpoint"), &menu);
actSetWatchpointAtVariableAddress->setEnabled(false);
}
actSetWatchpointAtVariableAddress->setToolTip(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment