debuggerplugin.cpp 107 KB
Newer Older
1
/**************************************************************************
con's avatar
con committed
2
3
4
**
** This file is part of Qt Creator
**
hjk's avatar
hjk committed
5
** Copyright (c) 2010 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
**
9
** Commercial Usage
10
**
11
12
13
14
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
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
**
25
** If you are unsure which license is appropriate for your use, please
hjk's avatar
hjk committed
26
** contact the sales department at http://qt.nokia.com/contact.
con's avatar
con committed
27
**
28
**************************************************************************/
hjk's avatar
hjk committed
29

con's avatar
con committed
30
31
#include "debuggerplugin.h"

32
#include "debuggeractions.h"
33
#include "debuggeragents.h"
con's avatar
con committed
34
#include "debuggerconstants.h"
35
36
37
38
#include "debuggerdialogs.h"
#include "debuggerengine.h"
#include "debuggermainwindow.h"
#include "debuggerplugin.h"
con's avatar
con committed
39
#include "debuggerrunner.h"
40
#include "debuggerstringutils.h"
41
#include "debuggertooltip.h"
42
#include "debuggeruiswitcher.h"
43
44

#include "breakwindow.h"
45
#include "consolewindow.h"
46
#include "logwindow.h"
47
48
49
50
51
52
53
54
#include "moduleswindow.h"
#include "registerwindow.h"
#include "snapshotwindow.h"
#include "stackwindow.h"
#include "sourcefileswindow.h"
#include "threadswindow.h"
#include "watchwindow.h"

55
#include "breakhandler.h"
56
#include "sessionengine.h"
57
58
59
#include "snapshothandler.h"
#include "threadshandler.h"
#include "watchutils.h"
60
61
62
63
64

#ifdef Q_OS_WIN
#  include "shared/peutils.h"
#endif

con's avatar
con committed
65

66
#include "ui_commonoptionspage.h"
hjk's avatar
hjk committed
67
#include "ui_dumperoptionpage.h"
68

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

con's avatar
con committed
89
#include <cplusplus/ExpressionUnderCursor.h>
90
#include <cplusplus/CppDocument.h>
hjk's avatar
hjk committed
91

con's avatar
con committed
92
#include <cppeditor/cppeditorconstants.h>
93
#include <cpptools/cppmodelmanagerinterface.h>
hjk's avatar
hjk committed
94

95
96
#include <extensionsystem/pluginmanager.h>

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

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

111
112
//#include <qt4projectmanager/qt4projectmanagerconstants.h>

hjk's avatar
hjk committed
113
#include <utils/qtcassert.h>
114
#include <utils/savedaction.h>
115
#include <utils/styledbar.h>
con's avatar
con committed
116

117
118
#include <qml/scriptconsole.h>

119
#include <QtCore/QCoreApplication>
con's avatar
con committed
120
#include <QtCore/QDebug>
121
122
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
con's avatar
con committed
123
124
125
#include <QtCore/QObject>
#include <QtCore/QPoint>
#include <QtCore/QSettings>
126
127
#include <QtCore/QTextStream>
#include <QtCore/QTime>
128
#include <QtCore/QTimer>
129
#include <QtCore/QVariant>
130
#include <QtCore/QtPlugin>
hjk's avatar
hjk committed
131

132
133
134
135
#include <QtGui/QAbstractItemView>
#include <QtGui/QAction>
#include <QtGui/QApplication>
#include <QtGui/QComboBox>
136
#include <QtGui/QDockWidget>
137
138
139
140
141
142
143
#include <QtGui/QErrorMessage>
#include <QtGui/QFileDialog>
#include <QtGui/QHeaderView>
#include <QtGui/QLabel>
#include <QtGui/QLineEdit>
#include <QtGui/QMenu>
#include <QtGui/QMessageBox>
con's avatar
con committed
144
#include <QtGui/QPlainTextEdit>
145
146
#include <QtGui/QPushButton>
#include <QtGui/QStatusBar>
con's avatar
con committed
147
148
#include <QtGui/QTextBlock>
#include <QtGui/QTextCursor>
149
#include <QtGui/QToolButton>
150
151
#include <QtGui/QToolTip>
#include <QtGui/QTreeWidget>
con's avatar
con committed
152

