Newer
Older
/**************************************************************************
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
**************************************************************************/
#include "debuggermanager.h"
#include "debuggerconstants.h"
#include "idebuggerengine.h"
#include "breakwindow.h"
#include "disassemblerwindow.h"
#include "debuggeroutputwindow.h"
#include "moduleswindow.h"
#include "registerwindow.h"
#include "stackwindow.h"
#include "sourcefileswindow.h"
#include "threadswindow.h"
#include "watchwindow.h"
#include "ui_breakbyfunction.h"
#include "disassemblerhandler.h"
#include "breakhandler.h"
#include "moduleshandler.h"
#include "registerhandler.h"
#include "stackhandler.h"
#include "watchhandler.h"
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
#include <QtCore/QTimer>
#include <QtGui/QAction>
#include <QtGui/QComboBox>
#include <QtGui/QDockWidget>
#include <QtGui/QErrorMessage>
#include <QtGui/QFileDialog>
#include <QtGui/QLabel>
#include <QtGui/QMainWindow>
#include <QtGui/QMessageBox>
#include <QtGui/QPlainTextEdit>
#include <QtGui/QStatusBar>
#include <QtGui/QTextBlock>
#include <QtGui/QTextCursor>
#include <QtGui/QToolBar>
#include <QtGui/QToolButton>
#include <QtGui/QToolTip>
using namespace Debugger;
using namespace Debugger::Internal;
using namespace Debugger::Constants;
static const QString tooltipIName = "tooltip";
DebuggerSettings::DebuggerSettings()
{
m_autoRun = false;
m_autoQuit = false;
m_skipKnownFrames = false;
m_debugDumpers = false;
m_useToolTips = false;
m_useCustomDumpers = true;
m_listSourceFiles = false;
QString DebuggerSettings::dump()
{
QString out;
QTextStream ts(&out);
ts << "Debugger settings: "
<< " gdbCmd: " << m_gdbCmd
<< " gdbEnv: " << m_gdbEnv
<< " autoRun: " << m_autoRun
<< " autoQuit: " << m_autoQuit
<< " useCustomDumpers: " << m_useCustomDumpers
<< " skipKnownFrames: " << m_skipKnownFrames
<< " debugDumpers: " << m_debugDumpers
<< " useToolTips: " << m_useToolTips
<< " listSourceFiles: " << m_listSourceFiles
<< " scriptFile: " << m_scriptFile
<< " pluginAllBreakpoints: " << m_pluginAllBreakpoints
<< " pluginSelectedBreakpoints: " << m_pluginSelectedBreakpoints
<< " pluginNoBreakpoints: " << m_pluginNoBreakpoints
<< " pluginSelectedBreakpointsPattern: " << m_pluginSelectedBreakpointsPattern;
return out;
}
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
///////////////////////////////////////////////////////////////////////
//
// BreakByFunctionDialog
//
///////////////////////////////////////////////////////////////////////
class BreakByFunctionDialog : public QDialog, Ui::BreakByFunctionDialog
{
Q_OBJECT
public:
explicit BreakByFunctionDialog(QWidget *parent)
: QDialog(parent)
{
setupUi(this);
connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
}
QString functionName() const { return functionLineEdit->text(); }
};
///////////////////////////////////////////////////////////////////////
//
// DebuggerManager
//
///////////////////////////////////////////////////////////////////////
static IDebuggerEngine *gdbEngine = 0;
static IDebuggerEngine *winEngine = 0;
static IDebuggerEngine *scriptEngine = 0;
extern IDebuggerEngine *createGdbEngine(DebuggerManager *parent);
extern IDebuggerEngine *createWinEngine(DebuggerManager *)
#ifdef CDB_ENABLED
;
#else
{ return 0; }
#endif
extern IDebuggerEngine *createScriptEngine(DebuggerManager *parent);
DebuggerManager::DebuggerManager() :
m_attachCoreAction(0)
{
init();
}
DebuggerManager::~DebuggerManager()
{
delete gdbEngine;
delete winEngine;
delete scriptEngine;
}
void DebuggerManager::init()
{
m_status = -1;
m_busy = false;
m_attachedPID = 0;
m_disassemblerHandler = 0;
m_modulesHandler = 0;
m_registerHandler = 0;
m_statusLabel = new QLabel;
m_breakWindow = new BreakWindow;
m_disassemblerWindow = new DisassemblerWindow;
m_modulesWindow = new ModulesWindow;
m_outputWindow = new DebuggerOutputWindow;
m_registerWindow = new RegisterWindow;
m_stackWindow = new StackWindow;
m_sourceFilesWindow = new SourceFilesWindow;
m_threadsWindow = new ThreadsWindow;
m_localsWindow = new WatchWindow(WatchWindow::LocalsType);
m_watchersWindow = new WatchWindow(WatchWindow::WatchersType);
//m_tooltipWindow = new WatchWindow(WatchWindow::TooltipType);
//m_watchersWindow = new QTreeView;
m_tooltipWindow = new QTreeView;
m_statusTimer = new QTimer(this);
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
m_mainWindow = new QMainWindow;
m_mainWindow->setTabPosition(Qt::AllDockWidgetAreas, QTabWidget::North);
m_mainWindow->setDocumentMode(true);
// Stack
m_stackHandler = new StackHandler;
QAbstractItemView *stackView =
qobject_cast<QAbstractItemView *>(m_stackWindow);
stackView->setModel(m_stackHandler->stackModel());
connect(stackView, SIGNAL(frameActivated(int)),
this, SLOT(activateFrame(int)));
// Threads
m_threadsHandler = new ThreadsHandler;
QAbstractItemView *threadsView =
qobject_cast<QAbstractItemView *>(m_threadsWindow);
threadsView->setModel(m_threadsHandler->threadsModel());
connect(threadsView, SIGNAL(threadSelected(int)),
this, SLOT(selectThread(int)));
// Disassembler
m_disassemblerHandler = new DisassemblerHandler;
QAbstractItemView *disassemblerView =
qobject_cast<QAbstractItemView *>(m_disassemblerWindow);
disassemblerView->setModel(m_disassemblerHandler->model());
// Breakpoints
m_breakHandler = new BreakHandler;
QAbstractItemView *breakView =
qobject_cast<QAbstractItemView *>(m_breakWindow);
breakView->setModel(m_breakHandler->model());
connect(breakView, SIGNAL(breakpointActivated(int)),
m_breakHandler, SLOT(activateBreakpoint(int)));
connect(breakView, SIGNAL(breakpointDeleted(int)),
connect(breakView, SIGNAL(settingsDialogRequested()),
this, SIGNAL(settingsDialogRequested()));
connect(breakView, SIGNAL(breakpointSynchronizationRequested()),
this, SLOT(attemptBreakpointSynchronization()));
connect(m_breakHandler, SIGNAL(gotoLocation(QString,int,bool)),
this, SLOT(gotoLocation(QString,int,bool)));
connect(m_breakHandler, SIGNAL(sessionValueRequested(QString,QVariant*)),
this, SIGNAL(sessionValueRequested(QString,QVariant*)));
connect(m_breakHandler, SIGNAL(setSessionValueRequested(QString,QVariant)),
this, SIGNAL(setSessionValueRequested(QString,QVariant)));
// Modules
QAbstractItemView *modulesView =
qobject_cast<QAbstractItemView *>(m_modulesWindow);
m_modulesHandler = new ModulesHandler;
modulesView->setModel(m_modulesHandler->model());
connect(modulesView, SIGNAL(reloadModulesRequested()),
this, SLOT(reloadModules()));
connect(modulesView, SIGNAL(loadSymbolsRequested(QString)),
this, SLOT(loadSymbols(QString)));
connect(modulesView, SIGNAL(loadAllSymbolsRequested()),
this, SLOT(loadAllSymbols()));
connect(modulesView, SIGNAL(fileOpenRequested(QString)),
this, SLOT(fileOpen(QString)));
// Source Files
//m_sourceFilesHandler = new SourceFilesHandler;
QAbstractItemView *sourceFilesView =
qobject_cast<QAbstractItemView *>(m_sourceFilesWindow);
//sourceFileView->setModel(m_stackHandler->stackModel());
connect(sourceFilesView, SIGNAL(reloadSourceFilesRequested()),
this, SLOT(reloadSourceFiles()));
connect(sourceFilesView, SIGNAL(fileOpenRequested(QString)),
this, SLOT(fileOpen(QString)));
// Registers
QAbstractItemView *registerView =
qobject_cast<QAbstractItemView *>(m_registerWindow);
m_registerHandler = new RegisterHandler;
registerView->setModel(m_registerHandler->model());
m_watchHandler = new WatchHandler;
// Locals
QTreeView *localsView = qobject_cast<QTreeView *>(m_localsWindow);
localsView->setModel(m_watchHandler->model());
connect(localsView, SIGNAL(requestExpandChildren(QModelIndex)),
this, SLOT(expandChildren(QModelIndex)));
connect(localsView, SIGNAL(requestCollapseChildren(QModelIndex)),
this, SLOT(collapseChildren(QModelIndex)));
connect(localsView, SIGNAL(requestAssignValue(QString,QString)),
this, SLOT(assignValueInDebugger(QString,QString)));
connect(localsView, SIGNAL(requestWatchExpression(QString)),
this, SLOT(watchExpression(QString)));
connect(localsView, SIGNAL(settingsDialogRequested()),
this, SIGNAL(settingsDialogRequested()));
// Watchers
QTreeView *watchersView = qobject_cast<QTreeView *>(m_watchersWindow);
watchersView->setModel(m_watchHandler->model());
connect(watchersView, SIGNAL(requestAssignValue(QString,QString)),
this, SLOT(assignValueInDebugger(QString,QString)));
connect(watchersView, SIGNAL(requestExpandChildren(QModelIndex)),
this, SLOT(expandChildren(QModelIndex)));
connect(watchersView, SIGNAL(requestCollapseChildren(QModelIndex)),
this, SLOT(collapseChildren(QModelIndex)));
connect(watchersView, SIGNAL(requestWatchExpression(QString)),
this, SLOT(watchExpression(QString)));
connect(watchersView, SIGNAL(requestRemoveWatchExpression(QString)),
this, SLOT(removeWatchExpression(QString)));
connect(m_watchHandler, SIGNAL(sessionValueRequested(QString,QVariant*)),
this, SIGNAL(sessionValueRequested(QString,QVariant*)));
connect(m_watchHandler, SIGNAL(setSessionValueRequested(QString,QVariant)),
this, SIGNAL(setSessionValueRequested(QString,QVariant)));
connect(watchersView, SIGNAL(settingsDialogRequested()),
this, SIGNAL(settingsDialogRequested()));
// Tooltip
QTreeView *tooltipView = qobject_cast<QTreeView *>(m_tooltipWindow);
tooltipView->setModel(m_watchHandler->model());
connect(m_watchHandler, SIGNAL(watchModelUpdateRequested()),
this, SLOT(updateWatchModel()));
m_startExternalAction = new QAction(this);
m_startExternalAction->setText(tr("Start and Debug External Application..."));
m_attachExternalAction = new QAction(this);
m_attachExternalAction->setText(tr("Attach to Running External Application..."));
m_attachCoreAction = new QAction(this);
m_attachCoreAction->setText(tr("Attach to Core..."));
connect(m_attachCoreAction, SIGNAL(triggered()), this, SLOT(attachCore()));
#endif
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
m_continueAction = new QAction(this);
m_continueAction->setText(tr("Continue"));
m_continueAction->setIcon(QIcon(":/gdbdebugger/images/debugger_continue_small.png"));
m_stopAction = new QAction(this);
m_stopAction->setText(tr("Interrupt"));
m_stopAction->setIcon(QIcon(":/gdbdebugger/images/debugger_interrupt_small.png"));
m_resetAction = new QAction(this);
m_resetAction->setText(tr("Reset Debugger"));
m_nextAction = new QAction(this);
m_nextAction->setText(tr("Step Over"));
//m_nextAction->setShortcut(QKeySequence(tr("F6")));
m_nextAction->setIcon(QIcon(":/gdbdebugger/images/debugger_stepover_small.png"));
m_stepAction = new QAction(this);
m_stepAction->setText(tr("Step Into"));
//m_stepAction->setShortcut(QKeySequence(tr("F7")));
m_stepAction->setIcon(QIcon(":/gdbdebugger/images/debugger_stepinto_small.png"));
m_nextIAction = new QAction(this);
m_nextIAction->setText(tr("Step Over Instruction"));
//m_nextIAction->setShortcut(QKeySequence(tr("Shift+F6")));
m_nextIAction->setIcon(QIcon(":/gdbdebugger/images/debugger_stepoverproc_small.png"));
m_stepIAction = new QAction(this);
m_stepIAction->setText(tr("Step One Instruction"));
//m_stepIAction->setShortcut(QKeySequence(tr("Shift+F9")));
m_stepIAction->setIcon(QIcon(":/gdbdebugger/images/debugger_steponeproc_small.png"));
m_stepOutAction = new QAction(this);
m_stepOutAction->setText(tr("Step Out"));
//m_stepOutAction->setShortcut(QKeySequence(tr("Shift+F7")));
m_stepOutAction->setIcon(QIcon(":/gdbdebugger/images/debugger_stepout_small.png"));
m_runToLineAction = new QAction(this);
m_runToLineAction->setText(tr("Run to Line"));
m_runToFunctionAction = new QAction(this);
m_runToFunctionAction->setText(tr("Run to Outermost Function"));
m_jumpToLineAction = new QAction(this);
m_jumpToLineAction->setText(tr("Jump to Line"));
m_breakAction = new QAction(this);
m_breakAction->setText(tr("Toggle Breakpoint"));
m_breakByFunctionAction = new QAction(this);
m_breakByFunctionAction->setText(tr("Set Breakpoint at Function..."));
m_breakAtMainAction = new QAction(this);
m_breakAtMainAction->setText(tr("Set Breakpoint at Function \"main\""));
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
m_watchAction = new QAction(this);
m_watchAction->setText(tr("Add to Watch Window"));
// For usuage hints oin focus{In,Out}
//connect(m_outputWindow, SIGNAL(statusMessageRequested(QString,int)),
// this, SLOT(showStatusMessage(QString,int)));
connect(m_continueAction, SIGNAL(triggered()),
this, SLOT(continueExec()));
connect(m_startExternalAction, SIGNAL(triggered()),
this, SLOT(startExternalApplication()));
connect(m_attachExternalAction, SIGNAL(triggered()),
this, SLOT(attachExternalApplication()));
connect(m_stopAction, SIGNAL(triggered()),
this, SLOT(interruptDebuggingRequest()));
connect(m_resetAction, SIGNAL(triggered()),
this, SLOT(exitDebugger()));
connect(m_nextAction, SIGNAL(triggered()),
this, SLOT(nextExec()));
connect(m_stepAction, SIGNAL(triggered()),
this, SLOT(stepExec()));
connect(m_nextIAction, SIGNAL(triggered()),
this, SLOT(nextIExec()));
connect(m_stepIAction, SIGNAL(triggered()),
this, SLOT(stepIExec()));
connect(m_stepOutAction, SIGNAL(triggered()),
this, SLOT(stepOutExec()));
connect(m_runToLineAction, SIGNAL(triggered()),
this, SLOT(runToLineExec()));
connect(m_runToFunctionAction, SIGNAL(triggered()),
this, SLOT(runToFunctionExec()));
connect(m_jumpToLineAction, SIGNAL(triggered()),
this, SLOT(jumpToLineExec()));
connect(m_watchAction, SIGNAL(triggered()),
this, SLOT(addToWatchWindow()));
connect(m_breakAction, SIGNAL(triggered()),
this, SLOT(toggleBreakpoint()));
connect(m_breakByFunctionAction, SIGNAL(triggered()),
this, SLOT(breakByFunction()));
connect(m_breakAtMainAction, SIGNAL(triggered()),
this, SLOT(breakAtMain()));
connect(m_statusTimer, SIGNAL(timeout()),
this, SLOT(clearStatusMessage()));
connect(m_outputWindow, SIGNAL(commandExecutionRequested(QString)),
this, SLOT(executeDebuggerCommand(QString)));
m_breakDock = createDockForWidget(m_breakWindow);
m_disassemblerDock = createDockForWidget(m_disassemblerWindow);
connect(m_disassemblerDock->toggleViewAction(), SIGNAL(toggled(bool)),
this, SLOT(reloadDisassembler()), Qt::QueuedConnection);
m_modulesDock = createDockForWidget(m_modulesWindow);
connect(m_modulesDock->toggleViewAction(), SIGNAL(toggled(bool)),
this, SLOT(reloadModules()), Qt::QueuedConnection);
m_registerDock = createDockForWidget(m_registerWindow);
connect(m_registerDock->toggleViewAction(), SIGNAL(toggled(bool)),
this, SLOT(reloadRegisters()), Qt::QueuedConnection);
m_outputDock = createDockForWidget(m_outputWindow);
m_stackDock = createDockForWidget(m_stackWindow);
m_sourceFilesDock = createDockForWidget(m_sourceFilesWindow);
connect(m_sourceFilesDock->toggleViewAction(), SIGNAL(toggled(bool)),
this, SLOT(reloadSourceFiles()), Qt::QueuedConnection);
m_threadsDock = createDockForWidget(m_threadsWindow);
setStatus(DebuggerProcessNotReady);
gdbEngine = createGdbEngine(this);
winEngine = createWinEngine(this);
scriptEngine = createScriptEngine(this);
setDebuggerType(GdbDebugger);
if (Debugger::Constants::Internal::debug)
qDebug() << Q_FUNC_INFO << gdbEngine << winEngine << scriptEngine;
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
}
void DebuggerManager::setDebuggerType(DebuggerType type)
{
switch (type) {
case GdbDebugger:
m_engine = gdbEngine;
break;
case ScriptDebugger:
m_engine = scriptEngine;
break;
case WinDebugger:
m_engine = winEngine;
break;
}
}
IDebuggerEngine *DebuggerManager::engine()
{
return m_engine;
}
IDebuggerManagerAccessForEngines *DebuggerManager::engineInterface()
{
return dynamic_cast<IDebuggerManagerAccessForEngines *>(this);
}
void DebuggerManager::createDockWidgets()
{
QSplitter *localsAndWatchers = new QSplitter(Qt::Vertical, 0);
localsAndWatchers->setWindowTitle(m_localsWindow->windowTitle());
localsAndWatchers->addWidget(m_localsWindow);
localsAndWatchers->addWidget(m_watchersWindow);
localsAndWatchers->setStretchFactor(0, 3);
localsAndWatchers->setStretchFactor(1, 1);
m_watchDock = createDockForWidget(localsAndWatchers);
}
QDockWidget *DebuggerManager::createDockForWidget(QWidget *widget)
{
QDockWidget *dockWidget = new QDockWidget(widget->windowTitle(), m_mainWindow);
dockWidget->setObjectName(widget->windowTitle());
dockWidget->setFeatures(QDockWidget::DockWidgetClosable);
dockWidget->setTitleBarWidget(new QWidget(dockWidget));
dockWidget->setWidget(widget);
connect(dockWidget->toggleViewAction(), SIGNAL(toggled(bool)),
this, SLOT(dockToggled(bool)), Qt::QueuedConnection);
m_dockWidgets.append(dockWidget);
return dockWidget;
}
void DebuggerManager::setSimpleDockWidgetArrangement()
{
foreach (QDockWidget *dockWidget, m_dockWidgets)
m_mainWindow->removeDockWidget(dockWidget);
foreach (QDockWidget *dockWidget, m_dockWidgets) {
m_mainWindow->addDockWidget(Qt::BottomDockWidgetArea, dockWidget);
dockWidget->show();
}
m_mainWindow->tabifyDockWidget(m_watchDock, m_breakDock);
m_mainWindow->tabifyDockWidget(m_watchDock, m_disassemblerDock);
m_mainWindow->tabifyDockWidget(m_watchDock, m_modulesDock);
m_mainWindow->tabifyDockWidget(m_watchDock, m_outputDock);
m_mainWindow->tabifyDockWidget(m_watchDock, m_registerDock);
m_mainWindow->tabifyDockWidget(m_watchDock, m_threadsDock);
m_mainWindow->tabifyDockWidget(m_watchDock, m_sourceFilesDock);
// They are rarely used even in ordinary debugging. Hiding them also saves
// cycles since the corresponding information won't be retrieved.
m_sourceFilesDock->hide();
m_registerDock->hide();
m_disassemblerDock->hide();
m_modulesDock->hide();
m_outputDock->hide();
}
void DebuggerManager::setLocked(bool locked)
{
const QDockWidget::DockWidgetFeatures features =
(locked) ? QDockWidget::DockWidgetClosable :
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetClosable;
foreach (QDockWidget *dockWidget, m_dockWidgets) {
QWidget *titleBarWidget = dockWidget->titleBarWidget();
if (locked && !titleBarWidget)
titleBarWidget = new QWidget(dockWidget);
else if (!locked && titleBarWidget) {
delete titleBarWidget;
titleBarWidget = 0;
}
dockWidget->setTitleBarWidget(titleBarWidget);
dockWidget->setFeatures(features);
}
}
void DebuggerManager::dockToggled(bool on)
{
QDockWidget *dw = qobject_cast<QDockWidget *>(sender()->parent());
if (on && dw)
dw->raise();
}
QAbstractItemModel *DebuggerManager::threadsModel()
{
return qobject_cast<ThreadsWindow*>(m_threadsWindow)->model();
}
void DebuggerManager::clearStatusMessage()
{
m_statusLabel->setText(m_lastPermanentStatusMessage);
}
void DebuggerManager::showStatusMessage(const QString &msg, int timeout)
{
Q_UNUSED(timeout)
if (Debugger::Constants::Internal::debug)
qDebug() << "STATUS MSG: " << msg;
m_statusLabel->setText(" " + msg);
if (timeout > 0) {
m_statusTimer->setSingleShot(true);
m_statusTimer->start(timeout);
} else {
m_lastPermanentStatusMessage = msg;
m_statusTimer->stop();
}
void DebuggerManager::notifyInferiorStopRequested()
{
setStatus(DebuggerInferiorStopRequested);
showStatusMessage(tr("Stop requested..."), 5000);
}
void DebuggerManager::notifyInferiorStopped()
{
resetLocation();
setStatus(DebuggerInferiorStopped);
showStatusMessage(tr("Stopped."), 5000);
}
void DebuggerManager::notifyInferiorRunningRequested()
{
setStatus(DebuggerInferiorRunningRequested);
showStatusMessage(tr("Running requested..."), 5000);
}
void DebuggerManager::notifyInferiorRunning()
{
setStatus(DebuggerInferiorRunning);
showStatusMessage(tr("Running..."), 5000);
}
void DebuggerManager::notifyInferiorExited()
{
showStatusMessage(tr("Stopped."), 5000);
}
void DebuggerManager::notifyInferiorPidChanged(int pid)
{
if (Debugger::Constants::Internal::debug)
qDebug() << Q_FUNC_INFO << pid;
//QMessageBox::warning(0, "PID", "PID: " + QString::number(pid));
emit inferiorPidChanged(pid);
}
void DebuggerManager::showApplicationOutput(const QString &str)
if (Debugger::Constants::Internal::debug)
qDebug() << Q_FUNC_INFO << m_engine;
if (m_engine)
m_engine->shutdown();
m_engine = 0;
delete scriptEngine;
scriptEngine = 0;
delete gdbEngine;
gdbEngine = 0;
delete winEngine;
winEngine = 0;
// Delete these manually before deleting the manager
// (who will delete the models for most views)
delete m_breakWindow;
delete m_disassemblerWindow;
delete m_modulesWindow;
delete m_outputWindow;
delete m_registerWindow;
delete m_stackWindow;
delete m_sourceFilesWindow;
delete m_threadsWindow;
delete m_tooltipWindow;
delete m_watchersWindow;
delete m_localsWindow;
// These widgets are all in some layout which will take care of deletion.
m_breakWindow = 0;
m_disassemblerWindow = 0;
m_modulesWindow = 0;
m_outputWindow = 0;
m_registerWindow = 0;
m_stackWindow = 0;
m_sourceFilesWindow = 0;
m_threadsWindow = 0;
m_tooltipWindow = 0;
m_watchersWindow = 0;
m_localsWindow = 0;
delete m_breakHandler;
delete m_disassemblerHandler;
delete m_modulesHandler;
delete m_registerHandler;
delete m_stackHandler;
delete m_watchHandler;
m_breakHandler = 0;
m_disassemblerHandler = 0;
m_modulesHandler = 0;
m_registerHandler = 0;
m_stackHandler = 0;
m_watchHandler = 0;
//qDebug() << "DEBUGGER_MANAGER SHUTDOWN END";
}
void DebuggerManager::toggleBreakpoint()
{
QString fileName;
int lineNumber = -1;
queryCurrentTextEditor(&fileName, &lineNumber, 0);
if (lineNumber == -1)
return;
toggleBreakpoint(fileName, lineNumber);
}
void DebuggerManager::toggleBreakpoint(const QString &fileName, int lineNumber)
{
if (Debugger::Constants::Internal::debug)
qDebug() << Q_FUNC_INFO << fileName << lineNumber;
QTC_ASSERT(m_engine, return);
QTC_ASSERT(m_breakHandler, return);
if (status() != DebuggerInferiorRunning
&& status() != DebuggerInferiorStopped
&& status() != DebuggerProcessNotReady) {
showStatusMessage(tr("Changing breakpoint state requires either a "
"fully running or fully stopped application."));
return;
}
int index = m_breakHandler->indexOf(fileName, lineNumber);
if (index == -1)
m_breakHandler->setBreakpoint(fileName, lineNumber);
m_breakHandler->removeBreakpoint(index);
m_engine->attemptBreakpointSynchronization();
void DebuggerManager::attemptBreakpointSynchronization()
{
m_engine->attemptBreakpointSynchronization();
}
void DebuggerManager::setToolTipExpression(const QPoint &pos, const QString &exp)
{
QTC_ASSERT(m_engine, return);
m_engine->setToolTipExpression(pos, exp);
QTC_ASSERT(m_engine, return);
m_engine->updateWatchModel();
}
void DebuggerManager::expandChildren(const QModelIndex &idx)
{
QTC_ASSERT(m_watchHandler, return);
m_watchHandler->expandChildren(idx);
}
void DebuggerManager::collapseChildren(const QModelIndex &idx)
{
QTC_ASSERT(m_watchHandler, return);
m_watchHandler->collapseChildren(idx);
void DebuggerManager::removeWatchExpression(const QString &exp)
QTC_ASSERT(m_watchHandler, return);
m_watchHandler->removeWatchExpression(exp);
}
QVariant DebuggerManager::sessionValue(const QString &name)
{
// this is answered by the plugin
QVariant value;
emit sessionValueRequested(name, &value);
return value;
}
void DebuggerManager::querySessionValue(const QString &name, QVariant *value)
{
// this is answered by the plugin
emit sessionValueRequested(name, value);
}
void DebuggerManager::setSessionValue(const QString &name, const QVariant &value)
{
// this is answered by the plugin
emit setSessionValueRequested(name, value);
}
QVariant DebuggerManager::configValue(const QString &name)
{
// this is answered by the plugin
QVariant value;
emit configValueRequested(name, &value);
return value;
}
void DebuggerManager::queryConfigValue(const QString &name, QVariant *value)
{
// this is answered by the plugin
emit configValueRequested(name, value);
}
void DebuggerManager::setConfigValue(const QString &name, const QVariant &value)
{
// this is answered by the plugin
emit setConfigValueRequested(name, value);
}
void DebuggerManager::startExternalApplication()
{
emit debuggingFinished();
}
void DebuggerManager::attachExternalApplication()
{
void DebuggerManager::attachCore()
{
if (!startNewDebugger(AttachCore))
emit debuggingFinished();
}
// Figure out the debugger type of an executable
static bool determineDebuggerType(const QString &executable,
DebuggerManager::DebuggerType *dt,
QString *errorMessage)
{
if (executable.endsWith(QLatin1String(".js"))) {
*dt = DebuggerManager::ScriptDebugger;
return true;
}
#ifndef Q_OS_WIN
Q_UNUSED(errorMessage)
return true;
#else
// If a file has PDB files, it has been compiled by VS.
QStringList pdbFiles;
if (!getPDBFiles(executable, &pdbFiles, errorMessage))
return false;
if (pdbFiles.empty()) {
*dt = DebuggerManager::GdbDebugger;
return true;
}
// We need the CDB debugger in order to be able to debug VS
// executables
if (!winEngine) {
*errorMessage = DebuggerManager::tr("Debugging VS executables is not supported.");
return false;
}
*dt = DebuggerManager::WinDebugger;
return true;
#endif
}
// Figure out the debugger type of a PID
static bool determineDebuggerType(int /* pid */,
DebuggerManager::DebuggerType *dt,
QString * /*errorMessage*/)
{
#ifdef Q_OS_WIN
// Preferably Windows debugger
*dt = winEngine ? DebuggerManager::WinDebugger : DebuggerManager::GdbDebugger;
#else
*dt = DebuggerManager::GdbDebugger;
#endif
return true;
}
bool DebuggerManager::startNewDebugger(DebuggerStartMode mode)
if (Debugger::Constants::Internal::debug)
qDebug() << Q_FUNC_INFO << mode;
switch (startMode()) {
case StartExternal: {
StartExternalDialog dlg(mainWindow());
dlg.setExecutableFile(
configValue(QLatin1String("LastExternalExecutableFile")).toString());
dlg.setExecutableArguments(
configValue(QLatin1String("LastExternalExecutableArguments")).toString());
if (dlg.exec() != QDialog::Accepted)
return false;
setConfigValue(QLatin1String("LastExternalExecutableFile"),
dlg.executableFile());
setConfigValue(QLatin1String("LastExternalExecutableArguments"),
dlg.executableArguments());
m_executable = dlg.executableFile();
m_processArgs = dlg.executableArguments().split(' ');
m_workingDir = QString();
m_attachedPID = -1;
AttachExternalDialog dlg(mainWindow());
if (dlg.exec() != QDialog::Accepted)
return false;
m_executable = QString();
m_processArgs = QStringList();
m_workingDir = QString();
m_attachedPID = dlg.attachPID();
if (m_attachedPID == 0) {
QMessageBox::warning(mainWindow(), tr("Warning"),
tr("Cannot attach to PID 0"));
return false;
}
if (m_executable.isEmpty()) {
QString startDirectory = m_executable;
if (m_executable.isEmpty()) {
QString fileName;
emit currentTextEditorRequested(&fileName, 0, 0);
if (!fileName.isEmpty()) {
const QFileInfo editorFile(fileName);
startDirectory = editorFile.dir().absolutePath();
}
}
StartExternalDialog dlg(mainWindow());
dlg.setExecutableFile(startDirectory);
if (dlg.exec() != QDialog::Accepted)
return false;
m_executable = dlg.executableFile();
m_processArgs = dlg.executableArguments().split(' ');
m_workingDir = QString();
m_attachedPID = 0;
} else {
//m_executable = QDir::convertSeparators(m_executable);
//m_processArgs = sd.processArgs.join(QLatin1String(" "));
m_attachedPID = 0;
}
dlg.setExecutableFile(
configValue(QLatin1String("LastExternalExecutableFile")).toString());
dlg.setCoreFile(
configValue(QLatin1String("LastExternalCoreFile")).toString());
if (dlg.exec() != QDialog::Accepted)
return false;
setConfigValue(QLatin1String("LastExternalExecutableFile"),
dlg.executableFile());
setConfigValue(QLatin1String("LastExternalCoreFile"),
dlg.coreFile());
m_executable = dlg.executableFile();
m_coreFile = dlg.coreFile();
m_processArgs.clear();
m_workingDir = QString();
m_attachedPID = -1;
const bool hasDebugger = startMode() == AttachExternal ?
determineDebuggerType(m_attachedPID, &type, &errorMessage) :
determineDebuggerType(m_executable, &type, &errorMessage);
if (!hasDebugger) {
QMessageBox::warning(mainWindow(), tr("Warning"),
tr("Cannot debug '%1': %2").arg(m_executable, errorMessage));
return false;
}
if (Debugger::Constants::Internal::debug)
qDebug() << m_executable << type;
setStatus(DebuggerProcessStartingUp);
if (!m_engine->startDebugger()) {
setStatus(DebuggerProcessNotReady);