debuggerplugin.cpp 117 KB
Newer Older
1
/**************************************************************************
con's avatar
con committed
2 3 4
**
** This file is part of Qt Creator
**
con's avatar
con committed
5
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
con's avatar
con committed
6
**
7
** Contact: Nokia Corporation (qt-info@nokia.com)
con's avatar
con committed
8
**
con's avatar
con committed
9
** No Commercial Usage
10
**
con's avatar
con committed
11 12 13 14
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
15
**
16
** GNU Lesser General Public License Usage
17
**
18 19 20 21 22 23
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24
**
con's avatar
con committed
25 26 27 28 29 30
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
con's avatar
con committed
31
**
32
**************************************************************************/
hjk's avatar
hjk committed
33

con's avatar
con committed
34 35
#include "debuggerplugin.h"

Friedemann Kleint's avatar
Friedemann Kleint committed
36
#include "debuggerstartparameters.h"
37
#include "debuggeractions.h"
con's avatar
con committed
38
#include "debuggerconstants.h"
39
#include "debuggercore.h"
40 41
#include "debuggerdialogs.h"
#include "debuggerengine.h"
42
#include "debuggermainwindow.h"
con's avatar
con committed
43
#include "debuggerrunner.h"
44
#include "debuggerruncontrolfactory.h"
45
#include "debuggerstringutils.h"
46 47
#include "debuggertooltip.h"

48 49
#include "breakpoint.h"
#include "breakhandler.h"
50
#include "breakwindow.h"
51
#include "consolewindow.h"
52
#include "disassembleragent.h"
53
#include "logwindow.h"
54
#include "moduleswindow.h"
Friedemann Kleint's avatar
Friedemann Kleint committed
55
#include "moduleshandler.h"
56 57
#include "registerwindow.h"
#include "snapshotwindow.h"
hjk's avatar
hjk committed
58
#include "stackhandler.h"
59 60 61
#include "stackwindow.h"
#include "sourcefileswindow.h"
#include "threadswindow.h"
hjk's avatar
hjk committed
62
#include "watchhandler.h"
63
#include "watchwindow.h"
hjk's avatar
hjk committed
64
#include "watchutils.h"
65

66 67
#include "snapshothandler.h"
#include "threadshandler.h"
hjk's avatar
hjk committed
68
#include "gdb/gdboptionspage.h"
con's avatar
con committed
69

70
#include "ui_commonoptionspage.h"
hjk's avatar
hjk committed
71
#include "ui_dumperoptionpage.h"
72

73
#include <coreplugin/actionmanager/actionmanager.h>
74 75
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/command.h>
76
#include <coreplugin/uniqueidmanager.h>
77
#include <coreplugin/imode.h>
con's avatar
con committed
78
#include <coreplugin/coreconstants.h>
79
#include <coreplugin/dialogs/ioptionspage.h>
con's avatar
con committed
80
#include <coreplugin/editormanager/editormanager.h>
hjk's avatar
hjk committed
81
#include <coreplugin/findplaceholder.h>
82
#include <coreplugin/icontext.h>
con's avatar
con committed
83
#include <coreplugin/icore.h>
84
#include <coreplugin/imode.h>
85
#include <coreplugin/icorelistener.h>
86
#include <coreplugin/manhattanstyle.h>
hjk's avatar
hjk committed
87
#include <coreplugin/minisplitter.h>
con's avatar
con committed
88
#include <coreplugin/modemanager.h>
hjk's avatar
hjk committed
89

con's avatar
con committed
90
#include <cppeditor/cppeditorconstants.h>
91
#include <cplusplus/ModelManagerInterface.h>
hjk's avatar
hjk committed
92

93 94
#include <extensionsystem/pluginmanager.h>

95
#include <projectexplorer/project.h>
96
#include <projectexplorer/projectexplorer.h>
con's avatar
con committed
97 98
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/session.h>
99
#include <projectexplorer/target.h>
hjk's avatar
hjk committed
100
#include <projectexplorer/toolchain.h>
101
#include <projectexplorer/toolchaintype.h>
hjk's avatar
hjk committed
102

103 104
#include <qt4projectmanager/qt4projectmanagerconstants.h>

hjk's avatar
hjk committed
105
#include <texteditor/basetexteditor.h>
106
#include <texteditor/fontsettings.h>
107
#include <texteditor/texteditorsettings.h>
hjk's avatar
hjk committed
108 109

#include <utils/qtcassert.h>
110
#include <utils/savedaction.h>
111
#include <utils/styledbar.h>
112
#include <utils/proxyaction.h>
con's avatar
con committed
113

114 115
#include <qml/scriptconsole.h>

116
#include <QtCore/QTimer>
117 118
#include <QtCore/QtPlugin>
#include <QtGui/QComboBox>
119
#include <QtGui/QDockWidget>
120
#include <QtGui/QFileDialog>
hjk's avatar
hjk committed
121
#include <QtGui/QMenu>
122
#include <QtGui/QMessageBox>
123 124 125
#include <QtGui/QPushButton>
#include <QtGui/QTextBlock>
#include <QtGui/QTextCursor>
126
#include <QtGui/QToolButton>
hjk's avatar
hjk committed
127
#include <QtGui/QTreeWidget>
con's avatar
con committed
128