153
154
#include <climits>

155
156
157
158
159
160
161
162
163
164
165
#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
166
// gdbserver, the trk client etc are referred to as 'Engine',
167
168
// whereas the debugged process is referred to as 'Inferior'.
//
169
170
// Transitions marked by '---' are done in the individual engines.
// Transitions marked by '+-+' are done in the base DebuggerEngine.
hjk's avatar
hjk committed
171
// Transitions marked by '*' are done asynchronously.
hjk's avatar
hjk committed
172
// The GdbEngine->setupEngine() function is described in more detail below.
173
//
hjk's avatar
hjk committed
174
175
176
177
178
179
//                        DebuggerNotReady
//                               +
//                      EngineSetupRequested
//                               +
//                  (calls *Engine->setupEngine())
//                            |      |
180
//                            |      |
hjk's avatar
hjk committed
181
182
183
//                       {notify-  {notify-
//                        Engine-   Engine-
//                        SetupOk}  SetupFailed}
184
185
186
187
188
189
//                            +      +
//                            +      `+-+-+> EngineSetupFailed
//                            +                   +
//                            +    [calls RunControl->startFailed]
//                            +                   +
//                            +             DebuggerFinished
hjk's avatar
hjk committed
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
//                            v
//                      EngineSetupOk
//                            +
//             [calls RunControl->StartSuccessful]
//                            +
//                  InferiorSetupRequested
//                            +
//             (calls *Engine->setupInferior())
//                         |       |
//                         |       |
//                    {notify-   {notify-
//                     Inferior- Inferior-
//                     SetupOk}  SetupFailed}
//                         +       +
//                         +       ` +-+-> InferiorSetupFailed +-+-+-+-+-+->.
//                         +                                                +
//                         +                                                +
//                  EngineRunRequested                                      +
//                         +                                                +
//                 (calls *Engine->runEngine())                             +
//               /       |            |        \                            +
//             /         |            |          \                          +
//            | (core)   | (attach)   |           |                         +
//            |          |            |           |                         +
//      {notify-    {notifyER&- {notifyER&-  {notify-                       +
//      Inferior-     Inferior-   Inferior-  RunEngine-                     +
//     Unrunnable}     StopOk}     RunOk}     Failed}                       +
//           +           +            +           +                         +
//   InferiorUnrunnable  +     InferiorRunOk      +                         +
//                       +                        +                         +
//                InferiorStopOk            EngineRunFailed                 +
//                                                +                         v
//                                                 `-+-+-+-+-+-+-+-+-+-+-+>-+
//                                                                          +
hjk's avatar
hjk committed
224
225
//                                                                          +
//                       #Interupt@InferiorRunOk#                           +
hjk's avatar
hjk committed
226
//                                  +                                       +
hjk's avatar
hjk committed
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
//                          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
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
//                InferiorShutdownRequested                                 +
//                            +                                             +
//           (calls *Engine->shutdownInferior())                            +
//                         |        |                                       +
//                    {notify-   {notify-                                   +
//                     Inferior- Inferior-                                  +
//                  ShutdownOk}  ShutdownFailed}                            +
//                         +        +                                       +
//                         +        +                                       +
//  #Inferior exited#      +        +                                       +
//         |               +        +                                       +
//   {notifyInferior-      +        +                                       +
//      Exited}            +        +                                       +
//           +             +        +                                       +
//            +            +        +                                       +
//             +           +        +                                       +
//            InferiorShutdownOk InferiorShutdownFailed                     +
//                      *          *                                        +
//                  EngineShutdownRequested                                 +
//                            +                                             +
//           (calls *Engine->shutdownEngine())  <+-+-+-+-+-+-+-+-+-+-+-+-+-+' 
//                         |        |                                        
266
//                         |        |                                        
hjk's avatar
hjk committed
267
//                    {notify-   {notify-                                    
hjk's avatar
hjk committed
268
//                     Engine-    Engine-
hjk's avatar
hjk committed
269
270
271
272
273
//                  ShutdownOk}  ShutdownFailed}                             
//                         +       +                                         
//            EngineShutdownOk  EngineShutdownFailed                         
//                         *       *
//                     DebuggerFinished
274
275
276
/* 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
277

278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
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" ];
sg1:   InferiorSetupRequested -> InferiorSetupFailed [ label="notifyInferiorFailed", style="dashed" ];
sg1:   InferiorSetupRequested -> EngineRunRequested [ label="notifyInferiorSetupOk", style="dashed" ];
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
sg1:   InferiorShutdownRequested -> InferiorShutdownOk [ label= "Engine::shutdownInferior\nnotifyInferiorShutdownOk", style="dashed" ];
sg1:   InferiorShutdownRequested -> InferiorShutdownFailed [ label="Engine::shutdownInferior\nnotifyInferiorShutdownFailed", style="dashed" ];
sg1:   InferiorExited -> InferiorShutdownOk [ label="notifyInferiorExited", style="dashed"];
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
311
// Additional signalling:    {notifyInferiorIll}   {notifyEngineIll}
hjk's avatar
hjk committed
312
313
314


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




348

con's avatar
con committed
349
using namespace Core;
hjk's avatar
hjk committed
350
351
using namespace Debugger::Constants;
using namespace Debugger::Internal;
con's avatar
con committed
352
using namespace ProjectExplorer;
hjk's avatar
hjk committed
353
using namespace TextEditor;
con's avatar
con committed
354

hjk's avatar
hjk committed
355
356
357
namespace CC = Core::Constants;
namespace PE = ProjectExplorer::Constants;

con's avatar
con committed
358
359
360
361

namespace Debugger {
namespace Constants {

362
363
const char * const M_DEBUG_START_DEBUGGING = "QtCreator.Menu.Debug.StartDebugging";

con's avatar
con committed
364
365
const char * const STARTEXTERNAL        = "Debugger.StartExternal";
const char * const ATTACHEXTERNAL       = "Debugger.AttachExternal";
366
const char * const ATTACHCORE           = "Debugger.AttachCore";
hjk's avatar
hjk committed
367
const char * const ATTACHTCF            = "Debugger.AttachTcf";
368
const char * const ATTACHREMOTE         = "Debugger.AttachRemote";
369
const char * const DETACH               = "Debugger.Detach";
con's avatar
con committed
370

371
372
const char * const RUN_TO_LINE1         = "Debugger.RunToLine1";
const char * const RUN_TO_LINE2         = "Debugger.RunToLine2";
con's avatar
con committed
373
const char * const RUN_TO_FUNCTION      = "Debugger.RunToFunction";
374
375
const char * const JUMP_TO_LINE1        = "Debugger.JumpToLine1";
const char * const JUMP_TO_LINE2        = "Debugger.JumpToLine2";
376
const char * const RETURN_FROM_FUNCTION = "Debugger.ReturnFromFunction";
377
const char * const SNAPSHOT             = "Debugger.Snapshot";
con's avatar
con committed
378
379
380
const char * const TOGGLE_BREAK         = "Debugger.ToggleBreak";
const char * const BREAK_BY_FUNCTION    = "Debugger.BreakByFunction";
const char * const BREAK_AT_MAIN        = "Debugger.BreakAtMain";
381
382
const char * const ADD_TO_WATCH1        = "Debugger.AddToWatch1";
const char * const ADD_TO_WATCH2        = "Debugger.AddToWatch2";
383
const char * const OPERATE_BY_INSTRUCTION  = "Debugger.OperateByInstruction";
384
385
const char * const FRAME_UP             = "Debugger.FrameUp";
const char * const FRAME_DOWN           = "Debugger.FrameDown";
con's avatar
con committed
386

Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
387
#ifdef Q_WS_MAC
con's avatar
con committed
388
const char * const STOP_KEY                 = "Shift+Ctrl+Y";
con's avatar
con committed
389
const char * const RESET_KEY                = "Ctrl+Shift+F5";
con's avatar
con committed
390
391
392
const char * const STEP_KEY                 = "Ctrl+Shift+I";
const char * const STEPOUT_KEY              = "Ctrl+Shift+T";
const char * const NEXT_KEY                 = "Ctrl+Shift+O";
393
const char * const REVERSE_KEY              = "";
con's avatar
con committed
394
395
const char * const RUN_TO_LINE_KEY          = "Shift+F8";
const char * const RUN_TO_FUNCTION_KEY      = "Ctrl+F6";
396
const char * const JUMP_TO_LINE_KEY         = "Ctrl+D,Ctrl+L";
con's avatar
con committed
397
const char * const TOGGLE_BREAK_KEY         = "F8";
398
399
400
401
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
402
#else
403
const char * const STOP_KEY                 = "Shift+F5";
con's avatar
con committed
404
405
406
407
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";
408
const char * const REVERSE_KEY              = "F12";
con's avatar
con committed
409
410
411
412
413
414
415
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";
416
const char * const SNAPSHOT_KEY             = "Ctrl+D,Ctrl+S";
con's avatar
con committed
417
418
419
420
421
422
#endif

} // namespace Constants
} // namespace Debugger


423

hjk's avatar
hjk committed
424
static SessionManager *sessionManager()
425
{
hjk's avatar
hjk committed
426
    return ProjectExplorerPlugin::instance()->session();
427
428
}

429
430
431
432
433
static QSettings *settings()
{
    return ICore::instance()->settings();
}

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

441
442
443
namespace Debugger {
namespace Internal {

hjk's avatar
hjk committed
444
445
static const char *Role = "ROLE";

446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
// 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.

void addGdbOptionPages(QList<Core::IOptionsPage*> *opts);
void addScriptOptionPages(QList<Core::IOptionsPage*> *opts);
void addTcfOptionPages(QList<Core::IOptionsPage*> *opts);
#ifdef CDB_ENABLED
void addCdbOptionPages(QList<Core::IOptionsPage*> *opts);
#endif


struct AttachRemoteParameters
{
    AttachRemoteParameters() : attachPid(0), winCrashEvent(0) {}
463
    void clear();
464
465

    quint64 attachPid;
466
467
    QString attachTarget;  // core file name or  server:port
    // Event handle for attaching to crashed Windows processes. 
468
469
470
    quint64 winCrashEvent;
};

471
472
473
474
475
void AttachRemoteParameters::clear()
{
    attachPid = winCrashEvent = 0;
    attachTarget.clear();
}
476

477
478
479
480
481
482
///////////////////////////////////////////////////////////////////////
//
// DebugMode
//
///////////////////////////////////////////////////////////////////////

hjk's avatar
hjk committed
483
484
485
class DebugMode : public Core::BaseMode
{
public:
486
487
    DebugMode(QObject *parent = 0) : BaseMode(parent)
    {
488
        setDisplayName(QCoreApplication::translate("Debugger::Internal::DebugMode", "Debug"));
489
        setType(Core::Constants::MODE_EDIT_TYPE);
490
        setId(MODE_DEBUG);
491
        setIcon(QIcon(__(":/fancyactionbar/images/mode_Debug.png")));
492
493
        setPriority(P_MODE_DEBUG);
    }
hjk's avatar
hjk committed
494

495
496
497
498
499
500
    ~DebugMode()
    {
        // Make sure the editor manager does not get deleted.
        EditorManager::instance()->setParent(0);
    }
};
hjk's avatar
hjk committed
501

con's avatar
con committed
502
503
504
505
506
507
///////////////////////////////////////////////////////////////////////
//
// LocationMark
//
///////////////////////////////////////////////////////////////////////

508
// Used in "real" editors
509
class LocationMark : public TextEditor::BaseTextMark
con's avatar
con committed
510
511
512
513
{
public:
    LocationMark(const QString &fileName, int linenumber)
        : BaseTextMark(fileName, linenumber)
514
    {}
con's avatar
con committed
515

516
    QIcon icon() const { return DebuggerPlugin::instance()->locationMarkIcon(); }
con's avatar
con committed
517
518
    void updateLineNumber(int /*lineNumber*/) {}
    void updateBlock(const QTextBlock & /*block*/) {}
