forked from qt-creator/qt-creator
Fixes: debugger: try accessing compiled-in dumpers when attaching to an
external application
This commit is contained in:
@@ -296,6 +296,8 @@ void DebuggerManager::init()
|
|||||||
this, SLOT(watchExpression(QString)));
|
this, SLOT(watchExpression(QString)));
|
||||||
connect(localsView, SIGNAL(settingsDialogRequested()),
|
connect(localsView, SIGNAL(settingsDialogRequested()),
|
||||||
this, SIGNAL(settingsDialogRequested()));
|
this, SIGNAL(settingsDialogRequested()));
|
||||||
|
connect(localsView, SIGNAL(requestRecheckCustomDumperAvailability()),
|
||||||
|
this, SLOT(recheckCustomDumperAvailability()));
|
||||||
|
|
||||||
// Watchers
|
// Watchers
|
||||||
QTreeView *watchersView = qobject_cast<QTreeView *>(m_watchersWindow);
|
QTreeView *watchersView = qobject_cast<QTreeView *>(m_watchersWindow);
|
||||||
@@ -316,6 +318,8 @@ void DebuggerManager::init()
|
|||||||
this, SIGNAL(setSessionValueRequested(QString,QVariant)));
|
this, SIGNAL(setSessionValueRequested(QString,QVariant)));
|
||||||
connect(watchersView, SIGNAL(settingsDialogRequested()),
|
connect(watchersView, SIGNAL(settingsDialogRequested()),
|
||||||
this, SIGNAL(settingsDialogRequested()));
|
this, SIGNAL(settingsDialogRequested()));
|
||||||
|
connect(watchersView, SIGNAL(requestRecheckCustomDumperAvailability()),
|
||||||
|
this, SLOT(recheckCustomDumperAvailability()));
|
||||||
|
|
||||||
// Tooltip
|
// Tooltip
|
||||||
QTreeView *tooltipView = qobject_cast<QTreeView *>(m_tooltipWindow);
|
QTreeView *tooltipView = qobject_cast<QTreeView *>(m_tooltipWindow);
|
||||||
@@ -993,13 +997,13 @@ bool DebuggerManager::startNewDebugger(DebuggerStartMode mode)
|
|||||||
qDebug() << m_executable << type;
|
qDebug() << m_executable << type;
|
||||||
|
|
||||||
setDebuggerType(type);
|
setDebuggerType(type);
|
||||||
|
setBusyCursor(false);
|
||||||
setStatus(DebuggerProcessStartingUp);
|
setStatus(DebuggerProcessStartingUp);
|
||||||
if (!m_engine->startDebugger()) {
|
if (!m_engine->startDebugger()) {
|
||||||
setStatus(DebuggerProcessNotReady);
|
setStatus(DebuggerProcessNotReady);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_busy = false;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1199,6 +1203,18 @@ void DebuggerManager::breakAtMain()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool isAllowedTransition(int from, int to)
|
||||||
|
{
|
||||||
|
return (from == -1)
|
||||||
|
|| (from == DebuggerProcessNotReady && to == DebuggerProcessStartingUp)
|
||||||
|
|| (from == DebuggerProcessStartingUp && to == DebuggerInferiorStopped)
|
||||||
|
|| (from == DebuggerInferiorStopped && to == DebuggerInferiorRunningRequested)
|
||||||
|
|| (from == DebuggerInferiorRunningRequested && to == DebuggerInferiorRunning)
|
||||||
|
|| (from == DebuggerInferiorRunning && to == DebuggerInferiorStopRequested)
|
||||||
|
|| (from == DebuggerInferiorStopRequested && to == DebuggerInferiorStopped)
|
||||||
|
|| (to == DebuggerProcessNotReady);
|
||||||
|
}
|
||||||
|
|
||||||
void DebuggerManager::setStatus(int status)
|
void DebuggerManager::setStatus(int status)
|
||||||
{
|
{
|
||||||
if (Debugger::Constants::Internal::debug)
|
if (Debugger::Constants::Internal::debug)
|
||||||
@@ -1207,6 +1223,10 @@ void DebuggerManager::setStatus(int status)
|
|||||||
if (status == m_status)
|
if (status == m_status)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!isAllowedTransition(m_status, status))
|
||||||
|
qDebug() << "UNEXPECTED TRANSITION: " << m_status << status;
|
||||||
|
|
||||||
|
|
||||||
m_status = status;
|
m_status = status;
|
||||||
|
|
||||||
const bool started = status == DebuggerInferiorRunning
|
const bool started = status == DebuggerInferiorRunning
|
||||||
@@ -1255,9 +1275,9 @@ void DebuggerManager::setStatus(int status)
|
|||||||
|
|
||||||
void DebuggerManager::setBusyCursor(bool busy)
|
void DebuggerManager::setBusyCursor(bool busy)
|
||||||
{
|
{
|
||||||
|
//qDebug() << "BUSY FROM: " << m_busy << " TO: " << m_busy;
|
||||||
if (busy == m_busy)
|
if (busy == m_busy)
|
||||||
return;
|
return;
|
||||||
//qDebug() << "BUSY: " << busy;
|
|
||||||
m_busy = busy;
|
m_busy = busy;
|
||||||
|
|
||||||
QCursor cursor(busy ? Qt::BusyCursor : Qt::ArrowCursor);
|
QCursor cursor(busy ? Qt::BusyCursor : Qt::ArrowCursor);
|
||||||
@@ -1413,6 +1433,16 @@ void DebuggerManager::fileOpen(const QString &fileName)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Watch specific stuff
|
||||||
|
//
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void DebuggerManager::recheckCustomDumperAvailability()
|
||||||
|
{
|
||||||
|
m_engine->recheckCustomDumperAvailability();
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -311,6 +311,7 @@ private slots:
|
|||||||
void setStatus(int status);
|
void setStatus(int status);
|
||||||
void clearStatusMessage();
|
void clearStatusMessage();
|
||||||
void attemptBreakpointSynchronization();
|
void attemptBreakpointSynchronization();
|
||||||
|
void recheckCustomDumperAvailability();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -112,8 +112,7 @@ enum GdbCommandType
|
|||||||
GdbInfoShared,
|
GdbInfoShared,
|
||||||
GdbInfoProc,
|
GdbInfoProc,
|
||||||
GdbInfoThreads,
|
GdbInfoThreads,
|
||||||
GdbQueryDataDumper1,
|
GdbQueryDataDumper,
|
||||||
GdbQueryDataDumper2,
|
|
||||||
GdbTemporaryContinue,
|
GdbTemporaryContinue,
|
||||||
GdbTargetCore,
|
GdbTargetCore,
|
||||||
|
|
||||||
@@ -799,11 +798,8 @@ void GdbEngine::handleResult(const GdbResultRecord & record, int type,
|
|||||||
case GdbInfoShared:
|
case GdbInfoShared:
|
||||||
handleInfoShared(record);
|
handleInfoShared(record);
|
||||||
break;
|
break;
|
||||||
case GdbQueryDataDumper1:
|
case GdbQueryDataDumper:
|
||||||
handleQueryDataDumper1(record);
|
handleQueryDataDumper(record);
|
||||||
break;
|
|
||||||
case GdbQueryDataDumper2:
|
|
||||||
handleQueryDataDumper2(record);
|
|
||||||
break;
|
break;
|
||||||
case GdbTemporaryContinue:
|
case GdbTemporaryContinue:
|
||||||
continueInferior();
|
continueInferior();
|
||||||
@@ -1570,7 +1566,7 @@ bool GdbEngine::startDebugger()
|
|||||||
gdbArgs.prepend(QLatin1String("mi"));
|
gdbArgs.prepend(QLatin1String("mi"));
|
||||||
gdbArgs.prepend(QLatin1String("-i"));
|
gdbArgs.prepend(QLatin1String("-i"));
|
||||||
|
|
||||||
if (q->startMode() == AttachCore) {
|
if (q->startMode() == AttachCore || q->startMode() == AttachExternal) {
|
||||||
// nothing to do
|
// nothing to do
|
||||||
} else if (q->m_useTerminal) {
|
} else if (q->m_useTerminal) {
|
||||||
m_stubProc.stop(); // We leave the console open, so recycle it now.
|
m_stubProc.stop(); // We leave the console open, so recycle it now.
|
||||||
@@ -1778,6 +1774,7 @@ void GdbEngine::handleAttach()
|
|||||||
handleAqcuiredInferior();
|
handleAqcuiredInferior();
|
||||||
|
|
||||||
q->resetLocation();
|
q->resetLocation();
|
||||||
|
recheckCustomDumperAvailability();
|
||||||
|
|
||||||
//
|
//
|
||||||
// Stack
|
// Stack
|
||||||
@@ -3520,14 +3517,9 @@ void GdbEngine::updateWatchModel2()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GdbEngine::handleQueryDataDumper1(const GdbResultRecord &record)
|
void GdbEngine::handleQueryDataDumper(const GdbResultRecord &record)
|
||||||
{
|
{
|
||||||
Q_UNUSED(record);
|
qDebug() << "DATA DUMPER TRIAL:" << record.toString();
|
||||||
}
|
|
||||||
|
|
||||||
void GdbEngine::handleQueryDataDumper2(const GdbResultRecord &record)
|
|
||||||
{
|
|
||||||
//qDebug() << "DATA DUMPER TRIAL:" << record.toString();
|
|
||||||
GdbMi output = record.data.findChild("consolestreamoutput");
|
GdbMi output = record.data.findChild("consolestreamoutput");
|
||||||
QByteArray out = output.data();
|
QByteArray out = output.data();
|
||||||
out = out.mid(out.indexOf('"') + 2); // + 1 is success marker
|
out = out.mid(out.indexOf('"') + 2); // + 1 is success marker
|
||||||
@@ -3568,6 +3560,8 @@ void GdbEngine::handleQueryDataDumper2(const GdbResultRecord &record)
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
m_dataDumperState = DataDumperAvailable;
|
m_dataDumperState = DataDumperAvailable;
|
||||||
|
q->showStatusMessage(tr("%1 custom dumpers found")
|
||||||
|
.arg(m_availableSimpleDumpers.size()));
|
||||||
}
|
}
|
||||||
//qDebug() << "DATA DUMPERS AVAILABLE" << m_availableSimpleDumpers;
|
//qDebug() << "DATA DUMPERS AVAILABLE" << m_availableSimpleDumpers;
|
||||||
}
|
}
|
||||||
@@ -4274,9 +4268,8 @@ void GdbEngine::tryLoadCustomDumpers()
|
|||||||
|
|
||||||
if (m_dataDumperState == DataDumperLoadTried) {
|
if (m_dataDumperState == DataDumperLoadTried) {
|
||||||
// retreive list of dumpable classes
|
// retreive list of dumpable classes
|
||||||
sendCommand("call qDumpObjectData440(1,%1+1,0,0,0,0,0,0)",
|
sendCommand("call qDumpObjectData440(1,%1+1,0,0,0,0,0,0)");
|
||||||
GdbQueryDataDumper1);
|
sendCommand("p (char*)qDumpOutBuffer", GdbQueryDataDumper);
|
||||||
sendCommand("p (char*)qDumpOutBuffer", GdbQueryDataDumper2);
|
|
||||||
} else {
|
} else {
|
||||||
debugMessage(QString("DEBUG HELPER LIBRARY IS NOT USABLE: "
|
debugMessage(QString("DEBUG HELPER LIBRARY IS NOT USABLE: "
|
||||||
" %1 EXISTS: %2, EXECUTABLE: %3").arg(lib)
|
" %1 EXISTS: %2, EXECUTABLE: %3").arg(lib)
|
||||||
@@ -4285,6 +4278,12 @@ void GdbEngine::tryLoadCustomDumpers()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GdbEngine::recheckCustomDumperAvailability()
|
||||||
|
{
|
||||||
|
// retreive list of dumpable classes
|
||||||
|
sendCommand("call qDumpObjectData440(1,%1+1,0,0,0,0,0,0)");
|
||||||
|
sendCommand("p (char*)qDumpOutBuffer", GdbQueryDataDumper);
|
||||||
|
}
|
||||||
|
|
||||||
IDebuggerEngine *createGdbEngine(DebuggerManager *parent)
|
IDebuggerEngine *createGdbEngine(DebuggerManager *parent)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -304,6 +304,7 @@ private:
|
|||||||
void maybeHandleInferiorPidChanged(const QString &pid);
|
void maybeHandleInferiorPidChanged(const QString &pid);
|
||||||
|
|
||||||
void tryLoadCustomDumpers();
|
void tryLoadCustomDumpers();
|
||||||
|
Q_SLOT void recheckCustomDumperAvailability();
|
||||||
void runCustomDumper(const WatchData &data, bool dumpChildren);
|
void runCustomDumper(const WatchData &data, bool dumpChildren);
|
||||||
void runDirectDumper(const WatchData &data, bool dumpChildren);
|
void runDirectDumper(const WatchData &data, bool dumpChildren);
|
||||||
bool isCustomValueDumperAvailable(const QString &type) const;
|
bool isCustomValueDumperAvailable(const QString &type) const;
|
||||||
@@ -317,8 +318,7 @@ private:
|
|||||||
const WatchData &cookie);
|
const WatchData &cookie);
|
||||||
void handleToolTip(const GdbResultRecord &record,
|
void handleToolTip(const GdbResultRecord &record,
|
||||||
const QString &cookie);
|
const QString &cookie);
|
||||||
void handleQueryDataDumper1(const GdbResultRecord &record);
|
void handleQueryDataDumper(const GdbResultRecord &record);
|
||||||
void handleQueryDataDumper2(const GdbResultRecord &record);
|
|
||||||
void handleDumpCustomValue1(const GdbResultRecord &record,
|
void handleDumpCustomValue1(const GdbResultRecord &record,
|
||||||
const WatchData &cookie);
|
const WatchData &cookie);
|
||||||
void handleDumpCustomValue2(const GdbResultRecord &record,
|
void handleDumpCustomValue2(const GdbResultRecord &record,
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ public:
|
|||||||
virtual void reloadRegisters() = 0;
|
virtual void reloadRegisters() = 0;
|
||||||
virtual void setDebugDumpers(bool on) = 0;
|
virtual void setDebugDumpers(bool on) = 0;
|
||||||
virtual void setUseCustomDumpers(bool on) = 0;
|
virtual void setUseCustomDumpers(bool on) = 0;
|
||||||
|
virtual void recheckCustomDumperAvailability() = 0;
|
||||||
|
|
||||||
virtual void reloadSourceFiles() = 0;
|
virtual void reloadSourceFiles() = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -99,6 +99,7 @@ private:
|
|||||||
|
|
||||||
void setDebugDumpers(bool) {}
|
void setDebugDumpers(bool) {}
|
||||||
void setUseCustomDumpers(bool) {}
|
void setUseCustomDumpers(bool) {}
|
||||||
|
void recheckCustomDumperAvailability() {}
|
||||||
|
|
||||||
void assignValueInDebugger(const QString &expr, const QString &value);
|
void assignValueInDebugger(const QString &expr, const QString &value);
|
||||||
void executeDebuggerCommand(const QString & command);
|
void executeDebuggerCommand(const QString & command);
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
|
|||||||
QAction *act3 = 0;
|
QAction *act3 = 0;
|
||||||
QAction *act4 = 0;
|
QAction *act4 = 0;
|
||||||
QAction *act5 = new QAction("Debugger properties...", &menu);
|
QAction *act5 = new QAction("Debugger properties...", &menu);
|
||||||
|
QAction *act6 = new QAction("Re-check availability of custom dumpers", &menu);
|
||||||
|
|
||||||
menu.addAction(act1);
|
menu.addAction(act1);
|
||||||
menu.addAction(act2);
|
menu.addAction(act2);
|
||||||
@@ -130,6 +131,7 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
|
|||||||
// FIXME: menu.addAction(act4);
|
// FIXME: menu.addAction(act4);
|
||||||
}
|
}
|
||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
|
menu.addAction(act6);
|
||||||
menu.addAction(act5);
|
menu.addAction(act5);
|
||||||
|
|
||||||
QAction *act = menu.exec(ev->globalPos());
|
QAction *act = menu.exec(ev->globalPos());
|
||||||
@@ -149,6 +151,8 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
|
|||||||
model()->setData(mi0, !visual, VisualRole);
|
model()->setData(mi0, !visual, VisualRole);
|
||||||
else if (act == act5)
|
else if (act == act5)
|
||||||
emit settingsDialogRequested();
|
emit settingsDialogRequested();
|
||||||
|
else if (act == act6)
|
||||||
|
emit requestRecheckCustomDumperAvailability();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WatchWindow::resizeColumnsToContents()
|
void WatchWindow::resizeColumnsToContents()
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ signals:
|
|||||||
void requestAssignValue(const QString &exp, const QString &value);
|
void requestAssignValue(const QString &exp, const QString &value);
|
||||||
void requestExpandChildren(const QModelIndex &idx);
|
void requestExpandChildren(const QModelIndex &idx);
|
||||||
void requestCollapseChildren(const QModelIndex &idx);
|
void requestCollapseChildren(const QModelIndex &idx);
|
||||||
|
void requestRecheckCustomDumperAvailability();
|
||||||
void settingsDialogRequested();
|
void settingsDialogRequested();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|||||||
Reference in New Issue
Block a user