2012-10-02 09:12:39 +02:00
|
|
|
/****************************************************************************
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2016-01-15 14:57:40 +01:00
|
|
|
** Copyright (C) 2016 The Qt Company Ltd.
|
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
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
|
2016-01-15 14:57:40 +01:00
|
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
|
|
|
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
|
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
2008-12-02 14:17:16 +01:00
|
|
|
**
|
2016-01-15 14:57:40 +01:00
|
|
|
** GNU General Public License Usage
|
|
|
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
|
|
|
** General Public License version 3 as published by the Free Software
|
|
|
|
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
|
|
|
|
** included in the packaging of this file. Please review the following
|
|
|
|
|
** information to ensure the GNU General Public License requirements will
|
|
|
|
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
2010-12-17 16:01:08 +01:00
|
|
|
**
|
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"
|
|
|
|
|
|
2016-02-29 12:11:18 +01:00
|
|
|
#include "debuggermainwindow.h"
|
2011-01-10 10:14:23 +01:00
|
|
|
#include "debuggerstartparameters.h"
|
2009-03-17 17:00:06 +01:00
|
|
|
#include "debuggeractions.h"
|
2011-04-21 15:52:51 +02:00
|
|
|
#include "debuggerinternalconstants.h"
|
2010-11-10 11:39:01 +01:00
|
|
|
#include "debuggercore.h"
|
2013-08-14 18:30:40 +02:00
|
|
|
#include "debuggerkitconfigwidget.h"
|
2010-06-16 11:08:54 +02:00
|
|
|
#include "debuggerdialogs.h"
|
|
|
|
|
#include "debuggerengine.h"
|
2015-11-23 16:41:54 +01:00
|
|
|
#include "debuggericons.h"
|
2016-03-09 19:16:14 +01:00
|
|
|
#include "debuggeritem.h"
|
2013-10-25 13:47:08 +02:00
|
|
|
#include "debuggeritemmanager.h"
|
2010-12-02 17:43:14 +01:00
|
|
|
#include "debuggermainwindow.h"
|
2013-03-27 13:03:15 +01:00
|
|
|
#include "debuggerrunconfigurationaspect.h"
|
2014-10-17 13:40:04 +02:00
|
|
|
#include "debuggerruncontrol.h"
|
2013-10-25 13:47:08 +02:00
|
|
|
#include "debuggeroptionspage.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 "breakhandler.h"
|
2011-04-12 17:32:41 +02:00
|
|
|
#include "disassemblerlines.h"
|
2010-09-22 16:20:08 +02:00
|
|
|
#include "logwindow.h"
|
2011-01-10 10:14:23 +01:00
|
|
|
#include "moduleshandler.h"
|
2010-06-16 11:08:54 +02:00
|
|
|
#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"
|
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"
|
2013-09-20 16:48:01 +02:00
|
|
|
#include "unstartedappwatcherdialog.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"
|
2013-01-24 16:33:17 +01:00
|
|
|
#include "sourceutils.h"
|
2015-11-10 16:59:02 +01:00
|
|
|
#include "shared/hostutils.h"
|
|
|
|
|
#include "console/console.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
|
|
|
|
2016-02-24 14:42:52 +01:00
|
|
|
#include "analyzer/analyzerconstants.h"
|
|
|
|
|
#include "analyzer/analyzermanager.h"
|
2016-03-02 13:57:37 +01:00
|
|
|
#include "analyzer/analyzerruncontrol.h"
|
|
|
|
|
#include "analyzer/analyzerstartparameters.h"
|
2016-02-24 14:42:52 +01:00
|
|
|
|
2010-03-18 10:59:06 +01:00
|
|
|
#include <coreplugin/actionmanager/actioncontainer.h>
|
2016-02-29 12:11:18 +01:00
|
|
|
#include <coreplugin/actionmanager/actionmanager.h>
|
2015-02-26 13:38:54 +01:00
|
|
|
#include <coreplugin/actionmanager/command.h>
|
2016-02-29 12:11:18 +01:00
|
|
|
#include <coreplugin/coreconstants.h>
|
|
|
|
|
#include <coreplugin/editormanager/documentmodel.h>
|
|
|
|
|
#include <coreplugin/editormanager/editormanager.h>
|
|
|
|
|
#include <coreplugin/find/itemviewfind.h>
|
2008-12-02 12:01:29 +01:00
|
|
|
#include <coreplugin/icore.h>
|
2016-02-29 12:11:18 +01:00
|
|
|
#include <coreplugin/imode.h>
|
2014-11-25 13:08:18 +01:00
|
|
|
#include <coreplugin/messagebox.h>
|
2013-03-05 11:10:33 +01:00
|
|
|
#include <coreplugin/messagemanager.h>
|
2008-12-02 12:01:29 +01:00
|
|
|
#include <coreplugin/modemanager.h>
|
2016-03-02 13:57:37 +01:00
|
|
|
#include <coreplugin/modemanager.h>
|
2016-02-29 12:11:18 +01:00
|
|
|
#include <coreplugin/navigationwidget.h>
|
|
|
|
|
#include <coreplugin/outputpane.h>
|
|
|
|
|
#include <coreplugin/rightpane.h>
|
2008-12-09 16:18:28 +01:00
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
#include <cppeditor/cppeditorconstants.h>
|
2014-09-15 00:12:27 +02:00
|
|
|
#include <cpptools/cppmodelmanager.h>
|
2008-12-09 16:18:28 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
#include <projectexplorer/buildconfiguration.h>
|
2012-10-31 18:14:17 +01:00
|
|
|
#include <projectexplorer/buildmanager.h>
|
2012-08-08 12:03:07 +02:00
|
|
|
#include <projectexplorer/devicesupport/deviceprocessesdialog.h>
|
2016-03-02 13:57:37 +01:00
|
|
|
#include <projectexplorer/devicesupport/deviceprocesslist.h>
|
|
|
|
|
#include <projectexplorer/project.h>
|
2011-10-25 18:23:37 +08:00
|
|
|
#include <projectexplorer/projectexplorer.h>
|
2015-11-23 16:41:54 +01:00
|
|
|
#include <projectexplorer/projectexplorericons.h>
|
2011-10-25 18:23:37 +08:00
|
|
|
#include <projectexplorer/projectexplorersettings.h>
|
2016-03-02 13:57:37 +01:00
|
|
|
#include <projectexplorer/projecttree.h>
|
2016-02-29 12:11:18 +01:00
|
|
|
#include <projectexplorer/runconfiguration.h>
|
2016-01-25 15:00:20 +01:00
|
|
|
#include <projectexplorer/runnables.h>
|
2008-12-02 12:01:29 +01:00
|
|
|
#include <projectexplorer/session.h>
|
2010-07-21 17:06:22 +02:00
|
|
|
#include <projectexplorer/target.h>
|
2016-03-02 13:57:37 +01:00
|
|
|
#include <projectexplorer/taskhub.h>
|
|
|
|
|
#include <projectexplorer/toolchain.h>
|
2010-11-08 16:17:59 +01:00
|
|
|
|
2014-09-26 09:14:03 +02:00
|
|
|
#include <texteditor/texteditor.h>
|
2015-02-26 13:22:35 +01:00
|
|
|
#include <texteditor/textdocument.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
|
|
|
|
2016-02-29 12:11:18 +01:00
|
|
|
#include <utils/algorithm.h>
|
|
|
|
|
#include <utils/appmainwindow.h>
|
2014-06-04 14:45:10 +02:00
|
|
|
#include <utils/basetreeview.h>
|
2016-03-02 13:57:37 +01:00
|
|
|
#include <utils/checkablemessagebox.h>
|
2016-02-29 12:11:18 +01:00
|
|
|
#include <utils/fancymainwindow.h>
|
2012-08-23 15:53:58 +02:00
|
|
|
#include <utils/hostosinfo.h>
|
2015-02-04 09:32:46 +01:00
|
|
|
#include <utils/mimetypes/mimedatabase.h>
|
2011-01-12 16:36:29 +01:00
|
|
|
#include <utils/proxyaction.h>
|
2014-06-04 14:45:10 +02:00
|
|
|
#include <utils/qtcassert.h>
|
|
|
|
|
#include <utils/savedaction.h>
|
2011-03-16 13:49:28 +01:00
|
|
|
#include <utils/statuslabel.h>
|
2014-06-04 14:45:10 +02:00
|
|
|
#include <utils/styledbar.h>
|
2016-08-03 17:55:54 +02:00
|
|
|
#include <utils/utilsicons.h>
|
2014-02-19 15:35:58 +01:00
|
|
|
#include <utils/winutils.h>
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2016-02-29 12:11:18 +01:00
|
|
|
#include <QAction>
|
2014-05-18 15:43:20 +10:00
|
|
|
#include <QApplication>
|
2014-05-16 17:32:07 +02:00
|
|
|
#include <QCheckBox>
|
2013-06-07 17:57:25 +02:00
|
|
|
#include <QComboBox>
|
2016-02-29 12:11:18 +01:00
|
|
|
#include <QDebug>
|
2016-03-02 13:57:37 +01:00
|
|
|
#include <QDialog>
|
|
|
|
|
#include <QDialogButtonBox>
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QDockWidget>
|
|
|
|
|
#include <QFileDialog>
|
2014-05-16 17:32:07 +02:00
|
|
|
#include <QHBoxLayout>
|
|
|
|
|
#include <QHeaderView>
|
2012-06-05 10:25:48 +02:00
|
|
|
#include <QInputDialog>
|
2016-02-29 12:11:18 +01:00
|
|
|
#include <QMenu>
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QMessageBox>
|
2016-03-02 13:57:37 +01:00
|
|
|
#include <QPointer>
|
|
|
|
|
#include <QPushButton>
|
|
|
|
|
#include <QSettings>
|
2016-03-01 07:51:06 +01:00
|
|
|
#include <QStackedWidget>
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QTextBlock>
|
|
|
|
|
#include <QToolButton>
|
|
|
|
|
#include <QTreeWidget>
|
2014-06-04 14:45:10 +02:00
|
|
|
#include <QVBoxLayout>
|
2016-03-02 13:57:37 +01:00
|
|
|
#include <QVariant>
|
2016-02-29 12:11:18 +01:00
|
|
|
#include <QtPlugin>
|
2014-06-04 14:45:10 +02:00
|
|
|
|
2012-01-23 16:45:00 +01:00
|
|
|
#ifdef WITH_TESTS
|
2016-03-09 19:16:14 +01:00
|
|
|
|
|
|
|
|
#include <cpptools/cpptoolstestcase.h>
|
|
|
|
|
#include <cpptools/projectinfo.h>
|
|
|
|
|
|
2016-05-18 07:33:52 +02:00
|
|
|
#include <utils/executeondestruction.h>
|
|
|
|
|
|
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)
|
2012-11-28 20:44:03 +02:00
|
|
|
# define STATE_DEBUG(s) do { qDebug() << s; } while (0)
|
2010-06-16 11:08:54 +02:00
|
|
|
#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
|
|
|
|
|
|
2013-06-05 14:29:24 +02:00
|
|
|
\brief The DebuggerEngine class is the base class of a debugger engine.
|
2011-01-26 17:22:25 +01:00
|
|
|
|
2013-09-06 17:16:18 +02:00
|
|
|
\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} + + +
|
|
|
|
|
+ + + +
|
2015-06-16 15:01:46 +02:00
|
|
|
+ + + +
|
2011-01-26 17:22:25 +01:00
|
|
|
+ + + +
|
|
|
|
|
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
|
2013-06-05 14:29:24 +02:00
|
|
|
\brief The GdbEngine class implements Debugger::Engine driving a GDB
|
|
|
|
|
executable.
|
2011-01-26 17:22:25 +01:00
|
|
|
|
|
|
|
|
GdbEngine specific startup. All happens in EngineSetupRequested state:
|
|
|
|
|
|
2013-09-06 17:16:18 +02:00
|
|
|
\list
|
|
|
|
|
\li Transitions marked by '---' are done in the individual adapters.
|
2011-01-26 17:22:25 +01:00
|
|
|
|
2013-09-06 17:16:18 +02:00
|
|
|
\li Transitions marked by '+-+' are done in the GdbEngine.
|
|
|
|
|
\endlist
|
2011-01-26 17:22:25 +01:00
|
|
|
|
|
|
|
|
\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;
|
2016-03-09 19:16:14 +01:00
|
|
|
using namespace Core::Constants;
|
2009-01-13 18:15:24 +01:00
|
|
|
using namespace Debugger::Constants;
|
2014-10-22 13:04:47 +02:00
|
|
|
using namespace Debugger::Internal;
|
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 {
|
2010-11-24 11:44:43 +01:00
|
|
|
namespace Internal {
|
|
|
|
|
|
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);
|
2015-05-27 16:09:43 +02:00
|
|
|
QObject *createDebuggerRunControlFactory(QObject *parent);
|
2010-11-26 15:10:10 +01:00
|
|
|
|
2016-04-24 22:51:24 +02:00
|
|
|
static QIcon visibleStartIcon(Id id, bool toolBarStyle)
|
|
|
|
|
{
|
|
|
|
|
if (id == Id(Constants::DEBUG)) {
|
|
|
|
|
const static QIcon sidebarIcon =
|
|
|
|
|
Icon::sideBarIcon(ProjectExplorer::Icons::DEBUG_START, ProjectExplorer::Icons::DEBUG_START_FLAT);
|
|
|
|
|
const static QIcon icon =
|
|
|
|
|
Icon::combinedIcon({ProjectExplorer::Icons::DEBUG_START_SMALL.icon(), sidebarIcon});
|
|
|
|
|
const static QIcon iconToolBar =
|
|
|
|
|
Icon::combinedIcon({ProjectExplorer::Icons::DEBUG_START_SMALL_TOOLBAR.icon(), sidebarIcon});
|
|
|
|
|
return toolBarStyle ? iconToolBar : icon;
|
|
|
|
|
} else if (id == Id(Constants::CONTINUE)) {
|
|
|
|
|
const static QIcon sidebarIcon =
|
|
|
|
|
Icon::sideBarIcon(Icons::CONTINUE, Icons::CONTINUE_FLAT);
|
|
|
|
|
const static QIcon icon =
|
|
|
|
|
Icon::combinedIcon({Icons::DEBUG_CONTINUE_SMALL.icon(), sidebarIcon});
|
|
|
|
|
const static QIcon iconToolBar =
|
|
|
|
|
Icon::combinedIcon({Icons::DEBUG_CONTINUE_SMALL_TOOLBAR.icon(), sidebarIcon});
|
|
|
|
|
return toolBarStyle ? iconToolBar : icon;
|
|
|
|
|
} else if (id == Id(Constants::INTERRUPT)) {
|
|
|
|
|
const static QIcon sidebarIcon =
|
|
|
|
|
Icon::sideBarIcon(Icons::INTERRUPT, Icons::INTERRUPT_FLAT);
|
|
|
|
|
const static QIcon icon =
|
|
|
|
|
Icon::combinedIcon({Icons::DEBUG_INTERRUPT_SMALL.icon(), sidebarIcon});
|
|
|
|
|
const static QIcon iconToolBar =
|
|
|
|
|
Icon::combinedIcon({Icons::DEBUG_INTERRUPT_SMALL_TOOLBAR.icon(), sidebarIcon});
|
|
|
|
|
return toolBarStyle ? iconToolBar : icon;
|
|
|
|
|
}
|
|
|
|
|
return QIcon();
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-03 23:58:49 +02:00
|
|
|
static void setProxyAction(ProxyAction *proxy, Id id)
|
2012-05-24 10:19:50 +02:00
|
|
|
{
|
2012-07-18 16:20:19 +02:00
|
|
|
proxy->setAction(ActionManager::command(id)->action());
|
2016-04-24 22:51:24 +02:00
|
|
|
proxy->setIcon(visibleStartIcon(id, true));
|
2012-05-24 10:19:50 +02:00
|
|
|
}
|
|
|
|
|
|
2016-07-18 12:36:31 +02:00
|
|
|
QAction *addAction(QMenu *menu, const QString &display, bool on,
|
|
|
|
|
const std::function<void()> &onTriggered)
|
|
|
|
|
{
|
|
|
|
|
QAction *act = menu->addAction(display);
|
|
|
|
|
act->setEnabled(on);
|
|
|
|
|
QObject::connect(act, &QAction::triggered, onTriggered);
|
|
|
|
|
return act;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
QAction *addAction(QMenu *menu, const QString &d1, const QString &d2, bool on,
|
|
|
|
|
const std::function<void()> &onTriggered)
|
|
|
|
|
{
|
|
|
|
|
return on ? addAction(menu, d1, true, onTriggered) : addAction(menu, d2, false);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
QAction *addCheckableAction(QMenu *menu, const QString &display, bool on, bool checked,
|
|
|
|
|
const std::function<void()> &onTriggered)
|
|
|
|
|
{
|
|
|
|
|
QAction *act = addAction(menu, display, on, onTriggered);
|
|
|
|
|
act->setCheckable(true);
|
|
|
|
|
act->setChecked(checked);
|
|
|
|
|
return act;
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-23 13:44:37 +01:00
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
|
|
|
|
// DummyEngine
|
|
|
|
|
//
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
class DummyEngine : public DebuggerEngine
|
|
|
|
|
{
|
|
|
|
|
public:
|
2015-05-27 13:59:56 +02:00
|
|
|
DummyEngine() : DebuggerEngine(DebuggerRunParameters()) {}
|
2016-03-02 13:57:37 +01:00
|
|
|
~DummyEngine() override {}
|
|
|
|
|
|
|
|
|
|
void setupEngine() override {}
|
|
|
|
|
void setupInferior() override {}
|
|
|
|
|
void runEngine() override {}
|
|
|
|
|
void shutdownEngine() override {}
|
|
|
|
|
void shutdownInferior() override {}
|
|
|
|
|
bool hasCapability(unsigned cap) const override;
|
|
|
|
|
bool acceptsBreakpoint(Breakpoint) const override { return false; }
|
|
|
|
|
bool acceptsDebuggerCommands() const override { return false; }
|
|
|
|
|
void selectThread(ThreadId) override {}
|
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.
|
2014-11-19 17:58:33 +01:00
|
|
|
Project *project = ProjectTree::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:
|
2013-03-27 13:03:15 +01:00
|
|
|
if (activeRc->extraAspect<Debugger::DebuggerRunConfigurationAspect>()->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
|
|
|
|
|
//
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2016-03-10 08:53:49 +01:00
|
|
|
class DebugModeContext : public IContext
|
|
|
|
|
{
|
|
|
|
|
public:
|
2016-03-24 13:59:05 +01:00
|
|
|
DebugModeContext(QWidget *modeWindow)
|
2016-03-10 08:53:49 +01:00
|
|
|
{
|
|
|
|
|
setContext(Context(CC::C_EDITORMANAGER));
|
2016-03-24 13:59:05 +01:00
|
|
|
setWidget(modeWindow);
|
2016-03-10 08:53:49 +01:00
|
|
|
ICore::addContextObject(this);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2010-12-02 13:34:23 +01:00
|
|
|
class DebugMode : public IMode
|
2009-01-13 18:15:24 +01:00
|
|
|
{
|
|
|
|
|
public:
|
2016-03-24 13:59:05 +01:00
|
|
|
DebugMode()
|
2011-04-13 13:00:30 +02:00
|
|
|
{
|
|
|
|
|
setObjectName(QLatin1String("DebugMode"));
|
2014-07-01 13:20:53 +02:00
|
|
|
setContext(Context(C_DEBUGMODE, CC::C_NAVIGATION_PANE));
|
2011-04-13 16:09:04 +02:00
|
|
|
setDisplayName(DebuggerPlugin::tr("Debug"));
|
2015-11-11 19:26:58 +01:00
|
|
|
setIcon(Utils::Icon::modeIcon(Icons::MODE_DEBUGGER_CLASSIC,
|
|
|
|
|
Icons::MODE_DEBUGGER_FLAT, Icons::MODE_DEBUGGER_FLAT_ACTIVE));
|
2011-07-15 10:55:39 +02:00
|
|
|
setPriority(85);
|
2012-05-07 18:28:03 +02:00
|
|
|
setId(MODE_DEBUG);
|
2011-04-13 13:00:30 +02:00
|
|
|
}
|
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
|
|
|
|
|
//
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2014-06-06 00:53:31 +02:00
|
|
|
static QWidget *addSearch(BaseTreeView *treeView, const QString &title,
|
2016-07-18 12:36:31 +02:00
|
|
|
const QString &objectName)
|
2014-06-04 14:45:10 +02:00
|
|
|
{
|
2014-07-28 14:23:52 +02:00
|
|
|
QAction *act = action(UseAlternatingRowColors);
|
2014-06-04 14:45:10 +02:00
|
|
|
treeView->setAlternatingRowColors(act->isChecked());
|
2014-10-22 13:04:47 +02:00
|
|
|
QObject::connect(act, &QAction::toggled,
|
2016-07-18 12:36:31 +02:00
|
|
|
treeView, &BaseTreeView::setAlternatingRowColors);
|
2014-06-04 14:45:10 +02:00
|
|
|
|
2014-07-31 18:15:19 +02:00
|
|
|
QWidget *widget = ItemViewFind::createSearchableWrapper(treeView);
|
2016-07-18 12:36:31 +02:00
|
|
|
widget->setObjectName(objectName);
|
2014-06-04 14:45:10 +02:00
|
|
|
widget->setWindowTitle(title);
|
|
|
|
|
return widget;
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-23 09:09:20 +02:00
|
|
|
static std::function<bool(const Kit *)> cdbMatcher(char wordWidth = 0)
|
2012-08-23 15:23:37 +02:00
|
|
|
{
|
2014-07-23 09:09:20 +02:00
|
|
|
return [wordWidth](const Kit *k) -> bool {
|
2012-09-05 14:56:08 +02:00
|
|
|
if (DebuggerKitInformation::engineType(k) != CdbEngineType
|
2016-11-15 09:22:53 +01:00
|
|
|
|| DebuggerKitInformation::configurationErrors(k)) {
|
2012-08-23 15:23:37 +02:00
|
|
|
return false;
|
2012-09-05 14:56:08 +02:00
|
|
|
}
|
2016-07-13 10:40:05 +02:00
|
|
|
if (wordWidth)
|
|
|
|
|
ToolChainKitInformation::targetAbi(k).wordWidth();
|
2012-08-23 15:23:37 +02:00
|
|
|
return true;
|
2014-07-23 09:09:20 +02:00
|
|
|
};
|
|
|
|
|
}
|
2012-08-23 15:23:37 +02:00
|
|
|
|
2014-07-23 09:09:20 +02:00
|
|
|
// Find a CDB kit for debugging unknown processes.
|
|
|
|
|
// On a 64bit OS, prefer a 64bit debugger.
|
|
|
|
|
static Kit *findUniversalCdbKit()
|
|
|
|
|
{
|
|
|
|
|
if (Utils::is64BitWindowsSystem()) {
|
2016-02-02 18:26:51 +01:00
|
|
|
if (Kit *cdb64Kit = KitManager::find(KitMatcher(cdbMatcher(64))))
|
2014-07-23 09:09:20 +02:00
|
|
|
return cdb64Kit;
|
2012-08-23 15:23:37 +02:00
|
|
|
}
|
2016-02-02 18:26:51 +01:00
|
|
|
return KitManager::find(KitMatcher(cdbMatcher()));
|
2014-07-23 09:09:20 +02:00
|
|
|
}
|
2012-08-23 15:23:37 +02: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
|
|
|
|
2014-10-22 13:04:47 +02:00
|
|
|
static DebuggerPluginPrivate *dd = 0;
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2016-03-01 07:51:06 +01:00
|
|
|
//class DockWidgetEventFilter : public QObject
|
|
|
|
|
//{
|
|
|
|
|
//public:
|
|
|
|
|
// DockWidgetEventFilter() {}
|
2016-02-29 12:11:18 +01:00
|
|
|
|
2016-03-01 07:51:06 +01:00
|
|
|
//private:
|
|
|
|
|
// bool eventFilter(QObject *obj, QEvent *event) override;
|
|
|
|
|
//};
|
2016-02-29 12:11:18 +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.
|
|
|
|
|
*/
|
|
|
|
|
|
2014-10-22 13:04:47 +02:00
|
|
|
class DebuggerPluginPrivate : public QObject
|
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); }
|
2011-03-02 14:05:32 +01:00
|
|
|
DebuggerEngine *dummyEngine();
|
2010-02-09 20:44:40 +01:00
|
|
|
|
2015-06-12 11:55:57 +02:00
|
|
|
void setThreadBoxContents(const QStringList &list, int index)
|
2011-09-01 16:36:27 +02:00
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
}
|
2015-02-25 16:30:23 +01:00
|
|
|
|
|
|
|
|
DebuggerRunControl *attachToRunningProcess(Kit *kit, DeviceProcessItem process, bool contAfterAttach);
|
2011-09-01 16:36:27 +02:00
|
|
|
|
2011-02-22 12:05:25 +01:00
|
|
|
void writeSettings()
|
|
|
|
|
{
|
|
|
|
|
m_debuggerSettings->writeSettings();
|
2016-03-01 07:51:06 +01:00
|
|
|
// writeWindowSettings();
|
2011-02-22 12:05:25 +01:00
|
|
|
}
|
|
|
|
|
|
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
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
void breakpointSetMarginActionTriggered(bool isMessageOnly, const ContextData &data)
|
2010-11-08 15:41:44 +01:00
|
|
|
{
|
2011-06-27 10:37:57 +02:00
|
|
|
QString message;
|
2015-01-10 01:07:01 +01:00
|
|
|
if (isMessageOnly) {
|
2015-07-20 09:37:54 +02:00
|
|
|
if (data.type == LocationByAddress) {
|
2011-06-27 10:37:57 +02:00
|
|
|
//: Message tracepoint: Address hit.
|
|
|
|
|
message = tr("0x%1 hit").arg(data.address, 0, 16);
|
|
|
|
|
} else {
|
|
|
|
|
//: Message tracepoint: %1 file, %2 line %3 function hit.
|
2015-01-10 23:40:32 +02:00
|
|
|
message = tr("%1:%2 %3() hit").arg(FileName::fromString(data.fileName).fileName()).
|
2011-06-27 10:37:57 +02:00
|
|
|
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();
|
|
|
|
|
}
|
2015-07-20 09:37:54 +02:00
|
|
|
toggleBreakpoint(data, message);
|
2010-11-24 11:44:43 +01:00
|
|
|
}
|
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
|
|
|
{
|
2016-04-20 15:09:57 +02:00
|
|
|
if (m_shuttingDown)
|
|
|
|
|
return;
|
|
|
|
|
|
2014-06-04 14:45:10 +02:00
|
|
|
m_watchersView->header()->resizeSection(section, newSize);
|
|
|
|
|
m_returnView->header()->resizeSection(section, newSize);
|
2010-11-05 19:38:40 +01:00
|
|
|
}
|
2010-02-09 20:44:40 +01: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();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-21 08:50:28 +02:00
|
|
|
void reloadSourceFiles() { if (m_currentEngine) m_currentEngine->reloadSourceFiles(); }
|
|
|
|
|
void reloadRegisters() { if (m_currentEngine) m_currentEngine->reloadRegisters(); }
|
|
|
|
|
void reloadModules() { if (m_currentEngine) m_currentEngine->reloadModules(); }
|
|
|
|
|
|
2015-02-03 23:58:49 +02:00
|
|
|
void editorOpened(IEditor *editor);
|
|
|
|
|
void updateBreakMenuItem(IEditor *editor);
|
2010-06-16 11:08:54 +02:00
|
|
|
void setBusyCursor(bool busy);
|
2015-02-03 23:58:49 +02:00
|
|
|
void requestMark(TextEditorWidget *widget, int lineNumber,
|
|
|
|
|
TextMarkRequestKind kind);
|
|
|
|
|
void requestContextMenu(TextEditorWidget *widget,
|
2014-09-30 16:54:26 +02:00
|
|
|
int lineNumber, QMenu *menu);
|
2009-05-07 15:20:44 +02:00
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
void activatePreviousMode();
|
|
|
|
|
void activateDebugMode();
|
2015-07-20 09:37:54 +02:00
|
|
|
void toggleBreakpointHelper();
|
|
|
|
|
void toggleBreakpoint(const ContextData &location, const QString &tracePointMessage = QString());
|
2016-03-25 20:00:19 +01:00
|
|
|
void onModeChanged(Id mode);
|
2011-10-25 18:23:37 +08:00
|
|
|
void updateDebugWithoutDeployMenu();
|
2010-02-09 20:44:40 +01:00
|
|
|
|
2012-08-08 13:09:31 +02:00
|
|
|
void startAndDebugApplication();
|
2010-11-19 16:13:22 +01:00
|
|
|
void startRemoteCdbSession();
|
2015-02-25 16:30:23 +01:00
|
|
|
void startRemoteServerAndAttachToProcess();
|
2011-12-05 17:21:48 +01:00
|
|
|
void attachToRemoteServer();
|
2012-08-06 12:22:35 +02:00
|
|
|
void attachToRunningApplication();
|
2013-09-20 16:48:01 +02:00
|
|
|
void attachToUnstartedApplicationDialog();
|
2011-09-13 17:26:02 +02:00
|
|
|
void attachToQmlPort();
|
2016-03-09 19:16:14 +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-06-22 17:46:20 +02:00
|
|
|
void showStatusMessage(const QString &msg, int timeout = -1);
|
2010-11-10 11:39:01 +01:00
|
|
|
|
2010-12-10 10:01:29 +01:00
|
|
|
void runControlStarted(DebuggerEngine *engine);
|
|
|
|
|
void runControlFinished(DebuggerEngine *engine);
|
2015-03-09 10:59:58 +02:00
|
|
|
void remoteCommand(const QStringList &options);
|
2010-11-10 11:39:01 +01: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
|
|
|
|
2015-02-03 23:58:49 +02:00
|
|
|
void fontSettingsChanged(const FontSettings &settings);
|
2010-06-16 11:08:54 +02:00
|
|
|
|
|
|
|
|
void updateState(DebuggerEngine *engine);
|
2015-02-03 23:58:49 +02:00
|
|
|
void onCurrentProjectChanged(Project *project);
|
2010-06-16 11:08:54 +02:00
|
|
|
|
|
|
|
|
void sessionLoaded();
|
|
|
|
|
void aboutToUnloadSession();
|
|
|
|
|
void aboutToSaveSession();
|
2010-06-22 12:41:02 +02:00
|
|
|
|
2010-10-22 12:26:13 +02:00
|
|
|
void coreShutdown();
|
2010-08-26 16:02:41 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
public:
|
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
|
|
|
|
2014-06-05 17:22:51 +02:00
|
|
|
void handleReset()
|
|
|
|
|
{
|
|
|
|
|
currentEngine()->resetLocation();
|
|
|
|
|
currentEngine()->resetInferior();
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-08 15:19:13 +01:00
|
|
|
void handleExecStep()
|
|
|
|
|
{
|
2011-05-02 18:22:32 +02:00
|
|
|
if (currentEngine()->state() == DebuggerNotReady) {
|
2015-06-29 10:36:29 +03:00
|
|
|
ProjectExplorerPlugin::runStartupProject(ProjectExplorer::Constants::DEBUG_RUN_MODE_WITH_BREAK_ON_MAIN);
|
2011-05-02 18:22:32 +02:00
|
|
|
} 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) {
|
2015-06-29 10:36:29 +03:00
|
|
|
ProjectExplorerPlugin::runStartupProject(ProjectExplorer::Constants::DEBUG_RUN_MODE_WITH_BREAK_ON_MAIN);
|
2011-05-02 18:22:32 +02:00
|
|
|
} 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()
|
|
|
|
|
{
|
2010-12-14 12:21:29 +01:00
|
|
|
currentEngine()->resetLocation();
|
2015-07-20 09:37:54 +02:00
|
|
|
if (BaseTextEditor *textEditor = BaseTextEditor::currentTextEditor()) {
|
|
|
|
|
ContextData location = getLocationContext(textEditor->textDocument(),
|
|
|
|
|
textEditor->currentLine());
|
|
|
|
|
if (location.isValid())
|
|
|
|
|
currentEngine()->executeJumpToLine(location);
|
|
|
|
|
}
|
2010-11-08 15:19:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void handleExecRunToLine()
|
|
|
|
|
{
|
2010-12-14 12:21:29 +01:00
|
|
|
currentEngine()->resetLocation();
|
2015-07-20 09:37:54 +02:00
|
|
|
if (BaseTextEditor *textEditor = BaseTextEditor::currentTextEditor()) {
|
|
|
|
|
ContextData location = getLocationContext(textEditor->textDocument(),
|
|
|
|
|
textEditor->currentLine());
|
|
|
|
|
if (location.isValid())
|
|
|
|
|
currentEngine()->executeRunToLine(location);
|
|
|
|
|
}
|
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
|
|
|
{
|
2014-07-23 19:10:38 +02:00
|
|
|
BaseTextEditor *textEditor = BaseTextEditor::currentTextEditor();
|
2010-11-08 16:17:59 +01:00
|
|
|
QTC_ASSERT(textEditor, return);
|
2014-08-27 11:57:32 +02:00
|
|
|
QTextCursor cursor = textEditor->textCursor();
|
2010-11-08 16:17:59 +01:00
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void handleAddToWatchWindow()
|
|
|
|
|
{
|
|
|
|
|
// Requires a selection, but that's the only case we want anyway.
|
2014-08-27 11:57:32 +02:00
|
|
|
BaseTextEditor *textEditor = BaseTextEditor::currentTextEditor();
|
2010-11-08 15:19:13 +01:00
|
|
|
if (!textEditor)
|
|
|
|
|
return;
|
2014-08-27 11:57:32 +02:00
|
|
|
QTextCursor tc = textEditor->textCursor();
|
2010-11-08 15:19:13 +01:00
|
|
|
QString exp;
|
|
|
|
|
if (tc.hasSelection()) {
|
|
|
|
|
exp = tc.selectedText();
|
|
|
|
|
} else {
|
|
|
|
|
int line, column;
|
2014-09-19 15:26:41 +02:00
|
|
|
exp = cppExpressionAt(textEditor->editorWidget(), tc.position(), &line, &column);
|
2010-11-08 15:19:13 +01:00
|
|
|
}
|
2013-01-09 14:51:49 +01:00
|
|
|
if (currentEngine()->hasCapability(WatchComplexExpressionsCapability))
|
|
|
|
|
exp = removeObviousSideEffects(exp);
|
|
|
|
|
else
|
|
|
|
|
exp = fixCppExpression(exp);
|
2015-03-19 22:35:39 +02:00
|
|
|
exp = exp.trimmed();
|
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.
|
2015-03-04 17:43:59 +01:00
|
|
|
if (DebuggerEngine *cppEngine = currentEngine()->cppEngine()) {
|
|
|
|
|
if (cppEngine->stackHandler()->currentIndex() >= 0) {
|
|
|
|
|
const StackFrame frame = cppEngine->stackHandler()->currentFrame();
|
|
|
|
|
if (operateByInstructionTriggered || frame.isUsable())
|
|
|
|
|
cppEngine->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
|
|
|
void showMessage(const QString &msg, int channel, int timeout = -1);
|
|
|
|
|
|
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);
|
2013-03-05 11:10:33 +01:00
|
|
|
void parseCommandLineArguments();
|
2011-02-08 13:48:04 +01:00
|
|
|
|
2016-02-29 12:11:18 +01:00
|
|
|
// Called when all dependent plugins have loaded.
|
|
|
|
|
void initialize();
|
|
|
|
|
|
|
|
|
|
void updateUiForProject(ProjectExplorer::Project *project);
|
|
|
|
|
void updateUiForTarget(ProjectExplorer::Target *target);
|
|
|
|
|
void updateUiForRunConfiguration(ProjectExplorer::RunConfiguration *rc);
|
|
|
|
|
void updateActiveLanguages();
|
2012-04-18 14:20:54 +02:00
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
public:
|
2016-03-24 13:59:05 +01:00
|
|
|
QPointer<DebuggerMainWindow> m_mainWindow;
|
|
|
|
|
QPointer<QWidget> m_modeWindow;
|
|
|
|
|
QPointer<DebugMode> m_mode;
|
2016-03-02 13:57:37 +01:00
|
|
|
|
|
|
|
|
QHash<Id, ActionDescription> m_descriptions;
|
|
|
|
|
ActionContainer *m_menu = 0;
|
2016-02-29 12:11:18 +01:00
|
|
|
|
2016-03-01 07:51:06 +01:00
|
|
|
// DockWidgetEventFilter m_resizeEventFilter;
|
2016-02-29 12:11:18 +01:00
|
|
|
|
|
|
|
|
QHash<DebuggerLanguage, Core::Context> m_contextsForLanguage;
|
|
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
Project *m_previousProject = 0;
|
2016-03-17 14:32:06 +01:00
|
|
|
QPointer<Target> m_previousTarget;
|
2016-03-02 13:57:37 +01:00
|
|
|
QPointer<RunConfiguration> m_previousRunConfiguration;
|
2016-02-29 12:11:18 +01:00
|
|
|
|
2012-05-07 18:28:03 +02:00
|
|
|
Id m_previousMode;
|
2015-06-24 08:26:35 +02:00
|
|
|
QVector<QPair<DebuggerRunParameters, Kit *>> m_scheduledStarts;
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2016-02-29 12:11:18 +01:00
|
|
|
ProxyAction *m_visibleStartAction = 0;
|
|
|
|
|
ProxyAction *m_hiddenStopAction = 0;
|
|
|
|
|
QAction *m_startAction = 0;
|
|
|
|
|
QAction *m_debugWithoutDeployAction = 0;
|
|
|
|
|
QAction *m_startAndDebugApplicationAction = 0;
|
|
|
|
|
QAction *m_startRemoteServerAction = 0;
|
|
|
|
|
QAction *m_attachToRunningApplication = 0;
|
|
|
|
|
QAction *m_attachToUnstartedApplication = 0;
|
|
|
|
|
QAction *m_attachToQmlPortAction = 0;
|
|
|
|
|
QAction *m_attachToRemoteServerAction = 0;
|
|
|
|
|
QAction *m_startRemoteCdbAction = 0;
|
|
|
|
|
QAction *m_attachToCoreAction = 0;
|
|
|
|
|
QAction *m_detachAction = 0;
|
|
|
|
|
QAction *m_continueAction = 0;
|
|
|
|
|
QAction *m_exitAction = 0; // On application output button if "Stop" is possible
|
|
|
|
|
QAction *m_interruptAction = 0; // On the fat debug button if "Pause" is possible
|
|
|
|
|
QAction *m_undisturbableAction = 0; // On the fat debug button if nothing can be done
|
|
|
|
|
QAction *m_abortAction = 0;
|
|
|
|
|
QAction *m_stepAction = 0;
|
|
|
|
|
QAction *m_stepOutAction = 0;
|
|
|
|
|
QAction *m_runToLineAction = 0; // In the debug menu
|
|
|
|
|
QAction *m_runToSelectedFunctionAction = 0;
|
|
|
|
|
QAction *m_jumpToLineAction = 0; // In the Debug menu.
|
|
|
|
|
QAction *m_returnFromFunctionAction = 0;
|
|
|
|
|
QAction *m_nextAction = 0;
|
|
|
|
|
QAction *m_watchAction1 = 0; // In the Debug menu.
|
|
|
|
|
QAction *m_watchAction2 = 0; // In the text editor context menu.
|
|
|
|
|
QAction *m_breakAction = 0;
|
|
|
|
|
QAction *m_reverseDirectionAction = 0;
|
|
|
|
|
QAction *m_frameUpAction = 0;
|
|
|
|
|
QAction *m_frameDownAction = 0;
|
|
|
|
|
QAction *m_resetAction = 0;
|
2016-03-02 13:57:37 +01:00
|
|
|
QAction *m_operateByInstructionAction = 0;
|
2016-02-29 12:11:18 +01:00
|
|
|
|
|
|
|
|
QToolButton *m_reverseToolButton = 0;
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2016-04-16 20:59:42 +02:00
|
|
|
QLabel *m_threadLabel = 0;
|
2016-02-29 12:11:18 +01:00
|
|
|
QComboBox *m_threadBox = 0;
|
|
|
|
|
|
|
|
|
|
BaseTreeView *m_breakView = 0;
|
|
|
|
|
BaseTreeView *m_returnView = 0;
|
|
|
|
|
BaseTreeView *m_localsView = 0;
|
|
|
|
|
BaseTreeView *m_watchersView = 0;
|
2016-04-19 22:49:23 +02:00
|
|
|
WatchTreeView *m_inspectorView = 0;
|
2016-02-29 12:11:18 +01:00
|
|
|
BaseTreeView *m_registerView = 0;
|
|
|
|
|
BaseTreeView *m_modulesView = 0;
|
|
|
|
|
BaseTreeView *m_snapshotView = 0;
|
|
|
|
|
BaseTreeView *m_sourceFilesView = 0;
|
|
|
|
|
BaseTreeView *m_stackView = 0;
|
|
|
|
|
BaseTreeView *m_threadsView = 0;
|
|
|
|
|
|
|
|
|
|
QWidget *m_breakWindow = 0;
|
|
|
|
|
BreakHandler *m_breakHandler = 0;
|
|
|
|
|
QWidget *m_returnWindow = 0;
|
|
|
|
|
QWidget *m_localsWindow = 0;
|
|
|
|
|
QWidget *m_watchersWindow = 0;
|
|
|
|
|
QWidget *m_inspectorWindow = 0;
|
|
|
|
|
QWidget *m_registerWindow = 0;
|
|
|
|
|
QWidget *m_modulesWindow = 0;
|
|
|
|
|
QWidget *m_snapshotWindow = 0;
|
|
|
|
|
QWidget *m_sourceFilesWindow = 0;
|
|
|
|
|
QWidget *m_stackWindow = 0;
|
|
|
|
|
QWidget *m_threadsWindow = 0;
|
|
|
|
|
LogWindow *m_logWindow = 0;
|
|
|
|
|
LocalsAndExpressionsWindow *m_localsAndExpressionsWindow = 0;
|
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;
|
2016-02-29 12:11:18 +01:00
|
|
|
DebuggerPlugin *m_plugin = 0;
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2016-02-29 12:11:18 +01:00
|
|
|
SnapshotHandler *m_snapshotHandler = 0;
|
|
|
|
|
bool m_shuttingDown = false;
|
2016-04-21 16:03:08 +02:00
|
|
|
QPointer<DebuggerEngine> m_currentEngine;
|
2016-02-29 12:11:18 +01:00
|
|
|
DebuggerSettings *m_debuggerSettings = 0;
|
2011-02-22 11:21:08 +01:00
|
|
|
QStringList m_arguments;
|
2014-11-07 13:50:09 +01:00
|
|
|
DebuggerToolTipManager m_toolTipManager;
|
2016-02-29 12:11:18 +01:00
|
|
|
CommonOptionsPage *m_commonOptionsPage = 0;
|
|
|
|
|
DummyEngine *m_dummyEngine = 0;
|
2011-03-04 16:21:57 +01:00
|
|
|
const QSharedPointer<GlobalDebuggerOptions> m_globalDebuggerOptions;
|
2010-06-16 11:08:54 +02:00
|
|
|
};
|
|
|
|
|
|
2016-02-29 12:11:18 +01:00
|
|
|
DebuggerPluginPrivate::DebuggerPluginPrivate(DebuggerPlugin *plugin)
|
|
|
|
|
: m_globalDebuggerOptions(new GlobalDebuggerOptions)
|
2010-06-16 11:08:54 +02:00
|
|
|
{
|
2011-01-04 15:54:36 +01:00
|
|
|
qRegisterMetaType<ContextData>("ContextData");
|
2015-05-27 13:59:56 +02:00
|
|
|
qRegisterMetaType<DebuggerRunParameters>("DebuggerRunParameters");
|
2011-01-04 15:54:36 +01:00
|
|
|
|
2014-10-22 13:04:47 +02:00
|
|
|
QTC_CHECK(!dd);
|
|
|
|
|
dd = this;
|
2010-11-10 11:39:01 +01:00
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
m_plugin = plugin;
|
|
|
|
|
|
2016-03-01 07:51:06 +01:00
|
|
|
// m_toolBars.insert(CppLanguage, 0);
|
|
|
|
|
// m_toolBars.insert(QmlLanguage, 0);
|
|
|
|
|
m_contextsForLanguage.insert(CppLanguage, Context(C_CPPDEBUGGER));
|
|
|
|
|
m_contextsForLanguage.insert(QmlLanguage, Context(C_QMLDEBUGGER));
|
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;
|
|
|
|
|
|
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);
|
2016-06-07 17:04:53 +02:00
|
|
|
m_dummyEngine->setObjectName("DummyEngine");
|
2011-03-02 14:05:32 +01:00
|
|
|
}
|
|
|
|
|
return m_dummyEngine;
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-08 13:48:04 +01:00
|
|
|
static QString msgParameterMissing(const QString &a)
|
|
|
|
|
{
|
2014-04-17 14:09:47 +02:00
|
|
|
return DebuggerPlugin::tr("Option \"%1\" is missing the parameter.").arg(a);
|
2011-02-08 13:48:04 +01:00
|
|
|
}
|
|
|
|
|
|
2016-03-22 17:17:05 +01:00
|
|
|
static Kit *guessKitFromParameters(const DebuggerRunParameters &rp)
|
|
|
|
|
{
|
|
|
|
|
Kit *kit = 0;
|
|
|
|
|
|
|
|
|
|
// Try to find a kit via ABI.
|
|
|
|
|
QList<Abi> abis;
|
|
|
|
|
if (rp.toolChainAbi.isValid())
|
|
|
|
|
abis.push_back(rp.toolChainAbi);
|
|
|
|
|
else if (!rp.inferior.executable.isEmpty())
|
|
|
|
|
abis = Abi::abisOfBinary(FileName::fromString(rp.inferior.executable));
|
|
|
|
|
|
|
|
|
|
if (!abis.isEmpty()) {
|
|
|
|
|
// Try exact abis.
|
|
|
|
|
kit = KitManager::find(KitMatcher([abis](const Kit *k) -> bool {
|
2016-07-13 10:40:05 +02:00
|
|
|
const Abi tcAbi = ToolChainKitInformation::targetAbi(k);
|
2016-11-15 09:22:53 +01:00
|
|
|
return abis.contains(tcAbi) && !DebuggerKitInformation::configurationErrors(k);
|
2016-03-22 17:17:05 +01:00
|
|
|
}));
|
|
|
|
|
if (!kit) {
|
|
|
|
|
// Or something compatible.
|
|
|
|
|
kit = KitManager::find(KitMatcher([abis](const Kit *k) -> bool {
|
2016-07-13 10:40:05 +02:00
|
|
|
const Abi tcAbi = ToolChainKitInformation::targetAbi(k);
|
2016-11-15 09:22:53 +01:00
|
|
|
return !DebuggerKitInformation::configurationErrors(k)
|
2016-07-13 10:40:05 +02:00
|
|
|
&& Utils::contains(abis, [tcAbi](const Abi &a) { return a.isCompatibleWith(tcAbi); });
|
2016-03-22 17:17:05 +01:00
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!kit)
|
|
|
|
|
kit = KitManager::defaultKit();
|
|
|
|
|
|
|
|
|
|
return kit;
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-08 13:48:04 +01:00
|
|
|
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>'
|
2015-09-04 11:32:42 +02:00
|
|
|
// '-debug <exe>[,server=<server:port>][,core=<core>][,kit=<kit>][,terminal={0,1}]'
|
2016-06-07 17:04:53 +02:00
|
|
|
if (*it == "-debug") {
|
2011-02-08 13:48:04 +01:00
|
|
|
++it;
|
|
|
|
|
if (it == cend) {
|
|
|
|
|
*errorMessage = msgParameterMissing(*it);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2012-09-03 18:31:44 +02:00
|
|
|
Kit *kit = 0;
|
2015-05-27 13:59:56 +02:00
|
|
|
DebuggerRunParameters rp;
|
2011-02-08 13:48:04 +01:00
|
|
|
qulonglong pid = it->toULongLong();
|
|
|
|
|
if (pid) {
|
2015-05-27 13:59:56 +02:00
|
|
|
rp.startMode = AttachExternal;
|
|
|
|
|
rp.closeMode = DetachAtClose;
|
|
|
|
|
rp.attachPID = pid;
|
|
|
|
|
rp.displayName = tr("Process %1").arg(rp.attachPID);
|
|
|
|
|
rp.startMessage = tr("Attaching to local process %1.").arg(rp.attachPID);
|
2011-02-08 13:48:04 +01:00
|
|
|
} else {
|
2015-05-27 13:59:56 +02:00
|
|
|
rp.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()) {
|
2013-07-17 00:01:45 +03:00
|
|
|
if (key.isEmpty()) {
|
2012-02-17 12:32:57 +02:00
|
|
|
continue;
|
2016-01-28 10:31:24 +01:00
|
|
|
} else if (rp.inferior.executable.isEmpty()) {
|
|
|
|
|
rp.inferior.executable = key;
|
2013-07-17 00:01:45 +03:00
|
|
|
} else {
|
2014-08-22 13:26:36 +02:00
|
|
|
*errorMessage = DebuggerPlugin::tr("Only one executable allowed.");
|
2012-02-17 12:32:57 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (key == QLatin1String("server")) {
|
2015-05-27 13:59:56 +02:00
|
|
|
rp.startMode = AttachToRemoteServer;
|
|
|
|
|
rp.remoteChannel = val;
|
|
|
|
|
rp.displayName = tr("Remote: \"%1\"").arg(rp.remoteChannel);
|
|
|
|
|
rp.startMessage = tr("Attaching to remote server %1.").arg(rp.remoteChannel);
|
2013-07-17 00:01:45 +03:00
|
|
|
} else if (key == QLatin1String("core")) {
|
2015-05-27 13:59:56 +02:00
|
|
|
rp.startMode = AttachCore;
|
|
|
|
|
rp.closeMode = DetachAtClose;
|
|
|
|
|
rp.coreFile = val;
|
|
|
|
|
rp.displayName = tr("Core file \"%1\"").arg(rp.coreFile);
|
|
|
|
|
rp.startMessage = tr("Attaching to core file %1.").arg(rp.coreFile);
|
2015-09-04 11:32:42 +02:00
|
|
|
} else if (key == QLatin1String("terminal")) {
|
|
|
|
|
rp.useTerminal = bool(val.toInt());
|
2013-07-17 00:01:45 +03:00
|
|
|
} else if (key == QLatin1String("kit")) {
|
2013-08-21 12:48:46 +02:00
|
|
|
kit = KitManager::find(Id::fromString(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
|
|
|
}
|
2015-05-27 13:59:56 +02:00
|
|
|
if (rp.startMode == StartExternal) {
|
2016-01-28 10:31:24 +01:00
|
|
|
rp.displayName = tr("Executable file \"%1\"").arg(rp.inferior.executable);
|
|
|
|
|
rp.startMessage = tr("Debugging file %1.").arg(rp.inferior.executable);
|
2011-02-08 13:48:04 +01:00
|
|
|
}
|
2016-01-28 10:31:24 +01:00
|
|
|
rp.inferior.environment = Utils::Environment::systemEnvironment();
|
2015-12-08 12:39:10 +01:00
|
|
|
rp.stubEnvironment = Utils::Environment::systemEnvironment();
|
2016-07-29 15:55:15 +02:00
|
|
|
rp.debugger.environment = Utils::Environment::systemEnvironment();
|
2016-03-22 17:17:05 +01:00
|
|
|
|
|
|
|
|
if (!kit)
|
|
|
|
|
kit = guessKitFromParameters(rp);
|
2015-06-24 08:26:35 +02:00
|
|
|
m_scheduledStarts.append(QPair<DebuggerRunParameters, Kit *>(rp, kit));
|
2011-02-08 13:48:04 +01:00
|
|
|
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")
|
2012-11-26 20:43:43 +02:00
|
|
|
// << QString::fromLatin1("%1:%2").arg(argWinCrashEvent).arg(argProcessId);
|
2016-06-07 17:04:53 +02:00
|
|
|
if (*it == "-wincrashevent") {
|
2011-02-08 13:48:04 +01:00
|
|
|
++it;
|
|
|
|
|
if (it == cend) {
|
|
|
|
|
*errorMessage = msgParameterMissing(*it);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2015-05-27 13:59:56 +02:00
|
|
|
DebuggerRunParameters rp;
|
|
|
|
|
rp.startMode = AttachCrashedExternal;
|
|
|
|
|
rp.crashParameter = it->section(QLatin1Char(':'), 0, 0);
|
|
|
|
|
rp.attachPID = it->section(QLatin1Char(':'), 1, 1).toULongLong();
|
|
|
|
|
rp.displayName = tr("Crashed process %1").arg(rp.attachPID);
|
|
|
|
|
rp.startMessage = tr("Attaching to crashed process %1").arg(rp.attachPID);
|
|
|
|
|
if (!rp.attachPID) {
|
2014-04-17 14:09:47 +02:00
|
|
|
*errorMessage = DebuggerPlugin::tr("The parameter \"%1\" of option \"%2\" "
|
2011-02-08 13:48:04 +01:00
|
|
|
"does not match the pattern <handle>:<pid>.").arg(*it, option);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2015-06-24 08:26:35 +02:00
|
|
|
m_scheduledStarts.append(QPair<DebuggerRunParameters, Kit *>(rp, findUniversalCdbKit()));
|
2011-02-08 13:48:04 +01:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-05 11:10:33 +01:00
|
|
|
void DebuggerPluginPrivate::parseCommandLineArguments()
|
|
|
|
|
{
|
|
|
|
|
QString errorMessage;
|
|
|
|
|
if (!parseArguments(m_arguments, &errorMessage)) {
|
|
|
|
|
errorMessage = tr("Error evaluating command line arguments: %1")
|
|
|
|
|
.arg(errorMessage);
|
|
|
|
|
qWarning("%s\n", qPrintable(errorMessage));
|
2013-09-05 01:52:17 +02:00
|
|
|
MessageManager::write(errorMessage);
|
2013-03-05 11:10:33 +01:00
|
|
|
}
|
|
|
|
|
if (!m_scheduledStarts.isEmpty())
|
2016-03-09 19:16:14 +01:00
|
|
|
QTimer::singleShot(0, this, &DebuggerPluginPrivate::runScheduled);
|
2013-03-05 11:10:33 +01:00
|
|
|
}
|
|
|
|
|
|
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);
|
2015-02-04 09:32:46 +01:00
|
|
|
Utils::MimeDatabase::addMimeTypes(QLatin1String(":/debugger/Debugger.mimetypes.xml"));
|
|
|
|
|
|
2011-02-22 11:21:08 +01:00
|
|
|
m_arguments = arguments;
|
2013-03-05 11:10:33 +01:00
|
|
|
if (!m_arguments.isEmpty())
|
2016-03-17 10:59:48 +01:00
|
|
|
connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::finishedInitialization,
|
2014-10-22 13:04:47 +02:00
|
|
|
this, &DebuggerPluginPrivate::parseCommandLineArguments);
|
2015-11-10 16:59:02 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
m_mainWindow = new DebuggerMainWindow;
|
|
|
|
|
|
|
|
|
|
// Menus
|
|
|
|
|
m_menu = ActionManager::createMenu(M_DEBUG_ANALYZER);
|
|
|
|
|
m_menu->menu()->setTitle(tr("&Analyze"));
|
|
|
|
|
m_menu->menu()->setEnabled(true);
|
|
|
|
|
|
|
|
|
|
m_menu->appendGroup(G_ANALYZER_CONTROL);
|
|
|
|
|
m_menu->appendGroup(G_ANALYZER_TOOLS);
|
|
|
|
|
m_menu->appendGroup(G_ANALYZER_REMOTE_TOOLS);
|
|
|
|
|
m_menu->appendGroup(G_ANALYZER_OPTIONS);
|
|
|
|
|
|
|
|
|
|
ActionContainer *menubar = ActionManager::actionContainer(MENU_BAR);
|
|
|
|
|
ActionContainer *mtools = ActionManager::actionContainer(M_TOOLS);
|
|
|
|
|
menubar->addMenu(mtools, m_menu);
|
|
|
|
|
|
|
|
|
|
m_menu->addSeparator(G_ANALYZER_TOOLS);
|
|
|
|
|
m_menu->addSeparator(G_ANALYZER_REMOTE_TOOLS);
|
|
|
|
|
m_menu->addSeparator(G_ANALYZER_OPTIONS);
|
|
|
|
|
|
|
|
|
|
// Populate Windows->Views menu with standard actions.
|
|
|
|
|
Context debugcontext(Constants::C_DEBUGMODE);
|
|
|
|
|
|
|
|
|
|
auto openMemoryEditorAction = new QAction(this);
|
|
|
|
|
openMemoryEditorAction->setText(DebuggerPluginPrivate::tr("Memory..."));
|
|
|
|
|
connect(openMemoryEditorAction, &QAction::triggered,
|
|
|
|
|
this, &Internal::openMemoryEditor);
|
2016-03-01 07:51:06 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
Command *cmd = ActionManager::registerAction(openMemoryEditorAction,
|
|
|
|
|
"Debugger.Views.OpenMemoryEditor", debugcontext);
|
|
|
|
|
cmd->setAttribute(Command::CA_Hide);
|
2016-03-01 07:51:06 +01:00
|
|
|
|
2015-11-10 16:59:02 +01:00
|
|
|
m_plugin->addAutoReleasedObject(debuggerConsole());
|
2010-12-03 10:45:51 +01:00
|
|
|
|
2015-02-03 23:58:49 +02:00
|
|
|
TaskHub::addCategory(TASK_CATEGORY_DEBUGGER_DEBUGINFO,
|
2013-08-15 12:14:46 +02:00
|
|
|
tr("Debug Information"));
|
2015-02-03 23:58:49 +02:00
|
|
|
TaskHub::addCategory(TASK_CATEGORY_DEBUGGER_RUNTIME,
|
2013-08-15 12:14:46 +02:00
|
|
|
tr("Debugger Runtime"));
|
|
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
const QKeySequence debugKey = QKeySequence(UseMacShortcuts ? tr("Ctrl+Y") : tr("F5"));
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
QSettings *settings = ICore::settings();
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
m_debuggerSettings = new DebuggerSettings;
|
|
|
|
|
m_debuggerSettings->readSettings();
|
2013-06-07 12:52:24 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
connect(ICore::instance(), &ICore::coreAboutToClose, this, &DebuggerPluginPrivate::coreShutdown);
|
2013-06-07 12:52:24 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
const Context cppDebuggercontext(C_CPPDEBUGGER);
|
|
|
|
|
const Context cppeditorcontext(CppEditor::Constants::CPPEDITOR_ID);
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
m_busy = false;
|
2012-07-24 17:02:42 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
m_logWindow = new LogWindow;
|
|
|
|
|
m_logWindow->setObjectName(QLatin1String(DOCKWIDGET_OUTPUT));
|
2011-02-24 16:50:15 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
m_breakHandler = new BreakHandler;
|
2016-10-04 17:05:37 +02:00
|
|
|
m_breakView = new BaseTreeView;
|
|
|
|
|
m_breakView->setIconSize(QSize(10, 10));
|
2016-07-18 12:36:31 +02:00
|
|
|
m_breakView->setWindowIcon(Icons::BREAKPOINTS.icon());
|
|
|
|
|
m_breakView->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
|
|
|
|
connect(action(UseAddressInBreakpointsView), &QAction::toggled,
|
|
|
|
|
this, [this](bool on) { m_breakView->setColumnHidden(BreakpointAddressColumn, !on); });
|
2016-03-02 13:57:37 +01:00
|
|
|
m_breakView->setSettings(settings, "Debugger.BreakWindow");
|
|
|
|
|
m_breakView->setModel(m_breakHandler->model());
|
|
|
|
|
m_breakWindow = addSearch(m_breakView, tr("Breakpoints"), DOCKWIDGET_BREAK);
|
2011-02-24 16:50:15 +01:00
|
|
|
|
2016-07-18 12:36:31 +02:00
|
|
|
m_modulesView = new BaseTreeView;
|
|
|
|
|
m_modulesView->setSortingEnabled(true);
|
2016-03-02 13:57:37 +01:00
|
|
|
m_modulesView->setSettings(settings, "Debugger.ModulesView");
|
2016-07-21 08:50:28 +02:00
|
|
|
connect(m_modulesView, &BaseTreeView::aboutToShow,
|
|
|
|
|
this, &DebuggerPluginPrivate::reloadModules,
|
|
|
|
|
Qt::QueuedConnection);
|
2016-03-02 13:57:37 +01:00
|
|
|
m_modulesWindow = addSearch(m_modulesView, tr("Modules"), DOCKWIDGET_MODULES);
|
2010-07-22 10:23:27 +02:00
|
|
|
|
2016-07-18 12:36:31 +02:00
|
|
|
m_registerView = new BaseTreeView;
|
|
|
|
|
m_registerView->setRootIsDecorated(true);
|
2016-03-02 13:57:37 +01:00
|
|
|
m_registerView->setSettings(settings, "Debugger.RegisterView");
|
2016-07-21 08:50:28 +02:00
|
|
|
connect(m_registerView, &BaseTreeView::aboutToShow,
|
|
|
|
|
this, &DebuggerPluginPrivate::reloadRegisters,
|
|
|
|
|
Qt::QueuedConnection);
|
2016-03-02 13:57:37 +01:00
|
|
|
m_registerWindow = addSearch(m_registerView, tr("Registers"), DOCKWIDGET_REGISTER);
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
m_stackView = new StackTreeView;
|
|
|
|
|
m_stackView->setSettings(settings, "Debugger.StackView");
|
2016-11-01 08:28:43 +01:00
|
|
|
m_stackView->setIconSize(QSize(10, 10));
|
2016-03-02 13:57:37 +01:00
|
|
|
m_stackWindow = addSearch(m_stackView, tr("Stack"), DOCKWIDGET_STACK);
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2016-07-18 12:36:31 +02:00
|
|
|
m_sourceFilesView = new BaseTreeView;
|
|
|
|
|
m_sourceFilesView->setSortingEnabled(true);
|
2016-03-02 13:57:37 +01:00
|
|
|
m_sourceFilesView->setSettings(settings, "Debugger.SourceFilesView");
|
2016-07-21 08:50:28 +02:00
|
|
|
connect(m_sourceFilesView, &BaseTreeView::aboutToShow,
|
|
|
|
|
this, &DebuggerPluginPrivate::reloadSourceFiles,
|
|
|
|
|
Qt::QueuedConnection);
|
2016-03-02 13:57:37 +01:00
|
|
|
m_sourceFilesWindow = addSearch(m_sourceFilesView, tr("Source Files"), DOCKWIDGET_SOURCE_FILES);
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2016-07-18 12:36:31 +02:00
|
|
|
m_threadsView = new BaseTreeView;
|
|
|
|
|
m_threadsView->setSortingEnabled(true);
|
2016-03-02 13:57:37 +01:00
|
|
|
m_threadsView->setSettings(settings, "Debugger.ThreadsView");
|
2016-11-01 08:28:43 +01:00
|
|
|
m_threadsView->setIconSize(QSize(10, 10));
|
2016-03-02 13:57:37 +01:00
|
|
|
m_threadsWindow = addSearch(m_threadsView, tr("Threads"), DOCKWIDGET_THREADS);
|
2015-02-25 16:30:23 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
m_returnView = new WatchTreeView(ReturnType); // No settings.
|
|
|
|
|
m_returnWindow = addSearch(m_returnView, tr("Locals and Expressions"), "CppDebugReturn");
|
2015-02-25 16:30:23 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
m_localsView = new WatchTreeView(LocalsType);
|
|
|
|
|
m_localsView->setSettings(settings, "Debugger.LocalsView");
|
|
|
|
|
m_localsWindow = addSearch(m_localsView, tr("Locals and Expressions"), "CppDebugLocals");
|
2012-03-21 17:54:56 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
m_watchersView = new WatchTreeView(WatchersType); // No settings.
|
|
|
|
|
m_watchersWindow = addSearch(m_watchersView, tr("Locals and Expressions"), "CppDebugWatchers");
|
2012-08-08 12:03:07 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
m_inspectorView = new WatchTreeView(InspectType);
|
|
|
|
|
m_inspectorView->setSettings(settings, "Debugger.LocalsView"); // sic! same as locals view.
|
|
|
|
|
m_inspectorWindow = addSearch(m_inspectorView, tr("Locals and Expressions"), "Inspector");
|
2012-08-08 12:03:07 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
// Snapshot
|
|
|
|
|
m_snapshotHandler = new SnapshotHandler;
|
|
|
|
|
m_snapshotView = new SnapshotTreeView(m_snapshotHandler);
|
|
|
|
|
m_snapshotView->setSettings(settings, "Debugger.SnapshotView");
|
|
|
|
|
m_snapshotView->setModel(m_snapshotHandler->model());
|
|
|
|
|
m_snapshotWindow = addSearch(m_snapshotView, tr("Snapshots"), DOCKWIDGET_SNAPSHOTS);
|
2013-09-20 16:48:01 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
// Watchers
|
|
|
|
|
connect(m_localsView->header(), &QHeaderView::sectionResized,
|
|
|
|
|
this, &DebuggerPluginPrivate::updateWatchersHeader, Qt::QueuedConnection);
|
2013-09-20 16:48:01 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
auto act = m_continueAction = new QAction(tr("Continue"), this);
|
2016-04-24 22:51:24 +02:00
|
|
|
act->setIcon(visibleStartIcon(Id(Constants::CONTINUE), false));
|
2016-03-02 13:57:37 +01:00
|
|
|
connect(act, &QAction::triggered, this, &DebuggerPluginPrivate::handleExecContinue);
|
2013-09-20 16:48:01 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
act = m_exitAction = new QAction(tr("Stop Debugger"), this);
|
2016-04-24 22:51:24 +02:00
|
|
|
act->setIcon(Icons::DEBUG_EXIT_SMALL.icon());
|
2016-03-02 13:57:37 +01:00
|
|
|
connect(act, &QAction::triggered, this, &DebuggerPluginPrivate::handleExecExit);
|
2013-09-20 16:48:01 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
act = m_interruptAction = new QAction(tr("Interrupt"), this);
|
2016-04-24 22:51:24 +02:00
|
|
|
act->setIcon(visibleStartIcon(Id(Constants::INTERRUPT), false));
|
2016-03-02 13:57:37 +01:00
|
|
|
connect(act, &QAction::triggered, this, &DebuggerPluginPrivate::handleExecInterrupt);
|
2013-09-20 16:48:01 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
// A "disabled pause" seems to be a good choice.
|
|
|
|
|
act = m_undisturbableAction = new QAction(tr("Debugger is Busy"), this);
|
2016-04-24 22:51:24 +02:00
|
|
|
act->setIcon(visibleStartIcon(Id(Constants::INTERRUPT), false));
|
2016-03-02 13:57:37 +01:00
|
|
|
act->setEnabled(false);
|
2013-09-20 16:48:01 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
act = m_abortAction = new QAction(tr("Abort Debugging"), this);
|
|
|
|
|
act->setToolTip(tr("Aborts debugging and "
|
|
|
|
|
"resets the debugger to the initial state."));
|
|
|
|
|
connect(act, &QAction::triggered, this, &DebuggerPluginPrivate::handleAbort);
|
2012-08-08 12:03:07 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
act = m_resetAction = new QAction(tr("Restart Debugging"),this);
|
|
|
|
|
act->setToolTip(tr("Restart the debugging session."));
|
2016-04-20 16:12:42 +02:00
|
|
|
act->setIcon(Icons::RESTART_TOOLBAR.icon());
|
2016-03-02 13:57:37 +01:00
|
|
|
connect(act, &QAction::triggered, this, &DebuggerPluginPrivate::handleReset);
|
2012-08-08 12:03:07 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
act = m_nextAction = new QAction(tr("Step Over"), this);
|
2016-04-24 22:51:24 +02:00
|
|
|
act->setIcon(Icons::STEP_OVER.icon());
|
2016-03-02 13:57:37 +01:00
|
|
|
connect(act, &QAction::triggered, this, &DebuggerPluginPrivate::handleExecNext);
|
2013-09-20 16:48:01 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
act = m_stepAction = new QAction(tr("Step Into"), this);
|
2016-04-24 22:51:24 +02:00
|
|
|
act->setIcon(Icons::STEP_INTO.icon());
|
2016-03-02 13:57:37 +01:00
|
|
|
connect(act, &QAction::triggered, this, &DebuggerPluginPrivate::handleExecStep);
|
2011-12-05 17:21:48 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
act = m_stepOutAction = new QAction(tr("Step Out"), this);
|
2016-04-24 22:51:24 +02:00
|
|
|
act->setIcon(Icons::STEP_OUT.icon());
|
2016-03-02 13:57:37 +01:00
|
|
|
connect(act, &QAction::triggered, this, &DebuggerPluginPrivate::handleExecStepOut);
|
2012-08-30 10:26:09 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
act = m_runToLineAction = new QAction(tr("Run to Line"), this);
|
|
|
|
|
connect(act, &QAction::triggered, this, &DebuggerPluginPrivate::handleExecRunToLine);
|
2011-09-13 17:26:02 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
act = m_runToSelectedFunctionAction = new QAction(tr("Run to Selected Function"), this);
|
|
|
|
|
connect(act, &QAction::triggered, this, &DebuggerPluginPrivate::handleExecRunToSelectedFunction);
|
2011-09-13 17:26:02 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
act = m_returnFromFunctionAction =
|
|
|
|
|
new QAction(tr("Immediately Return From Inner Function"), this);
|
|
|
|
|
connect(act, &QAction::triggered, this, &DebuggerPluginPrivate::handleExecReturn);
|
2011-10-11 15:21:00 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
act = m_jumpToLineAction = new QAction(tr("Jump to Line"), this);
|
|
|
|
|
connect(act, &QAction::triggered, this, &DebuggerPluginPrivate::handleExecJumpToLine);
|
2011-09-13 17:26:02 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
m_breakAction = new QAction(tr("Toggle Breakpoint"), this);
|
2011-09-13 17:26:02 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
act = m_watchAction1 = new QAction(tr("Add Expression Evaluator"), this);
|
|
|
|
|
connect(act, &QAction::triggered, this, &DebuggerPluginPrivate::handleAddToWatchWindow);
|
2011-10-28 13:25:58 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
act = m_watchAction2 = new QAction(tr("Add Expression Evaluator"), this);
|
|
|
|
|
connect(act, &QAction::triggered, this, &DebuggerPluginPrivate::handleAddToWatchWindow);
|
2011-10-28 13:25:58 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
//act = m_snapshotAction = new QAction(tr("Create Snapshot"), this);
|
|
|
|
|
//act->setProperty(Role, RequestCreateSnapshotRole);
|
|
|
|
|
//act->setIcon(Icons::SNAPSHOT.icon());
|
2011-09-13 17:26:02 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
act = m_reverseDirectionAction = new QAction(tr("Reverse Direction"), this);
|
|
|
|
|
act->setCheckable(true);
|
|
|
|
|
act->setChecked(false);
|
|
|
|
|
act->setCheckable(false);
|
|
|
|
|
act->setIcon(Icons::REVERSE_MODE.icon());
|
|
|
|
|
act->setIconVisibleInMenu(false);
|
2010-09-22 12:25:42 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
act = m_frameDownAction = new QAction(tr("Move to Called Frame"), this);
|
|
|
|
|
connect(act, &QAction::triggered, this, &DebuggerPluginPrivate::handleFrameDown);
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
act = m_frameUpAction = new QAction(tr("Move to Calling Frame"), this);
|
|
|
|
|
connect(act, &QAction::triggered, this, &DebuggerPluginPrivate::handleFrameUp);
|
2014-09-30 16:54:26 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
act = m_operateByInstructionAction = action(OperateByInstruction);
|
|
|
|
|
connect(act, &QAction::triggered,
|
|
|
|
|
this, &DebuggerPluginPrivate::handleOperateByInstructionTriggered);
|
2010-09-22 12:25:42 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
ActionContainer *debugMenu = ActionManager::actionContainer(PE::M_DEBUG);
|
2011-02-04 14:36:50 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
m_localsAndExpressionsWindow = new LocalsAndExpressionsWindow(
|
|
|
|
|
m_localsWindow, m_inspectorWindow, m_returnWindow, m_watchersWindow);
|
|
|
|
|
m_localsAndExpressionsWindow->setObjectName(QLatin1String(DOCKWIDGET_WATCHERS));
|
|
|
|
|
m_localsAndExpressionsWindow->setWindowTitle(m_localsWindow->windowTitle());
|
2015-07-20 09:37:54 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
m_plugin->addAutoReleasedObject(createDebuggerRunControlFactory(m_plugin));
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
// The main "Start Debugging" action.
|
|
|
|
|
act = m_startAction = new QAction(this);
|
2016-04-24 22:51:24 +02:00
|
|
|
act->setIcon(visibleStartIcon(Id(Constants::DEBUG), false));
|
2016-03-02 13:57:37 +01:00
|
|
|
act->setText(tr("Start Debugging"));
|
|
|
|
|
connect(act, &QAction::triggered, [] { ProjectExplorerPlugin::runStartupProject(ProjectExplorer::Constants::DEBUG_RUN_MODE); });
|
2015-01-10 01:07:01 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
act = m_debugWithoutDeployAction = new QAction(this);
|
|
|
|
|
act->setText(tr("Start Debugging Without Deployment"));
|
|
|
|
|
connect(act, &QAction::triggered, [] { ProjectExplorerPlugin::runStartupProject(ProjectExplorer::Constants::DEBUG_RUN_MODE, true); });
|
2010-08-18 13:54:12 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
act = m_startAndDebugApplicationAction = new QAction(this);
|
|
|
|
|
act->setText(tr("Start and Debug External Application..."));
|
|
|
|
|
connect(act, &QAction::triggered, this, &DebuggerPluginPrivate::startAndDebugApplication);
|
2010-08-26 16:02:41 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
act = m_attachToCoreAction = new QAction(this);
|
|
|
|
|
act->setText(tr("Load Core File..."));
|
|
|
|
|
connect(act, &QAction::triggered, this, &DebuggerPluginPrivate::attachCore);
|
2015-01-10 01:07:01 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
act = m_attachToRemoteServerAction = new QAction(this);
|
|
|
|
|
act->setText(tr("Attach to Running Debug Server..."));
|
|
|
|
|
connect(act, &QAction::triggered, this, &DebuggerPluginPrivate::attachToRemoteServer);
|
2015-01-10 01:07:01 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
act = m_startRemoteServerAction = new QAction(this);
|
|
|
|
|
act->setText(tr("Start Debug Server Attached to Process..."));
|
|
|
|
|
connect(act, &QAction::triggered, this, &DebuggerPluginPrivate::startRemoteServerAndAttachToProcess);
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
act = m_attachToRunningApplication = new QAction(this);
|
|
|
|
|
act->setText(tr("Attach to Running Application..."));
|
|
|
|
|
connect(act, &QAction::triggered, this, &DebuggerPluginPrivate::attachToRunningApplication);
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
act = m_attachToUnstartedApplication = new QAction(this);
|
|
|
|
|
act->setText(tr("Attach to Unstarted Application..."));
|
|
|
|
|
connect(act, &QAction::triggered, this, &DebuggerPluginPrivate::attachToUnstartedApplicationDialog);
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
act = m_attachToQmlPortAction = new QAction(this);
|
|
|
|
|
act->setText(tr("Attach to QML Port..."));
|
|
|
|
|
connect(act, &QAction::triggered, this, &DebuggerPluginPrivate::attachToQmlPort);
|
2010-11-09 10:23:10 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
if (HostOsInfo::isWindowsHost()) {
|
|
|
|
|
m_startRemoteCdbAction = new QAction(tr("Attach to Remote CDB Session..."), this);
|
|
|
|
|
connect(m_startRemoteCdbAction, &QAction::triggered,
|
|
|
|
|
this, &DebuggerPluginPrivate::startRemoteCdbSession);
|
2010-12-02 13:20:06 +01:00
|
|
|
}
|
2010-12-01 15:41:08 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
act = m_detachAction = new QAction(this);
|
|
|
|
|
act->setText(tr("Detach Debugger"));
|
|
|
|
|
connect(act, &QAction::triggered, this, &DebuggerPluginPrivate::handleExecDetach);
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
// "Start Debugging" sub-menu
|
|
|
|
|
// groups:
|
|
|
|
|
// G_DEFAULT_ONE
|
|
|
|
|
// G_START_LOCAL
|
|
|
|
|
// G_START_REMOTE
|
|
|
|
|
// G_START_QML
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
ActionContainer *mstart = ActionManager::actionContainer(PE::M_DEBUG_STARTDEBUGGING);
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
cmd = ActionManager::registerAction(m_startAction, Constants::DEBUG);
|
|
|
|
|
cmd->setDescription(tr("Start Debugging"));
|
|
|
|
|
cmd->setDefaultKeySequence(debugKey);
|
|
|
|
|
cmd->setAttribute(Command::CA_UpdateText);
|
|
|
|
|
mstart->addAction(cmd, CC::G_DEFAULT_ONE);
|
|
|
|
|
m_visibleStartAction = new ProxyAction(this);
|
2016-03-14 14:08:43 +01:00
|
|
|
m_visibleStartAction->initialize(m_startAction);
|
2016-03-02 13:57:37 +01:00
|
|
|
m_visibleStartAction->setAttribute(ProxyAction::UpdateText);
|
2016-03-14 14:08:43 +01:00
|
|
|
m_visibleStartAction->setAction(m_startAction);
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
ModeManager::addAction(m_visibleStartAction, Constants::P_ACTION_DEBUG);
|
2011-10-06 17:38:28 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
cmd = ActionManager::registerAction(m_debugWithoutDeployAction,
|
|
|
|
|
"Debugger.DebugWithoutDeploy");
|
|
|
|
|
cmd->setAttribute(Command::CA_Hide);
|
|
|
|
|
mstart->addAction(cmd, CC::G_DEFAULT_ONE);
|
2010-11-12 20:18:29 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
cmd = ActionManager::registerAction(m_attachToRunningApplication,
|
|
|
|
|
"Debugger.AttachToRemoteProcess");
|
|
|
|
|
cmd->setDescription(tr("Attach to Running Application"));
|
|
|
|
|
mstart->addAction(cmd, G_GENERAL);
|
2009-06-04 16:06:12 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
cmd = ActionManager::registerAction(m_attachToUnstartedApplication,
|
|
|
|
|
"Debugger.AttachToUnstartedProcess");
|
|
|
|
|
cmd->setDescription(tr("Attach to Unstarted Application"));
|
|
|
|
|
mstart->addAction(cmd, G_GENERAL);
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
cmd = ActionManager::registerAction(m_startAndDebugApplicationAction,
|
|
|
|
|
"Debugger.StartAndDebugApplication");
|
|
|
|
|
cmd->setAttribute(Command::CA_Hide);
|
|
|
|
|
mstart->addAction(cmd, G_GENERAL);
|
2010-12-01 15:41:08 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
cmd = ActionManager::registerAction(m_attachToCoreAction,
|
|
|
|
|
"Debugger.AttachCore");
|
|
|
|
|
cmd->setAttribute(Command::CA_Hide);
|
|
|
|
|
mstart->addAction(cmd, Constants::G_GENERAL);
|
2009-03-02 15:14:12 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
cmd = ActionManager::registerAction(m_attachToRemoteServerAction,
|
|
|
|
|
"Debugger.AttachToRemoteServer");
|
|
|
|
|
cmd->setAttribute(Command::CA_Hide);
|
|
|
|
|
mstart->addAction(cmd, Constants::G_SPECIAL);
|
2012-06-12 13:29:37 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
cmd = ActionManager::registerAction(m_startRemoteServerAction,
|
|
|
|
|
"Debugger.StartRemoteServer");
|
|
|
|
|
cmd->setDescription(tr("Start Gdbserver"));
|
|
|
|
|
mstart->addAction(cmd, Constants::G_SPECIAL);
|
|
|
|
|
|
|
|
|
|
if (m_startRemoteCdbAction) {
|
|
|
|
|
cmd = ActionManager::registerAction(m_startRemoteCdbAction,
|
|
|
|
|
"Debugger.AttachRemoteCdb");
|
|
|
|
|
cmd->setAttribute(Command::CA_Hide);
|
|
|
|
|
mstart->addAction(cmd, Constants::G_SPECIAL);
|
2010-12-02 13:20:06 +01:00
|
|
|
}
|
2010-05-05 12:41:52 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
mstart->addSeparator(Context(CC::C_GLOBAL), Constants::G_START_QML);
|
2009-05-07 17:11:19 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
cmd = ActionManager::registerAction(m_attachToQmlPortAction, "Debugger.AttachToQmlPort");
|
|
|
|
|
cmd->setAttribute(Command::CA_Hide);
|
|
|
|
|
mstart->addAction(cmd, Constants::G_START_QML);
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
cmd = ActionManager::registerAction(m_detachAction, "Debugger.Detach");
|
|
|
|
|
cmd->setAttribute(Command::CA_Hide);
|
|
|
|
|
debugMenu->addAction(cmd, CC::G_DEFAULT_ONE);
|
2010-07-22 10:23:27 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
cmd = ActionManager::registerAction(m_interruptAction, Constants::INTERRUPT);
|
|
|
|
|
cmd->setDescription(tr("Interrupt Debugger"));
|
|
|
|
|
debugMenu->addAction(cmd, CC::G_DEFAULT_ONE);
|
2010-10-05 12:47:23 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
cmd = ActionManager::registerAction(m_continueAction, Constants::CONTINUE);
|
|
|
|
|
cmd->setDefaultKeySequence(debugKey);
|
|
|
|
|
debugMenu->addAction(cmd, CC::G_DEFAULT_ONE);
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
cmd = ActionManager::registerAction(m_exitAction, Constants::STOP);
|
|
|
|
|
debugMenu->addAction(cmd, CC::G_DEFAULT_ONE);
|
|
|
|
|
m_hiddenStopAction = new ProxyAction(this);
|
|
|
|
|
m_hiddenStopAction->initialize(cmd->action());
|
|
|
|
|
m_hiddenStopAction->setAttribute(ProxyAction::UpdateText);
|
|
|
|
|
m_hiddenStopAction->setAttribute(ProxyAction::UpdateIcon);
|
2011-02-04 14:36:50 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
cmd = ActionManager::registerAction(m_hiddenStopAction, Constants::HIDDEN_STOP);
|
|
|
|
|
cmd->setDefaultKeySequence(QKeySequence(UseMacShortcuts ? tr("Shift+Ctrl+Y") : tr("Shift+F5")));
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
cmd = ActionManager::registerAction(m_abortAction, Constants::ABORT);
|
|
|
|
|
cmd->setDescription(tr("Reset Debugger"));
|
|
|
|
|
debugMenu->addAction(cmd, CC::G_DEFAULT_ONE);
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
cmd = ActionManager::registerAction(m_resetAction, Constants::RESET);
|
|
|
|
|
cmd->setDescription(tr("Restart Debugging"));
|
|
|
|
|
debugMenu->addAction(cmd, CC::G_DEFAULT_ONE);
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
debugMenu->addSeparator();
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
cmd = ActionManager::registerAction(m_nextAction, Constants::NEXT);
|
|
|
|
|
cmd->setDefaultKeySequence(QKeySequence(UseMacShortcuts ? tr("Ctrl+Shift+O") : tr("F10")));
|
|
|
|
|
cmd->setAttribute(Command::CA_Hide);
|
|
|
|
|
cmd->setAttribute(Command::CA_UpdateText);
|
|
|
|
|
debugMenu->addAction(cmd);
|
2010-03-18 10:56:25 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
cmd = ActionManager::registerAction(m_stepAction, Constants::STEP);
|
|
|
|
|
cmd->setDefaultKeySequence(QKeySequence(UseMacShortcuts ? tr("Ctrl+Shift+I") : tr("F11")));
|
|
|
|
|
cmd->setAttribute(Command::CA_Hide);
|
|
|
|
|
cmd->setAttribute(Command::CA_UpdateText);
|
|
|
|
|
debugMenu->addAction(cmd);
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2016-08-02 11:52:52 +02:00
|
|
|
cmd = ActionManager::registerAction(m_stepOutAction, Constants::STEPOUT);
|
2016-03-02 13:57:37 +01:00
|
|
|
cmd->setDefaultKeySequence(QKeySequence(UseMacShortcuts ? tr("Ctrl+Shift+T") : tr("Shift+F11")));
|
|
|
|
|
cmd->setAttribute(Command::CA_Hide);
|
|
|
|
|
debugMenu->addAction(cmd);
|
2010-12-02 13:20:06 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
cmd = ActionManager::registerAction(m_runToLineAction,
|
|
|
|
|
"Debugger.RunToLine", cppDebuggercontext);
|
|
|
|
|
cmd->setDefaultKeySequence(QKeySequence(UseMacShortcuts ? tr("Shift+F8") : tr("Ctrl+F10")));
|
|
|
|
|
cmd->setAttribute(Command::CA_Hide);
|
|
|
|
|
debugMenu->addAction(cmd);
|
2010-03-18 10:56:25 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
cmd = ActionManager::registerAction(m_runToSelectedFunctionAction,
|
|
|
|
|
"Debugger.RunToSelectedFunction", cppDebuggercontext);
|
|
|
|
|
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+F6")));
|
|
|
|
|
cmd->setAttribute(Command::CA_Hide);
|
|
|
|
|
// 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);
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
cmd = ActionManager::registerAction(m_jumpToLineAction,
|
|
|
|
|
"Debugger.JumpToLine", cppDebuggercontext);
|
|
|
|
|
cmd->setAttribute(Command::CA_Hide);
|
|
|
|
|
debugMenu->addAction(cmd);
|
2012-03-26 17:30:57 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
cmd = ActionManager::registerAction(m_returnFromFunctionAction,
|
|
|
|
|
"Debugger.ReturnFromFunction", cppDebuggercontext);
|
|
|
|
|
cmd->setAttribute(Command::CA_Hide);
|
|
|
|
|
debugMenu->addAction(cmd);
|
2010-03-18 10:56:25 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
if (isReverseDebuggingEnabled()) {
|
|
|
|
|
cmd = ActionManager::registerAction(m_reverseDirectionAction,
|
|
|
|
|
Constants::REVERSE, cppDebuggercontext);
|
|
|
|
|
cmd->setDefaultKeySequence(QKeySequence(UseMacShortcuts ? QString() : tr("F12")));
|
|
|
|
|
cmd->setAttribute(Command::CA_Hide);
|
|
|
|
|
debugMenu->addAction(cmd);
|
|
|
|
|
}
|
2010-02-15 16:02:41 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
debugMenu->addSeparator();
|
2010-03-18 10:56:25 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
//cmd = ActionManager::registerAction(m_snapshotAction,
|
|
|
|
|
// "Debugger.Snapshot", cppDebuggercontext);
|
|
|
|
|
//cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+D,Ctrl+S")));
|
|
|
|
|
//cmd->setAttribute(Command::CA_Hide);
|
|
|
|
|
//debugMenu->addAction(cmd);
|
2009-05-25 17:19:42 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
ActionManager::registerAction(m_frameDownAction,
|
|
|
|
|
"Debugger.FrameDown", cppDebuggercontext);
|
|
|
|
|
ActionManager::registerAction(m_frameUpAction,
|
|
|
|
|
"Debugger.FrameUp", cppDebuggercontext);
|
2010-03-18 10:56:25 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
cmd = ActionManager::registerAction(m_operateByInstructionAction,
|
|
|
|
|
Constants::OPERATE_BY_INSTRUCTION, cppDebuggercontext);
|
|
|
|
|
cmd->setAttribute(Command::CA_Hide);
|
|
|
|
|
debugMenu->addAction(cmd);
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
cmd = ActionManager::registerAction(m_breakAction, "Debugger.ToggleBreak");
|
|
|
|
|
cmd->setDefaultKeySequence(QKeySequence(UseMacShortcuts ? tr("F8") : tr("F9")));
|
|
|
|
|
debugMenu->addAction(cmd);
|
|
|
|
|
connect(m_breakAction, &QAction::triggered,
|
|
|
|
|
this, &DebuggerPluginPrivate::toggleBreakpointHelper);
|
2011-05-02 18:22:32 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
debugMenu->addSeparator();
|
2010-03-18 10:56:25 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
// currently broken
|
|
|
|
|
// auto qmlUpdateOnSaveDummyAction = new QAction(tr("Apply Changes on Save"), this);
|
|
|
|
|
// qmlUpdateOnSaveDummyAction->setCheckable(true);
|
|
|
|
|
// qmlUpdateOnSaveDummyAction->setIcon(Icons::APPLY_ON_SAVE.icon());
|
|
|
|
|
// qmlUpdateOnSaveDummyAction->setEnabled(false);
|
|
|
|
|
// cmd = ActionManager::registerAction(qmlUpdateOnSaveDummyAction, Constants::QML_UPDATE_ON_SAVE);
|
|
|
|
|
// debugMenu->addAction(cmd);
|
2010-06-07 13:17:19 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
auto qmlShowAppOnTopDummyAction = new QAction(tr("Show Application on Top"), this);
|
|
|
|
|
qmlShowAppOnTopDummyAction->setCheckable(true);
|
|
|
|
|
qmlShowAppOnTopDummyAction->setIcon(Icons::APP_ON_TOP.icon());
|
|
|
|
|
qmlShowAppOnTopDummyAction->setEnabled(false);
|
|
|
|
|
cmd = ActionManager::registerAction(qmlShowAppOnTopDummyAction, Constants::QML_SHOW_APP_ON_TOP);
|
|
|
|
|
debugMenu->addAction(cmd);
|
2010-03-18 10:56:25 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
auto qmlSelectDummyAction = new QAction(tr("Select"), this);
|
|
|
|
|
qmlSelectDummyAction->setCheckable(true);
|
|
|
|
|
qmlSelectDummyAction->setIcon(Icons::SELECT.icon());
|
|
|
|
|
qmlSelectDummyAction->setEnabled(false);
|
|
|
|
|
cmd = ActionManager::registerAction(qmlSelectDummyAction, Constants::QML_SELECTTOOL);
|
|
|
|
|
debugMenu->addAction(cmd);
|
2010-03-18 10:56:25 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
debugMenu->addSeparator();
|
2011-07-18 17:23:42 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
// Don't add '1' to the string as it shows up in the shortcut dialog.
|
|
|
|
|
cmd = ActionManager::registerAction(m_watchAction1,
|
|
|
|
|
"Debugger.AddToWatch", cppeditorcontext);
|
|
|
|
|
//cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+D,Ctrl+W")));
|
|
|
|
|
debugMenu->addAction(cmd);
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
// If the CppEditor plugin is there, we want to add something to
|
|
|
|
|
// the editor context menu.
|
|
|
|
|
if (ActionContainer *editorContextMenu =
|
|
|
|
|
ActionManager::actionContainer(CppEditor::Constants::M_CONTEXT)) {
|
|
|
|
|
cmd = editorContextMenu->addSeparator(cppDebuggercontext);
|
|
|
|
|
cmd->setAttribute(Command::CA_Hide);
|
2011-01-31 15:17:53 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
cmd = ActionManager::registerAction(m_watchAction2,
|
|
|
|
|
"Debugger.AddToWatch2", cppDebuggercontext);
|
|
|
|
|
cmd->action()->setEnabled(true);
|
|
|
|
|
editorContextMenu->addAction(cmd);
|
|
|
|
|
cmd->setAttribute(Command::CA_Hide);
|
|
|
|
|
cmd->setAttribute(Command::CA_NonConfigurable);
|
|
|
|
|
// Debugger.AddToWatch is enough.
|
|
|
|
|
}
|
2009-12-11 18:19:51 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
QList<IOptionsPage *> engineOptionPages;
|
|
|
|
|
addGdbOptionPages(&engineOptionPages);
|
|
|
|
|
addCdbOptionPages(&engineOptionPages);
|
2010-02-08 09:13:21 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
foreach (IOptionsPage *op, engineOptionPages)
|
|
|
|
|
m_plugin->addAutoReleasedObject(op);
|
|
|
|
|
m_plugin->addAutoReleasedObject(new LocalsAndExpressionsOptionsPage);
|
|
|
|
|
m_plugin->addAutoReleasedObject(new DebuggerOptionsPage);
|
2010-02-08 09:13:21 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
connect(ModeManager::instance(), &ModeManager::currentModeChanged,
|
|
|
|
|
this, &DebuggerPluginPrivate::onModeChanged);
|
2016-08-26 13:33:30 +02:00
|
|
|
connect(ModeManager::instance(), &ModeManager::currentModeChanged,
|
|
|
|
|
m_mainWindow.data(), &DebuggerMainWindow::onModeChanged);
|
2016-03-02 13:57:37 +01:00
|
|
|
connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::settingsChanged,
|
|
|
|
|
this, &DebuggerPluginPrivate::updateDebugWithoutDeployMenu);
|
2012-05-08 09:43:14 +02:00
|
|
|
|
2016-03-24 13:59:05 +01:00
|
|
|
m_mainWindow->finalizeSetup();
|
|
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
// Debug mode setup
|
2016-03-24 13:59:05 +01:00
|
|
|
m_mode = new DebugMode;
|
2016-05-12 11:57:29 +02:00
|
|
|
m_modeWindow = createModeWindow(Constants::MODE_DEBUG, m_mainWindow);
|
2016-03-24 13:59:05 +01:00
|
|
|
m_mode->setWidget(m_modeWindow);
|
2010-11-26 15:10:10 +01:00
|
|
|
|
2016-09-23 10:46:40 +02:00
|
|
|
m_plugin->addAutoReleasedObject(new DebugModeContext(m_modeWindow));
|
2016-03-10 08:53:49 +01:00
|
|
|
|
2016-03-24 13:59:05 +01:00
|
|
|
m_plugin->addObject(m_mode);
|
2016-02-29 12:11:18 +01:00
|
|
|
|
2010-03-10 13:46:05 +01:00
|
|
|
|
2016-03-10 08:53:49 +01:00
|
|
|
connect(SessionManager::instance(), &SessionManager::startupProjectChanged,
|
|
|
|
|
this, &DebuggerPluginPrivate::updateUiForProject);
|
2010-03-11 11:07:16 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
//
|
|
|
|
|
// Connections
|
|
|
|
|
//
|
2010-11-23 16:42:46 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
// Core
|
|
|
|
|
connect(ICore::instance(), &ICore::saveSettingsRequested,
|
|
|
|
|
this, &DebuggerPluginPrivate::writeSettings);
|
2010-02-09 20:44:40 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
// TextEditor
|
|
|
|
|
connect(TextEditorSettings::instance(), &TextEditorSettings::fontSettingsChanged,
|
|
|
|
|
this, &DebuggerPluginPrivate::fontSettingsChanged);
|
2010-09-27 12:23:34 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
// ProjectExplorer
|
|
|
|
|
connect(SessionManager::instance(), &SessionManager::sessionLoaded,
|
|
|
|
|
this, &DebuggerPluginPrivate::sessionLoaded);
|
|
|
|
|
connect(SessionManager::instance(), &SessionManager::aboutToSaveSession,
|
|
|
|
|
this, &DebuggerPluginPrivate::aboutToSaveSession);
|
|
|
|
|
connect(SessionManager::instance(), &SessionManager::aboutToUnloadSession,
|
|
|
|
|
this, &DebuggerPluginPrivate::aboutToUnloadSession);
|
|
|
|
|
connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::updateRunActions,
|
|
|
|
|
this, &DebuggerPluginPrivate::updateDebugActions);
|
|
|
|
|
|
|
|
|
|
// EditorManager
|
|
|
|
|
connect(EditorManager::instance(), &EditorManager::editorOpened,
|
|
|
|
|
this, &DebuggerPluginPrivate::editorOpened);
|
|
|
|
|
connect(EditorManager::instance(), &EditorManager::currentEditorChanged,
|
|
|
|
|
this, &DebuggerPluginPrivate::updateBreakMenuItem);
|
|
|
|
|
|
|
|
|
|
// Application interaction
|
|
|
|
|
connect(action(SettingsDialog), &QAction::triggered,
|
|
|
|
|
[] { ICore::showOptionsDialog(DEBUGGER_COMMON_SETTINGS_ID); });
|
|
|
|
|
|
|
|
|
|
// Toolbar
|
|
|
|
|
ToolbarDescription toolbar;
|
|
|
|
|
toolbar.addAction(m_visibleStartAction);
|
2016-04-24 22:51:24 +02:00
|
|
|
toolbar.addAction(ActionManager::command(Constants::STOP)->action(), Icons::DEBUG_EXIT_SMALL_TOOLBAR.icon());
|
|
|
|
|
toolbar.addAction(ActionManager::command(Constants::NEXT)->action(), Icons::STEP_OVER_TOOLBAR.icon());
|
|
|
|
|
toolbar.addAction(ActionManager::command(Constants::STEP)->action(), Icons::STEP_INTO_TOOLBAR.icon());
|
|
|
|
|
toolbar.addAction(ActionManager::command(Constants::STEPOUT)->action(), Icons::STEP_OUT_TOOLBAR.icon());
|
|
|
|
|
toolbar.addAction(ActionManager::command(Constants::RESET)->action(), Icons::RESTART_TOOLBAR.icon());
|
2016-04-22 10:01:32 +02:00
|
|
|
toolbar.addAction(ActionManager::command(Constants::OPERATE_BY_INSTRUCTION)->action());
|
2016-03-02 13:57:37 +01:00
|
|
|
|
|
|
|
|
if (isReverseDebuggingEnabled()) {
|
|
|
|
|
m_reverseToolButton = new QToolButton;
|
|
|
|
|
m_reverseToolButton->setDefaultAction(m_reverseDirectionAction);
|
|
|
|
|
toolbar.addWidget(m_reverseToolButton);
|
2010-07-21 17:06:22 +02:00
|
|
|
}
|
2016-03-02 13:57:37 +01:00
|
|
|
|
|
|
|
|
toolbar.addWidget(new StyledSeparator);
|
2016-04-16 20:59:42 +02:00
|
|
|
|
|
|
|
|
m_threadLabel = new QLabel(tr("Threads:"));
|
|
|
|
|
toolbar.addWidget(m_threadLabel);
|
2016-03-02 13:57:37 +01:00
|
|
|
|
|
|
|
|
m_threadBox = new QComboBox;
|
|
|
|
|
m_threadBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
|
|
|
|
connect(m_threadBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::activated),
|
|
|
|
|
this, &DebuggerPluginPrivate::selectThread);
|
|
|
|
|
|
|
|
|
|
toolbar.addWidget(m_threadBox);
|
|
|
|
|
// toolbar.addSpacerItem(new QSpacerItem(4, 0));
|
|
|
|
|
|
|
|
|
|
// ToolbarDescription qmlToolbar
|
|
|
|
|
// qmlToolbar.addAction(qmlUpdateOnSaveDummyAction);
|
2016-05-06 17:27:22 +02:00
|
|
|
// qmlToolbar.addAction(qmlShowAppOnTopDummyAction, Icons::APP_ON_TOP_TOOLBAR.icon());
|
2016-03-02 13:57:37 +01:00
|
|
|
// qmlToolbar.addWidget(new StyledSeparator);
|
2016-05-06 17:27:22 +02:00
|
|
|
// qmlToolbar.addAction(qmlSelectDummyAction, Icons::SELECT_TOOLBAR.icon());
|
2016-03-02 13:57:37 +01:00
|
|
|
// qmlToolbar.addWidget(new StyledSeparator);
|
|
|
|
|
|
2016-05-12 11:57:29 +02:00
|
|
|
auto createBasePerspective = [this] { return new Perspective({}, {
|
2016-03-02 13:57:37 +01:00
|
|
|
{ DOCKWIDGET_STACK, m_stackWindow, {}, Perspective::SplitVertical },
|
|
|
|
|
{ DOCKWIDGET_BREAK, m_breakWindow, DOCKWIDGET_STACK, Perspective::SplitHorizontal },
|
|
|
|
|
{ DOCKWIDGET_THREADS, m_threadsWindow, DOCKWIDGET_BREAK, Perspective::AddToTab, false },
|
|
|
|
|
{ DOCKWIDGET_MODULES, m_modulesWindow, DOCKWIDGET_THREADS, Perspective::AddToTab, false },
|
|
|
|
|
{ DOCKWIDGET_SOURCE_FILES, m_sourceFilesWindow, DOCKWIDGET_MODULES, Perspective::AddToTab, false },
|
|
|
|
|
{ DOCKWIDGET_SNAPSHOTS, m_snapshotWindow, DOCKWIDGET_SOURCE_FILES, Perspective::AddToTab, false },
|
|
|
|
|
{ DOCKWIDGET_WATCHERS, m_localsAndExpressionsWindow, {}, Perspective::AddToTab, true,
|
|
|
|
|
Qt::RightDockWidgetArea },
|
|
|
|
|
{ DOCKWIDGET_OUTPUT, m_logWindow, {}, Perspective::AddToTab, false, Qt::TopDockWidgetArea },
|
|
|
|
|
{ DOCKWIDGET_BREAK, 0, {}, Perspective::Raise }
|
2016-05-12 11:57:29 +02:00
|
|
|
}); };
|
2016-03-02 13:57:37 +01:00
|
|
|
|
2016-05-12 11:57:29 +02:00
|
|
|
Perspective *cppPerspective = createBasePerspective();
|
|
|
|
|
cppPerspective->setName(tr("Debugger"));
|
|
|
|
|
cppPerspective->addOperation({ DOCKWIDGET_REGISTER, m_registerWindow, DOCKWIDGET_SNAPSHOTS,
|
2016-03-02 13:57:37 +01:00
|
|
|
Perspective::AddToTab, false });
|
|
|
|
|
|
|
|
|
|
Debugger::registerToolbar(CppPerspectiveId, toolbar);
|
|
|
|
|
Debugger::registerPerspective(CppPerspectiveId, cppPerspective);
|
|
|
|
|
|
2016-05-12 11:57:29 +02:00
|
|
|
// Perspective *qmlPerspective = createBasePerspective();
|
|
|
|
|
// qmlPerspective->setName(tr("QML Debugger"));
|
|
|
|
|
// qmlPerspective->addOperation({ DOCKWIDGET_REGISTER, DOCKWIDGET_SNAPSHOTS,
|
2016-03-02 13:57:37 +01:00
|
|
|
// Perspective::AddToTab, false });
|
|
|
|
|
//
|
|
|
|
|
// Debugger::registerToolbar(QmlPerspectiveId, toolbarContainer);
|
|
|
|
|
// Debugger::registerPerspective(QmlPerspectiveId, qmlPerspective);
|
|
|
|
|
|
|
|
|
|
connect(action(EnableReverseDebugging), &SavedAction::valueChanged,
|
|
|
|
|
this, &DebuggerPluginPrivate::enableReverseDebuggingTriggered);
|
|
|
|
|
|
|
|
|
|
setInitialState();
|
|
|
|
|
connectEngine(0);
|
|
|
|
|
|
|
|
|
|
connect(SessionManager::instance(), &SessionManager::startupProjectChanged,
|
|
|
|
|
this, &DebuggerPluginPrivate::onCurrentProjectChanged);
|
|
|
|
|
|
|
|
|
|
m_commonOptionsPage = new CommonOptionsPage(m_globalDebuggerOptions);
|
|
|
|
|
m_plugin->addAutoReleasedObject(m_commonOptionsPage);
|
|
|
|
|
|
|
|
|
|
m_globalDebuggerOptions->fromSettings();
|
|
|
|
|
m_watchersWindow->setVisible(false);
|
|
|
|
|
m_returnWindow->setVisible(false);
|
|
|
|
|
|
|
|
|
|
return true;
|
2010-07-21 17:06:22 +02:00
|
|
|
}
|
|
|
|
|
|
2016-06-07 17:04:53 +02:00
|
|
|
void setConfigValue(const QString &name, const QVariant &value)
|
2010-12-02 13:20:06 +01:00
|
|
|
{
|
2016-06-07 17:04:53 +02:00
|
|
|
ICore::settings()->setValue("DebugMode/" + name, value);
|
2010-12-02 13:20:06 +01:00
|
|
|
}
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2016-06-07 17:04:53 +02:00
|
|
|
QVariant configValue(const QString &name)
|
2011-02-25 13:43:06 +01:00
|
|
|
{
|
2016-06-07 17:04:53 +02:00
|
|
|
return ICore::settings()->value("DebugMode/" + name);
|
2011-02-25 13:43:06 +01:00
|
|
|
}
|
|
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void DebuggerPluginPrivate::onCurrentProjectChanged(Project *project)
|
2010-12-02 13:20:06 +01:00
|
|
|
{
|
2016-03-02 13:57:37 +01:00
|
|
|
RunConfiguration *activeRc = 0;
|
|
|
|
|
if (project) {
|
|
|
|
|
Target *target = project->activeTarget();
|
|
|
|
|
if (target)
|
|
|
|
|
activeRc = target->activeRunConfiguration();
|
|
|
|
|
if (!activeRc)
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
for (int i = 0, n = m_snapshotHandler->size(); i != n; ++i) {
|
|
|
|
|
// Run controls might be deleted during exit.
|
|
|
|
|
if (DebuggerEngine *engine = m_snapshotHandler->at(i)) {
|
|
|
|
|
DebuggerRunControl *runControl = engine->runControl();
|
|
|
|
|
RunConfiguration *rc = runControl->runConfiguration();
|
|
|
|
|
if (rc == activeRc) {
|
|
|
|
|
m_snapshotHandler->setCurrentIndex(i);
|
|
|
|
|
updateState(engine);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If we have a running debugger, don't touch it.
|
|
|
|
|
if (m_snapshotHandler->size())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// No corresponding debugger found. So we are ready to start one.
|
|
|
|
|
m_interruptAction->setEnabled(false);
|
|
|
|
|
m_continueAction->setEnabled(false);
|
|
|
|
|
m_exitAction->setEnabled(false);
|
|
|
|
|
QString whyNot;
|
2016-03-10 11:11:19 +01:00
|
|
|
const bool canRun = ProjectExplorerPlugin::canRunStartupProject(ProjectExplorer::Constants::DEBUG_RUN_MODE, &whyNot);
|
2016-03-02 13:57:37 +01:00
|
|
|
m_startAction->setEnabled(canRun);
|
|
|
|
|
m_startAction->setToolTip(whyNot);
|
|
|
|
|
m_debugWithoutDeployAction->setEnabled(canRun);
|
|
|
|
|
setProxyAction(m_visibleStartAction, Id(Constants::DEBUG));
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void DebuggerPluginPrivate::startAndDebugApplication()
|
2010-04-06 17:58:11 +02:00
|
|
|
{
|
2016-03-02 13:57:37 +01:00
|
|
|
DebuggerRunParameters rp;
|
|
|
|
|
Kit *kit;
|
|
|
|
|
if (StartApplicationDialog::run(ICore::dialogParent(), &rp, &kit))
|
|
|
|
|
createAndScheduleRun(rp, kit);
|
2010-04-06 17:58:11 +02:00
|
|
|
}
|
|
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void DebuggerPluginPrivate::attachCore()
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2016-03-02 13:57:37 +01:00
|
|
|
AttachCoreDialog dlg(ICore::dialogParent());
|
2010-12-02 13:20:06 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
const QString lastExternalKit = configValue("LastExternalKit").toString();
|
|
|
|
|
if (!lastExternalKit.isEmpty())
|
|
|
|
|
dlg.setKitId(Id::fromString(lastExternalKit));
|
|
|
|
|
dlg.setLocalExecutableFile(configValue("LastExternalExecutableFile").toString());
|
|
|
|
|
dlg.setLocalCoreFile(configValue("LastLocalCoreFile").toString());
|
|
|
|
|
dlg.setRemoteCoreFile(configValue("LastRemoteCoreFile").toString());
|
|
|
|
|
dlg.setOverrideStartScript(configValue("LastExternalStartScript").toString());
|
|
|
|
|
dlg.setForceLocalCoreFile(configValue("LastForceLocalCoreFile").toBool());
|
2010-12-02 13:20:06 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
if (dlg.exec() != QDialog::Accepted)
|
2010-06-16 11:08:54 +02:00
|
|
|
return;
|
2016-03-02 13:57:37 +01:00
|
|
|
|
|
|
|
|
setConfigValue("LastExternalExecutableFile", dlg.localExecutableFile());
|
|
|
|
|
setConfigValue("LastLocalCoreFile", dlg.localCoreFile());
|
|
|
|
|
setConfigValue("LastRemoteCoreFile", dlg.remoteCoreFile());
|
|
|
|
|
setConfigValue("LastExternalKit", dlg.kit()->id().toSetting());
|
|
|
|
|
setConfigValue("LastExternalStartScript", dlg.overrideStartScript());
|
|
|
|
|
setConfigValue("LastForceLocalCoreFile", dlg.forcesLocalCoreFile());
|
|
|
|
|
|
|
|
|
|
QString display = dlg.useLocalCoreFile() ? dlg.localCoreFile() : dlg.remoteCoreFile();
|
|
|
|
|
DebuggerRunParameters rp;
|
|
|
|
|
rp.masterEngineType = DebuggerKitInformation::engineType(dlg.kit());
|
|
|
|
|
rp.inferior.executable = dlg.localExecutableFile();
|
|
|
|
|
rp.coreFile = dlg.localCoreFile();
|
|
|
|
|
rp.displayName = tr("Core file \"%1\"").arg(display);
|
|
|
|
|
rp.startMode = AttachCore;
|
|
|
|
|
rp.closeMode = DetachAtClose;
|
|
|
|
|
rp.overrideStartScript = dlg.overrideStartScript();
|
|
|
|
|
createAndScheduleRun(rp, dlg.kit());
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void DebuggerPluginPrivate::startRemoteCdbSession()
|
2010-11-19 16:13:22 +01:00
|
|
|
{
|
2016-06-07 17:04:53 +02:00
|
|
|
const QString connectionKey = "CdbRemoteConnection";
|
2016-03-02 13:57:37 +01:00
|
|
|
DebuggerRunParameters rp;
|
|
|
|
|
Kit *kit = findUniversalCdbKit();
|
|
|
|
|
QTC_ASSERT(kit, return);
|
|
|
|
|
rp.startMode = AttachToRemoteServer;
|
|
|
|
|
rp.closeMode = KillAtClose;
|
|
|
|
|
StartRemoteCdbDialog dlg(ICore::dialogParent());
|
|
|
|
|
QString previousConnection = configValue(connectionKey).toString();
|
|
|
|
|
if (previousConnection.isEmpty())
|
|
|
|
|
previousConnection = QLatin1String("localhost:1234");
|
|
|
|
|
dlg.setConnection(previousConnection);
|
|
|
|
|
if (dlg.exec() != QDialog::Accepted)
|
|
|
|
|
return;
|
|
|
|
|
rp.remoteChannel = dlg.connection();
|
|
|
|
|
setConfigValue(connectionKey, rp.remoteChannel);
|
|
|
|
|
createAndScheduleRun(rp, kit);
|
2010-11-19 16:13:22 +01:00
|
|
|
}
|
|
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void DebuggerPluginPrivate::attachToRemoteServer()
|
2015-06-10 14:19:42 +02:00
|
|
|
{
|
2016-03-02 13:57:37 +01:00
|
|
|
DebuggerRunParameters rp;
|
|
|
|
|
Kit *kit;
|
|
|
|
|
rp.startMode = AttachToRemoteServer;
|
2016-05-02 20:53:03 +03:00
|
|
|
rp.useContinueInsteadOfRun = true;
|
2016-03-02 13:57:37 +01:00
|
|
|
if (StartApplicationDialog::run(ICore::dialogParent(), &rp, &kit)) {
|
|
|
|
|
rp.closeMode = KillAtClose;
|
|
|
|
|
createAndScheduleRun(rp, kit);
|
|
|
|
|
}
|
2015-06-10 14:19:42 +02:00
|
|
|
}
|
|
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void DebuggerPluginPrivate::startRemoteServerAndAttachToProcess()
|
2015-06-10 14:19:42 +02:00
|
|
|
{
|
2016-03-02 13:57:37 +01:00
|
|
|
auto kitChooser = new DebuggerKitChooser(DebuggerKitChooser::AnyDebugging);
|
|
|
|
|
auto dlg = new DeviceProcessesDialog(kitChooser, ICore::dialogParent());
|
|
|
|
|
dlg->addAcceptButton(DeviceProcessesDialog::tr("&Attach to Process"));
|
|
|
|
|
dlg->showAllDevices();
|
|
|
|
|
if (dlg->exec() == QDialog::Rejected) {
|
|
|
|
|
delete dlg;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2012-05-23 13:25:51 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
dlg->setAttribute(Qt::WA_DeleteOnClose);
|
|
|
|
|
Kit *kit = kitChooser->currentKit();
|
|
|
|
|
QTC_ASSERT(kit, return);
|
|
|
|
|
IDevice::ConstPtr device = DeviceKitInformation::device(kit);
|
|
|
|
|
QTC_ASSERT(device, return);
|
2014-07-16 16:32:11 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
GdbServerStarter *starter = new GdbServerStarter(dlg, true);
|
|
|
|
|
starter->run();
|
|
|
|
|
}
|
2010-12-01 15:41:08 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void DebuggerPluginPrivate::attachToRunningApplication()
|
|
|
|
|
{
|
|
|
|
|
auto kitChooser = new DebuggerKitChooser(DebuggerKitChooser::LocalDebugging);
|
2010-12-01 15:41:08 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
auto dlg = new DeviceProcessesDialog(kitChooser, ICore::dialogParent());
|
|
|
|
|
dlg->addAcceptButton(DeviceProcessesDialog::tr("&Attach to Process"));
|
|
|
|
|
dlg->showAllDevices();
|
|
|
|
|
if (dlg->exec() == QDialog::Rejected) {
|
|
|
|
|
delete dlg;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2010-05-12 16:48:04 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
dlg->setAttribute(Qt::WA_DeleteOnClose);
|
|
|
|
|
Kit *kit = kitChooser->currentKit();
|
|
|
|
|
QTC_ASSERT(kit, return);
|
|
|
|
|
IDevice::ConstPtr device = DeviceKitInformation::device(kit);
|
|
|
|
|
QTC_ASSERT(device, return);
|
2010-12-02 13:20:06 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
if (device->type() == PE::DESKTOP_DEVICE_TYPE) {
|
|
|
|
|
attachToRunningProcess(kit, dlg->currentProcess(), false);
|
|
|
|
|
} else {
|
|
|
|
|
GdbServerStarter *starter = new GdbServerStarter(dlg, true);
|
|
|
|
|
starter->run();
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-12-02 13:20:06 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void DebuggerPluginPrivate::attachToUnstartedApplicationDialog()
|
|
|
|
|
{
|
|
|
|
|
auto dlg = new UnstartedAppWatcherDialog(ICore::dialogParent());
|
2014-06-04 14:45:10 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
connect(dlg, &QDialog::finished, dlg, &QObject::deleteLater);
|
|
|
|
|
connect(dlg, &UnstartedAppWatcherDialog::processFound, this, [this, dlg] {
|
|
|
|
|
DebuggerRunControl *rc = attachToRunningProcess(dlg->currentKit(),
|
|
|
|
|
dlg->currentProcess(),
|
|
|
|
|
dlg->continueOnAttach());
|
|
|
|
|
if (!rc)
|
|
|
|
|
return;
|
2014-06-04 14:45:10 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
if (dlg->hideOnAttach())
|
|
|
|
|
connect(rc, &RunControl::finished, dlg, &UnstartedAppWatcherDialog::startWatching);
|
|
|
|
|
});
|
2014-06-04 14:45:10 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
dlg->show();
|
|
|
|
|
}
|
2014-06-04 14:45:10 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
DebuggerRunControl *DebuggerPluginPrivate::attachToRunningProcess(Kit *kit,
|
|
|
|
|
DeviceProcessItem process, bool contAfterAttach)
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(kit, return 0);
|
|
|
|
|
IDevice::ConstPtr device = DeviceKitInformation::device(kit);
|
|
|
|
|
QTC_ASSERT(device, return 0);
|
|
|
|
|
if (process.pid == 0) {
|
|
|
|
|
AsynchronousMessageBox::warning(tr("Warning"), tr("Cannot attach to process with PID 0"));
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2014-06-04 14:45:10 +02:00
|
|
|
|
2016-07-13 10:40:05 +02:00
|
|
|
const Abi tcAbi = ToolChainKitInformation::targetAbi(kit);
|
|
|
|
|
const bool isWindows = (tcAbi.os() == Abi::WindowsOS);
|
2016-03-02 13:57:37 +01:00
|
|
|
if (isWindows && isWinProcessBeingDebugged(process.pid)) {
|
|
|
|
|
AsynchronousMessageBox::warning(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 0;
|
|
|
|
|
}
|
2014-06-04 14:45:10 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
if (device->type() != PE::DESKTOP_DEVICE_TYPE) {
|
|
|
|
|
AsynchronousMessageBox::warning(tr("Not a Desktop Device Type"),
|
|
|
|
|
tr("It is only possible to attach to a locally running process."));
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2014-06-04 14:45:10 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
DebuggerRunParameters rp;
|
|
|
|
|
rp.attachPID = process.pid;
|
|
|
|
|
rp.displayName = tr("Process %1").arg(process.pid);
|
|
|
|
|
rp.inferior.executable = process.exe;
|
|
|
|
|
rp.startMode = AttachExternal;
|
|
|
|
|
rp.closeMode = DetachAtClose;
|
|
|
|
|
rp.continueAfterAttach = contAfterAttach;
|
|
|
|
|
return createAndScheduleRun(rp, kit);
|
|
|
|
|
}
|
2014-06-04 14:45:10 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void DebuggerPlugin::attachExternalApplication(RunControl *rc)
|
|
|
|
|
{
|
|
|
|
|
DebuggerRunParameters rp;
|
|
|
|
|
rp.attachPID = rc->applicationProcessHandle().pid();
|
|
|
|
|
rp.displayName = tr("Process %1").arg(rp.attachPID);
|
|
|
|
|
rp.startMode = AttachExternal;
|
|
|
|
|
rp.closeMode = DetachAtClose;
|
|
|
|
|
rp.toolChainAbi = rc->abi();
|
|
|
|
|
Kit *kit = 0;
|
|
|
|
|
if (const RunConfiguration *runConfiguration = rc->runConfiguration())
|
|
|
|
|
if (const Target *target = runConfiguration->target())
|
|
|
|
|
kit = target->kit();
|
2016-03-22 17:17:05 +01:00
|
|
|
if (!kit)
|
|
|
|
|
kit = guessKitFromParameters(rp);
|
2016-03-02 13:57:37 +01:00
|
|
|
createAndScheduleRun(rp, kit);
|
|
|
|
|
}
|
2014-06-04 14:45:10 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void DebuggerPluginPrivate::attachToQmlPort()
|
|
|
|
|
{
|
|
|
|
|
DebuggerRunParameters rp;
|
|
|
|
|
AttachToQmlPortDialog dlg(ICore::mainWindow());
|
2014-06-04 14:45:10 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
const QVariant qmlServerPort = configValue("LastQmlServerPort");
|
|
|
|
|
if (qmlServerPort.isValid())
|
|
|
|
|
dlg.setPort(qmlServerPort.toInt());
|
2016-06-13 14:18:50 +02:00
|
|
|
else if (rp.qmlServer.port.isValid())
|
|
|
|
|
dlg.setPort(rp.qmlServer.port.number());
|
2016-03-02 13:57:37 +01:00
|
|
|
else
|
2016-04-19 16:43:30 +02:00
|
|
|
dlg.setPort(-1);
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
const Id kitId = Id::fromSetting(configValue("LastProfile"));
|
|
|
|
|
if (kitId.isValid())
|
|
|
|
|
dlg.setKitId(kitId);
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
if (dlg.exec() != QDialog::Accepted)
|
|
|
|
|
return;
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
Kit *kit = dlg.kit();
|
|
|
|
|
QTC_ASSERT(kit, return);
|
|
|
|
|
setConfigValue("LastQmlServerPort", dlg.port());
|
|
|
|
|
setConfigValue("LastProfile", kit->id().toSetting());
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
IDevice::ConstPtr device = DeviceKitInformation::device(kit);
|
|
|
|
|
if (device) {
|
|
|
|
|
rp.connParams = device->sshParameters();
|
2016-06-03 19:11:29 +02:00
|
|
|
Connection toolControl = device->toolControlChannel(IDevice::QmlControlChannel);
|
|
|
|
|
QTC_ASSERT(toolControl.is<HostName>(), return);
|
2016-06-13 14:18:50 +02:00
|
|
|
rp.qmlServer.host = toolControl.as<HostName>().host();
|
2016-03-02 13:57:37 +01:00
|
|
|
}
|
2016-06-13 14:18:50 +02:00
|
|
|
rp.qmlServer.port = Utils::Port(dlg.port());
|
2016-03-02 13:57:37 +01:00
|
|
|
rp.startMode = AttachToRemoteProcess;
|
|
|
|
|
rp.closeMode = KillAtClose;
|
|
|
|
|
rp.languages = QmlLanguage;
|
|
|
|
|
rp.masterEngineType = QmlEngineType;
|
2010-11-08 15:19:13 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
//
|
|
|
|
|
// get files from all the projects in the session
|
|
|
|
|
//
|
|
|
|
|
QList<Project *> projects = SessionManager::projects();
|
|
|
|
|
if (Project *startupProject = SessionManager::startupProject()) {
|
|
|
|
|
// startup project first
|
|
|
|
|
projects.removeOne(startupProject);
|
|
|
|
|
projects.insert(0, startupProject);
|
|
|
|
|
}
|
|
|
|
|
QStringList sourceFiles;
|
|
|
|
|
foreach (Project *project, projects)
|
|
|
|
|
sourceFiles << project->files(Project::SourceFiles);
|
2010-11-08 15:19:13 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
rp.projectSourceDirectory =
|
|
|
|
|
!projects.isEmpty() ? projects.first()->projectDirectory().toString() : QString();
|
|
|
|
|
rp.projectSourceFiles = sourceFiles;
|
|
|
|
|
createAndScheduleRun(rp, kit);
|
|
|
|
|
}
|
2010-11-08 15:19:13 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void DebuggerPluginPrivate::enableReverseDebuggingTriggered(const QVariant &value)
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(m_reverseToolButton, return);
|
|
|
|
|
m_reverseToolButton->setVisible(value.toBool());
|
|
|
|
|
m_reverseDirectionAction->setChecked(false);
|
|
|
|
|
m_reverseDirectionAction->setEnabled(value.toBool());
|
|
|
|
|
}
|
2010-11-08 15:19:13 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void DebuggerPluginPrivate::runScheduled()
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0, n = m_scheduledStarts.size(); i != n; ++i)
|
|
|
|
|
createAndScheduleRun(m_scheduledStarts.at(i).first, m_scheduledStarts.at(i).second);
|
|
|
|
|
}
|
2010-11-10 16:33:11 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void DebuggerPluginPrivate::editorOpened(IEditor *editor)
|
|
|
|
|
{
|
|
|
|
|
if (auto widget = qobject_cast<TextEditorWidget *>(editor->widget())) {
|
|
|
|
|
connect(widget, &TextEditorWidget::markRequested,
|
|
|
|
|
this, &DebuggerPluginPrivate::requestMark);
|
2014-06-05 17:22:51 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
connect(widget, &TextEditorWidget::markContextMenuRequested,
|
|
|
|
|
this, &DebuggerPluginPrivate::requestContextMenu);
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-04-28 15:08:52 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void DebuggerPluginPrivate::updateBreakMenuItem(IEditor *editor)
|
|
|
|
|
{
|
|
|
|
|
BaseTextEditor *textEditor = qobject_cast<BaseTextEditor *>(editor);
|
|
|
|
|
m_breakAction->setEnabled(textEditor != 0);
|
|
|
|
|
}
|
2010-11-24 18:36:17 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void DebuggerPluginPrivate::requestContextMenu(TextEditorWidget *widget,
|
|
|
|
|
int lineNumber, QMenu *menu)
|
|
|
|
|
{
|
|
|
|
|
Breakpoint bp;
|
|
|
|
|
TextDocument *document = widget->textDocument();
|
2010-11-24 18:36:17 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
ContextData args = getLocationContext(document, lineNumber);
|
|
|
|
|
if (args.type == LocationByAddress) {
|
|
|
|
|
BreakpointResponse needle;
|
|
|
|
|
needle.type = BreakpointByAddress;
|
|
|
|
|
needle.address = args.address;
|
|
|
|
|
needle.lineNumber = -1;
|
|
|
|
|
bp = breakHandler()->findSimilarBreakpoint(needle);
|
|
|
|
|
} else if (args.type == LocationByFile) {
|
|
|
|
|
bp = breakHandler()->findBreakpointByFileAndLine(args.fileName, lineNumber);
|
|
|
|
|
if (!bp)
|
|
|
|
|
bp = breakHandler()->findBreakpointByFileAndLine(args.fileName, lineNumber, false);
|
|
|
|
|
}
|
2010-11-24 18:36:17 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
if (bp) {
|
|
|
|
|
QString id = bp.id().toString();
|
2010-12-02 13:20:06 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
// Remove existing breakpoint.
|
|
|
|
|
auto act = menu->addAction(tr("Remove Breakpoint %1").arg(id));
|
|
|
|
|
connect(act, &QAction::triggered, [bp] { bp.removeBreakpoint(); });
|
2010-12-02 13:20:06 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
// Enable/disable existing breakpoint.
|
|
|
|
|
if (bp.isEnabled()) {
|
|
|
|
|
act = menu->addAction(tr("Disable Breakpoint %1").arg(id));
|
|
|
|
|
connect(act, &QAction::triggered, [bp] { bp.setEnabled(false); });
|
|
|
|
|
} else {
|
|
|
|
|
act = menu->addAction(tr("Enable Breakpoint %1").arg(id));
|
|
|
|
|
connect(act, &QAction::triggered, [bp] { bp.setEnabled(true); });
|
|
|
|
|
}
|
2010-12-02 13:20:06 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
// Edit existing breakpoint.
|
|
|
|
|
act = menu->addAction(tr("Edit Breakpoint %1...").arg(id));
|
|
|
|
|
connect(act, &QAction::triggered, [bp] {
|
2016-07-18 12:36:31 +02:00
|
|
|
breakHandler()->editBreakpoint(bp, ICore::dialogParent());
|
2016-03-02 13:57:37 +01:00
|
|
|
});
|
2010-12-02 13:20:06 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
} else {
|
|
|
|
|
// Handle non-existing breakpoint.
|
|
|
|
|
const QString text = args.address
|
|
|
|
|
? tr("Set Breakpoint at 0x%1").arg(args.address, 0, 16)
|
|
|
|
|
: tr("Set Breakpoint at Line %1").arg(lineNumber);
|
|
|
|
|
auto act = menu->addAction(text);
|
|
|
|
|
act->setEnabled(args.isValid());
|
|
|
|
|
connect(act, &QAction::triggered, [this, args] {
|
|
|
|
|
breakpointSetMarginActionTriggered(false, args);
|
|
|
|
|
});
|
2010-12-02 13:20:06 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
// Message trace point
|
|
|
|
|
const QString tracePointText = args.address
|
|
|
|
|
? tr("Set Message Tracepoint at 0x%1...").arg(args.address, 0, 16)
|
|
|
|
|
: tr("Set Message Tracepoint at Line %1...").arg(lineNumber);
|
|
|
|
|
act = menu->addAction(tracePointText);
|
|
|
|
|
act->setEnabled(args.isValid());
|
|
|
|
|
connect(act, &QAction::triggered, [this, args] {
|
|
|
|
|
breakpointSetMarginActionTriggered(true, args);
|
|
|
|
|
});
|
|
|
|
|
}
|
2010-12-02 13:20:06 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
// Run to, jump to line below in stopped state.
|
|
|
|
|
if (currentEngine()->state() == InferiorStopOk && args.isValid()) {
|
|
|
|
|
menu->addSeparator();
|
|
|
|
|
if (currentEngine()->hasCapability(RunToLineCapability)) {
|
|
|
|
|
auto act = menu->addAction(args.address
|
|
|
|
|
? DebuggerEngine::tr("Run to Address 0x%1").arg(args.address, 0, 16)
|
|
|
|
|
: DebuggerEngine::tr("Run to Line %1").arg(args.lineNumber));
|
|
|
|
|
connect(act, &QAction::triggered, [this, args] {
|
|
|
|
|
currentEngine()->executeRunToLine(args);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
if (currentEngine()->hasCapability(JumpToLineCapability)) {
|
|
|
|
|
auto act = menu->addAction(args.address
|
|
|
|
|
? DebuggerEngine::tr("Jump to Address 0x%1").arg(args.address, 0, 16)
|
|
|
|
|
: DebuggerEngine::tr("Jump to Line %1").arg(args.lineNumber));
|
|
|
|
|
connect(act, &QAction::triggered, [this, args] {
|
|
|
|
|
currentEngine()->executeJumpToLine(args);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
// Disassemble current function in stopped state.
|
|
|
|
|
if (currentEngine()->hasCapability(DisassemblerCapability)) {
|
|
|
|
|
StackFrame frame;
|
|
|
|
|
frame.function = cppFunctionAt(args.fileName, lineNumber, 1);
|
|
|
|
|
frame.line = 42; // trick gdb into mixed mode.
|
|
|
|
|
if (!frame.function.isEmpty()) {
|
|
|
|
|
const QString text = tr("Disassemble Function \"%1\"")
|
|
|
|
|
.arg(frame.function);
|
|
|
|
|
auto act = new QAction(text, menu);
|
|
|
|
|
connect(act, &QAction::triggered, [this, frame] {
|
|
|
|
|
currentEngine()->openDisassemblerView(Location(frame));
|
|
|
|
|
});
|
|
|
|
|
menu->addAction(act);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-06-11 12:38:54 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void DebuggerPluginPrivate::toggleBreakpoint(const ContextData &location, const QString &tracePointMessage)
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(location.isValid(), return);
|
|
|
|
|
BreakHandler *handler = m_breakHandler;
|
|
|
|
|
Breakpoint bp;
|
|
|
|
|
if (location.type == LocationByFile) {
|
|
|
|
|
bp = handler->findBreakpointByFileAndLine(location.fileName, location.lineNumber, true);
|
|
|
|
|
if (!bp)
|
|
|
|
|
bp = handler->findBreakpointByFileAndLine(location.fileName, location.lineNumber, false);
|
|
|
|
|
} else if (location.type == LocationByAddress) {
|
|
|
|
|
bp = handler->findBreakpointByAddress(location.address);
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
if (bp) {
|
|
|
|
|
bp.removeBreakpoint();
|
|
|
|
|
} else {
|
|
|
|
|
BreakpointParameters data;
|
|
|
|
|
if (location.type == LocationByFile) {
|
|
|
|
|
data.type = BreakpointByFileAndLine;
|
|
|
|
|
if (boolSetting(BreakpointsFullPathByDefault))
|
|
|
|
|
data.pathUsage = BreakpointUseFullPath;
|
|
|
|
|
data.tracepoint = !tracePointMessage.isEmpty();
|
|
|
|
|
data.message = tracePointMessage;
|
|
|
|
|
data.fileName = location.fileName;
|
|
|
|
|
data.lineNumber = location.lineNumber;
|
|
|
|
|
} else if (location.type == LocationByAddress) {
|
|
|
|
|
data.type = BreakpointByAddress;
|
|
|
|
|
data.tracepoint = !tracePointMessage.isEmpty();
|
|
|
|
|
data.message = tracePointMessage;
|
|
|
|
|
data.address = location.address;
|
|
|
|
|
}
|
|
|
|
|
handler->appendBreakpoint(data);
|
|
|
|
|
}
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void DebuggerPluginPrivate::toggleBreakpointHelper()
|
|
|
|
|
{
|
|
|
|
|
BaseTextEditor *textEditor = BaseTextEditor::currentTextEditor();
|
|
|
|
|
QTC_ASSERT(textEditor, return);
|
|
|
|
|
const int lineNumber = textEditor->currentLine();
|
|
|
|
|
ContextData location = getLocationContext(textEditor->textDocument(), lineNumber);
|
|
|
|
|
if (location.isValid())
|
|
|
|
|
toggleBreakpoint(location);
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void DebuggerPluginPrivate::requestMark(TextEditorWidget *widget, int lineNumber,
|
|
|
|
|
TextMarkRequestKind kind)
|
|
|
|
|
{
|
|
|
|
|
if (kind == BreakpointRequest) {
|
|
|
|
|
ContextData location = getLocationContext(widget->textDocument(), lineNumber);
|
|
|
|
|
if (location.isValid())
|
|
|
|
|
toggleBreakpoint(location);
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-12-02 18:19:05 +01:00
|
|
|
|
2016-03-02 13:57:37 +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();
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void DebuggerPluginPrivate::connectEngine(DebuggerEngine *engine)
|
|
|
|
|
{
|
|
|
|
|
if (!engine)
|
|
|
|
|
engine = dummyEngine();
|
2009-05-25 16:22:11 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
if (m_currentEngine == engine)
|
|
|
|
|
return;
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2016-04-20 15:09:57 +02:00
|
|
|
if (m_shuttingDown)
|
|
|
|
|
return;
|
|
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
if (m_currentEngine)
|
|
|
|
|
m_currentEngine->resetLocation();
|
|
|
|
|
m_currentEngine = engine;
|
2010-03-29 18:44:02 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
m_localsView->setModel(engine->watchModel());
|
|
|
|
|
m_modulesView->setModel(engine->modulesModel());
|
|
|
|
|
m_registerView->setModel(engine->registerModel());
|
|
|
|
|
m_returnView->setModel(engine->watchModel());
|
|
|
|
|
m_sourceFilesView->setModel(engine->sourceFilesModel());
|
|
|
|
|
m_stackView->setModel(engine->stackModel());
|
|
|
|
|
m_threadsView->setModel(engine->threadsModel());
|
|
|
|
|
m_watchersView->setModel(engine->watchModel());
|
|
|
|
|
m_inspectorView->setModel(engine->watchModel());
|
2012-04-18 14:20:54 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
engine->watchHandler()->resetWatchers();
|
|
|
|
|
m_localsView->hideProgressIndicator();
|
2016-04-17 23:44:13 +03:00
|
|
|
updateActiveLanguages();
|
2016-03-02 13:57:37 +01:00
|
|
|
}
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
static void changeFontSize(QWidget *widget, qreal size)
|
|
|
|
|
{
|
|
|
|
|
QFont font = widget->font();
|
|
|
|
|
font.setPointSizeF(size);
|
|
|
|
|
widget->setFont(font);
|
|
|
|
|
}
|
2012-01-12 17:04:14 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void DebuggerPluginPrivate::fontSettingsChanged(const FontSettings &settings)
|
|
|
|
|
{
|
|
|
|
|
if (!boolSetting(FontSizeFollowsEditor))
|
|
|
|
|
return;
|
|
|
|
|
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);
|
|
|
|
|
changeFontSize(m_inspectorWindow, size);
|
|
|
|
|
}
|
2010-08-18 13:54:12 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void DebuggerPluginPrivate::cleanupViews()
|
|
|
|
|
{
|
|
|
|
|
m_reverseDirectionAction->setChecked(false);
|
|
|
|
|
m_reverseDirectionAction->setEnabled(false);
|
2010-07-05 17:08:30 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
const bool closeSource = boolSetting(CloseSourceBuffersOnExit);
|
|
|
|
|
const bool closeMemory = boolSetting(CloseMemoryBuffersOnExit);
|
2011-10-25 18:23:37 +08:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
QList<IDocument *> toClose;
|
|
|
|
|
foreach (IDocument *document, DocumentModel::openedDocuments()) {
|
|
|
|
|
const bool isMemory = document->property(Constants::OPENED_WITH_DISASSEMBLY).toBool();
|
|
|
|
|
if (document->property(Constants::OPENED_BY_DEBUGGER).toBool()) {
|
|
|
|
|
bool keepIt = true;
|
|
|
|
|
if (document->isModified())
|
|
|
|
|
keepIt = true;
|
|
|
|
|
else if (isMemory)
|
|
|
|
|
keepIt = !closeMemory;
|
|
|
|
|
else
|
|
|
|
|
keepIt = !closeSource;
|
2010-07-05 17:08:30 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
if (keepIt)
|
|
|
|
|
document->setProperty(Constants::OPENED_BY_DEBUGGER, false);
|
|
|
|
|
else
|
|
|
|
|
toClose.append(document);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
EditorManager::closeDocuments(toClose);
|
|
|
|
|
}
|
2011-12-05 17:21:48 +01:00
|
|
|
|
2016-03-02 13:57:37 +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);
|
|
|
|
|
}
|
2011-12-06 15:39:25 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void DebuggerPluginPrivate::setInitialState()
|
|
|
|
|
{
|
|
|
|
|
m_watchersWindow->setVisible(false);
|
|
|
|
|
m_returnWindow->setVisible(false);
|
|
|
|
|
setBusyCursor(false);
|
|
|
|
|
m_reverseDirectionAction->setChecked(false);
|
|
|
|
|
m_reverseDirectionAction->setEnabled(false);
|
|
|
|
|
m_toolTipManager.closeAllToolTips();
|
2011-09-14 15:22:08 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
m_startAndDebugApplicationAction->setEnabled(true);
|
|
|
|
|
m_attachToQmlPortAction->setEnabled(true);
|
|
|
|
|
m_attachToCoreAction->setEnabled(true);
|
|
|
|
|
m_attachToRemoteServerAction->setEnabled(true);
|
|
|
|
|
m_attachToRunningApplication->setEnabled(true);
|
|
|
|
|
m_attachToUnstartedApplication->setEnabled(true);
|
|
|
|
|
m_detachAction->setEnabled(false);
|
2013-09-20 16:48:01 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
m_watchAction1->setEnabled(true);
|
|
|
|
|
m_watchAction2->setEnabled(true);
|
|
|
|
|
m_breakAction->setEnabled(false);
|
|
|
|
|
//m_snapshotAction->setEnabled(false);
|
|
|
|
|
m_operateByInstructionAction->setEnabled(false);
|
2011-09-13 17:26:02 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
m_exitAction->setEnabled(false);
|
|
|
|
|
m_abortAction->setEnabled(false);
|
|
|
|
|
m_resetAction->setEnabled(false);
|
2010-07-05 17:08:30 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
m_interruptAction->setEnabled(false);
|
|
|
|
|
m_continueAction->setEnabled(false);
|
2010-11-23 13:28:18 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
m_stepAction->setEnabled(true);
|
|
|
|
|
m_stepOutAction->setEnabled(false);
|
|
|
|
|
m_runToLineAction->setEnabled(false);
|
|
|
|
|
m_runToSelectedFunctionAction->setEnabled(true);
|
|
|
|
|
m_returnFromFunctionAction->setEnabled(false);
|
|
|
|
|
m_jumpToLineAction->setEnabled(false);
|
|
|
|
|
m_nextAction->setEnabled(true);
|
2011-10-10 13:38:58 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
action(AutoDerefPointers)->setEnabled(true);
|
|
|
|
|
action(ExpandStack)->setEnabled(false);
|
2016-04-16 20:59:42 +02:00
|
|
|
|
|
|
|
|
m_threadLabel->setEnabled(false);
|
2016-03-02 13:57:37 +01:00
|
|
|
}
|
2010-08-24 16:22:21 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void DebuggerPluginPrivate::updateState(DebuggerEngine *engine)
|
|
|
|
|
{
|
2016-04-04 09:15:28 +02:00
|
|
|
if (m_shuttingDown)
|
|
|
|
|
return;
|
2016-03-02 13:57:37 +01:00
|
|
|
QTC_ASSERT(engine, return);
|
|
|
|
|
QTC_ASSERT(m_watchersView->model(), return);
|
|
|
|
|
QTC_ASSERT(m_returnView->model(), return);
|
|
|
|
|
QTC_ASSERT(!engine->isSlaveEngine(), return);
|
2011-02-03 14:17:23 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
m_threadBox->setCurrentIndex(engine->threadsHandler()->currentThreadIndex());
|
2010-10-28 08:55:50 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
const DebuggerState state = engine->state();
|
|
|
|
|
//showMessage(QString::fromLatin1("PLUGIN SET STATE: ")
|
|
|
|
|
// + DebuggerEngine::stateName(state), LogStatus);
|
|
|
|
|
//qDebug() << "PLUGIN SET STATE: " << state;
|
2011-10-25 18:23:37 +08:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
static DebuggerState previousState = DebuggerNotReady;
|
|
|
|
|
if (state == previousState)
|
|
|
|
|
return;
|
2011-10-19 11:51:51 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
bool actionsEnabled = DebuggerEngine::debuggerActionsEnabled(state);
|
2013-09-20 16:48:01 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
if (state == DebuggerNotReady) {
|
|
|
|
|
QTC_ASSERT(false, /* We use the Core's m_debugAction here */);
|
|
|
|
|
// F5 starts debugging. It is "startable".
|
|
|
|
|
m_interruptAction->setEnabled(false);
|
|
|
|
|
m_continueAction->setEnabled(false);
|
|
|
|
|
m_exitAction->setEnabled(false);
|
|
|
|
|
m_startAction->setEnabled(true);
|
|
|
|
|
m_debugWithoutDeployAction->setEnabled(true);
|
|
|
|
|
setProxyAction(m_visibleStartAction, Id(Constants::DEBUG));
|
|
|
|
|
m_hiddenStopAction->setAction(m_undisturbableAction);
|
|
|
|
|
} else if (state == InferiorStopOk) {
|
|
|
|
|
// F5 continues, Shift-F5 kills. It is "continuable".
|
|
|
|
|
m_interruptAction->setEnabled(false);
|
|
|
|
|
m_continueAction->setEnabled(true);
|
|
|
|
|
m_exitAction->setEnabled(true);
|
|
|
|
|
m_startAction->setEnabled(false);
|
|
|
|
|
m_debugWithoutDeployAction->setEnabled(false);
|
|
|
|
|
setProxyAction(m_visibleStartAction, Id(Constants::CONTINUE));
|
|
|
|
|
m_hiddenStopAction->setAction(m_exitAction);
|
|
|
|
|
m_localsAndExpressionsWindow->setShowLocals(true);
|
|
|
|
|
} else if (state == InferiorRunOk) {
|
|
|
|
|
// Shift-F5 interrupts. It is also "interruptible".
|
|
|
|
|
m_interruptAction->setEnabled(true);
|
|
|
|
|
m_continueAction->setEnabled(false);
|
|
|
|
|
m_exitAction->setEnabled(true);
|
|
|
|
|
m_startAction->setEnabled(false);
|
|
|
|
|
m_debugWithoutDeployAction->setEnabled(false);
|
|
|
|
|
setProxyAction(m_visibleStartAction, Id(Constants::INTERRUPT));
|
|
|
|
|
m_hiddenStopAction->setAction(m_interruptAction);
|
|
|
|
|
m_localsAndExpressionsWindow->setShowLocals(false);
|
|
|
|
|
} else if (state == DebuggerFinished) {
|
2016-03-10 11:11:19 +01:00
|
|
|
const bool canRun = ProjectExplorerPlugin::canRunStartupProject(ProjectExplorer::Constants::DEBUG_RUN_MODE);
|
2016-03-02 13:57:37 +01:00
|
|
|
// We don't want to do anything anymore.
|
|
|
|
|
m_interruptAction->setEnabled(false);
|
|
|
|
|
m_continueAction->setEnabled(false);
|
|
|
|
|
m_exitAction->setEnabled(false);
|
|
|
|
|
m_startAction->setEnabled(canRun);
|
|
|
|
|
m_debugWithoutDeployAction->setEnabled(canRun);
|
|
|
|
|
setProxyAction(m_visibleStartAction, Id(Constants::DEBUG));
|
|
|
|
|
m_hiddenStopAction->setAction(m_undisturbableAction);
|
|
|
|
|
m_codeModelSnapshot = CPlusPlus::Snapshot();
|
|
|
|
|
setBusyCursor(false);
|
|
|
|
|
cleanupViews();
|
|
|
|
|
} else if (state == InferiorUnrunnable) {
|
|
|
|
|
// We don't want to do anything anymore.
|
|
|
|
|
m_interruptAction->setEnabled(false);
|
|
|
|
|
m_continueAction->setEnabled(false);
|
|
|
|
|
m_exitAction->setEnabled(true);
|
|
|
|
|
m_startAction->setEnabled(false);
|
|
|
|
|
m_debugWithoutDeployAction->setEnabled(false);
|
|
|
|
|
m_visibleStartAction->setAction(m_undisturbableAction);
|
|
|
|
|
m_hiddenStopAction->setAction(m_exitAction);
|
|
|
|
|
// show locals in core dumps
|
|
|
|
|
m_localsAndExpressionsWindow->setShowLocals(true);
|
|
|
|
|
} else {
|
|
|
|
|
// Everything else is "undisturbable".
|
|
|
|
|
m_interruptAction->setEnabled(false);
|
|
|
|
|
m_continueAction->setEnabled(false);
|
|
|
|
|
m_exitAction->setEnabled(false);
|
|
|
|
|
m_startAction->setEnabled(false);
|
|
|
|
|
m_debugWithoutDeployAction->setEnabled(false);
|
|
|
|
|
m_visibleStartAction->setAction(m_undisturbableAction);
|
|
|
|
|
m_hiddenStopAction->setAction(m_undisturbableAction);
|
|
|
|
|
}
|
2012-01-07 17:18:52 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
m_startAndDebugApplicationAction->setEnabled(true);
|
|
|
|
|
m_attachToQmlPortAction->setEnabled(true);
|
|
|
|
|
m_attachToCoreAction->setEnabled(true);
|
|
|
|
|
m_attachToRemoteServerAction->setEnabled(true);
|
|
|
|
|
m_attachToRunningApplication->setEnabled(true);
|
|
|
|
|
m_attachToUnstartedApplication->setEnabled(true);
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
m_threadBox->setEnabled(state == InferiorStopOk || state == InferiorUnrunnable);
|
2016-04-16 20:59:42 +02:00
|
|
|
m_threadLabel->setEnabled(m_threadBox->isEnabled());
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
const bool isCore = engine->runParameters().startMode == AttachCore;
|
|
|
|
|
const bool stopped = state == InferiorStopOk;
|
|
|
|
|
const bool detachable = stopped && !isCore;
|
|
|
|
|
m_detachAction->setEnabled(detachable);
|
2011-12-06 15:39:25 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
if (stopped)
|
|
|
|
|
QApplication::alert(mainWindow(), 3000);
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
const bool canReverse = engine->hasCapability(ReverseSteppingCapability)
|
|
|
|
|
&& boolSetting(EnableReverseDebugging);
|
|
|
|
|
m_reverseDirectionAction->setEnabled(canReverse);
|
2011-10-10 13:38:58 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
m_watchAction1->setEnabled(true);
|
|
|
|
|
m_watchAction2->setEnabled(true);
|
|
|
|
|
m_breakAction->setEnabled(true);
|
2011-09-22 11:18:14 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
const bool canOperateByInstruction = engine->hasCapability(OperateByInstructionCapability)
|
|
|
|
|
&& (stopped || isCore);
|
|
|
|
|
m_operateByInstructionAction->setEnabled(canOperateByInstruction);
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
m_abortAction->setEnabled(state != DebuggerNotReady
|
|
|
|
|
&& state != DebuggerFinished);
|
|
|
|
|
m_resetAction->setEnabled((stopped || state == DebuggerNotReady)
|
|
|
|
|
&& engine->hasCapability(ResetInferiorCapability));
|
2011-01-12 16:36:29 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
m_stepAction->setEnabled(stopped || state == DebuggerNotReady);
|
|
|
|
|
m_nextAction->setEnabled(stopped || state == DebuggerNotReady);
|
|
|
|
|
m_stepAction->setToolTip(QString());
|
|
|
|
|
m_nextAction->setToolTip(QString());
|
2010-09-24 16:55:22 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
m_stepOutAction->setEnabled(stopped);
|
|
|
|
|
m_runToLineAction->setEnabled(stopped && engine->hasCapability(RunToLineCapability));
|
|
|
|
|
m_runToSelectedFunctionAction->setEnabled(stopped);
|
|
|
|
|
m_returnFromFunctionAction->
|
|
|
|
|
setEnabled(stopped && engine->hasCapability(ReturnFromFunctionCapability));
|
2010-11-12 20:18:29 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
const bool canJump = stopped && engine->hasCapability(JumpToLineCapability);
|
|
|
|
|
m_jumpToLineAction->setEnabled(canJump);
|
2010-11-23 16:42:46 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
const bool canDeref = actionsEnabled && engine->hasCapability(AutoDerefPointersCapability);
|
|
|
|
|
action(AutoDerefPointers)->setEnabled(canDeref);
|
|
|
|
|
action(AutoDerefPointers)->setEnabled(true);
|
|
|
|
|
action(ExpandStack)->setEnabled(actionsEnabled);
|
2009-05-25 18:21:31 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
const bool notbusy = state == InferiorStopOk
|
|
|
|
|
|| state == DebuggerNotReady
|
|
|
|
|
|| state == DebuggerFinished
|
|
|
|
|
|| state == InferiorUnrunnable;
|
|
|
|
|
setBusyCursor(!notbusy);
|
|
|
|
|
}
|
2009-01-13 18:15:24 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void DebuggerPluginPrivate::updateDebugActions()
|
|
|
|
|
{
|
2016-04-04 09:15:28 +02:00
|
|
|
if (m_shuttingDown)
|
|
|
|
|
return;
|
2016-03-02 13:57:37 +01:00
|
|
|
//if we're currently debugging the actions are controlled by engine
|
2016-04-26 16:19:17 +02:00
|
|
|
if (m_currentEngine && m_currentEngine->state() != DebuggerNotReady)
|
2016-03-02 13:57:37 +01:00
|
|
|
return;
|
2009-02-27 11:41:19 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
QString whyNot;
|
2016-03-10 11:11:19 +01:00
|
|
|
const bool canRun = ProjectExplorerPlugin::canRunStartupProject(ProjectExplorer::Constants::DEBUG_RUN_MODE, &whyNot);
|
2016-03-02 13:57:37 +01:00
|
|
|
m_startAction->setEnabled(canRun);
|
|
|
|
|
m_startAction->setToolTip(whyNot);
|
|
|
|
|
m_debugWithoutDeployAction->setEnabled(canRun);
|
2009-06-16 13:44:45 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
// Step into/next: Start and break at 'main' unless a debugger is running.
|
|
|
|
|
if (m_snapshotHandler->currentIndex() < 0) {
|
|
|
|
|
QString toolTip;
|
|
|
|
|
const bool canRunAndBreakMain
|
2016-03-10 11:11:19 +01:00
|
|
|
= ProjectExplorerPlugin::canRunStartupProject(ProjectExplorer::Constants::DEBUG_RUN_MODE_WITH_BREAK_ON_MAIN, &toolTip);
|
2016-03-02 13:57:37 +01:00
|
|
|
m_stepAction->setEnabled(canRunAndBreakMain);
|
|
|
|
|
m_nextAction->setEnabled(canRunAndBreakMain);
|
|
|
|
|
if (canRunAndBreakMain) {
|
2016-03-10 11:11:19 +01:00
|
|
|
Project *project = SessionManager::startupProject();
|
|
|
|
|
QTC_ASSERT(project, return);
|
2016-03-02 13:57:37 +01:00
|
|
|
toolTip = tr("Start \"%1\" and break at function \"main()\"")
|
|
|
|
|
.arg(project->displayName());
|
|
|
|
|
}
|
|
|
|
|
m_stepAction->setToolTip(toolTip);
|
|
|
|
|
m_nextAction->setToolTip(toolTip);
|
2015-06-10 14:19:42 +02:00
|
|
|
}
|
2016-03-02 13:57:37 +01:00
|
|
|
}
|
2009-05-05 17:48:54 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void DebuggerPluginPrivate::updateDebugWithoutDeployMenu()
|
|
|
|
|
{
|
|
|
|
|
const bool state = ProjectExplorerPlugin::projectExplorerSettings().deployBeforeRun;
|
|
|
|
|
m_debugWithoutDeployAction->setVisible(state);
|
|
|
|
|
}
|
2009-05-05 17:48:54 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void DebuggerPluginPrivate::dumpLog()
|
|
|
|
|
{
|
|
|
|
|
QString fileName = QFileDialog::getSaveFileName(ICore::mainWindow(),
|
|
|
|
|
tr("Save Debugger Log"), QDir::tempPath());
|
|
|
|
|
if (fileName.isEmpty())
|
|
|
|
|
return;
|
|
|
|
|
FileSaver saver(fileName);
|
|
|
|
|
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(ICore::mainWindow());
|
|
|
|
|
}
|
2009-09-30 12:27:03 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
/*! Activates the previous mode when the current mode is the debug mode. */
|
|
|
|
|
void DebuggerPluginPrivate::activatePreviousMode()
|
|
|
|
|
{
|
2016-03-25 20:00:19 +01:00
|
|
|
if (ModeManager::currentMode() == MODE_DEBUG && m_previousMode.isValid()) {
|
2016-03-02 13:57:37 +01:00
|
|
|
// If stopping the application also makes Qt Creator active (as the
|
|
|
|
|
// "previously active application"), doing the switch synchronously
|
|
|
|
|
// leads to funny effects with floating dock widgets
|
|
|
|
|
const Core::Id mode = m_previousMode;
|
|
|
|
|
QTimer::singleShot(0, this, [mode]() { ModeManager::activateMode(mode); });
|
|
|
|
|
m_previousMode = Id();
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-05-05 17:48:54 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void DebuggerPluginPrivate::activateDebugMode()
|
|
|
|
|
{
|
|
|
|
|
m_reverseDirectionAction->setChecked(false);
|
|
|
|
|
m_reverseDirectionAction->setEnabled(false);
|
|
|
|
|
ModeManager::activateMode(MODE_DEBUG);
|
|
|
|
|
}
|
2010-08-26 16:02:41 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void DebuggerPluginPrivate::sessionLoaded()
|
|
|
|
|
{
|
|
|
|
|
m_breakHandler->loadSessionData();
|
|
|
|
|
dummyEngine()->watchHandler()->loadSessionData();
|
|
|
|
|
DebuggerToolTipManager::loadSessionData();
|
|
|
|
|
}
|
2010-08-26 16:02:41 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void DebuggerPluginPrivate::aboutToUnloadSession()
|
|
|
|
|
{
|
|
|
|
|
m_toolTipManager.sessionAboutToChange();
|
|
|
|
|
}
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void DebuggerPluginPrivate::aboutToSaveSession()
|
|
|
|
|
{
|
|
|
|
|
dummyEngine()->watchHandler()->saveSessionData();
|
|
|
|
|
m_breakHandler->saveSessionData();
|
|
|
|
|
DebuggerToolTipManager::saveSessionData();
|
|
|
|
|
}
|
2012-11-27 15:33:20 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void DebuggerPluginPrivate::showStatusMessage(const QString &msg0, int timeout)
|
|
|
|
|
{
|
2016-04-20 15:09:57 +02:00
|
|
|
if (m_shuttingDown)
|
|
|
|
|
return;
|
2016-03-02 13:57:37 +01:00
|
|
|
showMessage(msg0, LogStatus);
|
|
|
|
|
QString msg = msg0;
|
|
|
|
|
msg.replace(QChar::LineFeed, QLatin1String("; "));
|
|
|
|
|
m_mainWindow->showStatusMessage(msg, timeout);
|
|
|
|
|
}
|
2012-11-27 15:33:20 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void DebuggerPluginPrivate::coreShutdown()
|
|
|
|
|
{
|
|
|
|
|
m_shuttingDown = true;
|
2016-04-20 15:09:57 +02:00
|
|
|
if (currentEngine()) {
|
2016-04-20 18:15:21 +02:00
|
|
|
if (currentEngine()->state() != Debugger::DebuggerNotReady) {
|
|
|
|
|
currentEngine()->setTargetState(Debugger::DebuggerFinished);
|
|
|
|
|
currentEngine()->abortDebugger();
|
|
|
|
|
}
|
2016-04-20 15:09:57 +02:00
|
|
|
}
|
2016-03-02 13:57:37 +01:00
|
|
|
}
|
2012-11-27 15:33:20 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
const CPlusPlus::Snapshot &cppCodeModelSnapshot()
|
|
|
|
|
{
|
|
|
|
|
if (dd->m_codeModelSnapshot.isEmpty() && action(UseCodeModel)->isChecked())
|
|
|
|
|
dd->m_codeModelSnapshot = CppTools::CppModelManager::instance()->snapshot();
|
|
|
|
|
return dd->m_codeModelSnapshot;
|
|
|
|
|
}
|
2012-11-27 15:33:20 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void setSessionValue(const QByteArray &key, const QVariant &value)
|
|
|
|
|
{
|
|
|
|
|
SessionManager::setValue(QString::fromUtf8(key), value);
|
|
|
|
|
}
|
2012-11-27 15:33:20 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
QVariant sessionValue(const QByteArray &key)
|
|
|
|
|
{
|
|
|
|
|
return SessionManager::value(QString::fromUtf8(key));
|
|
|
|
|
}
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2016-04-19 22:49:23 +02:00
|
|
|
WatchTreeView *inspectorView()
|
2016-03-02 13:57:37 +01:00
|
|
|
{
|
|
|
|
|
return dd->m_inspectorView;
|
|
|
|
|
}
|
2010-11-10 12:38:29 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void DebuggerPluginPrivate::showMessage(const QString &msg, int channel, int timeout)
|
|
|
|
|
{
|
2016-04-04 09:15:28 +02:00
|
|
|
if (m_shuttingDown)
|
|
|
|
|
return;
|
2016-03-02 13:57:37 +01:00
|
|
|
//qDebug() << "PLUGIN OUTPUT: " << channel << msg;
|
|
|
|
|
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;
|
|
|
|
|
case LogError:
|
|
|
|
|
m_logWindow->showInput(LogError, QLatin1String("ERROR: ") + msg);
|
|
|
|
|
m_logWindow->showOutput(LogError, QLatin1String("ERROR: ") + msg);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
m_logWindow->showOutput(channel, msg);
|
|
|
|
|
break;
|
2011-01-06 14:57:21 +01:00
|
|
|
}
|
2016-03-02 13:57:37 +01:00
|
|
|
}
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
static void createNewDock(QWidget *widget)
|
|
|
|
|
{
|
|
|
|
|
// m_mainWindow->registerDockWidget(dockId, widget);
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
// QDockWidget *dockWidget = qobject_cast<QDockWidget *>(widget->parentWidget());
|
|
|
|
|
// //dockWidget->installEventFilter(&m_resizeEventFilter);
|
2010-11-10 11:39:01 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
// QAction *toggleViewAction = dockWidget->toggleViewAction();
|
|
|
|
|
// Command *cmd = ActionManager::registerAction(toggleViewAction,
|
|
|
|
|
// Id("Debugger.").withSuffix(widget->objectName()));
|
|
|
|
|
// cmd->setAttribute(Command::CA_Hide);
|
|
|
|
|
// dd->createDockWidget(Core::Id::fromString(widget->objectName()), widget);
|
|
|
|
|
// QDockWidget *dockWidget = qobject_cast<QDockWidget *>(widget->parentWidget());
|
|
|
|
|
// QDockWidget *dockWidget = Debugger::registerDockWidget(Id::fromString(widget->objectName()), widget);
|
|
|
|
|
QDockWidget *dockWidget = new QDockWidget;
|
|
|
|
|
dockWidget->setWidget(widget);
|
2010-11-10 11:39:01 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
dockWidget->setWindowTitle(widget->windowTitle());
|
|
|
|
|
dockWidget->setFeatures(QDockWidget::DockWidgetClosable);
|
|
|
|
|
dockWidget->show();
|
|
|
|
|
}
|
2010-11-10 11:39:01 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
static QString formatStartParameters(DebuggerRunParameters &sp)
|
|
|
|
|
{
|
|
|
|
|
QString rc;
|
|
|
|
|
QTextStream str(&rc);
|
|
|
|
|
str << "Start parameters: '" << sp.displayName << "' mode: " << sp.startMode
|
|
|
|
|
<< "\nABI: " << sp.toolChainAbi.toString() << '\n';
|
|
|
|
|
str << "Languages: ";
|
|
|
|
|
if (sp.languages == AnyLanguage)
|
2016-03-03 17:14:27 +02:00
|
|
|
str << "any ";
|
2016-03-02 13:57:37 +01:00
|
|
|
if (sp.languages & CppLanguage)
|
|
|
|
|
str << "c++ ";
|
|
|
|
|
if (sp.languages & QmlLanguage)
|
|
|
|
|
str << "qml";
|
|
|
|
|
str << '\n';
|
|
|
|
|
if (!sp.inferior.executable.isEmpty()) {
|
|
|
|
|
str << "Executable: " << QDir::toNativeSeparators(sp.inferior.executable)
|
|
|
|
|
<< ' ' << sp.inferior.commandLineArguments;
|
|
|
|
|
if (sp.useTerminal)
|
|
|
|
|
str << " [terminal]";
|
|
|
|
|
str << '\n';
|
|
|
|
|
if (!sp.inferior.workingDirectory.isEmpty())
|
|
|
|
|
str << "Directory: " << QDir::toNativeSeparators(sp.inferior.workingDirectory)
|
|
|
|
|
<< '\n';
|
|
|
|
|
}
|
2016-07-29 15:55:15 +02:00
|
|
|
QString cmd = sp.debugger.executable;
|
2016-03-02 13:57:37 +01:00
|
|
|
if (!cmd.isEmpty())
|
|
|
|
|
str << "Debugger: " << QDir::toNativeSeparators(cmd) << '\n';
|
|
|
|
|
if (!sp.coreFile.isEmpty())
|
|
|
|
|
str << "Core: " << QDir::toNativeSeparators(sp.coreFile) << '\n';
|
|
|
|
|
if (sp.attachPID > 0)
|
|
|
|
|
str << "PID: " << sp.attachPID << ' ' << sp.crashParameter << '\n';
|
|
|
|
|
if (!sp.projectSourceDirectory.isEmpty()) {
|
|
|
|
|
str << "Project: " << QDir::toNativeSeparators(sp.projectSourceDirectory);
|
|
|
|
|
str << "Addtional Search Directories:"
|
|
|
|
|
<< sp.additionalSearchDirectories.join(QLatin1Char(' ')) << '\n';
|
|
|
|
|
}
|
|
|
|
|
if (!sp.remoteChannel.isEmpty())
|
|
|
|
|
str << "Remote: " << sp.remoteChannel << '\n';
|
2016-06-13 14:18:50 +02:00
|
|
|
if (!sp.qmlServer.host.isEmpty())
|
|
|
|
|
str << "QML server: " << sp.qmlServer.host << ':'
|
|
|
|
|
<< (sp.qmlServer.port.isValid() ? sp.qmlServer.port.number() : -1) << '\n';
|
2016-03-02 13:57:37 +01:00
|
|
|
str << "Sysroot: " << sp.sysRoot << '\n';
|
|
|
|
|
str << "Debug Source Location: " << sp.debugSourceLocation.join(QLatin1Char(':')) << '\n';
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
2010-11-10 11:39:01 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void DebuggerPluginPrivate::runControlStarted(DebuggerEngine *engine)
|
|
|
|
|
{
|
|
|
|
|
activateDebugMode();
|
|
|
|
|
const QString message = tr("Starting debugger \"%1\" for ABI \"%2\"...")
|
|
|
|
|
.arg(engine->objectName())
|
|
|
|
|
.arg(engine->runParameters().toolChainAbi.toString());
|
|
|
|
|
showStatusMessage(message);
|
|
|
|
|
showMessage(formatStartParameters(engine->runParameters()), LogDebug);
|
|
|
|
|
showMessage(m_debuggerSettings->dump(), LogDebug);
|
|
|
|
|
m_snapshotHandler->appendSnapshot(engine);
|
|
|
|
|
connectEngine(engine);
|
|
|
|
|
}
|
2010-11-10 11:39:01 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void DebuggerPluginPrivate::runControlFinished(DebuggerEngine *engine)
|
|
|
|
|
{
|
2016-04-20 15:09:57 +02:00
|
|
|
if (m_shuttingDown)
|
|
|
|
|
return;
|
2016-03-02 13:57:37 +01:00
|
|
|
showStatusMessage(tr("Debugger finished."));
|
|
|
|
|
m_snapshotHandler->removeSnapshot(engine);
|
|
|
|
|
if (m_snapshotHandler->size() == 0) {
|
|
|
|
|
// Last engine quits.
|
|
|
|
|
disconnectEngine();
|
|
|
|
|
if (boolSetting(SwitchModeOnExit))
|
|
|
|
|
activatePreviousMode();
|
|
|
|
|
} else {
|
|
|
|
|
// Connect to some existing engine.
|
|
|
|
|
m_snapshotHandler->activateSnapshot(0);
|
2015-06-10 14:19:42 +02:00
|
|
|
}
|
2016-03-02 13:57:37 +01:00
|
|
|
m_operateByInstructionAction->setChecked(false);
|
|
|
|
|
m_logWindow->clearUndoRedoStacks();
|
|
|
|
|
}
|
2010-11-10 11:39:01 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void DebuggerPluginPrivate::remoteCommand(const QStringList &options)
|
|
|
|
|
{
|
|
|
|
|
if (options.isEmpty())
|
|
|
|
|
return;
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
QString errorMessage;
|
2010-11-10 16:33:11 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
if (!parseArguments(options, &errorMessage)) {
|
|
|
|
|
qWarning("%s", qPrintable(errorMessage));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
runScheduled();
|
|
|
|
|
}
|
2010-11-10 11:39:01 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
QMessageBox *showMessageBox(int icon, const QString &title,
|
|
|
|
|
const QString &text, int buttons)
|
|
|
|
|
{
|
|
|
|
|
QMessageBox *mb = new QMessageBox(QMessageBox::Icon(icon),
|
|
|
|
|
title, text, QMessageBox::StandardButtons(buttons),
|
|
|
|
|
ICore::mainWindow());
|
|
|
|
|
mb->setAttribute(Qt::WA_DeleteOnClose);
|
|
|
|
|
mb->setTextInteractionFlags(Qt::TextSelectableByMouse);
|
|
|
|
|
mb->show();
|
|
|
|
|
return mb;
|
|
|
|
|
}
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
bool isReverseDebuggingEnabled()
|
|
|
|
|
{
|
|
|
|
|
static bool enabled = qEnvironmentVariableIsSet("QTC_DEBUGGER_ENABLE_REVERSE");
|
|
|
|
|
return enabled;
|
|
|
|
|
}
|
2011-12-06 15:39:25 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
bool isReverseDebugging()
|
|
|
|
|
{
|
|
|
|
|
return isReverseDebuggingEnabled() && dd->m_reverseDirectionAction->isChecked();
|
|
|
|
|
}
|
2010-06-29 18:12:22 +02:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void DebuggerPluginPrivate::extensionsInitialized()
|
|
|
|
|
{
|
2010-06-16 11:08:54 +02:00
|
|
|
}
|
2010-05-05 12:41:52 +02:00
|
|
|
|
2014-07-28 14:23:52 +02:00
|
|
|
DebuggerEngine *currentEngine()
|
|
|
|
|
{
|
2014-10-22 13:04:47 +02:00
|
|
|
return dd->m_currentEngine;
|
2014-07-28 14:23:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SavedAction *action(int code)
|
2010-11-10 16:33:11 +01:00
|
|
|
{
|
2014-10-22 13:04:47 +02:00
|
|
|
return dd->m_debuggerSettings->item(code);
|
2010-11-10 16:33:11 +01:00
|
|
|
}
|
|
|
|
|
|
2014-07-28 14:23:52 +02:00
|
|
|
bool boolSetting(int code)
|
2010-11-10 16:33:11 +01:00
|
|
|
{
|
2014-10-22 13:04:47 +02:00
|
|
|
return dd->m_debuggerSettings->item(code)->value().toBool();
|
2010-11-10 16:33:11 +01:00
|
|
|
}
|
|
|
|
|
|
2014-07-28 14:23:52 +02:00
|
|
|
QString stringSetting(int code)
|
2010-11-10 16:33:11 +01:00
|
|
|
{
|
2016-03-22 10:47:03 +01:00
|
|
|
return dd->m_debuggerSettings->item(code)->value().toString();
|
2010-11-10 16:33:11 +01:00
|
|
|
}
|
|
|
|
|
|
2014-07-28 14:23:52 +02:00
|
|
|
QStringList stringListSetting(int code)
|
|
|
|
|
{
|
2014-10-22 13:04:47 +02:00
|
|
|
return dd->m_debuggerSettings->item(code)->value().toStringList();
|
2014-07-28 14:23:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BreakHandler *breakHandler()
|
2013-05-27 10:20:20 +02:00
|
|
|
{
|
2014-10-22 13:04:47 +02:00
|
|
|
return dd->m_breakHandler;
|
2013-05-27 10:20:20 +02:00
|
|
|
}
|
|
|
|
|
|
2014-10-22 13:04:47 +02:00
|
|
|
void showModuleSymbols(const QString &moduleName, const Symbols &symbols)
|
2010-11-26 09:58:34 +01:00
|
|
|
{
|
|
|
|
|
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;
|
2014-10-22 13:04:47 +02:00
|
|
|
header.append(DebuggerPlugin::tr("Symbol"));
|
|
|
|
|
header.append(DebuggerPlugin::tr("Address"));
|
|
|
|
|
header.append(DebuggerPlugin::tr("Code"));
|
|
|
|
|
header.append(DebuggerPlugin::tr("Section"));
|
|
|
|
|
header.append(DebuggerPlugin::tr("Name"));
|
2010-11-26 09:58:34 +01:00
|
|
|
w->setHeaderLabels(header);
|
2014-10-22 13:04:47 +02:00
|
|
|
w->setWindowTitle(DebuggerPlugin::tr("Symbols in \"%1\"").arg(moduleName));
|
2010-11-26 09:58:34 +01:00
|
|
|
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
|
|
|
}
|
|
|
|
|
|
2014-10-22 13:04:47 +02:00
|
|
|
void showModuleSections(const QString &moduleName, const Sections §ions)
|
2012-11-07 18:31:17 +01:00
|
|
|
{
|
|
|
|
|
QTreeWidget *w = new QTreeWidget;
|
|
|
|
|
w->setUniformRowHeights(true);
|
|
|
|
|
w->setColumnCount(5);
|
|
|
|
|
w->setRootIsDecorated(false);
|
|
|
|
|
w->setAlternatingRowColors(true);
|
|
|
|
|
w->setSortingEnabled(true);
|
|
|
|
|
w->setObjectName(QLatin1String("Sections.") + moduleName);
|
|
|
|
|
QStringList header;
|
2014-10-22 13:04:47 +02:00
|
|
|
header.append(DebuggerPlugin::tr("Name"));
|
|
|
|
|
header.append(DebuggerPlugin::tr("From"));
|
|
|
|
|
header.append(DebuggerPlugin::tr("To"));
|
|
|
|
|
header.append(DebuggerPlugin::tr("Address"));
|
|
|
|
|
header.append(DebuggerPlugin::tr("Flags"));
|
2012-11-07 18:31:17 +01:00
|
|
|
w->setHeaderLabels(header);
|
2014-10-22 13:04:47 +02:00
|
|
|
w->setWindowTitle(DebuggerPlugin::tr("Sections in \"%1\"").arg(moduleName));
|
2012-11-07 18:31:17 +01:00
|
|
|
foreach (const Section &s, sections) {
|
|
|
|
|
QTreeWidgetItem *it = new QTreeWidgetItem;
|
|
|
|
|
it->setData(0, Qt::DisplayRole, s.name);
|
|
|
|
|
it->setData(1, Qt::DisplayRole, s.from);
|
|
|
|
|
it->setData(2, Qt::DisplayRole, s.to);
|
|
|
|
|
it->setData(3, Qt::DisplayRole, s.address);
|
|
|
|
|
it->setData(4, Qt::DisplayRole, s.flags);
|
|
|
|
|
w->addTopLevelItem(it);
|
|
|
|
|
}
|
|
|
|
|
createNewDock(w);
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-06 08:25:29 +01:00
|
|
|
void DebuggerPluginPrivate::aboutToShutdown()
|
|
|
|
|
{
|
2016-06-26 22:25:34 +03:00
|
|
|
disconnect(SessionManager::instance(), &SessionManager::startupProjectChanged, this, nullptr);
|
2016-03-24 13:59:05 +01:00
|
|
|
|
|
|
|
|
m_mainWindow->saveCurrentPerspective();
|
|
|
|
|
delete m_mainWindow;
|
|
|
|
|
m_mainWindow = 0;
|
|
|
|
|
|
|
|
|
|
// removeObject leads to aboutToRemoveObject, which leads to
|
|
|
|
|
// ModeManager::aboutToRemove, which leads to the mode manager
|
|
|
|
|
// removing the mode's widget from the stackwidget
|
|
|
|
|
// (currently by index, but possibly the stackwidget resets the
|
|
|
|
|
// parent and stuff on the widget)
|
|
|
|
|
m_plugin->removeObject(m_mode);
|
|
|
|
|
|
|
|
|
|
delete m_modeWindow;
|
|
|
|
|
m_modeWindow = 0;
|
|
|
|
|
|
|
|
|
|
delete m_mode;
|
|
|
|
|
m_mode = 0;
|
2010-12-06 08:25:29 +01:00
|
|
|
}
|
|
|
|
|
|
2014-10-22 13:04:47 +02:00
|
|
|
void updateState(DebuggerEngine *engine)
|
|
|
|
|
{
|
|
|
|
|
dd->updateState(engine);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void updateWatchersWindow(bool showWatch, bool showReturn)
|
|
|
|
|
{
|
2015-03-16 13:21:02 +01:00
|
|
|
dd->m_watchersWindow->setVisible(showWatch);
|
|
|
|
|
dd->m_returnWindow->setVisible(showReturn);
|
2014-10-22 13:04:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool hasSnapshots()
|
|
|
|
|
{
|
|
|
|
|
return dd->m_snapshotHandler->size();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void openTextEditor(const QString &titlePattern0, const QString &contents)
|
|
|
|
|
{
|
|
|
|
|
if (dd->m_shuttingDown)
|
|
|
|
|
return;
|
|
|
|
|
QString titlePattern = titlePattern0;
|
|
|
|
|
IEditor *editor = EditorManager::openEditorWithContents(
|
2015-02-26 20:50:28 +03:00
|
|
|
CC::K_DEFAULT_TEXT_EDITOR_ID, &titlePattern, contents.toUtf8(), QString(),
|
2014-10-22 13:04:47 +02:00
|
|
|
EditorManager::IgnoreNavigationHistory);
|
2015-07-20 17:07:28 +02:00
|
|
|
if (auto textEditor = qobject_cast<BaseTextEditor *>(editor)) {
|
|
|
|
|
QString suggestion = titlePattern;
|
|
|
|
|
if (!suggestion.contains(QLatin1Char('.')))
|
|
|
|
|
suggestion.append(QLatin1String(".txt"));
|
2016-01-14 14:45:01 +01:00
|
|
|
textEditor->textDocument()->setFallbackSaveAsFileName(suggestion);
|
2015-07-20 17:07:28 +02:00
|
|
|
}
|
2014-10-22 13:04:47 +02:00
|
|
|
QTC_ASSERT(editor, return);
|
|
|
|
|
}
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2014-10-22 13:04:47 +02:00
|
|
|
// void runTest(const QString &fileName);
|
|
|
|
|
void showMessage(const QString &msg, int channel, int timeout)
|
|
|
|
|
{
|
|
|
|
|
dd->showMessage(msg, channel, timeout);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void runControlStarted(DebuggerEngine *engine)
|
|
|
|
|
{
|
|
|
|
|
dd->runControlStarted(engine);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void runControlFinished(DebuggerEngine *engine)
|
|
|
|
|
{
|
|
|
|
|
dd->runControlFinished(engine);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void displayDebugger(DebuggerEngine *engine, bool updateEngine)
|
|
|
|
|
{
|
|
|
|
|
dd->displayDebugger(engine, updateEngine);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void synchronizeBreakpoints()
|
|
|
|
|
{
|
|
|
|
|
dd->synchronizeBreakpoints();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QWidget *mainWindow()
|
|
|
|
|
{
|
2016-03-02 13:57:37 +01:00
|
|
|
return dd->m_mainWindow;
|
2014-10-22 13:04:47 +02:00
|
|
|
}
|
|
|
|
|
|
2016-03-14 18:14:06 +01:00
|
|
|
bool isRegistersWindowVisible()
|
2014-10-22 13:04:47 +02:00
|
|
|
{
|
2016-03-14 18:14:06 +01:00
|
|
|
return dd->m_registerWindow->isVisible();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool isModulesWindowVisible()
|
|
|
|
|
{
|
|
|
|
|
return dd->m_modulesWindow->isVisible();
|
2014-10-22 13:04:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void openMemoryEditor()
|
|
|
|
|
{
|
|
|
|
|
AddressDialog dialog;
|
2014-12-17 13:14:29 +01:00
|
|
|
if (dialog.exec() == QDialog::Accepted) {
|
|
|
|
|
MemoryViewSetupData data;
|
|
|
|
|
data.startAddress = dialog.address();
|
|
|
|
|
currentEngine()->openMemoryView(data);
|
|
|
|
|
}
|
2014-10-22 13:04:47 +02:00
|
|
|
}
|
|
|
|
|
|
2015-06-12 11:55:57 +02:00
|
|
|
void setThreadBoxContents(const QStringList &list, int index)
|
2014-10-22 13:04:47 +02:00
|
|
|
{
|
2015-06-12 11:55:57 +02:00
|
|
|
dd->setThreadBoxContents(list, index);
|
2014-10-22 13:04:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QSharedPointer<Internal::GlobalDebuggerOptions> globalDebuggerOptions()
|
|
|
|
|
{
|
|
|
|
|
return dd->m_globalDebuggerOptions;
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-10 11:39:01 +01:00
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
|
|
|
|
// DebuggerPlugin
|
|
|
|
|
//
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
2010-06-16 11:08:54 +02:00
|
|
|
|
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
|
2012-12-30 11:37:50 +01:00
|
|
|
is DebuggerCore, implemented in DebuggerPluginPrivate.
|
|
|
|
|
*/
|
2011-02-04 15:08:31 +01:00
|
|
|
|
2016-02-24 14:42:52 +01:00
|
|
|
static DebuggerPlugin *m_instance = 0;
|
|
|
|
|
|
2010-11-10 11:39:01 +01:00
|
|
|
DebuggerPlugin::DebuggerPlugin()
|
2010-07-13 15:57:34 +02:00
|
|
|
{
|
2014-10-28 08:26:25 +01:00
|
|
|
setObjectName(QLatin1String("DebuggerPlugin"));
|
2016-02-24 14:42:52 +01:00
|
|
|
m_instance = 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
|
|
|
{
|
2014-10-22 13:04:47 +02:00
|
|
|
delete dd;
|
|
|
|
|
dd = 0;
|
2016-02-24 14:42:52 +01:00
|
|
|
m_instance = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DebuggerPlugin *DebuggerPlugin::instance()
|
|
|
|
|
{
|
|
|
|
|
return m_instance;
|
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
|
|
|
{
|
2016-02-29 12:11:18 +01:00
|
|
|
dd = new DebuggerPluginPrivate(this);
|
|
|
|
|
|
2015-06-16 15:24:42 +02:00
|
|
|
addObject(this);
|
2011-10-10 13:38:58 +02:00
|
|
|
// Menu groups
|
2012-07-18 16:20:19 +02:00
|
|
|
ActionContainer *mstart = ActionManager::actionContainer(PE::M_DEBUG_STARTDEBUGGING);
|
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
|
2015-02-26 13:58:00 +01:00
|
|
|
mstart->addSeparator(Constants::G_GENERAL);
|
|
|
|
|
mstart->addSeparator(Constants::G_SPECIAL);
|
2011-10-10 13:38:58 +02:00
|
|
|
|
2013-10-09 12:42:00 +02:00
|
|
|
addAutoReleasedObject(new DebuggerItemManager);
|
2013-08-14 18:30:40 +02:00
|
|
|
DebuggerItemManager::restoreDebuggers();
|
|
|
|
|
|
2013-08-21 12:48:46 +02:00
|
|
|
KitManager::registerKitInformation(new DebuggerKitInformation);
|
2012-04-24 15:49:09 +02:00
|
|
|
|
2016-02-24 14:42:52 +01:00
|
|
|
// Task integration.
|
|
|
|
|
//: Category under which Analyzer tasks are listed in Issues view
|
2016-03-02 13:57:37 +01:00
|
|
|
ProjectExplorer::TaskHub::addCategory(Debugger::Constants::ANALYZERTASK_ID, tr("Debugger"));
|
2016-02-24 14:42:52 +01:00
|
|
|
|
2014-10-22 13:04:47 +02:00
|
|
|
return dd->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
|
|
|
{
|
2014-10-28 10:01:19 +01:00
|
|
|
removeObject(this);
|
2014-10-22 13:04:47 +02:00
|
|
|
dd->aboutToShutdown();
|
2010-11-10 11:39:01 +01:00
|
|
|
return SynchronousShutdown;
|
2010-06-16 11:08:54 +02:00
|
|
|
}
|
|
|
|
|
|
2013-03-11 18:15:49 +02:00
|
|
|
QObject *DebuggerPlugin::remoteCommand(const QStringList &options,
|
2015-03-09 10:59:58 +02:00
|
|
|
const QString &workingDirectory,
|
|
|
|
|
const QStringList &list)
|
2010-06-16 11:08:54 +02:00
|
|
|
{
|
2015-03-09 10:59:58 +02:00
|
|
|
Q_UNUSED(workingDirectory);
|
|
|
|
|
Q_UNUSED(list);
|
|
|
|
|
dd->remoteCommand(options);
|
2013-03-11 18:15:49 +02:00
|
|
|
return 0;
|
2010-06-16 11:08:54 +02:00
|
|
|
}
|
|
|
|
|
|
2010-11-10 11:39:01 +01:00
|
|
|
void DebuggerPlugin::extensionsInitialized()
|
2010-11-05 13:35:31 +01:00
|
|
|
{
|
2014-10-22 13:04:47 +02:00
|
|
|
dd->extensionsInitialized();
|
2010-11-05 13:35:31 +01:00
|
|
|
}
|
|
|
|
|
|
2016-02-29 12:11:18 +01:00
|
|
|
void DebuggerPluginPrivate::updateUiForProject(Project *project)
|
|
|
|
|
{
|
|
|
|
|
if (m_previousProject) {
|
|
|
|
|
disconnect(m_previousProject, &Project::activeTargetChanged,
|
|
|
|
|
this, &DebuggerPluginPrivate::updateUiForTarget);
|
|
|
|
|
}
|
|
|
|
|
m_previousProject = project;
|
|
|
|
|
if (!project) {
|
|
|
|
|
updateUiForTarget(0);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
connect(project, &Project::activeTargetChanged,
|
2016-03-02 13:57:37 +01:00
|
|
|
this, &DebuggerPluginPrivate::updateUiForTarget,
|
|
|
|
|
Qt::QueuedConnection);
|
2016-02-29 12:11:18 +01:00
|
|
|
updateUiForTarget(project->activeTarget());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DebuggerPluginPrivate::updateUiForTarget(Target *target)
|
|
|
|
|
{
|
|
|
|
|
if (m_previousTarget) {
|
2016-03-17 14:32:06 +01:00
|
|
|
disconnect(m_previousTarget.data(), &Target::activeRunConfigurationChanged,
|
2016-02-29 12:11:18 +01:00
|
|
|
this, &DebuggerPluginPrivate::updateUiForRunConfiguration);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_previousTarget = target;
|
|
|
|
|
|
|
|
|
|
if (!target) {
|
|
|
|
|
updateUiForRunConfiguration(0);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
connect(target, &Target::activeRunConfigurationChanged,
|
2016-03-02 13:57:37 +01:00
|
|
|
this, &DebuggerPluginPrivate::updateUiForRunConfiguration,
|
|
|
|
|
Qt::QueuedConnection);
|
2016-02-29 12:11:18 +01:00
|
|
|
updateUiForRunConfiguration(target->activeRunConfiguration());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// updates default debug language settings per run config.
|
|
|
|
|
void DebuggerPluginPrivate::updateUiForRunConfiguration(RunConfiguration *rc)
|
|
|
|
|
{
|
2016-03-02 13:57:37 +01:00
|
|
|
// if (m_previousRunConfiguration)
|
|
|
|
|
// disconnect(m_previousRunConfiguration, &RunConfiguration::requestRunActionsUpdate,
|
|
|
|
|
// this, &DebuggerPluginPrivate::updateActiveLanguages);
|
|
|
|
|
// m_previousRunConfiguration = rc;
|
|
|
|
|
Q_UNUSED(rc); // FIXME
|
2016-02-29 12:11:18 +01:00
|
|
|
updateActiveLanguages();
|
2016-03-02 13:57:37 +01:00
|
|
|
// if (m_previousRunConfiguration)
|
|
|
|
|
// connect(m_previousRunConfiguration, &RunConfiguration::requestRunActionsUpdate,
|
|
|
|
|
// this, &DebuggerPluginPrivate::updateActiveLanguages,
|
|
|
|
|
// Qt::QueuedConnection);
|
2016-02-29 12:11:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DebuggerPluginPrivate::updateActiveLanguages()
|
|
|
|
|
{
|
2016-04-29 14:51:51 +02:00
|
|
|
QTC_ASSERT(dd->m_currentEngine, return);
|
2016-03-03 10:06:18 +02:00
|
|
|
const DebuggerLanguages languages = dd->m_currentEngine->runParameters().languages;
|
2016-03-02 13:57:37 +01:00
|
|
|
// Id perspective = (languages & QmlLanguage) && !(languages & CppLanguage)
|
|
|
|
|
// ? QmlPerspectiveId : CppPerspectiveId;
|
|
|
|
|
// m_mainWindow->restorePerspective(perspective);
|
2016-03-03 10:06:18 +02:00
|
|
|
for (DebuggerLanguage language: {QmlLanguage, CppLanguage}) {
|
|
|
|
|
const Context context = m_contextsForLanguage.value(language);
|
|
|
|
|
if (languages & language)
|
|
|
|
|
ICore::addAdditionalContext(context);
|
|
|
|
|
else
|
|
|
|
|
ICore::removeAdditionalContext(context);
|
|
|
|
|
}
|
2016-02-29 12:11:18 +01:00
|
|
|
}
|
|
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
//bool DockWidgetEventFilter::eventFilter(QObject *obj, QEvent *event)
|
|
|
|
|
//{
|
|
|
|
|
// switch (event->type()) {
|
|
|
|
|
// case QEvent::Resize:
|
|
|
|
|
// case QEvent::ZOrderChange:
|
|
|
|
|
// dd->updateDockWidgetSettings();
|
|
|
|
|
// break;
|
|
|
|
|
// default:
|
|
|
|
|
// break;
|
|
|
|
|
// }
|
|
|
|
|
// return QObject::eventFilter(obj, event);
|
|
|
|
|
//}
|
|
|
|
|
|
2016-03-25 20:00:19 +01:00
|
|
|
void DebuggerPluginPrivate::onModeChanged(Id mode)
|
2016-02-29 12:11:18 +01:00
|
|
|
{
|
2016-03-02 13:57:37 +01:00
|
|
|
// 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.
|
2016-02-29 12:11:18 +01:00
|
|
|
|
2016-03-25 20:00:19 +01:00
|
|
|
if (mode == MODE_DEBUG) {
|
2016-03-02 13:57:37 +01:00
|
|
|
if (IEditor *editor = EditorManager::currentEditor())
|
|
|
|
|
editor->widget()->setFocus();
|
2016-02-29 12:11:18 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
m_toolTipManager.debugModeEntered();
|
|
|
|
|
|
|
|
|
|
// static bool firstTime = true;
|
|
|
|
|
// if (firstTime) {
|
|
|
|
|
|
|
|
|
|
// // Dock widgets
|
|
|
|
|
// connect(m_mainWindow->dockWidget(DOCKWIDGET_MODULES)->toggleViewAction(), &QAction::toggled,
|
|
|
|
|
// this, &DebuggerPluginPrivate::modulesDockToggled, Qt::QueuedConnection);
|
|
|
|
|
// connect(m_mainWindow->dockWidget(DOCKWIDGET_OUTPUT)->toggleViewAction(), &QAction::toggled,
|
|
|
|
|
// this, &DebuggerPluginPrivate::registerDockToggled, Qt::QueuedConnection);
|
|
|
|
|
// connect(m_mainWindow->dockWidget(DOCKWIDGET_SOURCE_FILES)->toggleViewAction(), &QAction::toggled,
|
|
|
|
|
// this, &DebuggerPluginPrivate::sourceFilesDockToggled, Qt::QueuedConnection);
|
|
|
|
|
|
|
|
|
|
// firstTime = false;
|
|
|
|
|
// }
|
|
|
|
|
updateActiveLanguages();
|
|
|
|
|
} else {
|
|
|
|
|
m_toolTipManager.leavingDebugMode();
|
|
|
|
|
}
|
2016-02-29 12:11:18 +01:00
|
|
|
}
|
|
|
|
|
|
2016-03-17 10:11:38 +01:00
|
|
|
void saveModeToRestore()
|
|
|
|
|
{
|
2016-03-25 20:00:19 +01:00
|
|
|
dd->m_previousMode = ModeManager::currentMode();
|
2016-03-17 10:11:38 +01:00
|
|
|
}
|
|
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
} // namespace Internal
|
|
|
|
|
|
|
|
|
|
bool ActionDescription::isRunnable(QString *reason) const
|
2016-02-29 12:11:18 +01:00
|
|
|
{
|
2016-03-02 13:57:37 +01:00
|
|
|
if (m_customToolStarter) // Something special. Pretend we can always run it.
|
|
|
|
|
return true;
|
2016-02-29 12:11:18 +01:00
|
|
|
|
2016-03-10 11:11:19 +01:00
|
|
|
return ProjectExplorerPlugin::canRunStartupProject(m_runMode, reason);
|
2016-03-02 13:57:37 +01:00
|
|
|
}
|
2016-02-29 12:11:18 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
static bool buildTypeAccepted(QFlags<ToolMode> toolMode, BuildConfiguration::BuildType buildType)
|
|
|
|
|
{
|
|
|
|
|
if (buildType == BuildConfiguration::Unknown)
|
|
|
|
|
return true;
|
|
|
|
|
if (buildType == BuildConfiguration::Debug && (toolMode & DebugMode))
|
|
|
|
|
return true;
|
|
|
|
|
if (buildType == BuildConfiguration::Release && (toolMode & ReleaseMode))
|
|
|
|
|
return true;
|
|
|
|
|
if (buildType == BuildConfiguration::Profile && (toolMode & ProfileMode))
|
|
|
|
|
return true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2016-02-29 12:11:18 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void ActionDescription::startTool() const
|
|
|
|
|
{
|
|
|
|
|
TaskHub::clearTasks(Constants::ANALYZERTASK_ID);
|
|
|
|
|
Debugger::selectPerspective(m_perspectiveId);
|
2016-02-29 12:11:18 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
if (m_toolPreparer && !m_toolPreparer())
|
|
|
|
|
return;
|
2016-02-29 12:11:18 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
// ### not sure if we're supposed to check if the RunConFiguration isEnabled
|
|
|
|
|
Project *pro = SessionManager::startupProject();
|
|
|
|
|
RunConfiguration *rc = 0;
|
|
|
|
|
BuildConfiguration::BuildType buildType = BuildConfiguration::Unknown;
|
|
|
|
|
if (pro) {
|
|
|
|
|
if (const Target *target = pro->activeTarget()) {
|
|
|
|
|
// Build configuration is 0 for QML projects.
|
|
|
|
|
if (const BuildConfiguration *buildConfig = target->activeBuildConfiguration())
|
|
|
|
|
buildType = buildConfig->buildType();
|
|
|
|
|
rc = target->activeRunConfiguration();
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-02-29 12:11:18 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
// Custom start.
|
|
|
|
|
if (m_customToolStarter) {
|
|
|
|
|
if (rc) {
|
|
|
|
|
m_customToolStarter(rc);
|
|
|
|
|
} else {
|
|
|
|
|
QMessageBox *errorDialog = new QMessageBox(ICore::mainWindow());
|
|
|
|
|
errorDialog->setIcon(QMessageBox::Warning);
|
|
|
|
|
errorDialog->setWindowTitle(m_text);
|
|
|
|
|
errorDialog->setText(tr("Cannot start %1 without a project. Please open the project "
|
|
|
|
|
"and try again.").arg(m_text));
|
|
|
|
|
errorDialog->setStandardButtons(QMessageBox::Ok);
|
|
|
|
|
errorDialog->setDefaultButton(QMessageBox::Ok);
|
|
|
|
|
errorDialog->show();
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
2016-02-29 12:11:18 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
// Check the project for whether the build config is in the correct mode
|
|
|
|
|
// if not, notify the user and urge him to use the correct mode.
|
|
|
|
|
if (!buildTypeAccepted(m_toolMode, buildType)) {
|
|
|
|
|
QString currentMode;
|
|
|
|
|
switch (buildType) {
|
|
|
|
|
case BuildConfiguration::Debug:
|
|
|
|
|
currentMode = tr("Debug");
|
|
|
|
|
break;
|
|
|
|
|
case BuildConfiguration::Profile:
|
|
|
|
|
currentMode = tr("Profile");
|
|
|
|
|
break;
|
|
|
|
|
case BuildConfiguration::Release:
|
|
|
|
|
currentMode = tr("Release");
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
QTC_CHECK(false);
|
|
|
|
|
}
|
2016-02-29 12:11:18 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
QString toolModeString;
|
|
|
|
|
switch (m_toolMode) {
|
|
|
|
|
case DebugMode:
|
|
|
|
|
toolModeString = tr("in Debug mode");
|
|
|
|
|
break;
|
|
|
|
|
case ProfileMode:
|
|
|
|
|
toolModeString = tr("in Profile mode");
|
|
|
|
|
break;
|
|
|
|
|
case ReleaseMode:
|
|
|
|
|
toolModeString = tr("in Release mode");
|
|
|
|
|
break;
|
|
|
|
|
case SymbolsMode:
|
|
|
|
|
toolModeString = tr("with debug symbols (Debug or Profile mode)");
|
|
|
|
|
break;
|
|
|
|
|
case OptimizedMode:
|
|
|
|
|
toolModeString = tr("on optimized code (Profile or Release mode)");
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
QTC_CHECK(false);
|
|
|
|
|
}
|
|
|
|
|
const QString toolName = m_text; // The action text is always the name of the tool
|
|
|
|
|
const QString title = tr("Run %1 in %2 Mode?").arg(toolName).arg(currentMode);
|
|
|
|
|
const QString message = tr("<html><head/><body><p>You are trying "
|
|
|
|
|
"to run the tool \"%1\" on an application in %2 mode. "
|
|
|
|
|
"The tool is designed to be used %3.</p><p>"
|
|
|
|
|
"Run-time characteristics differ significantly between "
|
|
|
|
|
"optimized and non-optimized binaries. Analytical "
|
|
|
|
|
"findings for one mode may or may not be relevant for "
|
|
|
|
|
"the other.</p><p>"
|
|
|
|
|
"Running tools that need debug symbols on binaries that "
|
|
|
|
|
"don't provide any may lead to missing function names "
|
|
|
|
|
"or otherwise insufficient output.</p><p>"
|
|
|
|
|
"Do you want to continue and run the tool in %2 mode?</p></body></html>")
|
|
|
|
|
.arg(toolName).arg(currentMode).arg(toolModeString);
|
|
|
|
|
if (Utils::CheckableMessageBox::doNotAskAgainQuestion(ICore::mainWindow(),
|
|
|
|
|
title, message, ICore::settings(), QLatin1String("AnalyzerCorrectModeWarning"))
|
|
|
|
|
!= QDialogButtonBox::Yes)
|
|
|
|
|
return;
|
|
|
|
|
}
|
2016-02-29 12:11:18 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
ProjectExplorerPlugin::runStartupProject(m_runMode);
|
2016-02-29 12:11:18 +01:00
|
|
|
}
|
|
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void registerAction(Id actionId, const ActionDescription &desc, QAction *startAction)
|
|
|
|
|
{
|
2016-03-08 12:40:05 +01:00
|
|
|
auto action = new QAction(dd);
|
|
|
|
|
action->setText(desc.text());
|
|
|
|
|
action->setToolTip(desc.toolTip());
|
|
|
|
|
dd->m_descriptions.insert(actionId, desc);
|
|
|
|
|
|
|
|
|
|
Id menuGroup = desc.menuGroup();
|
|
|
|
|
if (menuGroup.isValid()) {
|
|
|
|
|
Command *command = ActionManager::registerAction(action, actionId);
|
|
|
|
|
dd->m_menu->addAction(command, menuGroup);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QObject::connect(action, &QAction::triggered, dd, [desc] { desc.startTool(); });
|
|
|
|
|
|
|
|
|
|
if (startAction) {
|
|
|
|
|
QObject::connect(startAction, &QAction::triggered, action, &QAction::triggered);
|
|
|
|
|
|
|
|
|
|
QObject::connect(startAction, &QAction::changed, action, [action, startAction] {
|
|
|
|
|
action->setEnabled(startAction->isEnabled());
|
|
|
|
|
});
|
|
|
|
|
}
|
2016-03-02 13:57:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void registerToolbar(const QByteArray &perspectiveId, const ToolbarDescription &desc)
|
|
|
|
|
{
|
|
|
|
|
auto toolbar = new QWidget;
|
|
|
|
|
toolbar->setObjectName(QString::fromLatin1(perspectiveId + ".Toolbar"));
|
|
|
|
|
auto hbox = new QHBoxLayout(toolbar);
|
|
|
|
|
hbox->setMargin(0);
|
|
|
|
|
hbox->setSpacing(0);
|
|
|
|
|
for (QWidget *widget : desc.widgets())
|
|
|
|
|
hbox->addWidget(widget);
|
|
|
|
|
hbox->addStretch();
|
|
|
|
|
toolbar->setLayout(hbox);
|
|
|
|
|
|
|
|
|
|
dd->m_mainWindow->registerToolbar(perspectiveId, toolbar);
|
|
|
|
|
}
|
2016-02-29 12:11:18 +01:00
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
QAction *createStartAction()
|
|
|
|
|
{
|
2016-03-13 22:15:19 +02:00
|
|
|
auto action = new QAction(DebuggerMainWindow::tr("Start"), DebuggerPlugin::instance());
|
2016-05-30 16:29:51 +02:00
|
|
|
action->setIcon(ProjectExplorer::Icons::ANALYZER_START_SMALL_TOOLBAR.icon());
|
2016-03-02 13:57:37 +01:00
|
|
|
action->setEnabled(true);
|
|
|
|
|
return action;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QAction *createStopAction()
|
|
|
|
|
{
|
2016-03-13 22:15:19 +02:00
|
|
|
auto action = new QAction(DebuggerMainWindow::tr("Stop"), DebuggerPlugin::instance());
|
2016-08-03 17:55:54 +02:00
|
|
|
action->setIcon(Utils::Icons::STOP_SMALL_TOOLBAR.icon());
|
2016-03-02 13:57:37 +01:00
|
|
|
action->setEnabled(true);
|
|
|
|
|
return action;
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-12 11:57:29 +02:00
|
|
|
void registerPerspective(const QByteArray &perspectiveId, const Perspective *perspective)
|
2016-03-02 13:57:37 +01:00
|
|
|
{
|
|
|
|
|
dd->m_mainWindow->registerPerspective(perspectiveId, perspective);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void selectPerspective(const QByteArray &perspectiveId)
|
|
|
|
|
{
|
2016-08-23 09:35:02 +02:00
|
|
|
if (dd->m_mainWindow->currentPerspective() == perspectiveId)
|
|
|
|
|
return;
|
|
|
|
|
|
2016-03-09 11:02:39 +01:00
|
|
|
// FIXME: Work-around aslong as the GammaRay integration does not use the same setup,
|
|
|
|
|
if (perspectiveId.isEmpty())
|
|
|
|
|
return;
|
2016-03-02 13:57:37 +01:00
|
|
|
ModeManager::activateMode(MODE_DEBUG);
|
2016-03-09 11:02:39 +01:00
|
|
|
dd->m_mainWindow->restorePerspective(perspectiveId);
|
2016-03-02 13:57:37 +01:00
|
|
|
}
|
|
|
|
|
|
2016-05-12 13:55:34 +02:00
|
|
|
QWidget *mainWindow()
|
|
|
|
|
{
|
|
|
|
|
return dd->m_mainWindow;
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-02 13:57:37 +01:00
|
|
|
void enableMainWindow(bool on)
|
|
|
|
|
{
|
|
|
|
|
dd->m_mainWindow->setEnabled(on);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void showStatusMessage(const QString &message, int timeoutMS)
|
|
|
|
|
{
|
|
|
|
|
dd->m_mainWindow->showStatusMessage(message, timeoutMS);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void showPermanentStatusMessage(const QString &message)
|
|
|
|
|
{
|
|
|
|
|
dd->m_mainWindow->showStatusMessage(message, -1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AnalyzerRunControl *createAnalyzerRunControl(RunConfiguration *runConfiguration, Id runMode)
|
|
|
|
|
{
|
|
|
|
|
foreach (const ActionDescription &action, dd->m_descriptions) {
|
|
|
|
|
if (action.runMode() == runMode)
|
|
|
|
|
return action.runControlCreator()(runConfiguration, runMode);
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-09 19:16:14 +01:00
|
|
|
namespace Internal {
|
2016-03-02 10:49:06 +02:00
|
|
|
|
2016-03-09 19:16:14 +01:00
|
|
|
static bool s_testRun = false;
|
|
|
|
|
bool isTestRun() { return s_testRun; }
|
2016-03-02 10:49:06 +02:00
|
|
|
|
2016-03-09 19:16:14 +01:00
|
|
|
#ifdef WITH_TESTS
|
2016-03-02 10:49:06 +02:00
|
|
|
|
2016-03-09 19:16:14 +01:00
|
|
|
class DebuggerUnitTests : public QObject
|
2016-03-02 10:49:06 +02:00
|
|
|
{
|
2016-03-09 19:16:14 +01:00
|
|
|
Q_OBJECT
|
2016-03-02 10:49:06 +02:00
|
|
|
|
2016-03-09 19:16:14 +01:00
|
|
|
public:
|
|
|
|
|
DebuggerUnitTests() {}
|
2016-03-02 10:49:06 +02:00
|
|
|
|
2016-03-09 19:16:14 +01:00
|
|
|
private slots:
|
|
|
|
|
void initTestCase();
|
|
|
|
|
void cleanupTestCase();
|
2016-03-02 10:49:06 +02:00
|
|
|
|
2016-03-09 19:16:14 +01:00
|
|
|
void testDebuggerMatching_data();
|
|
|
|
|
void testDebuggerMatching();
|
2016-03-02 10:49:06 +02:00
|
|
|
|
2016-03-09 19:16:14 +01:00
|
|
|
void testBenchmark();
|
|
|
|
|
void testStateMachine();
|
2016-03-02 10:49:06 +02:00
|
|
|
|
2016-03-09 19:16:14 +01:00
|
|
|
private:
|
|
|
|
|
CppTools::Tests::TemporaryCopiedDir *m_tmpDir = 0;
|
|
|
|
|
};
|
2016-03-02 10:49:06 +02:00
|
|
|
|
2016-03-09 19:16:14 +01:00
|
|
|
void DebuggerUnitTests::initTestCase()
|
2016-03-02 10:49:06 +02:00
|
|
|
{
|
2016-03-09 19:16:14 +01:00
|
|
|
// const QList<Kit *> allKits = KitManager::kits();
|
|
|
|
|
// if (allKits.count() != 1)
|
|
|
|
|
// QSKIP("This test requires exactly one kit to be present");
|
|
|
|
|
// const ToolChain * const toolchain = ToolChainKitInformation::toolChain(allKits.first());
|
|
|
|
|
// if (!toolchain)
|
|
|
|
|
// QSKIP("This test requires that there is a kit with a toolchain.");
|
|
|
|
|
// bool hasClangExecutable;
|
|
|
|
|
// clangExecutableFromSettings(toolchain->typeId(), &hasClangExecutable);
|
|
|
|
|
// if (!hasClangExecutable)
|
|
|
|
|
// QSKIP("No clang suitable for analyzing found");
|
2016-03-02 10:49:06 +02:00
|
|
|
|
2016-03-09 19:16:14 +01:00
|
|
|
s_testRun = true;
|
|
|
|
|
m_tmpDir = new CppTools::Tests::TemporaryCopiedDir(QLatin1String(":/unit-tests"));
|
|
|
|
|
QVERIFY(m_tmpDir->isValid());
|
2016-03-02 10:49:06 +02:00
|
|
|
}
|
|
|
|
|
|
2016-03-09 19:16:14 +01:00
|
|
|
void DebuggerUnitTests::cleanupTestCase()
|
2016-03-02 10:49:06 +02:00
|
|
|
{
|
2016-03-09 19:16:14 +01:00
|
|
|
delete m_tmpDir;
|
2016-03-02 10:49:06 +02:00
|
|
|
}
|
|
|
|
|
|
2016-03-09 19:16:14 +01:00
|
|
|
void DebuggerUnitTests::testStateMachine()
|
|
|
|
|
{
|
|
|
|
|
QString proFile = m_tmpDir->absolutePath("simple/simple.pro");
|
2013-09-10 13:37:31 +02:00
|
|
|
|
2016-03-09 19:16:14 +01:00
|
|
|
CppTools::Tests::ProjectOpenerAndCloser projectManager;
|
|
|
|
|
const CppTools::ProjectInfo projectInfo = projectManager.open(proFile, true);
|
|
|
|
|
QVERIFY(projectInfo.isValid());
|
2012-01-26 13:14:00 +01:00
|
|
|
|
2016-03-09 19:16:14 +01:00
|
|
|
QEventLoop loop;
|
|
|
|
|
connect(BuildManager::instance(), &BuildManager::buildQueueFinished,
|
|
|
|
|
&loop, &QEventLoop::quit);
|
|
|
|
|
ProjectExplorerPlugin::buildProject(SessionManager::startupProject());
|
|
|
|
|
loop.exec();
|
2012-01-26 13:14:00 +01:00
|
|
|
|
2016-05-18 07:33:52 +02:00
|
|
|
ExecuteOnDestruction guard([] () {
|
|
|
|
|
EditorManager::closeAllEditors(false);
|
|
|
|
|
});
|
2016-03-09 19:16:14 +01:00
|
|
|
DebuggerRunParameters rp;
|
|
|
|
|
Target *t = SessionManager::startupProject()->activeTarget();
|
|
|
|
|
QVERIFY(t);
|
|
|
|
|
Kit *kit = t->kit();
|
|
|
|
|
QVERIFY(kit);
|
|
|
|
|
RunConfiguration *rc = t->activeRunConfiguration();
|
|
|
|
|
QVERIFY(rc);
|
|
|
|
|
rp.inferior = rc->runnable().as<StandardRunnable>();
|
|
|
|
|
rp.testCase = TestNoBoundsOfCurrentFunction;
|
|
|
|
|
DebuggerRunControl *runControl = createAndScheduleRun(rp, kit);
|
|
|
|
|
|
|
|
|
|
connect(runControl, &RunControl::finished, this, [this] {
|
|
|
|
|
QTestEventLoop::instance().exitLoop();
|
|
|
|
|
});
|
2012-01-26 13:14:00 +01:00
|
|
|
|
2016-04-20 15:09:57 +02:00
|
|
|
QTestEventLoop::instance().enterLoop(5);
|
2012-01-26 13:14:00 +01:00
|
|
|
}
|
|
|
|
|
|
2016-03-09 19:16:14 +01:00
|
|
|
|
2012-01-26 13:14:00 +01:00
|
|
|
enum FakeEnum { FakeDebuggerCommonSettingsId };
|
|
|
|
|
|
2016-03-09 19:16:14 +01:00
|
|
|
void DebuggerUnitTests::testBenchmark()
|
2012-01-26 13:14:00 +01:00
|
|
|
{
|
|
|
|
|
#ifdef WITH_BENCHMARK
|
|
|
|
|
CALLGRIND_START_INSTRUMENTATION;
|
2015-02-03 23:58:49 +02:00
|
|
|
volatile Id id1 = Id(DEBUGGER_COMMON_SETTINGS_ID);
|
2012-01-26 13:14:00 +01:00
|
|
|
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
|
|
|
}
|
|
|
|
|
|
2016-03-09 19:16:14 +01:00
|
|
|
void DebuggerUnitTests::testDebuggerMatching_data()
|
|
|
|
|
{
|
|
|
|
|
QTest::addColumn<QStringList>("debugger");
|
|
|
|
|
QTest::addColumn<QString>("target");
|
|
|
|
|
QTest::addColumn<int>("result");
|
|
|
|
|
|
|
|
|
|
QTest::newRow("Invalid data")
|
|
|
|
|
<< QStringList()
|
|
|
|
|
<< QString()
|
|
|
|
|
<< int(DebuggerItem::DoesNotMatch);
|
|
|
|
|
QTest::newRow("Invalid debugger")
|
|
|
|
|
<< QStringList()
|
|
|
|
|
<< QString::fromLatin1("x86-linux-generic-elf-32bit")
|
|
|
|
|
<< int(DebuggerItem::DoesNotMatch);
|
|
|
|
|
QTest::newRow("Invalid target")
|
|
|
|
|
<< (QStringList() << QLatin1String("x86-linux-generic-elf-32bit"))
|
|
|
|
|
<< QString()
|
|
|
|
|
<< int(DebuggerItem::DoesNotMatch);
|
|
|
|
|
|
|
|
|
|
QTest::newRow("Fuzzy match 1")
|
|
|
|
|
<< (QStringList() << QLatin1String("unknown-unknown-unknown-unknown-0bit"))
|
|
|
|
|
<< QString::fromLatin1("x86-linux-generic-elf-32bit")
|
|
|
|
|
<< int(DebuggerItem::MatchesWell); // Is this the expected behavior?
|
|
|
|
|
QTest::newRow("Fuzzy match 2")
|
|
|
|
|
<< (QStringList() << QLatin1String("unknown-unknown-unknown-unknown-0bit"))
|
|
|
|
|
<< QString::fromLatin1("arm-windows-msys-pe-64bit")
|
|
|
|
|
<< int(DebuggerItem::MatchesWell); // Is this the expected behavior?
|
|
|
|
|
|
|
|
|
|
QTest::newRow("Architecture mismatch")
|
|
|
|
|
<< (QStringList() << QLatin1String("x86-linux-generic-elf-32bit"))
|
|
|
|
|
<< QString::fromLatin1("arm-linux-generic-elf-32bit")
|
|
|
|
|
<< int(DebuggerItem::DoesNotMatch);
|
|
|
|
|
QTest::newRow("OS mismatch")
|
|
|
|
|
<< (QStringList() << QLatin1String("x86-linux-generic-elf-32bit"))
|
|
|
|
|
<< QString::fromLatin1("x86-macosx-generic-elf-32bit")
|
|
|
|
|
<< int(DebuggerItem::DoesNotMatch);
|
|
|
|
|
QTest::newRow("Format mismatch")
|
|
|
|
|
<< (QStringList() << QLatin1String("x86-linux-generic-elf-32bit"))
|
|
|
|
|
<< QString::fromLatin1("x86-linux-generic-pe-32bit")
|
|
|
|
|
<< int(DebuggerItem::DoesNotMatch);
|
|
|
|
|
|
|
|
|
|
QTest::newRow("Linux perfect match")
|
|
|
|
|
<< (QStringList() << QLatin1String("x86-linux-generic-elf-32bit"))
|
|
|
|
|
<< QString::fromLatin1("x86-linux-generic-elf-32bit")
|
|
|
|
|
<< int(DebuggerItem::MatchesWell);
|
|
|
|
|
QTest::newRow("Linux match")
|
|
|
|
|
<< (QStringList() << QLatin1String("x86-linux-generic-elf-64bit"))
|
|
|
|
|
<< QString::fromLatin1("x86-linux-generic-elf-32bit")
|
|
|
|
|
<< int(DebuggerItem::MatchesSomewhat);
|
|
|
|
|
|
|
|
|
|
QTest::newRow("Windows perfect match 1")
|
|
|
|
|
<< (QStringList() << QLatin1String("x86-windows-msvc2013-pe-64bit"))
|
|
|
|
|
<< QString::fromLatin1("x86-windows-msvc2013-pe-64bit")
|
|
|
|
|
<< int(DebuggerItem::MatchesWell);
|
|
|
|
|
QTest::newRow("Windows perfect match 2")
|
|
|
|
|
<< (QStringList() << QLatin1String("x86-windows-msvc2013-pe-64bit"))
|
|
|
|
|
<< QString::fromLatin1("x86-windows-msvc2012-pe-64bit")
|
|
|
|
|
<< int(DebuggerItem::MatchesWell);
|
|
|
|
|
QTest::newRow("Windows match 1")
|
|
|
|
|
<< (QStringList() << QLatin1String("x86-windows-msvc2013-pe-64bit"))
|
|
|
|
|
<< QString::fromLatin1("x86-windows-msvc2013-pe-32bit")
|
|
|
|
|
<< int(DebuggerItem::MatchesSomewhat);
|
|
|
|
|
QTest::newRow("Windows match 2")
|
|
|
|
|
<< (QStringList() << QLatin1String("x86-windows-msvc2013-pe-64bit"))
|
|
|
|
|
<< QString::fromLatin1("x86-windows-msvc2012-pe-32bit")
|
|
|
|
|
<< int(DebuggerItem::MatchesSomewhat);
|
|
|
|
|
QTest::newRow("Windows mismatch on word size")
|
|
|
|
|
<< (QStringList() << QLatin1String("x86-windows-msvc2013-pe-32bit"))
|
|
|
|
|
<< QString::fromLatin1("x86-windows-msvc2013-pe-64bit")
|
|
|
|
|
<< int(DebuggerItem::DoesNotMatch);
|
|
|
|
|
QTest::newRow("Windows mismatch on osflavor 1")
|
|
|
|
|
<< (QStringList() << QLatin1String("x86-windows-msvc2013-pe-32bit"))
|
|
|
|
|
<< QString::fromLatin1("x86-windows-msys-pe-64bit")
|
|
|
|
|
<< int(DebuggerItem::DoesNotMatch);
|
|
|
|
|
QTest::newRow("Windows mismatch on osflavor 2")
|
|
|
|
|
<< (QStringList() << QLatin1String("x86-windows-msys-pe-32bit"))
|
|
|
|
|
<< QString::fromLatin1("x86-windows-msvc2010-pe-64bit")
|
|
|
|
|
<< int(DebuggerItem::DoesNotMatch);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DebuggerUnitTests::testDebuggerMatching()
|
|
|
|
|
{
|
|
|
|
|
QFETCH(QStringList, debugger);
|
|
|
|
|
QFETCH(QString, target);
|
|
|
|
|
QFETCH(int, result);
|
|
|
|
|
|
|
|
|
|
DebuggerItem::MatchLevel expectedLevel = static_cast<DebuggerItem::MatchLevel>(result);
|
|
|
|
|
|
|
|
|
|
QList<Abi> debuggerAbis;
|
|
|
|
|
foreach (const QString &abi, debugger)
|
|
|
|
|
debuggerAbis << Abi(abi);
|
|
|
|
|
|
|
|
|
|
DebuggerItem item;
|
|
|
|
|
item.setAbis(debuggerAbis);
|
|
|
|
|
|
|
|
|
|
DebuggerItem::MatchLevel level = item.matchTarget(Abi(target));
|
|
|
|
|
if (level == DebuggerItem::MatchesPerfectly)
|
|
|
|
|
level = DebuggerItem::MatchesWell;
|
|
|
|
|
|
|
|
|
|
QCOMPARE(expectedLevel, level);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
QList<QObject *> DebuggerPlugin::createTestObjects() const
|
|
|
|
|
{
|
|
|
|
|
return { new DebuggerUnitTests };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#else // ^-- if WITH_TESTS else --v
|
|
|
|
|
|
|
|
|
|
QList<QObject *> DebuggerPlugin::createTestObjects() const
|
|
|
|
|
{
|
|
|
|
|
return {};
|
|
|
|
|
}
|
2012-01-26 13:14:00 +01:00
|
|
|
|
|
|
|
|
#endif // if WITH_TESTS
|
2012-01-23 16:45:00 +01:00
|
|
|
|
2016-03-09 19:16:14 +01:00
|
|
|
} // namespace Internal
|
2016-06-21 14:06:24 +02:00
|
|
|
|
|
|
|
|
void *AnalyzerConnection::staticTypeId = &AnalyzerConnection::staticTypeId;
|
|
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
} // namespace Debugger
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
#include "debuggerplugin.moc"
|