519
    void removedFromEditor() {}
con's avatar
con committed
520
521
};

522
523
524

///////////////////////////////////////////////////////////////////////
//
525
// CommonOptionsPage
526
527
528
//
///////////////////////////////////////////////////////////////////////

529
class CommonOptionsPage : public Core::IOptionsPage
530
531
{
public:
532
    CommonOptionsPage() {}
533
534

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

    QWidget *createPage(QWidget *parent);
547
    void apply() { m_group.apply(settings()); }
548
    void finish() { m_group.finish(); }
549
    virtual bool matches(const QString &s) const;
550
551

private:
552
    Ui::CommonOptionsPage m_ui;
553
    Utils::SavedActionSet m_group;
554
    QString m_searchKeywords;
555
556
};

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

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

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

612
613
614
615
616
bool CommonOptionsPage::matches(const QString &s) const
{
    return m_searchKeywords.contains(s, Qt::CaseInsensitive);
}

hjk's avatar
hjk committed
617
618
///////////////////////////////////////////////////////////////////////
//
619
// DebuggingHelperOptionPage
hjk's avatar
hjk committed
620
621
622
//
///////////////////////////////////////////////////////////////////////

623
624
625
static inline bool oxygenStyle()
{
    if (const ManhattanStyle *ms = qobject_cast<const ManhattanStyle *>(qApp->style()))
626
        return !qstrcmp("OxygenStyle", ms->baseStyle()->metaObject()->className());
627
628
629
    return false;
}

