2012-10-02 09:12:39 +02:00
|
|
|
/****************************************************************************
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
|
|
|
|
|
** Contact: http://www.qt-project.org/legal
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** This file is part of Qt Creator.
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** Commercial License Usage
|
|
|
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
|
|
|
** accordance with the commercial license agreement provided with the
|
|
|
|
|
** Software or, alternatively, in accordance with the terms contained in
|
|
|
|
|
** a written agreement between you and Digia. For licensing terms and
|
|
|
|
|
** conditions see http://qt.digia.com/licensing. For further information
|
|
|
|
|
** use the contact form at http://qt.digia.com/contact-us.
|
2008-12-02 14:17:16 +01:00
|
|
|
**
|
2009-02-25 09:15:00 +01:00
|
|
|
** GNU Lesser General Public License Usage
|
2012-10-02 09:12:39 +02:00
|
|
|
** 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.
|
|
|
|
|
**
|
|
|
|
|
** In addition, as a special exception, Digia gives you certain additional
|
|
|
|
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
2010-12-17 16:01:08 +01:00
|
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
****************************************************************************/
|
2008-12-02 15:08:31 +01:00
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
#include "debuggerplugin.h"
|
|
|
|
|
|
2011-01-10 10:14:23 +01:00
|
|
|
#include "debuggerstartparameters.h"
|
2009-03-17 17:00:06 +01:00
|
|
|
#include "debuggeractions.h"
|
2008-12-02 12:01:29 +01:00
|
|
|
#include "debuggerconstants.h"
|
2011-04-21 15:52:51 +02:00
|
|
|
#include "debuggerinternalconstants.h"
|
2010-11-10 11:39:01 +01:00
|
|
|
#include "debuggercore.h"
|
2010-06-16 11:08:54 +02:00
|
|
|
#include "debuggerdialogs.h"
|
|
|
|
|
#include "debuggerengine.h"
|
2010-12-02 17:43:14 +01:00
|
|
|
#include "debuggermainwindow.h"
|
2008-12-02 12:01:29 +01:00
|
|
|
#include "debuggerrunner.h"
|
2011-01-10 10:35:41 +01:00
|
|
|
#include "debuggerruncontrolfactory.h"
|
2009-09-25 15:02:16 +02:00
|
|
|
#include "debuggerstringutils.h"
|
2012-09-03 18:31:44 +02:00
|
|
|
#include "debuggerkitinformation.h"
|
2011-04-19 12:17:48 +02:00
|
|
|
#include "memoryagent.h"
|
2010-11-04 09:54:23 +01:00
|
|
|
#include "breakpoint.h"
|
|
|
|
|
#include "breakhandler.h"
|
2010-06-16 11:08:54 +02:00
|
|
|
#include "breakwindow.h"
|
2011-04-12 17:32:41 +02:00
|
|
|
#include "disassemblerlines.h"
|
2010-09-22 16:20:08 +02:00
|
|
|
#include "logwindow.h"
|
2010-06-16 11:08:54 +02:00
|
|
|
#include "moduleswindow.h"
|
2011-01-10 10:14:23 +01:00
|
|
|
#include "moduleshandler.h"
|
2010-06-16 11:08:54 +02:00
|
|
|
#include "registerwindow.h"
|
|
|
|
|
#include "snapshotwindow.h"
|
2010-11-08 15:19:13 +01:00
|
|
|
#include "stackhandler.h"
|
2010-06-16 11:08:54 +02:00
|
|
|
#include "stackwindow.h"
|
|
|
|
|
#include "sourcefileswindow.h"
|
|
|
|
|
#include "threadswindow.h"
|
2010-11-04 18:11:09 +01:00
|
|
|
#include "watchhandler.h"
|
2010-06-16 11:08:54 +02:00
|
|
|
#include "watchwindow.h"
|
2010-11-08 15:19:13 +01:00
|
|
|
#include "watchutils.h"
|
2011-02-11 15:00:13 +01:00
|
|
|
#include "debuggertooltipmanager.h"
|
2012-05-14 16:09:12 +02:00
|
|
|
#include "localsandexpressionswindow.h"
|
2012-07-24 17:02:42 +02:00
|
|
|
#include "loadcoredialog.h"
|
2012-08-08 12:03:07 +02:00
|
|
|
#include "hostutils.h"
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2010-07-21 13:11:03 +02:00
|
|
|
#include "snapshothandler.h"
|
|
|
|
|
#include "threadshandler.h"
|
2011-02-22 12:28:46 +01:00
|
|
|
#include "commonoptionspage.h"
|
2012-07-27 00:17:12 +02:00
|
|
|
#include "gdb/startgdbserverdialog.h"
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2009-01-13 13:39:31 +01:00
|
|
|
#include <coreplugin/actionmanager/actionmanager.h>
|
2010-03-18 10:59:06 +01:00
|
|
|
#include <coreplugin/actionmanager/actioncontainer.h>
|
|
|
|
|
#include <coreplugin/actionmanager/command.h>
|
2011-09-05 16:10:37 +02:00
|
|
|
#include <coreplugin/id.h>
|
2010-12-02 13:34:23 +01:00
|
|
|
#include <coreplugin/imode.h>
|
2008-12-02 12:01:29 +01:00
|
|
|
#include <coreplugin/coreconstants.h>
|
2009-01-14 18:09:02 +01:00
|
|
|
#include <coreplugin/dialogs/ioptionspage.h>
|
2008-12-02 12:01:29 +01:00
|
|
|
#include <coreplugin/editormanager/editormanager.h>
|
2009-01-13 18:15:24 +01:00
|
|
|
#include <coreplugin/findplaceholder.h>
|
2010-06-25 12:56:16 +02:00
|
|
|
#include <coreplugin/icontext.h>
|
2008-12-02 12:01:29 +01:00
|
|
|
#include <coreplugin/icore.h>
|
2010-08-18 13:54:12 +02:00
|
|
|
#include <coreplugin/imode.h>
|
2009-10-26 18:05:11 +01:00
|
|
|
#include <coreplugin/icorelistener.h>
|
2009-01-13 18:15:24 +01:00
|
|
|
#include <coreplugin/minisplitter.h>
|
2008-12-02 12:01:29 +01:00
|
|
|
#include <coreplugin/modemanager.h>
|
2008-12-09 16:18:28 +01:00
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
#include <cppeditor/cppeditorconstants.h>
|
2012-03-14 10:25:55 +01:00
|
|
|
#include <cpptools/ModelManagerInterface.h>
|
2008-12-09 16:18:28 +01:00
|
|
|
|
2009-01-20 11:52:04 +01:00
|
|
|
#include <extensionsystem/pluginmanager.h>
|
2012-01-25 17:28:06 +01:00
|
|
|
#include <extensionsystem/invoker.h>
|
2009-01-20 11:52:04 +01:00
|
|
|
|
2011-10-25 18:23:37 +08:00
|
|
|
#include <projectexplorer/abi.h>
|
2012-01-23 16:45:00 +01:00
|
|
|
#include <projectexplorer/applicationrunconfiguration.h>
|
|
|
|
|
#include <projectexplorer/buildconfiguration.h>
|
2012-08-08 12:03:07 +02:00
|
|
|
#include <projectexplorer/devicesupport/deviceprocessesdialog.h>
|
2008-12-02 12:01:29 +01:00
|
|
|
#include <projectexplorer/projectexplorerconstants.h>
|
2011-10-25 18:23:37 +08:00
|
|
|
#include <projectexplorer/projectexplorer.h>
|
|
|
|
|
#include <projectexplorer/projectexplorersettings.h>
|
|
|
|
|
#include <projectexplorer/project.h>
|
2008-12-02 12:01:29 +01:00
|
|
|
#include <projectexplorer/session.h>
|
2012-09-03 18:31:44 +02:00
|
|
|
#include <projectexplorer/kitchooser.h>
|
|
|
|
|
#include <projectexplorer/kitinformation.h>
|
|
|
|
|
#include <projectexplorer/kitmanager.h>
|
2010-07-21 17:06:22 +02:00
|
|
|
#include <projectexplorer/target.h>
|
2011-10-25 18:23:37 +08:00
|
|
|
#include <projectexplorer/toolchain.h>
|
|
|
|
|
#include <projectexplorer/toolchainmanager.h>
|
2012-08-23 15:23:37 +02:00
|
|
|
#include <projectexplorer/devicesupport/deviceprocesslist.h>
|
2008-12-09 16:18:28 +01:00
|
|
|
|
2011-05-20 21:40:53 +02:00
|
|
|
#include <qtsupport/qtsupportconstants.h>
|
2010-11-08 16:17:59 +01:00
|
|
|
|
2008-12-09 16:18:28 +01:00
|
|
|
#include <texteditor/basetexteditor.h>
|
2010-06-16 11:08:54 +02:00
|
|
|
#include <texteditor/fontsettings.h>
|
2010-04-19 16:42:02 +02:00
|
|
|
#include <texteditor/texteditorsettings.h>
|
2008-12-09 16:18:28 +01:00
|
|
|
|
2012-08-23 15:53:58 +02:00
|
|
|
#include <utils/hostosinfo.h>
|
2008-12-09 16:18:28 +01:00
|
|
|
#include <utils/qtcassert.h>
|
2010-03-18 10:59:06 +01:00
|
|
|
#include <utils/savedaction.h>
|
2010-06-16 11:08:54 +02:00
|
|
|
#include <utils/styledbar.h>
|
2011-01-12 16:36:29 +01:00
|
|
|
#include <utils/proxyaction.h>
|
2011-03-16 13:49:28 +01:00
|
|
|
#include <utils/statuslabel.h>
|
2011-03-30 15:15:15 +02:00
|
|
|
#include <utils/fileutils.h>
|
2012-08-23 15:23:37 +02:00
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
|
# include <utils/winutils.h>
|
|
|
|
|
#endif
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QComboBox>
|
|
|
|
|
#include <QDockWidget>
|
|
|
|
|
#include <QFileDialog>
|
2012-06-05 10:25:48 +02:00
|
|
|
#include <QInputDialog>
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QMenu>
|
|
|
|
|
#include <QMessageBox>
|
|
|
|
|
#include <QPushButton>
|
2012-06-05 10:25:48 +02:00
|
|
|
#include <QTemporaryFile>
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QTextBlock>
|
|
|
|
|
#include <QTextCursor>
|
2012-06-05 10:25:48 +02:00
|
|
|
#include <QTimer>
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QToolButton>
|
2012-06-05 10:25:48 +02:00
|
|
|
#include <QtPlugin>
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QTreeWidget>
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2012-01-23 16:45:00 +01:00
|
|
|
#ifdef WITH_TESTS
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QTest>
|
|
|
|
|
#include <QSignalSpy>
|
|
|
|
|
#include <QTestEventLoop>
|
2012-01-26 13:14:00 +01:00
|
|
|
|
|
|
|
|
//#define WITH_BENCHMARK
|
|
|
|
|
#ifdef WITH_BENCHMARK
|
|
|
|
|
#include <valgrind/callgrind.h>
|
2012-01-23 16:45:00 +01:00
|
|
|
#endif
|
|
|
|
|
|
2012-01-26 13:14:00 +01:00
|
|
|
#endif // WITH_TESTS
|
|
|
|
|
|
2009-08-12 10:51:25 +02:00
|
|
|
#include <climits>
|
|
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
#define DEBUG_STATE 1
|
|
|
|
|
#ifdef DEBUG_STATE
|
|
|
|
|
//# define STATE_DEBUG(s)
|
|
|
|
|
// do { QString msg; QTextStream ts(&msg); ts << s;
|
|
|
|
|
// showMessage(msg, LogDebug); } while (0)
|
|
|
|
|
# define STATE_DEBUG(s) do { qDebug() << s; } while(0)
|
|
|
|
|
#else
|
|
|
|
|
# define STATE_DEBUG(s)
|
|
|
|
|
#endif
|
|
|
|
|
|
2011-01-26 17:22:25 +01:00
|
|
|
/*!
|
|
|
|
|
\namespace Debugger
|
|
|
|
|
Debugger plugin namespace
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
\namespace Debugger::Internal
|
|
|
|
|
Internal namespace of the Debugger plugin
|
2011-02-04 15:08:31 +01:00
|
|
|
\internal
|
2011-01-26 17:22:25 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
\class Debugger::DebuggerEngine
|
|
|
|
|
|
|
|
|
|
\brief Base class of a debugger engine.
|
|
|
|
|
|
|
|
|
|
Note: the Debugger process itself and any helper processes like
|
2012-08-22 13:27:25 +02:00
|
|
|
gdbserver are referred to as 'Engine', whereas the debugged process
|
|
|
|
|
is referred to as 'Inferior'.
|
2011-01-26 17:22:25 +01:00
|
|
|
|
|
|
|
|
Transitions marked by '---' are done in the individual engines.
|
|
|
|
|
Transitions marked by '+-+' are done in the base DebuggerEngine.
|
|
|
|
|
Transitions marked by '*' are done asynchronously.
|
|
|
|
|
|
|
|
|
|
The GdbEngine->setupEngine() function is described in more detail below.
|
|
|
|
|
|
|
|
|
|
The engines are responsible for local roll-back to the last
|
|
|
|
|
acknowledged state before calling notify*Failed. I.e. before calling
|
|
|
|
|
notifyEngineSetupFailed() any process started during setupEngine()
|
|
|
|
|
so far must be terminated.
|
|
|
|
|
\code
|
|
|
|
|
|
|
|
|
|
DebuggerNotReady
|
|
|
|
|
progressmanager/progressmanager.cpp +
|
|
|
|
|
EngineSetupRequested
|
|
|
|
|
+
|
|
|
|
|
(calls *Engine->setupEngine())
|
|
|
|
|
| |
|
|
|
|
|
| |
|
|
|
|
|
{notify- {notify-
|
|
|
|
|
Engine- Engine-
|
|
|
|
|
SetupOk} SetupFailed}
|
|
|
|
|
+ +
|
|
|
|
|
+ `+-+-+> EngineSetupFailed
|
|
|
|
|
+ +
|
|
|
|
|
+ [calls RunControl->startFailed]
|
|
|
|
|
+ +
|
|
|
|
|
+ DebuggerFinished
|
|
|
|
|
v
|
|
|
|
|
EngineSetupOk
|
|
|
|
|
+
|
|
|
|
|
[calls RunControl->StartSuccessful]
|
|
|
|
|
+
|
|
|
|
|
InferiorSetupRequested
|
|
|
|
|
+
|
|
|
|
|
(calls *Engine->setupInferior())
|
|
|
|
|
| |
|
|
|
|
|
| |
|
|
|
|
|
{notify- {notify-
|
|
|
|
|
Inferior- Inferior-
|
|
|
|
|
SetupOk} SetupFailed}
|
|
|
|
|
+ +
|
|
|
|
|
+ ` +-+-> InferiorSetupFailed +-+-+-+-+-+->.
|
|
|
|
|
+ +
|
|
|
|
|
InferiorSetupOk +
|
|
|
|
|
+ +
|
|
|
|
|
EngineRunRequested +
|
|
|
|
|
+ +
|
|
|
|
|
(calls *Engine->runEngine()) +
|
|
|
|
|
/ | | \ +
|
|
|
|
|
/ | | \ +
|
|
|
|
|
| (core) | (attach) | | +
|
|
|
|
|
| | | | +
|
|
|
|
|
{notify- {notifyER&- {notifyER&- {notify- +
|
|
|
|
|
Inferior- Inferior- Inferior- EngineRun- +
|
|
|
|
|
Unrunnable} StopOk} RunOk} Failed} +
|
|
|
|
|
+ + + + +
|
|
|
|
|
InferiorUnrunnable + InferiorRunOk + +
|
|
|
|
|
+ + +
|
|
|
|
|
InferiorStopOk EngineRunFailed +
|
|
|
|
|
+ v
|
|
|
|
|
`-+-+-+-+-+-+-+-+-+-+-+>-+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
#Interrupt@InferiorRunOk# +
|
|
|
|
|
+ +
|
|
|
|
|
InferiorStopRequested +
|
|
|
|
|
#SpontaneousStop + +
|
|
|
|
|
@InferiorRunOk# (calls *Engine-> +
|
|
|
|
|
+ interruptInferior()) +
|
|
|
|
|
{notify- | | +
|
|
|
|
|
Spontaneous- {notify- {notify- +
|
|
|
|
|
Inferior- Inferior- Inferior- +
|
|
|
|
|
StopOk} StopOk} StopFailed} +
|
|
|
|
|
+ + + +
|
|
|
|
|
+ + + +
|
|
|
|
|
InferiorStopOk + +
|
|
|
|
|
+ + +
|
|
|
|
|
+ + +
|
|
|
|
|
+ + +
|
|
|
|
|
#Stop@InferiorUnrunnable# + +
|
|
|
|
|
#Creator Close Event# + +
|
|
|
|
|
+ + +
|
|
|
|
|
InferiorShutdownRequested +
|
|
|
|
|
+ +
|
|
|
|
|
(calls *Engine->shutdownInferior()) +
|
|
|
|
|
| | +
|
|
|
|
|
{notify- {notify- +
|
|
|
|
|
Inferior- Inferior- +
|
|
|
|
|
ShutdownOk} ShutdownFailed} +
|
|
|
|
|
+ + +
|
|
|
|
|
+ + +
|
|
|
|
|
#Inferior exited# + + +
|
|
|
|
|
| + + +
|
|
|
|
|
{notifyInferior- + + +
|
|
|
|
|
Exited} + + +
|
|
|
|
|
+ + + +
|
|
|
|
|
InferiorExitOk + + +
|
|
|
|
|
+ + + +
|
|
|
|
|
InferiorShutdownOk InferiorShutdownFailed +
|
|
|
|
|
* * +
|
|
|
|
|
EngineShutdownRequested +
|
|
|
|
|
+ +
|
|
|
|
|
(calls *Engine->shutdownEngine()) <+-+-+-+-+-+-+-+-+-+-+-+-+-+'
|
|
|
|
|
| |
|
|
|
|
|
| |
|
|
|
|
|
{notify- {notify-
|
|
|
|
|
Engine- Engine-
|
|
|
|
|
ShutdownOk} ShutdownFailed}
|
|
|
|
|
+ +
|
|
|
|
|
EngineShutdownOk EngineShutdownFailed
|
|
|
|
|
* *
|
|
|
|
|
DebuggerFinished
|
|
|
|
|
|
|
|
|
|
\endcode */
|
2010-11-08 15:19:13 +01:00
|
|
|
|
2010-08-31 12:49:51 +02:00
|
|
|
/* Here is a matching graph as a GraphViz graph. View it using
|
|
|
|
|
* \code
|
|
|
|
|
grep "^sg1:" debuggerplugin.cpp | cut -c5- | dot -osg1.ps -Tps && gv sg1.ps
|
2010-07-08 11:44:00 +02:00
|
|
|
|
2010-08-31 12:49:51 +02:00
|
|
|
sg1: digraph DebuggerStates {
|
|
|
|
|
sg1: DebuggerNotReady -> EngineSetupRequested
|
|
|
|
|
sg1: EngineSetupRequested -> EngineSetupOk [ label="notifyEngineSetupOk", style="dashed" ];
|
|
|
|
|
sg1: EngineSetupRequested -> EngineSetupFailed [ label= "notifyEngineSetupFailed", style="dashed"];
|
|
|
|
|
sg1: EngineSetupFailed -> DebuggerFinished [ label= "RunControl::StartFailed" ];
|
|
|
|
|
sg1: EngineSetupOk -> InferiorSetupRequested [ label= "RunControl::StartSuccessful" ];
|
2011-01-17 10:36:13 +01:00
|
|
|
sg1: InferiorSetupRequested -> InferiorSetupOk [ label="notifyInferiorSetupOk", style="dashed" ];
|
2010-08-31 12:49:51 +02:00
|
|
|
sg1: InferiorSetupRequested -> InferiorSetupFailed [ label="notifyInferiorFailed", style="dashed" ];
|
2011-01-17 10:36:13 +01:00
|
|
|
sg1: InferiorSetupOk -> EngineRunRequested
|
2010-08-31 12:49:51 +02:00
|
|
|
sg1: InferiorSetupFailed -> EngineShutdownRequested
|
|
|
|
|
sg1: EngineRunRequested -> InferiorUnrunnable [ label="notifyInferiorUnrunnable", style="dashed" ];
|
|
|
|
|
sg1: EngineRunRequested -> InferiorStopOk [ label="notifyEngineRunAndInferiorStopOk", style="dashed" ];
|
|
|
|
|
sg1: EngineRunRequested -> InferiorRunOk [ label="notifyEngineRunAndInferiorRunOk", style="dashed" ];
|
|
|
|
|
sg1: EngineRunRequested -> EngineRunFailed [ label="notifyEngineRunFailed", style="dashed" ];
|
|
|
|
|
sg1: EngineRunFailed -> EngineShutdownRequested
|
|
|
|
|
sg1: InferiorRunOk -> InferiorStopOk [ label="SpontaneousStop\nnotifyInferiorSpontaneousStop", style="dashed" ];
|
|
|
|
|
sg1: InferiorRunOk -> InferiorStopRequested [ label="User stop\nEngine::interruptInferior", style="dashed"];
|
|
|
|
|
sg1: InferiorStopRequested -> InferiorStopOk [ label="notifyInferiorStopOk", style="dashed" ];
|
|
|
|
|
sg1: InferiorStopRequested -> InferiorShutdownRequested [ label="notifyInferiorStopFailed", style="dashed" ];
|
|
|
|
|
sg1: InferiorStopOk -> InferiorRunRequested [ label="User\nEngine::continueInferior" ];
|
|
|
|
|
sg1: InferiorRunRequested -> InferiorRunOk [ label="notifyInferiorRunOk", style="dashed"];
|
|
|
|
|
sg1: InferiorRunRequested -> InferiorRunFailed [ label="notifyInferiorRunFailed", style="dashed"];
|
|
|
|
|
sg1: InferiorRunFailed -> InferiorStopOk
|
2011-01-17 10:36:13 +01:00
|
|
|
sg1: InferiorStopOk -> InferiorShutdownRequested [ label="Close event" ];
|
|
|
|
|
sg1: InferiorUnrunnable -> InferiorShutdownRequested [ label="Close event" ];
|
2010-08-31 12:49:51 +02:00
|
|
|
sg1: InferiorShutdownRequested -> InferiorShutdownOk [ label= "Engine::shutdownInferior\nnotifyInferiorShutdownOk", style="dashed" ];
|
|
|
|
|
sg1: InferiorShutdownRequested -> InferiorShutdownFailed [ label="Engine::shutdownInferior\nnotifyInferiorShutdownFailed", style="dashed" ];
|
2011-01-17 10:36:13 +01:00
|
|
|
sg1: InferiorExited -> InferiorExitOk [ label="notifyInferiorExited", style="dashed"];
|
|
|
|
|
sg1: InferiorExitOk -> InferiorShutdownOk
|
2010-08-31 12:49:51 +02:00
|
|
|
sg1: InferiorShutdownOk -> EngineShutdownRequested
|
|
|
|
|
sg1: InferiorShutdownFailed -> EngineShutdownRequested
|
|
|
|
|
sg1: EngineShutdownRequested -> EngineShutdownOk [ label="Engine::shutdownEngine\nnotifyEngineShutdownOk", style="dashed" ];
|
|
|
|
|
sg1: EngineShutdownRequested -> EngineShutdownFailed [ label="Engine::shutdownEngine\nnotifyEngineShutdownFailed", style="dashed" ];
|
|
|
|
|
sg1: EngineShutdownOk -> DebuggerFinished [ style = "dotted" ];
|
|
|
|
|
sg1: EngineShutdownFailed -> DebuggerFinished [ style = "dotted" ];
|
|
|
|
|
sg1: }
|
|
|
|
|
* \endcode */
|
2010-07-15 09:41:11 +02:00
|
|
|
// Additional signalling: {notifyInferiorIll} {notifyEngineIll}
|
2010-07-09 17:07:59 +02:00
|
|
|
|
|
|
|
|
|
2011-01-26 17:22:25 +01:00
|
|
|
/*!
|
|
|
|
|
\class Debugger::Internal::GdbEngine
|
|
|
|
|
\brief Implementation of Debugger::Engine driving a gdb executable.
|
|
|
|
|
|
|
|
|
|
GdbEngine specific startup. All happens in EngineSetupRequested state:
|
|
|
|
|
|
|
|
|
|
Transitions marked by '---' are done in the individual adapters.
|
|
|
|
|
|
|
|
|
|
Transitions marked by '+-+' are done in the GdbEngine.
|
|
|
|
|
|
|
|
|
|
\code
|
|
|
|
|
GdbEngine::setupEngine()
|
|
|
|
|
+
|
|
|
|
|
(calls *Adapter->startAdapter())
|
|
|
|
|
| |
|
|
|
|
|
| `---> handleAdapterStartFailed()
|
|
|
|
|
| +
|
|
|
|
|
| {notifyEngineSetupFailed}
|
|
|
|
|
|
|
|
|
|
|
handleAdapterStarted()
|
|
|
|
|
+
|
|
|
|
|
{notifyEngineSetupOk}
|
2010-07-08 11:44:00 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-01-26 17:22:25 +01:00
|
|
|
GdbEngine::setupInferior()
|
|
|
|
|
+
|
|
|
|
|
(calls *Adapter->prepareInferior())
|
|
|
|
|
| |
|
|
|
|
|
| `---> handlePrepareInferiorFailed()
|
|
|
|
|
| +
|
|
|
|
|
| {notifyInferiorSetupFailed}
|
|
|
|
|
|
|
|
|
|
|
handleInferiorPrepared()
|
|
|
|
|
+
|
|
|
|
|
{notifyInferiorSetupOk}
|
2010-07-08 11:44:00 +02:00
|
|
|
|
2011-01-26 17:22:25 +01:00
|
|
|
\endcode */
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
using namespace Core;
|
2009-01-13 18:15:24 +01:00
|
|
|
using namespace Debugger::Constants;
|
2012-08-15 16:19:15 +02:00
|
|
|
using namespace ExtensionSystem;
|
2008-12-02 12:01:29 +01:00
|
|
|
using namespace ProjectExplorer;
|
2009-01-13 18:15:24 +01:00
|
|
|
using namespace TextEditor;
|
2012-08-15 16:19:15 +02:00
|
|
|
using namespace Utils;
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2010-03-11 12:22:24 +01:00
|
|
|
namespace CC = Core::Constants;
|
|
|
|
|
namespace PE = ProjectExplorer::Constants;
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
|
|
|
|
|
namespace Debugger {
|
|
|
|
|
namespace Constants {
|
|
|
|
|
|
|
|
|
|
} // namespace Constants
|
|
|
|
|
|
|
|
|
|
|
2010-11-24 11:44:43 +01:00
|
|
|
namespace Internal {
|
|
|
|
|
|
2011-06-27 10:37:57 +02:00
|
|
|
// To be passed through margin menu action's data
|
|
|
|
|
struct BreakpointMenuContextData : public ContextData
|
|
|
|
|
{
|
|
|
|
|
enum Mode
|
|
|
|
|
{
|
|
|
|
|
Breakpoint,
|
|
|
|
|
MessageTracePoint
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
BreakpointMenuContextData() : mode(Breakpoint) {}
|
|
|
|
|
Mode mode;
|
|
|
|
|
};
|
|
|
|
|
|
2012-01-25 17:28:06 +01:00
|
|
|
struct TestCallBack
|
|
|
|
|
{
|
|
|
|
|
TestCallBack() : receiver(0), slot(0) {}
|
|
|
|
|
TestCallBack(QObject *ob, const char *s) : receiver(ob), slot(s) {}
|
|
|
|
|
|
|
|
|
|
QObject *receiver;
|
|
|
|
|
const char *slot;
|
|
|
|
|
QVariant cookie;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2011-06-27 10:37:57 +02:00
|
|
|
} // namespace Internal
|
|
|
|
|
} // namespace Debugger
|
|
|
|
|
|
|
|
|
|
Q_DECLARE_METATYPE(Debugger::Internal::BreakpointMenuContextData)
|
2012-01-25 17:28:06 +01:00
|
|
|
Q_DECLARE_METATYPE(Debugger::Internal::TestCallBack)
|
|
|
|
|
|
2011-06-27 10:37:57 +02:00
|
|
|
|
|
|
|
|
namespace Debugger {
|
|
|
|
|
namespace Internal {
|
|
|
|
|
|
2010-11-24 11:44:43 +01:00
|
|
|
// FIXME: Outdated?
|
|
|
|
|
// The createCdbEngine function takes a list of options pages it can add to.
|
|
|
|
|
// This allows for having a "enabled" toggle on the page independently
|
|
|
|
|
// of the engine. That's good for not enabling the related ActiveX control
|
|
|
|
|
// unnecessarily.
|
|
|
|
|
|
2011-01-12 12:10:12 +01:00
|
|
|
void addCdbOptionPages(QList<IOptionsPage*> *opts);
|
2010-11-24 11:44:43 +01:00
|
|
|
void addGdbOptionPages(QList<IOptionsPage*> *opts);
|
|
|
|
|
void addScriptOptionPages(QList<IOptionsPage*> *opts);
|
|
|
|
|
void addTcfOptionPages(QList<IOptionsPage*> *opts);
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2010-11-26 15:10:10 +01:00
|
|
|
#ifdef WITH_LLDB
|
|
|
|
|
void addLldbOptionPages(QList<IOptionsPage*> *opts);
|
|
|
|
|
#endif
|
|
|
|
|
|
2010-08-31 13:07:33 +02:00
|
|
|
static SessionManager *sessionManager()
|
2009-01-28 14:29:54 +01:00
|
|
|
{
|
2010-08-31 13:07:33 +02:00
|
|
|
return ProjectExplorerPlugin::instance()->session();
|
2009-01-28 14:29:54 +01:00
|
|
|
}
|
|
|
|
|
|
2009-07-16 15:57:59 +02:00
|
|
|
static QToolButton *toolButton(QAction *action)
|
|
|
|
|
{
|
|
|
|
|
QToolButton *button = new QToolButton;
|
|
|
|
|
button->setDefaultAction(action);
|
|
|
|
|
return button;
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-15 16:19:15 +02:00
|
|
|
static void setProxyAction(ProxyAction *proxy, const char *id)
|
2012-05-24 10:19:50 +02:00
|
|
|
{
|
2012-07-18 16:20:19 +02:00
|
|
|
proxy->setAction(ActionManager::command(id)->action());
|
2012-05-24 10:19:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static QToolButton *toolButton(const char *id)
|
|
|
|
|
{
|
2012-07-18 16:20:19 +02:00
|
|
|
return toolButton(ActionManager::command(id)->action());
|
2012-05-24 10:19:50 +02:00
|
|
|
}
|
|
|
|
|
|
2010-11-23 13:44:37 +01:00
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
|
|
|
|
// DummyEngine
|
|
|
|
|
//
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
class DummyEngine : public DebuggerEngine
|
|
|
|
|
{
|
|
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
|
|
public:
|
2012-08-14 17:54:01 +02:00
|
|
|
DummyEngine() : DebuggerEngine(DebuggerStartParameters()) {}
|
2010-11-26 10:20:50 +01:00
|
|
|
~DummyEngine() {}
|
|
|
|
|
|
|
|
|
|
void setupEngine() {}
|
|
|
|
|
void setupInferior() {}
|
|
|
|
|
void runEngine() {}
|
|
|
|
|
void shutdownEngine() {}
|
|
|
|
|
void shutdownInferior() {}
|
2012-01-12 20:28:17 +01:00
|
|
|
bool hasCapability(unsigned cap) const;
|
2011-06-24 16:25:30 +02:00
|
|
|
bool acceptsBreakpoint(BreakpointModelId) const { return false; }
|
2011-02-16 12:41:06 +01:00
|
|
|
bool acceptsDebuggerCommands() const { return false; }
|
2012-10-19 16:37:57 +02:00
|
|
|
void selectThread(ThreadId) {}
|
2010-11-23 13:44:37 +01:00
|
|
|
};
|
|
|
|
|
|
2012-01-12 20:28:17 +01:00
|
|
|
bool DummyEngine::hasCapability(unsigned cap) const
|
2012-01-12 19:32:25 +01:00
|
|
|
{
|
|
|
|
|
// This can only be a first approximation of what to expect when running.
|
2012-01-24 18:57:39 +01:00
|
|
|
Project *project = ProjectExplorerPlugin::currentProject();
|
2012-01-12 19:32:25 +01:00
|
|
|
if (!project)
|
|
|
|
|
return 0;
|
|
|
|
|
Target *target = project->activeTarget();
|
|
|
|
|
QTC_ASSERT(target, return 0);
|
|
|
|
|
RunConfiguration *activeRc = target->activeRunConfiguration();
|
|
|
|
|
QTC_ASSERT(activeRc, return 0);
|
|
|
|
|
|
|
|
|
|
// This is a non-started Cdb or Gdb engine:
|
2012-02-17 19:05:11 +01:00
|
|
|
if (activeRc->debuggerAspect()->useCppDebugger())
|
2012-01-12 20:28:17 +01:00
|
|
|
return cap & (WatchpointByAddressCapability
|
2012-01-12 19:32:25 +01:00
|
|
|
| BreakConditionCapability
|
|
|
|
|
| TracePointCapability
|
2012-01-12 20:28:17 +01:00
|
|
|
| OperateByInstructionCapability);
|
2012-01-12 19:32:25 +01:00
|
|
|
|
|
|
|
|
// This is a Qml or unknown engine.
|
2012-01-12 20:28:17 +01:00
|
|
|
return cap & AddWatcherCapability;
|
2012-01-12 19:32:25 +01:00
|
|
|
}
|
|
|
|
|
|
2009-01-14 18:09:02 +01:00
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
|
|
|
|
// DebugMode
|
|
|
|
|
//
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2010-12-02 13:34:23 +01:00
|
|
|
class DebugMode : public IMode
|
2009-01-13 18:15:24 +01:00
|
|
|
{
|
|
|
|
|
public:
|
2011-04-13 13:00:30 +02:00
|
|
|
DebugMode()
|
|
|
|
|
{
|
|
|
|
|
setObjectName(QLatin1String("DebugMode"));
|
|
|
|
|
setContext(Context(CC::C_EDITORMANAGER, C_DEBUGMODE, CC::C_NAVIGATION_PANE));
|
2011-04-13 16:09:04 +02:00
|
|
|
setDisplayName(DebuggerPlugin::tr("Debug"));
|
|
|
|
|
setIcon(QIcon(QLatin1String(":/fancyactionbar/images/mode_Debug.png")));
|
2011-07-15 10:55:39 +02:00
|
|
|
setPriority(85);
|
2012-05-07 18:28:03 +02:00
|
|
|
setId(MODE_DEBUG);
|
|
|
|
|
setType(CC::MODE_EDIT_TYPE);
|
2011-04-13 13:00:30 +02:00
|
|
|
}
|
2009-01-13 18:15:24 +01:00
|
|
|
|
2010-12-08 17:54:16 +01:00
|
|
|
~DebugMode()
|
|
|
|
|
{
|
|
|
|
|
// Make sure the editor manager does not get deleted.
|
|
|
|
|
//EditorManager::instance()->setParent(0);
|
|
|
|
|
delete m_widget;
|
|
|
|
|
}
|
2010-06-16 11:08:54 +02:00
|
|
|
};
|
2009-01-13 18:15:24 +01:00
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
|
|
|
|
// Misc
|
|
|
|
|
//
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2012-08-23 15:23:37 +02:00
|
|
|
static inline QString executableForPid(qint64 pid)
|
|
|
|
|
{
|
|
|
|
|
foreach (const ProjectExplorer::DeviceProcess &p, ProjectExplorer::DeviceProcessList::localProcesses())
|
|
|
|
|
if (p.pid == pid)
|
|
|
|
|
return p.exe;
|
|
|
|
|
return QString();
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-03 18:31:44 +02:00
|
|
|
class AbiKitMatcher : public KitMatcher
|
2012-08-23 15:23:37 +02:00
|
|
|
{
|
|
|
|
|
public:
|
2012-09-03 18:31:44 +02:00
|
|
|
explicit AbiKitMatcher(const QList<Abi> &abis) : m_abis(abis) {}
|
2012-09-09 20:41:30 +03:00
|
|
|
bool matches(const Kit *k) const
|
2012-08-23 15:23:37 +02:00
|
|
|
{
|
2012-09-09 20:41:30 +03:00
|
|
|
if (const ToolChain *tc = ToolChainKitInformation::toolChain(k)) {
|
2012-09-05 14:56:08 +02:00
|
|
|
return m_abis.contains(tc->targetAbi())
|
2012-09-09 20:41:30 +03:00
|
|
|
&& DebuggerKitInformation::isValidDebugger(k);
|
2012-09-05 14:56:08 +02:00
|
|
|
}
|
2012-08-23 15:23:37 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
const QList<Abi> m_abis;
|
|
|
|
|
};
|
|
|
|
|
|
2012-09-03 18:31:44 +02:00
|
|
|
class CompatibleAbiKitMatcher : public KitMatcher
|
2012-08-23 15:23:37 +02:00
|
|
|
{
|
|
|
|
|
public:
|
2012-09-03 18:31:44 +02:00
|
|
|
explicit CompatibleAbiKitMatcher(const QList<Abi> &abis) : m_abis(abis) {}
|
2012-09-09 20:41:30 +03:00
|
|
|
bool matches(const Kit *k) const
|
2012-08-23 15:23:37 +02:00
|
|
|
{
|
2012-09-09 20:41:30 +03:00
|
|
|
if (const ToolChain *tc = ToolChainKitInformation::toolChain(k))
|
2012-08-23 15:23:37 +02:00
|
|
|
foreach (const Abi &a, m_abis)
|
2012-09-09 20:41:30 +03:00
|
|
|
if (a.isCompatibleWith(tc->targetAbi()) && DebuggerKitInformation::isValidDebugger(k))
|
2012-08-23 15:23:37 +02:00
|
|
|
return true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
const QList<Abi> m_abis;
|
|
|
|
|
};
|
|
|
|
|
|
2012-09-03 18:31:44 +02:00
|
|
|
class CdbMatcher : KitMatcher
|
2012-06-28 10:00:04 +02:00
|
|
|
{
|
2012-08-23 15:23:37 +02:00
|
|
|
public:
|
|
|
|
|
CdbMatcher(char wordWidth = 0) : m_wordWidth(wordWidth) {}
|
|
|
|
|
|
2012-09-03 18:31:44 +02:00
|
|
|
bool matches(const Kit *k) const
|
2012-08-23 15:23:37 +02:00
|
|
|
{
|
2012-09-05 14:56:08 +02:00
|
|
|
if (DebuggerKitInformation::engineType(k) != CdbEngineType
|
|
|
|
|
|| !DebuggerKitInformation::isValidDebugger(k)) {
|
2012-08-23 15:23:37 +02:00
|
|
|
return false;
|
2012-09-05 14:56:08 +02:00
|
|
|
}
|
|
|
|
|
if (m_wordWidth) {
|
|
|
|
|
const ToolChain *tc = ToolChainKitInformation::toolChain(k);
|
|
|
|
|
return tc && m_wordWidth == tc->targetAbi().wordWidth();
|
|
|
|
|
}
|
2012-08-23 15:23:37 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-03 18:31:44 +02:00
|
|
|
// Find a CDB kit for debugging unknown processes.
|
2012-08-23 15:23:37 +02:00
|
|
|
// On a 64bit OS, prefer a 64bit debugger.
|
2012-09-03 18:31:44 +02:00
|
|
|
static Kit *findUniversalCdbKit()
|
2012-08-23 15:23:37 +02:00
|
|
|
{
|
|
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
|
if (Utils::winIs64BitSystem()) {
|
|
|
|
|
CdbMatcher matcher64(64);
|
2012-09-03 18:31:44 +02:00
|
|
|
if (Kit *cdb64Kit = KitManager::instance()->find(&matcher64))
|
|
|
|
|
return cdb64Kit;
|
2012-08-23 15:23:37 +02:00
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
CdbMatcher matcher;
|
2012-09-03 18:31:44 +02:00
|
|
|
return KitManager::instance()->find(&matcher);
|
2012-08-23 15:23:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
const char m_wordWidth;
|
|
|
|
|
};
|
|
|
|
|
|
2012-09-05 14:56:08 +02:00
|
|
|
bool fillParameters(DebuggerStartParameters *sp, const Kit *kit /* = 0 */, QString *errorMessage /* = 0 */)
|
2012-08-23 15:23:37 +02:00
|
|
|
{
|
2012-09-03 18:31:44 +02:00
|
|
|
if (!kit) {
|
2012-08-31 15:06:07 +02:00
|
|
|
// This code can only be reached when starting via the command line
|
|
|
|
|
// (-debug pid or executable) or attaching from runconfiguration
|
2012-09-03 18:31:44 +02:00
|
|
|
// without specifying a kit. Try to find a kit via ABI.
|
2012-08-31 15:06:07 +02:00
|
|
|
QList<Abi> abis;
|
|
|
|
|
if (sp->toolChainAbi.isValid()) {
|
|
|
|
|
abis.push_back(sp->toolChainAbi);
|
|
|
|
|
} else {
|
|
|
|
|
// Try via executable.
|
|
|
|
|
if (sp->executable.isEmpty()
|
|
|
|
|
&& (sp->startMode == AttachExternal || sp->startMode == AttachCrashedExternal)) {
|
|
|
|
|
sp->executable = executableForPid(sp->attachPID);
|
|
|
|
|
}
|
|
|
|
|
if (!sp->executable.isEmpty())
|
|
|
|
|
abis = Abi::abisOfBinary(Utils::FileName::fromString(sp->executable));
|
2012-08-23 15:23:37 +02:00
|
|
|
}
|
2012-08-31 15:06:07 +02:00
|
|
|
if (!abis.isEmpty()) {
|
2012-09-03 18:31:44 +02:00
|
|
|
AbiKitMatcher matcher(abis);
|
|
|
|
|
kit = KitManager::instance()->find(&matcher);
|
|
|
|
|
if (!kit) {
|
|
|
|
|
CompatibleAbiKitMatcher matcher(abis);
|
|
|
|
|
kit = KitManager::instance()->find(&matcher);
|
2012-08-23 15:23:37 +02:00
|
|
|
}
|
|
|
|
|
}
|
2012-09-03 18:31:44 +02:00
|
|
|
if (!kit)
|
|
|
|
|
kit = KitManager::instance()->defaultKit();
|
2012-08-23 15:23:37 +02:00
|
|
|
}
|
|
|
|
|
|
2012-09-05 14:56:08 +02:00
|
|
|
// Verify that debugger and profile are valid
|
|
|
|
|
if (!kit) {
|
|
|
|
|
sp->startMode = NoStartMode;
|
|
|
|
|
if (errorMessage)
|
|
|
|
|
*errorMessage = DebuggerKitInformation::tr("No kit found.");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2012-10-16 15:28:54 +02:00
|
|
|
// validate debugger if C++ debugging is enabled
|
|
|
|
|
if (sp->languages & CppLanguage) {
|
|
|
|
|
const QList<ProjectExplorer::Task> tasks = DebuggerKitInformation::validateDebugger(kit);
|
|
|
|
|
if (!tasks.isEmpty()) {
|
|
|
|
|
sp->startMode = NoStartMode;
|
|
|
|
|
if (errorMessage) {
|
|
|
|
|
foreach (const ProjectExplorer::Task &t, tasks) {
|
|
|
|
|
if (errorMessage->isEmpty())
|
|
|
|
|
errorMessage->append(QLatin1Char('\n'));
|
|
|
|
|
errorMessage->append(t.description);
|
|
|
|
|
}
|
2012-09-05 14:56:08 +02:00
|
|
|
}
|
2012-10-16 15:28:54 +02:00
|
|
|
return false;
|
2012-09-05 14:56:08 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
sp->cppEngineType = DebuggerKitInformation::engineType(kit);
|
2012-09-03 18:31:44 +02:00
|
|
|
sp->sysRoot = SysRootKitInformation::sysRoot(kit).toString();
|
|
|
|
|
sp->debuggerCommand = DebuggerKitInformation::debuggerCommand(kit).toString();
|
2012-07-25 01:42:14 +02:00
|
|
|
|
2012-09-03 18:31:44 +02:00
|
|
|
ToolChain *tc = ToolChainKitInformation::toolChain(kit);
|
2012-06-28 10:00:04 +02:00
|
|
|
if (tc)
|
|
|
|
|
sp->toolChainAbi = tc->targetAbi();
|
2012-07-25 01:42:14 +02:00
|
|
|
|
2012-09-03 18:31:44 +02:00
|
|
|
IDevice::ConstPtr device = DeviceKitInformation::device(kit);
|
2012-07-25 01:42:14 +02:00
|
|
|
if (device) {
|
|
|
|
|
sp->connParams = device->sshParameters();
|
2012-08-22 11:58:33 +02:00
|
|
|
sp->remoteChannel = sp->connParams.host + QLatin1Char(':') + QString::number(sp->connParams.port);
|
2012-07-25 01:42:14 +02:00
|
|
|
}
|
2012-09-05 14:56:08 +02:00
|
|
|
return true;
|
2012-06-28 10:00:04 +02:00
|
|
|
}
|
|
|
|
|
|
2011-02-23 10:16:11 +01:00
|
|
|
static TextEditor::ITextEditor *currentTextEditor()
|
2011-01-04 15:54:36 +01:00
|
|
|
{
|
2012-07-18 16:20:19 +02:00
|
|
|
return qobject_cast<TextEditor::ITextEditor *>(EditorManager::currentEditor());
|
2011-02-23 10:16:11 +01:00
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2011-02-23 10:16:11 +01:00
|
|
|
static bool currentTextEditorPosition(ContextData *data)
|
|
|
|
|
{
|
2012-01-17 16:22:05 +01:00
|
|
|
TextEditor::ITextEditor *textEditor = currentTextEditor();
|
|
|
|
|
if (!textEditor)
|
|
|
|
|
return false;
|
2012-07-18 16:20:19 +02:00
|
|
|
const IDocument *document = textEditor->document();
|
2012-02-14 16:43:51 +01:00
|
|
|
QTC_ASSERT(document, return false);
|
|
|
|
|
data->fileName = document->fileName();
|
2012-01-17 16:22:05 +01:00
|
|
|
if (textEditor->property("DisassemblerView").toBool()) {
|
|
|
|
|
int lineNumber = textEditor->currentLine();
|
|
|
|
|
QString line = textEditor->contents()
|
|
|
|
|
.section(QLatin1Char('\n'), lineNumber - 1, lineNumber - 1);
|
|
|
|
|
data->address = DisassemblerLine::addressFromDisassemblyLine(line);
|
|
|
|
|
} else {
|
|
|
|
|
data->lineNumber = textEditor->currentLine();
|
2011-02-23 10:16:11 +01:00
|
|
|
}
|
2012-01-17 16:22:05 +01:00
|
|
|
return true;
|
2011-02-23 10:16:11 +01:00
|
|
|
}
|
2011-02-03 14:08:01 +01:00
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
2011-02-03 14:08:01 +01:00
|
|
|
// DebuggerPluginPrivate
|
2010-06-16 11:08:54 +02:00
|
|
|
//
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2010-11-10 11:39:01 +01:00
|
|
|
static DebuggerPluginPrivate *theDebuggerCore = 0;
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2011-02-04 15:08:31 +01:00
|
|
|
/*!
|
|
|
|
|
\class Debugger::Internal::DebuggerCore
|
|
|
|
|
|
|
|
|
|
This is the "internal" interface of the debugger plugin that's
|
|
|
|
|
used by debugger views and debugger engines. The interface is
|
|
|
|
|
implemented in DebuggerPluginPrivate.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
\class Debugger::Internal::DebuggerPluginPrivate
|
|
|
|
|
|
|
|
|
|
Implementation of DebuggerCore.
|
|
|
|
|
*/
|
|
|
|
|
|
2010-11-10 11:39:01 +01:00
|
|
|
class DebuggerPluginPrivate : public DebuggerCore
|
2010-06-16 11:08:54 +02:00
|
|
|
{
|
|
|
|
|
Q_OBJECT
|
2010-03-19 13:58:26 +01:00
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
public:
|
|
|
|
|
explicit DebuggerPluginPrivate(DebuggerPlugin *plugin);
|
2010-11-10 11:39:01 +01:00
|
|
|
~DebuggerPluginPrivate();
|
2010-03-10 13:46:05 +01:00
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
bool initialize(const QStringList &arguments, QString *errorMessage);
|
2010-12-06 08:25:29 +01:00
|
|
|
void extensionsInitialized();
|
|
|
|
|
void aboutToShutdown();
|
|
|
|
|
|
2010-11-18 17:35:22 +01:00
|
|
|
void connectEngine(DebuggerEngine *engine);
|
2010-11-04 18:11:09 +01:00
|
|
|
void disconnectEngine() { connectEngine(0); }
|
2010-11-05 19:38:40 +01:00
|
|
|
DebuggerEngine *currentEngine() const { return m_currentEngine; }
|
2011-03-02 14:05:32 +01:00
|
|
|
DebuggerEngine *dummyEngine();
|
2010-02-09 20:44:40 +01:00
|
|
|
|
2011-09-01 16:36:27 +02:00
|
|
|
void setThreads(const QStringList &list, int index)
|
|
|
|
|
{
|
|
|
|
|
const bool state = m_threadBox->blockSignals(true);
|
|
|
|
|
m_threadBox->clear();
|
|
|
|
|
foreach (const QString &item, list)
|
|
|
|
|
m_threadBox->addItem(item);
|
|
|
|
|
m_threadBox->setCurrentIndex(index);
|
|
|
|
|
m_threadBox->blockSignals(state);
|
|
|
|
|
}
|
|
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
public slots:
|
2011-02-22 12:05:25 +01:00
|
|
|
void writeSettings()
|
|
|
|
|
{
|
|
|
|
|
m_debuggerSettings->writeSettings();
|
|
|
|
|
m_mainWindow->writeSettings();
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-08 15:50:13 +01:00
|
|
|
void selectThread(int index)
|
|
|
|
|
{
|
2012-10-19 16:37:57 +02:00
|
|
|
ThreadId id = m_currentEngine->threadsHandler()->threadAt(index);
|
|
|
|
|
m_currentEngine->selectThread(id);
|
2010-11-08 15:50:13 +01:00
|
|
|
}
|
2010-11-08 15:41:44 +01:00
|
|
|
|
2010-11-10 16:33:11 +01:00
|
|
|
void breakpointSetMarginActionTriggered()
|
2010-11-08 15:41:44 +01:00
|
|
|
{
|
2011-01-04 15:54:36 +01:00
|
|
|
const QAction *action = qobject_cast<const QAction *>(sender());
|
|
|
|
|
QTC_ASSERT(action, return);
|
2011-06-28 19:20:09 +02:00
|
|
|
const BreakpointMenuContextData data =
|
|
|
|
|
action->data().value<BreakpointMenuContextData>();
|
2011-06-27 10:37:57 +02:00
|
|
|
QString message;
|
|
|
|
|
if (data.mode == BreakpointMenuContextData::MessageTracePoint) {
|
|
|
|
|
if (data.address) {
|
|
|
|
|
//: Message tracepoint: Address hit.
|
|
|
|
|
message = tr("0x%1 hit").arg(data.address, 0, 16);
|
|
|
|
|
} else {
|
|
|
|
|
//: Message tracepoint: %1 file, %2 line %3 function hit.
|
|
|
|
|
message = tr("%1:%2 %3() hit").arg(QFileInfo(data.fileName).fileName()).
|
|
|
|
|
arg(data.lineNumber).
|
|
|
|
|
arg(cppFunctionAt(data.fileName, data.lineNumber));
|
|
|
|
|
}
|
|
|
|
|
QInputDialog dialog; // Create wide input dialog.
|
|
|
|
|
dialog.setWindowFlags(dialog.windowFlags()
|
2011-06-28 19:20:09 +02:00
|
|
|
& ~(Qt::WindowContextHelpButtonHint|Qt::MSWindowsFixedSizeDialogHint));
|
2011-06-27 10:37:57 +02:00
|
|
|
dialog.resize(600, dialog.height());
|
|
|
|
|
dialog.setWindowTitle(tr("Add Message Tracepoint"));
|
|
|
|
|
dialog.setLabelText (tr("Message:"));
|
|
|
|
|
dialog.setTextValue(message);
|
|
|
|
|
if (dialog.exec() != QDialog::Accepted || dialog.textValue().isEmpty())
|
|
|
|
|
return;
|
|
|
|
|
message = dialog.textValue();
|
|
|
|
|
}
|
2011-01-04 15:54:36 +01:00
|
|
|
if (data.address)
|
2011-06-27 10:37:57 +02:00
|
|
|
toggleBreakpointByAddress(data.address, message);
|
2011-01-04 15:54:36 +01:00
|
|
|
else
|
2011-06-27 10:37:57 +02:00
|
|
|
toggleBreakpointByFileAndLine(data.fileName, data.lineNumber, message);
|
2010-11-24 11:44:43 +01:00
|
|
|
}
|
2010-11-08 15:41:44 +01:00
|
|
|
|
2010-11-10 16:33:11 +01:00
|
|
|
void breakpointRemoveMarginActionTriggered()
|
2010-11-08 15:41:44 +01:00
|
|
|
{
|
2010-11-10 16:33:11 +01:00
|
|
|
const QAction *act = qobject_cast<QAction *>(sender());
|
|
|
|
|
QTC_ASSERT(act, return);
|
2011-06-24 16:25:30 +02:00
|
|
|
BreakpointModelId id = act->data().value<BreakpointModelId>();
|
2011-06-15 14:02:26 +02:00
|
|
|
m_breakHandler->removeBreakpoint(id);
|
2010-11-10 16:33:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void breakpointEnableMarginActionTriggered()
|
|
|
|
|
{
|
|
|
|
|
const QAction *act = qobject_cast<QAction *>(sender());
|
|
|
|
|
QTC_ASSERT(act, return);
|
2011-06-24 16:25:30 +02:00
|
|
|
BreakpointModelId id = act->data().value<BreakpointModelId>();
|
2011-06-15 14:02:26 +02:00
|
|
|
breakHandler()->setEnabled(id, true);
|
2010-11-10 16:33:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void breakpointDisableMarginActionTriggered()
|
|
|
|
|
{
|
|
|
|
|
const QAction *act = qobject_cast<QAction *>(sender());
|
|
|
|
|
QTC_ASSERT(act, return);
|
2011-06-24 16:25:30 +02:00
|
|
|
BreakpointModelId id = act->data().value<BreakpointModelId>();;
|
2011-06-15 14:02:26 +02:00
|
|
|
breakHandler()->setEnabled(id, false);
|
2010-11-08 15:41:44 +01:00
|
|
|
}
|
|
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
void updateWatchersHeader(int section, int, int newSize)
|
2010-11-05 19:38:40 +01:00
|
|
|
{
|
|
|
|
|
m_watchersWindow->header()->resizeSection(section, newSize);
|
2011-11-11 17:17:26 +01:00
|
|
|
m_returnWindow->header()->resizeSection(section, newSize);
|
2010-11-05 19:38:40 +01:00
|
|
|
}
|
2010-02-09 20:44:40 +01:00
|
|
|
|
2011-12-08 16:31:21 +01:00
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
void sourceFilesDockToggled(bool on)
|
2010-11-05 19:38:40 +01:00
|
|
|
{
|
2010-11-15 12:06:38 +01:00
|
|
|
if (on && m_currentEngine->state() == InferiorStopOk)
|
2010-11-05 19:38:40 +01:00
|
|
|
m_currentEngine->reloadSourceFiles();
|
|
|
|
|
}
|
|
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
void modulesDockToggled(bool on)
|
2010-11-05 19:38:40 +01:00
|
|
|
{
|
2010-11-15 12:06:38 +01:00
|
|
|
if (on && m_currentEngine->state() == InferiorStopOk)
|
2010-11-05 19:38:40 +01:00
|
|
|
m_currentEngine->reloadModules();
|
|
|
|
|
}
|
2010-11-05 13:35:31 +01:00
|
|
|
|
2010-06-22 12:02:24 +02:00
|
|
|
void registerDockToggled(bool on)
|
2010-11-05 13:35:31 +01:00
|
|
|
{
|
2010-11-15 12:06:38 +01:00
|
|
|
if (on && m_currentEngine->state() == InferiorStopOk)
|
2010-11-05 13:35:31 +01:00
|
|
|
m_currentEngine->reloadRegisters();
|
|
|
|
|
}
|
2009-05-05 17:48:54 +02:00
|
|
|
|
2010-11-04 09:54:23 +01:00
|
|
|
void synchronizeBreakpoints()
|
|
|
|
|
{
|
2011-12-21 14:02:52 +01:00
|
|
|
showMessage(QLatin1String("ATTEMPT SYNC"), LogDebug);
|
2010-11-04 09:54:23 +01:00
|
|
|
for (int i = 0, n = m_snapshotHandler->size(); i != n; ++i) {
|
2010-12-10 10:01:29 +01:00
|
|
|
if (DebuggerEngine *engine = m_snapshotHandler->at(i))
|
2010-11-04 09:54:23 +01:00
|
|
|
engine->attemptBreakpointSynchronization();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-04 18:11:09 +01:00
|
|
|
void synchronizeWatchers()
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0, n = m_snapshotHandler->size(); i != n; ++i) {
|
2010-12-10 10:01:29 +01:00
|
|
|
if (DebuggerEngine *engine = m_snapshotHandler->at(i))
|
2010-11-25 16:32:07 +01:00
|
|
|
engine->watchHandler()->updateWatchers();
|
2010-11-04 18:11:09 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
void editorOpened(Core::IEditor *editor);
|
2011-02-04 14:36:50 +01:00
|
|
|
void updateBreakMenuItem(Core::IEditor *editor);
|
2010-06-16 11:08:54 +02:00
|
|
|
void setBusyCursor(bool busy);
|
2011-11-29 13:51:00 +01:00
|
|
|
void requestMark(TextEditor::ITextEditor *editor,
|
|
|
|
|
int lineNumber,
|
|
|
|
|
TextEditor::ITextEditor::MarkRequestKind kind);
|
2010-06-16 11:08:54 +02:00
|
|
|
void requestContextMenu(TextEditor::ITextEditor *editor,
|
|
|
|
|
int lineNumber, QMenu *menu);
|
2009-05-07 15:20:44 +02:00
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
void activatePreviousMode();
|
|
|
|
|
void activateDebugMode();
|
|
|
|
|
void toggleBreakpoint();
|
2011-06-27 10:37:57 +02:00
|
|
|
void toggleBreakpointByFileAndLine(const QString &fileName, int lineNumber,
|
|
|
|
|
const QString &tracePointMessage = QString());
|
|
|
|
|
void toggleBreakpointByAddress(quint64 address,
|
|
|
|
|
const QString &tracePointMessage = QString());
|
2010-06-16 11:08:54 +02:00
|
|
|
void onModeChanged(Core::IMode *mode);
|
2011-01-31 15:17:53 +01:00
|
|
|
void onCoreAboutToOpen();
|
2010-06-16 11:08:54 +02:00
|
|
|
void showSettingsDialog();
|
2011-10-25 18:23:37 +08:00
|
|
|
void updateDebugWithoutDeployMenu();
|
2010-02-09 20:44:40 +01:00
|
|
|
|
2010-11-12 20:18:29 +01:00
|
|
|
void debugProject();
|
2011-10-25 18:23:37 +08:00
|
|
|
void debugProjectWithoutDeploy();
|
2011-05-02 18:22:32 +02:00
|
|
|
void debugProjectBreakMain();
|
2012-08-08 13:09:31 +02:00
|
|
|
void startAndDebugApplication();
|
2010-11-19 16:13:22 +01:00
|
|
|
void startRemoteCdbSession();
|
2011-12-06 15:39:25 +01:00
|
|
|
void startRemoteServer();
|
2011-12-05 17:21:48 +01:00
|
|
|
void attachToRemoteServer();
|
2012-08-08 12:03:07 +02:00
|
|
|
void attachToProcess(bool startServerOnly);
|
2012-08-06 12:22:35 +02:00
|
|
|
void attachToRunningApplication();
|
2012-08-30 10:26:09 +02:00
|
|
|
void attachExternalApplication(ProjectExplorer::RunControl *rc);
|
2011-09-13 17:26:02 +02:00
|
|
|
void attachToQmlPort();
|
2010-12-01 15:41:08 +01:00
|
|
|
void startRemoteEngine();
|
2011-02-08 13:48:04 +01:00
|
|
|
void runScheduled();
|
2010-06-16 11:08:54 +02:00
|
|
|
void attachCore();
|
2009-06-08 19:28:28 +02:00
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
void enableReverseDebuggingTriggered(const QVariant &value);
|
2010-12-06 11:06:18 +01:00
|
|
|
void languagesChanged();
|
2010-06-22 17:46:20 +02:00
|
|
|
void showStatusMessage(const QString &msg, int timeout = -1);
|
2010-09-09 17:58:26 +02:00
|
|
|
void openMemoryEditor();
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2010-11-10 11:39:01 +01:00
|
|
|
const CPlusPlus::Snapshot &cppCodeModelSnapshot() const;
|
|
|
|
|
|
2010-12-03 14:29:19 +01:00
|
|
|
DebuggerMainWindow *mainWindow() const { return m_mainWindow; }
|
2010-12-03 15:03:51 +01:00
|
|
|
bool isDockVisible(const QString &objectName) const
|
2010-12-03 15:23:23 +01:00
|
|
|
{ return mainWindow()->isDockVisible(objectName); }
|
2010-11-10 11:39:01 +01:00
|
|
|
|
|
|
|
|
bool hasSnapshots() const { return m_snapshotHandler->size(); }
|
2010-12-03 15:55:17 +01:00
|
|
|
void createNewDock(QWidget *widget);
|
2010-11-10 11:39:01 +01:00
|
|
|
|
2010-12-10 10:01:29 +01:00
|
|
|
void runControlStarted(DebuggerEngine *engine);
|
|
|
|
|
void runControlFinished(DebuggerEngine *engine);
|
2010-11-10 11:39:01 +01:00
|
|
|
DebuggerLanguages activeLanguages() const;
|
|
|
|
|
void remoteCommand(const QStringList &options, const QStringList &);
|
|
|
|
|
|
|
|
|
|
bool isReverseDebugging() const;
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2010-11-10 11:39:01 +01:00
|
|
|
BreakHandler *breakHandler() const { return m_breakHandler; }
|
|
|
|
|
SnapshotHandler *snapshotHandler() const { return m_snapshotHandler; }
|
|
|
|
|
|
|
|
|
|
void setConfigValue(const QString &name, const QVariant &value);
|
|
|
|
|
QVariant configValue(const QString &name) const;
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2010-08-18 13:54:12 +02:00
|
|
|
void displayDebugger(DebuggerEngine *engine, bool updateEngine = true);
|
2010-06-16 11:08:54 +02:00
|
|
|
|
|
|
|
|
void dumpLog();
|
|
|
|
|
void cleanupViews();
|
2010-07-05 17:08:30 +02:00
|
|
|
void setInitialState();
|
2010-06-16 11:08:54 +02:00
|
|
|
|
|
|
|
|
void fontSettingsChanged(const TextEditor::FontSettings &settings);
|
|
|
|
|
|
|
|
|
|
void updateState(DebuggerEngine *engine);
|
2012-05-18 02:28:41 +02:00
|
|
|
void updateWatchersWindow(bool showWatch, bool showReturn);
|
2010-07-21 17:06:22 +02:00
|
|
|
void onCurrentProjectChanged(ProjectExplorer::Project *project);
|
2010-06-16 11:08:54 +02:00
|
|
|
|
|
|
|
|
void sessionLoaded();
|
|
|
|
|
void aboutToUnloadSession();
|
|
|
|
|
void aboutToSaveSession();
|
2010-06-22 12:41:02 +02:00
|
|
|
|
2012-04-10 09:36:15 +02:00
|
|
|
void executeDebuggerCommand(const QString &command, DebuggerLanguages languages);
|
2010-10-22 12:26:13 +02:00
|
|
|
void coreShutdown();
|
2010-08-26 16:02:41 +02:00
|
|
|
|
2012-01-23 16:45:00 +01:00
|
|
|
#ifdef WITH_TESTS
|
|
|
|
|
public slots:
|
2012-01-25 17:28:06 +01:00
|
|
|
void testLoadProject(const QString &proFile, const TestCallBack &cb);
|
2012-01-23 16:45:00 +01:00
|
|
|
void testProjectLoaded(ProjectExplorer::Project *project);
|
2012-01-25 17:28:06 +01:00
|
|
|
void testUnloadProject();
|
|
|
|
|
void testFinished();
|
|
|
|
|
|
|
|
|
|
void testRunProject(const DebuggerStartParameters &sp, const TestCallBack &cb);
|
2012-01-23 16:45:00 +01:00
|
|
|
void testRunControlFinished();
|
2012-01-25 17:28:06 +01:00
|
|
|
|
|
|
|
|
void testPythonDumpers1();
|
|
|
|
|
void testPythonDumpers2();
|
|
|
|
|
void testPythonDumpers3();
|
|
|
|
|
|
|
|
|
|
void testStateMachine1();
|
|
|
|
|
void testStateMachine2();
|
|
|
|
|
void testStateMachine3();
|
|
|
|
|
|
2012-01-26 13:14:00 +01:00
|
|
|
void testBenchmark1();
|
|
|
|
|
|
2012-01-25 17:28:06 +01:00
|
|
|
public:
|
|
|
|
|
bool m_testSuccess;
|
|
|
|
|
QList<TestCallBack> m_testCallbacks;
|
|
|
|
|
|
2012-01-23 16:45:00 +01:00
|
|
|
#endif
|
|
|
|
|
|
2010-11-08 15:19:13 +01:00
|
|
|
public slots:
|
2010-11-12 20:18:29 +01:00
|
|
|
void updateDebugActions();
|
2010-11-23 16:42:46 +01:00
|
|
|
|
|
|
|
|
void handleExecDetach()
|
|
|
|
|
{
|
2010-12-14 12:21:29 +01:00
|
|
|
currentEngine()->resetLocation();
|
2010-11-23 16:42:46 +01:00
|
|
|
currentEngine()->detachDebugger();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void handleExecContinue()
|
|
|
|
|
{
|
2010-12-14 12:21:29 +01:00
|
|
|
currentEngine()->resetLocation();
|
2010-11-23 16:42:46 +01:00
|
|
|
currentEngine()->continueInferior();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void handleExecInterrupt()
|
|
|
|
|
{
|
2010-12-14 12:21:29 +01:00
|
|
|
currentEngine()->resetLocation();
|
2010-11-23 16:42:46 +01:00
|
|
|
currentEngine()->requestInterruptInferior();
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-31 16:15:48 +01:00
|
|
|
void handleAbort()
|
2010-11-23 16:42:46 +01:00
|
|
|
{
|
2010-12-14 12:21:29 +01:00
|
|
|
currentEngine()->resetLocation();
|
2011-10-31 16:15:48 +01:00
|
|
|
currentEngine()->abortDebugger();
|
2010-11-23 16:42:46 +01:00
|
|
|
}
|
2010-11-08 15:19:13 +01:00
|
|
|
|
|
|
|
|
void handleExecStep()
|
|
|
|
|
{
|
2011-05-02 18:22:32 +02:00
|
|
|
if (currentEngine()->state() == DebuggerNotReady) {
|
|
|
|
|
debugProjectBreakMain();
|
|
|
|
|
} else {
|
|
|
|
|
currentEngine()->resetLocation();
|
|
|
|
|
if (boolSetting(OperateByInstruction))
|
|
|
|
|
currentEngine()->executeStepI();
|
|
|
|
|
else
|
|
|
|
|
currentEngine()->executeStep();
|
|
|
|
|
}
|
2010-11-08 15:19:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void handleExecNext()
|
|
|
|
|
{
|
2011-05-02 18:22:32 +02:00
|
|
|
if (currentEngine()->state() == DebuggerNotReady) {
|
|
|
|
|
debugProjectBreakMain();
|
|
|
|
|
} else {
|
|
|
|
|
currentEngine()->resetLocation();
|
|
|
|
|
if (boolSetting(OperateByInstruction))
|
|
|
|
|
currentEngine()->executeNextI();
|
|
|
|
|
else
|
|
|
|
|
currentEngine()->executeNext();
|
|
|
|
|
}
|
2010-11-08 15:19:13 +01:00
|
|
|
}
|
|
|
|
|
|
2010-11-08 15:41:44 +01:00
|
|
|
void handleExecStepOut()
|
|
|
|
|
{
|
2010-12-14 12:21:29 +01:00
|
|
|
currentEngine()->resetLocation();
|
2010-11-08 15:41:44 +01:00
|
|
|
currentEngine()->executeStepOut();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void handleExecReturn()
|
|
|
|
|
{
|
2010-12-14 12:21:29 +01:00
|
|
|
currentEngine()->resetLocation();
|
2010-11-08 15:41:44 +01:00
|
|
|
currentEngine()->executeReturn();
|
|
|
|
|
}
|
2010-11-08 15:19:13 +01:00
|
|
|
|
|
|
|
|
void handleExecJumpToLine()
|
|
|
|
|
{
|
|
|
|
|
//removeTooltip();
|
2010-12-14 12:21:29 +01:00
|
|
|
currentEngine()->resetLocation();
|
2011-02-23 10:16:11 +01:00
|
|
|
ContextData data;
|
|
|
|
|
if (currentTextEditorPosition(&data))
|
|
|
|
|
currentEngine()->executeJumpToLine(data);
|
2010-11-08 15:19:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void handleExecRunToLine()
|
|
|
|
|
{
|
|
|
|
|
//removeTooltip();
|
2010-12-14 12:21:29 +01:00
|
|
|
currentEngine()->resetLocation();
|
2011-02-23 10:16:11 +01:00
|
|
|
ContextData data;
|
|
|
|
|
if (currentTextEditorPosition(&data))
|
|
|
|
|
currentEngine()->executeRunToLine(data);
|
2010-11-08 15:19:13 +01:00
|
|
|
}
|
|
|
|
|
|
2011-02-02 11:52:39 +01:00
|
|
|
void handleExecRunToSelectedFunction()
|
2010-11-08 15:19:13 +01:00
|
|
|
{
|
2010-11-08 16:17:59 +01:00
|
|
|
ITextEditor *textEditor = currentTextEditor();
|
|
|
|
|
QTC_ASSERT(textEditor, return);
|
|
|
|
|
QPlainTextEdit *ed = qobject_cast<QPlainTextEdit*>(textEditor->widget());
|
|
|
|
|
if (!ed)
|
|
|
|
|
return;
|
|
|
|
|
QTextCursor cursor = ed->textCursor();
|
|
|
|
|
QString functionName = cursor.selectedText();
|
|
|
|
|
if (functionName.isEmpty()) {
|
|
|
|
|
const QTextBlock block = cursor.block();
|
|
|
|
|
const QString line = block.text();
|
2011-12-21 14:02:52 +01:00
|
|
|
foreach (const QString &str, line.trimmed().split(QLatin1Char('('))) {
|
2010-11-08 16:17:59 +01:00
|
|
|
QString a;
|
|
|
|
|
for (int i = str.size(); --i >= 0; ) {
|
|
|
|
|
if (!str.at(i).isLetterOrNumber())
|
|
|
|
|
break;
|
|
|
|
|
a = str.at(i) + a;
|
|
|
|
|
}
|
|
|
|
|
if (!a.isEmpty()) {
|
|
|
|
|
functionName = a;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-02 11:52:39 +01:00
|
|
|
if (functionName.isEmpty()) {
|
|
|
|
|
showStatusMessage(tr("No function selected."));
|
|
|
|
|
} else {
|
|
|
|
|
showStatusMessage(tr("Running to function \"%1\".")
|
|
|
|
|
.arg(functionName));
|
|
|
|
|
currentEngine()->resetLocation();
|
2010-11-08 16:17:59 +01:00
|
|
|
currentEngine()->executeRunToFunction(functionName);
|
2011-02-02 11:52:39 +01:00
|
|
|
}
|
2010-11-08 15:19:13 +01:00
|
|
|
}
|
|
|
|
|
|
2010-11-08 15:41:44 +01:00
|
|
|
void slotEditBreakpoint()
|
|
|
|
|
{
|
|
|
|
|
const QAction *act = qobject_cast<QAction *>(sender());
|
|
|
|
|
QTC_ASSERT(act, return);
|
2011-06-24 16:25:30 +02:00
|
|
|
const BreakpointModelId id = act->data().value<BreakpointModelId>();
|
2010-11-10 16:33:11 +01:00
|
|
|
QTC_ASSERT(id > 0, return);
|
2012-03-29 14:20:45 +02:00
|
|
|
BreakTreeView::editBreakpoint(id, mainWindow());
|
2010-11-08 15:41:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void slotRunToLine()
|
|
|
|
|
{
|
2011-01-04 15:54:36 +01:00
|
|
|
const QAction *action = qobject_cast<const QAction *>(sender());
|
|
|
|
|
QTC_ASSERT(action, return);
|
2011-08-15 16:52:08 +02:00
|
|
|
const BreakpointMenuContextData data = action->data().value<BreakpointMenuContextData>();
|
2011-02-23 10:16:11 +01:00
|
|
|
currentEngine()->executeRunToLine(data);
|
2010-11-08 15:41:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void slotJumpToLine()
|
|
|
|
|
{
|
2011-01-04 15:54:36 +01:00
|
|
|
const QAction *action = qobject_cast<const QAction *>(sender());
|
|
|
|
|
QTC_ASSERT(action, return);
|
2011-08-15 16:52:08 +02:00
|
|
|
const BreakpointMenuContextData data = action->data().value<BreakpointMenuContextData>();
|
2011-02-23 10:16:11 +01:00
|
|
|
currentEngine()->executeJumpToLine(data);
|
2010-11-08 15:41:44 +01:00
|
|
|
}
|
|
|
|
|
|
2012-02-01 17:44:07 +01:00
|
|
|
void slotDisassembleFunction()
|
|
|
|
|
{
|
|
|
|
|
const QAction *action = qobject_cast<const QAction *>(sender());
|
|
|
|
|
QTC_ASSERT(action, return);
|
|
|
|
|
const StackFrame frame = action->data().value<StackFrame>();
|
|
|
|
|
QTC_ASSERT(!frame.function.isEmpty(), return);
|
|
|
|
|
currentEngine()->openDisassemblerView(Location(frame));
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-08 15:19:13 +01:00
|
|
|
void handleAddToWatchWindow()
|
|
|
|
|
{
|
|
|
|
|
// Requires a selection, but that's the only case we want anyway.
|
2012-05-08 09:43:14 +02:00
|
|
|
IEditor *editor = EditorManager::currentEditor();
|
2010-11-08 15:19:13 +01:00
|
|
|
if (!editor)
|
|
|
|
|
return;
|
|
|
|
|
ITextEditor *textEditor = qobject_cast<ITextEditor*>(editor);
|
|
|
|
|
if (!textEditor)
|
|
|
|
|
return;
|
|
|
|
|
QTextCursor tc;
|
|
|
|
|
QPlainTextEdit *ptEdit = qobject_cast<QPlainTextEdit*>(editor->widget());
|
|
|
|
|
if (ptEdit)
|
|
|
|
|
tc = ptEdit->textCursor();
|
|
|
|
|
QString exp;
|
|
|
|
|
if (tc.hasSelection()) {
|
|
|
|
|
exp = tc.selectedText();
|
|
|
|
|
} else {
|
|
|
|
|
int line, column;
|
|
|
|
|
exp = cppExpressionAt(textEditor, tc.position(), &line, &column);
|
|
|
|
|
}
|
2012-08-30 18:03:34 +02:00
|
|
|
exp = fixCppExpression(exp);
|
2010-11-08 15:19:13 +01:00
|
|
|
if (exp.isEmpty())
|
|
|
|
|
return;
|
2012-10-29 12:59:53 +01:00
|
|
|
currentEngine()->watchHandler()->watchVariable(exp);
|
2010-11-08 15:19:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void handleExecExit()
|
|
|
|
|
{
|
2010-11-08 17:43:31 +01:00
|
|
|
currentEngine()->exitDebugger();
|
2010-11-08 15:19:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void handleFrameDown()
|
|
|
|
|
{
|
|
|
|
|
currentEngine()->frameDown();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void handleFrameUp()
|
|
|
|
|
{
|
|
|
|
|
currentEngine()->frameUp();
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-22 12:21:56 +01:00
|
|
|
void handleOperateByInstructionTriggered(bool operateByInstructionTriggered)
|
2010-11-08 15:19:13 +01:00
|
|
|
{
|
2010-11-22 12:21:56 +01:00
|
|
|
// Go to source only if we have the file.
|
|
|
|
|
if (currentEngine()->stackHandler()->currentIndex() >= 0) {
|
|
|
|
|
const StackFrame frame = currentEngine()->stackHandler()->currentFrame();
|
2010-12-16 19:06:33 +01:00
|
|
|
if (operateByInstructionTriggered || frame.isUsable()) {
|
|
|
|
|
currentEngine()->gotoLocation(Location(frame, true));
|
|
|
|
|
}
|
2010-11-22 12:21:56 +01:00
|
|
|
}
|
2010-11-08 15:19:13 +01:00
|
|
|
}
|
|
|
|
|
|
2010-11-10 11:39:01 +01:00
|
|
|
bool isActiveDebugLanguage(int lang) const
|
2010-11-08 15:19:13 +01:00
|
|
|
{
|
2010-12-02 17:33:39 +01:00
|
|
|
return m_mainWindow->activeDebugLanguages() & lang;
|
2010-11-08 15:19:13 +01:00
|
|
|
}
|
|
|
|
|
|
2010-11-10 11:39:01 +01:00
|
|
|
QVariant sessionValue(const QString &name);
|
|
|
|
|
void setSessionValue(const QString &name, const QVariant &value);
|
|
|
|
|
QIcon locationMarkIcon() const { return m_locationMarkIcon; }
|
|
|
|
|
|
|
|
|
|
void openTextEditor(const QString &titlePattern0, const QString &contents);
|
|
|
|
|
void showMessage(const QString &msg, int channel, int timeout = -1);
|
|
|
|
|
|
2012-08-15 16:19:15 +02:00
|
|
|
SavedAction *action(int code) const;
|
2010-11-10 16:33:11 +01:00
|
|
|
bool boolSetting(int code) const;
|
|
|
|
|
QString stringSetting(int code) const;
|
|
|
|
|
|
2010-11-26 09:58:34 +01:00
|
|
|
void showModuleSymbols(const QString &moduleName, const Symbols &symbols);
|
|
|
|
|
|
2011-02-08 13:48:04 +01:00
|
|
|
bool parseArgument(QStringList::const_iterator &it,
|
2012-08-09 01:50:26 +02:00
|
|
|
const QStringList::const_iterator &cend, QString *errorMessage);
|
|
|
|
|
bool parseArguments(const QStringList &args, QString *errorMessage);
|
2011-02-08 13:48:04 +01:00
|
|
|
|
2011-02-11 15:00:13 +01:00
|
|
|
DebuggerToolTipManager *toolTipManager() const { return m_toolTipManager; }
|
2012-07-27 00:17:12 +02:00
|
|
|
QSharedPointer<GlobalDebuggerOptions> globalDebuggerOptions() const { return m_globalDebuggerOptions; }
|
2011-02-11 15:00:13 +01:00
|
|
|
|
2012-04-18 14:20:54 +02:00
|
|
|
void updateQmlActions() {
|
|
|
|
|
action(QmlUpdateOnSave)->setEnabled(boolSetting(ShowQmlObjectTree));
|
|
|
|
|
}
|
|
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
public:
|
2010-12-02 17:33:39 +01:00
|
|
|
DebuggerMainWindow *m_mainWindow;
|
2010-06-16 11:08:54 +02:00
|
|
|
DebuggerRunControlFactory *m_debuggerRunControlFactory;
|
|
|
|
|
|
2012-05-07 18:28:03 +02:00
|
|
|
Id m_previousMode;
|
2011-02-08 13:48:04 +01:00
|
|
|
QList<DebuggerStartParameters> m_scheduledStarts;
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2012-08-15 16:19:15 +02:00
|
|
|
ProxyAction *m_visibleStartAction;
|
|
|
|
|
ProxyAction *m_hiddenStopAction;
|
2011-08-03 18:57:37 +02:00
|
|
|
QAction *m_startAction;
|
2011-10-25 18:23:37 +08:00
|
|
|
QAction *m_debugWithoutDeployAction;
|
2012-08-08 13:09:31 +02:00
|
|
|
QAction *m_startAndDebugApplicationAction;
|
2011-12-06 15:39:25 +01:00
|
|
|
QAction *m_startRemoteServerAction;
|
2012-08-06 12:22:35 +02:00
|
|
|
QAction *m_attachToRunningApplication;
|
2011-09-13 17:26:02 +02:00
|
|
|
QAction *m_attachToQmlPortAction;
|
2011-12-05 17:21:48 +01:00
|
|
|
QAction *m_attachToRemoteServerAction;
|
2010-11-19 16:13:22 +01:00
|
|
|
QAction *m_startRemoteCdbAction;
|
2011-12-05 17:21:48 +01:00
|
|
|
QAction *m_attachToCoreAction;
|
2010-06-16 11:08:54 +02:00
|
|
|
QAction *m_detachAction;
|
2011-02-03 14:08:01 +01:00
|
|
|
QAction *m_continueAction;
|
|
|
|
|
QAction *m_exitAction; // On application output button if "Stop" is possible
|
|
|
|
|
QAction *m_interruptAction; // On the fat debug button if "Pause" is possible
|
|
|
|
|
QAction *m_undisturbableAction; // On the fat debug button if nothing can be done
|
2011-10-31 16:15:48 +01:00
|
|
|
QAction *m_abortAction;
|
2011-02-03 14:08:01 +01:00
|
|
|
QAction *m_stepAction;
|
|
|
|
|
QAction *m_stepOutAction;
|
|
|
|
|
QAction *m_runToLineAction; // In the debug menu
|
|
|
|
|
QAction *m_runToSelectedFunctionAction;
|
|
|
|
|
QAction *m_jumpToLineAction; // In the Debug menu.
|
|
|
|
|
QAction *m_returnFromFunctionAction;
|
|
|
|
|
QAction *m_nextAction;
|
|
|
|
|
QAction *m_watchAction1; // In the Debug menu.
|
|
|
|
|
QAction *m_watchAction2; // In the text editor context menu.
|
|
|
|
|
QAction *m_breakAction;
|
|
|
|
|
QAction *m_reverseDirectionAction;
|
|
|
|
|
QAction *m_frameUpAction;
|
|
|
|
|
QAction *m_frameDownAction;
|
|
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
QToolButton *m_reverseToolButton;
|
|
|
|
|
|
2010-10-05 12:47:23 +02:00
|
|
|
QIcon m_startIcon;
|
2010-11-08 17:43:31 +01:00
|
|
|
QIcon m_exitIcon;
|
2010-10-05 12:47:23 +02:00
|
|
|
QIcon m_continueIcon;
|
2010-06-16 11:08:54 +02:00
|
|
|
QIcon m_interruptIcon;
|
|
|
|
|
QIcon m_locationMarkIcon;
|
|
|
|
|
|
2012-08-15 16:19:15 +02:00
|
|
|
StatusLabel *m_statusLabel;
|
2010-06-16 11:08:54 +02:00
|
|
|
QComboBox *m_threadBox;
|
|
|
|
|
|
2012-03-29 14:20:45 +02:00
|
|
|
BaseWindow *m_breakWindow;
|
2010-11-04 09:54:23 +01:00
|
|
|
BreakHandler *m_breakHandler;
|
2012-03-29 14:20:45 +02:00
|
|
|
WatchWindow *m_returnWindow;
|
|
|
|
|
WatchWindow *m_localsWindow;
|
|
|
|
|
WatchWindow *m_watchersWindow;
|
2012-04-18 14:20:54 +02:00
|
|
|
WatchWindow *m_inspectorWindow;
|
2012-03-22 11:54:49 +01:00
|
|
|
BaseWindow *m_registerWindow;
|
|
|
|
|
BaseWindow *m_modulesWindow;
|
|
|
|
|
BaseWindow *m_snapshotWindow;
|
2012-03-29 14:20:45 +02:00
|
|
|
BaseWindow *m_sourceFilesWindow;
|
2012-03-22 11:54:49 +01:00
|
|
|
BaseWindow *m_stackWindow;
|
|
|
|
|
BaseWindow *m_threadsWindow;
|
2010-09-22 16:20:08 +02:00
|
|
|
LogWindow *m_logWindow;
|
2012-05-14 16:09:12 +02:00
|
|
|
LocalsAndExpressionsWindow *m_localsAndExpressionsWindow;
|
2010-06-16 11:08:54 +02:00
|
|
|
|
|
|
|
|
bool m_busy;
|
|
|
|
|
QString m_lastPermanentStatusMessage;
|
|
|
|
|
|
2010-11-10 11:39:01 +01:00
|
|
|
mutable CPlusPlus::Snapshot m_codeModelSnapshot;
|
2010-06-16 11:08:54 +02:00
|
|
|
DebuggerPlugin *m_plugin;
|
|
|
|
|
|
2010-07-20 17:36:20 +02:00
|
|
|
SnapshotHandler *m_snapshotHandler;
|
2010-10-22 12:26:13 +02:00
|
|
|
bool m_shuttingDown;
|
2010-11-04 18:11:09 +01:00
|
|
|
DebuggerEngine *m_currentEngine;
|
2010-11-10 16:33:11 +01:00
|
|
|
DebuggerSettings *m_debuggerSettings;
|
|
|
|
|
QSettings *m_coreSettings;
|
2011-02-22 11:21:08 +01:00
|
|
|
QStringList m_arguments;
|
2011-02-11 15:00:13 +01:00
|
|
|
DebuggerToolTipManager *m_toolTipManager;
|
2011-02-22 12:58:32 +01:00
|
|
|
CommonOptionsPage *m_commonOptionsPage;
|
2011-03-02 14:05:32 +01:00
|
|
|
DummyEngine *m_dummyEngine;
|
2011-03-04 16:21:57 +01:00
|
|
|
const QSharedPointer<GlobalDebuggerOptions> m_globalDebuggerOptions;
|
2010-06-16 11:08:54 +02:00
|
|
|
};
|
|
|
|
|
|
2011-02-11 15:00:13 +01:00
|
|
|
DebuggerPluginPrivate::DebuggerPluginPrivate(DebuggerPlugin *plugin) :
|
2011-03-02 14:05:32 +01:00
|
|
|
m_toolTipManager(new DebuggerToolTipManager(this)),
|
2011-03-04 16:21:57 +01:00
|
|
|
m_dummyEngine(0),
|
|
|
|
|
m_globalDebuggerOptions(new GlobalDebuggerOptions)
|
2010-06-16 11:08:54 +02:00
|
|
|
{
|
2011-12-21 14:02:52 +01:00
|
|
|
setObjectName(QLatin1String("DebuggerCore"));
|
2011-01-04 15:54:36 +01:00
|
|
|
qRegisterMetaType<WatchData>("WatchData");
|
|
|
|
|
qRegisterMetaType<ContextData>("ContextData");
|
2011-01-07 09:44:23 +01:00
|
|
|
qRegisterMetaType<DebuggerStartParameters>("DebuggerStartParameters");
|
2011-01-04 15:54:36 +01:00
|
|
|
|
2011-07-29 12:00:11 +02:00
|
|
|
QTC_CHECK(!theDebuggerCore);
|
2010-11-10 11:39:01 +01:00
|
|
|
theDebuggerCore = this;
|
|
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
m_plugin = plugin;
|
|
|
|
|
|
2010-11-23 16:42:46 +01:00
|
|
|
m_startRemoteCdbAction = 0;
|
2010-11-04 18:11:09 +01:00
|
|
|
m_shuttingDown = false;
|
2010-06-16 11:08:54 +02:00
|
|
|
m_statusLabel = 0;
|
|
|
|
|
m_threadBox = 0;
|
|
|
|
|
|
|
|
|
|
m_breakWindow = 0;
|
2010-11-04 09:54:23 +01:00
|
|
|
m_breakHandler = 0;
|
2010-06-16 11:08:54 +02:00
|
|
|
m_returnWindow = 0;
|
|
|
|
|
m_localsWindow = 0;
|
|
|
|
|
m_watchersWindow = 0;
|
2012-04-18 14:20:54 +02:00
|
|
|
m_inspectorWindow = 0;
|
2010-06-16 11:08:54 +02:00
|
|
|
m_registerWindow = 0;
|
|
|
|
|
m_modulesWindow = 0;
|
|
|
|
|
m_snapshotWindow = 0;
|
|
|
|
|
m_sourceFilesWindow = 0;
|
|
|
|
|
m_stackWindow = 0;
|
|
|
|
|
m_threadsWindow = 0;
|
2010-09-22 16:20:08 +02:00
|
|
|
m_logWindow = 0;
|
2012-05-14 16:09:12 +02:00
|
|
|
m_localsAndExpressionsWindow = 0;
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2010-12-02 17:33:39 +01:00
|
|
|
m_mainWindow = 0;
|
2010-07-20 17:36:20 +02:00
|
|
|
m_snapshotHandler = 0;
|
2010-11-04 18:11:09 +01:00
|
|
|
m_currentEngine = 0;
|
2010-11-10 16:33:11 +01:00
|
|
|
m_debuggerSettings = 0;
|
|
|
|
|
|
2010-12-06 08:04:43 +01:00
|
|
|
m_reverseToolButton = 0;
|
2011-08-03 18:57:37 +02:00
|
|
|
m_startAction = 0;
|
2011-10-25 18:23:37 +08:00
|
|
|
m_debugWithoutDeployAction = 0;
|
2012-08-08 13:09:31 +02:00
|
|
|
m_startAndDebugApplicationAction = 0;
|
2011-12-05 17:21:48 +01:00
|
|
|
m_attachToRemoteServerAction = 0;
|
2012-08-06 12:22:35 +02:00
|
|
|
m_attachToRunningApplication = 0;
|
2011-09-13 17:26:02 +02:00
|
|
|
m_attachToQmlPortAction = 0;
|
2010-12-06 08:04:43 +01:00
|
|
|
m_startRemoteCdbAction = 0;
|
2011-12-05 17:21:48 +01:00
|
|
|
m_attachToCoreAction = 0;
|
2010-12-06 08:04:43 +01:00
|
|
|
m_detachAction = 0;
|
2011-02-22 12:58:32 +01:00
|
|
|
|
|
|
|
|
m_commonOptionsPage = 0;
|
2010-06-16 11:08:54 +02:00
|
|
|
}
|
|
|
|
|
|
2010-11-10 11:39:01 +01:00
|
|
|
DebuggerPluginPrivate::~DebuggerPluginPrivate()
|
|
|
|
|
{
|
2010-11-10 16:33:11 +01:00
|
|
|
delete m_debuggerSettings;
|
|
|
|
|
m_debuggerSettings = 0;
|
|
|
|
|
|
2011-03-15 14:52:35 +01:00
|
|
|
// Mainwindow will be deleted by debug mode.
|
2010-11-10 11:39:01 +01:00
|
|
|
|
|
|
|
|
delete m_snapshotHandler;
|
|
|
|
|
m_snapshotHandler = 0;
|
2011-02-24 13:25:30 +01:00
|
|
|
|
|
|
|
|
delete m_breakHandler;
|
|
|
|
|
m_breakHandler = 0;
|
2010-11-10 11:39:01 +01:00
|
|
|
}
|
|
|
|
|
|
2011-03-02 14:05:32 +01:00
|
|
|
DebuggerEngine *DebuggerPluginPrivate::dummyEngine()
|
|
|
|
|
{
|
|
|
|
|
if (!m_dummyEngine) {
|
|
|
|
|
m_dummyEngine = new DummyEngine;
|
|
|
|
|
m_dummyEngine->setParent(this);
|
|
|
|
|
m_dummyEngine->setObjectName(_("DummyEngine"));
|
|
|
|
|
}
|
|
|
|
|
return m_dummyEngine;
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-10 11:39:01 +01:00
|
|
|
DebuggerCore *debuggerCore()
|
|
|
|
|
{
|
|
|
|
|
return theDebuggerCore;
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-08 13:48:04 +01:00
|
|
|
static QString msgParameterMissing(const QString &a)
|
|
|
|
|
{
|
|
|
|
|
return DebuggerPlugin::tr("Option '%1' is missing the parameter.").arg(a);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool DebuggerPluginPrivate::parseArgument(QStringList::const_iterator &it,
|
2012-08-09 01:50:26 +02:00
|
|
|
const QStringList::const_iterator &cend, QString *errorMessage)
|
2011-02-08 13:48:04 +01:00
|
|
|
{
|
|
|
|
|
const QString &option = *it;
|
|
|
|
|
// '-debug <pid>'
|
2012-09-03 18:31:44 +02:00
|
|
|
// '-debug <exe>[,server=<server:port>][,core=<core>][,kit=<kit>]'
|
2011-02-08 13:48:04 +01:00
|
|
|
if (*it == _("-debug")) {
|
|
|
|
|
++it;
|
|
|
|
|
if (it == cend) {
|
|
|
|
|
*errorMessage = msgParameterMissing(*it);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2012-09-03 18:31:44 +02:00
|
|
|
Kit *kit = 0;
|
2011-02-08 13:48:04 +01:00
|
|
|
DebuggerStartParameters sp;
|
|
|
|
|
qulonglong pid = it->toULongLong();
|
|
|
|
|
if (pid) {
|
|
|
|
|
sp.startMode = AttachExternal;
|
2012-03-26 16:03:25 +02:00
|
|
|
sp.closeMode = DetachAtClose;
|
2011-02-08 13:48:04 +01:00
|
|
|
sp.attachPID = pid;
|
|
|
|
|
sp.displayName = tr("Process %1").arg(sp.attachPID);
|
|
|
|
|
sp.startMessage = tr("Attaching to local process %1.").arg(sp.attachPID);
|
|
|
|
|
} else {
|
2012-02-17 12:32:57 +02:00
|
|
|
sp.startMode = StartExternal;
|
2012-06-28 10:00:04 +02:00
|
|
|
QStringList args = it->split(QLatin1Char(','));
|
2012-02-17 12:32:57 +02:00
|
|
|
foreach (const QString &arg, args) {
|
|
|
|
|
QString key = arg.section(QLatin1Char('='), 0, 0);
|
|
|
|
|
QString val = arg.section(QLatin1Char('='), 1, 1);
|
|
|
|
|
if (val.isEmpty()) {
|
|
|
|
|
if (key.isEmpty())
|
|
|
|
|
continue;
|
|
|
|
|
else if (sp.executable.isEmpty())
|
|
|
|
|
sp.executable = key;
|
|
|
|
|
else {
|
|
|
|
|
*errorMessage = DebuggerPlugin::tr("Only one executable allowed!");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (key == QLatin1String("server")) {
|
|
|
|
|
sp.startMode = AttachToRemoteServer;
|
|
|
|
|
sp.remoteChannel = val;
|
|
|
|
|
sp.displayName = tr("Remote: \"%1\"").arg(sp.remoteChannel);
|
|
|
|
|
sp.startMessage = tr("Attaching to remote server %1.").arg(sp.remoteChannel);
|
|
|
|
|
}
|
|
|
|
|
else if (key == QLatin1String("core")) {
|
|
|
|
|
sp.startMode = AttachCore;
|
2012-06-13 10:15:56 +02:00
|
|
|
sp.closeMode = DetachAtClose;
|
2012-02-17 12:32:57 +02:00
|
|
|
sp.coreFile = val;
|
|
|
|
|
sp.displayName = tr("Core file \"%1\"").arg(sp.coreFile);
|
|
|
|
|
sp.startMessage = tr("Attaching to core file %1.").arg(sp.coreFile);
|
|
|
|
|
}
|
2012-09-03 18:31:44 +02:00
|
|
|
else if (key == QLatin1String("kit")) {
|
|
|
|
|
kit = KitManager::instance()->find(Id(val));
|
2012-08-15 15:42:53 +02:00
|
|
|
}
|
2011-04-19 14:30:13 +02:00
|
|
|
}
|
2012-02-17 12:32:57 +02:00
|
|
|
}
|
2012-09-21 12:50:40 +02:00
|
|
|
if (!fillParameters(&sp, kit, errorMessage))
|
2012-09-05 14:56:08 +02:00
|
|
|
return false;
|
2012-02-17 12:32:57 +02:00
|
|
|
if (sp.startMode == StartExternal) {
|
|
|
|
|
sp.displayName = tr("Executable file \"%1\"").arg(sp.executable);
|
|
|
|
|
sp.startMessage = tr("Debugging file %1.").arg(sp.executable);
|
2011-02-08 13:48:04 +01:00
|
|
|
}
|
|
|
|
|
m_scheduledStarts.append(sp);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
// -wincrashevent <event-handle>:<pid>. A handle used for
|
|
|
|
|
// a handshake when attaching to a crashed Windows process.
|
|
|
|
|
// This is created by $QTC/src/tools/qtcdebugger/main.cpp:
|
|
|
|
|
// args << QLatin1String("-wincrashevent")
|
|
|
|
|
// << QString("%1:%2").arg(argWinCrashEvent).arg(argProcessId);
|
|
|
|
|
if (*it == _("-wincrashevent")) {
|
|
|
|
|
++it;
|
|
|
|
|
if (it == cend) {
|
|
|
|
|
*errorMessage = msgParameterMissing(*it);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
DebuggerStartParameters sp;
|
2012-09-05 14:56:08 +02:00
|
|
|
if (!fillParameters(&sp, CdbMatcher::findUniversalCdbKit(), errorMessage))
|
|
|
|
|
return false;
|
2011-02-08 13:48:04 +01:00
|
|
|
sp.startMode = AttachCrashedExternal;
|
2011-12-21 14:02:52 +01:00
|
|
|
sp.crashParameter = it->section(QLatin1Char(':'), 0, 0);
|
|
|
|
|
sp.attachPID = it->section(QLatin1Char(':'), 1, 1).toULongLong();
|
2011-02-08 13:48:04 +01:00
|
|
|
sp.displayName = tr("Crashed process %1").arg(sp.attachPID);
|
|
|
|
|
sp.startMessage = tr("Attaching to crashed process %1").arg(sp.attachPID);
|
|
|
|
|
if (!sp.attachPID) {
|
|
|
|
|
*errorMessage = DebuggerPlugin::tr("The parameter '%1' of option '%2' "
|
|
|
|
|
"does not match the pattern <handle>:<pid>.").arg(*it, option);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
m_scheduledStarts.append(sp);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*errorMessage = DebuggerPlugin::tr("Invalid debugger option: %1").arg(option);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool DebuggerPluginPrivate::parseArguments(const QStringList &args,
|
2012-08-09 01:50:26 +02:00
|
|
|
QString *errorMessage)
|
2011-02-08 13:48:04 +01:00
|
|
|
{
|
|
|
|
|
const QStringList::const_iterator cend = args.constEnd();
|
|
|
|
|
for (QStringList::const_iterator it = args.constBegin(); it != cend; ++it)
|
2012-08-09 01:50:26 +02:00
|
|
|
if (!parseArgument(it, cend, errorMessage))
|
2011-02-08 13:48:04 +01:00
|
|
|
return false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-10 11:39:01 +01:00
|
|
|
bool DebuggerPluginPrivate::initialize(const QStringList &arguments,
|
|
|
|
|
QString *errorMessage)
|
2010-06-16 11:08:54 +02:00
|
|
|
{
|
2011-02-22 11:21:08 +01:00
|
|
|
Q_UNUSED(errorMessage);
|
|
|
|
|
m_arguments = arguments;
|
2010-12-03 10:45:51 +01:00
|
|
|
// Cpp/Qml ui setup
|
|
|
|
|
m_mainWindow = new DebuggerMainWindow;
|
|
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
return true;
|
|
|
|
|
}
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
void DebuggerPluginPrivate::setConfigValue(const QString &name, const QVariant &value)
|
|
|
|
|
{
|
|
|
|
|
m_coreSettings->setValue(_("DebugMode/") + name, value);
|
|
|
|
|
}
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
QVariant DebuggerPluginPrivate::configValue(const QString &name) const
|
|
|
|
|
{
|
|
|
|
|
const QVariant value = m_coreSettings->value(_("DebugMode/") + name);
|
|
|
|
|
if (value.isValid())
|
|
|
|
|
return value;
|
|
|
|
|
// Legacy (pre-2.1): Check old un-namespaced-settings.
|
|
|
|
|
return m_coreSettings->value(name);
|
|
|
|
|
}
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
void DebuggerPluginPrivate::onCurrentProjectChanged(Project *project)
|
|
|
|
|
{
|
|
|
|
|
RunConfiguration *activeRc = 0;
|
|
|
|
|
if (project) {
|
|
|
|
|
Target *target = project->activeTarget();
|
2011-10-28 10:15:04 +00:00
|
|
|
if (target)
|
|
|
|
|
activeRc = target->activeRunConfiguration();
|
|
|
|
|
if (!activeRc)
|
|
|
|
|
return;
|
2010-12-02 13:20:06 +01:00
|
|
|
}
|
|
|
|
|
for (int i = 0, n = m_snapshotHandler->size(); i != n; ++i) {
|
|
|
|
|
// Run controls might be deleted during exit.
|
2010-12-10 10:01:29 +01:00
|
|
|
if (DebuggerEngine *engine = m_snapshotHandler->at(i)) {
|
|
|
|
|
DebuggerRunControl *runControl = engine->runControl();
|
2010-12-02 13:20:06 +01:00
|
|
|
RunConfiguration *rc = runControl->runConfiguration();
|
|
|
|
|
if (rc == activeRc) {
|
|
|
|
|
m_snapshotHandler->setCurrentIndex(i);
|
|
|
|
|
updateState(engine);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// No corresponding debugger found. So we are ready to start one.
|
2011-02-03 14:08:01 +01:00
|
|
|
m_interruptAction->setEnabled(false);
|
|
|
|
|
m_continueAction->setEnabled(false);
|
|
|
|
|
m_exitAction->setEnabled(false);
|
2011-08-03 18:57:37 +02:00
|
|
|
m_startAction->setEnabled(true);
|
2011-10-25 18:23:37 +08:00
|
|
|
m_debugWithoutDeployAction->setEnabled(true);
|
2012-05-24 10:19:50 +02:00
|
|
|
setProxyAction(m_visibleStartAction, Constants::DEBUG);
|
2010-12-02 13:20:06 +01:00
|
|
|
}
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2010-12-06 11:06:18 +01:00
|
|
|
void DebuggerPluginPrivate::languagesChanged()
|
2010-12-02 13:20:06 +01:00
|
|
|
{
|
|
|
|
|
}
|
2010-11-04 18:11:09 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
void DebuggerPluginPrivate::debugProject()
|
|
|
|
|
{
|
|
|
|
|
ProjectExplorerPlugin *pe = ProjectExplorerPlugin::instance();
|
|
|
|
|
if (Project *pro = pe->startupProject())
|
2012-01-10 19:17:24 +01:00
|
|
|
pe->runProject(pro, DebugRunMode);
|
2010-12-02 13:20:06 +01:00
|
|
|
}
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2011-10-25 18:23:37 +08:00
|
|
|
void DebuggerPluginPrivate::debugProjectWithoutDeploy()
|
|
|
|
|
{
|
|
|
|
|
ProjectExplorerPlugin *pe = ProjectExplorerPlugin::instance();
|
|
|
|
|
if (Project *pro = pe->startupProject())
|
2012-01-10 19:17:24 +01:00
|
|
|
pe->runProject(pro, DebugRunMode, true);
|
2011-10-25 18:23:37 +08:00
|
|
|
}
|
|
|
|
|
|
2011-05-02 18:22:32 +02:00
|
|
|
void DebuggerPluginPrivate::debugProjectBreakMain()
|
|
|
|
|
{
|
|
|
|
|
ProjectExplorerPlugin *pe = ProjectExplorerPlugin::instance();
|
|
|
|
|
if (Project *pro = pe->startupProject())
|
2012-01-10 19:17:24 +01:00
|
|
|
pe->runProject(pro, DebugRunModeWithBreakOnMain);
|
2011-05-02 18:22:32 +02:00
|
|
|
}
|
|
|
|
|
|
2012-08-08 13:09:31 +02:00
|
|
|
void DebuggerPluginPrivate::startAndDebugApplication()
|
2010-12-02 13:20:06 +01:00
|
|
|
{
|
|
|
|
|
DebuggerStartParameters sp;
|
2012-08-15 13:21:37 +02:00
|
|
|
if (StartApplicationDialog::run(mainWindow(), m_coreSettings, &sp))
|
|
|
|
|
DebuggerRunControlFactory::createAndScheduleRun(sp);
|
2010-12-02 13:20:06 +01:00
|
|
|
}
|
2010-11-08 15:19:13 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
void DebuggerPluginPrivate::attachCore()
|
|
|
|
|
{
|
|
|
|
|
AttachCoreDialog dlg(mainWindow());
|
2012-07-24 17:02:42 +02:00
|
|
|
|
2012-10-22 11:14:18 +02:00
|
|
|
dlg.setKitId(Id(configValue(_("LastExternalKit")).toString()));
|
2012-07-24 17:02:42 +02:00
|
|
|
dlg.setLocalExecutableFile(configValue(_("LastExternalExecutableFile")).toString());
|
|
|
|
|
dlg.setLocalCoreFile(configValue(_("LastLocalCoreFile")).toString());
|
|
|
|
|
dlg.setRemoteCoreFile(configValue(_("LastRemoteCoreFile")).toString());
|
2011-05-03 14:57:05 +02:00
|
|
|
dlg.setOverrideStartScript(configValue(_("LastExternalStartScript")).toString());
|
2012-10-22 11:14:18 +02:00
|
|
|
dlg.setForceLocalCoreFile(configValue(_("LastForceLocalCoreFile")).toBool());
|
2011-02-24 16:50:15 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
if (dlg.exec() != QDialog::Accepted)
|
|
|
|
|
return;
|
2011-02-24 16:50:15 +01:00
|
|
|
|
2012-07-24 17:02:42 +02:00
|
|
|
setConfigValue(_("LastExternalExecutableFile"), dlg.localExecutableFile());
|
|
|
|
|
setConfigValue(_("LastLocalCoreFile"), dlg.localCoreFile());
|
|
|
|
|
setConfigValue(_("LastRemoteCoreFile"), dlg.remoteCoreFile());
|
2012-10-22 11:14:18 +02:00
|
|
|
setConfigValue(_("LastExternalKit"), dlg.kit()->id().toString());
|
2011-05-03 14:57:05 +02:00
|
|
|
setConfigValue(_("LastExternalStartScript"), dlg.overrideStartScript());
|
2012-10-22 11:14:18 +02:00
|
|
|
setConfigValue(_("LastForceLocalCoreFile"), dlg.forcesLocalCoreFile());
|
2010-07-22 10:23:27 +02:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
DebuggerStartParameters sp;
|
2012-10-22 11:14:18 +02:00
|
|
|
QString display = dlg.useLocalCoreFile() ? dlg.localCoreFile() : dlg.remoteCoreFile();
|
2012-09-05 14:56:08 +02:00
|
|
|
QTC_ASSERT(fillParameters(&sp, dlg.kit()), return);
|
2012-08-15 13:21:37 +02:00
|
|
|
sp.masterEngineType = GdbEngineType;
|
2012-07-24 17:02:42 +02:00
|
|
|
sp.executable = dlg.localExecutableFile();
|
|
|
|
|
sp.coreFile = dlg.localCoreFile();
|
|
|
|
|
sp.displayName = tr("Core file \"%1\"").arg(display);
|
2010-12-02 13:20:06 +01:00
|
|
|
sp.startMode = AttachCore;
|
2012-06-13 10:15:56 +02:00
|
|
|
sp.closeMode = DetachAtClose;
|
2011-05-31 10:27:32 +02:00
|
|
|
sp.overrideStartScript = dlg.overrideStartScript();
|
2012-08-15 13:21:37 +02:00
|
|
|
DebuggerRunControlFactory::createAndScheduleRun(sp);
|
2010-12-02 13:20:06 +01:00
|
|
|
}
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
void DebuggerPluginPrivate::startRemoteCdbSession()
|
|
|
|
|
{
|
|
|
|
|
const QString connectionKey = _("CdbRemoteConnection");
|
|
|
|
|
DebuggerStartParameters sp;
|
2012-09-03 18:31:44 +02:00
|
|
|
Kit *kit = CdbMatcher::findUniversalCdbKit();
|
2012-09-05 14:56:08 +02:00
|
|
|
QTC_ASSERT(kit && fillParameters(&sp, kit), return);
|
2011-09-16 11:04:11 +02:00
|
|
|
sp.startMode = AttachToRemoteServer;
|
2012-03-26 16:03:25 +02:00
|
|
|
sp.closeMode = KillAtClose;
|
2010-12-02 13:20:06 +01:00
|
|
|
StartRemoteCdbDialog dlg(mainWindow());
|
|
|
|
|
QString previousConnection = configValue(connectionKey).toString();
|
|
|
|
|
if (previousConnection.isEmpty())
|
|
|
|
|
previousConnection = QLatin1String("localhost:1234");
|
|
|
|
|
dlg.setConnection(previousConnection);
|
|
|
|
|
if (dlg.exec() != QDialog::Accepted)
|
|
|
|
|
return;
|
|
|
|
|
sp.remoteChannel = dlg.connection();
|
|
|
|
|
setConfigValue(connectionKey, sp.remoteChannel);
|
2012-08-15 13:21:37 +02:00
|
|
|
DebuggerRunControlFactory::createAndScheduleRun(sp);
|
2010-12-02 13:20:06 +01:00
|
|
|
}
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2011-12-05 17:21:48 +01:00
|
|
|
void DebuggerPluginPrivate::attachToRemoteServer()
|
2011-09-14 15:22:08 +02:00
|
|
|
{
|
|
|
|
|
DebuggerStartParameters sp;
|
2012-08-08 13:09:31 +02:00
|
|
|
sp.startMode = AttachToRemoteServer;
|
|
|
|
|
if (StartApplicationDialog::run(mainWindow(), m_coreSettings, &sp)) {
|
2012-03-26 16:03:25 +02:00
|
|
|
sp.closeMode = KillAtClose;
|
2012-02-06 15:15:57 +01:00
|
|
|
sp.serverStartScript.clear();
|
2012-08-15 13:21:37 +02:00
|
|
|
DebuggerRunControlFactory::createAndScheduleRun(sp);
|
2012-02-06 15:15:57 +01:00
|
|
|
}
|
2010-12-02 13:20:06 +01:00
|
|
|
}
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2011-12-06 15:39:25 +01:00
|
|
|
void DebuggerPluginPrivate::startRemoteServer()
|
|
|
|
|
{
|
2012-08-08 12:03:07 +02:00
|
|
|
attachToProcess(true);
|
2012-03-21 17:54:56 +01:00
|
|
|
}
|
|
|
|
|
|
2012-08-06 12:22:35 +02:00
|
|
|
void DebuggerPluginPrivate::attachToRunningApplication()
|
2012-03-21 17:54:56 +01:00
|
|
|
{
|
2012-08-08 12:03:07 +02:00
|
|
|
attachToProcess(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DebuggerPluginPrivate::attachToProcess(bool startServerOnly)
|
|
|
|
|
{
|
2012-09-05 10:55:05 +02:00
|
|
|
const DebuggerKitChooser::Mode mode = startServerOnly ?
|
|
|
|
|
DebuggerKitChooser::RemoteDebugging : DebuggerKitChooser::LocalDebugging;
|
2012-09-07 15:13:10 +02:00
|
|
|
DebuggerKitChooser *kitChooser = new DebuggerKitChooser(mode);
|
|
|
|
|
DeviceProcessesDialog *dlg = new DeviceProcessesDialog(kitChooser, mainWindow());
|
2012-08-22 16:38:21 +02:00
|
|
|
dlg->addAcceptButton(DeviceProcessesDialog::tr("&Attach to Process"));
|
2012-08-08 12:03:07 +02:00
|
|
|
dlg->showAllDevices();
|
|
|
|
|
if (dlg->exec() == QDialog::Rejected) {
|
|
|
|
|
delete dlg;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dlg->setAttribute(Qt::WA_DeleteOnClose);
|
2012-09-03 18:31:44 +02:00
|
|
|
Kit *kit = kitChooser->currentKit();
|
|
|
|
|
QTC_ASSERT(kit, return);
|
|
|
|
|
IDevice::ConstPtr device = DeviceKitInformation::device(kit);
|
2012-08-08 12:03:07 +02:00
|
|
|
QTC_ASSERT(device, return);
|
|
|
|
|
DeviceProcess process = dlg->currentProcess();
|
|
|
|
|
if (process.pid == 0) {
|
|
|
|
|
QMessageBox::warning(mainWindow(), tr("Warning"),
|
|
|
|
|
tr("Cannot attach to process with PID 0"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
|
if (isWinProcessBeingDebugged(process.pid)) {
|
|
|
|
|
QMessageBox::warning(ICore::mainWindow(), tr("Process Already Under Debugger Control"),
|
|
|
|
|
tr("The process %1 is already under the control of a debugger.\n"
|
|
|
|
|
"Qt Creator cannot attach to it.").arg(process.pid));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) {
|
|
|
|
|
DebuggerStartParameters sp;
|
2012-09-05 14:56:08 +02:00
|
|
|
QTC_ASSERT(fillParameters(&sp, kit), return);
|
2012-08-08 12:03:07 +02:00
|
|
|
sp.attachPID = process.pid;
|
|
|
|
|
sp.displayName = tr("Process %1").arg(process.pid);
|
|
|
|
|
sp.executable = process.exe;
|
|
|
|
|
sp.startMode = AttachExternal;
|
|
|
|
|
sp.closeMode = DetachAtClose;
|
2012-08-15 13:21:37 +02:00
|
|
|
DebuggerRunControlFactory::createAndScheduleRun(sp);
|
2012-08-08 12:03:07 +02:00
|
|
|
} else {
|
|
|
|
|
GdbServerStarter *starter = new GdbServerStarter(dlg, startServerOnly);
|
|
|
|
|
starter->run();
|
|
|
|
|
}
|
2011-12-05 17:21:48 +01:00
|
|
|
}
|
|
|
|
|
|
2012-08-30 10:26:09 +02:00
|
|
|
void DebuggerPluginPrivate::attachExternalApplication(ProjectExplorer::RunControl *rc)
|
|
|
|
|
{
|
|
|
|
|
DebuggerStartParameters sp;
|
|
|
|
|
sp.attachPID = rc->applicationProcessHandle().pid();
|
|
|
|
|
sp.displayName = tr("Process %1").arg(sp.attachPID);
|
|
|
|
|
sp.startMode = AttachExternal;
|
|
|
|
|
sp.closeMode = DetachAtClose;
|
|
|
|
|
sp.toolChainAbi = rc->abi();
|
2012-09-03 18:31:44 +02:00
|
|
|
Kit *kit = 0;
|
2012-08-31 15:06:07 +02:00
|
|
|
if (const RunConfiguration *runConfiguration = rc->runConfiguration())
|
|
|
|
|
if (const Target *target = runConfiguration->target())
|
2012-09-03 18:31:44 +02:00
|
|
|
kit = target->kit();
|
2012-09-05 14:56:08 +02:00
|
|
|
QTC_ASSERT(fillParameters(&sp, kit), return);
|
2012-08-30 10:26:09 +02:00
|
|
|
DebuggerRunControlFactory::createAndScheduleRun(sp);
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-13 17:26:02 +02:00
|
|
|
void DebuggerPluginPrivate::attachToQmlPort()
|
|
|
|
|
{
|
|
|
|
|
DebuggerStartParameters sp;
|
|
|
|
|
AttachToQmlPortDialog dlg(mainWindow());
|
|
|
|
|
|
|
|
|
|
const QVariant qmlServerPort = configValue(_("LastQmlServerPort"));
|
2012-08-15 16:20:11 +02:00
|
|
|
if (qmlServerPort.isValid())
|
2011-09-13 17:26:02 +02:00
|
|
|
dlg.setPort(qmlServerPort.toInt());
|
2012-08-15 16:20:11 +02:00
|
|
|
else
|
2011-09-13 17:26:02 +02:00
|
|
|
dlg.setPort(sp.qmlServerPort);
|
|
|
|
|
|
2012-09-03 18:31:44 +02:00
|
|
|
const QVariant kitId = configValue(_("LastProfile"));
|
|
|
|
|
if (kitId.isValid())
|
|
|
|
|
dlg.setKitId(Id(kitId.toString()));
|
2011-10-11 15:21:00 +02:00
|
|
|
|
2011-09-13 17:26:02 +02:00
|
|
|
if (dlg.exec() != QDialog::Accepted)
|
|
|
|
|
return;
|
|
|
|
|
|
2012-09-03 18:31:44 +02:00
|
|
|
Kit *kit = dlg.kit();
|
2012-09-05 14:56:08 +02:00
|
|
|
QTC_ASSERT(kit && fillParameters(&sp, kit), return);
|
2011-09-13 17:26:02 +02:00
|
|
|
setConfigValue(_("LastQmlServerPort"), dlg.port());
|
2012-09-03 18:31:44 +02:00
|
|
|
setConfigValue(_("LastProfile"), kit->id().toString());
|
2011-09-13 17:26:02 +02:00
|
|
|
|
2012-08-15 16:20:11 +02:00
|
|
|
sp.qmlServerAddress = sp.connParams.host;
|
2011-09-14 16:58:10 +02:00
|
|
|
sp.qmlServerPort = dlg.port();
|
2012-06-13 11:55:16 +02:00
|
|
|
sp.startMode = AttachToRemoteProcess;
|
2012-03-26 16:03:25 +02:00
|
|
|
sp.closeMode = KillAtClose;
|
2012-02-21 10:13:52 +01:00
|
|
|
sp.languages = QmlLanguage;
|
2011-10-28 13:25:58 +02:00
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// get files from all the projects in the session
|
|
|
|
|
//
|
2011-12-06 15:39:25 +01:00
|
|
|
SessionManager *sessionManager = ProjectExplorerPlugin::instance()->session();
|
2011-10-28 13:25:58 +02:00
|
|
|
QList<Project *> projects = sessionManager->projects();
|
2011-12-06 15:39:25 +01:00
|
|
|
if (Project *startupProject = ProjectExplorerPlugin::instance()->startupProject()) {
|
2011-10-28 13:25:58 +02:00
|
|
|
// startup project first
|
2011-12-06 15:39:25 +01:00
|
|
|
projects.removeOne(ProjectExplorerPlugin::instance()->startupProject());
|
2011-10-28 13:25:58 +02:00
|
|
|
projects.insert(0, startupProject);
|
|
|
|
|
}
|
|
|
|
|
QStringList sourceFiles;
|
|
|
|
|
foreach (Project *project, projects)
|
|
|
|
|
sourceFiles << project->files(Project::ExcludeGeneratedFiles);
|
|
|
|
|
|
|
|
|
|
sp.projectSourceFiles = sourceFiles;
|
2012-08-15 13:21:37 +02:00
|
|
|
DebuggerRunControlFactory::createAndScheduleRun(sp);
|
2011-09-13 17:26:02 +02:00
|
|
|
}
|
|
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
void DebuggerPluginPrivate::startRemoteEngine()
|
|
|
|
|
{
|
|
|
|
|
DebuggerStartParameters sp;
|
|
|
|
|
StartRemoteEngineDialog dlg(mainWindow());
|
|
|
|
|
if (dlg.exec() != QDialog::Accepted)
|
|
|
|
|
return;
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
sp.connParams.host = dlg.host();
|
2011-02-15 13:33:52 +01:00
|
|
|
sp.connParams.userName = dlg.username();
|
|
|
|
|
sp.connParams.password = dlg.password();
|
2010-11-10 16:33:11 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
sp.connParams.timeout = 5;
|
2012-05-18 10:49:35 +02:00
|
|
|
sp.connParams.authenticationType = QSsh::SshConnectionParameters::AuthenticationByPassword;
|
2010-12-02 13:20:06 +01:00
|
|
|
sp.connParams.port = 22;
|
2012-10-01 14:51:27 +02:00
|
|
|
sp.connParams.options = QSsh::SshIgnoreDefaultProxy;
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
sp.executable = dlg.inferiorPath();
|
|
|
|
|
sp.serverStartScript = dlg.enginePath();
|
|
|
|
|
sp.startMode = StartRemoteEngine;
|
2012-08-15 13:21:37 +02:00
|
|
|
DebuggerRunControlFactory::createAndScheduleRun(sp);
|
2010-12-02 13:20:06 +01:00
|
|
|
}
|
2010-09-22 12:25:42 +02:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
void DebuggerPluginPrivate::enableReverseDebuggingTriggered(const QVariant &value)
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(m_reverseToolButton, return);
|
|
|
|
|
m_reverseToolButton->setVisible(value.toBool());
|
2011-02-03 14:08:01 +01:00
|
|
|
m_reverseDirectionAction->setChecked(false);
|
|
|
|
|
m_reverseDirectionAction->setEnabled(value.toBool());
|
2010-12-02 13:20:06 +01:00
|
|
|
}
|
2010-09-22 12:25:42 +02:00
|
|
|
|
2011-02-08 13:48:04 +01:00
|
|
|
void DebuggerPluginPrivate::runScheduled()
|
2010-12-02 13:20:06 +01:00
|
|
|
{
|
2012-08-15 13:21:37 +02:00
|
|
|
foreach (const DebuggerStartParameters &sp, m_scheduledStarts)
|
|
|
|
|
DebuggerRunControlFactory::createAndScheduleRun(sp);
|
2010-12-02 13:20:06 +01:00
|
|
|
}
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2011-01-04 15:37:17 +01:00
|
|
|
void DebuggerPluginPrivate::editorOpened(IEditor *editor)
|
2010-12-02 13:20:06 +01:00
|
|
|
{
|
2011-02-17 10:08:57 +01:00
|
|
|
if (!isEditorDebuggable(editor))
|
2010-12-02 13:20:06 +01:00
|
|
|
return;
|
|
|
|
|
ITextEditor *textEditor = qobject_cast<ITextEditor *>(editor);
|
|
|
|
|
if (!textEditor)
|
|
|
|
|
return;
|
|
|
|
|
connect(textEditor,
|
2012-03-05 22:30:59 +01:00
|
|
|
SIGNAL(markRequested(TextEditor::ITextEditor*,int,TextEditor::ITextEditor::MarkRequestKind)),
|
|
|
|
|
SLOT(requestMark(TextEditor::ITextEditor*,int,TextEditor::ITextEditor::MarkRequestKind)));
|
2010-12-02 13:20:06 +01:00
|
|
|
connect(textEditor,
|
|
|
|
|
SIGNAL(markContextMenuRequested(TextEditor::ITextEditor*,int,QMenu*)),
|
|
|
|
|
SLOT(requestContextMenu(TextEditor::ITextEditor*,int,QMenu*)));
|
|
|
|
|
}
|
2010-09-22 12:25:42 +02:00
|
|
|
|
2012-07-18 16:20:19 +02:00
|
|
|
void DebuggerPluginPrivate::updateBreakMenuItem(IEditor *editor)
|
2011-02-04 14:36:50 +01:00
|
|
|
{
|
|
|
|
|
ITextEditor *textEditor = qobject_cast<ITextEditor *>(editor);
|
|
|
|
|
m_breakAction->setEnabled(textEditor != 0);
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-04 15:37:17 +01:00
|
|
|
void DebuggerPluginPrivate::requestContextMenu(ITextEditor *editor,
|
2010-12-02 13:20:06 +01:00
|
|
|
int lineNumber, QMenu *menu)
|
|
|
|
|
{
|
2011-02-17 10:08:57 +01:00
|
|
|
if (!isEditorDebuggable(editor))
|
2010-12-02 13:20:06 +01:00
|
|
|
return;
|
2010-06-22 12:02:24 +02:00
|
|
|
|
2011-06-27 10:37:57 +02:00
|
|
|
BreakpointMenuContextData args;
|
2011-01-04 15:54:36 +01:00
|
|
|
args.lineNumber = lineNumber;
|
2011-02-23 10:16:11 +01:00
|
|
|
bool contextUsable = true;
|
2011-01-04 15:54:36 +01:00
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
BreakpointModelId id = BreakpointModelId();
|
2012-02-14 16:43:51 +01:00
|
|
|
const QString fileName = editor->document()->fileName();
|
2010-12-02 13:20:06 +01:00
|
|
|
if (editor->property("DisassemblerView").toBool()) {
|
2012-02-01 17:44:07 +01:00
|
|
|
args.fileName = fileName;
|
2010-12-02 13:20:06 +01:00
|
|
|
QString line = editor->contents()
|
2011-12-21 14:02:52 +01:00
|
|
|
.section(QLatin1Char('\n'), lineNumber - 1, lineNumber - 1);
|
2010-12-02 13:20:06 +01:00
|
|
|
BreakpointResponse needle;
|
|
|
|
|
needle.type = BreakpointByAddress;
|
2011-04-12 17:32:41 +02:00
|
|
|
needle.address = DisassemblerLine::addressFromDisassemblyLine(line);
|
2011-01-04 15:54:36 +01:00
|
|
|
args.address = needle.address;
|
2010-12-02 13:20:06 +01:00
|
|
|
needle.lineNumber = -1;
|
|
|
|
|
id = breakHandler()->findSimilarBreakpoint(needle);
|
2011-02-23 10:16:11 +01:00
|
|
|
contextUsable = args.address != 0;
|
2010-12-02 13:20:06 +01:00
|
|
|
} else {
|
2012-02-14 16:43:51 +01:00
|
|
|
args.fileName = editor->document()->fileName();
|
2011-02-03 13:45:03 +01:00
|
|
|
id = breakHandler()
|
|
|
|
|
->findBreakpointByFileAndLine(args.fileName, lineNumber);
|
2012-01-10 13:19:46 +01:00
|
|
|
if (!id)
|
|
|
|
|
id = breakHandler()->findBreakpointByFileAndLine(args.fileName, lineNumber, false);
|
2010-12-02 13:20:06 +01:00
|
|
|
}
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
if (id) {
|
|
|
|
|
// Remove existing breakpoint.
|
|
|
|
|
QAction *act = new QAction(menu);
|
2011-06-15 14:02:26 +02:00
|
|
|
act->setData(QVariant::fromValue(id));
|
|
|
|
|
act->setText(tr("Remove Breakpoint %1").arg(id.toString()));
|
2010-12-02 13:20:06 +01:00
|
|
|
connect(act, SIGNAL(triggered()),
|
|
|
|
|
SLOT(breakpointRemoveMarginActionTriggered()));
|
|
|
|
|
menu->addAction(act);
|
2010-08-18 13:54:12 +02:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
// Enable/disable existing breakpoint.
|
|
|
|
|
act = new QAction(menu);
|
2011-06-15 14:02:26 +02:00
|
|
|
act->setData(QVariant::fromValue(id));
|
2010-12-02 13:20:06 +01:00
|
|
|
if (breakHandler()->isEnabled(id)) {
|
2011-06-15 14:02:26 +02:00
|
|
|
act->setText(tr("Disable Breakpoint %1").arg(id.toString()));
|
2010-12-02 13:20:06 +01:00
|
|
|
connect(act, SIGNAL(triggered()),
|
|
|
|
|
SLOT(breakpointDisableMarginActionTriggered()));
|
|
|
|
|
} else {
|
2011-06-15 14:02:26 +02:00
|
|
|
act->setText(tr("Enable Breakpoint %1").arg(id.toString()));
|
2010-12-02 13:20:06 +01:00
|
|
|
connect(act, SIGNAL(triggered()),
|
|
|
|
|
SLOT(breakpointEnableMarginActionTriggered()));
|
|
|
|
|
}
|
|
|
|
|
menu->addAction(act);
|
2010-08-26 16:02:41 +02:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
// Edit existing breakpoint.
|
|
|
|
|
act = new QAction(menu);
|
2011-06-15 14:02:26 +02:00
|
|
|
act->setText(tr("Edit Breakpoint %1...").arg(id.toString()));
|
2010-12-02 13:20:06 +01:00
|
|
|
connect(act, SIGNAL(triggered()), SLOT(slotEditBreakpoint()));
|
2011-06-15 14:02:26 +02:00
|
|
|
act->setData(QVariant::fromValue(id));
|
2010-12-02 13:20:06 +01:00
|
|
|
menu->addAction(act);
|
|
|
|
|
} else {
|
|
|
|
|
// Handle non-existing breakpoint.
|
2011-02-23 10:16:11 +01:00
|
|
|
const QString text = args.address
|
|
|
|
|
? tr("Set Breakpoint at 0x%1").arg(args.address, 0, 16)
|
2012-03-20 18:05:12 +01:00
|
|
|
: tr("Set Breakpoint at Line %1").arg(lineNumber);
|
2010-12-02 13:20:06 +01:00
|
|
|
QAction *act = new QAction(text, menu);
|
2011-01-04 15:54:36 +01:00
|
|
|
act->setData(QVariant::fromValue(args));
|
2011-02-23 10:16:11 +01:00
|
|
|
act->setEnabled(contextUsable);
|
2010-12-02 13:20:06 +01:00
|
|
|
connect(act, SIGNAL(triggered()),
|
|
|
|
|
SLOT(breakpointSetMarginActionTriggered()));
|
|
|
|
|
menu->addAction(act);
|
2011-06-27 10:37:57 +02:00
|
|
|
// Message trace point
|
|
|
|
|
args.mode = BreakpointMenuContextData::MessageTracePoint;
|
|
|
|
|
const QString tracePointText = args.address
|
|
|
|
|
? tr("Set Message Tracepoint at 0x%1...").arg(args.address, 0, 16)
|
2012-03-20 18:05:12 +01:00
|
|
|
: tr("Set Message Tracepoint at Line %1...").arg(lineNumber);
|
2011-06-27 10:37:57 +02:00
|
|
|
act = new QAction(tracePointText, menu);
|
|
|
|
|
act->setData(QVariant::fromValue(args));
|
|
|
|
|
act->setEnabled(contextUsable);
|
|
|
|
|
connect(act, SIGNAL(triggered()),
|
|
|
|
|
SLOT(breakpointSetMarginActionTriggered()));
|
|
|
|
|
menu->addAction(act);
|
2010-12-02 13:20:06 +01:00
|
|
|
}
|
|
|
|
|
// Run to, jump to line below in stopped state.
|
2011-02-23 10:16:11 +01:00
|
|
|
if (currentEngine()->state() == InferiorStopOk && contextUsable) {
|
2010-12-02 13:20:06 +01:00
|
|
|
menu->addSeparator();
|
2012-01-12 20:28:17 +01:00
|
|
|
if (currentEngine()->hasCapability(RunToLineCapability)) {
|
2011-04-01 19:47:39 +02:00
|
|
|
const QString runText = args.address
|
|
|
|
|
? DebuggerEngine::tr("Run to Address 0x%1").arg(args.address, 0, 16)
|
|
|
|
|
: DebuggerEngine::tr("Run to Line %1").arg(args.lineNumber);
|
|
|
|
|
QAction *runToLineAction = new QAction(runText, menu);
|
|
|
|
|
runToLineAction->setData(QVariant::fromValue(args));
|
|
|
|
|
connect(runToLineAction, SIGNAL(triggered()), SLOT(slotRunToLine()));
|
|
|
|
|
menu->addAction(runToLineAction);
|
|
|
|
|
}
|
2012-01-12 20:28:17 +01:00
|
|
|
if (currentEngine()->hasCapability(JumpToLineCapability)) {
|
2011-02-23 10:16:11 +01:00
|
|
|
const QString jumpText = args.address
|
|
|
|
|
? DebuggerEngine::tr("Jump to Address 0x%1").arg(args.address, 0, 16)
|
|
|
|
|
: DebuggerEngine::tr("Jump to Line %1").arg(args.lineNumber);
|
2010-12-02 13:20:06 +01:00
|
|
|
QAction *jumpToLineAction = new QAction(jumpText, menu);
|
2011-01-04 15:54:36 +01:00
|
|
|
jumpToLineAction->setData(QVariant::fromValue(args));
|
2010-12-02 13:20:06 +01:00
|
|
|
connect(jumpToLineAction, SIGNAL(triggered()), SLOT(slotJumpToLine()));
|
|
|
|
|
menu->addAction(jumpToLineAction);
|
|
|
|
|
}
|
2012-02-01 17:44:07 +01:00
|
|
|
// Disassemble current function in stopped state.
|
|
|
|
|
if (currentEngine()->state() == InferiorStopOk
|
|
|
|
|
&& currentEngine()->hasCapability(DisassemblerCapability)) {
|
|
|
|
|
StackFrame frame;
|
|
|
|
|
frame.function = cppFunctionAt(fileName, lineNumber);
|
|
|
|
|
frame.line = 42; // trick gdb into mixed mode.
|
|
|
|
|
if (!frame.function.isEmpty()) {
|
2012-03-20 18:05:12 +01:00
|
|
|
const QString text = tr("Disassemble Function \"%1\"")
|
|
|
|
|
.arg(frame.function);
|
2012-02-01 17:44:07 +01:00
|
|
|
QAction *disassembleAction = new QAction(text, menu);
|
|
|
|
|
disassembleAction->setData(QVariant::fromValue(frame));
|
|
|
|
|
connect(disassembleAction, SIGNAL(triggered()), SLOT(slotDisassembleFunction()));
|
|
|
|
|
menu->addAction(disassembleAction );
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-06-16 11:08:54 +02:00
|
|
|
}
|
2010-12-02 13:20:06 +01:00
|
|
|
}
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
void DebuggerPluginPrivate::toggleBreakpoint()
|
|
|
|
|
{
|
|
|
|
|
ITextEditor *textEditor = currentTextEditor();
|
|
|
|
|
QTC_ASSERT(textEditor, return);
|
|
|
|
|
const int lineNumber = textEditor->currentLine();
|
|
|
|
|
if (textEditor->property("DisassemblerView").toBool()) {
|
|
|
|
|
QString line = textEditor->contents()
|
2011-12-21 14:02:52 +01:00
|
|
|
.section(QLatin1Char('\n'), lineNumber - 1, lineNumber - 1);
|
2011-04-12 17:32:41 +02:00
|
|
|
quint64 address = DisassemblerLine::addressFromDisassemblyLine(line);
|
2010-12-02 13:20:06 +01:00
|
|
|
toggleBreakpointByAddress(address);
|
|
|
|
|
} else if (lineNumber >= 0) {
|
2012-02-14 16:43:51 +01:00
|
|
|
toggleBreakpointByFileAndLine(textEditor->document()->fileName(), lineNumber);
|
2010-12-02 13:20:06 +01:00
|
|
|
}
|
|
|
|
|
}
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
void DebuggerPluginPrivate::toggleBreakpointByFileAndLine(const QString &fileName,
|
2011-06-27 10:37:57 +02:00
|
|
|
int lineNumber, const QString &tracePointMessage)
|
2010-12-02 13:20:06 +01:00
|
|
|
{
|
|
|
|
|
BreakHandler *handler = m_breakHandler;
|
2011-06-24 16:25:30 +02:00
|
|
|
BreakpointModelId id =
|
2010-12-02 13:20:06 +01:00
|
|
|
handler->findBreakpointByFileAndLine(fileName, lineNumber, true);
|
|
|
|
|
if (!id)
|
|
|
|
|
id = handler->findBreakpointByFileAndLine(fileName, lineNumber, false);
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
if (id) {
|
|
|
|
|
handler->removeBreakpoint(id);
|
|
|
|
|
} else {
|
|
|
|
|
BreakpointParameters data(BreakpointByFileAndLine);
|
2012-06-10 01:20:30 +04:00
|
|
|
if (debuggerCore()->boolSetting(BreakpointsFullPathByDefault))
|
|
|
|
|
data.pathUsage = BreakpointUseFullPath;
|
2011-06-27 10:37:57 +02:00
|
|
|
data.tracepoint = !tracePointMessage.isEmpty();
|
|
|
|
|
data.message = tracePointMessage;
|
2010-12-02 13:20:06 +01:00
|
|
|
data.fileName = fileName;
|
|
|
|
|
data.lineNumber = lineNumber;
|
|
|
|
|
handler->appendBreakpoint(data);
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2011-06-27 10:37:57 +02:00
|
|
|
void DebuggerPluginPrivate::toggleBreakpointByAddress(quint64 address,
|
|
|
|
|
const QString &tracePointMessage)
|
2010-12-02 13:20:06 +01:00
|
|
|
{
|
|
|
|
|
BreakHandler *handler = m_breakHandler;
|
2011-06-24 16:25:30 +02:00
|
|
|
BreakpointModelId id = handler->findBreakpointByAddress(address);
|
2010-11-12 20:18:29 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
if (id) {
|
|
|
|
|
handler->removeBreakpoint(id);
|
|
|
|
|
} else {
|
|
|
|
|
BreakpointParameters data(BreakpointByAddress);
|
2011-06-27 10:37:57 +02:00
|
|
|
data.tracepoint = !tracePointMessage.isEmpty();
|
|
|
|
|
data.message = tracePointMessage;
|
2010-12-02 13:20:06 +01:00
|
|
|
data.address = address;
|
|
|
|
|
handler->appendBreakpoint(data);
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-11-09 10:23:10 +01:00
|
|
|
|
2011-11-29 13:51:00 +01:00
|
|
|
void DebuggerPluginPrivate::requestMark(ITextEditor *editor,
|
|
|
|
|
int lineNumber,
|
|
|
|
|
ITextEditor::MarkRequestKind kind)
|
2010-12-02 13:20:06 +01:00
|
|
|
{
|
2011-11-29 13:51:00 +01:00
|
|
|
if (kind != ITextEditor::BreakpointRequest)
|
|
|
|
|
return;
|
|
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
if (editor->property("DisassemblerView").toBool()) {
|
|
|
|
|
QString line = editor->contents()
|
2011-12-21 14:02:52 +01:00
|
|
|
.section(QLatin1Char('\n'), lineNumber - 1, lineNumber - 1);
|
2011-04-12 17:32:41 +02:00
|
|
|
quint64 address = DisassemblerLine::addressFromDisassemblyLine(line);
|
2010-12-02 13:20:06 +01:00
|
|
|
toggleBreakpointByAddress(address);
|
2012-02-14 16:43:51 +01:00
|
|
|
} else if (editor->document()) {
|
|
|
|
|
toggleBreakpointByFileAndLine(editor->document()->fileName(), lineNumber);
|
2010-12-02 13:20:06 +01:00
|
|
|
}
|
|
|
|
|
}
|
2010-12-01 15:41:08 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
// If updateEngine is set, the engine will update its threads/modules and so forth.
|
|
|
|
|
void DebuggerPluginPrivate::displayDebugger(DebuggerEngine *engine, bool updateEngine)
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(engine, return);
|
|
|
|
|
disconnectEngine();
|
|
|
|
|
connectEngine(engine);
|
|
|
|
|
if (updateEngine)
|
|
|
|
|
engine->updateAll();
|
|
|
|
|
engine->updateViews();
|
|
|
|
|
}
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
void DebuggerPluginPrivate::connectEngine(DebuggerEngine *engine)
|
|
|
|
|
{
|
|
|
|
|
if (!engine)
|
|
|
|
|
engine = dummyEngine();
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
if (m_currentEngine == engine)
|
|
|
|
|
return;
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2010-12-14 12:21:29 +01:00
|
|
|
if (m_currentEngine)
|
|
|
|
|
m_currentEngine->resetLocation();
|
2010-12-02 13:20:06 +01:00
|
|
|
m_currentEngine = engine;
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
m_localsWindow->setModel(engine->localsModel());
|
|
|
|
|
m_modulesWindow->setModel(engine->modulesModel());
|
|
|
|
|
m_registerWindow->setModel(engine->registerModel());
|
|
|
|
|
m_returnWindow->setModel(engine->returnModel());
|
|
|
|
|
m_sourceFilesWindow->setModel(engine->sourceFilesModel());
|
|
|
|
|
m_stackWindow->setModel(engine->stackModel());
|
|
|
|
|
m_threadsWindow->setModel(engine->threadsModel());
|
|
|
|
|
m_watchersWindow->setModel(engine->watchersModel());
|
2012-04-18 14:20:54 +02:00
|
|
|
m_inspectorWindow->setModel(engine->inspectorModel());
|
2011-10-06 17:38:28 +02:00
|
|
|
|
2011-02-23 16:09:56 +01:00
|
|
|
engine->watchHandler()->rebuildModel();
|
2011-10-12 16:30:14 +02:00
|
|
|
|
2012-08-14 17:54:01 +02:00
|
|
|
mainWindow()->setEngineDebugLanguages(engine->startParameters().languages);
|
2012-03-13 13:50:05 +01:00
|
|
|
mainWindow()->setCurrentEngine(engine);
|
2010-12-02 13:20:06 +01:00
|
|
|
}
|
2010-11-12 20:18:29 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
static void changeFontSize(QWidget *widget, qreal size)
|
|
|
|
|
{
|
|
|
|
|
QFont font = widget->font();
|
|
|
|
|
font.setPointSizeF(size);
|
|
|
|
|
widget->setFont(font);
|
|
|
|
|
}
|
2009-06-04 16:06:12 +02:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
void DebuggerPluginPrivate::fontSettingsChanged
|
|
|
|
|
(const TextEditor::FontSettings &settings)
|
|
|
|
|
{
|
2011-04-01 12:01:14 +02:00
|
|
|
if (!boolSetting(FontSizeFollowsEditor))
|
|
|
|
|
return;
|
2010-12-02 13:20:06 +01:00
|
|
|
qreal size = settings.fontZoom() * settings.fontSize() / 100.;
|
|
|
|
|
changeFontSize(m_breakWindow, size);
|
|
|
|
|
changeFontSize(m_logWindow, size);
|
|
|
|
|
changeFontSize(m_localsWindow, size);
|
|
|
|
|
changeFontSize(m_modulesWindow, size);
|
|
|
|
|
//changeFontSize(m_consoleWindow, size);
|
|
|
|
|
changeFontSize(m_registerWindow, size);
|
|
|
|
|
changeFontSize(m_returnWindow, size);
|
|
|
|
|
changeFontSize(m_sourceFilesWindow, size);
|
|
|
|
|
changeFontSize(m_stackWindow, size);
|
|
|
|
|
changeFontSize(m_threadsWindow, size);
|
|
|
|
|
changeFontSize(m_watchersWindow, size);
|
2012-04-18 14:20:54 +02:00
|
|
|
changeFontSize(m_inspectorWindow, size);
|
2010-12-02 13:20:06 +01:00
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
void DebuggerPluginPrivate::cleanupViews()
|
|
|
|
|
{
|
2011-02-03 14:08:01 +01:00
|
|
|
m_reverseDirectionAction->setChecked(false);
|
|
|
|
|
m_reverseDirectionAction->setEnabled(false);
|
2010-12-01 15:41:08 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
if (!boolSetting(CloseBuffersOnExit))
|
|
|
|
|
return;
|
2009-03-02 15:14:12 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
EditorManager *editorManager = EditorManager::instance();
|
|
|
|
|
QTC_ASSERT(editorManager, return);
|
|
|
|
|
QList<IEditor *> toClose;
|
|
|
|
|
foreach (IEditor *editor, editorManager->openedEditors()) {
|
|
|
|
|
if (editor->property(Constants::OPENED_BY_DEBUGGER).toBool()) {
|
2012-06-12 13:29:37 +02:00
|
|
|
IDocument *doc = editor->document();
|
|
|
|
|
bool keepIt = true;
|
|
|
|
|
if (editor->property(Constants::OPENED_WITH_DISASSEMBLY).toBool())
|
|
|
|
|
keepIt = false;
|
|
|
|
|
else if (doc->isModified())
|
|
|
|
|
keepIt = true;
|
|
|
|
|
else if (doc->fileName().contains(_("qeventdispatcher")))
|
|
|
|
|
keepIt = false;
|
|
|
|
|
else
|
|
|
|
|
keepIt = (editor == EditorManager::currentEditor());
|
|
|
|
|
|
|
|
|
|
if (keepIt)
|
2010-12-02 13:20:06 +01:00
|
|
|
editor->setProperty(Constants::OPENED_BY_DEBUGGER, false);
|
2012-06-12 13:29:37 +02:00
|
|
|
else
|
|
|
|
|
toClose.append(editor);
|
2010-12-02 13:20:06 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
editorManager->closeEditors(toClose);
|
|
|
|
|
}
|
2010-05-05 12:41:52 +02:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
void DebuggerPluginPrivate::setBusyCursor(bool busy)
|
|
|
|
|
{
|
|
|
|
|
//STATE_DEBUG("BUSY FROM: " << m_busy << " TO: " << busy);
|
|
|
|
|
if (busy == m_busy)
|
|
|
|
|
return;
|
|
|
|
|
m_busy = busy;
|
|
|
|
|
QCursor cursor(busy ? Qt::BusyCursor : Qt::ArrowCursor);
|
|
|
|
|
m_breakWindow->setCursor(cursor);
|
|
|
|
|
//m_consoleWindow->setCursor(cursor);
|
|
|
|
|
m_localsWindow->setCursor(cursor);
|
|
|
|
|
m_modulesWindow->setCursor(cursor);
|
|
|
|
|
m_logWindow->setCursor(cursor);
|
|
|
|
|
m_registerWindow->setCursor(cursor);
|
|
|
|
|
m_returnWindow->setCursor(cursor);
|
|
|
|
|
m_sourceFilesWindow->setCursor(cursor);
|
|
|
|
|
m_stackWindow->setCursor(cursor);
|
|
|
|
|
m_threadsWindow->setCursor(cursor);
|
|
|
|
|
m_watchersWindow->setCursor(cursor);
|
|
|
|
|
m_snapshotWindow->setCursor(cursor);
|
|
|
|
|
}
|
2009-05-07 17:11:19 +02:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
void DebuggerPluginPrivate::setInitialState()
|
|
|
|
|
{
|
|
|
|
|
m_watchersWindow->setVisible(false);
|
|
|
|
|
m_returnWindow->setVisible(false);
|
|
|
|
|
setBusyCursor(false);
|
2011-02-03 14:08:01 +01:00
|
|
|
m_reverseDirectionAction->setChecked(false);
|
|
|
|
|
m_reverseDirectionAction->setEnabled(false);
|
2011-02-11 15:00:13 +01:00
|
|
|
m_toolTipManager->closeAllToolTips();
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2012-08-08 13:09:31 +02:00
|
|
|
m_startAndDebugApplicationAction->setEnabled(true);
|
2011-09-13 17:26:02 +02:00
|
|
|
m_attachToQmlPortAction->setEnabled(true);
|
2011-12-05 17:21:48 +01:00
|
|
|
m_attachToCoreAction->setEnabled(true);
|
|
|
|
|
m_attachToRemoteServerAction->setEnabled(true);
|
2012-08-06 12:22:35 +02:00
|
|
|
m_attachToRunningApplication->setEnabled(true);
|
2010-12-02 13:20:06 +01:00
|
|
|
m_detachAction->setEnabled(false);
|
2010-07-22 10:23:27 +02:00
|
|
|
|
2011-02-03 14:08:01 +01:00
|
|
|
m_watchAction1->setEnabled(true);
|
|
|
|
|
m_watchAction2->setEnabled(true);
|
2011-02-04 14:36:50 +01:00
|
|
|
m_breakAction->setEnabled(false);
|
2011-02-03 14:08:01 +01:00
|
|
|
//m_snapshotAction->setEnabled(false);
|
2010-12-02 13:20:06 +01:00
|
|
|
action(OperateByInstruction)->setEnabled(false);
|
2010-10-05 12:47:23 +02:00
|
|
|
|
2011-02-03 14:08:01 +01:00
|
|
|
m_exitAction->setEnabled(false);
|
2011-10-31 16:15:48 +01:00
|
|
|
m_abortAction->setEnabled(false);
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2011-02-04 14:36:50 +01:00
|
|
|
m_interruptAction->setEnabled(false);
|
|
|
|
|
m_continueAction->setEnabled(false);
|
|
|
|
|
|
2011-05-02 18:22:32 +02:00
|
|
|
m_stepAction->setEnabled(true);
|
2011-02-03 14:08:01 +01:00
|
|
|
m_stepOutAction->setEnabled(false);
|
|
|
|
|
m_runToLineAction->setEnabled(false);
|
|
|
|
|
m_runToSelectedFunctionAction->setEnabled(true);
|
|
|
|
|
m_returnFromFunctionAction->setEnabled(false);
|
|
|
|
|
m_jumpToLineAction->setEnabled(false);
|
2011-05-02 18:22:32 +02:00
|
|
|
m_nextAction->setEnabled(true);
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
action(AutoDerefPointers)->setEnabled(true);
|
|
|
|
|
action(ExpandStack)->setEnabled(false);
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2012-05-18 02:28:41 +02:00
|
|
|
void DebuggerPluginPrivate::updateWatchersWindow(bool showWatch, bool showReturn)
|
2010-12-02 13:20:06 +01:00
|
|
|
{
|
2012-05-18 02:28:41 +02:00
|
|
|
m_watchersWindow->setVisible(showWatch);
|
|
|
|
|
m_returnWindow->setVisible(showReturn);
|
2010-12-02 13:20:06 +01:00
|
|
|
}
|
2010-03-18 10:56:25 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
void DebuggerPluginPrivate::updateState(DebuggerEngine *engine)
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(engine, return);
|
|
|
|
|
QTC_ASSERT(m_watchersWindow->model(), return);
|
|
|
|
|
QTC_ASSERT(m_returnWindow->model(), return);
|
|
|
|
|
QTC_ASSERT(!engine->isSlaveEngine(), return);
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2012-10-19 16:37:57 +02:00
|
|
|
m_threadBox->setCurrentIndex(engine->threadsHandler()->currentThreadIndex());
|
2012-05-18 02:28:41 +02:00
|
|
|
engine->watchHandler()->updateWatchersWindow();
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2011-01-04 16:05:53 +01:00
|
|
|
const DebuggerState state = engine->state();
|
|
|
|
|
//showMessage(QString("PLUGIN SET STATE: ")
|
|
|
|
|
// + DebuggerEngine::stateName(state), LogStatus);
|
|
|
|
|
//qDebug() << "PLUGIN SET STATE: " << state;
|
2010-03-18 10:56:25 +01:00
|
|
|
|
2011-01-04 16:05:53 +01:00
|
|
|
static DebuggerState previousState = DebuggerNotReady;
|
|
|
|
|
if (state == previousState)
|
2010-12-02 13:20:06 +01:00
|
|
|
return;
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2011-01-04 16:05:53 +01:00
|
|
|
bool actionsEnabled = DebuggerEngine::debuggerActionsEnabled(state);
|
2010-12-02 13:20:06 +01:00
|
|
|
|
2011-01-04 16:05:53 +01:00
|
|
|
if (state == DebuggerNotReady) {
|
2011-08-03 18:57:37 +02:00
|
|
|
QTC_ASSERT(false, /* We use the Core's m_debugAction here */);
|
2010-12-02 13:20:06 +01:00
|
|
|
// F5 starts debugging. It is "startable".
|
2011-02-03 14:08:01 +01:00
|
|
|
m_interruptAction->setEnabled(false);
|
|
|
|
|
m_continueAction->setEnabled(false);
|
|
|
|
|
m_exitAction->setEnabled(false);
|
2011-08-03 18:57:37 +02:00
|
|
|
m_startAction->setEnabled(true);
|
2011-10-25 18:23:37 +08:00
|
|
|
m_debugWithoutDeployAction->setEnabled(true);
|
2012-05-24 10:19:50 +02:00
|
|
|
setProxyAction(m_visibleStartAction, Constants::DEBUG);
|
2011-08-03 18:57:37 +02:00
|
|
|
m_hiddenStopAction->setAction(m_undisturbableAction);
|
2011-01-04 16:05:53 +01:00
|
|
|
} else if (state == InferiorStopOk) {
|
2010-12-02 13:20:06 +01:00
|
|
|
// F5 continues, Shift-F5 kills. It is "continuable".
|
2011-02-03 14:08:01 +01:00
|
|
|
m_interruptAction->setEnabled(false);
|
|
|
|
|
m_continueAction->setEnabled(true);
|
|
|
|
|
m_exitAction->setEnabled(true);
|
2011-08-03 18:57:37 +02:00
|
|
|
m_startAction->setEnabled(false);
|
2011-10-25 18:23:37 +08:00
|
|
|
m_debugWithoutDeployAction->setEnabled(false);
|
2012-05-24 10:19:50 +02:00
|
|
|
setProxyAction(m_visibleStartAction, Constants::CONTINUE);
|
2011-08-03 18:57:37 +02:00
|
|
|
m_hiddenStopAction->setAction(m_exitAction);
|
2012-05-14 16:09:12 +02:00
|
|
|
m_localsAndExpressionsWindow->setShowLocals(true);
|
2011-01-04 16:05:53 +01:00
|
|
|
} else if (state == InferiorRunOk) {
|
2010-12-02 13:20:06 +01:00
|
|
|
// Shift-F5 interrupts. It is also "interruptible".
|
2011-02-03 14:08:01 +01:00
|
|
|
m_interruptAction->setEnabled(true);
|
|
|
|
|
m_continueAction->setEnabled(false);
|
2011-08-03 18:57:37 +02:00
|
|
|
m_exitAction->setEnabled(true);
|
|
|
|
|
m_startAction->setEnabled(false);
|
2011-10-25 18:23:37 +08:00
|
|
|
m_debugWithoutDeployAction->setEnabled(false);
|
2012-05-24 10:19:50 +02:00
|
|
|
setProxyAction(m_visibleStartAction, Constants::INTERRUPT);
|
2011-08-03 18:57:37 +02:00
|
|
|
m_hiddenStopAction->setAction(m_interruptAction);
|
2012-05-14 16:09:12 +02:00
|
|
|
m_localsAndExpressionsWindow->setShowLocals(false);
|
2011-01-04 16:05:53 +01:00
|
|
|
} else if (state == DebuggerFinished) {
|
2010-12-02 13:20:06 +01:00
|
|
|
// We don't want to do anything anymore.
|
2011-02-03 14:08:01 +01:00
|
|
|
m_interruptAction->setEnabled(false);
|
|
|
|
|
m_continueAction->setEnabled(false);
|
|
|
|
|
m_exitAction->setEnabled(false);
|
2011-08-03 18:57:37 +02:00
|
|
|
m_startAction->setEnabled(true);
|
2011-10-25 18:23:37 +08:00
|
|
|
m_debugWithoutDeployAction->setEnabled(true);
|
2012-05-24 10:19:50 +02:00
|
|
|
setProxyAction(m_visibleStartAction, Constants::DEBUG);
|
2011-08-03 18:57:37 +02:00
|
|
|
m_hiddenStopAction->setAction(m_undisturbableAction);
|
2010-12-02 13:20:06 +01:00
|
|
|
m_codeModelSnapshot = CPlusPlus::Snapshot();
|
|
|
|
|
setBusyCursor(false);
|
|
|
|
|
cleanupViews();
|
2011-01-04 16:05:53 +01:00
|
|
|
} else if (state == InferiorUnrunnable) {
|
2010-12-02 13:20:06 +01:00
|
|
|
// We don't want to do anything anymore.
|
2011-02-03 14:08:01 +01:00
|
|
|
m_interruptAction->setEnabled(false);
|
|
|
|
|
m_continueAction->setEnabled(false);
|
|
|
|
|
m_exitAction->setEnabled(true);
|
2011-08-03 18:57:37 +02:00
|
|
|
m_startAction->setEnabled(false);
|
2011-10-25 18:23:37 +08:00
|
|
|
m_debugWithoutDeployAction->setEnabled(false);
|
2012-01-11 19:29:01 +01:00
|
|
|
m_visibleStartAction->setAction(m_undisturbableAction);
|
|
|
|
|
m_hiddenStopAction->setAction(m_exitAction);
|
2012-05-14 16:03:44 +02:00
|
|
|
// show locals in core dumps
|
2012-05-14 16:09:12 +02:00
|
|
|
m_localsAndExpressionsWindow->setShowLocals(true);
|
2010-12-02 13:20:06 +01:00
|
|
|
} else {
|
|
|
|
|
// Everything else is "undisturbable".
|
2011-02-03 14:08:01 +01:00
|
|
|
m_interruptAction->setEnabled(false);
|
|
|
|
|
m_continueAction->setEnabled(false);
|
|
|
|
|
m_exitAction->setEnabled(false);
|
2011-08-03 18:57:37 +02:00
|
|
|
m_startAction->setEnabled(false);
|
2011-10-25 18:23:37 +08:00
|
|
|
m_debugWithoutDeployAction->setEnabled(false);
|
2011-08-03 18:57:37 +02:00
|
|
|
m_visibleStartAction->setAction(m_undisturbableAction);
|
|
|
|
|
m_hiddenStopAction->setAction(m_undisturbableAction);
|
2010-12-02 13:20:06 +01:00
|
|
|
}
|
2010-03-18 10:56:25 +01:00
|
|
|
|
2012-08-08 13:09:31 +02:00
|
|
|
m_startAndDebugApplicationAction->setEnabled(true);
|
2011-09-13 17:26:02 +02:00
|
|
|
m_attachToQmlPortAction->setEnabled(true);
|
2011-12-05 17:21:48 +01:00
|
|
|
m_attachToCoreAction->setEnabled(true);
|
|
|
|
|
m_attachToRemoteServerAction->setEnabled(true);
|
2012-08-06 12:22:35 +02:00
|
|
|
m_attachToRunningApplication->setEnabled(true);
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2012-03-26 17:30:57 +02:00
|
|
|
m_threadBox->setEnabled(state == InferiorStopOk);
|
|
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
const bool isCore = engine->startParameters().startMode == AttachCore;
|
2011-01-04 16:05:53 +01:00
|
|
|
const bool stopped = state == InferiorStopOk;
|
2010-12-02 13:20:06 +01:00
|
|
|
const bool detachable = stopped && !isCore;
|
|
|
|
|
m_detachAction->setEnabled(detachable);
|
2010-03-18 10:56:25 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
if (stopped)
|
|
|
|
|
QApplication::alert(mainWindow(), 3000);
|
2010-02-15 16:02:41 +01:00
|
|
|
|
2012-01-12 20:28:17 +01:00
|
|
|
const bool canReverse = engine->hasCapability(ReverseSteppingCapability)
|
2010-12-02 13:20:06 +01:00
|
|
|
&& boolSetting(EnableReverseDebugging);
|
2011-02-03 14:08:01 +01:00
|
|
|
m_reverseDirectionAction->setEnabled(canReverse);
|
2010-03-18 10:56:25 +01:00
|
|
|
|
2011-02-03 14:08:01 +01:00
|
|
|
m_watchAction1->setEnabled(true);
|
|
|
|
|
m_watchAction2->setEnabled(true);
|
|
|
|
|
m_breakAction->setEnabled(true);
|
2009-05-25 17:19:42 +02:00
|
|
|
|
2012-01-12 20:28:17 +01:00
|
|
|
const bool canOperateByInstruction = engine->hasCapability(OperateByInstructionCapability)
|
2011-04-01 19:47:39 +02:00
|
|
|
&& (stopped || isCore);
|
|
|
|
|
action(OperateByInstruction)->setEnabled(canOperateByInstruction);
|
2010-03-18 10:56:25 +01:00
|
|
|
|
2011-10-31 16:15:48 +01:00
|
|
|
m_abortAction->setEnabled(state != DebuggerNotReady
|
2011-01-04 16:05:53 +01:00
|
|
|
&& state != DebuggerFinished);
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2011-05-02 18:22:32 +02:00
|
|
|
m_stepAction->setEnabled(stopped || state == DebuggerNotReady);
|
|
|
|
|
m_nextAction->setEnabled(stopped || state == DebuggerNotReady);
|
2011-07-18 17:23:42 +02:00
|
|
|
m_stepAction->setToolTip(QString());
|
|
|
|
|
m_nextAction->setToolTip(QString());
|
2011-05-02 18:22:32 +02:00
|
|
|
|
2011-02-03 14:08:01 +01:00
|
|
|
m_stepOutAction->setEnabled(stopped);
|
2012-01-12 20:28:17 +01:00
|
|
|
m_runToLineAction->setEnabled(stopped && engine->hasCapability(RunToLineCapability));
|
2011-02-03 14:08:01 +01:00
|
|
|
m_runToSelectedFunctionAction->setEnabled(stopped);
|
|
|
|
|
m_returnFromFunctionAction->
|
2012-01-12 20:28:17 +01:00
|
|
|
setEnabled(stopped && engine->hasCapability(ReturnFromFunctionCapability));
|
2010-03-18 10:56:25 +01:00
|
|
|
|
2012-01-12 20:28:17 +01:00
|
|
|
const bool canJump = stopped && engine->hasCapability(JumpToLineCapability);
|
2011-02-03 14:08:01 +01:00
|
|
|
m_jumpToLineAction->setEnabled(canJump);
|
2010-06-07 13:17:19 +02:00
|
|
|
|
2012-01-12 20:28:17 +01:00
|
|
|
const bool canDeref = actionsEnabled && engine->hasCapability(AutoDerefPointersCapability);
|
2010-12-02 13:20:06 +01:00
|
|
|
action(AutoDerefPointers)->setEnabled(canDeref);
|
|
|
|
|
action(AutoDerefPointers)->setEnabled(true);
|
|
|
|
|
action(ExpandStack)->setEnabled(actionsEnabled);
|
2010-03-18 10:56:25 +01:00
|
|
|
|
2011-01-04 16:05:53 +01:00
|
|
|
const bool notbusy = state == InferiorStopOk
|
|
|
|
|
|| state == DebuggerNotReady
|
|
|
|
|
|| state == DebuggerFinished
|
|
|
|
|
|| state == InferiorUnrunnable;
|
2010-12-02 13:20:06 +01:00
|
|
|
setBusyCursor(!notbusy);
|
|
|
|
|
}
|
2010-03-18 10:56:25 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
void DebuggerPluginPrivate::updateDebugActions()
|
|
|
|
|
{
|
2011-10-13 13:22:26 +02:00
|
|
|
//if we're currently debugging the actions are controlled by engine
|
|
|
|
|
if (m_currentEngine->state() != DebuggerNotReady)
|
|
|
|
|
return;
|
|
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
ProjectExplorerPlugin *pe = ProjectExplorerPlugin::instance();
|
|
|
|
|
Project *project = pe->startupProject();
|
2012-01-10 19:17:24 +01:00
|
|
|
const bool canRun = pe->canRun(project, DebugRunMode);
|
2011-08-03 18:57:37 +02:00
|
|
|
m_startAction->setEnabled(canRun);
|
2012-01-10 19:17:24 +01:00
|
|
|
m_startAction->setToolTip(canRun ? QString() : pe->cannotRunReason(project, DebugRunMode));
|
2011-10-25 18:23:37 +08:00
|
|
|
m_debugWithoutDeployAction->setEnabled(canRun);
|
2011-07-18 17:23:42 +02:00
|
|
|
|
|
|
|
|
// Step into/next: Start and break at 'main' unless a debugger is running.
|
|
|
|
|
if (m_snapshotHandler->currentIndex() < 0) {
|
2012-01-10 19:17:24 +01:00
|
|
|
const bool canRunAndBreakMain = pe->canRun(project, DebugRunModeWithBreakOnMain);
|
2011-07-18 17:23:42 +02:00
|
|
|
m_stepAction->setEnabled(canRunAndBreakMain);
|
|
|
|
|
m_nextAction->setEnabled(canRunAndBreakMain);
|
|
|
|
|
QString toolTip;
|
|
|
|
|
if (canRunAndBreakMain) {
|
|
|
|
|
QTC_ASSERT(project, return ; );
|
|
|
|
|
toolTip = tr("Start '%1' and break at function 'main()'")
|
|
|
|
|
.arg(project->displayName());
|
|
|
|
|
} else {
|
2012-01-10 19:17:24 +01:00
|
|
|
// Do not display long tooltip saying run mode is not supported
|
|
|
|
|
// for project for projects to which 'break at main' is not applicable.
|
2011-07-18 17:23:42 +02:00
|
|
|
if (!canRun)
|
2012-01-10 19:17:24 +01:00
|
|
|
toolTip = pe->cannotRunReason(project, DebugRunModeWithBreakOnMain);
|
2011-07-18 17:23:42 +02:00
|
|
|
}
|
|
|
|
|
m_stepAction->setToolTip(toolTip);
|
|
|
|
|
m_nextAction->setToolTip(toolTip);
|
|
|
|
|
}
|
2010-12-02 13:20:06 +01:00
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2011-01-31 15:17:53 +01:00
|
|
|
void DebuggerPluginPrivate::onCoreAboutToOpen()
|
|
|
|
|
{
|
2012-01-26 01:18:02 +01:00
|
|
|
m_mainWindow->onModeChanged(ModeManager::currentMode());
|
2011-01-31 15:17:53 +01:00
|
|
|
}
|
|
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
void DebuggerPluginPrivate::onModeChanged(IMode *mode)
|
|
|
|
|
{
|
|
|
|
|
// FIXME: This one gets always called, even if switching between modes
|
|
|
|
|
// different then the debugger mode. E.g. Welcome and Help mode and
|
|
|
|
|
// also on shutdown.
|
2009-12-11 18:19:51 +01:00
|
|
|
|
2010-12-02 17:33:39 +01:00
|
|
|
m_mainWindow->onModeChanged(mode);
|
2010-02-08 09:13:21 +01:00
|
|
|
|
2012-05-07 18:28:03 +02:00
|
|
|
if (mode->id() != Constants::MODE_DEBUG) {
|
2011-02-11 15:00:13 +01:00
|
|
|
m_toolTipManager->leavingDebugMode();
|
2010-12-02 13:20:06 +01:00
|
|
|
return;
|
2011-02-11 15:00:13 +01:00
|
|
|
}
|
2010-02-08 09:13:21 +01:00
|
|
|
|
2012-05-08 09:43:14 +02:00
|
|
|
if (IEditor *editor = EditorManager::currentEditor())
|
|
|
|
|
editor->widget()->setFocus();
|
|
|
|
|
|
2011-02-11 15:00:13 +01:00
|
|
|
m_toolTipManager->debugModeEntered();
|
2010-12-02 13:20:06 +01:00
|
|
|
}
|
2010-11-26 15:10:10 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
void DebuggerPluginPrivate::showSettingsDialog()
|
|
|
|
|
{
|
2012-01-24 15:36:40 +01:00
|
|
|
ICore::showOptionsDialog(
|
2010-12-02 13:20:06 +01:00
|
|
|
_(DEBUGGER_SETTINGS_CATEGORY),
|
|
|
|
|
_(DEBUGGER_COMMON_SETTINGS_ID));
|
|
|
|
|
}
|
2010-04-06 16:42:24 +02:00
|
|
|
|
2011-10-25 18:23:37 +08:00
|
|
|
void DebuggerPluginPrivate::updateDebugWithoutDeployMenu()
|
|
|
|
|
{
|
|
|
|
|
const bool state = ProjectExplorerPlugin::instance()->projectExplorerSettings().deployBeforeRun;
|
|
|
|
|
m_debugWithoutDeployAction->setVisible(state);
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
void DebuggerPluginPrivate::dumpLog()
|
|
|
|
|
{
|
|
|
|
|
QString fileName = QFileDialog::getSaveFileName(mainWindow(),
|
|
|
|
|
tr("Save Debugger Log"), QDir::tempPath());
|
|
|
|
|
if (fileName.isEmpty())
|
|
|
|
|
return;
|
2012-08-15 16:19:15 +02:00
|
|
|
FileSaver saver(fileName);
|
2011-03-30 15:15:15 +02:00
|
|
|
if (!saver.hasError()) {
|
|
|
|
|
QTextStream ts(saver.file());
|
|
|
|
|
ts << m_logWindow->inputContents();
|
|
|
|
|
ts << "\n\n=======================================\n\n";
|
|
|
|
|
ts << m_logWindow->combinedContents();
|
|
|
|
|
saver.setResult(&ts);
|
|
|
|
|
}
|
|
|
|
|
saver.finalize(mainWindow());
|
2010-12-02 13:20:06 +01:00
|
|
|
}
|
2009-01-13 18:15:24 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
/*! Activates the previous mode when the current mode is the debug mode. */
|
|
|
|
|
void DebuggerPluginPrivate::activatePreviousMode()
|
|
|
|
|
{
|
2012-05-07 18:28:03 +02:00
|
|
|
if (ModeManager::currentMode() == ModeManager::mode(MODE_DEBUG)
|
|
|
|
|
&& m_previousMode.isValid()) {
|
2012-01-26 01:18:02 +01:00
|
|
|
ModeManager::activateMode(m_previousMode);
|
2012-05-07 18:28:03 +02:00
|
|
|
m_previousMode = Id();
|
2010-12-02 13:20:06 +01:00
|
|
|
}
|
|
|
|
|
}
|
2009-01-13 18:15:24 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
void DebuggerPluginPrivate::activateDebugMode()
|
|
|
|
|
{
|
2011-02-03 14:08:01 +01:00
|
|
|
m_reverseDirectionAction->setChecked(false);
|
|
|
|
|
m_reverseDirectionAction->setEnabled(false);
|
2012-01-26 01:18:02 +01:00
|
|
|
m_previousMode = ModeManager::currentMode()->id();
|
2012-05-07 18:28:03 +02:00
|
|
|
ModeManager::activateMode(MODE_DEBUG);
|
2010-12-02 13:20:06 +01:00
|
|
|
}
|
2010-02-12 14:15:20 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
void DebuggerPluginPrivate::sessionLoaded()
|
|
|
|
|
{
|
|
|
|
|
m_breakHandler->loadSessionData();
|
|
|
|
|
dummyEngine()->watchHandler()->loadSessionData();
|
2011-02-11 15:00:13 +01:00
|
|
|
m_toolTipManager->loadSessionData();
|
2010-12-02 13:20:06 +01:00
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
void DebuggerPluginPrivate::aboutToUnloadSession()
|
|
|
|
|
{
|
|
|
|
|
m_breakHandler->removeSessionData();
|
2011-02-11 15:00:13 +01:00
|
|
|
m_toolTipManager->sessionAboutToChange();
|
2010-12-02 13:20:06 +01:00
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
void DebuggerPluginPrivate::aboutToSaveSession()
|
|
|
|
|
{
|
2011-02-28 18:48:06 +01:00
|
|
|
dummyEngine()->watchHandler()->saveSessionData();
|
2011-02-11 15:00:13 +01:00
|
|
|
m_toolTipManager->saveSessionData();
|
2010-12-02 13:20:06 +01:00
|
|
|
m_breakHandler->saveSessionData();
|
|
|
|
|
}
|
2009-02-27 11:41:19 +01:00
|
|
|
|
2012-04-10 09:36:15 +02:00
|
|
|
void DebuggerPluginPrivate::executeDebuggerCommand(const QString &command, DebuggerLanguages languages)
|
2010-12-02 13:20:06 +01:00
|
|
|
{
|
2011-02-16 12:41:06 +01:00
|
|
|
if (currentEngine()->acceptsDebuggerCommands())
|
2012-04-10 09:36:15 +02:00
|
|
|
currentEngine()->executeDebuggerCommand(command, languages);
|
2011-02-16 12:41:06 +01:00
|
|
|
else
|
|
|
|
|
showStatusMessage(tr("User commands are not accepted in the current state."));
|
2010-12-02 13:20:06 +01:00
|
|
|
}
|
2010-03-10 13:46:05 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
void DebuggerPluginPrivate::showStatusMessage(const QString &msg0, int timeout)
|
|
|
|
|
{
|
|
|
|
|
showMessage(msg0, LogStatus);
|
|
|
|
|
QString msg = msg0;
|
2011-03-16 13:49:28 +01:00
|
|
|
msg.remove(QLatin1Char('\n'));
|
|
|
|
|
m_statusLabel->showStatusMessage(msg, timeout);
|
2010-12-02 13:20:06 +01:00
|
|
|
}
|
2010-03-11 11:07:16 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
void DebuggerPluginPrivate::openMemoryEditor()
|
|
|
|
|
{
|
|
|
|
|
AddressDialog dialog;
|
|
|
|
|
if (dialog.exec() == QDialog::Accepted)
|
2011-04-19 12:17:48 +02:00
|
|
|
currentEngine()->openMemoryView(dialog.address(), 0, QList<MemoryMarkup>(), QPoint());
|
2010-12-02 13:20:06 +01:00
|
|
|
}
|
2010-02-09 20:44:40 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
void DebuggerPluginPrivate::coreShutdown()
|
|
|
|
|
{
|
|
|
|
|
m_shuttingDown = true;
|
|
|
|
|
}
|
2010-03-10 13:46:05 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
const CPlusPlus::Snapshot &DebuggerPluginPrivate::cppCodeModelSnapshot() const
|
|
|
|
|
{
|
|
|
|
|
if (m_codeModelSnapshot.isEmpty() && action(UseCodeModel)->isChecked())
|
2010-12-03 13:49:35 +01:00
|
|
|
m_codeModelSnapshot = CPlusPlus::CppModelManagerInterface::instance()->snapshot();
|
2010-12-02 13:20:06 +01:00
|
|
|
return m_codeModelSnapshot;
|
|
|
|
|
}
|
2010-03-11 11:07:16 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
void DebuggerPluginPrivate::setSessionValue(const QString &name, const QVariant &value)
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(sessionManager(), return);
|
|
|
|
|
sessionManager()->setValue(name, value);
|
|
|
|
|
//qDebug() << "SET SESSION VALUE: " << name;
|
|
|
|
|
}
|
2010-11-23 16:42:46 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
QVariant DebuggerPluginPrivate::sessionValue(const QString &name)
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(sessionManager(), return QVariant());
|
|
|
|
|
//qDebug() << "GET SESSION VALUE: " << name;
|
|
|
|
|
return sessionManager()->value(name);
|
2010-02-09 20:44:40 +01:00
|
|
|
}
|
|
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
void DebuggerPluginPrivate::openTextEditor(const QString &titlePattern0,
|
|
|
|
|
const QString &contents)
|
2010-09-27 12:23:34 +02:00
|
|
|
{
|
2010-12-02 13:20:06 +01:00
|
|
|
if (m_shuttingDown)
|
|
|
|
|
return;
|
|
|
|
|
QString titlePattern = titlePattern0;
|
2012-05-08 09:43:14 +02:00
|
|
|
IEditor *editor = EditorManager::openEditorWithContents(
|
2010-12-02 13:20:06 +01:00
|
|
|
CC::K_DEFAULT_TEXT_EDITOR_ID, &titlePattern, contents);
|
|
|
|
|
QTC_ASSERT(editor, return);
|
2012-05-08 09:43:14 +02:00
|
|
|
EditorManager::activateEditor(editor, EditorManager::IgnoreNavigationHistory);
|
2010-09-27 12:23:34 +02:00
|
|
|
}
|
|
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
void DebuggerPluginPrivate::showMessage(const QString &msg, int channel, int timeout)
|
2010-07-21 17:06:22 +02:00
|
|
|
{
|
2010-12-02 13:20:06 +01:00
|
|
|
//qDebug() << "PLUGIN OUTPUT: " << channel << msg;
|
|
|
|
|
//ConsoleWindow *cw = m_consoleWindow;
|
|
|
|
|
QTC_ASSERT(m_logWindow, return);
|
|
|
|
|
switch (channel) {
|
|
|
|
|
case StatusBar:
|
|
|
|
|
// This will append to m_logWindow's output pane, too.
|
|
|
|
|
showStatusMessage(msg, timeout);
|
|
|
|
|
break;
|
|
|
|
|
case LogMiscInput:
|
|
|
|
|
m_logWindow->showInput(LogMisc, msg);
|
|
|
|
|
m_logWindow->showOutput(LogMisc, msg);
|
|
|
|
|
break;
|
|
|
|
|
case LogInput:
|
|
|
|
|
m_logWindow->showInput(LogInput, msg);
|
|
|
|
|
m_logWindow->showOutput(LogInput, msg);
|
|
|
|
|
break;
|
2012-02-22 12:46:47 +01:00
|
|
|
case LogError:
|
|
|
|
|
m_logWindow->showInput(LogError, QLatin1String("ERROR: ") + msg);
|
|
|
|
|
m_logWindow->showOutput(LogError, QLatin1String("ERROR: ") + msg);
|
2010-12-02 13:20:06 +01:00
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
m_logWindow->showOutput(channel, msg);
|
|
|
|
|
break;
|
2010-07-21 17:06:22 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-03 15:55:17 +01:00
|
|
|
void DebuggerPluginPrivate::createNewDock(QWidget *widget)
|
2010-12-02 13:20:06 +01:00
|
|
|
{
|
|
|
|
|
QDockWidget *dockWidget =
|
2010-12-03 15:55:17 +01:00
|
|
|
m_mainWindow->createDockWidget(CppLanguage, widget);
|
2010-12-02 13:20:06 +01:00
|
|
|
dockWidget->setWindowTitle(widget->windowTitle());
|
|
|
|
|
dockWidget->setFeatures(QDockWidget::DockWidgetClosable);
|
|
|
|
|
dockWidget->show();
|
|
|
|
|
}
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2011-02-25 13:43:06 +01:00
|
|
|
static QString formatStartParameters(DebuggerStartParameters &sp)
|
|
|
|
|
{
|
|
|
|
|
QString rc;
|
|
|
|
|
QTextStream str(&rc);
|
|
|
|
|
str << "Start parameters: '" << sp.displayName << "' mode: " << sp.startMode
|
|
|
|
|
<< "\nABI: " << sp.toolChainAbi.toString() << '\n';
|
2012-02-01 09:03:05 +01:00
|
|
|
str << "Languages: ";
|
|
|
|
|
if (sp.languages == AnyLanguage)
|
|
|
|
|
str << "any";
|
|
|
|
|
if (sp.languages & CppLanguage)
|
|
|
|
|
str << "c++ ";
|
|
|
|
|
if (sp.languages & QmlLanguage)
|
|
|
|
|
str << "qml";
|
|
|
|
|
str << '\n';
|
2011-02-25 13:43:06 +01:00
|
|
|
if (!sp.executable.isEmpty()) {
|
2011-09-26 12:38:17 +02:00
|
|
|
str << "Executable: " << QDir::toNativeSeparators(sp.executable)
|
|
|
|
|
<< ' ' << sp.processArgs;
|
2011-02-25 13:43:06 +01:00
|
|
|
if (sp.useTerminal)
|
|
|
|
|
str << " [terminal]";
|
|
|
|
|
str << '\n';
|
|
|
|
|
if (!sp.workingDirectory.isEmpty())
|
2011-09-26 12:38:17 +02:00
|
|
|
str << "Directory: " << QDir::toNativeSeparators(sp.workingDirectory)
|
|
|
|
|
<< '\n';
|
2011-02-25 13:43:06 +01:00
|
|
|
}
|
2012-06-28 10:00:04 +02:00
|
|
|
QString cmd = sp.debuggerCommand;
|
|
|
|
|
if (!cmd.isEmpty())
|
|
|
|
|
str << "Debugger: " << QDir::toNativeSeparators(cmd) << '\n';
|
2011-02-25 13:43:06 +01:00
|
|
|
if (!sp.coreFile.isEmpty())
|
|
|
|
|
str << "Core: " << QDir::toNativeSeparators(sp.coreFile) << '\n';
|
|
|
|
|
if (sp.attachPID > 0)
|
|
|
|
|
str << "PID: " << sp.attachPID << ' ' << sp.crashParameter << '\n';
|
2011-04-26 09:46:05 +02:00
|
|
|
if (!sp.projectSourceDirectory.isEmpty()) {
|
|
|
|
|
str << "Project: " << QDir::toNativeSeparators(sp.projectSourceDirectory);
|
|
|
|
|
if (!sp.projectBuildDirectory.isEmpty())
|
2011-09-26 12:38:17 +02:00
|
|
|
str << " (built: " << QDir::toNativeSeparators(sp.projectBuildDirectory)
|
|
|
|
|
<< ')';
|
2011-02-25 13:43:06 +01:00
|
|
|
str << '\n';
|
|
|
|
|
}
|
|
|
|
|
if (!sp.qmlServerAddress.isEmpty())
|
2011-09-26 12:38:17 +02:00
|
|
|
str << "QML server: " << sp.qmlServerAddress << ':'
|
|
|
|
|
<< sp.qmlServerPort << '\n';
|
2011-02-25 13:43:06 +01:00
|
|
|
if (!sp.remoteChannel.isEmpty()) {
|
2012-07-25 03:38:19 +02:00
|
|
|
str << "Remote: " << sp.remoteChannel << '\n';
|
2011-02-25 13:43:06 +01:00
|
|
|
if (!sp.remoteSourcesDir.isEmpty())
|
|
|
|
|
str << "Remote sources: " << sp.remoteSourcesDir << '\n';
|
|
|
|
|
if (!sp.remoteMountPoint.isEmpty())
|
2011-09-26 12:38:17 +02:00
|
|
|
str << "Remote mount point: " << sp.remoteMountPoint
|
|
|
|
|
<< " Local: " << sp.localMountDir << '\n';
|
2011-02-25 13:43:06 +01:00
|
|
|
}
|
2012-06-28 10:00:04 +02:00
|
|
|
str << "Sysroot: " << sp.sysRoot << '\n';
|
2011-12-21 14:02:52 +01:00
|
|
|
str << "Debug Source Location: " << sp.debugSourceLocation.join(QLatin1String(":")) << '\n';
|
2011-09-26 12:38:17 +02:00
|
|
|
str << "Symbol file: " << sp.symbolFileName << '\n';
|
|
|
|
|
str << "Dumper libraries: " << QDir::toNativeSeparators(sp.dumperLibrary);
|
|
|
|
|
foreach (const QString &dl, sp.dumperLibraryLocations)
|
|
|
|
|
str << ' ' << QDir::toNativeSeparators(dl);
|
|
|
|
|
str << '\n';
|
2011-02-25 13:43:06 +01:00
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-10 10:01:29 +01:00
|
|
|
void DebuggerPluginPrivate::runControlStarted(DebuggerEngine *engine)
|
2010-12-02 13:20:06 +01:00
|
|
|
{
|
|
|
|
|
activateDebugMode();
|
2012-03-07 16:40:54 +01:00
|
|
|
const QString message = tr("Starting debugger \"%1\" for ABI \"%2\"...")
|
2011-02-01 18:36:00 +01:00
|
|
|
.arg(engine->objectName())
|
|
|
|
|
.arg(engine->startParameters().toolChainAbi.toString());
|
2012-03-07 16:40:54 +01:00
|
|
|
showStatusMessage(message);
|
2011-02-25 13:43:06 +01:00
|
|
|
showMessage(formatStartParameters(engine->startParameters()), LogDebug);
|
2010-12-02 13:20:06 +01:00
|
|
|
showMessage(m_debuggerSettings->dump(), LogDebug);
|
2010-12-10 10:01:29 +01:00
|
|
|
m_snapshotHandler->appendSnapshot(engine);
|
2010-12-10 09:37:31 +01:00
|
|
|
connectEngine(engine);
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2010-12-10 10:01:29 +01:00
|
|
|
void DebuggerPluginPrivate::runControlFinished(DebuggerEngine *engine)
|
2010-04-06 17:58:11 +02:00
|
|
|
{
|
2011-02-22 18:45:52 +01:00
|
|
|
showStatusMessage(tr("Debugger finished."));
|
2010-12-10 10:01:29 +01:00
|
|
|
m_snapshotHandler->removeSnapshot(engine);
|
2010-12-02 13:20:06 +01:00
|
|
|
if (m_snapshotHandler->size() == 0) {
|
|
|
|
|
// Last engine quits.
|
|
|
|
|
disconnectEngine();
|
|
|
|
|
if (boolSetting(SwitchModeOnExit))
|
|
|
|
|
activatePreviousMode();
|
|
|
|
|
} else {
|
|
|
|
|
// Connect to some existing engine.
|
|
|
|
|
m_snapshotHandler->activateSnapshot(0);
|
|
|
|
|
}
|
2011-05-02 15:05:16 +02:00
|
|
|
action(OperateByInstruction)->setValue(QVariant(false));
|
2010-04-06 17:58:11 +02:00
|
|
|
}
|
|
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
void DebuggerPluginPrivate::remoteCommand(const QStringList &options,
|
|
|
|
|
const QStringList &)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2010-12-02 13:20:06 +01:00
|
|
|
if (options.isEmpty())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
QString errorMessage;
|
|
|
|
|
|
2012-08-09 01:50:26 +02:00
|
|
|
if (!parseArguments(options, &errorMessage)) {
|
2010-12-02 13:20:06 +01:00
|
|
|
qWarning("%s", qPrintable(errorMessage));
|
2010-06-16 11:08:54 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2011-02-08 13:48:04 +01:00
|
|
|
runScheduled();
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
DebuggerLanguages DebuggerPluginPrivate::activeLanguages() const
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2010-12-06 08:43:29 +01:00
|
|
|
QTC_ASSERT(m_mainWindow, return AnyLanguage);
|
2010-12-02 17:33:39 +01:00
|
|
|
return m_mainWindow->activeDebugLanguages();
|
2010-07-15 10:44:53 +02:00
|
|
|
}
|
|
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
bool DebuggerPluginPrivate::isReverseDebugging() const
|
2010-07-15 10:44:53 +02:00
|
|
|
{
|
2011-02-03 14:08:01 +01:00
|
|
|
return m_reverseDirectionAction->isChecked();
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
QMessageBox *showMessageBox(int icon, const QString &title,
|
|
|
|
|
const QString &text, int buttons)
|
2010-11-19 16:13:22 +01:00
|
|
|
{
|
2010-12-02 13:20:06 +01:00
|
|
|
QMessageBox *mb = new QMessageBox(QMessageBox::Icon(icon),
|
|
|
|
|
title, text, QMessageBox::StandardButtons(buttons),
|
|
|
|
|
debuggerCore()->mainWindow());
|
|
|
|
|
mb->setAttribute(Qt::WA_DeleteOnClose);
|
|
|
|
|
mb->show();
|
|
|
|
|
return mb;
|
2010-11-19 16:13:22 +01:00
|
|
|
}
|
|
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
void DebuggerPluginPrivate::extensionsInitialized()
|
2010-12-01 15:41:08 +01:00
|
|
|
{
|
2012-05-23 13:25:51 +02:00
|
|
|
const QKeySequence debugKey = QKeySequence(UseMacShortcuts ? tr("Ctrl+Y") : tr("F5"));
|
|
|
|
|
|
2012-01-24 15:36:40 +01:00
|
|
|
m_coreSettings = ICore::settings();
|
2011-07-08 15:33:13 +02:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
m_debuggerSettings = new DebuggerSettings(m_coreSettings);
|
2011-07-08 15:33:13 +02:00
|
|
|
m_debuggerSettings->readSettings();
|
2010-12-01 15:41:08 +01:00
|
|
|
|
2012-01-24 15:36:40 +01:00
|
|
|
connect(ICore::instance(), SIGNAL(coreAboutToClose()), this, SLOT(coreShutdown()));
|
2010-12-01 15:41:08 +01:00
|
|
|
|
2011-05-31 09:48:00 +02:00
|
|
|
m_plugin->addObject(this);
|
|
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
const Context globalcontext(CC::C_GLOBAL);
|
|
|
|
|
const Context cppDebuggercontext(C_CPPDEBUGGER);
|
|
|
|
|
const Context cppeditorcontext(CppEditor::Constants::C_CPPEDITOR);
|
2010-05-12 16:48:04 +02:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
m_startIcon = QIcon(_(":/debugger/images/debugger_start_small.png"));
|
2012-02-16 11:12:02 +01:00
|
|
|
m_startIcon.addFile(QLatin1String(":/debugger/images/debugger_start.png"));
|
2010-12-02 13:20:06 +01:00
|
|
|
m_exitIcon = QIcon(_(":/debugger/images/debugger_stop_small.png"));
|
2012-02-16 11:12:02 +01:00
|
|
|
m_exitIcon.addFile(QLatin1String(":/debugger/images/debugger_stop.png"));
|
|
|
|
|
m_continueIcon = QIcon(QLatin1String(":/debugger/images/debugger_continue_small.png"));
|
|
|
|
|
m_continueIcon.addFile(QLatin1String(":/debugger/images/debugger_continue.png"));
|
2010-12-02 13:20:06 +01:00
|
|
|
m_interruptIcon = QIcon(_(":/debugger/images/debugger_interrupt_small.png"));
|
2012-02-16 11:12:02 +01:00
|
|
|
m_interruptIcon.addFile(QLatin1String(":/debugger/images/debugger_interrupt.png"));
|
2010-12-02 13:20:06 +01:00
|
|
|
m_locationMarkIcon = QIcon(_(":/debugger/images/location_16.png"));
|
|
|
|
|
|
|
|
|
|
m_busy = false;
|
|
|
|
|
|
2012-08-15 16:19:15 +02:00
|
|
|
m_statusLabel = new StatusLabel;
|
2010-12-02 13:20:06 +01:00
|
|
|
|
|
|
|
|
m_breakHandler = new BreakHandler;
|
|
|
|
|
m_breakWindow = new BreakWindow;
|
2011-12-21 14:02:52 +01:00
|
|
|
m_breakWindow->setObjectName(QLatin1String(DOCKWIDGET_BREAK));
|
2010-12-02 13:20:06 +01:00
|
|
|
m_breakWindow->setModel(m_breakHandler->model());
|
|
|
|
|
|
|
|
|
|
m_modulesWindow = new ModulesWindow;
|
2011-12-21 14:02:52 +01:00
|
|
|
m_modulesWindow->setObjectName(QLatin1String(DOCKWIDGET_MODULES));
|
2010-12-02 13:20:06 +01:00
|
|
|
m_logWindow = new LogWindow;
|
2011-12-21 14:02:52 +01:00
|
|
|
m_logWindow->setObjectName(QLatin1String(DOCKWIDGET_OUTPUT));
|
2010-12-02 13:20:06 +01:00
|
|
|
m_registerWindow = new RegisterWindow;
|
2011-12-21 14:02:52 +01:00
|
|
|
m_registerWindow->setObjectName(QLatin1String(DOCKWIDGET_REGISTER));
|
2010-12-02 13:20:06 +01:00
|
|
|
m_stackWindow = new StackWindow;
|
2011-12-21 14:02:52 +01:00
|
|
|
m_stackWindow->setObjectName(QLatin1String(DOCKWIDGET_STACK));
|
2010-12-02 13:20:06 +01:00
|
|
|
m_sourceFilesWindow = new SourceFilesWindow;
|
2011-12-21 14:02:52 +01:00
|
|
|
m_sourceFilesWindow->setObjectName(QLatin1String(DOCKWIDGET_SOURCE_FILES));
|
2010-12-02 13:20:06 +01:00
|
|
|
m_threadsWindow = new ThreadsWindow;
|
2011-12-21 14:02:52 +01:00
|
|
|
m_threadsWindow->setObjectName(QLatin1String(DOCKWIDGET_THREADS));
|
2012-03-29 14:20:45 +02:00
|
|
|
m_returnWindow = new WatchWindow(WatchTreeView::ReturnType);
|
2010-12-02 13:20:06 +01:00
|
|
|
m_returnWindow->setObjectName(QLatin1String("CppDebugReturn"));
|
2012-03-29 14:20:45 +02:00
|
|
|
m_localsWindow = new WatchWindow(WatchTreeView::LocalsType);
|
2010-12-02 13:20:06 +01:00
|
|
|
m_localsWindow->setObjectName(QLatin1String("CppDebugLocals"));
|
2012-03-29 14:20:45 +02:00
|
|
|
m_watchersWindow = new WatchWindow(WatchTreeView::WatchersType);
|
2010-12-02 13:20:06 +01:00
|
|
|
m_watchersWindow->setObjectName(QLatin1String("CppDebugWatchers"));
|
2012-04-18 14:20:54 +02:00
|
|
|
m_inspectorWindow = new WatchWindow(WatchTreeView::InspectType);
|
|
|
|
|
m_inspectorWindow->setObjectName(QLatin1String("Inspector"));
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
// Snapshot
|
|
|
|
|
m_snapshotHandler = new SnapshotHandler;
|
|
|
|
|
m_snapshotWindow = new SnapshotWindow(m_snapshotHandler);
|
2011-12-21 14:02:52 +01:00
|
|
|
m_snapshotWindow->setObjectName(QLatin1String(DOCKWIDGET_SNAPSHOTS));
|
2010-12-02 13:20:06 +01:00
|
|
|
m_snapshotWindow->setModel(m_snapshotHandler->model());
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
// Watchers
|
|
|
|
|
connect(m_localsWindow->header(), SIGNAL(sectionResized(int,int,int)),
|
|
|
|
|
SLOT(updateWatchersHeader(int,int,int)), Qt::QueuedConnection);
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
QAction *act = 0;
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2011-02-03 14:08:01 +01:00
|
|
|
act = m_continueAction = new QAction(tr("Continue"), this);
|
2010-12-02 13:20:06 +01:00
|
|
|
act->setIcon(m_continueIcon);
|
|
|
|
|
connect(act, SIGNAL(triggered()), SLOT(handleExecContinue()));
|
2010-11-08 15:19:13 +01:00
|
|
|
|
2012-05-24 10:19:50 +02:00
|
|
|
act = m_exitAction = new QAction(tr("Stop Debugger"), this);
|
2010-12-02 13:20:06 +01:00
|
|
|
act->setIcon(m_exitIcon);
|
|
|
|
|
connect(act, SIGNAL(triggered()), SLOT(handleExecExit()));
|
2010-11-08 15:19:13 +01:00
|
|
|
|
2011-02-03 14:08:01 +01:00
|
|
|
act = m_interruptAction = new QAction(tr("Interrupt"), this);
|
2010-12-02 13:20:06 +01:00
|
|
|
act->setIcon(m_interruptIcon);
|
|
|
|
|
connect(act, SIGNAL(triggered()), SLOT(handleExecInterrupt()));
|
2010-11-08 15:19:13 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
// A "disabled pause" seems to be a good choice.
|
2011-02-03 14:08:01 +01:00
|
|
|
act = m_undisturbableAction = new QAction(tr("Debugger is Busy"), this);
|
2010-12-02 13:20:06 +01:00
|
|
|
act->setIcon(m_interruptIcon);
|
|
|
|
|
act->setEnabled(false);
|
2010-11-08 15:19:13 +01:00
|
|
|
|
2011-10-31 16:15:48 +01:00
|
|
|
act = m_abortAction = new QAction(tr("Abort Debugging"), this);
|
2010-12-02 13:20:06 +01:00
|
|
|
act->setToolTip(tr("Aborts debugging and "
|
|
|
|
|
"resets the debugger to the initial state."));
|
2011-10-31 16:15:48 +01:00
|
|
|
connect(act, SIGNAL(triggered()), SLOT(handleAbort()));
|
2010-11-10 16:33:11 +01:00
|
|
|
|
2011-02-03 14:08:01 +01:00
|
|
|
act = m_nextAction = new QAction(tr("Step Over"), this);
|
2012-02-16 11:12:02 +01:00
|
|
|
act->setIcon(QIcon(QLatin1String(":/debugger/images/debugger_stepover_small.png")));
|
2010-12-02 13:20:06 +01:00
|
|
|
connect(act, SIGNAL(triggered()), SLOT(handleExecNext()));
|
2009-04-28 15:08:52 +02:00
|
|
|
|
2011-02-03 14:08:01 +01:00
|
|
|
act = m_stepAction = new QAction(tr("Step Into"), this);
|
2012-02-16 11:12:02 +01:00
|
|
|
act->setIcon(QIcon(QLatin1String(":/debugger/images/debugger_stepinto_small.png")));
|
2010-12-02 13:20:06 +01:00
|
|
|
connect(act, SIGNAL(triggered()), SLOT(handleExecStep()));
|
2010-11-24 18:36:17 +01:00
|
|
|
|
2011-02-03 14:08:01 +01:00
|
|
|
act = m_stepOutAction = new QAction(tr("Step Out"), this);
|
2012-02-16 11:12:02 +01:00
|
|
|
act->setIcon(QIcon(QLatin1String(":/debugger/images/debugger_stepout_small.png")));
|
2010-12-02 13:20:06 +01:00
|
|
|
connect(act, SIGNAL(triggered()), SLOT(handleExecStepOut()));
|
2010-11-24 18:36:17 +01:00
|
|
|
|
2011-02-03 14:08:01 +01:00
|
|
|
act = m_runToLineAction = new QAction(tr("Run to Line"), this);
|
2010-12-02 13:20:06 +01:00
|
|
|
connect(act, SIGNAL(triggered()), SLOT(handleExecRunToLine()));
|
2010-06-11 12:38:54 +02:00
|
|
|
|
2011-02-03 14:08:01 +01:00
|
|
|
act = m_runToSelectedFunctionAction =
|
2011-02-02 11:52:39 +01:00
|
|
|
new QAction(tr("Run to Selected Function"), this);
|
|
|
|
|
connect(act, SIGNAL(triggered()), SLOT(handleExecRunToSelectedFunction()));
|
2010-11-24 18:36:17 +01:00
|
|
|
|
2011-02-03 14:08:01 +01:00
|
|
|
act = m_returnFromFunctionAction =
|
2010-12-02 13:20:06 +01:00
|
|
|
new QAction(tr("Immediately Return From Inner Function"), this);
|
|
|
|
|
connect(act, SIGNAL(triggered()), SLOT(handleExecReturn()));
|
|
|
|
|
|
2011-02-03 14:08:01 +01:00
|
|
|
act = m_jumpToLineAction = new QAction(tr("Jump to Line"), this);
|
2010-12-02 13:20:06 +01:00
|
|
|
connect(act, SIGNAL(triggered()), SLOT(handleExecJumpToLine()));
|
|
|
|
|
|
2011-02-03 14:08:01 +01:00
|
|
|
act = m_breakAction = new QAction(tr("Toggle Breakpoint"), this);
|
2010-12-02 13:20:06 +01:00
|
|
|
|
2012-05-14 11:21:01 +02:00
|
|
|
act = m_watchAction1 = new QAction(tr("Add Expression Evaluator"), this);
|
2010-12-02 13:20:06 +01:00
|
|
|
connect(act, SIGNAL(triggered()), SLOT(handleAddToWatchWindow()));
|
|
|
|
|
|
2012-05-14 11:21:01 +02:00
|
|
|
act = m_watchAction2 = new QAction(tr("Add Expression Evaluator"), this);
|
2010-12-02 13:20:06 +01:00
|
|
|
connect(act, SIGNAL(triggered()), SLOT(handleAddToWatchWindow()));
|
|
|
|
|
|
2011-02-03 14:08:01 +01:00
|
|
|
//m_snapshotAction = new QAction(tr("Create Snapshot"), this);
|
|
|
|
|
//m_snapshotAction->setProperty(Role, RequestCreateSnapshotRole);
|
|
|
|
|
//m_snapshotAction->setIcon(
|
2010-12-02 13:20:06 +01:00
|
|
|
// QIcon(__(":/debugger/images/debugger_snapshot_small.png")));
|
|
|
|
|
|
2011-02-03 14:08:01 +01:00
|
|
|
act = m_reverseDirectionAction =
|
2010-12-02 13:20:06 +01:00
|
|
|
new QAction(tr("Reverse Direction"), this);
|
|
|
|
|
act->setCheckable(true);
|
|
|
|
|
act->setChecked(false);
|
|
|
|
|
act->setCheckable(false);
|
2012-02-16 11:12:02 +01:00
|
|
|
act->setIcon(QIcon(QLatin1String(":/debugger/images/debugger_reversemode_16.png")));
|
2010-12-02 13:20:06 +01:00
|
|
|
act->setIconVisibleInMenu(false);
|
2010-06-11 12:38:54 +02:00
|
|
|
|
2011-02-03 14:08:01 +01:00
|
|
|
act = m_frameDownAction = new QAction(tr("Move to Called Frame"), this);
|
2010-12-02 13:20:06 +01:00
|
|
|
connect(act, SIGNAL(triggered()), SLOT(handleFrameDown()));
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2011-02-03 14:08:01 +01:00
|
|
|
act = m_frameUpAction = new QAction(tr("Move to Calling Frame"), this);
|
2010-12-02 13:20:06 +01:00
|
|
|
connect(act, SIGNAL(triggered()), SLOT(handleFrameUp()));
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
connect(action(OperateByInstruction), SIGNAL(triggered(bool)),
|
|
|
|
|
SLOT(handleOperateByInstructionTriggered(bool)));
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2012-04-18 14:20:54 +02:00
|
|
|
QAction *qmlSelectDummyAction = new QAction(tr("Select"), this);
|
|
|
|
|
qmlSelectDummyAction->setCheckable(true);
|
|
|
|
|
qmlSelectDummyAction->setIcon(QIcon(_(":/debugger/images/qml/select.png")));
|
|
|
|
|
qmlSelectDummyAction->setEnabled(false);
|
2012-07-18 16:20:19 +02:00
|
|
|
ActionManager::registerAction(qmlSelectDummyAction, Constants::QML_SELECTTOOL, globalcontext);
|
2012-04-18 14:20:54 +02:00
|
|
|
|
|
|
|
|
QAction *qmlZoomDummyAction = new QAction(tr("Zoom"), this);
|
|
|
|
|
qmlZoomDummyAction->setCheckable(true);
|
|
|
|
|
qmlZoomDummyAction->setIcon(QIcon(_(":/debugger/images/qml/zoom.png")));
|
|
|
|
|
qmlZoomDummyAction->setEnabled(false);
|
2012-07-18 16:20:19 +02:00
|
|
|
ActionManager::registerAction(qmlZoomDummyAction, Constants::QML_ZOOMTOOL, globalcontext);
|
2012-04-18 14:20:54 +02:00
|
|
|
|
2010-12-02 18:21:39 +01:00
|
|
|
ActionContainer *debugMenu =
|
2012-07-18 16:20:19 +02:00
|
|
|
ActionManager::actionContainer(ProjectExplorer::Constants::M_DEBUG);
|
2010-12-02 18:19:05 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
// Dock widgets
|
2010-12-03 15:03:51 +01:00
|
|
|
QDockWidget *dock = 0;
|
2010-12-03 15:55:17 +01:00
|
|
|
dock = m_mainWindow->createDockWidget(CppLanguage, m_modulesWindow);
|
2010-12-03 15:03:51 +01:00
|
|
|
connect(dock->toggleViewAction(), SIGNAL(toggled(bool)),
|
2010-12-02 13:20:06 +01:00
|
|
|
SLOT(modulesDockToggled(bool)), Qt::QueuedConnection);
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2010-12-03 15:55:17 +01:00
|
|
|
dock = m_mainWindow->createDockWidget(CppLanguage, m_registerWindow);
|
2010-12-03 15:03:51 +01:00
|
|
|
connect(dock->toggleViewAction(), SIGNAL(toggled(bool)),
|
2010-12-02 13:20:06 +01:00
|
|
|
SLOT(registerDockToggled(bool)), Qt::QueuedConnection);
|
2009-05-25 16:22:11 +02:00
|
|
|
|
2010-12-03 15:55:17 +01:00
|
|
|
dock = m_mainWindow->createDockWidget(CppLanguage, m_sourceFilesWindow);
|
2010-12-03 15:03:51 +01:00
|
|
|
connect(dock->toggleViewAction(), SIGNAL(toggled(bool)),
|
2010-12-02 13:20:06 +01:00
|
|
|
SLOT(sourceFilesDockToggled(bool)), Qt::QueuedConnection);
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2010-12-06 10:25:33 +01:00
|
|
|
dock = m_mainWindow->createDockWidget(AnyLanguage, m_logWindow);
|
|
|
|
|
dock->setProperty(DOCKWIDGET_DEFAULT_AREA, Qt::TopDockWidgetArea);
|
|
|
|
|
|
2010-12-03 15:55:17 +01:00
|
|
|
m_mainWindow->createDockWidget(CppLanguage, m_breakWindow);
|
|
|
|
|
m_mainWindow->createDockWidget(CppLanguage, m_snapshotWindow);
|
|
|
|
|
m_mainWindow->createDockWidget(CppLanguage, m_stackWindow);
|
|
|
|
|
m_mainWindow->createDockWidget(CppLanguage, m_threadsWindow);
|
2010-03-29 18:44:02 +02:00
|
|
|
|
2012-05-14 16:09:12 +02:00
|
|
|
m_localsAndExpressionsWindow = new LocalsAndExpressionsWindow(
|
2012-04-18 14:20:54 +02:00
|
|
|
m_localsWindow, m_inspectorWindow, m_returnWindow,
|
|
|
|
|
m_watchersWindow);
|
2012-05-14 16:09:12 +02:00
|
|
|
m_localsAndExpressionsWindow->setObjectName(QLatin1String(DOCKWIDGET_WATCHERS));
|
|
|
|
|
m_localsAndExpressionsWindow->setWindowTitle(m_localsWindow->windowTitle());
|
2012-04-18 14:20:54 +02:00
|
|
|
|
2012-05-14 16:09:12 +02:00
|
|
|
dock = m_mainWindow->createDockWidget(CppLanguage, m_localsAndExpressionsWindow);
|
2010-12-06 10:25:33 +01:00
|
|
|
dock->setProperty(DOCKWIDGET_DEFAULT_AREA, Qt::RightDockWidgetArea);
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2012-01-12 17:04:14 +01:00
|
|
|
m_mainWindow->addStagedMenuEntries();
|
|
|
|
|
|
2011-02-22 11:21:08 +01:00
|
|
|
// Do not fail to load the whole plugin if something goes wrong here.
|
|
|
|
|
QString errorMessage;
|
2012-08-09 01:50:26 +02:00
|
|
|
if (!parseArguments(m_arguments, &errorMessage)) {
|
2011-02-22 11:21:08 +01:00
|
|
|
errorMessage = tr("Error evaluating command line arguments: %1")
|
|
|
|
|
.arg(errorMessage);
|
|
|
|
|
qWarning("%s\n", qPrintable(errorMessage));
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
// Register factory of DebuggerRunControl.
|
2012-06-27 22:19:20 +02:00
|
|
|
m_debuggerRunControlFactory = new DebuggerRunControlFactory(m_plugin);
|
2010-12-02 13:20:06 +01:00
|
|
|
m_plugin->addAutoReleasedObject(m_debuggerRunControlFactory);
|
2010-08-18 13:54:12 +02:00
|
|
|
|
2010-12-06 08:04:43 +01:00
|
|
|
// The main "Start Debugging" action.
|
2011-08-03 18:57:37 +02:00
|
|
|
act = m_startAction = new QAction(this);
|
2011-12-21 14:02:52 +01:00
|
|
|
QIcon debuggerIcon(QLatin1String(":/projectexplorer/images/debugger_start_small.png"));
|
|
|
|
|
debuggerIcon.addFile(QLatin1String(":/projectexplorer/images/debugger_start.png"));
|
2010-12-02 13:20:06 +01:00
|
|
|
act->setIcon(debuggerIcon);
|
|
|
|
|
act->setText(tr("Start Debugging"));
|
|
|
|
|
connect(act, SIGNAL(triggered()), this, SLOT(debugProject()));
|
2010-07-05 17:08:30 +02:00
|
|
|
|
2011-10-25 18:23:37 +08:00
|
|
|
act = m_debugWithoutDeployAction = new QAction(this);
|
2011-12-08 16:31:21 +01:00
|
|
|
act->setText(tr("Start Debugging Without Deployment"));
|
2011-10-25 18:23:37 +08:00
|
|
|
connect(act, SIGNAL(triggered()), this, SLOT(debugProjectWithoutDeploy()));
|
|
|
|
|
|
2012-08-08 13:09:31 +02:00
|
|
|
act = m_startAndDebugApplicationAction = new QAction(this);
|
2012-08-14 09:45:53 +02:00
|
|
|
act->setText(tr("Start and Debug External Application..."));
|
2012-08-08 13:09:31 +02:00
|
|
|
connect(act, SIGNAL(triggered()), SLOT(startAndDebugApplication()));
|
2010-07-05 17:08:30 +02:00
|
|
|
|
2011-12-05 17:21:48 +01:00
|
|
|
act = m_attachToCoreAction = new QAction(this);
|
2011-12-08 16:31:21 +01:00
|
|
|
act->setText(tr("Load Core File..."));
|
2010-12-02 13:20:06 +01:00
|
|
|
connect(act, SIGNAL(triggered()), SLOT(attachCore()));
|
2010-07-05 17:08:30 +02:00
|
|
|
|
2011-12-05 17:21:48 +01:00
|
|
|
act = m_attachToRemoteServerAction = new QAction(this);
|
2011-09-14 15:22:08 +02:00
|
|
|
act->setText(tr("Attach to Remote Debug Server..."));
|
2011-12-05 17:21:48 +01:00
|
|
|
connect(act, SIGNAL(triggered()), SLOT(attachToRemoteServer()));
|
|
|
|
|
|
2011-12-06 15:39:25 +01:00
|
|
|
act = m_startRemoteServerAction = new QAction(this);
|
2012-03-21 17:54:56 +01:00
|
|
|
act->setText(tr("Start Remote Debug Server Attached to Process..."));
|
2011-12-06 15:39:25 +01:00
|
|
|
connect(act, SIGNAL(triggered()), SLOT(startRemoteServer()));
|
|
|
|
|
|
2012-08-06 12:22:35 +02:00
|
|
|
act = m_attachToRunningApplication = new QAction(this);
|
|
|
|
|
act->setText(tr("Attach to Running Application..."));
|
|
|
|
|
connect(act, SIGNAL(triggered()), SLOT(attachToRunningApplication()));
|
2011-09-14 15:22:08 +02:00
|
|
|
|
2011-09-13 17:26:02 +02:00
|
|
|
act = m_attachToQmlPortAction = new QAction(this);
|
|
|
|
|
act->setText(tr("Attach to QML Port..."));
|
|
|
|
|
connect(act, SIGNAL(triggered()), SLOT(attachToQmlPort()));
|
|
|
|
|
|
2012-08-23 15:53:58 +02:00
|
|
|
if (HostOsInfo::isWindowsHost()) {
|
|
|
|
|
m_startRemoteCdbAction = new QAction(tr("Attach to Remote CDB Session..."), this);
|
|
|
|
|
connect(m_startRemoteCdbAction, SIGNAL(triggered()),
|
|
|
|
|
SLOT(startRemoteCdbSession()));
|
|
|
|
|
}
|
2010-07-05 17:08:30 +02:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
act = m_detachAction = new QAction(this);
|
|
|
|
|
act->setText(tr("Detach Debugger"));
|
|
|
|
|
connect(act, SIGNAL(triggered()), SLOT(handleExecDetach()));
|
2010-11-23 13:28:18 +01:00
|
|
|
|
2011-10-10 13:38:58 +02:00
|
|
|
// "Start Debugging" sub-menu
|
|
|
|
|
// groups:
|
|
|
|
|
// G_DEFAULT_ONE
|
2011-10-19 11:51:51 +02:00
|
|
|
// G_START_LOCAL
|
|
|
|
|
// G_START_REMOTE
|
2011-10-10 13:38:58 +02:00
|
|
|
// G_START_QML
|
|
|
|
|
|
2010-12-02 18:19:05 +01:00
|
|
|
Command *cmd = 0;
|
2012-07-18 16:20:19 +02:00
|
|
|
ActionContainer *mstart = ActionManager::actionContainer(PE::M_DEBUG_STARTDEBUGGING);
|
2010-08-24 16:22:21 +02:00
|
|
|
|
2012-07-18 16:20:19 +02:00
|
|
|
cmd = ActionManager::registerAction(m_startAction, Constants::DEBUG, globalcontext);
|
2012-01-06 17:13:18 +01:00
|
|
|
cmd->setDescription(tr("Start Debugging"));
|
2012-05-23 13:25:51 +02:00
|
|
|
cmd->setDefaultKeySequence(debugKey);
|
2011-05-26 19:57:07 +02:00
|
|
|
cmd->setAttribute(Command::CA_UpdateText);
|
2011-10-10 13:38:58 +02:00
|
|
|
mstart->addAction(cmd, CC::G_DEFAULT_ONE);
|
2012-08-15 16:19:15 +02:00
|
|
|
m_visibleStartAction = new ProxyAction(this);
|
2012-05-24 10:19:50 +02:00
|
|
|
m_visibleStartAction->initialize(cmd->action());
|
2012-08-15 16:19:15 +02:00
|
|
|
m_visibleStartAction->setAttribute(ProxyAction::UpdateText);
|
|
|
|
|
m_visibleStartAction->setAttribute(ProxyAction::UpdateIcon);
|
2011-08-03 18:57:37 +02:00
|
|
|
m_visibleStartAction->setAction(cmd->action());
|
2011-02-03 14:17:23 +01:00
|
|
|
|
2012-01-26 01:18:02 +01:00
|
|
|
ModeManager::addAction(m_visibleStartAction, Constants::P_ACTION_DEBUG);
|
2010-10-28 08:55:50 +02:00
|
|
|
|
2012-07-18 16:20:19 +02:00
|
|
|
cmd = ActionManager::registerAction(m_debugWithoutDeployAction,
|
2011-10-25 18:23:37 +08:00
|
|
|
"Debugger.DebugWithoutDeploy", globalcontext);
|
|
|
|
|
cmd->setAttribute(Command::CA_Hide);
|
|
|
|
|
mstart->addAction(cmd, CC::G_DEFAULT_ONE);
|
|
|
|
|
|
2012-08-06 12:22:35 +02:00
|
|
|
cmd = ActionManager::registerAction(m_attachToRunningApplication,
|
|
|
|
|
"Debugger.AttachToRemoteProcess", globalcontext);
|
|
|
|
|
cmd->setDescription(tr("Attach to Running Application"));
|
2012-08-15 16:19:15 +02:00
|
|
|
mstart->addAction(cmd, Debugger::Constants::G_GENERAL);
|
2011-10-19 11:51:51 +02:00
|
|
|
|
2012-08-08 13:09:31 +02:00
|
|
|
cmd = ActionManager::registerAction(m_startAndDebugApplicationAction,
|
|
|
|
|
"Debugger.StartAndDebugApplication", globalcontext);
|
2011-10-19 11:51:51 +02:00
|
|
|
cmd->setAttribute(Command::CA_Hide);
|
2012-08-15 16:19:15 +02:00
|
|
|
mstart->addAction(cmd, Debugger::Constants::G_GENERAL);
|
2012-01-07 17:18:52 +01:00
|
|
|
|
2012-07-18 16:20:19 +02:00
|
|
|
cmd = ActionManager::registerAction(m_attachToCoreAction,
|
2011-08-04 10:31:15 +02:00
|
|
|
"Debugger.AttachCore", globalcontext);
|
2011-10-19 11:51:51 +02:00
|
|
|
cmd->setAttribute(Command::CA_Hide);
|
2012-08-15 16:19:15 +02:00
|
|
|
mstart->addAction(cmd, Constants::G_GENERAL);
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2012-07-18 16:20:19 +02:00
|
|
|
cmd = ActionManager::registerAction(m_attachToRemoteServerAction,
|
2011-12-05 17:21:48 +01:00
|
|
|
"Debugger.AttachToRemoteServer", globalcontext);
|
2010-12-02 13:20:06 +01:00
|
|
|
cmd->setAttribute(Command::CA_Hide);
|
2012-08-15 16:19:15 +02:00
|
|
|
mstart->addAction(cmd, Constants::G_SPECIAL);
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2012-07-18 16:20:19 +02:00
|
|
|
cmd = ActionManager::registerAction(m_startRemoteServerAction,
|
2011-12-06 15:39:25 +01:00
|
|
|
"Debugger.StartRemoteServer", globalcontext);
|
2012-01-06 17:13:18 +01:00
|
|
|
cmd->setDescription(tr("Start Gdbserver"));
|
2012-08-15 16:19:15 +02:00
|
|
|
mstart->addAction(cmd, Constants::G_SPECIAL);
|
2011-12-06 15:39:25 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
if (m_startRemoteCdbAction) {
|
2012-07-18 16:20:19 +02:00
|
|
|
cmd = ActionManager::registerAction(m_startRemoteCdbAction,
|
2011-08-04 10:31:15 +02:00
|
|
|
"Debugger.AttachRemoteCdb", globalcontext);
|
2010-12-02 13:20:06 +01:00
|
|
|
cmd->setAttribute(Command::CA_Hide);
|
2012-08-15 16:19:15 +02:00
|
|
|
mstart->addAction(cmd, Constants::G_SPECIAL);
|
2010-12-02 13:20:06 +01:00
|
|
|
}
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2012-06-05 14:22:20 +02:00
|
|
|
mstart->addSeparator(globalcontext, Constants::G_START_QML);
|
2011-10-10 13:38:58 +02:00
|
|
|
|
2012-07-18 16:20:19 +02:00
|
|
|
cmd = ActionManager::registerAction(m_attachToQmlPortAction,
|
2011-10-10 13:38:58 +02:00
|
|
|
"Debugger.AttachToQmlPort", globalcontext);
|
|
|
|
|
cmd->setAttribute(Command::CA_Hide);
|
|
|
|
|
mstart->addAction(cmd, Constants::G_START_QML);
|
2011-09-22 11:18:14 +02:00
|
|
|
|
2012-07-18 16:20:19 +02:00
|
|
|
cmd = ActionManager::registerAction(m_detachAction,
|
2011-08-04 10:31:15 +02:00
|
|
|
"Debugger.Detach", globalcontext);
|
2010-12-02 13:20:06 +01:00
|
|
|
cmd->setAttribute(Command::CA_Hide);
|
2010-12-02 18:21:39 +01:00
|
|
|
debugMenu->addAction(cmd, CC::G_DEFAULT_ONE);
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2012-07-18 16:20:19 +02:00
|
|
|
cmd = ActionManager::registerAction(m_interruptAction,
|
2011-01-12 16:36:29 +01:00
|
|
|
Constants::INTERRUPT, globalcontext);
|
2012-01-06 17:13:18 +01:00
|
|
|
cmd->setDescription(tr("Interrupt Debugger"));
|
2011-01-12 16:36:29 +01:00
|
|
|
debugMenu->addAction(cmd, CC::G_DEFAULT_ONE);
|
|
|
|
|
|
2012-07-18 16:20:19 +02:00
|
|
|
cmd = ActionManager::registerAction(m_continueAction,
|
2011-01-12 16:36:29 +01:00
|
|
|
Constants::CONTINUE, globalcontext);
|
2012-05-23 13:25:51 +02:00
|
|
|
cmd->setDefaultKeySequence(debugKey);
|
2011-01-12 16:36:29 +01:00
|
|
|
debugMenu->addAction(cmd, CC::G_DEFAULT_ONE);
|
|
|
|
|
|
2012-07-18 16:20:19 +02:00
|
|
|
cmd = ActionManager::registerAction(m_exitAction,
|
2010-12-02 13:20:06 +01:00
|
|
|
Constants::STOP, globalcontext);
|
2010-12-02 18:21:39 +01:00
|
|
|
debugMenu->addAction(cmd, CC::G_DEFAULT_ONE);
|
2012-08-15 16:19:15 +02:00
|
|
|
m_hiddenStopAction = new ProxyAction(this);
|
2012-05-24 10:19:50 +02:00
|
|
|
m_hiddenStopAction->initialize(cmd->action());
|
2012-08-15 16:19:15 +02:00
|
|
|
m_hiddenStopAction->setAttribute(ProxyAction::UpdateText);
|
|
|
|
|
m_hiddenStopAction->setAttribute(ProxyAction::UpdateIcon);
|
2011-08-03 18:57:37 +02:00
|
|
|
|
2012-07-18 16:20:19 +02:00
|
|
|
cmd = ActionManager::registerAction(m_hiddenStopAction,
|
2011-08-03 18:57:37 +02:00
|
|
|
Constants::HIDDEN_STOP, globalcontext);
|
2012-05-23 13:25:51 +02:00
|
|
|
cmd->setDefaultKeySequence(QKeySequence(UseMacShortcuts ? tr("Shift+Ctrl+Y") : tr("Shift+F5")));
|
2011-08-03 18:57:37 +02:00
|
|
|
|
2012-07-18 16:20:19 +02:00
|
|
|
cmd = ActionManager::registerAction(m_abortAction,
|
2011-10-31 16:15:48 +01:00
|
|
|
Constants::ABORT, globalcontext);
|
2012-01-06 17:13:18 +01:00
|
|
|
cmd->setDescription(tr("Reset Debugger"));
|
2010-12-02 18:21:39 +01:00
|
|
|
debugMenu->addAction(cmd, CC::G_DEFAULT_ONE);
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2012-06-05 14:22:20 +02:00
|
|
|
debugMenu->addSeparator(globalcontext);
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2012-07-18 16:20:19 +02:00
|
|
|
cmd = ActionManager::registerAction(m_nextAction,
|
2011-05-02 18:22:32 +02:00
|
|
|
Constants::NEXT, globalcontext);
|
2012-05-23 13:25:51 +02:00
|
|
|
cmd->setDefaultKeySequence(QKeySequence(UseMacShortcuts ? tr("Ctrl+Shift+O") : tr("F10")));
|
2010-12-02 13:20:06 +01:00
|
|
|
cmd->setAttribute(Command::CA_Hide);
|
2011-07-18 17:23:42 +02:00
|
|
|
cmd->setAttribute(Command::CA_UpdateText);
|
2010-12-02 18:21:39 +01:00
|
|
|
debugMenu->addAction(cmd);
|
2010-09-24 16:55:22 +02:00
|
|
|
|
2012-07-18 16:20:19 +02:00
|
|
|
cmd = ActionManager::registerAction(m_stepAction,
|
2011-05-02 18:22:32 +02:00
|
|
|
Constants::STEP, globalcontext);
|
2012-05-23 13:25:51 +02:00
|
|
|
cmd->setDefaultKeySequence(QKeySequence(UseMacShortcuts ? tr("Ctrl+Shift+I") : tr("F11")));
|
2010-12-02 13:20:06 +01:00
|
|
|
cmd->setAttribute(Command::CA_Hide);
|
2011-07-18 17:23:42 +02:00
|
|
|
cmd->setAttribute(Command::CA_UpdateText);
|
2010-12-02 18:21:39 +01:00
|
|
|
debugMenu->addAction(cmd);
|
2010-11-12 20:18:29 +01:00
|
|
|
|
2012-07-18 16:20:19 +02:00
|
|
|
cmd = ActionManager::registerAction(m_stepOutAction,
|
2010-12-02 13:20:06 +01:00
|
|
|
Constants::STEPOUT, cppDebuggercontext);
|
2012-05-23 13:25:51 +02:00
|
|
|
cmd->setDefaultKeySequence(QKeySequence(UseMacShortcuts ? tr("Ctrl+Shift+T") : tr("Shift+F11")));
|
2010-12-02 13:20:06 +01:00
|
|
|
cmd->setAttribute(Command::CA_Hide);
|
2010-12-02 18:21:39 +01:00
|
|
|
debugMenu->addAction(cmd);
|
2010-11-23 16:42:46 +01:00
|
|
|
|
2012-07-18 16:20:19 +02:00
|
|
|
cmd = ActionManager::registerAction(m_runToLineAction,
|
2011-08-04 10:31:15 +02:00
|
|
|
"Debugger.RunToLine", cppDebuggercontext);
|
2012-05-23 13:25:51 +02:00
|
|
|
cmd->setDefaultKeySequence(QKeySequence(UseMacShortcuts ? tr("Shift+F8") : tr("Ctrl+F10")));
|
2010-12-02 13:20:06 +01:00
|
|
|
cmd->setAttribute(Command::CA_Hide);
|
2010-12-02 18:21:39 +01:00
|
|
|
debugMenu->addAction(cmd);
|
2009-05-25 18:21:31 +02:00
|
|
|
|
2012-07-18 16:20:19 +02:00
|
|
|
cmd = ActionManager::registerAction(m_runToSelectedFunctionAction,
|
2011-08-04 10:31:15 +02:00
|
|
|
"Debugger.RunToSelectedFunction", cppDebuggercontext);
|
2012-05-23 13:25:51 +02:00
|
|
|
cmd->setDefaultKeySequence(QKeySequence(UseMacShortcuts ? tr("Ctrl+F6") : tr("Ctrl+F6")));
|
2010-12-02 13:20:06 +01:00
|
|
|
cmd->setAttribute(Command::CA_Hide);
|
2011-02-02 11:52:39 +01:00
|
|
|
// Don't add to menu by default as keeping its enabled state
|
|
|
|
|
// and text up-to-date is a lot of hassle.
|
|
|
|
|
// debugMenu->addAction(cmd);
|
2009-01-13 18:15:24 +01:00
|
|
|
|
2012-07-18 16:20:19 +02:00
|
|
|
cmd = ActionManager::registerAction(m_jumpToLineAction,
|
2011-08-04 10:31:15 +02:00
|
|
|
"Debugger.JumpToLine", cppDebuggercontext);
|
2010-12-02 13:20:06 +01:00
|
|
|
cmd->setAttribute(Command::CA_Hide);
|
2010-12-02 18:21:39 +01:00
|
|
|
debugMenu->addAction(cmd);
|
2009-02-27 11:41:19 +01:00
|
|
|
|
2012-07-18 16:20:19 +02:00
|
|
|
cmd = ActionManager::registerAction(m_returnFromFunctionAction,
|
2011-08-04 10:31:15 +02:00
|
|
|
"Debugger.ReturnFromFunction", cppDebuggercontext);
|
2010-12-02 13:20:06 +01:00
|
|
|
cmd->setAttribute(Command::CA_Hide);
|
2010-12-02 18:21:39 +01:00
|
|
|
debugMenu->addAction(cmd);
|
2009-06-16 13:44:45 +02:00
|
|
|
|
2012-07-18 16:20:19 +02:00
|
|
|
cmd = ActionManager::registerAction(m_reverseDirectionAction,
|
2010-12-02 13:20:06 +01:00
|
|
|
Constants::REVERSE, cppDebuggercontext);
|
2012-05-23 13:25:51 +02:00
|
|
|
cmd->setDefaultKeySequence(QKeySequence(UseMacShortcuts ? QString() : tr("F12")));
|
2010-12-02 13:20:06 +01:00
|
|
|
cmd->setAttribute(Command::CA_Hide);
|
2010-12-02 18:21:39 +01:00
|
|
|
debugMenu->addAction(cmd);
|
2009-05-05 17:48:54 +02:00
|
|
|
|
2012-06-05 14:22:20 +02:00
|
|
|
debugMenu->addSeparator(globalcontext);
|
2009-05-05 17:48:54 +02:00
|
|
|
|
2012-07-18 16:20:19 +02:00
|
|
|
//cmd = ActionManager::registerAction(m_snapshotAction,
|
2011-08-04 10:31:15 +02:00
|
|
|
// "Debugger.Snapshot", cppDebuggercontext);
|
2012-05-23 13:25:51 +02:00
|
|
|
//cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+D,Ctrl+S")));
|
2010-12-02 13:20:06 +01:00
|
|
|
//cmd->setAttribute(Command::CA_Hide);
|
2010-12-02 18:21:39 +01:00
|
|
|
//debugMenu->addAction(cmd);
|
2009-09-30 12:27:03 +02:00
|
|
|
|
2012-07-18 16:20:19 +02:00
|
|
|
cmd = ActionManager::registerAction(m_frameDownAction,
|
2011-08-04 10:31:15 +02:00
|
|
|
"Debugger.FrameDown", cppDebuggercontext);
|
2012-07-18 16:20:19 +02:00
|
|
|
cmd = ActionManager::registerAction(m_frameUpAction,
|
2011-08-04 10:31:15 +02:00
|
|
|
"Debugger.FrameUp", cppDebuggercontext);
|
2009-05-05 17:48:54 +02:00
|
|
|
|
2012-07-18 16:20:19 +02:00
|
|
|
cmd = ActionManager::registerAction(action(OperateByInstruction),
|
2010-12-02 13:20:06 +01:00
|
|
|
Constants::OPERATE_BY_INSTRUCTION, cppDebuggercontext);
|
|
|
|
|
cmd->setAttribute(Command::CA_Hide);
|
2010-12-02 18:21:39 +01:00
|
|
|
debugMenu->addAction(cmd);
|
2010-08-26 16:02:41 +02:00
|
|
|
|
2012-07-18 16:20:19 +02:00
|
|
|
cmd = ActionManager::registerAction(m_breakAction,
|
2011-08-04 10:31:15 +02:00
|
|
|
"Debugger.ToggleBreak", globalcontext);
|
2012-05-23 13:25:51 +02:00
|
|
|
cmd->setDefaultKeySequence(QKeySequence(UseMacShortcuts ? tr("F8") : tr("F9")));
|
2010-12-02 18:21:39 +01:00
|
|
|
debugMenu->addAction(cmd);
|
2011-02-03 14:08:01 +01:00
|
|
|
connect(m_breakAction, SIGNAL(triggered()),
|
2010-12-02 13:20:06 +01:00
|
|
|
SLOT(toggleBreakpoint()));
|
2010-08-26 16:02:41 +02:00
|
|
|
|
2012-06-05 14:22:20 +02:00
|
|
|
debugMenu->addSeparator(globalcontext);
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2011-08-04 10:31:15 +02:00
|
|
|
// Don't add '1' to the string as it shows up in the shortcut dialog.
|
2012-07-18 16:20:19 +02:00
|
|
|
cmd = ActionManager::registerAction(m_watchAction1,
|
2011-08-04 10:31:15 +02:00
|
|
|
"Debugger.AddToWatch", cppeditorcontext);
|
2010-12-02 13:20:06 +01:00
|
|
|
//cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+D,Ctrl+W")));
|
2010-12-02 18:21:39 +01:00
|
|
|
debugMenu->addAction(cmd);
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2011-01-06 14:57:21 +01:00
|
|
|
// If the CppEditor plugin is there, we want to add something to
|
|
|
|
|
// the editor context menu.
|
|
|
|
|
if (ActionContainer *editorContextMenu =
|
2012-07-18 16:20:19 +02:00
|
|
|
ActionManager::actionContainer(CppEditor::Constants::M_CONTEXT)) {
|
2012-06-05 14:22:20 +02:00
|
|
|
cmd = editorContextMenu->addSeparator(cppDebuggercontext);
|
2011-01-06 14:57:21 +01:00
|
|
|
cmd->setAttribute(Command::CA_Hide);
|
2010-11-10 12:38:29 +01:00
|
|
|
|
2012-07-18 16:20:19 +02:00
|
|
|
cmd = ActionManager::registerAction(m_watchAction2,
|
2011-08-04 10:31:15 +02:00
|
|
|
"Debugger.AddToWatch2", cppDebuggercontext);
|
2011-01-06 14:57:21 +01:00
|
|
|
cmd->action()->setEnabled(true);
|
|
|
|
|
editorContextMenu->addAction(cmd);
|
|
|
|
|
cmd->setAttribute(Command::CA_Hide);
|
2011-08-04 10:31:15 +02:00
|
|
|
cmd->setAttribute(Command::CA_NonConfigurable);
|
|
|
|
|
// Debugger.AddToWatch is enough.
|
2011-01-06 14:57:21 +01:00
|
|
|
}
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2011-12-06 15:39:25 +01:00
|
|
|
QList<IOptionsPage *> engineOptionPages;
|
2012-08-09 01:50:26 +02:00
|
|
|
addGdbOptionPages(&engineOptionPages);
|
|
|
|
|
addCdbOptionPages(&engineOptionPages);
|
2010-12-02 13:20:06 +01:00
|
|
|
#ifdef WITH_LLDB
|
2012-08-09 01:50:26 +02:00
|
|
|
addLldbOptionPages(&engineOptionPages);
|
2010-12-02 13:20:06 +01:00
|
|
|
#endif
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2012-08-09 01:50:26 +02:00
|
|
|
// addScriptOptionPages(&engineOptionPages);
|
|
|
|
|
// addTcfOptionPages(&engineOptionPages);
|
2011-12-06 15:39:25 +01:00
|
|
|
|
|
|
|
|
foreach (IOptionsPage *op, engineOptionPages)
|
2010-12-02 13:20:06 +01:00
|
|
|
m_plugin->addAutoReleasedObject(op);
|
2012-05-14 15:11:11 +02:00
|
|
|
m_plugin->addAutoReleasedObject(new LocalsAndExpressionsOptionsPage);
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
connect(ModeManager::instance(), SIGNAL(currentModeChanged(Core::IMode*)),
|
|
|
|
|
SLOT(onModeChanged(Core::IMode*)));
|
2011-01-31 15:17:53 +01:00
|
|
|
connect(ICore::instance(), SIGNAL(coreAboutToOpen()),
|
2011-02-03 14:17:23 +01:00
|
|
|
SLOT(onCoreAboutToOpen()));
|
2011-12-06 15:39:25 +01:00
|
|
|
connect(ProjectExplorerPlugin::instance(), SIGNAL(settingsChanged()),
|
2011-10-25 18:23:37 +08:00
|
|
|
this, SLOT(updateDebugWithoutDeployMenu()));
|
2010-12-03 15:23:23 +01:00
|
|
|
|
|
|
|
|
// Debug mode setup
|
2011-04-13 13:00:30 +02:00
|
|
|
DebugMode *debugMode = new DebugMode;
|
|
|
|
|
QWidget *widget = m_mainWindow->createContents(debugMode);
|
|
|
|
|
widget->setFocusProxy(EditorManager::instance());
|
|
|
|
|
debugMode->setWidget(widget);
|
|
|
|
|
|
|
|
|
|
m_plugin->addAutoReleasedObject(debugMode);
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
//
|
|
|
|
|
// Connections
|
|
|
|
|
//
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2011-02-22 12:05:25 +01:00
|
|
|
// Core
|
2012-01-24 15:36:40 +01:00
|
|
|
connect(ICore::instance(), SIGNAL(saveSettingsRequested()), SLOT(writeSettings()));
|
2011-02-22 12:05:25 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
// TextEditor
|
|
|
|
|
connect(TextEditorSettings::instance(),
|
|
|
|
|
SIGNAL(fontSettingsChanged(TextEditor::FontSettings)),
|
|
|
|
|
SLOT(fontSettingsChanged(TextEditor::FontSettings)));
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
// ProjectExplorer
|
2012-02-10 12:46:33 +01:00
|
|
|
connect(sessionManager(), SIGNAL(sessionLoaded(QString)),
|
2010-12-02 13:20:06 +01:00
|
|
|
SLOT(sessionLoaded()));
|
|
|
|
|
connect(sessionManager(), SIGNAL(aboutToSaveSession()),
|
|
|
|
|
SLOT(aboutToSaveSession()));
|
2012-02-10 12:46:33 +01:00
|
|
|
connect(sessionManager(), SIGNAL(aboutToUnloadSession(QString)),
|
2010-12-02 13:20:06 +01:00
|
|
|
SLOT(aboutToUnloadSession()));
|
|
|
|
|
connect(ProjectExplorerPlugin::instance(), SIGNAL(updateRunActions()),
|
|
|
|
|
SLOT(updateDebugActions()));
|
2010-11-10 11:39:01 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
// EditorManager
|
2012-01-24 15:36:40 +01:00
|
|
|
QObject *editorManager = ICore::editorManager();
|
2010-12-02 13:20:06 +01:00
|
|
|
connect(editorManager, SIGNAL(editorOpened(Core::IEditor*)),
|
|
|
|
|
SLOT(editorOpened(Core::IEditor*)));
|
2011-02-04 14:36:50 +01:00
|
|
|
connect(editorManager, SIGNAL(currentEditorChanged(Core::IEditor*)),
|
|
|
|
|
SLOT(updateBreakMenuItem(Core::IEditor*)));
|
2010-11-10 11:39:01 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
// Application interaction
|
|
|
|
|
connect(action(SettingsDialog), SIGNAL(triggered()),
|
|
|
|
|
SLOT(showSettingsDialog()));
|
2010-11-10 11:39:01 +01:00
|
|
|
|
2012-04-18 14:20:54 +02:00
|
|
|
// QML Actions
|
|
|
|
|
connect(action(ShowQmlObjectTree), SIGNAL(valueChanged(QVariant)),
|
|
|
|
|
SLOT(updateQmlActions()));
|
|
|
|
|
updateQmlActions();
|
|
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
// Toolbar
|
|
|
|
|
QWidget *toolbarContainer = new QWidget;
|
2010-11-10 11:39:01 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
QHBoxLayout *hbox = new QHBoxLayout(toolbarContainer);
|
|
|
|
|
hbox->setMargin(0);
|
|
|
|
|
hbox->setSpacing(0);
|
2011-08-03 18:57:37 +02:00
|
|
|
hbox->addWidget(toolButton(m_visibleStartAction));
|
2012-05-24 10:19:50 +02:00
|
|
|
hbox->addWidget(toolButton(Constants::STOP));
|
|
|
|
|
hbox->addWidget(toolButton(Constants::NEXT));
|
|
|
|
|
hbox->addWidget(toolButton(Constants::STEP));
|
|
|
|
|
hbox->addWidget(toolButton(Constants::STEPOUT));
|
|
|
|
|
hbox->addWidget(toolButton(Constants::OPERATE_BY_INSTRUCTION));
|
2010-11-10 11:39:01 +01:00
|
|
|
|
2012-08-15 16:19:15 +02:00
|
|
|
//hbox->addWidget(new StyledSeparator);
|
2012-05-24 10:19:50 +02:00
|
|
|
m_reverseToolButton = toolButton(Constants::REVERSE);
|
2010-12-02 13:20:06 +01:00
|
|
|
hbox->addWidget(m_reverseToolButton);
|
|
|
|
|
//m_reverseToolButton->hide();
|
2010-11-10 11:39:01 +01:00
|
|
|
|
2012-08-15 16:19:15 +02:00
|
|
|
hbox->addWidget(new StyledSeparator);
|
2010-12-02 13:20:06 +01:00
|
|
|
hbox->addWidget(new QLabel(tr("Threads:")));
|
2010-11-10 11:39:01 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
m_threadBox = new QComboBox;
|
2011-09-01 16:36:27 +02:00
|
|
|
m_threadBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
2010-12-02 13:20:06 +01:00
|
|
|
connect(m_threadBox, SIGNAL(activated(int)), SLOT(selectThread(int)));
|
2010-11-10 11:39:01 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
hbox->addWidget(m_threadBox);
|
|
|
|
|
hbox->addSpacerItem(new QSpacerItem(4, 0));
|
2010-11-10 11:39:01 +01:00
|
|
|
|
2011-02-16 10:02:30 +01:00
|
|
|
m_mainWindow->setToolBar(CppLanguage, toolbarContainer);
|
2012-04-18 14:20:54 +02:00
|
|
|
|
|
|
|
|
QWidget *qmlToolbar = new QWidget;
|
|
|
|
|
hbox = new QHBoxLayout(qmlToolbar);
|
|
|
|
|
hbox->setMargin(0);
|
|
|
|
|
hbox->setSpacing(0);
|
|
|
|
|
hbox->addWidget(toolButton(action(QmlUpdateOnSave)));
|
|
|
|
|
hbox->addWidget(toolButton(action(ShowAppOnTop)));
|
2012-08-15 16:19:15 +02:00
|
|
|
hbox->addWidget(new StyledSeparator);
|
2012-05-24 10:19:50 +02:00
|
|
|
hbox->addWidget(toolButton(Constants::QML_SELECTTOOL));
|
|
|
|
|
hbox->addWidget(toolButton(Constants::QML_ZOOMTOOL));
|
2012-08-15 16:19:15 +02:00
|
|
|
hbox->addWidget(new StyledSeparator);
|
2012-04-18 14:20:54 +02:00
|
|
|
m_mainWindow->setToolBar(QmlLanguage, qmlToolbar);
|
|
|
|
|
|
2012-03-26 17:30:57 +02:00
|
|
|
m_mainWindow->setToolBar(AnyLanguage, m_statusLabel);
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
connect(action(EnableReverseDebugging),
|
|
|
|
|
SIGNAL(valueChanged(QVariant)),
|
|
|
|
|
SLOT(enableReverseDebuggingTriggered(QVariant)));
|
2010-11-10 16:33:11 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
setInitialState();
|
|
|
|
|
connectEngine(0);
|
2010-11-10 11:39:01 +01:00
|
|
|
|
2010-12-02 13:20:06 +01:00
|
|
|
connect(sessionManager(),
|
|
|
|
|
SIGNAL(startupProjectChanged(ProjectExplorer::Project*)),
|
|
|
|
|
SLOT(onCurrentProjectChanged(ProjectExplorer::Project*)));
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2011-12-06 15:39:25 +01:00
|
|
|
m_commonOptionsPage = new CommonOptionsPage(m_globalDebuggerOptions);
|
|
|
|
|
m_plugin->addAutoReleasedObject(m_commonOptionsPage);
|
|
|
|
|
|
2011-07-29 12:00:11 +02:00
|
|
|
QTC_CHECK(m_coreSettings);
|
2011-03-04 16:21:57 +01:00
|
|
|
m_globalDebuggerOptions->fromSettings(m_coreSettings);
|
2010-11-10 11:39:01 +01:00
|
|
|
m_watchersWindow->setVisible(false);
|
|
|
|
|
m_returnWindow->setVisible(false);
|
2010-06-29 18:12:22 +02:00
|
|
|
|
2011-02-08 13:48:04 +01:00
|
|
|
// time gdb -i mi -ex 'b debuggerplugin.cpp:800' -ex r -ex q bin/qtcreator.bin
|
|
|
|
|
if (!m_scheduledStarts.isEmpty())
|
|
|
|
|
QTimer::singleShot(0, this, SLOT(runScheduled()));
|
2010-06-16 11:08:54 +02:00
|
|
|
}
|
2010-05-05 12:41:52 +02:00
|
|
|
|
2012-08-15 16:19:15 +02:00
|
|
|
SavedAction *DebuggerPluginPrivate::action(int code) const
|
2010-11-10 16:33:11 +01:00
|
|
|
{
|
|
|
|
|
return m_debuggerSettings->item(code);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool DebuggerPluginPrivate::boolSetting(int code) const
|
|
|
|
|
{
|
|
|
|
|
return m_debuggerSettings->item(code)->value().toBool();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString DebuggerPluginPrivate::stringSetting(int code) const
|
|
|
|
|
{
|
|
|
|
|
return m_debuggerSettings->item(code)->value().toString();
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-26 09:58:34 +01:00
|
|
|
void DebuggerPluginPrivate::showModuleSymbols(const QString &moduleName,
|
|
|
|
|
const Symbols &symbols)
|
|
|
|
|
{
|
|
|
|
|
QTreeWidget *w = new QTreeWidget;
|
2011-12-19 17:18:58 +01:00
|
|
|
w->setUniformRowHeights(true);
|
2010-11-26 09:58:34 +01:00
|
|
|
w->setColumnCount(5);
|
|
|
|
|
w->setRootIsDecorated(false);
|
|
|
|
|
w->setAlternatingRowColors(true);
|
|
|
|
|
w->setSortingEnabled(true);
|
2011-12-21 14:02:52 +01:00
|
|
|
w->setObjectName(QLatin1String("Symbols.") + moduleName);
|
2010-11-26 09:58:34 +01:00
|
|
|
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);
|
|
|
|
|
}
|
2010-12-03 15:55:17 +01:00
|
|
|
createNewDock(w);
|
2010-11-26 09:58:34 +01:00
|
|
|
}
|
|
|
|
|
|
2010-12-06 08:25:29 +01:00
|
|
|
void DebuggerPluginPrivate::aboutToShutdown()
|
|
|
|
|
{
|
2011-05-31 09:48:00 +02:00
|
|
|
m_plugin->removeObject(this);
|
2010-12-06 08:25:29 +01:00
|
|
|
disconnect(sessionManager(),
|
|
|
|
|
SIGNAL(startupProjectChanged(ProjectExplorer::Project*)),
|
|
|
|
|
this, 0);
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-10 11:39:01 +01:00
|
|
|
} // namespace Internal
|
2010-06-16 11:08:54 +02:00
|
|
|
|
|
|
|
|
|
2010-11-10 11:39:01 +01:00
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
|
|
|
|
// DebuggerPlugin
|
|
|
|
|
//
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2010-11-26 09:58:34 +01:00
|
|
|
using namespace Debugger::Internal;
|
|
|
|
|
|
2011-02-04 15:08:31 +01:00
|
|
|
/*!
|
|
|
|
|
\class Debugger::DebuggerPlugin
|
|
|
|
|
|
|
|
|
|
This is the "external" interface of the debugger plugin that's visible
|
|
|
|
|
from Qt Creator core. The internal interface to global debugger
|
|
|
|
|
functionality that is used by debugger views and debugger engines
|
|
|
|
|
is DebuggerCore, implemented in DebuggerPluginPrivate. */
|
|
|
|
|
|
2010-11-10 11:39:01 +01:00
|
|
|
DebuggerPlugin::DebuggerPlugin()
|
2010-07-13 15:57:34 +02:00
|
|
|
{
|
2010-11-10 11:39:01 +01:00
|
|
|
theDebuggerCore = new DebuggerPluginPrivate(this);
|
2010-08-18 13:54:12 +02:00
|
|
|
}
|
|
|
|
|
|
2010-11-10 11:39:01 +01:00
|
|
|
DebuggerPlugin::~DebuggerPlugin()
|
2010-08-18 13:54:12 +02:00
|
|
|
{
|
2010-11-10 11:39:01 +01:00
|
|
|
delete theDebuggerCore;
|
|
|
|
|
theDebuggerCore = 0;
|
2010-07-13 15:57:34 +02:00
|
|
|
}
|
|
|
|
|
|
2010-11-10 11:39:01 +01:00
|
|
|
bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMessage)
|
2010-06-16 11:08:54 +02:00
|
|
|
{
|
2011-10-10 13:38:58 +02:00
|
|
|
// Menu groups
|
|
|
|
|
const Context globalcontext(CC::C_GLOBAL);
|
|
|
|
|
|
2012-07-18 16:20:19 +02:00
|
|
|
ActionContainer *mstart = ActionManager::actionContainer(PE::M_DEBUG_STARTDEBUGGING);
|
2011-10-10 13:38:58 +02:00
|
|
|
|
2012-08-15 16:19:15 +02:00
|
|
|
mstart->appendGroup(Constants::G_GENERAL);
|
|
|
|
|
mstart->appendGroup(Constants::G_SPECIAL);
|
2011-10-10 13:38:58 +02:00
|
|
|
mstart->appendGroup(Constants::G_START_QML);
|
|
|
|
|
|
2011-10-19 11:51:51 +02:00
|
|
|
// Separators
|
2012-08-15 16:19:15 +02:00
|
|
|
mstart->addSeparator(globalcontext, Constants::G_GENERAL);
|
|
|
|
|
mstart->addSeparator(globalcontext, Constants::G_SPECIAL);
|
2011-10-10 13:38:58 +02:00
|
|
|
|
2012-09-03 18:31:44 +02:00
|
|
|
KitManager::instance()->registerKitInformation(new DebuggerKitInformation);
|
2012-04-24 15:49:09 +02:00
|
|
|
|
2010-11-10 11:39:01 +01:00
|
|
|
return theDebuggerCore->initialize(arguments, errorMessage);
|
2010-06-16 11:08:54 +02:00
|
|
|
}
|
|
|
|
|
|
2011-12-06 15:39:25 +01:00
|
|
|
IPlugin::ShutdownFlag DebuggerPlugin::aboutToShutdown()
|
2010-06-16 11:08:54 +02:00
|
|
|
{
|
2010-12-06 08:25:29 +01:00
|
|
|
theDebuggerCore->aboutToShutdown();
|
2010-11-10 11:39:01 +01:00
|
|
|
return SynchronousShutdown;
|
2010-06-16 11:08:54 +02:00
|
|
|
}
|
|
|
|
|
|
2010-11-10 11:39:01 +01:00
|
|
|
void DebuggerPlugin::remoteCommand(const QStringList &options,
|
|
|
|
|
const QStringList &list)
|
2010-06-16 11:08:54 +02:00
|
|
|
{
|
2010-11-10 11:39:01 +01:00
|
|
|
theDebuggerCore->remoteCommand(options, list);
|
2010-06-16 11:08:54 +02:00
|
|
|
}
|
|
|
|
|
|
2010-11-10 11:39:01 +01:00
|
|
|
DebuggerRunControl *DebuggerPlugin::createDebugger
|
2012-09-05 12:42:41 +02:00
|
|
|
(const DebuggerStartParameters &sp, RunConfiguration *rc, QString *errorMessage)
|
2010-08-18 13:54:12 +02:00
|
|
|
{
|
2012-09-05 12:42:41 +02:00
|
|
|
return DebuggerRunControlFactory::doCreate(sp, rc, errorMessage);
|
2010-06-28 09:10:20 +02:00
|
|
|
}
|
|
|
|
|
|
2010-11-10 11:39:01 +01:00
|
|
|
void DebuggerPlugin::extensionsInitialized()
|
2010-11-05 13:35:31 +01:00
|
|
|
{
|
2010-11-10 11:39:01 +01:00
|
|
|
theDebuggerCore->extensionsInitialized();
|
2010-11-05 13:35:31 +01:00
|
|
|
}
|
|
|
|
|
|
2010-11-10 11:39:01 +01:00
|
|
|
bool DebuggerPlugin::isActiveDebugLanguage(int language)
|
2010-10-20 12:13:28 +02:00
|
|
|
{
|
2010-11-10 11:39:01 +01:00
|
|
|
return theDebuggerCore->isActiveDebugLanguage(language);
|
2010-10-20 12:13:28 +02:00
|
|
|
}
|
|
|
|
|
|
2010-12-06 08:51:46 +01:00
|
|
|
DebuggerMainWindow *DebuggerPlugin::mainWindow()
|
|
|
|
|
{
|
|
|
|
|
return theDebuggerCore->m_mainWindow;
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-16 10:47:06 +01:00
|
|
|
QAction *DebuggerPlugin::visibleDebugAction()
|
|
|
|
|
{
|
2011-08-03 18:57:37 +02:00
|
|
|
return theDebuggerCore->m_visibleStartAction;
|
2011-02-16 10:47:06 +01:00
|
|
|
}
|
|
|
|
|
|
2012-01-23 16:45:00 +01:00
|
|
|
|
|
|
|
|
#ifdef WITH_TESTS
|
|
|
|
|
|
2012-01-25 17:28:06 +01:00
|
|
|
void DebuggerPluginPrivate::testLoadProject(const QString &proFile, const TestCallBack &cb)
|
2012-01-23 16:45:00 +01:00
|
|
|
{
|
|
|
|
|
ProjectExplorerPlugin *pe = ProjectExplorerPlugin::instance();
|
|
|
|
|
connect(pe, SIGNAL(currentProjectChanged(ProjectExplorer::Project*)),
|
|
|
|
|
this, SLOT(testProjectLoaded(ProjectExplorer::Project*)));
|
|
|
|
|
|
2012-01-25 17:28:06 +01:00
|
|
|
m_testCallbacks.append(cb);
|
2012-01-23 16:45:00 +01:00
|
|
|
QString error;
|
2012-01-25 17:28:06 +01:00
|
|
|
if (pe->openProject(proFile, &error))
|
|
|
|
|
return; // Will end up in callback.
|
2012-01-23 16:45:00 +01:00
|
|
|
|
2012-01-25 17:28:06 +01:00
|
|
|
// Eat the unused callback.
|
|
|
|
|
qWarning("Cannot open %s: %s", qPrintable(proFile), qPrintable(error));
|
|
|
|
|
QVERIFY(false);
|
|
|
|
|
m_testCallbacks.pop_back();
|
2012-01-23 16:45:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DebuggerPluginPrivate::testProjectLoaded(Project *project)
|
|
|
|
|
{
|
|
|
|
|
if (!project) {
|
|
|
|
|
qWarning("Changed to null project.");
|
|
|
|
|
return;
|
|
|
|
|
}
|
2012-01-25 17:28:06 +01:00
|
|
|
ProjectExplorerPlugin *pe = ProjectExplorerPlugin::instance();
|
|
|
|
|
disconnect(pe, SIGNAL(currentProjectChanged(ProjectExplorer::Project*)),
|
|
|
|
|
this, SLOT(testProjectLoaded(ProjectExplorer::Project*)));
|
|
|
|
|
|
2012-02-14 16:43:51 +01:00
|
|
|
QString fileName = project->document()->fileName();
|
2012-01-23 16:45:00 +01:00
|
|
|
QVERIFY(!fileName.isEmpty());
|
|
|
|
|
qWarning("Project %s loaded", qPrintable(fileName));
|
|
|
|
|
|
2012-01-25 17:28:06 +01:00
|
|
|
QVERIFY(!m_testCallbacks.isEmpty());
|
|
|
|
|
TestCallBack cb = m_testCallbacks.takeLast();
|
|
|
|
|
invoke<void>(cb.receiver, cb.slot);
|
|
|
|
|
}
|
2012-01-23 16:45:00 +01:00
|
|
|
|
2012-01-25 17:28:06 +01:00
|
|
|
void DebuggerPluginPrivate::testUnloadProject()
|
|
|
|
|
{
|
|
|
|
|
ProjectExplorerPlugin *pe = ProjectExplorerPlugin::instance();
|
|
|
|
|
invoke<void>(pe, "unloadProject");
|
|
|
|
|
}
|
2012-01-23 16:45:00 +01:00
|
|
|
|
2012-01-25 17:28:06 +01:00
|
|
|
static Target *activeTarget()
|
|
|
|
|
{
|
2012-04-24 15:49:09 +02:00
|
|
|
Project *project = ProjectExplorerPlugin::instance()->currentProject();
|
2012-01-25 17:28:06 +01:00
|
|
|
return project->activeTarget();
|
|
|
|
|
}
|
2012-01-23 16:45:00 +01:00
|
|
|
|
2012-09-03 18:31:44 +02:00
|
|
|
static Kit *currentKit()
|
2012-01-25 17:28:06 +01:00
|
|
|
{
|
2012-04-24 15:49:09 +02:00
|
|
|
Target *t = activeTarget();
|
|
|
|
|
if (!t || !t->isEnabled())
|
|
|
|
|
return 0;
|
2012-09-03 18:31:44 +02:00
|
|
|
return activeTarget()->kit();
|
2012-01-25 17:28:06 +01:00
|
|
|
}
|
2012-01-23 16:45:00 +01:00
|
|
|
|
2012-01-25 17:28:06 +01:00
|
|
|
static LocalApplicationRunConfiguration *activeLocalRunConfiguration()
|
|
|
|
|
{
|
2012-04-24 15:49:09 +02:00
|
|
|
return qobject_cast<LocalApplicationRunConfiguration *>(activeTarget()->activeRunConfiguration());
|
2012-01-25 17:28:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DebuggerPluginPrivate::testRunProject(const DebuggerStartParameters &sp, const TestCallBack &cb)
|
|
|
|
|
{
|
|
|
|
|
m_testCallbacks.append(cb);
|
2012-08-15 13:21:37 +02:00
|
|
|
RunControl *rc = DebuggerRunControlFactory::createAndScheduleRun(sp);
|
|
|
|
|
connect(rc, SIGNAL(finished()), this, SLOT(testRunControlFinished()));
|
2012-01-23 16:45:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DebuggerPluginPrivate::testRunControlFinished()
|
|
|
|
|
{
|
2012-01-25 17:28:06 +01:00
|
|
|
QVERIFY(!m_testCallbacks.isEmpty());
|
|
|
|
|
TestCallBack cb = m_testCallbacks.takeLast();
|
|
|
|
|
ExtensionSystem::invoke<void>(cb.receiver, cb.slot);
|
|
|
|
|
}
|
2012-01-23 16:45:00 +01:00
|
|
|
|
2012-01-25 17:28:06 +01:00
|
|
|
void DebuggerPluginPrivate::testFinished()
|
|
|
|
|
{
|
2012-01-23 16:45:00 +01:00
|
|
|
QTestEventLoop::instance().exitLoop();
|
2012-01-25 17:28:06 +01:00
|
|
|
QVERIFY(m_testSuccess);
|
2012-01-23 16:45:00 +01:00
|
|
|
}
|
|
|
|
|
|
2012-01-25 17:28:06 +01:00
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2012-01-23 16:45:00 +01:00
|
|
|
void DebuggerPlugin::testPythonDumpers()
|
|
|
|
|
{
|
2012-01-25 17:28:06 +01:00
|
|
|
theDebuggerCore->testPythonDumpers1();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DebuggerPluginPrivate::testPythonDumpers1()
|
|
|
|
|
{
|
|
|
|
|
m_testSuccess = true;
|
|
|
|
|
QString proFile = ICore::resourcePath()
|
2012-09-27 11:31:34 +02:00
|
|
|
#ifndef Q_OS_MAC
|
|
|
|
|
+ QLatin1String("/../..")
|
|
|
|
|
#endif
|
|
|
|
|
+ QLatin1String("/tests/manual/debugger/simple/simple.pro");
|
2012-01-25 17:28:06 +01:00
|
|
|
testLoadProject(proFile, TestCallBack(this, "testPythonDumpers2"));
|
|
|
|
|
QVERIFY(m_testSuccess);
|
|
|
|
|
QTestEventLoop::instance().enterLoop(20);
|
2012-01-23 16:45:00 +01:00
|
|
|
}
|
|
|
|
|
|
2012-01-25 17:28:06 +01:00
|
|
|
void DebuggerPluginPrivate::testPythonDumpers2()
|
|
|
|
|
{
|
|
|
|
|
DebuggerStartParameters sp;
|
2012-09-03 18:31:44 +02:00
|
|
|
fillParameters(&sp, currentKit());
|
2012-01-25 17:28:06 +01:00
|
|
|
sp.executable = activeLocalRunConfiguration()->executable();
|
|
|
|
|
testRunProject(sp, TestCallBack(this, "testPythonDumpers3"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DebuggerPluginPrivate::testPythonDumpers3()
|
|
|
|
|
{
|
|
|
|
|
testUnloadProject();
|
|
|
|
|
testFinished();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
void DebuggerPlugin::testStateMachine()
|
|
|
|
|
{
|
|
|
|
|
theDebuggerCore->testStateMachine1();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DebuggerPluginPrivate::testStateMachine1()
|
|
|
|
|
{
|
|
|
|
|
m_testSuccess = true;
|
|
|
|
|
QString proFile = ICore::resourcePath()
|
2012-08-22 11:58:33 +02:00
|
|
|
+ QLatin1String("/../../tests/manual/debugger/simple/simple.pro");
|
2012-01-25 17:28:06 +01:00
|
|
|
testLoadProject(proFile, TestCallBack(this, "testStateMachine2"));
|
|
|
|
|
QVERIFY(m_testSuccess);
|
|
|
|
|
QTestEventLoop::instance().enterLoop(20);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DebuggerPluginPrivate::testStateMachine2()
|
|
|
|
|
{
|
|
|
|
|
DebuggerStartParameters sp;
|
2012-09-03 18:31:44 +02:00
|
|
|
fillParameters(&sp, currentKit());
|
2012-01-25 17:28:06 +01:00
|
|
|
sp.executable = activeLocalRunConfiguration()->executable();
|
|
|
|
|
sp.testCase = TestNoBoundsOfCurrentFunction;
|
|
|
|
|
testRunProject(sp, TestCallBack(this, "testStateMachine3"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DebuggerPluginPrivate::testStateMachine3()
|
|
|
|
|
{
|
|
|
|
|
testUnloadProject();
|
|
|
|
|
testFinished();
|
|
|
|
|
}
|
2012-01-26 13:14:00 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
void DebuggerPlugin::testBenchmark()
|
|
|
|
|
{
|
|
|
|
|
theDebuggerCore->testBenchmark1();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enum FakeEnum { FakeDebuggerCommonSettingsId };
|
|
|
|
|
|
|
|
|
|
void DebuggerPluginPrivate::testBenchmark1()
|
|
|
|
|
{
|
|
|
|
|
#ifdef WITH_BENCHMARK
|
|
|
|
|
CALLGRIND_START_INSTRUMENTATION;
|
|
|
|
|
volatile Core::Id id1 = Core::Id(DEBUGGER_COMMON_SETTINGS_ID);
|
|
|
|
|
CALLGRIND_STOP_INSTRUMENTATION;
|
|
|
|
|
CALLGRIND_DUMP_STATS;
|
|
|
|
|
|
|
|
|
|
CALLGRIND_START_INSTRUMENTATION;
|
|
|
|
|
volatile FakeEnum id2 = FakeDebuggerCommonSettingsId;
|
|
|
|
|
CALLGRIND_STOP_INSTRUMENTATION;
|
|
|
|
|
CALLGRIND_DUMP_STATS;
|
2012-01-23 16:45:00 +01:00
|
|
|
#endif
|
2012-01-26 13:14:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif // if WITH_TESTS
|
2012-01-23 16:45:00 +01:00
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
} // namespace Debugger
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
#include "debuggerplugin.moc"
|
|
|
|
|
|
2010-08-31 13:07:33 +02:00
|
|
|
Q_EXPORT_PLUGIN(Debugger::DebuggerPlugin)
|