129 130
#include <climits>

131 132 133 134 135 136 137 138 139 140 141
#define DEBUG_STATE 1
#ifdef DEBUG_STATE
//#   define STATE_DEBUG(s)
//    do { QString msg; QTextStream ts(&msg); ts << s;
//      showMessage(msg, LogDebug); } while (0)
#   define STATE_DEBUG(s) do { qDebug() << s; } while(0)
#else
#   define STATE_DEBUG(s)
#endif

// Note: the Debugger process itself and any helper processes like
142
// gdbserver, the trk client etc are referred to as 'Engine',
143 144
// whereas the debugged process is referred to as 'Inferior'.
//
145 146
// Transitions marked by '---' are done in the individual engines.
// Transitions marked by '+-+' are done in the base DebuggerEngine.
hjk's avatar
hjk committed
147
// Transitions marked by '*' are done asynchronously.
hjk's avatar
hjk committed
148
// The GdbEngine->setupEngine() function is described in more detail below.
149
//
hjk's avatar
hjk committed
150 151 152 153 154 155 156
// 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.
//
//
//
hjk's avatar
hjk committed
157 158 159 160 161 162
//                        DebuggerNotReady
//                               +
//                      EngineSetupRequested
//                               +
//                  (calls *Engine->setupEngine())
//                            |      |
163
//                            |      |
hjk's avatar
hjk committed
164 165 166
//                       {notify-  {notify-
//                        Engine-   Engine-
//                        SetupOk}  SetupFailed}
167 168 169 170 171 172
//                            +      +
//                            +      `+-+-+> EngineSetupFailed
//                            +                   +
//                            +    [calls RunControl->startFailed]
//                            +                   +
//                            +             DebuggerFinished
hjk's avatar
hjk committed
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
//                            v
//                      EngineSetupOk
//                            +
//             [calls RunControl->StartSuccessful]
//                            +
//                  InferiorSetupRequested
//                            +
//             (calls *Engine->setupInferior())
//                         |       |
//                         |       |
//                    {notify-   {notify-
//                     Inferior- Inferior-
//                     SetupOk}  SetupFailed}
//                         +       +
//                         +       ` +-+-> InferiorSetupFailed +-+-+-+-+-+->.
//                         +                                                +
hjk's avatar
hjk committed
189
//                  InferiorSetupOk                                         +
hjk's avatar
hjk committed
190 191 192 193 194 195 196 197 198
//                         +                                                +
//                  EngineRunRequested                                      +
//                         +                                                +
//                 (calls *Engine->runEngine())                             +
//               /       |            |        \                            +
//             /         |            |          \                          +
//            | (core)   | (attach)   |           |                         +
//            |          |            |           |                         +
//      {notify-    {notifyER&- {notifyER&-  {notify-                       +
199
//      Inferior-     Inferior-   Inferior-  EngineRun-                     +
hjk's avatar
hjk committed
200 201 202 203 204 205 206 207
//     Unrunnable}     StopOk}     RunOk}     Failed}                       +
//           +           +            +           +                         +
//   InferiorUnrunnable  +     InferiorRunOk      +                         +
//                       +                        +                         +
//                InferiorStopOk            EngineRunFailed                 +
//                                                +                         v
//                                                 `-+-+-+-+-+-+-+-+-+-+-+>-+
//                                                                          +
hjk's avatar
hjk committed
208
//                                                                          +
209
//                       #Interrupt@InferiorRunOk#                          +
hjk's avatar
hjk committed
210
//                                  +                                       +
hjk's avatar
hjk committed
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
//                          InferiorStopRequested                           +
//  #SpontaneousStop                +                                       +
//   @InferiorRunOk#         (calls *Engine->                               +
//          +               interruptInferior())                            +
//      {notify-               |          |                                 +
//     Spontaneous-       {notify-    {notify-                              +
//      Inferior-          Inferior-   Inferior-                            +
//       StopOk}           StopOk}    StopFailed}                           +
//           +              +             +                                 +
//            +            +              +                                 +
//            InferiorStopOk              +                                 +
//                  +                     +                                 +
//                  +                    +                                  +
//                  +                   +                                   +
//        #Stop@InferiorUnrunnable#    +                                    +
//          #Creator Close Event#     +                                     +
//                       +           +                                      +
hjk's avatar
hjk committed
228 229 230 231 232 233 234 235 236 237 238 239 240 241
//                InferiorShutdownRequested                                 +
//                            +                                             +
//           (calls *Engine->shutdownInferior())                            +
//                         |        |                                       +
//                    {notify-   {notify-                                   +
//                     Inferior- Inferior-                                  +
//                  ShutdownOk}  ShutdownFailed}                            +
//                         +        +                                       +
//                         +        +                                       +
//  #Inferior exited#      +        +                                       +
//         |               +        +                                       +
//   {notifyInferior-      +        +                                       +
//      Exited}            +        +                                       +
//           +             +        +                                       +
hjk's avatar
hjk committed
242
//     InferiorExitOk      +        +                                       +
hjk's avatar
hjk committed
243 244 245 246 247
//             +           +        +                                       +
//            InferiorShutdownOk InferiorShutdownFailed                     +
//                      *          *                                        +
//                  EngineShutdownRequested                                 +
//                            +                                             +
248
//           (calls *Engine->shutdownEngine())  <+-+-+-+-+-+-+-+-+-+-+-+-+-+'
hjk's avatar
hjk committed
249 250 251
//                         |        |
//                         |        |
//                    {notify-   {notify-
hjk's avatar
hjk committed
252
//                     Engine-    Engine-
hjk's avatar
hjk committed
253 254 255
//                  ShutdownOk}  ShutdownFailed}
//                         +       +
//            EngineShutdownOk  EngineShutdownFailed
hjk's avatar
hjk committed
256 257
//                         *       *
//                     DebuggerFinished
hjk's avatar
hjk committed
258 259 260
//