630
class DebuggingHelperOptionPage : public Core::IOptionsPage
631
632
{   // Needs tr - context
    Q_OBJECT
hjk's avatar
hjk committed
633
public:
634
    DebuggingHelperOptionPage() {}
hjk's avatar
hjk committed
635
636

    // IOptionsPage
hjk's avatar
hjk committed
637
    QString id() const { return _("Z.DebuggingHelper"); }
638
    QString displayName() const { return tr("Debugging Helper"); }
hjk's avatar
hjk committed
639
    QString category() const { return _(DEBUGGER_SETTINGS_CATEGORY); }
640
641
642
643
    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
644
645

    QWidget *createPage(QWidget *parent);
646
    void apply() { m_group.apply(settings()); }
647
    void finish() { m_group.finish(); }
648
    virtual bool matches(const QString &s) const;
hjk's avatar
hjk committed
649
650

private:
651
    Ui::DebuggingHelperOptionPage m_ui;
652
    Utils::SavedActionSet m_group;
653
    QString m_searchKeywords;
hjk's avatar
hjk committed
654
655
};

656
QWidget *DebuggingHelperOptionPage::createPage(QWidget *parent)
hjk's avatar
hjk committed
657
658
659
660
{
    QWidget *w = new QWidget(parent);
    m_ui.setupUi(w);

661
    m_ui.dumperLocationChooser->setExpectedKind(Utils::PathChooser::Command);
662
    m_ui.dumperLocationChooser->setPromptDialogTitle(tr("Choose DebuggingHelper Location"));
hjk's avatar
hjk committed
663
664
    m_ui.dumperLocationChooser->setInitialBrowsePathBackup(
        Core::ICore::instance()->resourcePath() + "../../lib");
hjk's avatar
hjk committed
665

666
    m_group.clear();
667
    m_group.insert(theDebuggerAction(UseDebuggingHelpers),
668
        m_ui.debuggingHelperGroupBox);
669
    m_group.insert(theDebuggerAction(UseCustomDebuggingHelperLocation),
670
        m_ui.customLocationGroupBox);
hjk's avatar
hjk committed
671
    // Suppress Oxygen style's giving flat group boxes bold titles.
672
    if (oxygenStyle())
hjk's avatar
hjk committed
673
        m_ui.customLocationGroupBox->setStyleSheet(_("QGroupBox::title { font: ; }"));
674

675
    m_group.insert(theDebuggerAction(CustomDebuggingHelperLocation),
676
        m_ui.dumperLocationChooser);
hjk's avatar
hjk committed
677

678
679
680
    m_group.insert(theDebuggerAction(UseCodeModel),
        m_ui.checkBoxUseCodeModel);

681
#ifdef QT_DEBUG
682
683
    m_group.insert(theDebuggerAction(DebugDebuggingHelpers),
        m_ui.checkBoxDebugDebuggingHelpers);
684
685
686
#else
    m_ui.checkBoxDebugDebuggingHelpers->hide();
#endif
hjk's avatar
hjk committed
687
688
689
690

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

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

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

715

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

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

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

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

791
    *errorMessage = DebuggerPlugin::tr("Invalid debugger option: %1").arg(option);
792
793
794
    return false;
}

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

