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>
131
#include <QtCore/QScopedPointer>
hjk's avatar
hjk committed
132

133
134
135
136
#include <QtGui/QAbstractItemView>
#include <QtGui/QAction>
#include <QtGui/QApplication>
#include <QtGui/QComboBox>
137
#include <QtGui/QDockWidget>
138
139
140
141
142
143
144
#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
145
#include <QtGui/QPlainTextEdit>
146
147
#include <QtGui/QPushButton>
#include <QtGui/QStatusBar>
con's avatar
con committed
148
149
#include <QtGui/QTextBlock>
#include <QtGui/QTextCursor>
150
#include <QtGui/QToolButton>
151
152
#include <QtGui/QToolTip>
#include <QtGui/QTreeWidget>
con's avatar
con committed
153

154
155
#include <climits>

156
157
158
159
160
161
162
163
164
165
166
#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
167
// gdbserver, the trk client etc are referred to as 'Engine',
168
169
// whereas the debugged process is referred to as 'Inferior'.
//
170
171
// Transitions marked by '---' are done in the individual engines.
// Transitions marked by '+-+' are done in the base DebuggerEngine.
hjk's avatar
hjk committed
172
// Transitions marked by '*' are done asynchronously.
hjk's avatar
hjk committed
173
// The GdbEngine->setupEngine() function is described in more detail below.
174
//
hjk's avatar
hjk committed
175
176
177
178
179
180
//                        DebuggerNotReady
//                               +
//                      EngineSetupRequested
//                               +
//                  (calls *Engine->setupEngine())
//                            |      |
181
//                            |      |
hjk's avatar
hjk committed
182
183
184
//                       {notify-  {notify-
//                        Engine-   Engine-
//                        SetupOk}  SetupFailed}
185
186
187
188
189
190
//                            +      +
//                            +      `+-+-+> EngineSetupFailed
//                            +                   +
//                            +    [calls RunControl->startFailed]
//                            +                   +
//                            +             DebuggerFinished
hjk's avatar
hjk committed
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
224
//                            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
225
226
//                                                                          +
//                       #Interupt@InferiorRunOk#                           +
hjk's avatar
hjk committed
227
//                                  +                                       +
hjk's avatar
hjk committed
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
//                          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
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
//                InferiorShutdownRequested                                 +
//                            +                                             +
//           (calls *Engine->shutdownInferior())                            +
//                         |        |                                       +
//                    {notify-   {notify-                                   +
//                     Inferior- Inferior-                                  +
//                  ShutdownOk}  ShutdownFailed}                            +
//                         +        +                                       +
//                         +        +                                       +
//  #Inferior exited#      +        +                                       +
//         |               +        +                                       +
//   {notifyInferior-      +        +                                       +
//      Exited}            +        +                                       +
//           +             +        +                                       +
//            +            +        +                                       +
//             +           +        +                                       +
//            InferiorShutdownOk InferiorShutdownFailed                     +
//                      *          *                                        +
//                  EngineShutdownRequested                                 +
//                            +                                             +
//           (calls *Engine->shutdownEngine())  <+-+-+-+-+-+-+-+-+-+-+-+-+-+' 
//                         |        |                                        
267
//                         |        |                                        
hjk's avatar
hjk committed
268
//                    {notify-   {notify-                                    
hjk's avatar
hjk committed
269
//                     Engine-    Engine-
hjk's avatar
hjk committed
270
271
272
273
274
//                  ShutdownOk}  ShutdownFailed}                             
//                         +       +                                         
//            EngineShutdownOk  EngineShutdownFailed                         
//                         *       *
//                     DebuggerFinished
275
276
277
/* 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
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
311
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
312
// Additional signalling:    {notifyInferiorIll}   {notifyEngineIll}
hjk's avatar
hjk committed
313
314
315


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




349

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

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

con's avatar
con committed
359
360
361
362

namespace Debugger {
namespace Constants {

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

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

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

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

} // namespace Constants
} // namespace Debugger


424

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

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

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

442
443
444
namespace Debugger {
namespace Internal {

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

447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
// 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) {}
464
    void clear();
465
466

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

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

478
479
480
481
482
483
///////////////////////////////////////////////////////////////////////
//
// DebugMode
//
///////////////////////////////////////////////////////////////////////

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

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

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

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

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

523
524
525

///////////////////////////////////////////////////////////////////////
//
526
// CommonOptionsPage
527
528
529
//
///////////////////////////////////////////////////////////////////////

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

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

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

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

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

564
    m_group.insert(theDebuggerAction(ListSourceFiles),
565
        m_ui.checkBoxListSourceFiles);
566
    m_group.insert(theDebuggerAction(UseAlternatingRowColors),
567
        m_ui.checkBoxUseAlternatingRowColors);
568
    m_group.insert(theDebuggerAction(UseToolTipsInMainEditor),
569
        m_ui.checkBoxUseToolTipsInMainEditor);
570
571
572
573
    m_group.insert(theDebuggerAction(CloseBuffersOnExit),
        m_ui.checkBoxCloseBuffersOnExit);
    m_group.insert(theDebuggerAction(SwitchModeOnExit),
        m_ui.checkBoxSwitchModeOnExit);
574
    m_group.insert(theDebuggerAction(AutoDerefPointers), 0);
575
576
577
578
    m_group.insert(theDebuggerAction(UseToolTipsInLocalsView), 0);
    m_group.insert(theDebuggerAction(UseToolTipsInBreakpointsView), 0);
    m_group.insert(theDebuggerAction(UseAddressInBreakpointsView), 0);
    m_group.insert(theDebuggerAction(UseAddressInStackView), 0);
579
    m_group.insert(theDebuggerAction(MaximalStackDepth),
580
        m_ui.spinBoxMaximalStackDepth);
581
582
    m_group.insert(theDebuggerAction(ShowStdNamespace), 0);
    m_group.insert(theDebuggerAction(ShowQtNamespace), 0);
583
    m_group.insert(theDebuggerAction(SortStructMembers), 0);
584
    m_group.insert(theDebuggerAction(LogTimeStamps), 0);
585
    m_group.insert(theDebuggerAction(VerboseLog), 0);
586
587
    m_group.insert(theDebuggerAction(BreakOnThrow), 0);
    m_group.insert(theDebuggerAction(BreakOnCatch), 0);
588
589
590
591
592
593
594
#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
595

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

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

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

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

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

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

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

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

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

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

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

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

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

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

#ifndef QT_DEBUG
#if 0
    cmd = am->registerAction(m_manager->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
704
    if (m_searchKeywords.isEmpty()) {
        QTextStream(&m_searchKeywords)
                << ' ' << m_ui.debuggingHelperGroupBox->title()
                << ' ' << m_ui.customLocationGroupBox->title()
                << ' ' << m_ui.dumperLocationLabel->text()
                << ' ' << m_ui.checkBoxUseCodeModel->text()
705
                << ' ' << m_ui.checkBoxDebugDebuggingHelpers->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 &= ~Debugger::CdbEngineType;
773
774
        return true;
    }
hjk's avatar
hjk committed
775
    if (option == _("-disable-gdb")) {
776
        *enabledEngines &= ~Debugger::GdbEngineType;
777
778
        return true;
    }
779
780
781
782
    if (option == _("-disable-qmldb")) {
        *enabledEngines &= ~Debugger::QmlEngineType;
        return true;
    }
hjk's avatar
hjk committed
783
    if (option == _("-disable-sdb")) {
784
        *enabledEngines &= ~Debugger::ScriptEngineType;
785
786
        return true;
    }
787
    if (option == _("-disable-tcf")) {
hjk's avatar
hjk committed
788
789
790
        *enabledEngines &= ~TcfEngineType;
        return true;
    }
791

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

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

813
814
815
816
817
818
819
820

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

static bool isDebuggable(Core::IEditor *editor)
821
{
822
823
824
825
826
827
828
829
    // 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;
830
831
}

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

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

847
848
849
struct DebuggerActions
{
    QAction *continueAction;
850
851
852
    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
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
    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
872

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

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

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

883
884
885
class DebuggerPluginPrivate : public QObject
{
    Q_OBJECT
886

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

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

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

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

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

909
910
911
912
913
914
915
    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);
916

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

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

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

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

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

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

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

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

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

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

    void clearStatusMessage();

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

    void executeDebuggerCommand();