261 262 263
/* 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
264

265 266 267 268 269 270
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" ];
271
sg1:   InferiorSetupRequested -> InferiorSetupOk [ label="notifyInferiorSetupOk", style="dashed" ];
272
sg1:   InferiorSetupRequested -> InferiorSetupFailed [ label="notifyInferiorFailed", style="dashed" ];
273
sg1:   InferiorSetupOk -> EngineRunRequested
274 275 276 277 278 279 280 281 282 283 284 285 286 287
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
288 289
sg1:   InferiorStopOk -> InferiorShutdownRequested [ label="Close event" ];
sg1:   InferiorUnrunnable -> InferiorShutdownRequested [ label="Close event" ];
290 291
sg1:   InferiorShutdownRequested -> InferiorShutdownOk [ label= "Engine::shutdownInferior\nnotifyInferiorShutdownOk", style="dashed" ];
sg1:   InferiorShutdownRequested -> InferiorShutdownFailed [ label="Engine::shutdownInferior\nnotifyInferiorShutdownFailed", style="dashed" ];
292 293
sg1:   InferiorExited -> InferiorExitOk [ label="notifyInferiorExited", style="dashed"];
sg1:   InferiorExitOk -> InferiorShutdownOk
294 295 296 297 298 299 300 301
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 */
hjk's avatar
hjk committed
302
// Additional signalling:    {notifyInferiorIll}   {notifyEngineIll}
hjk's avatar
hjk committed
303 304 305


// GdbEngine specific startup. All happens in EngineSetupRequested state
306
//
307 308
// Transitions marked by '---' are done in the individual adapters.
// Transitions marked by '+-+' are done in the GdbEngine.
hjk's avatar
hjk committed
309
//
hjk's avatar
hjk committed
310
//                  GdbEngine::setupEngine()
311 312 313 314 315
//                          +
//            (calls *Adapter->startAdapter())
//                          |      |
//                          |      `---> handleAdapterStartFailed()
//                          |                   +
hjk's avatar
hjk committed
316
//                          |             {notifyEngineSetupFailed}
317 318 319
//                          |
//                 handleAdapterStarted()
//                          +
hjk's avatar
hjk committed
320 321 322 323 324
//                 {notifyEngineSetupOk}
//
//
//
//                GdbEngine::setupInferior()
325
//                          +
326 327
//            (calls *Adapter->prepareInferior())
//                          |      |
hjk's avatar
hjk committed
328
//                          |      `---> handlePrepareInferiorFailed()
329
//                          |                   +
hjk's avatar
hjk committed
330
//                          |             {notifyInferiorSetupFailed}
331
//                          |
hjk's avatar
hjk committed
332
//                handleInferiorPrepared()
333
//                          +
334
//                {notifyInferiorSetupOk}
335 336 337 338




339

con's avatar
con committed
340
using namespace Core;
hjk's avatar
hjk committed
341
using namespace Debugger::Constants;
con's avatar
con committed
342
using namespace ProjectExplorer;
hjk's avatar
hjk committed
343
using namespace TextEditor;
con's avatar
con committed
344

hjk's avatar
hjk committed
345 346 347
namespace CC = Core::Constants;
namespace PE = ProjectExplorer::Constants;

con's avatar
con committed
348 349 350 351