812
813
814
815
816
817
818
819

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

static bool isDebuggable(Core::IEditor *editor)
820
{
821
822
823
824
825
826
827
828
    // Only blacklist Qml. Whitelisting would fail on C++ code in files
    // with strange names, more harm would be done this way.
    //Core::IFile *file = editor->file();
    //return !(file && file->mimeType() == "application/x-qml");

    // Nowadays, even Qml is debuggable.
    Q_UNUSED(editor);
    return true;
829
830
}

831
static TextEditor::ITextEditor *currentTextEditor()
con's avatar
con committed
832
{
833
834
835
836
837
838
    EditorManager *editorManager = EditorManager::instance();
    if (!editorManager)
        return 0;
    Core::IEditor *editor = editorManager->currentEditor();
    return qobject_cast<ITextEditor*>(editor);
}
con's avatar
con committed
839

840
841
842
843
844
///////////////////////////////////////////////////////////////////////
//
// DebuggerPluginPrivate
//
///////////////////////////////////////////////////////////////////////
con's avatar
con committed
845

846
847
848
struct DebuggerActions
{
    QAction *continueAction;
849
850
851
    QAction *stopAction; // on the application output button if "Stop" is possible
    QAction *interruptAction; // on the fat debug button if "Pause" is possible
    QAction *undisturbableAction; // on the fat debug button if nothing can be done
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
    QAction *resetAction; // FIXME: Should not be needed in a stable release
    QAction *stepAction;
    QAction *stepOutAction;
    QAction *runToLineAction1; // in the Debug menu
    QAction *runToLineAction2; // in the text editor context menu
    QAction *runToFunctionAction;
    QAction *jumpToLineAction1; // in the Debug menu
    QAction *jumpToLineAction2; // in the text editor context menu
    QAction *returnFromFunctionAction;
    QAction *nextAction;
    QAction *snapshotAction;
    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
871

872
} // namespace Internal
con's avatar
con committed
873

874
using namespace Debugger::Internal;
con's avatar
con committed
875

876
877
878
879
880
///////////////////////////////////////////////////////////////////////
//
// DebuggerPluginPrivate
//
///////////////////////////////////////////////////////////////////////
con's avatar
con committed
881

882
883
884
class DebuggerPluginPrivate : public QObject
{
    Q_OBJECT
885

886
887
public:
    explicit DebuggerPluginPrivate(DebuggerPlugin *plugin);
888

889
890
    bool initialize(const QStringList &arguments, QString *errorMessage);
    void notifyCurrentEngine(int role, const QVariant &value = QVariant());
891
    void connectEngine(DebuggerEngine *engine, bool notify = true);
892
    void disconnectEngine() { connectEngine(m_sessionEngine); }
893

894
895
896
public slots:
    void updateWatchersHeader(int section, int, int newSize)
        { m_watchersWindow->header()->resizeSection(section, newSize); }
897

898
    void sourceFilesDockToggled(bool on)
hjk's avatar
hjk committed
899
        { if (on) notifyCurrentEngine(RequestReloadSourceFilesRole); }
900
    void modulesDockToggled(bool on)
hjk's avatar
hjk committed
901
902
903
        { if (on) notifyCurrentEngine(RequestReloadModulesRole); }
    void registerDockToggled(bool on)
        { if (on) notifyCurrentEngine(RequestReloadRegistersRole); }
904

905
    void onAction();
906
    void setSimpleDockWidgetArrangement(const Debugger::DebuggerLanguages &activeLanguages);
907

908
909
910
911
912
913
914
    void editorOpened(Core::IEditor *editor);
    void editorAboutToClose(Core::IEditor *editor);
    void setBusyCursor(bool busy);
    void requestMark(TextEditor::ITextEditor *editor, int lineNumber);
    void showToolTip(TextEditor::ITextEditor *editor, const QPoint &pnt, int pos);
    void requestContextMenu(TextEditor::ITextEditor *editor,
        int lineNumber, QMenu *menu);
915

916
917
918
919
920
921
    void activatePreviousMode();
    void activateDebugMode();
    void toggleBreakpoint();
    void toggleBreakpoint(const QString &fileName, int lineNumber);
    void onModeChanged(Core::IMode *mode);
    void showSettingsDialog();
922

923
924
925
926
927
    void startExternalApplication();
    void startRemoteApplication();
    void attachExternalApplication();
    void attachExternalApplication
        (qint64 pid, const QString &binary, const QString &crashParameter);
928
    bool attachCmdLine();
929
930
    void attachCore();
    void attachCore(const QString &core, const QString &exeFileName);
931
    void attachRemote(const QString &spec);
932
    void attachRemoteTcf();
933

934
    void enableReverseDebuggingTriggered(const QVariant &value);
935
    void languagesChanged(const Debugger::DebuggerLanguages &languages);
936
    void showStatusMessage(const QString &msg, int timeout = -1);
937
    void openMemoryEditor();
938
939
940
941
942