namespace Debugger {
namespace Constants {

352 353
const char * const M_DEBUG_START_DEBUGGING = "QtCreator.Menu.Debug.StartDebugging";

con's avatar
con committed
354 355
const char * const STARTEXTERNAL        = "Debugger.StartExternal";
const char * const ATTACHEXTERNAL       = "Debugger.AttachExternal";
356
const char * const ATTACHCORE           = "Debugger.AttachCore";
hjk's avatar
hjk committed
357
const char * const ATTACHTCF            = "Debugger.AttachTcf";
358
const char * const ATTACHREMOTE         = "Debugger.AttachRemote";
359
const char * const ATTACHREMOTECDB      = "Debugger.AttachRemoteCDB";
360
const char * const STARTREMOTELLDB      = "Debugger.StartRemoteLLDB";
361
const char * const DETACH               = "Debugger.Detach";
con's avatar
con committed
362

363 364
const char * const RUN_TO_LINE1         = "Debugger.RunToLine1";
const char * const RUN_TO_LINE2         = "Debugger.RunToLine2";
con's avatar
con committed
365
const char * const RUN_TO_FUNCTION      = "Debugger.RunToFunction";
366 367
const char * const JUMP_TO_LINE1        = "Debugger.JumpToLine1";
const char * const JUMP_TO_LINE2        = "Debugger.JumpToLine2";
368
const char * const RETURN_FROM_FUNCTION = "Debugger.ReturnFromFunction";
369
const char * const SNAPSHOT             = "Debugger.Snapshot";
con's avatar
con committed
370 371 372
const char * const TOGGLE_BREAK         = "Debugger.ToggleBreak";
const char * const BREAK_BY_FUNCTION    = "Debugger.BreakByFunction";
const char * const BREAK_AT_MAIN        = "Debugger.BreakAtMain";
373 374
const char * const ADD_TO_WATCH1        = "Debugger.AddToWatch1";
const char * const ADD_TO_WATCH2        = "Debugger.AddToWatch2";
375
const char * const OPERATE_BY_INSTRUCTION  = "Debugger.OperateByInstruction";
376 377
const char * const FRAME_UP             = "Debugger.FrameUp";
const char * const FRAME_DOWN           = "Debugger.FrameDown";
con's avatar
con committed
378

Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
379
#ifdef Q_WS_MAC
con's avatar
con committed
380
const char * const STOP_KEY                 = "Shift+Ctrl+Y";
con's avatar
con committed
381
const char * const RESET_KEY                = "Ctrl+Shift+F5";
con's avatar
con committed
382 383 384
const char * const STEP_KEY                 = "Ctrl+Shift+I";
const char * const STEPOUT_KEY              = "Ctrl+Shift+T";
const char * const NEXT_KEY                 = "Ctrl+Shift+O";
385
const char * const REVERSE_KEY              = "";
con's avatar
con committed
386 387
const char * const RUN_TO_LINE_KEY          = "Shift+F8";
const char * const RUN_TO_FUNCTION_KEY      = "Ctrl+F6";
388
const char * const JUMP_TO_LINE_KEY         = "Ctrl+D,Ctrl+L";
con's avatar
con committed
389
const char * const TOGGLE_BREAK_KEY         = "F8";
390 391 392 393
const char * const BREAK_BY_FUNCTION_KEY    = "Ctrl+D,Ctrl+F";
const char * const BREAK_AT_MAIN_KEY        = "Ctrl+D,Ctrl+M";
const char * const ADD_TO_WATCH_KEY         = "Ctrl+D,Ctrl+W";
const char * const SNAPSHOT_KEY             = "Ctrl+D,Ctrl+S";
con's avatar
con committed
394
#else
395
const char * const STOP_KEY                 = "Shift+F5";
con's avatar
con committed
396 397 398 399
const char * const RESET_KEY                = "Ctrl+Shift+F5";
const char * const STEP_KEY                 = "F11";
const char * const STEPOUT_KEY              = "Shift+F11";
const char * const NEXT_KEY                 = "F10";
400
const char * const REVERSE_KEY              = "F12";
con's avatar
con committed
401 402 403 404 405 406 407
const char * const RUN_TO_LINE_KEY          = "";
const char * const RUN_TO_FUNCTION_KEY      = "";
const char * const JUMP_TO_LINE_KEY         = "";
const char * const TOGGLE_BREAK_KEY         = "F9";
const char * const BREAK_BY_FUNCTION_KEY    = "";
const char * const BREAK_AT_MAIN_KEY        = "";
const char * const ADD_TO_WATCH_KEY         = "Ctrl+Alt+Q";
408
const char * const SNAPSHOT_KEY             = "Ctrl+D,Ctrl+S";
con's avatar
con committed
409 410 411 412 413
#endif

} // namespace Constants


414 415 416 417 418 419 420 421
namespace Internal {

// FIXME: Outdated?
// The createCdbEngine function takes a list of options pages it can add to.
// This allows for having a "enabled" toggle on the page independently
// of the engine. That's good for not enabling the related ActiveX control
// unnecessarily.

422
void addCdbOptionPages(QList<IOptionsPage*> *opts);
423 424 425
void addGdbOptionPages(QList<IOptionsPage*> *opts);
void addScriptOptionPages(QList<IOptionsPage*> *opts);
void addTcfOptionPages(QList<IOptionsPage*> *opts);
426

427 428 429 430
#ifdef WITH_LLDB
void addLldbOptionPages(QList<IOptionsPage*> *opts);
#endif

hjk's avatar
hjk committed
431
static SessionManager *sessionManager()
432
{
hjk's avatar
hjk committed
433
    return ProjectExplorerPlugin::instance()->session();
434 435
}

436 437 438 439 440 441 442
static QToolButton *toolButton(QAction *action)
{
    QToolButton *button = new QToolButton;
    button->setDefaultAction(action);
    return button;
}

443 444 445
struct AttachRemoteParameters
{
    AttachRemoteParameters() : attachPid(0), winCrashEvent(0) {}
446
    void clear();
447 448

    quint64 attachPid;
449
    QString attachTarget;  // core file name or  server:port
450
    // Event handle for attaching to crashed Windows processes.
451 452 453
    quint64 winCrashEvent;
};

454 455 456 457 458
void AttachRemoteParameters::clear()
{
    attachPid = winCrashEvent = 0;
    attachTarget.clear();
}
459

460 461 462 463 464 465 466 467 468 469 470 471 472

///////////////////////////////////////////////////////////////////////
//
// DummyEngine
//
///////////////////////////////////////////////////////////////////////

class DummyEngine : public DebuggerEngine
{
    Q_OBJECT

public:
    DummyEngine() : DebuggerEngine(DebuggerStartParameters()) {}
473 474 475 476 477 478 479 480 481 482
    ~DummyEngine() {}

    void setupEngine() {}
    void setupInferior() {}
    void runEngine() {}
    void shutdownEngine() {}
    void shutdownInferior() {}
    void executeDebuggerCommand(const QString &) {}
    unsigned debuggerCapabilities() const { return 0; }
    bool acceptsBreakpoint(BreakpointId) const { return false; }
483 484 485 486 487 488 489 490 491
};

static DebuggerEngine *dummyEngine()
{
    static DummyEngine dummy;
    return &dummy;
}


492 493 494 495 496 497
///////////////////////////////////////////////////////////////////////
//
// DebugMode
//
///////////////////////////////////////////////////////////////////////

498
class DebugMode : public IMode
hjk's avatar
hjk committed
499 500
{
public:
hjk's avatar
hjk committed
501
    DebugMode() : m_widget(0) { setObjectName(QLatin1String("DebugMode")); }
hjk's avatar
hjk committed
502

hjk's avatar
hjk committed
503 504 505 506 507 508
    ~DebugMode()
    {
        // Make sure the editor manager does not get deleted.
        //EditorManager::instance()->setParent(0);
        delete m_widget;
    }
509 510

    // IMode
hjk's avatar
hjk committed
511 512 513 514 515 516 517 518 519
    QString displayName() const { return DebuggerPlugin::tr("Debug"); }
    QIcon icon() const { return QIcon(__(":/fancyactionbar/images/mode_Debug.png")); }
    int priority() const { return P_MODE_DEBUG; }
    QWidget *widget();
    QString id() const { return MODE_DEBUG; }
    QString type() const { return CC::MODE_EDIT_TYPE; }
    Context context() const
        { return Context(CC::C_EDITORMANAGER, C_DEBUGMODE, CC::C_NAVIGATION_PANE); }
    QString contextHelpId() const { return QString(); }
520 521
private:
    QWidget *m_widget;
522
};
hjk's avatar
hjk committed
523

524

525 526
///////////////////////////////////////////////////////////////////////
//
527
// CommonOptionsPage
528 529 530
//
///////////////////////////////////////////////////////////////////////

531
class CommonOptionsPage : public Core::IOptionsPage
532 533
{
public:
534
    CommonOptionsPage() {}
535 536

    // IOptionsPage
537
    QString id() const
hjk's avatar
hjk committed
538
        { return _(DEBUGGER_COMMON_SETTINGS_ID); }
539
    QString displayName() const
hjk's avatar
hjk committed
540
        { return QCoreApplication::translate("Debugger", DEBUGGER_COMMON_SETTINGS_NAME); }
541
    QString category() const
hjk's avatar
hjk committed
542
        { return _(DEBUGGER_SETTINGS_CATEGORY);  }
543
    QString displayCategory() const
hjk's avatar
hjk committed
544
        { return QCoreApplication::translate("Debugger", DEBUGGER_SETTINGS_TR_CATEGORY); }
545 546
    QIcon categoryIcon() const
        { return QIcon(QLatin1String(DEBUGGER_COMMON_SETTINGS_CATEGORY_ICON)); }
547 548

    QWidget *createPage(QWidget *parent);
hjk's avatar
hjk committed
549
    void apply() { m_group.apply(ICore::instance()->settings()); }
550
    void finish() { m_group.finish(); }
551
    virtual bool matches(const QString &s) const;
552 553

private:
554
    Ui::CommonOptionsPage m_ui;
555
    Utils::SavedActionSet m_group;
556
    QString m_searchKeywords;
557 558
};

559
QWidget *CommonOptionsPage::createPage(QWidget *parent)
560 561 562
{
    QWidget *w = new QWidget(parent);
    m_ui.setupUi(w);
563
    m_group.clear();
564

hjk's avatar
hjk committed
565
    m_group.insert(debuggerCore()->action(ListSourceFiles),
566
        m_ui.checkBoxListSourceFiles);
hjk's avatar
hjk committed
567
    m_group.insert(debuggerCore()->action(UseAlternatingRowColors),
568
        m_ui.checkBoxUseAlternatingRowColors);
hjk's avatar
hjk committed
569
    m_group.insert(debuggerCore()->action(UseToolTipsInMainEditor),
570
        m_ui.checkBoxUseToolTipsInMainEditor);
hjk's avatar
hjk committed
571
    m_group.insert(debuggerCore()->action(CloseBuffersOnExit),
572
        m_ui.checkBoxCloseBuffersOnExit);
hjk's avatar
hjk committed
573
    m_group.insert(debuggerCore()->action(SwitchModeOnExit),
574
        m_ui.checkBoxSwitchModeOnExit);
hjk's avatar
hjk committed
575 576 577 578 579 580
    m_group.insert(debuggerCore()->action(AutoDerefPointers), 0);
    m_group.insert(debuggerCore()->action(UseToolTipsInLocalsView), 0);
    m_group.insert(debuggerCore()->action(UseToolTipsInBreakpointsView), 0);
    m_group.insert(debuggerCore()->action(UseAddressInBreakpointsView), 0);
    m_group.insert(debuggerCore()->action(UseAddressInStackView), 0);
    m_group.insert(debuggerCore()->action(MaximalStackDepth),
581
        m_ui.spinBoxMaximalStackDepth);
hjk's avatar
hjk committed
582 583 584 585 586 587 588
    m_group.insert(debuggerCore()->action(ShowStdNamespace), 0);
    m_group.insert(debuggerCore()->action(ShowQtNamespace), 0);
    m_group.insert(debuggerCore()->action(SortStructMembers), 0);
    m_group.insert(debuggerCore()->action(LogTimeStamps), 0);
    m_group.insert(debuggerCore()->action(VerboseLog), 0);
    m_group.insert(debuggerCore()->action(BreakOnThrow), 0);
    m_group.insert(debuggerCore()->action(BreakOnCatch), 0);
589
#ifdef Q_OS_WIN
hjk's avatar
hjk committed
590
    Utils::SavedAction *registerAction = debuggerCore()->action(RegisterForPostMortem);
591 592 593 594 595
    m_group.insert(registerAction,
        m_ui.checkBoxRegisterForPostMortem);
    connect(registerAction, SIGNAL(toggled(bool)),
            m_ui.checkBoxRegisterForPostMortem, SLOT(setChecked(bool)));
#endif
596

597
    if (m_searchKeywords.isEmpty()) {
598 599 600 601 602
        QLatin1Char sep(' ');
        QTextStream(&m_searchKeywords)
                << sep << m_ui.checkBoxUseAlternatingRowColors->text()
                << sep << m_ui.checkBoxUseToolTipsInMainEditor->text()
                << sep << m_ui.checkBoxListSourceFiles->text()
603
#ifdef Q_OS_WIN
604
                << sep << m_ui.checkBoxRegisterForPostMortem->text()
605
#endif
606 607 608 609
                << sep << m_ui.checkBoxCloseBuffersOnExit->text()
                << sep << m_ui.checkBoxSwitchModeOnExit->text()
                << sep << m_ui.labelMaximalStackDepth->text()
                   ;
610 611
        m_searchKeywords.remove(QLatin1Char('&'));
    }
612 613 614
#ifndef Q_OS_WIN
    m_ui.checkBoxRegisterForPostMortem->setVisible(false);
#endif
615 616 617
    return w;
}

618 619 620 621 622
bool CommonOptionsPage::matches(const QString &s) const
{
    return m_searchKeywords.contains(s, Qt::CaseInsensitive);
}

hjk's avatar
hjk committed
623 624
///////////////////////////////////////////////////////////////////////
//
625
// DebuggingHelperOptionPage
hjk's avatar
hjk committed
626 627 628
//
///////////////////////////////////////////////////////////////////////

hjk's avatar
hjk committed
629
static bool oxygenStyle()
630
{
hjk's avatar
hjk committed
631 632
    const ManhattanStyle *ms = qobject_cast<const ManhattanStyle *>(qApp->style());
    return ms && !qstrcmp("OxygenStyle", ms->baseStyle()->metaObject()->className());
633 634
}

635
class DebuggingHelperOptionPage : public Core::IOptionsPage
hjk's avatar
hjk committed
636 637
{
    Q_OBJECT // Needs tr-context.
hjk's avatar
hjk committed
638
public:
639
    DebuggingHelperOptionPage() {}
hjk's avatar
hjk committed
640 641

    // IOptionsPage
hjk's avatar
hjk committed
642
    QString id() const { return _("Z.DebuggingHelper"); }
643
    QString displayName() const { return tr("Debugging Helper"); }
hjk's avatar
hjk committed
644
    QString category() const { return _(DEBUGGER_SETTINGS_CATEGORY); }
645 646 647 648
    QString displayCategory() const
    { return QCoreApplication::translate("Debugger", DEBUGGER_SETTINGS_TR_CATEGORY); }
    QIcon categoryIcon() const
    { return QIcon(QLatin1String(DEBUGGER_COMMON_SETTINGS_CATEGORY_ICON)); }
hjk's avatar
hjk committed
649 650

    QWidget *createPage(QWidget *parent);
hjk's avatar
hjk committed
651
    void apply() { m_group.apply(ICore::instance()->settings()); }
652
    void finish() { m_group.finish(); }
653
    virtual bool matches(const QString &s) const;
hjk's avatar
hjk committed
654 655

private:
656
    Ui::DebuggingHelperOptionPage m_ui;
657
    Utils::SavedActionSet m_group;
658
    QString m_searchKeywords;
hjk's avatar
hjk committed
659 660
};

661
QWidget *DebuggingHelperOptionPage::createPage(QWidget *parent)
hjk's avatar
hjk committed
662 663 664 665
{
    QWidget *w = new QWidget(parent);
    m_ui.setupUi(w);

666
    m_ui.dumperLocationChooser->setExpectedKind(Utils::PathChooser::Command);
667
    m_ui.dumperLocationChooser->setPromptDialogTitle(tr("Choose DebuggingHelper Location"));
hjk's avatar
hjk committed
668
    m_ui.dumperLocationChooser->setInitialBrowsePathBackup(
hjk's avatar
hjk committed
669
        ICore::instance()->resourcePath() + "../../lib");
hjk's avatar
hjk committed
670

671
    m_group.clear();
hjk's avatar
hjk committed
672
    m_group.insert(debuggerCore()->action(UseDebuggingHelpers),
673
        m_ui.debuggingHelperGroupBox);
hjk's avatar
hjk committed
674
    m_group.insert(debuggerCore()->action(UseCustomDebuggingHelperLocation),
675
        m_ui.customLocationGroupBox);
hjk's avatar
hjk committed
676
    // Suppress Oxygen style's giving flat group boxes bold titles.
677
    if (oxygenStyle())
hjk's avatar
hjk committed
678
        m_ui.customLocationGroupBox->setStyleSheet(_("QGroupBox::title { font: ; }"));
679

hjk's avatar
hjk committed
680
    m_group.insert(debuggerCore()->action(CustomDebuggingHelperLocation),
681
        m_ui.dumperLocationChooser);
hjk's avatar
hjk committed
682

hjk's avatar
hjk committed
683
    m_group.insert(debuggerCore()->action(UseCodeModel),
684
        m_ui.checkBoxUseCodeModel);
685 686 687
    m_group.insert(debuggerCore()->action(ShowThreadNames),
        m_ui.checkBoxShowThreadNames);

688

hjk's avatar
hjk committed
689 690
#ifndef QT_DEBUG
#if 0
hjk's avatar
hjk committed
691
    cmd = am->registerAction(m_dumpLogAction,
hjk's avatar
hjk committed
692
        DUMP_LOG, globalcontext);
hjk's avatar
hjk committed
693 694 695 696 697 698
    //cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+D,Ctrl+L")));
    cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+F11")));
    mdebug->addAction(cmd);
#endif
#endif

699 700 701 702 703
    if (m_searchKeywords.isEmpty()) {
        QTextStream(&m_searchKeywords)
                << ' ' << m_ui.debuggingHelperGroupBox->title()
                << ' ' << m_ui.customLocationGroupBox->title()
                << ' ' << m_ui.dumperLocationLabel->text()
704 705
                << ' ' << m_ui.checkBoxUseCodeModel->text()
                << ' ' << m_ui.checkBoxShowThreadNames->text();
706 707
        m_searchKeywords.remove(QLatin1Char('&'));
    }
hjk's avatar
hjk committed
708 709 710
    return w;
}

711
bool DebuggingHelperOptionPage::matches(const QString &s) const
hjk's avatar
hjk committed
712
{
713
    return m_searchKeywords.contains(s, Qt::CaseInsensitive);
hjk's avatar
hjk committed
714 715
}

716

con's avatar
con committed
717 718
///////////////////////////////////////////////////////////////////////
//
719
// Argument parsing
con's avatar
con committed
720 721 722
//
///////////////////////////////////////////////////////////////////////

723
static QString msgParameterMissing(const QString &a)
724 725 726 727
{
    return DebuggerPlugin::tr("Option '%1' is missing the parameter.").arg(a);
}

728
static QString msgInvalidNumericParameter(const QString &a, const QString &number)
729 730 731 732
{
    return DebuggerPlugin::tr("The parameter '%1' of option '%2' is not a number.").arg(number, a);
}

733
static bool parseArgument(QStringList::const_iterator &it,
734 735 736
    const QStringList::const_iterator &cend,
    AttachRemoteParameters *attachRemoteParameters,
    unsigned *enabledEngines, QString *errorMessage)
737 738 739
{
    const QString &option = *it;
    // '-debug <pid>'
740 741
    // '-debug <corefile>'
    // '-debug <server:port>'
hjk's avatar
hjk committed
742
    if (*it == _("-debug")) {
743 744 745 746 747 748
        ++it;
        if (it == cend) {
            *errorMessage = msgParameterMissing(*it);
            return false;
        }
        bool ok;
749
        attachRemoteParameters->attachPid = it->toULongLong(&ok);
750 751
        if (!ok)
            attachRemoteParameters->attachTarget = *it;
752 753
        return true;
    }
754 755
    // -wincrashevent <event-handle>. A handle used for
    // a handshake when attaching to a crashed Windows process.
hjk's avatar
hjk committed
756
    if (*it == _("-wincrashevent")) {
757 758 759 760 761 762
        ++it;
        if (it == cend) {
            *errorMessage = msgParameterMissing(*it);
            return false;
        }
        bool ok;
763
        attachRemoteParameters->winCrashEvent = it->toULongLong(&ok);
764 765 766 767 768 769
        if (!ok) {
            *errorMessage = msgInvalidNumericParameter(option, *it);
            return false;
        }
        return true;
    }
hjk's avatar
hjk committed
770
    // Engine disabling.
hjk's avatar
hjk committed
771
    if (option == _("-disable-cdb")) {
772
        *enabledEngines &= ~CdbEngineType;
773 774
        return true;
    }
hjk's avatar
hjk committed
775
    if (option == _("-disable-gdb")) {
776
        *enabledEngines &= ~GdbEngineType;
777 778
        return true;
    }
779
    if (option == _("-disable-qmldb")) {
780
        *enabledEngines &= ~QmlEngineType;
781 782
        return true;
    }
hjk's avatar
hjk committed
783
    if (option == _("-disable-sdb")) {
784
        *enabledEngines &= ~ScriptEngineType;
785 786
        return true;
    }
787
    if (option == _("-disable-tcf")) {
hjk's avatar
hjk committed
788 789 790
        *enabledEngines &= ~TcfEngineType;
        return true;
    }
791 792 793 794
    if (option == _("-disable-lldb")) {
        *enabledEngines &= ~LldbEngineType;
        return true;
    }
795

796
    *errorMessage = DebuggerPlugin::tr("Invalid debugger option: %1").arg(option);
797 798 799
    return false;
}

800
static bool parseArguments(const QStringList &args,
801
   AttachRemoteParameters *attachRemoteParameters,
hjk's avatar
hjk committed
802
   unsigned *enabledEngines, QString *errorMessage)
803
{
804
    attachRemoteParameters->clear();
805 806
    const QStringList::const_iterator cend = args.constEnd();
    for (QStringList::const_iterator it = args.constBegin(); it != cend; ++it)
807
        if (!parseArgument(it, cend, attachRemoteParameters, enabledEngines, errorMessage))
808
            return false;
809
    if (Constants::Internal::debug)
810
        qDebug().nospace() << args << "engines=0x"
811 812
            << QString::number(*enabledEngines, 16)
            << " pid" << attachRemoteParameters->attachPid
813
            << " target" << attachRemoteParameters->attachTarget << '\n';
814 815 816
    return true;
}

817 818 819 820 821 822 823

///////////////////////////////////////////////////////////////////////
//
// Misc
//
///////////////////////////////////////////////////////////////////////

hjk's avatar
hjk committed
824
static bool isDebuggable(IEditor *editor)
825
{
826 827
    // Only blacklist Qml. Whitelisting would fail on C++ code in files
    // with strange names, more harm would be done this way.
hjk's avatar
hjk committed
828 829
    //   IFile *file = editor->file();
    //   return !(file && file->mimeType() == "application/x-qml");
830
    // Nowadays, even Qml is debuggable.
hjk's avatar
hjk committed
831
    return editor;
832 833
}

834 835 836 837 838 839 840 841 842 843 844 845 846 847 848
class ContextData
{
public:
    ContextData() : lineNumber(0), address(0) {}

public:
    QString fileName;
    int lineNumber;
    quint64 address;
};

} // namespace Internal
} // namespace Debugger