    DebuggerMainWindow *mainWindow()
        { return qobject_cast<DebuggerMainWindow*>
            (DebuggerUISwitcher::instance()->mainWindow()); }

943
944
    inline void setConfigValue(const QString &name, const QVariant &value);
    inline QVariant configValue(const QString &name) const;
945

ck's avatar
ck committed
946
    DebuggerRunControl *createDebugger(const DebuggerStartParameters &sp,
hjk's avatar
hjk committed
947
948
        RunConfiguration *rc = 0);
    void startDebugger(RunControl *runControl);
949
    void displayDebugger(DebuggerEngine *engine, bool updateEngine = true);
950
951
952

    void dumpLog();
    void cleanupViews();
953
    void setInitialState();
954
955
956
957
958

    void fontSettingsChanged(const TextEditor::FontSettings &settings);
    DebuggerState state() const { return m_state; }

    void updateState(DebuggerEngine *engine);
959
    void onCurrentProjectChanged(ProjectExplorer::Project *project);
960
961
962
963
964
965
966
967
968

    void resetLocation();
    void gotoLocation(const QString &file, int line, bool setMarker);

    void clearStatusMessage();

    void sessionLoaded();
    void aboutToUnloadSession();
    void aboutToSaveSession();
969
970

    void executeDebuggerCommand();
hjk's avatar
hjk committed
971
    void scriptExpressionEntered</