Q_DECLARE_METATYPE(Debugger::Internal::ContextData)
con's avatar
con committed
849

850 851
///////////////////////////////////////////////////////////////////////
//
hjk's avatar
hjk committed
852
// Debugger Actions
853 854
//
///////////////////////////////////////////////////////////////////////
con's avatar
con committed
855

856 857 858
namespace Debugger {
namespace Internal {

859 860 861
struct DebuggerActions
{
    QAction *continueAction;
862
    QAction *exitAction; // on the application output button if "Stop" is possible
863 864
    QAction *interruptAction; // on the fat debug button if "Pause" is possible
    QAction *undisturbableAction; // on the fat debug button if nothing can be done
865 866 867
    QAction *resetAction; // FIXME: Should not be needed in a stable release
    QAction *stepAction;
    QAction *stepOutAction;
868
    QAction *runToLineAction; // Debug menu
869
    QAction *runToFunctionAction;
870
    QAction *jumpToLineAction; // in the Debug menu
871 872
    QAction *returnFromFunctionAction;
    QAction *nextAction;
873
    //QAction *snapshotAction;
874 875 876 877 878 879 880 881
    QAction *watchAction1; // in the Debug menu
    QAction *watchAction2; // in the text editor context menu
    QAction *breakAction;
    QAction *sepAction;
    QAction *reverseDirectionAction;
    QAction *frameUpAction;
    QAction *frameDownAction;
};
con's avatar
con committed
882

883
static DebuggerPluginPrivate *theDebuggerCore = 0;
con's avatar
con committed
884 885


886 887 888 889 890
///////////////////////////////////////////////////////////////////////
//
// DebuggerPluginPrivate
//
///////////////////////////////////////////////////////////////////////
con's avatar
con committed
891

892
class DebuggerPluginPrivate : public DebuggerCore
893 894
{
    Q_OBJECT
895

896 897
public:
    explicit DebuggerPluginPrivate(DebuggerPlugin *plugin);
898
    ~DebuggerPluginPrivate();
899